shelve
Temporarily hide a GitHub pull request from daily checks and status reports while keeping it tracked.
Instructions
Shelve a PR to temporarily hide it from daily checks and status reports without untracking it.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| prUrl | Yes | Full GitHub PR URL to shelve |
Implementation Reference
- packages/mcp-server/src/tools.ts:453-464 (registration)MCP tool registration for 'shelve' — maps to runMove with target='shelved'
// 16. shelve — Shelve a PR server.registerTool( 'shelve', { description: 'Shelve a PR to temporarily hide it from daily checks and status reports without untracking it.', inputSchema: { prUrl: githubPrUrlSchema.describe('Full GitHub PR URL to shelve'), }, annotations: { readOnlyHint: false, destructiveHint: false }, }, wrapTool((args: { prUrl: string }) => runMove({ prUrl: args.prUrl, target: 'shelved' })), ); - packages/core/src/commands/move.ts:32-87 (handler)Actual handler that the 'shelve' tool delegates to — runMove() with target='shelved' calls stateManager.shelvePR() and clearStatusOverride()
export async function runMove(options: { prUrl: string; target: string }): Promise<MoveOutput> { validateUrl(options.prUrl); validateGitHubUrl(options.prUrl, PR_URL_PATTERN, 'PR'); const target = options.target as MoveTarget; if (!VALID_TARGETS.includes(target)) { throw new ValidationError(`Invalid target "${options.target}". Must be one of: ${VALID_TARGETS.join(', ')}`); } const stateManager = getStateManager(); switch (target) { case 'attention': case 'waiting': { const status = target === 'attention' ? 'needs_addressing' : 'waiting_on_maintainer'; const label = target === 'attention' ? 'Need Attention' : 'Waiting on Maintainer'; // Use current time — the CLI doesn't have cached PR data. The override // will auto-clear on the next daily run if the PR has new activity after this. const lastActivityAt = new Date().toISOString(); stateManager.batch(() => { stateManager.setStatusOverride(options.prUrl, status, lastActivityAt); stateManager.unshelvePR(options.prUrl); }); await maybeCheckpoint(stateManager, MODULE); return { url: options.prUrl, target, description: `Moved to ${label}` }; } case 'shelved': { stateManager.batch(() => { stateManager.shelvePR(options.prUrl); stateManager.clearStatusOverride(options.prUrl); }); await maybeCheckpoint(stateManager, MODULE); return { url: options.prUrl, target, description: 'Shelved — excluded from capacity and actionable items', }; } case 'auto': { stateManager.batch(() => { stateManager.clearStatusOverride(options.prUrl); stateManager.unshelvePR(options.prUrl); }); await maybeCheckpoint(stateManager, MODULE); return { url: options.prUrl, target, description: 'Reset to computed status', }; } default: { const _exhaustive: never = target; throw new Error(`Unhandled move target: ${_exhaustive}`); } } } - Input schema definition for the 'shelve' tool — validates GitHub PR URL format
const githubPrUrlSchema = z .string() .url() .regex(GITHUB_PR_URL_REGEX, 'Must be a GitHub PR URL like https://github.com/owner/repo/pull/123'); const githubIssueOrPrUrlSchema = z - StateManager.shelvePR() — the lowest-level helper that adds a PR URL to the shelvedPRUrls array and triggers autosave
shelvePR(url: string): boolean { if (!this.state.config.shelvedPRUrls) { this.state.config.shelvedPRUrls = []; } if (this.state.config.shelvedPRUrls.includes(url)) { return false; } this.state.config.shelvedPRUrls.push(url); this.autoSave(); return true; } - runUnshelve() — the direct companion function to undo shelving (also available via runMove with target='auto')
export async function runUnshelve(options: { prUrl: string }): Promise<UnshelveOutput> { validateUrl(options.prUrl); validateGitHubUrl(options.prUrl, PR_URL_PATTERN, 'PR'); const stateManager = getStateManager(); let removed = false; stateManager.batch(() => { removed = stateManager.unshelvePR(options.prUrl); stateManager.clearStatusOverride(options.prUrl); }); await maybeCheckpoint(stateManager, MODULE); return { unshelved: removed, url: options.prUrl }; }