Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 36 additions & 29 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bmo"
version = "0.5.0"
version = "0.6.0"
edition = "2024"
rust-version = "1.91.0"
description = "Local-first SQLite-backed CLI issue tracker for AI agents"
Expand Down Expand Up @@ -29,17 +29,17 @@ path = "examples/demo.rs"
ammonia = { version = "4" }
anyhow = { version = "1.0.102" }
async-stream = { version = "0.3" }
axum = { version = "0.8.8" }
axum = { version = "0.8.9" }
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.6.0", features = ["derive", "env"] }
clap = { version = "4.6.1", features = ["derive", "env"] }
comfy-table = { version = "7" }
futures-util = { version = "0.3", default-features = false }
minijinja = { version = "2" }
pulldown-cmark = { version = "0.13", default-features = false, features = ["html"] }
minijinja = { version = "2.19.0" }
pulldown-cmark = { version = "0.13.3", default-features = false, features = ["html"] }
owo-colors = { version = "4" }
rusqlite = { version = "0.38.0", features = ["bundled", "fallible_uint"] }
sea-query = { version = "1.0.0-rc.1" }
sea-query-rusqlite = { version = "0.8.0-rc.16", features = [
sea-query = { version = "1.0.0-rc.33" }
sea-query-rusqlite = { version = "0.8.0-rc.17", features = [
"with-chrono",
"with-json",
"with-uuid",
Expand All @@ -48,11 +48,11 @@ sea-query-rusqlite = { version = "0.8.0-rc.16", features = [
serde = { version = "1.0.228", features = ["derive"] }
serde_json = { version = "1.0.149" }
thiserror = { version = "2.0.18" }
toml = { version = "0.9.8" }
toml = { version = "1.1.2+spec-1.1.0" }
tokio = { version = "1.50.0", features = ["rt-multi-thread", "macros", "net", "signal", "sync", "time"] }

[dev-dependencies]
assert_cmd = { version = "2.2.0" }
assert_cmd = { version = "2.2.1" }
http = { version = "1" }
predicates = { version = "3" }
tempfile = { version = "3.27.0" }
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ Download the latest binary for your platform from [GitHub Releases](https://gith

```bash
bmo init
bmo issue create --title "First issue" --priority medium --kind task
bmo issue list
bmo create --title "First issue" --priority medium --kind task
bmo list
bmo board
bmo web
```
Expand Down
48 changes: 24 additions & 24 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,57 +68,57 @@ bmo plan --phase 2 --json | jq '.data[].title'

```bash
bmo next --json
bmo issue show BMO-7 --json
bmo issue comment list BMO-7 # always check comments — they may supersede the description
bmo issue file list BMO-7 # check attached files before starting
bmo show BMO-7 --json
bmo comment list BMO-7 # always check comments — they may supersede the description
bmo file list BMO-7 # check attached files before starting
```

## Creating Issues

Use `-d` to provide a rich description so any agent or human reading the issue later has full context:

```bash
bmo issue create -t "Implement retry logic" \
bmo create -t "Implement retry logic" \
-d "Add exponential backoff to the HTTP client. Max 3 retries. See src/client.rs." \
-p high -T task
-p high -k task
```

Attach all files the issue affects immediately after creation:

```bash
bmo issue file add BMO-7 src/client.rs
bmo issue file add BMO-7 src/client_test.rs
bmo file add BMO-7 src/client.rs
bmo file add BMO-7 src/client_test.rs
```

## Tracking Progress

Use `bmo issue claim` to atomically take ownership of an issue. It sets the status to
Use `bmo claim` to atomically take ownership of an issue. It sets the status to
`in-progress` and optionally records an assignee in a single operation. If another agent
has already claimed the ticket, it returns a conflict error (exit code 4) rather than
overwriting — making it safe for concurrent multi-agent workflows.

```bash
bmo issue claim BMO-7 # atomic: sets in-progress, fails if already claimed
bmo issue claim BMO-7 --assignee alice --json
bmo claim BMO-7 # atomic: sets in-progress, fails if already claimed
bmo claim BMO-7 --assignee alice --json
```

`bmo issue claim` replaces the older two-step `move + edit` pattern. The old pattern still
`bmo claim` replaces the older two-step `move + edit` pattern. The old pattern still
works but `claim` is preferred when multiple agents may be picking up work simultaneously.

If the claim response includes a `"file_conflicts"` key, another in-progress issue shares
the same file attachments. Check for conflicts before beginning implementation:

```bash
bmo issue claim BMO-7 --json | jq '.file_conflicts'
bmo issue file conflicts BMO-7 --json # also callable independently
bmo claim BMO-7 --json | jq '.file_conflicts'
bmo file conflicts BMO-7 --json # also callable independently
```

Once work is complete, close the issue:

```bash
bmo issue move BMO-7 --status done
bmo move BMO-7 --status done
# or equivalently:
bmo issue close BMO-7
bmo close BMO-7
```

## Adding Context via Comments
Expand All @@ -139,16 +139,16 @@ so other agents can scan comments efficiently:
| `HANDOFF:` | any | Work complete, context for the next agent |

```bash
bmo issue comment add BMO-7 --body "FINDING: the HTTP client also needs connection timeout handling. Needs a follow-up issue."
bmo issue comment add BMO-7 --body "DECISION: used exponential backoff with jitter rather than fixed intervals."
bmo issue comment add BMO-7 --body "HANDOFF: retry logic complete. Tests in src/client_test.rs. Next agent should add integration test."
bmo comment add BMO-7 --body "FINDING: the HTTP client also needs connection timeout handling. Needs a follow-up issue."
bmo comment add BMO-7 --body "DECISION: used exponential backoff with jitter rather than fixed intervals."
bmo comment add BMO-7 --body "HANDOFF: retry logic complete. Tests in src/client_test.rs. Next agent should add integration test."
```

Scan comments by tag before starting work:

```bash
bmo issue comment list BMO-7 --json | jq '.data[] | select(.body | startswith("HANDOFF:")) | .body'
bmo issue comment list BMO-7 --json | jq '.data[] | select(.body | startswith("BLOCKER:")) | .body'
bmo comment list BMO-7 --json | jq '.data[] | select(.body | startswith("HANDOFF:")) | .body'
bmo comment list BMO-7 --json | jq '.data[] | select(.body | startswith("BLOCKER:")) | .body'
```

Comments are the canonical record of what happened. Always read them before starting work.
Expand All @@ -158,9 +158,9 @@ Comments are the canonical record of what happened. Always read them before star
Record which files are relevant to an issue for traceability and to enable collision detection between concurrent agents:

```bash
bmo issue file add BMO-7 src/client.rs
bmo issue file list BMO-7
bmo issue file conflicts BMO-7 --json # check for overlaps with other in-progress work
bmo file add BMO-7 src/client.rs
bmo file list BMO-7
bmo file conflicts BMO-7 --json # check for overlaps with other in-progress work
```

## Reading JSON Output
Expand All @@ -171,7 +171,7 @@ to Python if `jq` is unavailable.
```bash
# Preferred: jq
bmo next --json | jq '.data[] | {id: .id, title: .title}'
bmo issue show BMO-7 --json | jq '.data.issue.status'
bmo show BMO-7 --json | jq '.data.issue.status'
bmo board --json | jq '.data.in_progress[].id'
bmo plan --phase 1 --json | jq '.data[].id'

Expand Down
Loading
Loading