An autonomous first-pass coding agent. Runs as a polling loop, picks up Linear tickets (or DMs to a Slack bot, or ad-hoc CLI tasks), uses Claude Code to plan and implement, opens PRs. Asks humans questions only when a real feature decision is needed; otherwise makes the call, documents the assumption, and ships.
git clone <this-repo>
cd wizard
uv venv && source .venv/bin/activate
uv pip install -e ".[slack]" # drop [slack] if you don't want the bot
wizard initwizard init walks through:
| Section | What it collects |
|---|---|
| Identity | WIZARD_OWNER (signature: <owner>'s Wizard 🧙♂️) |
| Claude Code | checks claude --version (auth handled by the CLI) |
| GitHub | checks gh auth status (no token here — gh auth login) |
| Linear | API key, team, project, repo (writes ~/.wizard/projects.md) |
| Notion | optional integration secret |
| Slack | optional bot/app tokens for the chat-bot interface |
| Target repo | absolute path to your local clone |
Config lands in ~/.wizard/config.env (mode 0600). Re-run anytime.
wizard start # long-running orchestrator loop
wizard tick # one iteration, exit (good for debugging)
wizard doctor # show config + integration health
wizard list # show all tasks and their states
wizard status <task-id-or-name>
wizard whoami # show the signature it'll sign things with
wizard add -n <name> -i "<instructions>" # ad-hoc task, no Linear needed
wizard projects list # show Linear projects polled by the orchestrator
wizard projects add # add another Linear project → repo mapping ┌── Linear (state: Todo, all projects in projects.md)
poll-loop ◄───────┤
├── Slack DM (@bot fix XYZ in /path/to/repo)
└── wizard add ...
per task:
pending ──► [Planner] ──► awaiting-approval ──► (human reply)
└─► approved ──► [Implementer] ──► pr-open
- Planner reads the ticket + skills + repo
.wizard/memory.md+ last 3 days of journal. Writes.wizard/plans/<name>.mdand commits it. Bias is toward making judgment calls and noting them as assumptions, not asking. - Implementer runs Claude Code on the existing branch, runs tests, opens
a PR via
gh. Captures a screenshot/video to.wizard/captures/for UI changes. - Approval in Linear: comment with
approved,lgtm,ship it,go ahead, oryes. Any other comment re-runs the Planner with that reply added as context. - Trigger: any Linear issue whose state is canonical type
unstarted(the "Todo" lane by default) in a project listed in~/.wizard/projects.md. When a ticket is picked up, the orchestrator transitions it to the team'sstartedstate so it shows as In Progress in Linear immediately.
Markdown files in skills/ are concatenated into every agent prompt. Edit
them to teach the agent your conventions:
style.md— formatting and namingtesting.md— test disciplinecommits.md— branch + commit stylejudgment.md— when to ask vs. when to decide
Add your own. Files starting with _ are ignored.
Each target repo gets a .wizard/memory.md the agent reads on every run
and updates as it learns. Commit it — it's project knowledge.
Everything is markdown. No database.
~/.wizard/
├── config.env # secrets (mode 0600)
├── tasks/<task-id>.md # one file per task, frontmatter + body
└── journal/2026-05-07.md # append-only WAL of every event
You can cat, grep, and even hand-edit task files if state gets confused.
Everything the agent produces is signed <WIZARD_OWNER>'s Wizard 🧙♂️:
- Git commits (via
GIT_AUTHOR_NAME/GIT_COMMITTER_NAMEenv) - PR bodies (trailer)
- Linear comments (trailer)
- Slack replies (trailer)
Override the name with WIZARD_OWNER, the email with WIZARD_OWNER_EMAIL.
If SLACK_BOT_TOKEN and SLACK_APP_TOKEN are set, wizard start connects
in Socket Mode. DM the bot or @-mention it in any channel where it's invited:
my-repo :: my-task :: fix the login validation bug # repo name from workspace
/abs/path/to/repo :: my-task :: fix it # absolute path also works
Required Slack scopes: chat:write, im:history, im:read, im:write,
app_mentions:read.
- Tester (Playwright + video) and Reviewer agents are not built yet — see
REVISED_SCOPE.mdfor the full vision. - One task per repo at a time; not yet enforced via lockfile (the orchestrator is single-threaded per tick so this is effectively true today).
- Repo-per-Linear-project mapping lives in
~/.wizard/projects.md(added bywizard initandwizard projects add). If projects.md is empty and a legacyLINEAR_PROJECT_IDis set, the orchestrator falls back to that one project and uses a longest-substring repo-name heuristic on the ticket title/description.
MIT