Issue basics — the CRUD floor
Everyday issue operations over the Forge kernel. Every command here is a real
forge issue verb (confirm with forge issue --help). The kernel is the single
source of truth — never hand-edit the issue store.
Every --json reply is the same envelope: { ok, schema_version, command, data, next_commands } on success, or { ok:false, error:{ message, exit_code } } on
failure. Gate on ok — do not parse data until you confirm ok:true.
The core loop
| Need |
Command |
| Create an issue |
forge issue create --title "…" --type <task|bug|epic|decision> |
| Inspect one issue |
forge issue show <id> [--json] |
| List / filter issues |
forge issue list [--status … --type … --priority … --label …] [--json] |
| Full-text search |
forge issue search "…" [--json] |
| Backlog counts |
forge issue stats [--json] |
| Claim work (DB-enforced lease) |
forge issue claim <id> |
| Release a claim |
forge issue release <id> |
| Update fields |
forge issue update <id> [flags] |
| Add a handoff note |
forge issue comment <id> "…" |
| Close (one or many) |
forge issue close <id...> --reason "…" |
| Dependencies |
forge issue dep add|remove <id> <blocks-id> |
Create — the flags that matter
forge issue create --title "Add rate limiting" --type task \
--priority P1 --label "feature,api,security" --assignee alice \
--acceptance "429 returned after N req/min; covered by a test"
| Flag |
Meaning |
Default |
--title "…" |
Human title (a bare leading positional also works) |
minted id |
--type <…> |
task · bug · epic · decision |
task |
--priority <…> |
P0..P4 (or bare 0..4); P0 is highest |
unset |
--label "a,b" |
Comma-separated set — one flag, split on , (repeats do NOT accumulate) |
none |
--body "…" |
Long description (--description is an accepted alias) |
empty |
--assignee <who> |
Persistent assignee |
unset |
--acceptance "…" |
Acceptance criteria (--design, --notes also persist) |
unset |
--parent <id> |
Parent/epic id |
none |
--status defaults to open. Status vocabulary: open · in_progress ·
review · done · cancelled. Unlike --priority and --status (which reject
unknown values), --type is stored verbatim — a non-canonical value like
feature is accepted without error but carries no kernel behaviour, so stick to
the four canonical types. Epics and decisions are excluded from the ready queue
(non-claimability is a queue convention, not enforcement — forge issue claim
currently returns ok:true on them too).
Update — same field flags, plus close
forge issue update <id> takes --status, --title, --body/--description,
--priority, --label (reparents the whole set), --parent, --assignee,
--acceptance, --design, --notes. forge issue close <id> --reason "…"
records the reason on the close event and accepts multiple ids in one call.
Migrating from a Beads-style tracker — verb disposition
Nothing you relied on silently disappears; a few verbs map onto a forge flag or
are intentionally unsupported:
| Old verb |
Forge equivalent |
label (add/remove) |
No subcommand — pass the full set via --label "a,b" on create/update (last-value-wins). |
reopen |
forge issue update <id> --status open. |
delete |
Unsupported by design — the kernel is append-only/event-sourced. Use forge issue close <id> --reason "…" instead. |
Reliability
- Check
ok before trusting output. On ok:false, read error.message and
fix the input rather than retrying blindly.
- Claim before you mutate shared work.
forge issue claim <id> takes a
DB-enforced lease; hand off to the claim-safety procedure before acting on a
claimed issue you intend to change. forge issue release <id> if you abandon it.
- Record decisions as comments, not memory.
forge issue comment <id> "…"
survives the session; scratch notes do not.
Fork points
Editable conventions — set these once for your team and this skill enforces them.
It is a canonical source you fork, not a fixed policy.
| Knob |
Default |
How to change |
| Default type |
task (kernel default) |
Decide your create convention — e.g. always pass --label feature for user-facing work (feature is a label, not a canonical type), --type bug for regressions. |
| Default priority |
unset |
Adopt a house scale (e.g. new work opens at P2, incidents at P0) and always pass --priority. |
| Fields required on create |
--title only |
Require --acceptance (and --label/--assignee) on every create so issues are actionable from birth. |
| Id / reference convention |
kernel-minted ids |
Standardize how you cite issues in commits/PRs (e.g. Closes <id>) and whether you pass an explicit --id. |
| Label taxonomy |
free-form |
Pin an allowed label set your team agrees on and pass it consistently via --label "a,b". |
1---2name: issue-basics3description: Everyday single-issue CRUD over the `forge issue` verbs: create/update/show/list/search/close/reopen/comment, set priority/labels/assignee, claim or release one issue, add/remove dependency edges, plus backlog `stats`. Use for ANY routine one-off issue op: "create an issue/bug/task for X", "update/edit issue <id>", "close or reopen this issue", "comment a handoff note on <id>", "list/filter open bugs by status/label/priority", "bump this to P1", "reassign to alice", "mark <id> blocked by <id>". Also the parity floor migrating off a Beads-style tracker (label/reopen/delete map to forge equivalents). Single-operation plumbing only. Does NOT choose, rank, or explain the next issue to work on or why it's blocked (use triage-ready); does NOT run claim-then-prove-lease-ownership safety (use claim-safety); does NOT drive an issue through the plan->dev->validate->ship pipeline or open a PR (use smith or stage skills); does NOT report the current stage or what's in flight (use status).4---56# Issue basics — the CRUD floor78Everyday issue operations over the Forge kernel. Every command here is a real9`forge issue` verb (confirm with `forge issue --help`). The kernel is the single10source of truth — never hand-edit the issue store.1112Every `--json` reply is the same envelope: `{ ok, schema_version, command, data,13next_commands }` on success, or `{ ok:false, error:{ message, exit_code } }` on14failure. **Gate on `ok`** — do not parse `data` until you confirm `ok:true`.1516## The core loop1718| Need | Command |19|------|---------|20| Create an issue | `forge issue create --title "…" --type <task\|bug\|epic\|decision>` |21| Inspect one issue | `forge issue show <id> [--json]` |22| List / filter issues | `forge issue list [--status … --type … --priority … --label …] [--json]` |23| Full-text search | `forge issue search "…" [--json]` |24| Backlog counts | `forge issue stats [--json]` |25| Claim work (DB-enforced lease) | `forge issue claim <id>` |26| Release a claim | `forge issue release <id>` |27| Update fields | `forge issue update <id> [flags]` |28| Add a handoff note | `forge issue comment <id> "…"` |29| Close (one or many) | `forge issue close <id...> --reason "…"` |30| Dependencies | `forge issue dep add\|remove <id> <blocks-id>` |3132## Create — the flags that matter3334```bash35forge issue create --title "Add rate limiting" --type task \36 --priority P1 --label "feature,api,security" --assignee alice \37 --acceptance "429 returned after N req/min; covered by a test"38```3940| Flag | Meaning | Default |41|------|---------|---------|42| `--title "…"` | Human title (a bare leading positional also works) | minted id |43| `--type <…>` | `task` · `bug` · `epic` · `decision` | `task` |44| `--priority <…>` | `P0`..`P4` (or bare `0`..`4`); `P0` is highest | unset |45| `--label "a,b"` | Comma-separated set — one flag, split on `,` (repeats do NOT accumulate) | none |46| `--body "…"` | Long description (`--description` is an accepted alias) | empty |47| `--assignee <who>` | Persistent assignee | unset |48| `--acceptance "…"` | Acceptance criteria (`--design`, `--notes` also persist) | unset |49| `--parent <id>` | Parent/epic id | none |5051`--status` defaults to `open`. Status vocabulary: `open` · `in_progress` ·52`review` · `done` · `cancelled`. Unlike `--priority` and `--status` (which reject53unknown values), `--type` is stored verbatim — a non-canonical value like54`feature` is accepted without error but carries no kernel behaviour, so stick to55the four canonical types. Epics and decisions are excluded from the ready queue56(non-claimability is a queue convention, not enforcement — `forge issue claim`57currently returns `ok:true` on them too).5859## Update — same field flags, plus close6061`forge issue update <id>` takes `--status`, `--title`, `--body`/`--description`,62`--priority`, `--label` (reparents the whole set), `--parent`, `--assignee`,63`--acceptance`, `--design`, `--notes`. `forge issue close <id> --reason "…"`64records the reason on the close event and accepts multiple ids in one call.6566## Migrating from a Beads-style tracker — verb disposition6768Nothing you relied on silently disappears; a few verbs map onto a `forge` flag or69are intentionally unsupported:7071| Old verb | Forge equivalent |72|----------|------------------|73| `label` (add/remove) | **No subcommand** — pass the full set via `--label "a,b"` on `create`/`update` (last-value-wins). |74| `reopen` | `forge issue update <id> --status open`. |75| `delete` | **Unsupported by design** — the kernel is append-only/event-sourced. Use `forge issue close <id> --reason "…"` instead. |7677## Reliability7879- **Check `ok` before trusting output.** On `ok:false`, read `error.message` and80 fix the input rather than retrying blindly.81- **Claim before you mutate shared work.** `forge issue claim <id>` takes a82 DB-enforced lease; hand off to the `claim-safety` procedure before acting on a83 claimed issue you intend to change. `forge issue release <id>` if you abandon it.84- **Record decisions as comments, not memory.** `forge issue comment <id> "…"`85 survives the session; scratch notes do not.8687## Fork points8889Editable conventions — set these once for your team and this skill enforces them.90It is a canonical source you fork, not a fixed policy.9192| Knob | Default | How to change |93|------|---------|---------------|94| **Default type** | `task` (kernel default) | Decide your create convention — e.g. always pass `--label feature` for user-facing work (feature is a label, not a canonical type), `--type bug` for regressions. |95| **Default priority** | unset | Adopt a house scale (e.g. new work opens at `P2`, incidents at `P0`) and always pass `--priority`. |96| **Fields required on create** | `--title` only | Require `--acceptance` (and `--label`/`--assignee`) on every create so issues are actionable from birth. |97| **Id / reference convention** | kernel-minted ids | Standardize how you cite issues in commits/PRs (e.g. `Closes <id>`) and whether you pass an explicit `--id`. |98| **Label taxonomy** | free-form | Pin an allowed label set your team agrees on and pass it consistently via `--label "a,b"`. |