| name | itx:execute |
| description | Execute the plan for an issue (parent or subtask) |
| argument-hint | [orchestrate] <issue-number> [in a subtree|--worktree] |
name: itx:execute
Issue Execution
Execute the implementation plan for a GitHub issue.
Orchestrate Mode
Triggered by orchestrate as the first token in arguments
(e.g. /itx:execute orchestrate 112). Use when the issue is a parent
with linked subtasks and you want a hands-off, stacked-PR pipeline
across all subtasks.
Preconditions
- Parent issue exists and has sub-issues linked (via GitHub
addSubIssue). Detect via:
gh issue view <parent> --json title,body,labels && \
gh api graphql -f query='query($owner: String!, $repo: String!, $num: Int!) {
repository(owner: $owner, name: $repo) {
issue(number: $num) {
subIssues(first: 50) { nodes { number title state } }
}
}
}' -f owner="$OWNER" -f repo="$REPO" -F num=<parent>
tmux available on the host. If not, fail with a clear message —
orchestrate mode requires tmux.
- A plan file exists at
.itx/<parent>/00_PLAN.md (created by
/itx:plan-create). Refuse to start otherwise.
ATX availability is not a precondition. Children use the
fallback chain in ATX Review below. Handoff is still keyed on
PR-open — without ATX, that just means the child opens the PR after
local make test + make lint pass instead of after an ATX rating
clears.
Orchestration contract
The orchestrator (the claude session that runs orchestrate mode) does
only these things:
- Creates worktrees + branches + tmux windows for each subtask.
- Spawns a child claude session per subtask via
claude --dangerously-skip-permissions '/itx:execute <N>' in the
subtask's worktree.
- Polls subtask PR state every ~5 minutes.
- When a subtask's PR appears (the child's handoff signal), spawns
the next subtask with the correct stacked base.
- Surfaces stuck children (PRs carrying
[ITX-STUCK]) in the
end-of-run summary table, but does not halt the pipeline
waiting for user input — see "Stuck child" below.
The orchestrator does NOT:
- Touch source code.
- Run tests / lint directly.
- Merge PRs. Merging is the user's decision.
- Block on user input. If something requires a decision, the child
records it as a Callout on its PR and proceeds.
- Bypass ATX when ATX is available; bypass
--no-verify.
- Spawn all subtask windows up front. Windows are created on demand
when the predecessor's PR is open.
Stacked PR layout
Given subtasks A, B, C, D (in dependency order from sub-issue
metadata), the orchestrator opens each child's PR against the
predecessor's branch, not main:
| Sub | Branch | PR base |
|---|
| A | issue-<A>-<slug> | main |
| B | issue-<B>-<slug> | issue-<A>-<slug> |
| C | issue-<C>-<slug> | issue-<B>-<slug> |
| D | issue-<D>-<slug> | issue-<C>-<slug> |
As predecessors merge, GitHub auto-updates downstream PR bases to main.
tmux layout
- Session name:
<project-name>-issue-<parent> where <project-name>
is the repo name from basename $(git rev-parse --show-toplevel).
Example: clawrium-issue-478.
- One window per subtask, named
issue-<N> (the subtask issue number).
Example: issue-481, issue-482, issue-483.
- Created on demand. User attaches with
tmux attach -t <project-name>-issue-<parent>.
- Window 0 (the session's default window) is owned by the orchestrator
and runs the polling loop / status display.
Step-by-step
-
Parse args. Extract orchestrate token + parent issue number.
Fall through to regular execution mode if orchestrate absent.
-
Verify preconditions (above). On failure, exit with a clear
message citing the missing precondition.
-
Enumerate subtasks. Order by sub-issue number (creation order).
Treat order as dependency order unless the plan file specifies
otherwise.
-
Create tmux session:
REPO_NAME=$(basename $(git rev-parse --show-toplevel))
SESSION="${REPO_NAME}-issue-${PARENT}"
tmux has-session -t "$SESSION" 2>/dev/null || \
tmux new-session -d -s "$SESSION"
-
Spawn subtask A:
REPO_PARENT=$(dirname $(git rev-parse --show-toplevel))
WORKTREE_A="${REPO_PARENT}/${REPO_NAME}-issue-${A_NUM}"
BRANCH_A="issue-${A_NUM}-<slug>"
git worktree add "$WORKTREE_A" -b "$BRANCH_A" main
tmux new-window -t "$SESSION" -n "issue-${A_NUM}" -c "$WORKTREE_A"
tmux send-keys -t "${SESSION}:issue-${A_NUM}" \
"claude --dangerously-skip-permissions '/itx:execute ${A_NUM}'" Enter
-
Poll predecessor PR state every 5 minutes:
gh pr list --repo "$OWNER/$REPO" --head "$BRANCH_A" \
--json number,state,reviewDecision,body --jq '.[0]'
The child opens its PR when its work is ready — that means
tests + lint pass and, if ATX is available, its iteration loop
has either cleared or exhausted (with unresolved blockers
documented as Callouts and an [ITX-STUCK] marker on the PR).
Do not poll faster than 5 minutes. Child iterations take
minutes; faster polling burns cache without changing outcomes.
-
On predecessor PR open, spawn next subtask:
-
Repeat until all subtasks have open PRs.
-
Final state. Orchestrator reports a summary table with each
subtask's PR URL, ATX rating, and base branch. Then stands down.
Merging is the user's decision; merging happens bottom-up.
Stuck child (non-blocking)
A child that exhausts its 3-iteration ATX ceiling without clearing
still opens its PR. The PR body documents every unresolved
blocker as a Callout and the PR carries an [ITX-STUCK] marker
comment.
The orchestrator's polling loop treats an [ITX-STUCK]-marked PR the
same as a clean PR for the purpose of advancing the pipeline — the
child has done its best, recorded the gaps, and handed off. Do not
halt and do not block on user input.
In the end-of-run summary, flag every stuck subtask with the count of
unresolved blockers so the user sees them up front. Merging decisions
remain entirely the user's — they can read the Callouts, push back on
the PR, take it over manually, or abandon. The orchestrator stands
down after reporting; it does not wait for that decision.
If the orchestrator itself encounters a genuinely unrecoverable
condition (e.g., worktree directory already exists with a conflicting
branch), it records a Callout on the parent issue (#<parent>)
and exits non-zero with a summary. It does not prompt.
PR base override (child contract)
When a child receives --pr-base=<branch>, it MUST:
- Open its PR against that branch, not
main.
- Include
Stacked on top of <branch> in the PR body so reviewers know
the dependency chain.
If the child's mode does not support --pr-base, the orchestrator
falls back to opening the PR itself after the child finishes:
gh pr edit <pr-num> --base "$PREV_BRANCH"
Failure modes
- No subtasks found: fail with "Issue #N has no linked sub-issues.
Use
/itx:execute <N> (without orchestrate) for direct execution."
- Subtask already has merged PR: skip and advance to next.
- Subtask already has open PR: skip the spawn step; treat as
"ATX-cleared, advance to next".
- Worktree already exists: re-use if branch matches expected name;
fail otherwise (manual cleanup required).
- tmux session orphaned: re-use if exists; do not create duplicate.
When to use orchestrate mode
- Parent issue with 2+ linked subtasks where order matters.
- You want hands-off execution across the whole chain.
- ATX is enabled and tmux is available.
When NOT to use orchestrate mode
- Single-issue (no subtasks) — use regular mode.
- You want manual control between every subtask — use regular mode
with explicit handoffs.
Note: ATX availability is not a precondition. If ATX is unavailable
or fails, the orchestrator still spawns subtasks; PR-open remains the
handoff signal. See ATX Review below.
ATX Review (resilient, non-blocking)
Code review via ATX is desired but not required. Children execute
review with a strict fallback chain and persist state so an interrupted
execution can resume without re-running ATX on identical changes.
Detection chain
Try each step in order; use the first that works. Never block the
user waiting for ATX to become available.
- ATX via MCP (preferred). Check whether
mcp__atx__request_review is available in the tool list. If yes,
call it with the iteration body specified in
AGENTS.md.
- ATX via CLI (fallback). If MCP is not available, check
command -v atx on the host. If found, invoke
atx review --pr <pr-number> --json (or the project's documented
CLI invocation in .claude/itx-config.json if specified) and parse
the JSON output the same way you'd parse the MCP response.
- Skip ATX (last resort). If neither MCP nor CLI is available,
proceed with the work — do not block, do not prompt the user.
Record a Callout on the PR (see "Callouts" below) noting that ATX
was unavailable so the reviewer knows to do a manual pass.
Session ID persistence
Whenever an ATX review is requested (MCP or CLI), persist the session
metadata immediately to .itx/<N>/atx-session.json:
{
"session_id": "<id returned by ATX>",
"transport": "mcp" | "cli",
"commit_sha": "<HEAD sha at the moment review was requested>",
"iteration": 1,
"last_rating": null,
"last_blockers": [],
"started_at": "<ISO-8601 UTC>",
"updated_at": "<ISO-8601 UTC>"
}
Update the file after every iteration with iteration, last_rating,
last_blockers, and updated_at. Commit this file alongside your
code changes — it's a planning artifact and helps the next run.
On resume / re-entry
When /itx:execute <N> starts and .itx/<N>/atx-session.json exists:
- Read the file.
- Compare
commit_sha with current git rev-parse HEAD.
- Match +
last_rating > 3 + no blockers → ATX already cleared
these changes. Skip ATX entirely; proceed to PR open / push.
- Match + unresolved blockers → Resume the same session
(poll status if MCP / re-fetch if CLI) instead of starting a new
review. This avoids burning cost on duplicate runs over identical
changes.
- Mismatch (HEAD has moved) → Stale session. Delete the file
and start a fresh ATX review against the new commit.
- If
transport differs from what's currently available (e.g., file
says mcp but only CLI is available now): treat as stale, start
fresh — sessions are not portable across transports.
Iteration ceiling (non-blocking)
Run at most 3 ATX iterations. After the 3rd iteration:
- If Rating > 3/5 with no blockers: open / update PR normally with
the ATX summary in the body.
- If still blocked: open the PR anyway with:
- The full ATX iteration history in the PR body (per
<pr-format-atx> in AGENTS.md).
- A Callouts section (see below) enumerating every unresolved
blocker with a best-guess decision and the reasoning. Do not
leave the work in an open-ended "stuck" state — close out with a
callout instead.
- Add the
[ITX-STUCK] marker comment on the PR so the
orchestrator's polling loop can flag it.
This replaces the older "wait for user direction" behavior. The
orchestrator may still surface a stuck child in its end-of-run
summary, but it will not pause the pipeline waiting for input — it
either proceeds to the next subtask (if one is queued) or stands down
with the report.
Callouts (required in every PR body)
Every PR opened by /itx:execute MUST include a Callouts section
near the bottom of the body — even if empty. Format:
## Callouts
- [DECISION] <one-line summary of a non-obvious choice you made>
- Why: <best-guess rationale based on existing project standards>
- Alternatives considered: <briefly>
- Reviewer: confirm or push back.
- [UNRESOLVED] <what could not be resolved by the agent alone>
- Best guess applied: <what you did anyway>
- Reviewer: please verify.
- [ENVIRONMENT] <anything unusual about the execution environment>
- Example: "ATX unavailable; review path was manual."
- [TODO-FOLLOWUP] <work intentionally deferred>
- Tracking: <issue number or `to be filed`>
If you would otherwise want to ask the user a question via
AskUserQuestion, don't — make a best-guess decision using
existing project conventions (CLAUDE.md, AGENTS.md, neighboring code)
and record it as a [DECISION] callout instead. The PR is the
synchronization point with the user; do not block during execution.
If there are genuinely no callouts, write:
## Callouts
_None._
so the reviewer knows the section wasn't forgotten.
Worktree Mode (Recommended for Parallel Execution)
Triggered by in a subtree or --worktree in arguments. Enables working on multiple issues simultaneously.
Worktree Naming Convention
<repo-parent>/<repo-name>-issue-<number>/
Example:
~/projects/myrepo/ # Main repo
~/projects/myrepo-issue-35/ # Worktree for issue 35
~/projects/myrepo-issue-42/ # Worktree for issue 42
Worktree Execution Steps
-
Create Worktree:
REPO_NAME=$(basename $(git rev-parse --show-toplevel))
REPO_PARENT=$(dirname $(git rev-parse --show-toplevel))
WORKTREE_PATH="${REPO_PARENT}/${REPO_NAME}-issue-${NUMBER}"
git worktree add "${WORKTREE_PATH}" -b issue-${NUMBER}-<slug> main
-
Launch Execution:
If tmux available (interactive execution in background):
REPO_NAME=$(basename $(git rev-parse --show-toplevel))
SESSION="${REPO_NAME}-issue-${NUMBER}"
tmux has-session -t "$SESSION" 2>/dev/null || \
tmux new-session -d -s "$SESSION"
tmux new-window -t "$SESSION" -n "issue-${NUMBER}" -c "${WORKTREE_PATH}"
tmux send-keys -t "${SESSION}:issue-${NUMBER}" \
"claude --dangerously-skip-permissions '/itx:execute ${NUMBER}'" Enter
echo "Spawned in tmux '${SESSION}:issue-${NUMBER}'"
echo "Attach: tmux attach -t ${SESSION}"
If tmux not available (fallback):
Do not prompt the user. Spawn a Task subagent
(subagent_type="general-purpose") in the worktree with prompt
/itx:execute ${NUMBER}. Record this fallback in the PR's
Callouts section so the user knows the execution path differed
from the default (tmux + interactive claude).
-
Exit: After spawning tmux window, exit current execution (work continues in tmux)
Worktree Cleanup
After PR is merged:
git worktree remove ../<repo>-issue-35
git worktree remove --force ../<repo>-issue-35
tmux kill-session -t "<repo>-issue-35"
tmux kill-window -t "<repo>-issue-<parent>:issue-35"
GitHub Project Board (Optional)
Project board integration is optional and controlled via .claude/itx-config.json.
Check if Project Board is Enabled
ITX_CONFIG="$(git rev-parse --show-toplevel)/.claude/itx-config.json"
if [ -f "$ITX_CONFIG" ]; then
PROJECT_ENABLED=$(jq -r '.github.project_board.enabled // false' "$ITX_CONFIG")
if [ "$PROJECT_ENABLED" = "true" ]; then
PROJECT_ID=$(jq -r '.github.project_board.project_id' "$ITX_CONFIG")
STATUS_FIELD_ID=$(jq -r '.github.project_board.status_field_id' "$ITX_CONFIG")
BACKLOG_ID=$(jq -r '.github.project_board.status_options.backlog' "$ITX_CONFIG")
READY_ID=$(jq -r '.github.project_board.status_options.ready' "$ITX_CONFIG")
EXECUTING_ID=$(jq -r '.github.project_board.status_options.executing' "$ITX_CONFIG")
IN_REVIEW_ID=$(jq -r '.github.project_board.status_options.in_review' "$ITX_CONFIG")
DONE_ID=$(jq -r '.github.project_board.status_options.done' "$ITX_CONFIG")
fi
else
PROJECT_ENABLED="false"
fi
Add Issue to Project & Set Status (if enabled)
Only execute if PROJECT_ENABLED="true":
REMOTE_URL=$(git config --get remote.origin.url)
OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's/.*[:/]([^/]+\/[^/]+)(\.git)?$/\1/')
OWNER=$(echo "$OWNER_REPO" | cut -d'/' -f1)
REPO=$(echo "$OWNER_REPO" | cut -d'/' -f2)
NODE_ID=$(gh api repos/$OWNER/$REPO/issues/<number> --jq '.node_id')
ITEM_ID=$(gh api graphql -f query='
mutation($projectId: ID!, $contentId: ID!) {
addProjectV2ItemById(input: {
projectId: $projectId
contentId: $contentId
}) { item { id } }
}
' -f projectId="$PROJECT_ID" -f contentId="$NODE_ID" --jq '.data.addProjectV2ItemById.item.id')
gh project item-edit --project-id "$PROJECT_ID" --id "$ITEM_ID" \
--field-id "$STATUS_FIELD_ID" --single-select-option-id "$EXECUTING_ID"
If project board not enabled, skip all project board operations silently.
Branch Protection
NEVER push directly to the main branch.
Always:
- Work on a feature branch:
issue-<number>-<slug>
- Push to the feature branch
- Create a PR targeting
main
Instructions
-
Fetch Issue: Get full issue details
gh issue view <number> --json number,title,body,labels,comments
-
Identify Issue Type:
- Subtask: Title starts with
[Parent #N]
- Parent with subtasks: Has subtask issues linked
- Parent without subtasks: Direct execution
-
Route Execution:
If Parent with Subtasks
- List subtasks by searching for issues with
[Parent #<number>] in title
- For each subtask (in order):
- Spawn a subagent to execute the subtask
- Wait for subtask completion
- Verify subtask is marked done
- Once all subtasks complete, close parent issue
If Parent without Subtasks OR Subtask
-
Log Start: Add execution start comment
## Execution Started
Beginning implementation...
---
<details>
<summary>Prompt Log</summary>
**Stage**: execution
**Skill**: /itx:execute
**Timestamp**: <ISO timestamp>
**Model**: <model>
```prompt
<user prompt that triggered execution>
```
-
Update Status to Executing (if project board enabled):
Use the conditional project board commands above.
If not enabled, skip this step silently.
-
Read Plan: Find the implementation plan in issue comments or .itx/<N>/01_EXECUTION.md
-
Load Build Configuration:
ITX_CONFIG="$(git rev-parse --show-toplevel)/.claude/itx-config.json"
if [ -f "$ITX_CONFIG" ]; then
TEST_CMD=$(jq -r '.build.test_command // "make test"' "$ITX_CONFIG")
LINT_CMD=$(jq -r '.build.lint_command // "make lint"' "$ITX_CONFIG")
else
TEST_CMD="make test"
LINT_CMD="make lint"
fi
-
Create Execution Checklist:
CRITICAL: ALWAYS create task checklist before any execution. Do not skip this step.
Parse the implementation plan and create tasks for tracking:
a. Create Implementation Tasks:
For each phase/step in the plan, create a task:
TaskCreate(
subject="Implement: <phase/step description>",
description="<detailed requirements from plan>",
activeForm="Implementing <phase/step>"
)
b. Create Verification Tasks:
TaskCreate(
subject="Run test suite",
description="Execute configured test command and ensure all tests pass",
activeForm="Running tests"
)
TaskCreate(
subject="Run linter",
description="Execute configured lint command and fix any issues",
activeForm="Running linter"
)
c. Set Dependencies (if needed):
TaskUpdate(
taskId="<later-task-id>",
addBlockedBy=["<prerequisite-task-id>"]
)
d. Review Task List:
TaskList() # Confirm all tasks created correctly
-
Execute Tasks Systematically:
a. Get Next Task: TaskList() - Find first pending task with no blockedBy
b. Start Task: TaskUpdate(taskId="<task-id>", status="in_progress")
c. Execute Changes: Implement the task requirements
- Make code changes
- Write/update tests
- Follow existing code patterns
d. Complete Task: TaskUpdate(taskId="<task-id>", status="completed")
e. Check Progress: TaskList() - See remaining tasks
f. Repeat until all implementation tasks are completed
-
Execute Verification Tasks:
Follow the same pattern as implementation:
- Mark verification task as in_progress
- Run verification using configured commands ($TEST_CMD, $LINT_CMD)
- Mark as completed
- Move to next verification task
-
Create PR:
PR body MUST follow the templates in AGENTS.md (ATX or manual,
depending on what was actually used during execution) and MUST
include a ## Callouts section near the bottom — see the
Callouts section earlier in this skill. The Callouts section is
non-optional; write _None._ if there are none.
If in worktree mode: Branch already exists (created during worktree setup)
git add <files>
git commit -m "<message>"
git push -u origin issue-<number>-<slug>
gh pr create --title "<title>" --body-file <body-file>
If in regular mode: Create branch first
git checkout -b issue-<number>-<slug>
git add <files>
git commit -m "<message>"
git push -u origin issue-<number>-<slug>
gh pr create --title "<title>" --body-file <body-file>
WARNING: Never push to main. Always push to feature branch and create PR.
Progress Tracking with Tasks
Creating Tasks from Plan
When reading the implementation plan, extract:
- Implementation steps: Each becomes a task
- Files to modify: Include in task descriptions
- Dependencies: Set using addBlockedBy
- Acceptance criteria: Include in task descriptions
Task Naming Convention
subject: "Implement: <what>"
description: "<detailed requirements>"
activeForm: "Implementing <what>"
Examples:
subject: "Implement: Update CLI help text for new terminology"
description: "Update all help text in src/cli/main.py to use new terminology"
activeForm: "Updating CLI help text"
subject: "Implement: Refactor service.py function names"
description: "Rename functions: old_name -> new_name, another_old -> another_new"
activeForm: "Refactoring service.py"
Standard Verification Checklist
Always create these verification tasks:
- Run test suite (using configured test command)
- Run linter (using configured lint command)
- Verify no regressions
When You Get Lost
If execution feels unclear or you lose track of progress:
- Run
TaskList() to see current state
- Check which task is in_progress
- Review that task's description
- Complete current task before starting next
- Never jump ahead without marking tasks complete
Subagent Spawning (for Parent with Subtasks)
Use the Task tool to spawn subagents:
Task(
subagent_type="general-purpose",
prompt="Execute /itx:execute <subtask-number>",
description="Execute subtask #<number>"
)
Execute subtasks sequentially to avoid conflicts.
Completion Check (for Subtasks)
After completing a subtask, check if all sibling subtasks are done:
Configuration
Build commands are configurable via .claude/itx-config.json:
{
"build": {
"test_command": "npm test",
"lint_command": "npm run lint"
}
}
Defaults (no config): make test, make lint
See CONFIG.md for full configuration options.
Notes
- NEVER block on user input. No
AskUserQuestion, no interactive
prompts. When in doubt, follow existing project standards (CLAUDE.md,
AGENTS.md, neighboring code) and record the decision as a Callout on
the PR. The PR is the synchronization point with the user.
- Always include a Callouts section in the PR body — see the
Callouts section of this skill. Write
_None._ if empty.
- ALWAYS create task checklist before execution — do not skip this step.
- Use TaskList() frequently to maintain awareness of progress.
- Complete tasks sequentially unless explicitly marked as parallel.
- If you feel lost, check TaskList() to reorient.
- ATX is best-effort: try MCP, then CLI, then skip and note in
Callouts. Never block on ATX availability. Persist
.itx/<N>/atx-session.json so interrupted runs don't re-run ATX on
identical changes.
- Project board updates are optional and only execute if configured.
- Build commands automatically adapt to project configuration.
- Subtasks can use cheaper/faster models (Haiku).
- Parent orchestration can use any model.
- Always verify before marking complete — don't skip the verification step.
Prompt Logging
REQUIRED: Append prompt log to .itx/<N>/01_EXECUTION.md.
See AGENTS.md for format specification.