sklp issue — CLI reference
Issues are the actionable unit devs care about. `sklp issue` is the CLI that lets you stay in the terminal — from triage to status change to GitHub mirror — instead of switching to the web UI for every small move.
For AI coding agents (Claude Code, Codex, Cursor)
This page is the source of truth for the
sklp issueverb. Every subcommand here maps 1:1 to a handler incmd/sklp/issue.go. Flags listed below are the only flags accepted — anything else fails withflag provided but not defined.Hard rules: every subcommand needs a project (either
--project, orSKLP_PROJECTin the environment, exceptissue list --stack). Authentication is mandatory (sklp auth login). Valid--typevalues:bug,feature,task,other. Valid--statusvalues:backlog,in_progress,done,wontfix.
Why this verb exists
Devs manage issues from the terminal: grep, sed, gh, and now sklp issue. Switching to a browser to retitle a bug, change a status, or open a GitHub mirror is friction. sklp issue exposes the project's issue context — including the bridge from collected feedback to actionable work — as a flat set of subcommands optimised for shell scripting and AI agents.
It replaces the prior sklp feedback verb. Feedback management (collect, triage, tag) belongs to the web UI where reviewers can see patterns at a glance; the CLI focuses on the unit you actually act on — the issue.
Authentication
Run sklp auth login once. The active profile's token is reused by every subcommand; pass --profile <name> to switch.
Subcommands
sklp issue list
List issues in a project or across a stack.
sklp issue list [--project ID | --stack ID] [--status S] [--type T] [--limit N] [--json | --plain] [--profile P]
--project ID— project id. Falls back toSKLP_PROJECT.--stack ID— stack id, alternative to--project. Adds aPROJECTcolumn.--status S— server-side filter:backlog,in_progress,done,wontfix.--type T— client-side filter:bug,feature,task,other.--limit N— cap the number of rows (0= no cap).--json— raw JSON from the API.--plain— TSV, one row per issue, no header. Pipe-friendly.
Example:
SKLP_PROJECT=proj_abc sklp issue list --status in_progress --type bug
sklp issue new
Create an issue. Optional file attachments are sent as multipart/form-data.
sklp issue new "<title>" [--body MD] [--type T] [--status S] [--attach FILE]... [--project ID] [--json] [--profile P]
- positional
<title>— required, non-empty. --body— markdown body.--type/--status— see valid values above.--attach FILE— repeatable; each occurrence adds one file.
Example:
sklp issue new "panic on startup" --type bug \
--body "stack trace in worker init, see attached log" \
--attach ./crash.log
sklp issue show
Print a single issue (key/value block + body).
sklp issue show <id> [--project ID] [--json] [--profile P]
Example:
sklp issue show iss_8f3a --json | jq '.status'
sklp issue edit
Patch title, body, or type. Only flags that are explicitly passed reach the API — omitting a flag means "keep the current value". Passing --body "" clears the body.
sklp issue edit <id> [--title T] [--body MD] [--type T] [--project ID] [--json] [--profile P]
You must pass at least one of --title, --body, --type.
Example:
sklp issue edit iss_8f3a --type feature --title "Allow custom backoff"
sklp issue status
Move an issue through its workflow.
sklp issue status <id> <status> [--reason TEXT] [--project ID] [--json] [--profile P]
- positional
<status>—backlog,in_progress,done, orwontfix. --reason—closed_reason, used when the new status closes the issue.
Example:
sklp issue status iss_8f3a wontfix --reason "duplicate of iss_71c2"
sklp issue promote
Promote a feedback into an issue. This is the bridge between the two bounded contexts: the feedback (collected via web UI / SDKs) becomes a tracked work item that the CLI can manage end-to-end.
sklp issue promote <feedback-id> [--title T] [--body MD] [--type T] [--status S] [--project ID] [--json] [--profile P]
Each override flag, when set, replaces the corresponding field carried over from the feedback. Defaults: title and body come from the feedback record.
Example:
sklp issue promote fb_4d11 --type bug --status backlog
sklp issue gh-link
Open a GitHub mirror issue for an existing Skalpel issue and persist the link (tracker_provider, tracker_external_id, tracker_url).
sklp issue gh-link <id> [--title T] [--body MD] [--project ID] [--json] [--profile P]
--title/--body— override the mirrored issue's content; defaults to the Skalpel issue's own fields.
Example:
sklp issue gh-link iss_8f3a
sklp issue gh-close
Close the linked GitHub issue. Only the GitHub mirror state changes — the local Skalpel status is untouched (use sklp issue status for that).
sklp issue gh-close <id> [--project ID] [--json] [--profile P]
sklp issue gh-reopen
Reopen the linked GitHub issue. Mirror state only, same semantics as gh-close.
sklp issue gh-reopen <id> [--project ID] [--json] [--profile P]
sklp issue gh-unlink
Drop the GitHub tracker link from the Skalpel issue. The GitHub issue itself is not touched.
sklp issue gh-unlink <id> [--project ID] [--profile P]
Common flags
These flags exist (with the same meaning) across most subcommands:
| Flag | Description |
|---|---|
--project ID | Project id. Falls back to SKLP_PROJECT. Required for everything except issue list --stack. |
--profile P | Named profile from the sklp config; defaults to the active one. |
--json | Emit the raw JSON returned by the API. Mutually exclusive with --plain. |
--plain | (list only) TSV output, no header. Designed for pipes — awk, cut, jq -R. |
Feedback vs issue
| Feedback | Issue | |
|---|---|---|
| Primary surface | Web UI | CLI (sklp issue) |
| Purpose | Collect + triage signal from users / agents | Act on a tracked unit of work |
| Lifecycle | Many in, most discarded or merged | Few in, each one finished |
| GitHub mirror | No | Yes (gh-link / gh-close / gh-reopen / gh-unlink) |
The bridge is sklp issue promote <feedback-id>: pick the signal that matters, materialise it as an issue, then drive it from the CLI.
Exit codes and errors
2— unknown subcommand or missing required positional argument.- non-zero with
token rejected (run sklp auth login)— the active profile's token is invalid or expired. - non-zero with
api <status>: <body>— the API rejected the request; body is truncated to 200 characters.