crewship issue
Issue tracking wired directly into agent dispatch. Use these commands to create and triage issues, manage labels, comments, relations, and sub-issues, and hand work to an assigned agent (start / stop / review). Issues can also be bound to a routine so a fixed workflow runs whenever the issue is started.
crewship issues
Subcommands
crewship issue list
List issues in the workspace with optional filters.
Output columns: ID, TITLE, STATUS, PRIORITY, ASSIGNEE, CREATOR, CREW, LABELS, UPDATED
A human table ends with
showing 1–50 of 1 015 · next page: --offset 50, read from the
X-Total-Count / X-Limit / X-Offset headers every paged list sends. Machine formats
stay flat — json / yaml a bare array, ndjson one issue object per line — since scripts
decode them directly (the one exception is --counts, above); quiet stays one id per line.
The response also carries X-Has-More (#2286) for clients that only read that boolean.
crewship issue get
Show issue details including comments.
BE-42) or the full ID.
Output fields: Identifier, Title, Status, Priority, Crew, Assignee, Assignee Type, Owner, Delegate, Description, Due Date, Mission Type, Labels, Comments count, Created By, Created, Updated, ID.
Owner and Delegate are the typed projection of the issue’s human owner and agent delegate (owner/delegate in the API — #2297, independent of each other and of the legacy Assignee/Assignee Type pair above). Each shows the resolved name, or - when nobody occupies that slot. In --format json / --format yaml, the same data is owner/delegate objects ({id, name}), omitted entirely when unset.
Comments are displayed below the detail section.
Who created an issue
Every issue records its creator. TheCreated By field (and the CREATOR
column in issue list) shows the resolved name, suffixed with (agent) when
the issue was created by an agent through a tool call rather than by a human:
--output json, the same information is available as the created_by
object ({type, id, name}, where type is user or agent) plus
authored_via (user_api or agent_tool_call).
crewship issue create
Create a new issue.
Owner and delegate are independent slots (#2297): assigning a person never
clears the agent already delegated, and delegating to an agent never
changes the owner. To clear both,
crewship issue update <id> --assignee "".
crewship issue update
Update an issue. Only changed flags are sent.
crewship issue delete
Delete an issue. Prompts for confirmation.
crewship issue comment
Add a comment to an issue.
--body flag (which takes precedence).
crewship issue labels
List all workspace labels.
crewship issue work
Take over an issue, hand it to a person or agent, or submit human work for
review. Requires workspace OWNER, ADMIN, or MANAGER access. The owner
stays accountable even when the current worker changes.
An exact retry returns the saved receipt. A changed request under the same ID
or a stale revision fails with a conflict. Human takeover fences new agent
work and requests cancellation of active runs. Handback and submission wait
until those runs have stopped. Handing back to an agent prepares a new step;
use
crewship issue start to execute it. submit moves human work to review.
crewship issue review-policy
Set whether a person has to accept the work before this issue counts as done.
Requires workspace OWNER, ADMIN, or MANAGER access.
The flag has no default on purpose: a bare call is refused rather than
guessing, because dropping acceptance removes a gate somebody set. The policy
can change only while the issue is
TODO or BACKLOG with no live
assignment — once work starts the server answers 409 instead of moving the
goalposts under the worker.
crewship issue result
Print one run’s result summary, outcome and status — what the worker reported
back, where crewship issue runs lists only that the
run happened.
id field of
crewship issue runs <identifier> -f json. It is not the RUN column of
that command’s table: that column is the journal trace id, and passing it
answers 404 Run not found for this issue. A run that
belongs to another issue answers 404 rather than reading across issues; a
run that reported nothing says so instead of printing an empty result.
crewship issue start
Start an issue — dispatches work to the assigned agent.
crewship issue stop
Stop an issue. Ships in two tiers, both fired by this one command:
- Tier 1 (cooperative, always applied). Marks pending/in-progress tasks
CANCELLEDand stampscancel_requested_aton every live assignment; a run that hasn’t started its exec yet never starts, and the runner polls the stamp at every step boundary. No further step is scheduled. - Tier 2 (hard, opt in with
--hard). After the Tier 1 stamp lands, ends each live run’s own tmux session (tmux kill-session -t agent-{slug}, run as a brand-new exec into the run’s same container), escalating to a directkill -KILLon that session’s own process group if it hasn’t exited after a short grace period. Most agent runs own a tmux session named for their own agent slug — a container-visible identity — so this never runs a container-level kill and never signals by OS pid: the crew’s container is shared by every agent on the crew, and a pid resolved from outside the container is not safe to signal from inside it (#2365 — the pre-fix mechanism did exactly that and silently signalled nothing). Only the run’s own session is ever touched; a sibling agent’s session keeps running untouched. A run whose exec bypassed tmux entirely (an oversized prompt delivered via stdin, or a container without tmux installed) has no session to end — confirmed first by listing its pane pids before touching anything, then reportedNOT_FOUNDimmediately rather than sending a signal that reaches nothing. Bounded to a few seconds; what was signalled and the result (TERMINATED_TERM,TERMINATED_KILL,ALREADY_EXITED,NOT_FOUND,PENDING_EXEC— the run wasRUNNINGbut its exec had not appeared within the wait window, so there was nothing to signal yet; Tier 1’s stamp still ends itCANCELLEDwhen it reports back —UNSUPPORTED,ERROR) is recorded on the run (also readable viacrewship issue runs -f json’shard_stop_result/hard_stop_at) and in the issue’s journal. Without--hard, a step already mid-exec simply finishes that exec and is then recordedCANCELLEDregardless of what it reports — nothing mid-exec is interrupted.
@mention dispatched on an issue that was never started (BACKLOG/TODO): the assignment gets the same cancel_requested_at stamp (and, with --hard, the same signal if it’s already RUNNING), and the issue’s own status is left unchanged. stop still refuses when the issue is not IN_PROGRESS/REVIEW and has no live run to reach.
crewship issue review
Review an issue — approve or request changes.
The review is a compare-and-set (#2448). The command always sends both
revisions, so a plain call is safe; the server answers
409 and leaves the
issue where it is when:
- the revision or brief revision no longer matches (The issue changed. Refresh before reviewing.);
- a run or a Lead review is still live on the issue (Work or Lead review is still running —
issue stopit or wait); - on
approve, a person submitted the work and the brief changed after that submission (Submit an updated result before approving); - on
approve, the latest agent execution ran against an older brief (Run the updated work before approving).
400 when the issue is not IN_PROGRESS/REVIEW. Full rules: API reference → Issues → Review Issue.
crewship issue comments
List comments on an issue. Hits GET /api/v1/crews/{crewId}/issues/{ident}/comments after resolving <identifier> to its crew via fetchIssue.
crewship issue activity
Dump the mission-activity timeline for an issue. Hits GET /api/v1/crews/{crewId}/issues/{ident}/activity. Server caps the result at 50 rows DESC — pipe through jq if you need older history.
type/name), ACTION, DETAILS (truncated to 60 chars).
crewship issue events
The same mission_activity rows as activity, but ordered by seq (the B1 event log’s monotonic per-issue cursor) instead of created_at, and NOT capped at 50 — this is the endpoint the board’s client-side gap detector calls to resync after a WebSocket frame is dropped under load (F43, work package B11, #2368). Hits GET /api/v1/crews/{crewId}/issues/{ident}/events?after_seq=. The server caps a single response at 500 rows; the CLI (like the client-side gap detector) follows after_seq pages automatically until it has everything up to the issue’s current latest_seq, so --format json’s events array is always the full requested range, never just the first page.
Output columns: SEQ, WHEN (relative time), ACTOR (
type/name), ACTION, DETAILS (truncated to 60 chars). In --format json, the response is {"events": [...], "after_seq": N, "latest_seq": N} — latest_seq is the issue’s current high-water mark, so a client with no new events can still tell “caught up at N” from “server has never heard of this issue”.
crewship issue runs
List every run attributed to an issue — mission tasks, mention-dispatched runs, and delegation-hop runs alike — the data the dashboard’s issue “Runs” tab shows. Hits GET /api/v1/crews/{crewId}/issues/{ident}/runs after resolving <identifier> to its crew via fetchIssue.
Output columns: RUN (the journal run id — what
crewship journal --run-id and the Activity page take; — when the assignment never reached a run), AGENT (slug), TASK (truncated to 28), STATUS, OUTCOME, STARTED (relative time), DURATION, SOURCE, RESULT (error message or result summary; ANSI-sanitised, truncated to 50 chars).
SOURCE is why the run is attributed to the issue: task (the issue’s own mission-task plan), mention (an @mention dispatch), or delegation (a sub-agent’s own further /assign call mid-mission). In --format json, the same run also carries mission_id (the issue’s mission ID; omitted on a legacy row that predates assignments.mission_id), run_id / trace_id, agent_id and agent_slug, and hard_stop_result / hard_stop_at (work package B7b, #2365) — what a Tier 2 issue stop --hard did to this run and when, omitted on a run that was never hard-stopped. Not shown as a table column; read it with --format json so a live check can confirm a hard stop actually landed without reading the journal.
OUTCOME is the §9.6 routing decision (work package B6, #2349) — NO_CHANGE, SUCCEEDED, WORK_CREATED, PARTIAL, NEEDS_HUMAN, FAILED, or CANCELLED; - on a run that predates the outcome column. It answers a different question than STATUS: a COMPLETED run that never reported a recognised outcome shows FAILED here, with its error naming "no outcome reported" — an absent outcome is treated as a bug, not a silent success. NEEDS_HUMAN is the one outcome that raises an inbox item (crewship inbox list --kind run_needs_human). Full vocabulary and routing table: API reference → Issues → Outcome.
crewship issue sessions
Session lifecycle:
issue_agent_sessions is work package B1 of the Issues & Routines architecture (docs/prd/PRD-ISSUES-AND-ROUTINES-2026.md). A mention resolves or creates a session — mentioning the same agent on the same issue twice reuses it rather than creating a second. As of B4 (#2348) the session’s state moves pending → active → idle/error with active_run_id set while a run is live; since B6 (#2358) a run that reports NEEDS_HUMAN parks the session in awaiting_input until the inbox item is answered. Only the idle → stale sweep is not wired yet — nothing writes stale. As of B5 (#2345), every session-bearing dispatch also reads the session back into the agent’s context — see crewship issue checkpoints below and Sessions, checkpoints and the context pack.GET /api/v1/crews/{crewId}/issues/{ident}/sessions after resolving <identifier> to its crew via fetchIssue.
last_consumed_seq), VERSION (agent_version, - when the agent has no config history), UPDATED (relative time).
crewship issue checkpoints
Work package B5 of the Issues & Routines architecture (
docs/prd/PRD-ISSUES-AND-ROUTINES-2026.md §9.5, #2345). A checkpoint is the done/plan/facts/blockers/next_step/confidence block a session-bearing run reports when it finishes; the next run on the same session is handed the latest one as part of its §11.1 context pack, so it does not repeat completed work.GET /api/v1/crews/{crewId}/issues/{ident}/sessions/{sessionId}/checkpoints after resolving <identifier> to its crew via fetchIssue and the session via GET .../sessions.
Output columns: RUN (the run that wrote it,
- if none), SEQ (seq_at_write), DONE (truncated to 40), NEXT STEP (truncated to 40), CONFIDENCE, PARSED (true/false — false means the run ended without a valid ---CHECKPOINT--- block), CREATED (relative time).
crewship issue changes
Show the base-branch git diff produced by the crew working an issue — the data the dashboard’s issue “Changes” tab renders. Hits GET /api/v1/crews/{crewId}/git-diff.
Without
--patch, prints a per-file summary table (STATUS, FILE, +, −). When the crew workspace has no git repo, prints No git repository in this crew's workspace — nothing to diff.; with no changes against the base branch, prints No changes against the base branch.
crewship issue subtasks
List sub-issues — children whose parent_issue_id equals this issue’s id. Mirrors the SubIssues panel on the issue-detail page.
Aliases: subissues, sub-issues.
crewship issue relate
Create a typed link between two issues. Wraps POST /api/v1/crews/{crewId}/issues/{ident}/relations.
crewship issue relations
List existing relations on an issue. Alias: relates.
crewship issue unrelate
Remove a relation by its relation ID (not the issue identifier). Hits DELETE /api/v1/relations/{id}.
crewship issue link
Attach a GitHub pull request or GitLab merge request to an issue. Wraps
POST /api/v1/crews/{crewId}/issues/{ident}/code-links.
/pull/ → GitHub,
/-/merge_requests/ → GitLab), so recognising a self-hosted instance of
either needs no provider-specific configuration. Crewship then fetches the
request through that provider’s API using a stored GITHUB / GITLAB
credential in the workspace.
Two things a self-hosted forge does still need: a credential labelled with its
host (below), and — if it lives on a private/intranet address — the operator
opt-in described in Git links.
Without the opt-in the fetch is refused with blocked-host.
For a self-hosted forge, set the credential’s account label to the forge’s
host so it is matched by host:
code): no-credential (412),
blocked-host (422 — the forge is on a private address; see
Git links), credential-rejected (502 — the token was
revoked), rate-limited (429), already-linked (409).
crewship issue links
List an issue’s pull-request links. Aliases: code-links, prs.
owner/repo#number), TITLE, BRANCH
(source → target), SYNCED. A link whose last refresh failed shows its state
as … (stale) — the data is the last one successfully fetched.
crewship issue relink
Re-read a link’s state from its provider. Alias: refresh-link. State is never
polled in the background; this is how you ask again.
crewship issue unlink
Remove a link by its link ID (the first column of issue links).
crewship issue attach
Attach a local file to an issue. Wraps
POST /api/v1/crews/{crewId}/issues/{ident}/attachments.
.txt
.log .md .csv .tsv .json .yaml .yml .toml .xml .diff
.patch .png .jpg .jpeg .gif .webp .avif .pdf .zip .gz
.tgz. Anything else is refused with a 415 that lists the set.
Maximum 25 MiB; a larger file is refused locally, naming its size, before
anything is uploaded. Attaching the same bytes twice is the same attachment, so
a retry is safe and does not add a second timeline entry.
The agent working the issue can read what you attach — see
Issue attachments.
crewship issue attachments
List an issue’s attached files. Alias: files.
(agent) when an agent
attached it), ADDED. Filenames are printed with control bytes stripped — they
are chosen by whoever uploaded the file.
crewship issue attachment
Download one attachment by its attachment ID (the first column of issue attachments). Alias: download.
Without
-o the bytes go to stdout, so the command composes with a pager or a
pipeline. The server’s stored filename is never used to choose a local
destination: it is a value someone else typed, and letting it name a path is how
a download writes somewhere you did not ask for.
crewship issue detach
Remove an attachment by its attachment ID. Alias: unattach.
crewship issue bind-routine
Bind a routine slug to an issue — the server stores the underlying routine_id (pipeline UUID) so subsequent routine renames don’t break the link. Wraps PATCH /api/v1/crews/{crewId}/issues/{ident} with {"routine_id": <id>}.
routine "xyz": <404> instead of a silent no-op.
crewship issue unbind-routine
Clear the routine binding (server normalises empty string to SQL NULL).
crewship issue bulk update
Apply the same field updates to up to 100 issues in a single round-trip. Wraps PATCH /api/v1/issues/bulk. The 100-id cap is enforced both client-side (friendly error) and server-side (400).
At least one of
--status / --priority / --assignee / --project / --labels must be supplied. Response surfaces as Bulk update applied to <updated>/<requested> issue(s). — the two counts differ when some IDs were 404 or 403.