git clone https://github.com/LightbridgeLab/CodeCannon
T=$(mktemp -d) && git clone --depth=1 https://github.com/LightbridgeLab/CodeCannon "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.agents/skills/start" ~/.claude/skills/lightbridgelab-codecannon-start && rm -rf "$T"
.agents/skills/start/SKILL.mdCodex CLI: This skill is triggered by description matching. State any arguments in your message. Sub-agent spawning is not supported — perform any review steps inline.
CRITICAL: Order of operations
You must complete Steps 1–4 before writing any code. Do not open any source file with intent to edit until
git branch --show-current shows a feature/* branch.
Determine case
If
$ARGUMENTS is a number (digits only) → go to Case B: Resume existing issue.
Otherwise → go to Case A: New work.
Parsing $ARGUMENTS (Case A only)
Skip this entirely if
triggered Case B.$ARGUMENTS
The argument string may contain optional inline flags after the description. Parse as follows:
- Identify flags — scan for the first token that starts with
,--label
,-l
, or--milestone
. Everything before it is the description. Everything from the first flag onward is flags.-m
/--label <value>
— comma-separated label string (e.g.-l <value>
orbug
). If provided, it bypasses label auto-selection entirely for this invocation — use the value verbatim. Labels containing spaces must be quoted (e.g.enhancement,ux
).--label "good first issue"
/--milestone <value>
— milestone name or number (e.g.-m <value>
orSprint 4
). Pass the value as-is; GitHub accepts both names and numbers.12- Flags may appear in any order after the description.
Label resolution (three-tier, Case A only):
After parsing flags, determine the active labels in this order:
- Per-invocation flag — if
was in--label <value>
, use that value verbatim. Skip all remaining steps.$ARGUMENTS - Pool-based selection — the allowed label pool is:
(comma-separated). Select 1–3 labels from this pool that genuinely fit the task description and implementation approach. Do not apply labels mechanically — pick only what fits. If no pool label fits the task, fall through to step 3.bug, documentation, enhancement, chore- If any selected label name contains a space (e.g.
), quote the entiregood first issue
value.--label
- If any selected label name contains a space (e.g.
- No label / creation — if the pool is empty or no pool label fits:
- Label creation is not allowed in this project. Omit
entirely. Proceed silently; do not inform the user.--label
- Label creation is not allowed in this project. Omit
Milestone resolution (three-tier, Case A only):
After parsing flags, determine the active milestone in this order:
- Per-invocation flag — if
was in--milestone <value>
, use that value. Stop.$ARGUMENTS - Auto-detect — if no milestone is resolved yet, query open milestones:
Usegh api repos/{owner}/{repo}/milestones --jq '[.[] | select(.state=="open")] | {count: length, milestones: [.[] | {number: .number, title: .title}]}'
first if the owner/repo are not already known.gh repo view --json owner,name- 0 results → no milestone; proceed without
.--milestone - 1 result → use its title silently. Inform the user inline:
.(milestone: <title>) - 2+ results → show the numbered list, ask once: "Multiple open milestones — which should this issue go under? (enter a number or title, or 'none')". Accept milestone number, title, or "none"/"skip". Wait for response before continuing.
- 0 results → no milestone; proceed without
Examples:
| Description | Labels | Milestone |
|---|---|---|---|
| | auto-selected from pool | auto-detected |
| | (verbatim) | auto-detected |
| | (verbatim) | |
Replace vs append: flags replace auto-selection entirely, they do not append. This avoids silent label duplication and milestone conflicts.
Pre-check: Existing feature branch
Before entering Case A or Case B, check the current branch:
git branch --show-current
If already on a
feature/* branch and $ARGUMENTS is not a number (i.e. this is new work, not a resume):
Say:
"You're already on
. Would you like to create a GitHub issue linked to this branch and start coding? Or switch to the base branch first? (yes to continue here / no to abort)"feature/<name>
Stop. Wait for the user to respond.
- Yes → proceed to Case A, but skip Step 4 (branch creation) entirely. The current branch is used as-is. In Step 3, after creating the issue, link it to the existing branch by running:
This links the issue to the branch in GitHub without creating or checking out a new branch. Ifgh issue develop <number> --base <base-branch> --name <current-branch-name>
fails because the branch already exists on the remote, that is fine — the link may already be established. Continue to Step 5.gh issue develop - No / abort → stop. Tell the user to switch to the base branch and run
again./start
If already on a
feature/* branch and $ARGUMENTS is a number → proceed to Case B normally (it handles branch checkout itself).
If on any other branch → proceed to Case A or Case B as determined by the
$ARGUMENTS check above.
Case A: New work (text description)
Step 1 — Investigate
Read the relevant code. Propose a concrete implementation approach. Be specific about which files change and how.
Step 2 — HUMAN GATE
Say exactly:
"Does this approach sound right? Type
to create a GitHub issue and branch, or share any questions/adjustments first."go
Stop. Wait for the user to respond.
The friendly text question is required regardless of harness mode. If your harness is currently in a preview / plan / dry-run mode where you cannot passively stop and wait (and must instead invoke the harness's own approval mechanism), still include the text question in your response. The harness's approval UI mediates the wait, but it is not a substitute for the question itself. Users expect to see the consistent text language across all modes; do not silently swap it for the harness's UI.
Intent classification (not keyword matching):
- Affirmative with no conditions ("go", "yes", "looks good", "let's do it") → continue to Step 3.
- Affirmative with conditions ("go, but first change X", "yes but can we also...") → treat as discussion. Address the conditions, revise the approach if needed, then re-ask.
- Questions or pushback ("what about...", "I'm not sure about...", any adjustment) → discuss, revise approach, re-ask.
- Abandonment ("never mind", "not now", "stop") → stop. Nothing to clean up.
Step 3 — Create GitHub Issue
Create the issue in two steps — this exact sequence is mandatory:
Step 3a — Create a temp directory and write the body file. Run:
mkdir -p /tmp/CodeCannon && mktemp -d /tmp/CodeCannon/XXXXXX
Note the returned path (e.g.
/tmp/CodeCannon/a8f3b2). Use this path for all temp files in this invocation.
Then use your file-writing tool (Write in Claude Code, equivalent in other agents) to create
<tmpdir>/issue_body.md with the structured markdown body (see sections below). Do NOT use Bash/shell to write this file. Do NOT use heredocs, cat, or echo. The file-writing tool bypasses shell parsing entirely.
Step 3b — Run
with gh issue create
--body-file pointing to the temp file:
gh issue create \ --title "<standalone full sentence — must make sense with no context>" \ --assignee @me \ [--label "<resolved labels>"] \ [--milestone "<resolved milestone>"] \ --body-file <tmpdir>/issue_body.md
IMPORTANT — never pass body content inline in the
command. Do not usegh,--body, heredocs (--body-file -or<<EOF), or<<'EOF'. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags$(cat ...)headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then#— is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex.--body-file <path>
Resolve labels and milestone using the resolution steps in the Parsing section above:
- Labels: use the value from three-tier label resolution. If non-empty, add
to the command. If empty (no flag, empty pool, creation not allowed), omit--label "<value>"
entirely.--label - Milestone: use the value from three-tier milestone resolution. If non-empty, add
to the command. If empty (no flag, no config default, no open milestones), omit--milestone "<value>"
entirely.--milestone
Body structure (required sections, in this order):
## Problem to Fix <what is broken or missing, written for a non-developer — no code or file paths> ## Why it Matters <the impact or motivation — who is affected and how> ## General Approach <high-level direction for the fix, in plain language> ## Complexity **Verification / QA effort:** <trivial | moderate | significant | extensive> <one-line justification — what makes verification easy or hard for this specific change> ## Acceptance Criteria - <specific, verifiable outcome> - <another outcome>
All five sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals).
Complexity scale guidance (for agent use only — do not include the scale definition in the issue body):
- trivial — single obvious check (e.g. color change, label text, toggle visibility)
- moderate — a few scenarios to verify, minor setup needed (e.g. form validation, a new UI component with a couple of states)
- significant — many scenarios, data setup, or cross-feature impact (e.g. multi-step workflow, permission changes across roles)
- extensive — complex data flows, integration testing, or edge cases spanning multiple areas (e.g. data import/export mapping, API contract changes consumed by multiple clients)
Title rules:
- ✅
Fix 'Contact Us' footer link pointing to 404 instead of /contact-us - ❌
Fix broken link
After the command runs, note the issue number from the output URL (e.g.
https://github.com/.../issues/42 → issue 42).
Show the user:
Created issue #<number>: <title>
Then immediately post agent implementation notes as a comment.
Use your file-writing tool (not Bash) to create
<tmpdir>/issue_comment.md (same temp directory from Step 3a):
## Agent Implementation Notes <full technical plan: exact files to change, approach, key decisions, edge cases>
Then post it (do NOT use
--body or heredocs — same rule as Step 3):
gh issue comment <number> --body-file <tmpdir>/issue_comment.md
Step 4 — Create feature branch
Ensure the base branch is up-to-date before branching:
git checkout dev && git pull origin dev
Now create the feature branch:
gh issue develop <number> --base dev --name feature/<number>-<short-descriptive-name> --checkout
is required:--basereads the default base from the GitHub API, not from local working state, sogh issue developon its own does not influence which branch the new feature branch is cut from.git checkout dev
Verify the branch was created:
git branch --show-current
Show the user:
On branch feature/<name>
Do not proceed to Step 5 until this shows a
branch.feature/*
Step 5 — Write the code
Now write the code. Do NOT commit anything.
When done, say: "The code is ready for review. Please run
and test locally. Let me know if it looks good, needs changes, or should be scrapped. When you're happy, run make dev
to commit, push, and open a PR."/submit-for-review
- User says looks good → run
/submit-for-review - User requests changes → iterate, repeat this message
- User says scrap it → run
make abandon
Case B: Resume existing issue (numeric argument)
Step 1 — Load context
gh issue view <number> --comments
Read the full body and all comments. Note: what was done, what remains, branch status.
Step 2 — Summarize and gate
Tell the user:
- What the issue is about
- What was previously done (from agent notes if present)
- What appears to remain
Ask: "Does this match your understanding? Type
to start coding, or share any questions/adjustments first."go
Intent classification (not keyword matching):
- Affirmative with no conditions ("go", "yes", "continue", "looks right") → proceed to Step 3.
- Affirmative with conditions ("go, but first...", "yes but let's also...") → treat as discussion. Address the conditions, then re-ask.
- Questions or discussion ("what about...", "can we change...", any adjustment) → discuss, then re-ask.
- Fresh start ("open a new one", "start fresh", "new ticket") → restart as Case A with a new description.
- Abandonment ("never mind", "not now", "stop") → stop. Nothing to clean up.
Step 3 — Check out branch
Ensure the base branch is up-to-date before branching:
git checkout dev && git pull origin dev
Find and check out the existing branch, or create a new one linked to the issue:
gh issue develop <number> --base dev --name feature/<number>-<short-name> --checkout
is required:--basereads the default base from the GitHub API, not from local working state.gh issue develop
Verify:
git branch --show-current
Post a resumption comment:
gh issue comment <number> --body "Resuming work. <brief note on what's being continued.>"
Step 4 — Write the code
Continue from where work left off. Do NOT commit.
When done, say: "The code is ready for review. Please run
and test locally. When you're happy, run make dev
to commit, push, and open a PR."/submit-for-review
Hard rules
- Do not write or edit any source file before
showsgit branch --show-current
.feature/* - Do not use
— always usemake branch
so the branch is linked to the issue in GitHub.gh issue develop - Do not commit during
— commits happen in/start
./submit-for-review - If already on a feature branch when
is invoked with new work (Case A), prompt the user to either continue on the current branch (skipping branch creation) or abort. See Pre-check: Existing feature branch above./start
must usegh issue create
and--title
flags. Never pass body content inline or open an interactive editor.--body-file- The issue is assigned to
at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with@me
.gh issue edit <number> --remove-assignee @me - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from
→ omitbug, documentation, enhancement, chore
entirely. Never apply a label outside--label
.bug, documentation, enhancement, chore - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation.