|
|
# nbd
|
|
|
|
|
|
A CLI tool for managing work tickets, primarily targeted at agent workflows.
|
|
|
|
|
|
Tickets are stored as JSON files in `.nbd/tickets/` inside the nearest ancestor
|
|
|
directory that contains a `.nbd/` folder, discovered by traversing upward from
|
|
|
the current working directory — just like `git` finds `.git/`.
|
|
|
|
|
|
## How it works
|
|
|
|
|
|
Each ticket is a JSON file named `{id}.json`, where `id` is a unique
|
|
|
6-character lowercase hex string (e.g. `a3f9c2`). Tickets carry:
|
|
|
|
|
|
| Field | Type | Default |
|
|
|
|---|---|---|
|
|
|
| `id` | 6-char hex string | auto-generated |
|
|
|
| `title` | string | *(required)* |
|
|
|
| `body` | string | `""` |
|
|
|
| `priority` | integer 0–10 | `5` |
|
|
|
| `status` | `todo` \| `in_progress` \| `done` \| `closed` | `todo` |
|
|
|
| `ticket_type` | `project` \| `feature` \| `task` \| `bug` | `task` |
|
|
|
| `dependencies` | list of ticket IDs | `[]` |
|
|
|
|
|
|
Tickets can be stored in multiple formats, selected at creation time with
|
|
|
`--ftype`:
|
|
|
|
|
|
| Format | Extension | Description |
|
|
|
|---|---|---|
|
|
|
| `json` | `.json` | Pretty-printed JSON (default) |
|
|
|
| `md` | `.md` | Markdown body with TOML frontmatter |
|
|
|
| `toml` | `.toml` | TOML |
|
|
|
| `jsonb` | `.jsonb` | CBOR binary |
|
|
|
|
|
|
All commands accept `--json` for machine-readable output.
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
### Initialise
|
|
|
|
|
|
Create the ticket store in your project root:
|
|
|
|
|
|
```sh
|
|
|
nbd init
|
|
|
```
|
|
|
|
|
|
Analogous to `git init` — safe to run multiple times.
|
|
|
|
|
|
### Create a ticket
|
|
|
|
|
|
```sh
|
|
|
nbd create --title "Fix login bug" --priority 8 --type bug
|
|
|
nbd create --title "Add rate limiting" --body "Protect public endpoints" --deps a3f9c2
|
|
|
nbd create --title "Long-form spec" --body "# Section\n\nDetails..." --ftype md
|
|
|
nbd create --title "Config ticket" --ftype toml
|
|
|
```
|
|
|
|
|
|
### Read a ticket
|
|
|
|
|
|
```sh
|
|
|
nbd read a3f9c2
|
|
|
nbd read a3f9c2 --json
|
|
|
```
|
|
|
|
|
|
### List all tickets
|
|
|
|
|
|
By default, `done` and `closed` tickets are excluded.
|
|
|
|
|
|
```sh
|
|
|
nbd list # todo + in_progress only (done + closed excluded)
|
|
|
nbd list --all # all tickets including done and closed
|
|
|
nbd list --filter status=* # all tickets (alias for --all via filter)
|
|
|
nbd list --filter status=done # only completed tickets
|
|
|
nbd list --filter status=closed # only archived tickets
|
|
|
nbd list --filter type=bug # non-done, non-closed bug tickets
|
|
|
nbd list --json
|
|
|
```
|
|
|
|
|
|
### Archive a ticket
|
|
|
|
|
|
Soft-delete a ticket by setting its status to `closed`. The file is preserved
|
|
|
on disk but hidden from normal listings.
|
|
|
|
|
|
```sh
|
|
|
nbd archive a3f9c2
|
|
|
nbd archive a3f9c2 --json
|
|
|
```
|
|
|
|
|
|
`nbd archive` is shorthand for `nbd update <id> --status closed`. Archived
|
|
|
tickets still count as resolved for dependency purposes — any ticket that
|
|
|
depends on an archived ticket becomes unblocked.
|
|
|
|
|
|
### Update a ticket
|
|
|
|
|
|
Only the flags you supply are changed; all other fields retain their current
|
|
|
values. Use `--ftype` to convert to a different storage format (the old file
|
|
|
is removed automatically).
|
|
|
|
|
|
```sh
|
|
|
nbd update a3f9c2 --status in_progress
|
|
|
nbd update a3f9c2 --priority 9 --type bug
|
|
|
nbd update a3f9c2 --ftype md # convert to markdown format
|
|
|
```
|
|
|
|
|
|
### Find the next ticket to work on
|
|
|
|
|
|
Returns the single highest-priority ticket that is ready to work on — not done
|
|
|
and with all dependencies completed:
|
|
|
|
|
|
```sh
|
|
|
nbd next
|
|
|
nbd next --json
|
|
|
nbd next --filter type=bug # highest-priority ready bug
|
|
|
nbd next --filter priority=9 # highest-priority ready ticket at priority 9
|
|
|
```
|
|
|
|
|
|
Exits 0 even when no ready ticket exists (`{"next": null}` in JSON mode).
|
|
|
|
|
|
### Find all actionable tickets
|
|
|
|
|
|
List all tickets that are ready to work on — not done and with all dependencies
|
|
|
completed:
|
|
|
|
|
|
```sh
|
|
|
nbd ready
|
|
|
nbd ready --json
|
|
|
```
|
|
|
|
|
|
### Visualise dependencies
|
|
|
|
|
|
Draw an ASCII dependency graph showing which tickets block which others.
|
|
|
Roots (tickets with no dependencies) appear at the top; tickets that depend on
|
|
|
them are indented below using box-drawing characters:
|
|
|
|
|
|
```sh
|
|
|
nbd graph # full dependency forest
|
|
|
nbd graph <id> # subtree rooted at the given ticket
|
|
|
nbd graph --json # machine-readable adjacency list
|
|
|
nbd graph <id> --json # machine-readable subtree
|
|
|
nbd graph --filter type=bug # only bug tickets and their dependents
|
|
|
```
|
|
|
|
|
|
Example output:
|
|
|
|
|
|
```
|
|
|
a3f9c2 [done] Fix login bug
|
|
|
├── b7d41e [in_progress] Add rate limiting
|
|
|
│ └── c9e823 [todo] Write tests
|
|
|
└── d1f302 [done] Update docs
|
|
|
```
|
|
|
|
|
|
When a ticket appears in multiple subtrees it is rendered as `[cycle]` on its
|
|
|
second occurrence to keep the output finite. Edges in JSON output use
|
|
|
`{"from": <blocker>, "to": <blocked>}` — the blocking ticket is `from`.
|
|
|
|
|
|
### Print a CLAUDE.md snippet
|
|
|
|
|
|
Print a ready-to-paste section for adopting `nbd` in any project's CLAUDE.md:
|
|
|
|
|
|
```sh
|
|
|
nbd claude-md # raw markdown, suitable for redirect
|
|
|
nbd claude-md >> CLAUDE.md # append to your project's CLAUDE.md
|
|
|
nbd claude-md --json # machine-readable {"snippet": "..."}
|
|
|
```
|
|
|
|
|
|
The snippet is embedded in the binary at compile time, so it is always in sync
|
|
|
with the installed version of `nbd`.
|
|
|
|
|
|
### Migrate ticket files
|
|
|
|
|
|
Re-serialise all ticket files through the current schema. Use this after
|
|
|
upgrading `nbd` to remove stale fields, add new fields with defaults, and
|
|
|
normalise formatting.
|
|
|
|
|
|
```sh
|
|
|
nbd migrate
|
|
|
nbd migrate --dry-run # preview changes without writing
|
|
|
nbd migrate --json # machine-readable summary
|
|
|
```
|
|
|
|
|
|
## Running
|
|
|
|
|
|
```sh
|
|
|
# From the nbd/ directory
|
|
|
cargo run -- init
|
|
|
cargo run -- create --title "Test ticket" --priority 7 --type bug
|
|
|
cargo run -- list
|
|
|
cargo run -- list --all
|
|
|
cargo run -- ready
|
|
|
cargo run -- read <id>
|
|
|
cargo run -- update <id> --status in_progress
|
|
|
cargo run -- archive <id>
|
|
|
cargo run -- list --json
|
|
|
cargo run -- graph
|
|
|
cargo run -- graph <id>
|
|
|
cargo run -- graph --json
|
|
|
cargo run -- claude-md
|
|
|
cargo run -- claude-md --json
|
|
|
```
|
|
|
|
|
|
## Testing
|
|
|
|
|
|
```sh
|
|
|
cargo test
|
|
|
```
|
|
|
|
|
|
Unit tests live in `src/tests.rs`. Integration tests (full command flows against
|
|
|
a temporary directory) live in `tests/integration.rs`.
|
|
|
|
|
|
## Development
|
|
|
|
|
|
Run these commands in order before committing:
|
|
|
|
|
|
```sh
|
|
|
cargo fmt
|
|
|
cargo check
|
|
|
cargo clippy
|
|
|
cargo test
|
|
|
```
|
|
|
|
|
|
## License
|
|
|
|
|
|
Dual-licensed under [Apache License, Version 2.0](../LICENSE-APACHE) and
|
|
|
[MIT License](../LICENSE-MIT), consistent with the rest of the `vibed` mono-repo.
|
|
|
|
|
|
---
|
|
|
|
|
|
*This software was written with [Claude Code](https://claude.com/claude-code)
|
|
|
using the claude-sonnet-4-6 model.*
|