* refactor: unify action into single composite step with run.ts entrypoint Consolidate the prepare and base-action phases into a single composite step that runs src/entrypoints/run.ts. This simplifies the action.yml from multiple steps to one execution step, while keeping the same behavior. Key changes: - Add src/entrypoints/run.ts as unified entrypoint - Simplify action.yml to single 'Run Claude Code Action' step - Pass all inputs via environment variables - Update base-action to accept inputs via env vars - Support agent mode auto-detection from prompt input * refactor: keep SSH signing cleanup and token revocation as separate action steps Move SSH signing key cleanup and app token revocation back to separate composite action steps in action.yml with always() conditions, rather than handling them inside run.ts. This keeps these cleanup concerns as independently visible steps in the workflow. * fix: address PR review feedback - Use path.dirname() instead of manual string slicing for executable path - Differentiate prepare vs execution errors in catch block so tracking comment accurately reflects which phase failed - Update CLAUDE.md architecture docs to reflect unified run.ts entrypoint and four-phase design * fix: address PR review feedback - Use path.dirname() instead of manual string slicing for executable path - Differentiate prepare vs execution errors in catch block so tracking comment accurately reflects which phase failed - Rewrite CLAUDE.md to focus on mental model, key concepts, and gotchas instead of exhaustive file listings
3.4 KiB
CLAUDE.md
Commands
bun test # Run tests
bun run typecheck # TypeScript type checking
bun run format # Format with prettier
bun run format:check # Check formatting
What This Is
A GitHub Action that lets Claude respond to @claude mentions on issues/PRs (tag mode) or run tasks via prompt input (agent mode). Mode is auto-detected: if prompt is provided, it's agent mode; if triggered by a comment/issue event with @claude, it's tag mode. See src/modes/registry.ts.
How It Runs
Single entrypoint: src/entrypoints/run.ts orchestrates everything — prepare (auth, permissions, trigger check, branch/comment creation), install Claude Code CLI, execute Claude via base-action/ functions (imported directly, not subprocess), then cleanup (update tracking comment, write step summary). SSH signing cleanup and token revocation are separate always() steps in action.yml.
base-action/ is also published standalone as @anthropic-ai/claude-code-base-action. Don't break its public API. It reads config from INPUT_-prefixed env vars (set by action.yml), not from action inputs directly.
Key Concepts
Auth priority: github_token input (user-provided) > GitHub App OIDC token (default). The claude_code_oauth_token and anthropic_api_key are for the Claude API, not GitHub. Token setup lives in src/github/token.ts.
Mode lifecycle: Modes implement shouldTrigger() → prepare() → prepareContext() → getSystemPrompt(). The registry in src/modes/registry.ts picks the mode based on event type and inputs. To add a new mode, implement the Mode type from src/modes/types.ts and register it.
Prompt construction: src/prepare/ builds the prompt by fetching GitHub data (src/github/data/fetcher.ts), formatting it as markdown (src/github/data/formatter.ts), and writing it to a temp file. The prompt includes issue/PR body, comments, diff, and CI status. This is the most important part of the action — it's what Claude sees.
Things That Will Bite You
- Strict TypeScript:
noUnusedLocalsandnoUnusedParametersare enabled. Typecheck will fail on unused variables. - Discriminated unions for GitHub context:
GitHubContextis a union type — callisEntityContext(context)before accessing entity-specific fields likecontext.issueorcontext.pullRequest. - Token lifecycle matters: The GitHub App token is obtained early and revoked in a separate
always()step inaction.yml. If you move token revocation intorun.ts, it won't run if the process crashes. Same for SSH signing cleanup. - Error phase attribution: The catch block in
run.tsusesprepareCompletedto distinguish prepare failures from execution failures. The tracking comment shows different messages for each. action.ymloutputs reference step IDs: Outputs likeexecution_file,branch_name,github_tokenreferencesteps.run.outputs.*. If you rename the step ID, update the outputs section too.- Integration testing happens in a separate repo (
install-test), not here. The tests in this repo are unit tests.
Code Conventions
- Runtime is Bun, not Node. Use
bun test, notjest. moduleResolution: "bundler"— imports don't need.jsextensions.- GitHub API calls should use retry logic (
src/utils/retry.ts). - MCP servers are auto-installed at runtime to
~/.claude/mcp/github-{type}-server/.