skills/report-tusk-issue/SKILL.md
File a GitHub issue against the tusk repo itself — tusk bugs, CLI limitations, skill improvements, or missing features. Use anytime the user identifies a gap in tusk (not in their own project's code).
npx skillsauth add gioe/tusk report-tusk-issueInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
File a well-formed GitHub issue against the tusk repo itself without leaving the workflow. Use this whenever the user (or you) notice a tusk bug, CLI limitation, skill rough-edge, or missing feature mid-session — i.e. a gap in tusk, not in the user's own project.
Don't use this skill for issues against the consumer project's code — those go through whatever issue tracker that project uses. This skill is hard-wired to file against the tusk distribution's repo (
gioe/tusk).
This skill complements /retro's LR-2 routing — retro still files tusk-issues at end-of-task. This skill is the fast path for noticing a gap outside a retro, or during a long task where waiting for retro would lose fidelity.
Invoked with an optional one-liner (e.g. /report-tusk-issue tusk lint rule 14 trips on multi-line skip-lint comments) or no argument.
Prompt the user for the standard tusk report-issue fields. Pre-fill from any one-liner argument, but always confirm before drafting:
<one-liner> (yes / edit)tusk report-issue will inline the placeholder comment, which is fine for tusk-team triage.cluster:<name> label currently present on the repo is accepted; the CLI does not validate against a closed list, so new clusters added to GitHub work immediately. Run gh label list --repo gioe/tusk --search "cluster:" to see the current set. Default to triage-needed only when no specific cluster fits.Don't pad missing fields with filler. An empty Steps/Expected section is more honest than invented content; tusk maintainers can ask follow-ups on the issue if needed.
Best-effort — try to associate the report with the work that surfaced it so the upstream issue links back to local context:
TASK_ID=$(tusk branch-parse 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin).get("task_id") or "")' 2>/dev/null)
If $TASK_ID is non-empty:
TASK_SUMMARY=$(tusk task-get "$TASK_ID" 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin).get("summary",""))' 2>/dev/null)
If either step fails (not on a tusk feature branch, or the task is unknown), set both to empty and proceed without a task back-link. Do not prompt the user — most mid-session tusk-issue reports surface during a task, but it's not a hard requirement.
The footer is what lets tusk maintainers distinguish AI-assisted reports from human-authored ones in triage. Read it from config, falling back to the standard default if the key is unset (older installs predate the key):
FOOTER=$(tusk config report_tusk_issue_footer 2>/dev/null)
if [[ -z "$FOOTER" ]]; then
FOOTER="_Filed via /report-tusk-issue from a Claude Code session._"
fi
Users who want to override the footer (e.g. to identify their AIQ environment) can set report_tusk_issue_footer in tusk/config.json. The default is intentionally generic.
Build the final body. The skill submits via tusk report-issue, which already wraps the user's inputs in the standard template (## Tusk version / ## Project context / ## Behavior observed / ## Steps to reproduce / ## Expected behavior) and applies the instance-feedback label. The skill's job is to (a) collect the inputs cleanly and (b) append the attribution footer + originating-task link.
Build a draft preview that mirrors what tusk report-issue will actually post — show the user the assembled body, not just the raw inputs. The footer goes after the template body so maintainers see context first:
=== Draft GitHub issue against gioe/tusk ===
Title: <title>
Cluster: <cluster>
Body:
## Tusk version
tusk version <integer from `tusk version`>
## Project context
<context or template placeholder>
## Behavior observed
<observed>
## Steps to reproduce
<steps or template placeholder>
## Expected behavior
<expected or template placeholder>
---
<FOOTER>
- Originating tusk task: TASK-<task_id> — <task summary> # only if Step 2 found one
Show the preview, then ask once (single prompt — do not re-prompt per-section):
Open this issue against
gioe/tusk? (yes / edit / cancel)
yes → proceed to Step 5.edit → loop back to Step 1, pre-filling current values so the user can adjust any field.cancel → stop. Do not call tusk report-issue or gh. Do not record progress.The submission has three tiers — each kicks in only if the previous tier fails. Never auto-retry the same tier: a failed gh issue create could have already partially filed the issue, so blindly retrying risks duplicates.
tusk report-issueThe primary path. tusk report-issue calls gh issue create --repo gioe/tusk --label instance-feedback --label cluster:<cluster> internally and exits with the issue URL on stdout:
if [[ -n "$EXPECTED" ]]; then
APPENDED_EXPECTED="$EXPECTED
---
$FOOTER"
else
APPENDED_EXPECTED="$FOOTER"
fi
if [[ -n "$TASK_ID" ]]; then
APPENDED_EXPECTED="$APPENDED_EXPECTED
- Originating tusk task: TASK-$TASK_ID — $TASK_SUMMARY"
fi
ISSUE_URL=$(tusk report-issue \
--title "$TITLE" \
--cluster "$CLUSTER" \
--context "$CONTEXT" \
--observed "$OBSERVED" \
--steps "$STEPS" \
--expected "$APPENDED_EXPECTED" 2>/tmp/tusk-report-issue.err)
RC=$?
The footer is appended to the --expected field rather than passed as a separate argument because tusk report-issue doesn't accept a --footer flag, and the body template renders ## Expected behavior last — appending here puts the footer at the bottom of the rendered issue, matching the draft preview shown in Step 4. (Appending to --observed would wedge the footer between the Behavior and Steps sections — visually wrong.) When the user supplied no expected behavior, the footer stands alone under the heading instead of below a blank-line gap.
If RC == 0 and $ISSUE_URL looks like a GitHub URL (https://github.com/.../issues/<N>), proceed to Step 6.
gh issue createIf Tier 1 failed (non-zero exit), inspect /tmp/tusk-report-issue.err. Common reasons tusk report-issue could fail while a direct gh call still succeeds: an unreleased CLI bug in the report-issue subcommand, a label mismatch, or a tusk-version probe failure. Try the direct call:
BODY=$(printf '## Project context\n%s\n\n## Behavior observed\n%s\n\n## Steps to reproduce\n%s\n\n## Expected behavior\n%s\n\n---\n\n%s%s' \
"${CONTEXT:-_(none provided)_}" \
"$OBSERVED" \
"${STEPS:-_(none provided)_}" \
"${EXPECTED:-_(none provided)_}" \
"$FOOTER" \
"${TASK_ID:+
- Originating tusk task: TASK-$TASK_ID — $TASK_SUMMARY}")
ISSUE_URL=$(printf '%s' "$BODY" | gh issue create \
--repo gioe/tusk \
--label instance-feedback \
--label cluster:$CLUSTER \
--title "$TITLE" \
--body-file - 2>/tmp/gh-issue-create.err)
RC=$?
The direct path drops the ## Tusk version section because that field is sourced inside tusk report-issue from $TUSK_VERSION — when we're bypassing that path due to a tusk-version probe failure, leaving the section out is more honest than fabricating it. Maintainers will infer from the instance-feedback label and the /report-tusk-issue footer that the report came from a tusk install.
If RC == 0, proceed to Step 6.
If both tiers failed, surface a copy-pasteable manual URL and the assembled body so the user can file by hand. Never silently swallow the failure:
Could not file the issue automatically. Both
tusk report-issueandgh issue createfailed.tusk report-issue stderr:
<contents of /tmp/tusk-report-issue.err>gh issue create stderr:<contents of /tmp/gh-issue-create.err>Please open https://github.com/gioe/tusk/issues/new and paste:
Title:
<title>Body:<assembled body>(Apply the
instance-feedbackandcluster:<cluster>labels.)
Then stop — do not record progress.
If Step 2 found $TASK_ID, log the URL as a progress checkpoint so it shows up in the local task history:
tusk progress "$TASK_ID" --note "Filed tusk-issue: $ISSUE_URL"
Use --note for the external issue URL so it stays out of next_steps, which is reserved for forward-looking handoff work.
If Step 2 found no task, skip this step.
Print the final summary verbatim:
Filed tusk-issue:
<ISSUE_URL>(linked on TASK-<task_id>).
Drop the (linked on …) suffix if no task was associated.
Do not invoke /tusk or /retro. Filing a tusk-issue is metadata, not task closure. The user resumes their original workflow when ready.
data-ai
Autonomously work through the backlog — dispatches /chain for chain heads, /tusk for standalone tasks, repeating until empty
tools
Investigate the scope of a problem and form an honest assessment — task creation is optional
data-ai
Groom the backlog by closing completed tickets, removing redundant/stale tickets, reprioritizing, and assigning agents
tools
Contribute a client-discovered fix or improvement back to the configured iOS library repo from an ios_app tusk project.