---
name: tbd
description: >-
  Git-native issue tracking (beads), coding guidelines, knowledge injection, and spec-driven
  planning for AI agents. Drop-in replacement for bd/Beads with simpler architecture.

  Use for: tracking issues/beads with dependencies, creating bugs/features/tasks, planning specs,
  implementing features from specs, code reviews, committing code, creating PRs, loading coding
  guidelines (TypeScript, Python, Rust, TDD, golden testing, Convex, monorepo patterns), code cleanup,
  research briefs, architecture docs, agent handoffs, external tracker and Linear integration setup,
  personal Linear API key onboarding, viewing beads in a live browser, and checking out third-party library
  source code.

  Invoke when user mentions: tbd, beads, bd, shortcuts, issues, bugs, tasks, features, epics, todo,
  tracking, specs, planning, implementation, validation, guidelines, templates, commit, PR, pull request,
  code review, testing, TDD, test-driven, golden testing, snapshot testing, TypeScript, Python, Rust, Convex,
  monorepo, cleanup, dead code, refactor, handoff, research, architecture, labels, search, web, browser,
  live view, external tracker, Linear, Linear API key, integration setup, checkout library, source code
  review, or any workflow shortcut.
allowed-tools: Bash(tbd:*) Read Write
---
**`tbd` helps humans and agents ship code with greater speed, quality, and discipline.**

1. **Beads**: Git-native issue tracking (tasks, bugs, features).
   Never lose work across sessions.
   Drop-in replacement for `bd`.
2. **Spec-Driven Workflows**: Plan features → break into beads → implement
   systematically.
3. **Knowledge Injection**: 40+ engineering guidelines (TypeScript, Python, Rust, TDD,
   testing, Convex, monorepos) available on demand.
4. **Shortcuts**: Reusable instruction templates for common workflows (code review,
   commits, PRs, cleanup, handoffs).

## Installation

```bash
npm install -g get-tbd@latest      # Install or upgrade the CLI (same command for both)
tbd setup --auto --prefix=<name>   # Fresh project (--prefix is REQUIRED: 2-8 alphabetic chars recommended. ALWAYS ASK THE USER FOR THE PREFIX; do not guess it)
tbd setup --auto                   # Existing tbd project — also the upgrade step (applies any format migration; commit the diff it reports)
tbd setup --from-beads             # Uninitialized repo: import and archive .beads/
```

If tbd refuses with “This repository requires a newer version of tbd”, run the two
install/upgrade commands above.
Setup installs `portable`, `agents-md`, `claude`, and `codex` project surfaces by
default. `--surfaces=<comma-list>` narrows only those generated agent files; setup still
performs initialization, config and format migration, and docs refresh.
Bare `tbd setup` displays help.
After `--from-beads`, verify the imported state; setup can continue after an import
warning and moves only `.beads/` to `.beads-disabled/`.

## Routine Commands

```bash
tbd --help    # Command reference
tbd status    # Status
tbd doctor    # If there are problems

tbd setup --auto   # Run any time to refresh setup
tbd prime      # Restore full context on tbd after compaction
tbd web --open # Open the live, read-only bead viewer
```

## CRITICAL: You Operate tbd, the User Doesn’t

**You are the tbd operator:** Users talk naturally; you translate their requests to tbd
actions. DO NOT tell users to run tbd commands.
That’s your job.

- **WRONG**: “Run `tbd create` to track this bug”

- **RIGHT**: *(you run `tbd create` yourself and tell the user it’s tracked)*

**Live browser requests:** When the user asks to see, show, open, or view beads in a
browser, start `tbd web --open` yourself with the agent platform’s long-running process
facility. Do not merely print the command.
If the requested project is outside your current working directory, start
`tbd web <path> --open`; the path may be its repository root or any subdirectory.
Wait for the startup descriptor, give the user its loopback URL, and leave the process
running until they ask you to stop it or the session environment requires cleanup.

The page is a live, read-only viewer, not an editor.
You remain the tbd operator: make every requested bead change with ordinary `tbd`
commands, and the running page observes the resulting local state automatically.
Browser filters change only the presentation.
Starting the viewer never justifies an implicit fetch, merge, or push; run `tbd sync`
only when the user asks to exchange remote bead state, after which its local result also
appears automatically.

**Welcoming a user:** When users ask “what is tbd?”
or want help → run `tbd shortcut welcome-user`

## User Request → Agent Action

| User Says | You (the Agent) Run |
| --- | --- |
| **Issues/Beads** |  |
| “There’s a bug where …” | `tbd create "..." --type=bug` |
| “Create a task/feature for …” | `tbd create "..." --type=task` or `--type=feature` |
| “Let’s work on issues/beads” | `tbd ready` |
| “Show my beads in a browser” | Start `tbd web --open` yourself, wait for its URL, and keep it running |
| “Show me issue X” (or several) | `tbd show <id1> [<id2> …]` (one call, never a loop; `--max-lines <n>` caps output per issue) |
| “Where do things stand on spec X?” | `tbd list --spec <path-or-filename>` (all specs at once: `tbd list --specs`) |
| “Close this issue” | `tbd close <id>` (several: `tbd close <id1> <id2> …` — one call, never a loop) |
| “Search issues for X” | `tbd search "X"` (matches content and issue IDs, so partial IDs work) |
| “Add label X to issue” | `tbd label add <id> <label>` (several beads: `tbd update <id1> <id2> … --add-label <label>`) |
| “What issues are stale?” | `tbd stale` |
| **Planning & Specs** |  |
| “Plan a new feature” / “Create a spec” | `tbd shortcut new-plan-spec` |
| “Break spec into beads” | `tbd shortcut plan-implementation-with-beads` |
| “Implement these beads” | `tbd shortcut implement-beads` |
| **Code Review & Commits** |  |
| “Review this code” / “Code review” | `tbd shortcut review-code` |
| “Review this PR” | `tbd shortcut review-github-pr` |
| “Commit this” / “Use the commit shortcut” | `tbd shortcut code-review-and-commit` |
| “Create a PR” / “File a PR” | `tbd shortcut create-or-update-pr-simple` |
| “Merge main into my branch” | `tbd shortcut merge-upstream` |
| **Guidelines & Knowledge** |  |
| *(any engineering work)* | Load the **General engineering** group first (see below) |
| “Use TypeScript best practices” | `tbd guidelines typescript-rules typescript-lint-format-rules` |
| “Use Python best practices” | `tbd guidelines python-rules` |
| “Use Rust best practices” | `tbd guidelines rust-rules rust-lint-format-rules` |
| “Set up TS/JS lint, format, or hooks” | `tbd guidelines typescript-lint-format-rules` |
| “Set up Rust lint, clippy, or the quality floor” | `tbd guidelines rust-lint-format-rules` |
| “Build a Rust CLI” | `tbd guidelines rust-cli-rules` |
| “Build a TypeScript CLI” | `tbd guidelines typescript-cli-tool-rules` |
| “Improve monorepo setup” | `tbd guidelines pnpm-monorepo-patterns` or `bun-monorepo-patterns` |
| “Add golden/e2e testing” | `tbd guidelines golden-testing-guidelines` |
| “Use TDD” / “Test-driven development” | `tbd guidelines general-tdd-guidelines` |
| “Convex best practices” | `tbd guidelines convex-rules` |
| **Documentation** |  |
| “Research this topic” | `tbd shortcut new-research-brief` |
| “Document architecture” | `tbd shortcut new-architecture-doc` |
| “What guidelines/docs are there?” | `tbd docs list` |
| “Make the guidelines visible / customize doc X” | `tbd docs fork --category=general --category=<lang>` (recommended: general + the repo’s languages), or `tbd docs fork <name>` / `--all`; then edit in `docs/tbd/` |
| “Update the guidelines to the latest” | `tbd docs update`; on conflicts ask the user, then `--merge` or `--keep-ours` |
| “I deleted a forked doc file” | `tbd docs status` shows it `missing`; restore with `tbd docs fork <name> --force` or finalize with `tbd docs unfork <name>` |
| **External Trackers** |  |
| “Set up Linear” / “Connect this repo to Linear” | `tbd shortcut setup-linear` |
| “My Linear sync isn’t working” / “Add my Linear key” | `tbd shortcut setup-linear` |
| **Cleanup & Maintenance** |  |
| “Clean up this code” / “Remove dead code” | `tbd shortcut code-cleanup-all` |
| “Fix repository problems” | `tbd doctor --fix` |
| **Sessions & Handoffs** |  |
| “Hand off to another agent” | `tbd shortcut agent-handoff` |
| “Check out this library’s source” | `tbd shortcut checkout-third-party-repo` |
| *(your choice whenever appropriate)* | `tbd list`, `tbd dep add`, `tbd close`, `tbd sync`, etc. |

**Loading guidelines for engineering work:** three layers, in this order.

1. **Always**, before writing or reviewing code, load the engineering core:

   ```bash
   tbd guidelines general-eng-agent-principles
   ```

2. **The language documents** that match the changed surface.
   Do not load an entire language group by default.

3. **Cross-cutting topics, by what the change actually touches**—errors, tests and
   goldens, code and comment policy, dependencies, published interfaces, commits,
   review, CI and gates, filesystem work, and releases.
   These are not always-load: read the group’s note in `tbd guidelines --list` and pull
   the ones that apply.

Load several selected documents in **one call**; `guidelines`, `shortcut`, `template`,
and `docs show` all take several names.

Run `tbd guidelines --list` to see all available guidelines.

**Where beads live:** on the dedicated `tbd-sync` branch, not your working branch.
Bead changes never appear in your feature branch’s commits or its PR diff.
That is the design, not lost work: don’t hunt for them there, and don’t claim
“everything is on this PR” about bead state.

**Let tbd own that branch.** `tbd sync` maintains it and `tbd doctor --fix` repairs it.
Use tbd commands rather than raw git for anything touching `tbd-sync`; hand checkouts,
merges, and pushes are how bead state gets tangled.

**Note:** `.tbd/workspaces/` is the exception: never gitignore it; the outbox must be
committed to your working branch.
See `tbd guidelines tbd-sync-troubleshooting` for details.

## CRITICAL: Session Closing Protocol

**Before saying “done”, you MUST complete this checklist:**

```
[ ] 1. git add + git commit
[ ] 2. git push
[ ] 3. gh pr checks <PR> --watch 2>&1 (IMPORTANT: WAIT for final summary, do NOT tell user it is done until you confirm it passes CI!)
[ ] 4. tbd close <id1> <id2> ... --reason "..." — one bulk call per group of beads sharing a reason (never a per-ID loop)
[ ] 5. tbd sync
[ ] 6. CONFIRM CI passed (if failed: fix, run tests, re-push, restart from step 3)
```

**Work is not done until pushed, CI passes, and tbd is synced.**

**Remote/proxied session where GitHub seems blocked?** If the environment has egress,
`gh` works through a scoped `NO_PROXY` bypass.
Three facts decide most of these:

- The git remote may sit behind a **ref-scoped credential broker**: pushes to
  `refs/heads/*` succeed, pushes to `refs/tags/*` fail with HTTP 403. Create the tag on
  the direct channel instead:
  `gh api repos/OWNER/REPO/git/refs -f ref=refs/tags/vX.Y.Z -f sha=SHA`.
- `git push --dry-run` **passes** for tags the broker then refuses at receive-pack, so a
  clean dry run proves nothing.
- A GitHub-host 403 carrying no `x-github-request-id` header is proxy-manufactured, not
  an organization egress denial.

Run `tbd shortcut setup-github-cli` and follow “Proxied Remote Sessions” before
concluding gh is unavailable.

## Bead Tracking Rules

- Track all task work not done immediately as beads (discovered work, TODOs,
  multi-session work)
- When in doubt, create a bead
- Check `tbd ready` when not given specific directions
- Always close/update beads and run `tbd sync` at session end

## Commands

### Finding Work

| Command | Purpose |
| --- | --- |
| `tbd ready` | Beads ready to work (open; no delegate, hold, future deferral, or non-closed blocker) |
| `tbd list --status open` | All open beads |
| `tbd list --status in_progress` | All in-progress work |
| `tbd list --spec <path>` | Beads tracking a spec (filename or suffix is enough) |
| `tbd list --sort updated --limit 10` | Recent activity; `--count` for totals |
| `tbd show <id1> [<id2> …]` | Bead details with dependencies (bulk: delimited per issue; `--max-lines <n>` caps each) |

### Creating & Updating

| Command | Purpose |
| --- | --- |
| `tbd create "title" --type=bug --priority=1` | New bead; run `tbd create --help` for all types and priorities (P0-P4, not “high/medium/low”) |
| `tbd create "title" --parent <epic> --depends-on <id>` | Create fully wired: parent and blockers in one call (`--depends-on` is repeatable) |
| `tbd start <id>` | Claim work |
| `tbd close <id> [--reason "..."]` | Mark complete |
| `tbd close <id1> <id2> <id3> --reason "..."` | Close several at once (always preferred over one-at-a-time) |
| `tbd update <id1> <id2> <id3> --priority 1` | Bulk-update shared fields on several beads |

Use `tbd start`, not a raw status update, to claim work.
It records the acting agent in `delegate`. On an already in-progress bead, it reports a
different visible delegate instead of overwriting that claim.
It does not require readiness or coordinate with a stale clone.
Before editing, run `tbd sync --pull`, re-read the bead, use `tbd start <id>`, and run
`tbd sync` so other replicas can see the accepted claim.
`assignee` remains the accountable person.
The acting name resolves from `start --as`, then `TBD_AGENT`, then the machine-local
session identity, and finally a derived `<harness>@<host>` fallback.
Use `tbd whoami` to inspect it; setup hooks call `tbd whoami --ensure-id` idempotently
to persist a local ID and friendly name.

**IMPORTANT: if you are about to shell-loop or pipe around tbd, stop; the bulk or filter
form exists.** `show`, `close`, `reopen`, and `update` take multiple IDs;
`guidelines`/`shortcut`/`template`/`docs show` take multiple names; `dep add` takes
multiple blockers; list/search/show have `--limit`/`--count`/`--max-lines`. NEVER
`for id in …; do tbd close $id; done` (one call gives one lock, one summary, `--json`,
and `--ignore-missing`), NEVER `tbd show X | head` (use `--max-lines`), NEVER
`tbd list | grep <id>` (use `tbd search <partial-id>`). A bulk call shares one reason
(and, for `update`, one set of field changes), so group the beads that share the same
mutation and make one call per group.

### Dependencies & Sync

| Command | Purpose |
| --- | --- |
| `tbd dep add <bead> <blocker1> [<blocker2> …]` | Add blocker dependencies (one call per bead) |
| `tbd blocked` | Show blocked beads |
| `tbd sync` | Sync with git remote (run at session end) |
| `tbd stats` | Project statistics |
| `tbd doctor` | Check for problems |
| `tbd doctor --fix` | Auto-fix repository problems |

### Labels & Search

| Command | Purpose |
| --- | --- |
| `tbd search <query>` | Search issues by text or (partial) issue ID |
| `tbd label add <id> <label>` | Add label to issue (several beads: `tbd update <ids…> --add-label`) |
| `tbd label remove <id> <label>` | Remove label from issue |
| `tbd label list` | List all labels in use |
| `tbd stale` | List issues not updated recently |

### External Trackers (Linear)

| Command | Purpose |
| --- | --- |
| `tbd integration status --offline` | Distinguish shared config from a missing personal key without a network call |
| `tbd integration status` | Verify the configured key and Linear team are reachable |
| `tbd --dry-run integration sync --push` | Preview which beads would go outward |
| `tbd integration sync --push` | Outbound only: create/update tracker issues (idempotent) |
| `tbd integration sync --pull` | Inbound only: tracker changes into beads, no external writes |
| `tbd integration sync --pull --external <ref...>` | Create beads from exactly named tracker items, independent of policy |
| `tbd integration sync` | Both directions; converges to `nothing to do` |
| `tbd integration link/unlink <bead> [ref]` | Bind or sever a bead and an existing tracker item; unlink safely cancels pending writes for that pair before clearing the link |
| `tbd integration comment <bead> "text"` | Author a provider comment offline; attempted on next `tbd integration sync` |

**Setting Linear up at all — including “add my key” — is `tbd shortcut setup-linear`.**
Run it rather than improvising; it detects which case applies and walks the user through
only that case.

The mental model it encodes: **config is shared, credentials are personal.** The
`integrations` block in `.tbd/config.yml` (team, project, policy) is committed, so a
teammate who clones already has it; `LINEAR_API_KEY` lives in the environment or a
**gitignored** `.env` and is never committed.
So a user joining a repo whose team already syncs needs *only* a key—never a config
edit, and never `integration sync --push` (their links arrived with the clone; after a
dry-run preview, plain `tbd sync` first pulls the team’s current bead state and then
reconciles Linear). Run `tbd integration status --offline` first in every case.
Full details: the External Tracker Integrations section of `tbd docs`. Bulk runs over 20
creates / 40 updates refuse without `--yes`. Never echo credentials into output or
commits.
`--pull` never replays or performs provider writes; deferred claims and conflict
notices remain journaled until the next full sync.
Link/inbound creation refuse a remote `tbd://bead/…` claim unless `--force` is explicit
and the old claim was verified stale.
Configured `project` scopes both creates and automatic inbound scans; an explicit
`--external` import bypasses that scan scope.
`identity.user_map` is an explicit assignee alias override.
Outbound handles can also reuse a stable bridge binding or resolve by one exact Linear
directory match; ambiguous and missing matches are skipped.
Inbound provider identities still need the map before they become bead aliases.
Emails and raw provider payloads never persist.
`identity.agent_map` maps only installed Linear app agents that may receive a bead
delegate; unmapped session delegates stay local and are reported as skipped.
`identity.state_map` selects state names for `backlog`, `unstarted`, `started`,
`completed`, `canceled`, and `duplicate`. Interactive `tbd integration setup` records
ambiguous choices; non-interactive and dry-run setup leave them unresolved, and
`tbd doctor` reports only the offline plan without persisting it.
Linear sub-issues import parent-first and never flatten; `max_nesting` limits only new
outbound creation. Comments are append-only and paginated; edits, deletions, reactions,
and thread shape are not synchronized.
Linear descriptions carry a tbd-owned `⟦tbd⟧` … `⟦/tbd⟧` region.
Human prose outside it is preserved; legacy HTML-comment delimiters are upgraded on the
next outbound sync. Never hand-edit the managed region—change the bead and sync instead.

Within `tbd integration sync`, bare = both directions, `--push` = outbound only, and
`--pull` = inbound only.
Top-level `tbd sync --push`/`--pull` operates on the issue Git surface and excludes
trackers unless `--integrations` is also explicit.
Plain `tbd sync` at session end covers docs, issues, and trackers according to
`integrations.on_tbd_sync`; surfaces run independently, so one failing (an expired key,
a down remote) never stops the others, and every failure is reported at the end.
Narrow with `--docs`, `--issues`, or `--integrations` for a single surface.
`tbd sync --status` reports docs and issue Git status only; use `tbd integration status`
for tracker health.

### Documentation

| Command | Purpose |
| --- | --- |
| `tbd shortcut <name>` | Run a shortcut |
| `tbd shortcut --list` | List shortcuts |
| `tbd guidelines <name> [<name> …]` | Load coding guidelines (several names in one call) |
| `tbd guidelines --list` | List guidelines |
| `tbd template <name>` | Output a template |
| `tbd docs` / `tbd docs list` | Managed-docs overview / cross-kind list with state markers |
| `tbd docs fork/unfork/update <name>` | Fork docs into `docs/tbd/`, return to upstream, pull upstream updates |

## Quick Reference

- **Priority**: P0=critical, P1=high, P2=medium (default), P3=low, P4=backlog
- **Types**: issues default to `task`; run `tbd create --help` for the valid types
- **Status**: open, in_progress, blocked, deferred, closed
- **JSON output**: Data-oriented commands honor `--json`; raw document commands such as
  `readme`, `prime`, `skill`, and `closing` remain text
