{"name":"jjhub","description":"Jujutsu-native overlay on GitHub: stable change IDs, CI-gated stack landing, durable conflicts, and platform-wide undo. The 141 skills mirror JJHub's shared agent command registry — the same deterministic verbs the ACP agent (jjhub acp serve) exposes, under the same snake_case names as the MCP endpoint (https://jjhub.erisera.com/mcp). Call one with a text part \"/<command> <positional...> key=value ...\" or a data part {\"command\": \"<name>\", \"args\": {...}}; results arrive as a JSON artifact plus a text summary, and commands that need confirmation pause in input-required.","supportedInterfaces":[{"url":"https://jjhub.erisera.com/a2a","protocolBinding":"JSONRPC","protocolVersion":"1.0"},{"url":"https://jjhub.erisera.com/a2a/v1","protocolBinding":"HTTP+JSON","protocolVersion":"1.0"}],"provider":{"url":"https://jjhub.erisera.com","organization":"JJHub"},"version":"0.3.0","documentationUrl":"https://jjhub.erisera.com/llms.txt","capabilities":{"streaming":true,"pushNotifications":true,"extendedAgentCard":false},"securitySchemes":{"oauth2AuthCode":{"oauth2SecurityScheme":{"description":"OAuth 2.1 authorization-code + PKCE against JJHub's own AS","flows":{"authorizationCode":{"authorizationUrl":"https://jjhub.erisera.com/oauth/authorize","tokenUrl":"https://jjhub.erisera.com/oauth/token","refreshUrl":"https://jjhub.erisera.com/oauth/token","scopes":{"read":"JJHub read access","write":"JJHub write access"},"pkceRequired":true}},"oauth2MetadataUrl":"https://jjhub.erisera.com/.well-known/oauth-authorization-server"}},"oauth2DeviceCode":{"oauth2SecurityScheme":{"description":"OAuth device flow (the same flow `jjhub auth login` uses)","flows":{"deviceCode":{"deviceAuthorizationUrl":"https://jjhub.erisera.com/oauth/device/code","tokenUrl":"https://jjhub.erisera.com/oauth/token","refreshUrl":"https://jjhub.erisera.com/oauth/token","scopes":{"read":"JJHub read access","write":"JJHub write access"}}},"oauth2MetadataUrl":"https://jjhub.erisera.com/.well-known/oauth-authorization-server"}},"bearer":{"httpAuthSecurityScheme":{"description":"Any JJHub-issued bearer token (e.g. from jjhub auth login)","scheme":"bearer","bearerFormat":"opaque"}}},"securityRequirements":[{"schemes":{"oauth2AuthCode":{"list":["read","write"]}}},{"schemes":{"oauth2DeviceCode":{"list":["read","write"]}}},{"schemes":{"bearer":{}}}],"defaultInputModes":["text/plain","application/json"],"defaultOutputModes":["application/json","text/plain"],"skills":[{"id":"list_repositories","name":"List repositories","description":"List every repository JJHub manages, with GitHub connection and daemon status.","tags":["read","read"],"examples":["/list_repositories","{\"command\":\"list_repositories\",\"args\":{}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"create_repository","name":"Create repository","description":"Register a GitHub repository ('owner/name') with JJHub. Args: fullName=... githubRepoId=... jjOverlayManaged=... stackReviewEnabled=... defaultBookmark=... contentMode=... githubToken=....","tags":["edit","mutation"],"examples":["/create_repository fullName=... githubRepoId=... jjOverlayManaged=... stackReviewEnabled=... defaultBookmark=... contentMode=... githubToken=...","{\"command\":\"create_repository\",\"args\":{\"fullName\":\"<fullName>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"create_github_repository","name":"Create github repository","description":"Create a brand-new repository on GitHub (through the GitHub App installation for the given owner) and register it with JJHub in one step — unlike createRepository, which only ever attaches an existing repository. Requires the App's 'Administration: write' repository permission. Args: owner=... name=... visibility=... description=... defaultBranch=... autoInit=.... Needs confirmation when it applies (creates a brand-new repository on GitHub under the chosen owner — visibility is never assumed, and a PUBLIC repository can never be auto-approved even in an 'auto' session): the task pauses in input-required — reply \"confirm\" to proceed, anything else cancels.","tags":["edit","mutation","confirmation"],"examples":["/create_github_repository owner=... name=... visibility=... description=... defaultBranch=... autoInit=...","{\"command\":\"create_github_repository\",\"args\":{\"owner\":\"<owner>\",\"name\":\"<name>\",\"visibility\":\"<visibility>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_repository","name":"Get repository","description":"Get one repository's details (GitHub connection, App coverage, daemon heartbeat). Args: <repositoryId>.","tags":["read","read"],"examples":["/get_repository <repositoryId>","{\"command\":\"get_repository\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"connect_github","name":"Connect github","description":"Connect a repository's own GitHub personal access token (fallback tier below App installation tokens). Args: <repositoryId> token=....","tags":["edit","mutation"],"examples":["/connect_github <repositoryId> token=...","{\"command\":\"connect_github\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"token\":\"<token>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"disconnect_github","name":"Disconnect github","description":"Disconnect a repository's own GitHub token, falling back to the server default gateway. Args: <repositoryId>.","tags":["delete","mutation"],"examples":["/disconnect_github <repositoryId>","{\"command\":\"disconnect_github\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"update_repository","name":"Update repository","description":"Update repository settings after creation. Omitted fields stay unchanged. Args: <repositoryId> jjOverlayManaged=... stackReviewEnabled=... defaultBookmark=... contentMode=... landCheckAppearTimeoutMs=....","tags":["edit","mutation"],"examples":["/update_repository <repositoryId> jjOverlayManaged=... stackReviewEnabled=... defaultBookmark=... contentMode=... landCheckAppearTimeoutMs=...","{\"command\":\"update_repository\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"archive_repository","name":"Archive repository","description":"Archive a repository: mutations rejected, sync skips it, reads still work (undo: unarchive). Args: <repositoryId>.","tags":["edit","mutation"],"examples":["/archive_repository <repositoryId>","{\"command\":\"archive_repository\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"unarchive_repository","name":"Unarchive repository","description":"Reactivate a previously archived repository. Args: <repositoryId>.","tags":["edit","mutation"],"examples":["/unarchive_repository <repositoryId>","{\"command\":\"unarchive_repository\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_repository_overview","name":"Get repository overview","description":"Compact orientation snapshot for a repository (issue #364): its own summary, server capabilities, and a short count/sample of in-flight (non-landed, non-abandoned) changes — a landing page for the full tool catalog, not a replacement for it. Next steps: list_changes for the full list, get_change for detail. Args: <repositoryId>.","tags":["read","read"],"examples":["/get_repository_overview <repositoryId>","{\"command\":\"get_repository_overview\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_workspace_agents","name":"List workspace agents","description":"List explicit local workspace observations, including their read-only jj topology evidence. Privacy (issue #268): each agent's raw local filesystem path is redacted to null; use its displayLabel (basename + short hash, e.g. \"payments (a1b2c3)\") for anything user-visible. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_workspace_agents <repositoryId>","{\"command\":\"list_workspace_agents\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"report_workspace_agent","name":"Report workspace agent","description":"Report an explicit, read-only local workspace observation. This never edits jj remotes or bookmarks. localPath is accepted for reporting but never echoed back or exposed elsewhere (issue #268): the response's localPath is always null; use its displayLabel instead. Args: <repositoryId> localRepositoryId=... workspaceName=... localPath=... workingCopyChangeId=... sparsePatterns=... jjVersion=... capabilities=... topology=... ok=... message=....","tags":["edit","mutation"],"examples":["/report_workspace_agent <repositoryId> localRepositoryId=... workspaceName=... localPath=... workingCopyChangeId=... sparsePatterns=... jjVersion=... capabilities=... topology=... ok=... message=...","{\"command\":\"report_workspace_agent\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"localRepositoryId\":\"<localRepositoryId>\",\"workspaceName\":\"<workspaceName>\",\"sparsePatterns\":\"<sparsePatterns>\",\"capabilities\":\"<capabilities>\",\"ok\":\"<ok>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_workspace_leases","name":"List workspace leases","description":"List every currently-live (not yet expired) lease across a repository's workspace agents (issue #268) — which workspace holds which purpose, and until when. Read-only: never grants, renews, or clears a lease. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_workspace_leases <repositoryId>","{\"command\":\"list_workspace_leases\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"set_primary_workspace","name":"Set primary workspace","description":"Mark one workspace agent as the repository's primary workspace (issue #268 Track A): an explicit, opt-in convenience target for actions that don't name their own workspaceId — never an implicit fallback. At most one workspace is primary per repository at a time. Args: <repositoryId> <workspaceId>.","tags":["edit","mutation"],"examples":["/set_primary_workspace <repositoryId> <workspaceId>","{\"command\":\"set_primary_workspace\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"workspaceId\":\"<workspaceId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"acquire_workspace_lease","name":"Acquire workspace lease","description":"Acquire or renew a short, renewable, compare-and-swap lease for a named workspace mutation (issue #268). A stale, unhealthy, or mismatched observation cannot be claimed. 'push' is repository-scoped: a live 'push' lease held by ANY workspace of the repository blocks every other workspace's acquisition of it, not just the same workspace's; every other purpose stays scoped to the acquiring workspace alone. Args: <repositoryId> <workspaceId> purpose=... holder=... observedAt=... ttlSeconds=... renewToken=....","tags":["edit","mutation"],"examples":["/acquire_workspace_lease <repositoryId> <workspaceId> purpose=... holder=... observedAt=... ttlSeconds=... renewToken=...","{\"command\":\"acquire_workspace_lease\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"workspaceId\":\"<workspaceId>\",\"purpose\":\"<purpose>\",\"holder\":\"<holder>\",\"observedAt\":\"<observedAt>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"release_workspace_lease","name":"Release workspace lease","description":"Release a workspace lease early rather than waiting out its TTL (issue #268). Returns {released:false} — not an error — for a wrong or already-expired token. Args: <repositoryId> <workspaceId> purpose=... leaseToken=....","tags":["edit","mutation"],"examples":["/release_workspace_lease <repositoryId> <workspaceId> purpose=... leaseToken=...","{\"command\":\"release_workspace_lease\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"workspaceId\":\"<workspaceId>\",\"purpose\":\"<purpose>\",\"leaseToken\":\"<leaseToken>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"claim_change_mapping","name":"Claim change mapping","description":"Idempotently claim a (localRepositoryId, jjChangeId) -> changeId mapping (issue #268 Track A): first writer wins. When the returned changeId differs from the one proposed, the caller lost a race — it must use the returned changeId going forward and never overwrite the existing claim. Args: <repositoryId> localRepositoryId=... jjChangeId=... changeId=....","tags":["edit","mutation"],"examples":["/claim_change_mapping <repositoryId> localRepositoryId=... jjChangeId=... changeId=...","{\"command\":\"claim_change_mapping\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"localRepositoryId\":\"<localRepositoryId>\",\"jjChangeId\":\"<jjChangeId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_change_mappings","name":"List change mappings","description":"List every durable (jjChangeId -> changeId) claim recorded for one local jj repository instance (issue #268). Read-only — recovers a mapping across a daemon restart, or for a second workspace of the same local repository, without relying on process-local memory. Args: <repositoryId> <localRepositoryId>.","tags":["read","read"],"examples":["/list_change_mappings <repositoryId> <localRepositoryId>","{\"command\":\"list_change_mappings\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"localRepositoryId\":\"<localRepositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"set_workspace_write_route","name":"Set workspace write route","description":"Set this repository's suggested local-write target (issue #268 Track A item 4): at most one workspace at a time. This is a SUGGESTION for a caller to pass explicitly as workspaceId on commitFiles/restackChange — it is never read as an implicit fallback by those operations. Args: <repositoryId> workspaceId=....","tags":["edit","mutation"],"examples":["/set_workspace_write_route <repositoryId> workspaceId=...","{\"command\":\"set_workspace_write_route\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"workspaceId\":\"<workspaceId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_workspace_write_route","name":"Get workspace write route","description":"Get this repository's suggested local-write target, if one is set (issue #268 Track A item 4). Null if none. Args: <repositoryId>.","tags":["read","read"],"examples":["/get_workspace_write_route <repositoryId>","{\"command\":\"get_workspace_write_route\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"clear_workspace_write_route","name":"Clear workspace write route","description":"Clear this repository's suggested local-write target, if one is set (issue #268 Track A item 4). Args: <repositoryId>.","tags":["delete","mutation"],"examples":["/clear_workspace_write_route <repositoryId>","{\"command\":\"clear_workspace_write_route\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_changes","name":"List changes","description":"List every jj-style change in a repository. Args: <repositoryId> status=....","tags":["read","read"],"examples":["/list_changes <repositoryId> status=...","{\"command\":\"list_changes\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"create_change","name":"Create change","description":"Create a change (projects a branch + draft PR on GitHub when connected); parentChangeId stacks it on an existing change. Args: <repositoryId> title=... description=... parentChangeId=... parentChangeIds=... base=... stackId=... projectionRoute=....","tags":["edit","mutation"],"examples":["/create_change <repositoryId> title=... description=... parentChangeId=... parentChangeIds=... base=... stackId=... projectionRoute=...","{\"command\":\"create_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"title\":\"<title>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_change","name":"Get change","description":"Get one change's full detail (status, commit history, restack flag, etc.). Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_change <repositoryId> <changeId>","{\"command\":\"get_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_change_context","name":"Get change context","description":"Compact orientation snapshot for one change (issue #368): status, a stat-only diff summary (no patches), landability, check-run summary, this change's unresolved conflicts, review health, and derived nextActions (tool names an agent would call next) — in one call instead of separately calling get_change, get_change_diff, get_landability_report, list_check_runs, list_conflicts, and get_review_health. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_change_context <repositoryId> <changeId>","{\"command\":\"get_change_context\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_change_handoff","name":"Get change handoff","description":"Durable, append-only task-handoff log for a change (issue #373): findings, validation evidence, outstanding work, or the last commit SHA an agent actually verified, so a different agent (or the same one after a break) can resume without reconstructing a chat transcript. Returns a bounded, oldest-first page; works for a landed or abandoned change too — a post-land follow-up note is the point, not an edge case. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_change_handoff <repositoryId> <changeId>","{\"command\":\"get_change_handoff\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"append_change_handoff","name":"Append change handoff","description":"Append one durable handoff entry to a change's task-handoff log (issue #373) — never updates or deletes an existing entry. author is always the calling identity, never caller-supplied. Works against a landed or abandoned change too. Args: <repositoryId> <changeId> kind=... body=....","tags":["edit","mutation"],"examples":["/append_change_handoff <repositoryId> <changeId> kind=... body=...","{\"command\":\"append_change_handoff\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"kind\":\"<kind>\",\"body\":\"<body>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_change_evolution","name":"Get change evolution","description":"Show an auditable logical-change timeline from immutable JJHub operation snapshots, including before/after evidence and remote recovery limits. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_change_evolution <repositoryId> <changeId>","{\"command\":\"get_change_evolution\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_evolution_edges","name":"List evolution edges","description":"List durable evolution edges (issue #275) naming this change in any role (from/to/related) — rewrite/squash/split/duplicate/restore/reparent/abandon/land/divergence — recorded at mutation time, newest first. Divergence edges carry a resolvedByOpId once recoverDivergence resolves them. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/list_evolution_edges <repositoryId> <changeId>","{\"command\":\"list_evolution_edges\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_landability_report","name":"Get landability report","description":"Explain the effective GitHub branch rules and live evidence that affect whether a projected change can land. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_landability_report <repositoryId> <changeId>","{\"command\":\"get_landability_report\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_change_blockers","name":"Get change blockers","description":"List the derived, server-side review-lifecycle blockers (restack, conflict, checks, review, queue, drift) currently active on a change. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_change_blockers <repositoryId> <changeId>","{\"command\":\"get_change_blockers\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_review_health","name":"Get review health","description":"Read live GitHub reviewer requests, approvals, unresolved threads, and advisory CODEOWNERS evidence for a projected change. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_review_health <repositoryId> <changeId>","{\"command\":\"get_review_health\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"request_reviewers","name":"Request reviewers","description":"Explicitly request GitHub users or teams to review an in-review change. Never inferred from CODEOWNERS or a rewrite. Args: <repositoryId> <changeId> reviewers=... teamReviewers=....","tags":["edit","mutation"],"examples":["/request_reviewers <repositoryId> <changeId> reviewers=... teamReviewers=...","{\"command\":\"request_reviewers\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"reviewers\":\"<reviewers>\",\"teamReviewers\":\"<teamReviewers>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"remove_reviewers","name":"Remove reviewers","description":"Remove explicitly requested GitHub users or teams from an in-review change. Args: <repositoryId> <changeId> reviewers=... teamReviewers=....","tags":["delete","mutation"],"examples":["/remove_reviewers <repositoryId> <changeId> reviewers=... teamReviewers=...","{\"command\":\"remove_reviewers\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"reviewers\":\"<reviewers>\",\"teamReviewers\":\"<teamReviewers>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_reviewer_routing_audit","name":"List reviewer routing audit","description":"List this change's reviewer-routing audit trail: every explicit GitHub reviewer request/remove that actually succeeded, who did it, and when. A failed GitHub API call never creates an entry. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/list_reviewer_routing_audit <repositoryId> <changeId>","{\"command\":\"list_reviewer_routing_audit\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"recommend_reviewers","name":"Recommend reviewers","description":"Advisory-only reviewer suggestions from CODEOWNERS, prior review history, and recent file authorship. Never requests a reviewer — use requestReviewers for that. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/recommend_reviewers <repositoryId> <changeId>","{\"command\":\"recommend_reviewers\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"request_review","name":"Request review","description":"Move a draft change into review and mark its GitHub pull request ready for review. Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/request_review <repositoryId> <changeId>","{\"command\":\"request_review\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"return_to_draft","name":"Return to draft","description":"Return an in-review change and its GitHub pull request to draft. Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/return_to_draft <repositoryId> <changeId>","{\"command\":\"return_to_draft\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"enqueue_change","name":"Enqueue change","description":"Ask GitHub to add an in-review change to its merge queue. The change remains queued until GitHub actually merges it. Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/enqueue_change <repositoryId> <changeId>","{\"command\":\"enqueue_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"dequeue_change","name":"Dequeue change","description":"Remove a queued change from GitHub's merge queue and return it to review. Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/dequeue_change <repositoryId> <changeId>","{\"command\":\"dequeue_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"describe_change","name":"Describe change","description":"Edit a change's title and/or description (like 'jj describe'). Args: <repositoryId> <changeId> title=... description=....","tags":["edit","mutation"],"examples":["/describe_change <repositoryId> <changeId> title=... description=...","{\"command\":\"describe_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"amend_change","name":"Amend change","description":"Amend (rewrite) a change in place — descendants will need a restack. Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/amend_change <repositoryId> <changeId>","{\"command\":\"amend_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"split_change","name":"Split change","description":"Split a change: a new change with the given title stacks on top of it. Args: <repositoryId> <changeId> title=... description=....","tags":["edit","mutation"],"examples":["/split_change <repositoryId> <changeId> title=... description=...","{\"command\":\"split_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"title\":\"<title>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"squash_change","name":"Squash change","description":"Squash a change into its parent. Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/squash_change <repositoryId> <changeId>","{\"command\":\"squash_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"abandon_change","name":"Abandon change","description":"Abandon a change outright (closes its projected PR on GitHub). Args: <repositoryId> <changeId>.","tags":["delete","mutation"],"examples":["/abandon_change <repositoryId> <changeId>","{\"command\":\"abandon_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"restore_change","name":"Restore change","description":"Re-materialize an abandoned OR squashed-away change as a live draft with its original changeId, from the op log's pre-deletion snapshot. Former children stay reparented where abandon/squash left them (returned as formerChildren, not automatically reclaimed); a former parent that has since landed or vanished re-roots the restored change onto its base instead (reported as rerootedOnBase). Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/restore_change <repositoryId> <changeId>","{\"command\":\"restore_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"restack_change","name":"Restack change","description":"Rebase a needs-restack change onto its rewritten ancestor and clear its needsRestack flag. Args: <repositoryId> <changeId> workspaceId=... expectedWorkspaceWorkingCopyChangeId=....","tags":["edit","mutation","plan"],"examples":["/restack_change <repositoryId> <changeId> workspaceId=... expectedWorkspaceWorkingCopyChangeId=...","{\"command\":\"restack_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"duplicate_change","name":"Duplicate change","description":"Create an independent copy of a change with the same title/description/content (like 'jj duplicate'). The source is never touched — it can be duplicated even if landed, queued, or abandoned. Args: <repositoryId> <changeId> destinationChangeId=....","tags":["edit","mutation"],"examples":["/duplicate_change <repositoryId> <changeId> destinationChangeId=...","{\"command\":\"duplicate_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"reparent_change","name":"Reparent change","description":"Repoint a change's parent edges directly (graph-level reparent, not a content rebase). Reuses create_change's cycle detection. Marks the change and its descendants needsRestack rather than performing the rebase itself — call restack_change afterward to materialize it. Args: <repositoryId> <changeId> parentChangeIds=....","tags":["edit","mutation"],"examples":["/reparent_change <repositoryId> <changeId> parentChangeIds=...","{\"command\":\"reparent_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"parentChangeIds\":\"<parentChangeIds>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"set_change_external_dependencies","name":"Set change external dependencies","description":"Issue #277 (3.8), phase 1 (read-only): declare a change's external cross-repository dependency edges — an issue, pull request, release, or bookmark in ANOTHER repository. Replaces the entire set; never itself reads GitHub (see refresh_external_dependencies) and never gates landing. Args: <repositoryId> <changeId> dependencies=....","tags":["edit","mutation"],"examples":["/set_change_external_dependencies <repositoryId> <changeId> dependencies=...","{\"command\":\"set_change_external_dependencies\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"dependencies\":\"<dependencies>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"refresh_external_dependencies","name":"Refresh external dependencies","description":"Best-effort, bounded live read of every declared external dependency's current GitHub state (open/closed, released/draft/prerelease, exists/missing). A single failed lookup degrades that one entry rather than failing the whole refresh. Args: <repositoryId> <changeId>.","tags":["fetch","mutation"],"examples":["/refresh_external_dependencies <repositoryId> <changeId>","{\"command\":\"refresh_external_dependencies\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"request_atomic_cross_repo_land","name":"Request atomic cross repo land","description":"Always refused (400): no backend JJHub talks to guarantees an atomic land across repositories. Land each repository's changes separately with land_change/land_stack. Args: <repositoryId> changeIds=....","tags":["edit","mutation"],"examples":["/request_atomic_cross_repo_land <repositoryId> changeIds=...","{\"command\":\"request_atomic_cross_repo_land\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeIds\":\"<changeIds>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"recover_divergence","name":"Recover divergence","description":"Resolve the most recent unresolved divergence (issue #275) naming this change — two live changeIds found to represent the same jj change id. Refuses (409) if either side is already landed. Requires a grant on BOTH ids, not just the one in the path. Args: <repositoryId> <changeId> keep=....","tags":["edit","mutation"],"examples":["/recover_divergence <repositoryId> <changeId> keep=...","{\"command\":\"recover_divergence\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"keep\":\"<keep>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"commit_files","name":"Commit files","description":"Commit one or more files directly onto a change's projected GitHub branch — write, delete, or both in one commit. Args: <repositoryId> <changeId> message=... files=... deletePaths=... expectedHeadSha=... workspaceId=... expectedWorkspaceWorkingCopyChangeId=....","tags":["edit","mutation"],"examples":["/commit_files <repositoryId> <changeId> message=... files=... deletePaths=... expectedHeadSha=... workspaceId=... expectedWorkspaceWorkingCopyChangeId=...","{\"command\":\"commit_files\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"propose_patch","name":"Propose patch","description":"Composite create+apply+read (issue #374): creates a change, commits the given files/deletes to it, and returns the resulting diff stats and PR link — the common create/edit/inspect workflow in one call. Two op-log entries are produced (create, then commit); see proposePatch's own doc comment. If the commit or the read-back fails AFTER the change was created, this fails with propose_patch_partial_failure naming the created change id in its error details — that change stays visible via list_changes/get_change and is abandon-able, never silently orphaned. Args: <repositoryId> title=... description=... base=... parentChangeId=... stackId=... files=... deletePaths=... message=... expectedBaseSha=....","tags":["edit","mutation"],"examples":["/propose_patch <repositoryId> title=... description=... base=... parentChangeId=... stackId=... files=... deletePaths=... message=... expectedBaseSha=...","{\"command\":\"propose_patch\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"title\":\"<title>\",\"files\":\"<files>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_change_diff","name":"Get change diff","description":"Per-file unified diffs of a change's projected branch against its base; landed changes return the merged PR audit diff. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_change_diff <repositoryId> <changeId>","{\"command\":\"get_change_diff\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_check_runs","name":"List check runs","description":"Real GitHub check runs (CI status) for a change's projected branch. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/list_check_runs <repositoryId> <changeId>","{\"command\":\"list_check_runs\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_workflow_evidence","name":"Get workflow evidence","description":"Show bounded live GitHub Actions workflow-run and job evidence behind a change's projected head, with explicit merge-queue context. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_workflow_evidence <repositoryId> <changeId>","{\"command\":\"get_workflow_evidence\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"rerun_workflow_run","name":"Rerun workflow run","description":"Ask GitHub to re-run a workflow run behind a change's projected head. The run id must already appear in that change's bounded workflow evidence — an unrelated or unknown run id is rejected before any GitHub call. Args: <repositoryId> <changeId> <runId>.","tags":["edit","mutation"],"examples":["/rerun_workflow_run <repositoryId> <changeId> <runId>","{\"command\":\"rerun_workflow_run\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"runId\":\"<runId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"cancel_workflow_run","name":"Cancel workflow run","description":"Ask GitHub to cancel a workflow run behind a change's projected head. The run id must already appear in that change's bounded workflow evidence — an unrelated or unknown run id is rejected before any GitHub call. GitHub responds 202 and the cancellation itself completes asynchronously. Args: <repositoryId> <changeId> <runId>.","tags":["edit","mutation"],"examples":["/cancel_workflow_run <repositoryId> <changeId> <runId>","{\"command\":\"cancel_workflow_run\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"runId\":\"<runId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_deployment_evidence","name":"Get deployment evidence","description":"Show bounded live GitHub deployment environments and latest reported status behind a change's projected head, with explicit merge-queue context. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_deployment_evidence <repositoryId> <changeId>","{\"command\":\"get_deployment_evidence\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_security_evidence","name":"Get security evidence","description":"Show bounded open GitHub code-scanning alerts for a change's projected head, without treating unrelated repository-wide security alerts as change-scoped. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_security_evidence <repositoryId> <changeId>","{\"command\":\"get_security_evidence\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_change_issue_context","name":"Get change issue context","description":"Show bounded live GitHub issue context referenced by a change's title and description, including closing and blocking intent. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_change_issue_context <repositoryId> <changeId>","{\"command\":\"get_change_issue_context\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_project_v2_evidence","name":"Get project v2 evidence","description":"Show bounded, read-only GitHub Projects v2 membership and field values for a change's linked issues — which project(s) each is on and its status/iteration/other field values there. Never mutates a project item. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/get_project_v2_evidence <repositoryId> <changeId>","{\"command\":\"get_project_v2_evidence\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_change_files","name":"List change files","description":"Locally-stored files of a change (contentMode 'local' repos only). Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/list_change_files <repositoryId> <changeId>","{\"command\":\"list_change_files\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"erase_change_content","name":"Erase change content","description":"Permanently redact a change's title and description everywhere JJHub stores them. Requires repo owner access, an erasure allowlist entry, and a real user session; the legacy API key is rejected. Records audit metadata, never the erased value. Args: <repositoryId> <changeId> reason=... caseId=....","tags":["delete","mutation"],"examples":["/erase_change_content <repositoryId> <changeId> reason=... caseId=...","{\"command\":\"erase_change_content\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"record_content_op_receipt","name":"Record content op receipt","description":"Record one `jjhub content apply` invocation's outcome for the durable content-op receipt trail (issue #276) — called by the CLI right after its local jj mutation succeeds or is rejected. The local jj mutation itself already happened by this point; this only records what happened. Args: <repositoryId> kind=... sourceRevision=... destinationRevision=... paths=... expectedOperationId=... resultOperationId=... changedChangeIds=... succeeded=... errorMessage=....","tags":["edit","mutation"],"examples":["/record_content_op_receipt <repositoryId> kind=... sourceRevision=... destinationRevision=... paths=... expectedOperationId=... resultOperationId=... changedChangeIds=... succeeded=... errorMessage=...","{\"command\":\"record_content_op_receipt\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"kind\":\"<kind>\",\"sourceRevision\":\"<sourceRevision>\",\"expectedOperationId\":\"<expectedOperationId>\",\"succeeded\":\"<succeeded>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_content_op_receipts","name":"List content op receipts","description":"List this repository's content-op receipt trail: every `jjhub content apply` invocation, successful or rejected. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_content_op_receipts <repositoryId>","{\"command\":\"list_content_op_receipts\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_stacks","name":"List stacks","description":"List every stack (ordered group of changes) in a repository. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_stacks <repositoryId>","{\"command\":\"list_stacks\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_stack","name":"Get stack","description":"Get one stack's detail, including its ordered member change ids. Args: <repositoryId> <stackId>.","tags":["read","read"],"examples":["/get_stack <repositoryId> <stackId>","{\"command\":\"get_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_stack_review_health","name":"Get stack review health","description":"Compare live GitHub review health across every stack member without treating JJHub as the review system of record. Args: <repositoryId> <stackId>.","tags":["read","read"],"examples":["/get_stack_review_health <repositoryId> <stackId>","{\"command\":\"get_stack_review_health\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_stack_landability_report","name":"Get stack landability report","description":"Batched effective GitHub landability policy for every stack member (issue #272) — one round trip for shared evidence instead of one get_landability_report call per member, plus a stack-order gate for a member blocked by an earlier, not-yet-landable one. Args: <repositoryId> <stackId>.","tags":["read","read"],"examples":["/get_stack_landability_report <repositoryId> <stackId>","{\"command\":\"get_stack_landability_report\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_check_runs_for_stack","name":"List check runs for stack","description":"Batched GitHub check runs for every member of a stack, keyed by change id — one round trip via GraphQL instead of one REST call per member. Args: <repositoryId> <stackId>.","tags":["read","read"],"examples":["/list_check_runs_for_stack <repositoryId> <stackId>","{\"command\":\"list_check_runs_for_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_stack_issue_context","name":"Get stack issue context","description":"Show a bounded, de-duplicated linked-issue and external-blocker summary across a stack's members. Args: <repositoryId> <stackId>.","tags":["read","read"],"examples":["/get_stack_issue_context <repositoryId> <stackId>","{\"command\":\"get_stack_issue_context\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"create_stack","name":"Create stack","description":"Create a stack, optionally seeding it with existing change ids (dependency order). Args: <repositoryId> stackId=... title=... base=... changeIds=....","tags":["edit","mutation"],"examples":["/create_stack <repositoryId> stackId=... title=... base=... changeIds=...","{\"command\":\"create_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"title\":\"<title>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"reorder_stack","name":"Reorder stack","description":"Set a stack's member change order. Args: <repositoryId> <stackId> order=....","tags":["edit","mutation"],"examples":["/reorder_stack <repositoryId> <stackId> order=...","{\"command\":\"reorder_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\",\"order\":\"<order>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"set_stack_members","name":"Set stack members","description":"Replace a stack's ordered members. Removed changes become loose; members of another stack move here atomically. Args: <repositoryId> <stackId> changeIds=....","tags":["edit","mutation"],"examples":["/set_stack_members <repositoryId> <stackId> changeIds=...","{\"command\":\"set_stack_members\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\",\"changeIds\":\"<changeIds>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"enqueue_stack","name":"Enqueue stack","description":"Queue every member of a LINEAR GitHub-native stack, root to tip, via GitHub's merge queue. Refuses before any GitHub call if the stack isn't linear (a member with more than one parent, an unprojected member, or a base that doesn't chain onto the previous member); reports each member's outcome individually rather than throwing on a partial failure. Args: <repositoryId> <stackId>.","tags":["edit","mutation"],"examples":["/enqueue_stack <repositoryId> <stackId>","{\"command\":\"enqueue_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"disband_stack","name":"Disband stack","description":"Dissolve a stack — members become loose changes (undoable). The dual of createStack. Args: <repositoryId> <stackId>.","tags":["delete","mutation"],"examples":["/disband_stack <repositoryId> <stackId>","{\"command\":\"disband_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_bookmarks","name":"List bookmarks","description":"List bookmarks (JJHub's analogue of git branches) in a repository. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_bookmarks <repositoryId>","{\"command\":\"list_bookmarks\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"set_bookmark","name":"Set bookmark","description":"Create or move a bookmark to point at a change. Args: <repositoryId> name=... kind=... targetChangeId=....","tags":["edit","mutation"],"examples":["/set_bookmark <repositoryId> name=... kind=... targetChangeId=...","{\"command\":\"set_bookmark\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"name\":\"<name>\",\"kind\":\"<kind>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_saved_views","name":"List saved views","description":"List saved revset views: named, reusable jj revset expressions stored per repository. Storage only — evaluate one locally with `jjhub revset <localRepoPath> <expression>`. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_saved_views <repositoryId>","{\"command\":\"list_saved_views\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"create_saved_view","name":"Create saved view","description":"Save a named jj revset expression for later reuse. Storage only — JJHub has no local jj workspace to evaluate it against; run `jjhub revset <localRepoPath> <expression>` to actually evaluate the expression. Args: <repositoryId> name=... revsetExpression=....","tags":["edit","mutation"],"examples":["/create_saved_view <repositoryId> name=... revsetExpression=...","{\"command\":\"create_saved_view\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"name\":\"<name>\",\"revsetExpression\":\"<revsetExpression>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"delete_saved_view","name":"Delete saved view","description":"Delete a saved revset view by name. The dual of createSavedView. Args: <repositoryId> <viewName>.","tags":["delete","mutation"],"examples":["/delete_saved_view <repositoryId> <viewName>","{\"command\":\"delete_saved_view\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"viewName\":\"<viewName>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"query_revset","name":"Query revset","description":"Request a live jj revset evaluation against one specific, healthy local workspace. JJHub's server has no jj of its own, so this is ALWAYS asynchronous: it returns immediately with status 'pending' and a request id, and the named workspace's own `jjhub daemon` evaluates the expression on its next sync cycle and posts the result back. Poll getRevsetQueryResult(id) for the outcome. 400 for a missing workspaceId, 404 for an unknown one, 409 for a known but currently-unhealthy one — all before any jj call is attempted. Args: <repositoryId> workspaceId=... revset=... limit=....","tags":["edit","mutation"],"examples":["/query_revset <repositoryId> workspaceId=... revset=... limit=...","{\"command\":\"query_revset\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"workspaceId\":\"<workspaceId>\",\"revset\":\"<revset>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_revset_query_result","name":"Get revset query result","description":"Get one revset query request's current status/result — 'pending' until the target workspace's daemon fulfils it, then 'completed' (see JjRevsetResult-shaped `result`) or 'failed' (see `errorKind`/`errorMessage`/`errorDetail`). Args: <repositoryId> <requestId>.","tags":["read","read"],"examples":["/get_revset_query_result <repositoryId> <requestId>","{\"command\":\"get_revset_query_result\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"requestId\":\"<requestId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_revset_query_requests","name":"List revset query requests","description":"List every revset query request recorded for a repository, newest first. Also how a workspace's own `jjhub daemon` discovers work: it filters this to status 'pending' and its own workspaceId. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_revset_query_requests <repositoryId>","{\"command\":\"list_revset_query_requests\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"preview_content_operation","name":"Preview content operation","description":"Request a dry-run preview of a jj content-curation operation against one specific, healthy local workspace. Always asynchronous, same as queryRevset: this returns immediately with status 'pending' and a request id, and the named workspace's own `jjhub daemon` runs the preview on its next sync cycle and posts the result back (see `preview`). Poll getContentOperationRequest(id) for the outcome. 400 for a missing workspaceId or malformed operation, 404 for an unknown workspaceId, 409 for a known-but-unhealthy workspace OR an operation whose target has already landed in JJHub — all refused before any jj call is attempted. jj's own immutable-commits check runs on the daemon and surfaces as errorKind 'immutable', never as one of these synchronous statuses. Args: <repositoryId> workspaceId=... operation=... expectedOperationId=....","tags":["edit","mutation"],"examples":["/preview_content_operation <repositoryId> workspaceId=... operation=... expectedOperationId=...","{\"command\":\"preview_content_operation\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"workspaceId\":\"<workspaceId>\",\"operation\":\"<operation>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"execute_content_operation","name":"Execute content operation","description":"Request execution of a jj content-curation operation against one specific, healthy local workspace. Always asynchronous, same as previewContentOperation: returns immediately with status 'pending', and the named workspace's own `jjhub daemon` runs it on its next sync cycle and posts the outcome back (see `receipt`). Poll getContentOperationRequest(id). Same 400/404/409 validation as previewContentOperation happens before recording; the expectedOperationId precondition and jj's own immutable-commits refusal are both checked ONLY by the daemon and surface as errorKind 'operation_id_mismatch'/'immutable' with nothing executed. A successful execute also appends a durable content_op_receipts entry (recordContentOpReceipt/listContentOpReceipts). Args: <repositoryId> workspaceId=... operation=... expectedOperationId=....","tags":["edit","mutation"],"examples":["/execute_content_operation <repositoryId> workspaceId=... operation=... expectedOperationId=...","{\"command\":\"execute_content_operation\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"workspaceId\":\"<workspaceId>\",\"operation\":\"<operation>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_content_operation_request","name":"Get content operation request","description":"Get one content-operation request's current status/result — 'pending' until the target workspace's daemon fulfils it, then 'completed' (see `preview` for a preview request or `receipt` for an execute request) or 'failed' (see `errorKind`/`errorMessage`/`errorDetail`). Args: <repositoryId> <requestId>.","tags":["read","read"],"examples":["/get_content_operation_request <repositoryId> <requestId>","{\"command\":\"get_content_operation_request\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"requestId\":\"<requestId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_content_operation_requests","name":"List content operation requests","description":"List every content-operation request recorded for a repository, newest first. Also how a workspace's own `jjhub daemon` discovers work: it filters this to status 'pending' and its own workspaceId. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_content_operation_requests <repositoryId>","{\"command\":\"list_content_operation_requests\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_conflicts","name":"List conflicts","description":"List durable conflicts recorded in a repository. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_conflicts <repositoryId>","{\"command\":\"list_conflicts\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"resolve_conflict","name":"Resolve conflict","description":"Resolve a conflict: resolutionState=left|right|preserve_unresolved, or edited with mergedContent=<final content>. Only states listed in the conflict's availableResolutions apply. Args: <repositoryId> <conflictId> resolutionState=... mergedContent=.... Also callable as resolve-conflict.","tags":["edit","mutation"],"examples":["/resolve_conflict <repositoryId> <conflictId> resolutionState=... mergedContent=...","{\"command\":\"resolve_conflict\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"conflictId\":\"<conflictId>\",\"resolutionState\":\"<resolutionState>\"}}","resolve-conflict <repositoryId> <conflictId> resolutionState=... mergedContent=..."],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"suggest_conflict_resolution","name":"Suggest conflict resolution","description":"AI-suggested resolution for a conflict (draft only — nothing is applied; the human reviews and resolves through resolve_conflict). Requires the server's AI provider to be configured; refuses when the conflict's content was never recorded. Args: <repositoryId> <conflictId>.","tags":["read","read"],"examples":["/suggest_conflict_resolution <repositoryId> <conflictId>","{\"command\":\"suggest_conflict_resolution\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"conflictId\":\"<conflictId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"summarize_change","name":"Summarize change","description":"AI summary of a change (title/description + its real diff) for reviewers or as a description draft. Stateless; requires the server's AI provider to be configured. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/summarize_change <repositoryId> <changeId>","{\"command\":\"summarize_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"summarize_stack","name":"Summarize stack","description":"AI summary of a whole stack (member titles/descriptions/statuses + per-member diff stats), root to tip. Stateless; requires the server's AI provider to be configured. Args: <repositoryId> <stackId>.","tags":["read","read"],"examples":["/summarize_stack <repositoryId> <stackId>","{\"command\":\"summarize_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"assess_land_risk","name":"Assess land risk","description":"Deterministic land-risk assessment (checks/conflicts/restack/diff-size signals) with an optional AI narrative. Works without an AI provider; read-only. Args: <repositoryId> <changeId> narrative=....","tags":["read","read"],"examples":["/assess_land_risk <repositoryId> <changeId> narrative=...","{\"command\":\"assess_land_risk\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_operations","name":"List operations","description":"List the repository's operation log (every recorded mutation, newest first). Args: <repositoryId>.","tags":["read","read"],"examples":["/list_operations <repositoryId>","{\"command\":\"list_operations\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"head_operation","name":"Head operation","description":"Get the operation currently at the head of the op-log, or null if none. Args: <repositoryId>.","tags":["read","read"],"examples":["/head_operation <repositoryId>","{\"command\":\"head_operation\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_operation_diff","name":"Get operation diff","description":"Structural diff between two operations' immutable snapshots: which changes/stacks/bookmarks/conflicts were created, modified, or removed going from fromOpId to toOpId. Works for adjacent or far-apart operations; never replays the operations in between. Args: <repositoryId> <fromOpId> <toOpId>.","tags":["read","read"],"examples":["/get_operation_diff <repositoryId> <fromOpId> <toOpId>","{\"command\":\"get_operation_diff\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"fromOpId\":\"<fromOpId>\",\"toOpId\":\"<toOpId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"undo","name":"Undo","description":"Move the op-log head back one operation. Refuses to undo a 'land' (the real GitHub merge can't be reversed); force overrides the refusal, not the merge. Args: <repositoryId> force=.... Needs confirmation when it applies (undoing a 'land' op rewinds JJHub's record but does NOT unmerge the real PR): the task pauses in input-required — reply \"confirm\" to proceed, anything else cancels.","tags":["edit","mutation","confirmation"],"examples":["/undo <repositoryId> force=...","{\"command\":\"undo\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"redo","name":"Redo","description":"Move the operation-log head pointer forward by one operation (after an undo). Args: <repositoryId>.","tags":["edit","mutation"],"examples":["/redo <repositoryId>","{\"command\":\"redo\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"prune_operation_log","name":"Prune operation log","description":"Permanently delete operation-log history at or before the safe boundary: the most recent land, never past the repo's current head. An optional retentionWindow further narrows that boundary by age. Irreversible; does not affect the current change/stack state. Reports deletedCount: 0 when nothing is eligible. Args: <repositoryId> retentionWindow=....","tags":["delete","mutation"],"examples":["/prune_operation_log <repositoryId> retentionWindow=...","{\"command\":\"prune_operation_log\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_erasures","name":"List erasures","description":"List this repository's compliance-erasure audit trail: structural metadata only, never the erased content. Same access restriction as eraseChangeContent. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_erasures <repositoryId>","{\"command\":\"list_erasures\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_force_land_audit","name":"List force land audit","description":"List this repository's force-land audit trail: every force attempt, how it was authorized, and whether it was allowed. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_force_land_audit <repositoryId>","{\"command\":\"list_force_land_audit\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_pending_confirmations","name":"List pending confirmations","description":"List this repository's durable confirmations: force-lands and trunk-bookmark deletes parked for later approval or denial by a user with sufficient repo access. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_pending_confirmations <repositoryId>","{\"command\":\"list_pending_confirmations\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_pending_confirmation","name":"Get pending confirmation","description":"Get one pending confirmation's full detail. Args: <repositoryId> <confirmationId>.","tags":["read","read"],"examples":["/get_pending_confirmation <repositoryId> <confirmationId>","{\"command\":\"get_pending_confirmation\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"confirmationId\":\"<confirmationId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"decide_confirmation","name":"Decide confirmation","description":"Approve or deny a pending confirmation. Approval executes the underlying action immediately; returns 409 if it was already decided. Args: <repositoryId> <confirmationId> approve=....","tags":["edit","mutation"],"examples":["/decide_confirmation <repositoryId> <confirmationId> approve=...","{\"command\":\"decide_confirmation\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"confirmationId\":\"<confirmationId>\",\"approve\":\"<approve>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"request_confirmation_signature","name":"Request confirmation signature","description":"Request an SSH- or GPG-signed decision for a pending confirmation, relayed through the requester's local `jjhub daemon`. Strictly opt-in; instant approve/deny remains available. Requires a real authenticated user and returns 409 if a signature is already requested or the confirmation is no longer pending. Args: <repositoryId> <confirmationId> approve=... method=....","tags":["edit","mutation"],"examples":["/request_confirmation_signature <repositoryId> <confirmationId> approve=... method=...","{\"command\":\"request_confirmation_signature\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"confirmationId\":\"<confirmationId>\",\"approve\":\"<approve>\",\"method\":\"<method>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_agent_tasks","name":"List agent tasks","description":"List A2A agent tasks (the durable ledger, src/a2a/stores.ts) whose bound command targeted this repository, grouped into needs_decision/running/done, each with its parked confirmation id (if any) and the change/stack id it touches. A task the executor couldn't attribute to any one repository never appears here. Args: <repositoryId> state=... limit=... cursor=....","tags":["read","read"],"examples":["/list_agent_tasks <repositoryId> state=... limit=... cursor=...","{\"command\":\"list_agent_tasks\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_project_automation","name":"Get project automation","description":"Get this repository's Projects v2 card-automation binding, or null when none is configured. Owner-only. Args: <repositoryId>.","tags":["read","read"],"examples":["/get_project_automation <repositoryId>","{\"command\":\"get_project_automation\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"set_project_automation","name":"Set project automation","description":"Create or replace this repository's Projects v2 card-automation binding. Requires the project to have linked this repository, the App's organization Projects permission, and a live-verified repository admin. Rejects the legacy shared-secret credential. Args: <repositoryId> projectNodeId=... fieldId=... optionId=... enabled=....","tags":["edit","mutation"],"examples":["/set_project_automation <repositoryId> projectNodeId=... fieldId=... optionId=... enabled=...","{\"command\":\"set_project_automation\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"projectNodeId\":\"<projectNodeId>\",\"fieldId\":\"<fieldId>\",\"optionId\":\"<optionId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"clear_project_automation","name":"Clear project automation","description":"Remove this repository's Projects v2 card-automation binding. Uses the same owner and live-admin gate as setting it. Args: <repositoryId>.","tags":["delete","mutation"],"examples":["/clear_project_automation <repositoryId>","{\"command\":\"clear_project_automation\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_project_field_rules","name":"List project field rules","description":"List this repository's Projects v2 lifecycle->field mapping rules (issue #280): opt-in rules that map a JJHub lifecycle state (draft/in_review/queued/landed/abandoned/blocked) to a single-select field value. Owner-only. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_project_field_rules <repositoryId>","{\"command\":\"list_project_field_rules\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"upsert_project_field_rule","name":"Upsert project field rule","description":"Create or replace one Projects v2 lifecycle->field mapping rule. Requires the project to have linked this repository, the App's organization Projects permission, and a real authenticated user. Rejects the legacy shared-secret credential. Args: <repositoryId> id=... projectNodeId=... fieldId=... optionId=... when=... enabled=....","tags":["edit","mutation"],"examples":["/upsert_project_field_rule <repositoryId> id=... projectNodeId=... fieldId=... optionId=... when=... enabled=...","{\"command\":\"upsert_project_field_rule\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"projectNodeId\":\"<projectNodeId>\",\"fieldId\":\"<fieldId>\",\"optionId\":\"<optionId>\",\"when\":\"<when>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"delete_project_field_rule","name":"Delete project field rule","description":"Delete one Projects v2 lifecycle->field mapping rule by id. Args: <repositoryId> <ruleId>.","tags":["delete","mutation"],"examples":["/delete_project_field_rule <repositoryId> <ruleId>","{\"command\":\"delete_project_field_rule\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"ruleId\":\"<ruleId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"preview_project_item_updates","name":"Preview project item updates","description":"Preview what applyProjectFieldRules would do right now for this change, without writing anything: evaluates every configured rule (plus the legacy project-automation binding, for visibility) against the change's current lifecycle state and live Projects v2 item evidence. Args: <repositoryId> <changeId>.","tags":["read","read"],"examples":["/preview_project_item_updates <repositoryId> <changeId>","{\"command\":\"preview_project_item_updates\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"apply_project_field_rules","name":"Apply project field rules","description":"Evaluate this change's Projects v2 lifecycle->field mapping rules (the same evaluation previewProjectItemUpdates shows) and write every matching update. One item's GraphQL failure never aborts the rest — the result reports each item's own outcome. Automatic dispatch already runs this on land; call it explicitly to apply queued/blocked/other rules on demand. Args: <repositoryId> <changeId>.","tags":["edit","mutation"],"examples":["/apply_project_field_rules <repositoryId> <changeId>","{\"command\":\"apply_project_field_rules\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_links","name":"List links","description":"List GitHub object links (PRs, branches, check runs, labels) projected for this repository. Args: <repositoryId>.","tags":["read","read"],"examples":["/list_links <repositoryId>","{\"command\":\"list_links\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"create_service_token","name":"Create service token","description":"Mint a bearer for a service principal (a reviewer agent, CI job, ...) owned by the signed-in caller. RBAC for requests bearing it evaluates the OWNER's live GitHub role intersected with repositoryIds; its audit-trail actor is \"service:<name>\". The raw token is returned exactly once — only its hash is stored. Args: name=... scope=... repositoryIds=....","tags":["edit","mutation"],"examples":["/create_service_token name=... scope=... repositoryIds=...","{\"command\":\"create_service_token\",\"args\":{\"name\":\"<name>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_service_tokens","name":"List service tokens","description":"List the signed-in caller's own service tokens — metadata only, never the raw bearer or its hash.","tags":["read","read"],"examples":["/list_service_tokens","{\"command\":\"list_service_tokens\",\"args\":{}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"revoke_service_token","name":"Revoke service token","description":"Revoke a service token by id — callable by its owner or the ops (legacy shared-secret) credential. {revoked:false} for an unknown or already-revoked id, never an error. Args: <tokenId>.","tags":["delete","mutation"],"examples":["/revoke_service_token <tokenId>","{\"command\":\"revoke_service_token\",\"args\":{\"tokenId\":\"<tokenId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"send_test_notification","name":"Send test notification","description":"Send a real push notification to every browser/device the signed-in caller has subscribed, exercising the whole delivery path (retry/backoff on 429/5xx, outcome recording, consecutive-failure pruning) and returning each subscription's outcome. Used by the Settings page's \"Send test notification\" button. 400 when push isn't configured on this server.","tags":["edit","mutation"],"examples":["/send_test_notification","{\"command\":\"send_test_notification\",\"args\":{}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"list_experiments","name":"List experiments","description":"The Experimental features registry merged with the signed-in caller's own choices — every registered experiment's id/title/description/status/docs link plus whether it's on for this user.","tags":["read","read"],"examples":["/list_experiments","{\"command\":\"list_experiments\",\"args\":{}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"set_experiment","name":"Set experiment","description":"Turn one experiment on or off for the signed-in caller. Experiments can change or be withdrawn — see the registry's own status/docs fields. Returns the full merged registry, same shape as listExperiments. Args: id=... enabled=....","tags":["edit","mutation"],"examples":["/set_experiment id=... enabled=...","{\"command\":\"set_experiment\",\"args\":{\"id\":\"<id>\",\"enabled\":\"<enabled>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"post_review_comment","name":"Post review comment","description":"Post a PR review comment (or a general PR comment when path is omitted) on a change's projected pull request, through the GitHub gateway. Refused (404) for a change with no projected PR. Recorded in this repository's review-comment audit trail with the calling actor. Args: <repositoryId> <changeId> body=... path=... line=....","tags":["edit","mutation"],"examples":["/post_review_comment <repositoryId> <changeId> body=... path=... line=...","{\"command\":\"post_review_comment\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"body\":\"<body>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"whoami","name":"Who am I","description":"The identity this connection acts as — mutations are attributed to this user.","tags":["read","read"],"examples":["/whoami","{\"command\":\"whoami\",\"args\":{}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"land_change","name":"Land change","description":"Merge a change's PR on GitHub and mark it landed. Blocked while checks are pending/failing; force=true overrides (asks permission). Args: <repositoryId> <changeId> force=... background=... expectedHeadSha=.... Needs confirmation when it applies (force-landing skips the CI check-run gate and the land-risk gate and merges the PR on GitHub — the merge cannot be undone): the task pauses in input-required — reply \"confirm\" to proceed, anything else cancels. Also callable as land-a-change.","tags":["execute","mutation","confirmation"],"examples":["/land_change <repositoryId> <changeId> force=... background=... expectedHeadSha=...","{\"command\":\"land_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}","land-a-change <repositoryId> <changeId> force=... background=... expectedHeadSha=..."],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"land_stack","name":"Land stack","description":"Merge every member PR root->tip and mark the stack landed, all-or-nothing. force=true overrides the check gate (asks permission). Args: <repositoryId> <stackId> force=... background=.... Needs confirmation when it applies (force-landing merges every member PR on GitHub with pending/failing checks — the merges cannot be undone): the task pauses in input-required — reply \"confirm\" to proceed, anything else cancels.","tags":["execute","mutation","confirmation","plan"],"examples":["/land_stack <repositoryId> <stackId> force=... background=...","{\"command\":\"land_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_land_job","name":"Get land job","description":"Poll a background land job started by land_change/land_stack's background=true (issue #196). Args: <repositoryId> <jobId>.","tags":["read","read"],"examples":["/get_land_job <repositoryId> <jobId>","{\"command\":\"get_land_job\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"jobId\":\"<jobId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"delete_bookmark","name":"Delete bookmark","description":"Delete a bookmark. The repo's default (trunk) bookmark requires force=true (asks permission — issue #204). Args: <repositoryId> <name> force=.... Needs confirmation when it applies (force-deleting the repository's default (trunk) bookmark removes the branch every change lands into): the task pauses in input-required — reply \"confirm\" to proceed, anything else cancels.","tags":["delete","mutation","confirmation"],"examples":["/delete_bookmark <repositoryId> <name> force=...","{\"command\":\"delete_bookmark\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"name\":\"<name>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"sync_github","name":"Sync GitHub","description":"Run one reconciliation sweep against GitHub (repair drift, absorb external state). Args: <repositoryId>.","tags":["fetch","mutation"],"examples":["/sync_github <repositoryId>","{\"command\":\"sync_github\",\"args\":{\"repositoryId\":\"<repositoryId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"raise_conflict","name":"Raise conflict","description":"Record a durable conflict on a change (sourceEvent=, conflictedFiles= comma-separated, leftLabel=, rightLabel= required). Args: <repositoryId> <changeId> sourceEvent=... conflictedFiles=... leftLabel=... rightLabel=... leftContent=... rightContent=....","tags":["edit","mutation"],"examples":["/raise_conflict <repositoryId> <changeId> sourceEvent=... conflictedFiles=... leftLabel=... rightLabel=... leftContent=... rightContent=...","{\"command\":\"raise_conflict\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\",\"sourceEvent\":\"<sourceEvent>\",\"conflictedFiles\":\"<conflictedFiles>\",\"leftLabel\":\"<leftLabel>\",\"rightLabel\":\"<rightLabel>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"stack_status","name":"Stack status","description":"One-shot stack overview: members (root -> tip) with status/title, plus the stack landability report. Args: <repositoryId> <stackId>. Also callable as stack-status.","tags":["read","read","registry-only"],"examples":["/stack_status <repositoryId> <stackId>","{\"command\":\"stack_status\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}","stack-status <repositoryId> <stackId>"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_conflict","name":"Get conflict","description":"One conflict by id, including its recorded left/right/merged content and available resolutions. Args: <repositoryId> <conflictId>.","tags":["read","read","registry-only"],"examples":["/get_conflict <repositoryId> <conflictId>","{\"command\":\"get_conflict\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"conflictId\":\"<conflictId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_landability","name":"Get landability","description":"Can this change land right now? The landability report (rules, requirements, resolution). Args: <repositoryId> <changeId>.","tags":["read","read","registry-only"],"examples":["/get_landability <repositoryId> <changeId>","{\"command\":\"get_landability\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"land_when_ready","name":"Land when ready","description":"Land a change or stack as soon as it's landable: waits out pending checks, restacks on drift, retries bounded transient failures, and pauses for confirmation only on a genuine force gate. stack=true treats <id> as a stackId (land_stack semantics) instead of a changeId. Args: <repositoryId> <id> stack=... maxAttempts=... waitForChecksMs=... force=.... Needs confirmation when it applies (force-landing skips the CI check-run gate and the land-risk gate and merges the PR(s) on GitHub — the merge cannot be undone): the task pauses in input-required — reply \"confirm\" to proceed, anything else cancels.","tags":["execute","mutation","confirmation","registry-only"],"examples":["/land_when_ready <repositoryId> <id> stack=... maxAttempts=... waitForChecksMs=... force=...","{\"command\":\"land_when_ready\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"id\":\"<id>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"get_skill","name":"Get skill","description":"Fetch the jjhub operating skill's markdown — the SAME content served at /.well-known/skills — for authoritative guidance on which command to use for a task. Call this once near the start of a session for full usage guidance. Args: name=... file=....","tags":["read","read","registry-only"],"examples":["/get_skill name=... file=...","{\"command\":\"get_skill\",\"args\":{}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"ask","name":"Ask","description":"Map a free-text prompt onto ONE command from this registry (the same interpreter 'jjhub acp serve' uses) and either return the resolved invocation for review, or run it. Reads execute automatically; a resolved mutation returns unexecuted unless execute=true, and a command needing confirmation (e.g. force=true) is always returned unexecuted here — call it directly so its own confirmation flow applies. Args: prompt=... repository=... dryRun=... execute=....","tags":["other","mutation","registry-only"],"examples":["/ask prompt=... repository=... dryRun=... execute=...","{\"command\":\"ask\",\"args\":{\"prompt\":\"<prompt>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"watch_change","name":"Watch change","description":"Stream landability/check/queue state for a change until it lands, is abandoned, a check fails terminally, or maxMs elapses (outcome: timeout). untilStates stops early once the landability state is reached instead of waiting for an actual land. Args: <repositoryId> <changeId> untilStates=... maxMs=... pollMs=....","tags":["read","read","registry-only"],"examples":["/watch_change <repositoryId> <changeId> untilStates=... maxMs=... pollMs=...","{\"command\":\"watch_change\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"changeId\":\"<changeId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]},{"id":"watch_stack","name":"Watch stack","description":"Stream landability/check/queue state for every member of a stack until it fully lands, a member is abandoned, a check fails terminally, or maxMs elapses (outcome: timeout). untilStates stops early once the stack landability state is reached instead of waiting for an actual land. Args: <repositoryId> <stackId> untilStates=... maxMs=... pollMs=....","tags":["read","read","registry-only"],"examples":["/watch_stack <repositoryId> <stackId> untilStates=... maxMs=... pollMs=...","{\"command\":\"watch_stack\",\"args\":{\"repositoryId\":\"<repositoryId>\",\"stackId\":\"<stackId>\"}}"],"inputModes":["text/plain","application/json"],"outputModes":["application/json","text/plain"]}]}