ship
Automates the shipping workflow by merging branches, running tests, and creating pull requests without user interaction.
Install this skill
Security score
The ship skill was audited on Jun 10, 2026 and we found 96 security issues across 3 threat categories. Review the findings below before installing.
Categories Tested
Security Issues
Template literal with variable interpolation in command context
| 35 | ```bash |
Template literal with variable interpolation in command context
| 285 | ```bash |
Template literal with variable interpolation in command context
| 420 | ```bash |
Template literal with variable interpolation in command context
| 454 | echo "before relying on \`gbrain search\` for code questions in this worktree." |
Template literal with variable interpolation in command context
| 582 | ```bash |
Access to hidden dotfiles in home directory
| 36 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
Access to hidden dotfiles in home directory
| 38 | mkdir -p ~/.gstack/sessions |
Access to hidden dotfiles in home directory
| 39 | touch ~/.gstack/sessions/"$PPID" |
Access to hidden dotfiles in home directory
| 40 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
Access to hidden dotfiles in home directory
| 41 | find ~/.gstack/sessions -mmin +120 -type f -exec rm {} + 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 42 | _PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo "true") |
Access to hidden dotfiles in home directory
| 43 | _PROACTIVE_PROMPTED=$([ -f ~/.gstack/.proactive-prompted ] && echo "yes" || echo "no") |
Access to hidden dotfiles in home directory
| 46 | _SKILL_PREFIX=$(~/.claude/skills/gstack/bin/gstack-config get skill_prefix 2>/dev/null || echo "false") |
Access to hidden dotfiles in home directory
| 50 | source <(~/.claude/skills/gstack/bin/gstack-repo-mode 2>/dev/null) || true |
Access to hidden dotfiles in home directory
| 53 | _SESSION_KIND=$(~/.claude/skills/gstack/bin/gstack-session-kind 2>/dev/null || echo "interactive") |
Access to hidden dotfiles in home directory
| 56 | _LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no") |
Access to hidden dotfiles in home directory
| 58 | _TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true) |
Access to hidden dotfiles in home directory
| 59 | _TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no") |
Access to hidden dotfiles in home directory
| 64 | _EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default") |
Access to hidden dotfiles in home directory
| 67 | _QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") |
Access to hidden dotfiles in home directory
| 69 | mkdir -p ~/.gstack/analytics |
Access to hidden dotfiles in home directory
| 71 | echo '{"skill":"ship","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(_repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null | tr -cd 'a-zA-Z0-9._-'); echo "${_repo:-unknown}") |
Access to hidden dotfiles in home directory
| 73 | for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do |
Access to hidden dotfiles in home directory
| 75 | if [ "$_TEL" != "off" ] && [ -x "~/.claude/skills/gstack/bin/gstack-telemetry-log" ]; then |
Access to hidden dotfiles in home directory
| 76 | ~/.claude/skills/gstack/bin/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 82 | eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 88 | ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 3 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 93 | ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ship","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & |
Access to hidden dotfiles in home directory
| 98 | _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") |
Access to hidden dotfiles in home directory
| 109 | _CHECKPOINT_MODE=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_mode 2>/dev/null || echo "explicit") |
Access to hidden dotfiles in home directory
| 110 | _CHECKPOINT_PUSH=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_push 2>/dev/null || echo "false") |
Access to hidden dotfiles in home directory
| 131 | In plan mode, allowed because they inform the plan: `$B`, `$D`, `codex exec`/`codex review`, writes to `~/.gstack/`, writes to the plan file, and `open` for generated artifacts. |
Access to hidden dotfiles in home directory
| 139 | If `SKILL_PREFIX` is `"true"`, suggest/invoke `/gstack-*` names. Disk paths stay `~/.claude/skills/gstack/[skill-name]/SKILL.md`. |
Access to hidden dotfiles in home directory
| 141 | If output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with |
Access to hidden dotfiles in home directory
| 146 | - Missing `~/.claude/skills/gstack/.feature-prompted-continuous-checkpoint`: AskUserQuestion for Continuous checkpoint auto-commits. If accepted, run `~/.claude/skills/gstack/bin/gstack-config set che |
Access to hidden dotfiles in home directory
| 147 | - Missing `~/.claude/skills/gstack/.feature-prompted-model-overlay`: inform "Model overlays are active. MODEL_OVERLAY shows the patch." Always touch marker. |
Access to hidden dotfiles in home directory
| 160 | If B: run `~/.claude/skills/gstack/bin/gstack-config set explain_level terse`. |
Access to hidden dotfiles in home directory
| 164 | rm -f ~/.gstack/.writing-style-prompt-pending |
Access to hidden dotfiles in home directory
| 165 | touch ~/.gstack/.writing-style-prompted |
Access to hidden dotfiles in home directory
| 174 | touch ~/.gstack/.completeness-intro-seen |
Access to hidden dotfiles in home directory
| 187 | If A: run `~/.claude/skills/gstack/bin/gstack-config set telemetry community` |
Access to hidden dotfiles in home directory
| 197 | If B→A: run `~/.claude/skills/gstack/bin/gstack-config set telemetry anonymous` |
Access to hidden dotfiles in home directory
| 198 | If B→B: run `~/.claude/skills/gstack/bin/gstack-config set telemetry off` |
Access to hidden dotfiles in home directory
| 202 | touch ~/.gstack/.telemetry-prompted |
Access to hidden dotfiles in home directory
| 215 | If A: run `~/.claude/skills/gstack/bin/gstack-config set proactive true` |
Access to hidden dotfiles in home directory
| 216 | If B: run `~/.claude/skills/gstack/bin/gstack-config set proactive false` |
Access to hidden dotfiles in home directory
| 220 | touch ~/.gstack/.proactive-prompted |
Access to hidden dotfiles in home directory
| 262 | If B: run `~/.claude/skills/gstack/bin/gstack-config set routing_declined true` and say they can re-enable with `gstack-config set routing_declined false`. |
Access to hidden dotfiles in home directory
| 266 | If `VENDORED_GSTACK` is `yes`, warn once via AskUserQuestion unless `~/.gstack/.vendoring-warned-$SLUG` exists: |
Access to hidden dotfiles in home directory
| 278 | 3. Run `~/.claude/skills/gstack/bin/gstack-team-init required` (or `optional`) |
Access to hidden dotfiles in home directory
| 280 | 5. Tell the user: "Done. Each developer now runs: `cd ~/.claude/skills/gstack && ./setup --team`" |
Access to hidden dotfiles in home directory
| 286 | eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 287 | touch ~/.gstack/.vendoring-warned-${SLUG:-unknown} |
Access to hidden dotfiles in home directory
| 429 | _BRAIN_SYNC_BIN="~/.claude/skills/gstack/bin/gstack-brain-sync" |
Access to hidden dotfiles in home directory
| 430 | _BRAIN_CONFIG_BIN="~/.claude/skills/gstack/bin/gstack-config" |
Access to hidden dotfiles in home directory
| 534 | If A/B and `~/.gstack/.git` is missing, ask whether to run `gstack-artifacts-init`. Do not block the skill. |
Access to hidden dotfiles in home directory
| 539 | "~/.claude/skills/gstack/bin/gstack-brain-sync" --discover-new 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 540 | "~/.claude/skills/gstack/bin/gstack-brain-sync" --once 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 583 | eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" |
Access to hidden dotfiles in home directory
| 600 | ~/.claude/skills/gstack/bin/gstack-decision-search --recent 5 2>/dev/null |
Access to hidden dotfiles in home directory
| 609 | **Cross-session decisions.** If `ACTIVE DECISIONS` are listed, treat them as prior settled calls with their rationale — do not silently re-litigate them; if you're about to reverse one, say so explici |
Access to hidden dotfiles in home directory
| 622 | Curated jargon list lives at `~/.claude/skills/gstack/scripts/jargon-list.json` (80+ terms). On the first jargon term you encounter this session, Read that file once; treat the `terms` array as the ca |
Access to hidden dotfiles in home directory
| 668 | Before each AskUserQuestion, choose `question_id` from `scripts/question-registry.ts` or `{skill}-{slug}`, then run `~/.claude/skills/gstack/bin/gstack-question-preference --check "<id>"`. `AUTO_DECID |
Access to hidden dotfiles in home directory
| 676 | ~/.claude/skills/gstack/bin/gstack-question-log '{"skill":"ship","question_id":"<id>","question_summary":"<short>","category":"<approval|clarification|routing|cherry-pick|feedback-loop>","door_type":" |
Access to hidden dotfiles in home directory
| 685 | ~/.claude/skills/gstack/bin/gstack-question-preference --write '{"question_id":"<id>","preference":"<pref>","source":"inline-user","free_text":"<optional original words>"}' |
Access to hidden dotfiles in home directory
| 700 | Before building anything unfamiliar, **search first.** See `~/.claude/skills/gstack/ETHOS.md`. |
Access to hidden dotfiles in home directory
| 705 | jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg skill "SKILL_NAME" --arg branch "$(git branch --show-current 2>/dev/null)" --arg insight "ONE_LINE_SUMMARY" '{ts:$ts,skill:$skill,branch:$branch,i |
Access to hidden dotfiles in home directory
| 723 | ~/.claude/skills/gstack/bin/gstack-learnings-log '{"skill":"SKILL_NAME","type":"operational","key":"SHORT_KEY","insight":"DESCRIPTION","confidence":N,"source":"observed"}' |
Access to hidden dotfiles in home directory
| 733 | `~/.gstack/analytics/`, matching preamble analytics writes. |
Access to hidden dotfiles in home directory
| 740 | rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 742 | ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"SKILL_NAME","event":"completed","branch":"'$(git branch --show-current 2>/dev/null || echo unknown)'","outcome":"OUTCOME","duration_s":"'"$_T |
Access to hidden dotfiles in home directory
| 745 | echo '{"skill":"SKILL_NAME","duration_s":"'"$_TEL_DUR"'","outcome":"OUTCOME","browse":"USED_BROWSE","session":"'"$_SESSION_ID"'","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' >> ~/.gstack/analytics/skill- |
Access to hidden dotfiles in home directory
| 748 | if [ "$_TEL" != "off" ] && [ -x ~/.claude/skills/gstack/bin/gstack-telemetry-log ]; then |
Access to hidden dotfiles in home directory
| 749 | ~/.claude/skills/gstack/bin/gstack-telemetry-log \ |
Access to hidden dotfiles in home directory
| 874 | ~/.claude/skills/gstack/bin/gstack-review-read |
Access to hidden dotfiles in home directory
| 928 | For Design Review: run `source <(~/.claude/skills/gstack/bin/gstack-diff-scope <base> 2>/dev/null)`. If `SCOPE_FRONTEND=true` and no design review (plan-design-review or design-review-lite) exists in |
Access to hidden dotfiles in home directory
| 976 | > **STOP.** Before running the test suites and (if prompt files changed) the eval suites (Steps 4-6), Read `~/.claude/skills/gstack/ship/sections/tests.md` and execute it |
Access to hidden dotfiles in home directory
| 979 | > **STOP.** Before auditing test coverage of the diff (Step 7), Read `~/.claude/skills/gstack/ship/sections/test-coverage.md` and execute it |
Access to hidden dotfiles in home directory
| 982 | > **STOP.** Before auditing plan completion, verification, and scope drift (Step 8), Read `~/.claude/skills/gstack/ship/sections/plan-completion.md` and execute it |
Access to hidden dotfiles in home directory
| 985 | > **STOP.** Before the pre-landing review and specialist dispatch (Step 9), Read `~/.claude/skills/gstack/ship/sections/review-army.md` and execute it |
Access to hidden dotfiles in home directory
| 988 | > **STOP.** Before addressing Greptile review comments when a PR exists (Step 10), Read `~/.claude/skills/gstack/ship/sections/greptile.md` and execute it |
Access to hidden dotfiles in home directory
| 991 | > **STOP.** Before the adversarial review and learnings capture (Step 11), Read `~/.claude/skills/gstack/ship/sections/adversarial.md` and execute it |
Access to hidden dotfiles in home directory
| 1002 | bun run ~/.claude/skills/gstack/bin/gstack-version-bump classify --base <base> |
Access to hidden dotfiles in home directory
| 1017 | QUEUE_JSON=$(bun run ~/.claude/skills/gstack/bin/gstack-next-version --base <base> --bump "$BUMP_LEVEL" --current-version "$BASE_VERSION" 2>/dev/null || echo '{"offline":true}') |
Access to hidden dotfiles in home directory
| 1024 | bun run ~/.claude/skills/gstack/bin/gstack-version-bump write --version "$NEW_VERSION" |
Access to hidden dotfiles in home directory
| 1030 | ~/.claude/skills/gstack/bin/gstack-decision-log '{"decision":"Ship NEW_VERSION (BUMP_LEVEL)","rationale":"WHY","scope":"repo","source":"skill","confidence":9}' 2>/dev/null || true |
Access to hidden dotfiles in home directory
| 1034 | > **STOP.** Before writing the CHANGELOG entry (Step 13), Read `~/.claude/skills/gstack/ship/sections/changelog.md` and execute it |
Access to hidden dotfiles in home directory
| 1241 | **PR/MR title invariant (always applies — do not skip even if you don't open the section below):** Any PR or MR you create OR update in the next step MUST have a title that starts with `v$NEW_VERSION` |
Access to hidden dotfiles in home directory
| 1243 | > **STOP.** Before syncing docs and creating or updating the PR/MR (Steps 18-19), Read `~/.claude/skills/gstack/ship/sections/pr-body.md` and execute it |
Access to hidden dotfiles in home directory
| 1251 | eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" && mkdir -p ~/.gstack/projects/$SLUG |
Access to hidden dotfiles in home directory
| 1254 | Append to `~/.gstack/projects/$SLUG/$BRANCH-reviews.jsonl`: |
Access to hidden dotfiles in home directory
| 1257 | echo '{"skill":"ship","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","coverage_pct":COVERAGE_PCT,"plan_items_total":PLAN_TOTAL,"plan_items_done":PLAN_DONE,"verification_result":"VERIFY_RESULT","vers |
Access to hidden dotfiles in home directory
| 1279 | _QT=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") |
Access to hidden dotfiles in home directory
| 1291 | `rm ~/.gstack/.plan-tune-nudge-shown` before next ship. |
External URL reference
| 170 | If `LAKE_INTRO` is `no`: say "gstack follows the **Boil the Ocean** principle — do the complete thing when AI makes marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean" Off |
External URL reference
| 173 | open https://garryslist.org/posts/boil-the-ocean |