Prism is a lightweight orchestrator that connects Linear to a containerised TDD workflow. Assign an issue to the agent user, comment @prism start on the card, and Prism spawns a Claude Code session that runs the /tdd skill, posts milestone comments as work progresses, and moves the card to In Review when done.
Issue assigned → @prism start → Prism claims card → runs /tdd → posts plan + checkpoints → PR created → card → In Review
| Dependency | Purpose |
|---|---|
| Python 3.12+ | Runtime |
| uv | Package manager |
| claude-agent-sdk | Spawns inner Claude Code session |
Claude Code (~/.claude/) |
Auth + plugin host |
codezen plugin (~/.claude/plugins/codezen/) |
Provides the /tdd skill |
| Docker | TDD container runtime |
gh CLI (authenticated) |
PR creation |
| Linear API key | Issue tracking |
git clone https://github.com/sauravsrijan/prism
cd prism
uv syncCreate .prism/config.yaml in the directory where you run prism:
linear:
api_key_env: LINEAR_API_KEY # env var holding your Linear API key
agent_user_id: "<your-user-uuid>" # Linear UUID of the account issues are assigned to
team_id: "<your-team-uuid>" # Linear team UUID
poll_interval_seconds: 30
poll_jitter_seconds: 5
active_states: ["In Progress"] # states Prism watches for new work
on_complete_state: "In Review" # state to move card to on success
project:
repo_path: /path/to/your/repo # absolute path to the target codebase
base_branch: main
sdk:
model: "claude-sonnet-4-6"
max_turns: 100
permission_mode: "bypassPermissions"
tdd:
use_real_infra: false # pass --use_real_infra=true to /tdd when true
timeout_seconds: 1800
runtime:
max_concurrent_tasks: 1
events_path: .prism/events.jsonl
heartbeat:
edit_interval_seconds: 30 # how often to edit the in-progress commentSet your Linear API key in the environment:
export LINEAR_API_KEY="lin_api_..."prism preflightRuns 8 startup checks (API key, Linear reachability, Docker, gh auth, codezen plugin, etc.) and exits 0 if all pass.
prism dispatch KOR-1One-shot: fetches the issue, claims it, runs TDD, posts results. Exits 0 on success, 1 on failure.
prism dispatch KOR-1 --dry-runBuilds and prints the feature spec that would be sent to the inner Claude — no side effects, nothing posted to Linear.
prism runPolls Linear every poll_interval_seconds (± jitter). Press Ctrl-C to stop cleanly.
Prism does not auto-dispatch assigned issues. It only acts when you comment on the card:
| Comment | Effect |
|---|---|
@prism start |
Start TDD on this card |
@prism start, <instructions> |
Start TDD and pass extra instructions to the inner Claude (e.g. @prism start, focus on edge cases) |
Prism reads the trigger comment at dispatch time — anything after @prism start, is appended to the feature spec as operator instructions.
prism events tail # last 50 events
prism events tail --follow # stream new events as they arrive- Poll — finds issues in
active_statesassigned toagent_user_id. - Trigger check — scans comments for
@prism start. Skips the issue silently if not found. - Claim — posts an HTML-marker comment (
<!-- prism:kind=claim ... -->). Skips if already in-flight. - Preflight — quick checks (clean working tree, Docker warning) before starting work.
- Feature spec — builds a description from the issue title, body, and human comments. Any text after
@prism start,is appended as extra instructions. - Run /tdd — spawns a
claude-agent-sdksession with the codezen plugin loaded. The inner Claude runs/tdd, creates a PR viagh pr create, and emits structured checkpoint markers. - Checkpoints — Prism posts a new Linear comment at each milestone: plan ready, failing tests written, tests passing.
- Result — on success: posts PR link, moves card to
on_complete_state. On failure: posts error details.
Every lifecycle event is appended to events.jsonl with fsync. On restart, Prism replays the log, finds any IssueClaimed events without a matching TaskCompleted or TaskFailed, posts an abandoned comment on those cards, and marks them as eligible for re-dispatch.
Prism writes to .prism/ (gitignored):
.prism/
├── config.yaml # your configuration
├── events.jsonl # append-only event log
└── instance-id # UUID identifying this orchestrator installation
- One task at a time (
MAX_CONCURRENT_TASKS=1) - Polling only — no webhooks
- Single Linear project per instance
- Only the
/tddworkflow is supported - No web dashboard (Linear is the UI)
v0.2 will add daemon mode, a FastAPI dashboard, webhooks, and Linear MCP access for the inner Claude.