Files
Garry Tan db9447c333 v1.26.3.0 feat: /sync-gbrain skill + native code-surface orchestrator (#1314)
* feat: native gbrain code-surface orchestrator + ensureSourceRegistered helper

Replaces gbrain import (markdown only) with gbrain sources add + sync
--strategy code (or reindex-code on --full). Adds lib/gbrain-sources.ts
exporting ensureSourceRegistered/probeSource/sourcePageCount, plus lock
file + tmp-rename atomicity + dry-run write skip in the orchestrator.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: setup-gbrain Step 8 writes ## GBrain Search Guidance after smoke test

Extends Step 8 to write a machine-agnostic guidance block that teaches
the agent when to prefer gbrain CLI (search/query/code-def/code-refs/
code-callers/code-callees) over Grep. Gated on smoke test pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: /sync-gbrain skill — keep gbrain current and refresh agent guidance

New top-level skill that wraps gstack-gbrain-sync with state probing,
capability check (write+search round-trip, not gbrain doctor), CLAUDE.md
guidance lifecycle (write iff healthy, remove iff broken), and a
per-source verdict block. Re-runnable, idempotent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: preamble emits gbrain-availability block when capability ok

Extends generate-brain-sync-block.ts to emit Variant A (steady-state, 4
lines) when cwd page_count > 0 or Variant B (empty-corpus emergency, 3
lines) when 0; empty string otherwise. Reads cached page_count from
.gbrain-sync-state.json (handles pretty + compact JSON). Refreshes ship
golden fixtures and bumps the plan-review preamble byte budget to 35K
to absorb the new block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: register /sync-gbrain in AGENTS.md and docs/skills.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: regenerate SKILL.md across all hosts (gen:skill-docs)

Mechanical regeneration after preamble + setup-gbrain template + new
sync-gbrain skill. Run via: bun run gen:skill-docs --host all.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v1.26.3.0)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: add /sync-gbrain to README skills table and gbrain section

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 09:29:48 -07:00

24 KiB

name, preamble-tier, version, description, triggers, allowed-tools
name preamble-tier version description triggers allowed-tools
setup-browser-cookies 1 1.0.0 Import cookies from your real Chromium browser into the headless browse session. Opens an interactive picker UI where you select which cookie domains to import. Use before QA testing authenticated pages. Use when asked to "import cookies", "login to the site", or "authenticate the browser". (gstack)
import browser cookies
login to test site
setup authenticated session
Bash
Read
AskUserQuestion

Preamble (run first)

_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)
[ -n "$_UPD" ] && echo "$_UPD" || true
mkdir -p ~/.gstack/sessions
touch ~/.gstack/sessions/"$PPID"
_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')
find ~/.gstack/sessions -mmin +120 -type f -exec rm {} + 2>/dev/null || true
_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo "true")
_PROACTIVE_PROMPTED=$([ -f ~/.gstack/.proactive-prompted ] && echo "yes" || echo "no")
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "BRANCH: $_BRANCH"
_SKILL_PREFIX=$(~/.claude/skills/gstack/bin/gstack-config get skill_prefix 2>/dev/null || echo "false")
echo "PROACTIVE: $_PROACTIVE"
echo "PROACTIVE_PROMPTED: $_PROACTIVE_PROMPTED"
echo "SKILL_PREFIX: $_SKILL_PREFIX"
source <(~/.claude/skills/gstack/bin/gstack-repo-mode 2>/dev/null) || true
REPO_MODE=${REPO_MODE:-unknown}
echo "REPO_MODE: $REPO_MODE"
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
echo "LAKE_INTRO: $_LAKE_SEEN"
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
_TEL_START=$(date +%s)
_SESSION_ID="$$-$(date +%s)"
echo "TELEMETRY: ${_TEL:-off}"
echo "TEL_PROMPTED: $_TEL_PROMPTED"
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL"
_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false")
echo "QUESTION_TUNING: $_QUESTION_TUNING"
mkdir -p ~/.gstack/analytics
if [ "$_TEL" != "off" ]; then
echo '{"skill":"setup-browser-cookies","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
fi
for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do
  if [ -f "$_PF" ]; then
    if [ "$_TEL" != "off" ] && [ -x "~/.claude/skills/gstack/bin/gstack-telemetry-log" ]; then
      ~/.claude/skills/gstack/bin/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true
    fi
    rm -f "$_PF" 2>/dev/null || true
  fi
  break
done
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" 2>/dev/null || true
_LEARN_FILE="${GSTACK_HOME:-$HOME/.gstack}/projects/${SLUG:-unknown}/learnings.jsonl"
if [ -f "$_LEARN_FILE" ]; then
  _LEARN_COUNT=$(wc -l < "$_LEARN_FILE" 2>/dev/null | tr -d ' ')
  echo "LEARNINGS: $_LEARN_COUNT entries loaded"
  if [ "$_LEARN_COUNT" -gt 5 ] 2>/dev/null; then
    ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 3 2>/dev/null || true
  fi
else
  echo "LEARNINGS: 0"
fi
~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"setup-browser-cookies","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null &
_HAS_ROUTING="no"
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
  _HAS_ROUTING="yes"
fi
_ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false")
echo "HAS_ROUTING: $_HAS_ROUTING"
echo "ROUTING_DECLINED: $_ROUTING_DECLINED"
_VENDORED="no"
if [ -d ".claude/skills/gstack" ] && [ ! -L ".claude/skills/gstack" ]; then
  if [ -f ".claude/skills/gstack/VERSION" ] || [ -d ".claude/skills/gstack/.git" ]; then
    _VENDORED="yes"
  fi
fi
echo "VENDORED_GSTACK: $_VENDORED"
echo "MODEL_OVERLAY: claude"
_CHECKPOINT_MODE=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_mode 2>/dev/null || echo "explicit")
_CHECKPOINT_PUSH=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_push 2>/dev/null || echo "false")
echo "CHECKPOINT_MODE: $_CHECKPOINT_MODE"
echo "CHECKPOINT_PUSH: $_CHECKPOINT_PUSH"
[ -n "$OPENCLAW_SESSION" ] && echo "SPAWNED_SESSION: true" || true

Plan Mode Safe Operations

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.

Skill Invocation During Plan Mode

If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. Treat the skill file as executable instructions, not reference. Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — mcp__*__AskUserQuestion or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, fall back to writing the decision brief into the plan file as a ## Decisions to confirm section + ExitPlanMode — never silently auto-decide. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode.

If PROACTIVE is "false", do not auto-invoke or proactively suggest skills. If a skill seems useful, ask: "I think /skillname might help here — want me to run it?"

If SKILL_PREFIX is "true", suggest/invoke /gstack-* names. Disk paths stay ~/.claude/skills/gstack/[skill-name]/SKILL.md.

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 4 options, write snooze state if declined).

If output shows JUST_UPGRADED <from> <to>: print "Running gstack v{to} (just updated!)". If SPAWNED_SESSION is true, skip feature discovery.

Feature discovery, max one prompt per session:

  • Missing ~/.claude/skills/gstack/.feature-prompted-continuous-checkpoint: AskUserQuestion for Continuous checkpoint auto-commits. If accepted, run ~/.claude/skills/gstack/bin/gstack-config set checkpoint_mode continuous. Always touch marker.
  • Missing ~/.claude/skills/gstack/.feature-prompted-model-overlay: inform "Model overlays are active. MODEL_OVERLAY shows the patch." Always touch marker.

After upgrade prompts, continue workflow.

If WRITING_STYLE_PENDING is yes: ask once about writing style:

v1 prompts are simpler: first-use jargon glosses, outcome-framed questions, shorter prose. Keep default or restore terse?

Options:

  • A) Keep the new default (recommended — good writing helps everyone)
  • B) Restore V0 prose — set explain_level: terse

If A: leave explain_level unset (defaults to default). If B: run ~/.claude/skills/gstack/bin/gstack-config set explain_level terse.

Always run (regardless of choice):

rm -f ~/.gstack/.writing-style-prompt-pending
touch ~/.gstack/.writing-style-prompted

Skip if WRITING_STYLE_PENDING is no.

If LAKE_INTRO is no: say "gstack follows the Boil the Lake principle — do the complete thing when AI makes marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean" Offer to open:

open https://garryslist.org/posts/boil-the-ocean
touch ~/.gstack/.completeness-intro-seen

Only run open if yes. Always run touch.

If TEL_PROMPTED is no AND LAKE_INTRO is yes: ask telemetry once via AskUserQuestion:

Help gstack get better. Share usage data only: skill, duration, crashes, stable device ID. No code, file paths, or repo names.

Options:

  • A) Help gstack get better! (recommended)
  • B) No thanks

If A: run ~/.claude/skills/gstack/bin/gstack-config set telemetry community

If B: ask follow-up:

Anonymous mode sends only aggregate usage, no unique ID.

Options:

  • A) Sure, anonymous is fine
  • B) No thanks, fully off

If B→A: run ~/.claude/skills/gstack/bin/gstack-config set telemetry anonymous If B→B: run ~/.claude/skills/gstack/bin/gstack-config set telemetry off

Always run:

touch ~/.gstack/.telemetry-prompted

Skip if TEL_PROMPTED is yes.

If PROACTIVE_PROMPTED is no AND TEL_PROMPTED is yes: ask once:

Let gstack proactively suggest skills, like /qa for "does this work?" or /investigate for bugs?

Options:

  • A) Keep it on (recommended)
  • B) Turn it off — I'll type /commands myself

If A: run ~/.claude/skills/gstack/bin/gstack-config set proactive true If B: run ~/.claude/skills/gstack/bin/gstack-config set proactive false

Always run:

touch ~/.gstack/.proactive-prompted

Skip if PROACTIVE_PROMPTED is yes.

If HAS_ROUTING is no AND ROUTING_DECLINED is false AND PROACTIVE_PROMPTED is yes: Check if a CLAUDE.md file exists in the project root. If it does not exist, create it.

Use AskUserQuestion:

gstack works best when your project's CLAUDE.md includes skill routing rules.

Options:

  • A) Add routing rules to CLAUDE.md (recommended)
  • B) No thanks, I'll invoke skills manually

If A: Append this section to the end of CLAUDE.md:


## Skill routing

When the user's request matches an available skill, invoke it via the Skill tool. When in doubt, invoke the skill.

Key routing rules:
- Product ideas/brainstorming → invoke /office-hours
- Strategy/scope → invoke /plan-ceo-review
- Architecture → invoke /plan-eng-review
- Design system/plan review → invoke /design-consultation or /plan-design-review
- Full review pipeline → invoke /autoplan
- Bugs/errors → invoke /investigate
- QA/testing site behavior → invoke /qa or /qa-only
- Code review/diff check → invoke /review
- Visual polish → invoke /design-review
- Ship/deploy/PR → invoke /ship or /land-and-deploy
- Save progress → invoke /context-save
- Resume context → invoke /context-restore

Then commit the change: git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"

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.

This only happens once per project. Skip if HAS_ROUTING is yes or ROUTING_DECLINED is true.

If VENDORED_GSTACK is yes, warn once via AskUserQuestion unless ~/.gstack/.vendoring-warned-$SLUG exists:

This project has gstack vendored in .claude/skills/gstack/. Vendoring is deprecated. Migrate to team mode?

Options:

  • A) Yes, migrate to team mode now
  • B) No, I'll handle it myself

If A:

  1. Run git rm -r .claude/skills/gstack/
  2. Run echo '.claude/skills/gstack/' >> .gitignore
  3. Run ~/.claude/skills/gstack/bin/gstack-team-init required (or optional)
  4. Run git add .claude/ .gitignore CLAUDE.md && git commit -m "chore: migrate gstack from vendored to team mode"
  5. Tell the user: "Done. Each developer now runs: cd ~/.claude/skills/gstack && ./setup --team"

If B: say "OK, you're on your own to keep the vendored copy up to date."

Always run (regardless of choice):

eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" 2>/dev/null || true
touch ~/.gstack/.vendoring-warned-${SLUG:-unknown}

If marker exists, skip.

If SPAWNED_SESSION is "true", you are running inside a session spawned by an AI orchestrator (e.g., OpenClaw). In spawned sessions:

  • Do NOT use AskUserQuestion for interactive prompts. Auto-choose the recommended option.
  • Do NOT run upgrade checks, telemetry prompts, routing injection, or lake intro.
  • Focus on completing the task and reporting results via prose output.
  • End with a completion report: what shipped, decisions made, anything uncertain.

GBrain Sync (skill start)

_GSTACK_HOME="${GSTACK_HOME:-$HOME/.gstack}"
_BRAIN_REMOTE_FILE="$HOME/.gstack-brain-remote.txt"
_BRAIN_SYNC_BIN="~/.claude/skills/gstack/bin/gstack-brain-sync"
_BRAIN_CONFIG_BIN="~/.claude/skills/gstack/bin/gstack-config"

# /sync-gbrain context-load: teach the agent to use gbrain when it's available.
# Mutually exclusive variants per /plan-eng-review §4. Empty string when gbrain
# is not configured (zero context cost for non-gbrain users).
_GBRAIN_CONFIG="$HOME/.gbrain/config.json"
if [ -f "$_GBRAIN_CONFIG" ] && command -v gbrain >/dev/null 2>&1; then
  _GBRAIN_VERSION_OK=$(gbrain --version 2>/dev/null | grep -c '^gbrain ' || echo 0)
  if [ "$_GBRAIN_VERSION_OK" -gt 0 ] 2>/dev/null; then
    _SYNC_STATE="$_GSTACK_HOME/.gbrain-sync-state.json"
    _CWD_PAGES=0
    if [ -f "$_SYNC_STATE" ]; then
      # Flatten newlines so the regex works against pretty-printed JSON too.
      _CWD_PAGES=$(tr -d '\n' < "$_SYNC_STATE" 2>/dev/null \
        | grep -o '"name": *"code"[^}]*"detail": *{[^}]*"page_count": *[0-9]*' \
        | grep -o '"page_count": *[0-9]*' | grep -o '[0-9]\+' | head -1)
      _CWD_PAGES=${_CWD_PAGES:-0}
    fi
    if [ "$_CWD_PAGES" -gt 0 ] 2>/dev/null; then
      echo "GBrain configured. Prefer \`gbrain search\`/\`gbrain query\` over Grep for"
      echo "semantic questions; use \`gbrain code-def\`/\`code-refs\`/\`code-callers\` for"
      echo "symbol-aware code lookup. See \"## GBrain Search Guidance\" in CLAUDE.md."
      echo "Run /sync-gbrain to refresh."
    else
      echo "GBrain configured but this repo isn't indexed yet. Run \`/sync-gbrain --full\`"
      echo "before relying on \`gbrain search\` for code questions in this repo."
      echo "Falls back to Grep until indexed."
    fi
  fi
fi

_BRAIN_SYNC_MODE=$("$_BRAIN_CONFIG_BIN" get gbrain_sync_mode 2>/dev/null || echo off)

if [ -f "$_BRAIN_REMOTE_FILE" ] && [ ! -d "$_GSTACK_HOME/.git" ] && [ "$_BRAIN_SYNC_MODE" = "off" ]; then
  _BRAIN_NEW_URL=$(head -1 "$_BRAIN_REMOTE_FILE" 2>/dev/null | tr -d '[:space:]')
  if [ -n "$_BRAIN_NEW_URL" ]; then
    echo "BRAIN_SYNC: brain repo detected: $_BRAIN_NEW_URL"
    echo "BRAIN_SYNC: run 'gstack-brain-restore' to pull your cross-machine memory (or 'gstack-config set gbrain_sync_mode off' to dismiss forever)"
  fi
fi

if [ -d "$_GSTACK_HOME/.git" ] && [ "$_BRAIN_SYNC_MODE" != "off" ]; then
  _BRAIN_LAST_PULL_FILE="$_GSTACK_HOME/.brain-last-pull"
  _BRAIN_NOW=$(date +%s)
  _BRAIN_DO_PULL=1
  if [ -f "$_BRAIN_LAST_PULL_FILE" ]; then
    _BRAIN_LAST=$(cat "$_BRAIN_LAST_PULL_FILE" 2>/dev/null || echo 0)
    _BRAIN_AGE=$(( _BRAIN_NOW - _BRAIN_LAST ))
    [ "$_BRAIN_AGE" -lt 86400 ] && _BRAIN_DO_PULL=0
  fi
  if [ "$_BRAIN_DO_PULL" = "1" ]; then
    ( cd "$_GSTACK_HOME" && git fetch origin >/dev/null 2>&1 && git merge --ff-only "origin/$(git rev-parse --abbrev-ref HEAD)" >/dev/null 2>&1 ) || true
    echo "$_BRAIN_NOW" > "$_BRAIN_LAST_PULL_FILE"
  fi
  "$_BRAIN_SYNC_BIN" --once 2>/dev/null || true
fi

if [ -d "$_GSTACK_HOME/.git" ] && [ "$_BRAIN_SYNC_MODE" != "off" ]; then
  _BRAIN_QUEUE_DEPTH=0
  [ -f "$_GSTACK_HOME/.brain-queue.jsonl" ] && _BRAIN_QUEUE_DEPTH=$(wc -l < "$_GSTACK_HOME/.brain-queue.jsonl" | tr -d ' ')
  _BRAIN_LAST_PUSH="never"
  [ -f "$_GSTACK_HOME/.brain-last-push" ] && _BRAIN_LAST_PUSH=$(cat "$_GSTACK_HOME/.brain-last-push" 2>/dev/null || echo never)
  echo "BRAIN_SYNC: mode=$_BRAIN_SYNC_MODE | last_push=$_BRAIN_LAST_PUSH | queue=$_BRAIN_QUEUE_DEPTH"
else
  echo "BRAIN_SYNC: off"
fi

Privacy stop-gate: if output shows BRAIN_SYNC: off, gbrain_sync_mode_prompted is false, and gbrain is on PATH or gbrain doctor --fast --json works, ask once:

gstack can publish your session memory to a private GitHub repo that GBrain indexes across machines. How much should sync?

Options:

  • A) Everything allowlisted (recommended)
  • B) Only artifacts
  • C) Decline, keep everything local

After answer:

# Chosen mode: full | artifacts-only | off
"$_BRAIN_CONFIG_BIN" set gbrain_sync_mode <choice>
"$_BRAIN_CONFIG_BIN" set gbrain_sync_mode_prompted true

If A/B and ~/.gstack/.git is missing, ask whether to run gstack-brain-init. Do not block the skill.

At skill END before telemetry:

"~/.claude/skills/gstack/bin/gstack-brain-sync" --discover-new 2>/dev/null || true
"~/.claude/skills/gstack/bin/gstack-brain-sync" --once 2>/dev/null || true

Model-Specific Behavioral Patch (claude)

The following nudges are tuned for the claude model family. They are subordinate to skill workflow, STOP points, AskUserQuestion gates, plan-mode safety, and /ship review gates. If a nudge below conflicts with skill instructions, the skill wins. Treat these as preferences, not rules.

Todo-list discipline. When working through a multi-step plan, mark each task complete individually as you finish it. Do not batch-complete at the end. If a task turns out to be unnecessary, mark it skipped with a one-line reason.

Think before heavy actions. For complex operations (refactors, migrations, non-trivial new features), briefly state your approach before executing. This lets the user course-correct cheaply instead of mid-flight.

Dedicated tools over Bash. Prefer Read, Edit, Write, Glob, Grep over shell equivalents (cat, sed, find, grep). The dedicated tools are cheaper and clearer.

Voice

Direct, concrete, builder-to-builder. Name the file, function, command, and user-visible impact. No filler.

No em dashes. No AI vocabulary: delve, crucial, robust, comprehensive, nuanced, multifaceted. Never corporate or academic. Short paragraphs. End with what to do.

The user has context you do not. Cross-model agreement is a recommendation, not a decision. The user decides.

Completion Status Protocol

When completing a skill workflow, report status using one of:

  • DONE — completed with evidence.
  • DONE_WITH_CONCERNS — completed, but list concerns.
  • BLOCKED — cannot proceed; state blocker and what was tried.
  • NEEDS_CONTEXT — missing info; state exactly what is needed.

Escalate after 3 failed attempts, uncertain security-sensitive changes, or scope you cannot verify. Format: STATUS, REASON, ATTEMPTED, RECOMMENDATION.

Operational Self-Improvement

Before completing, if you discovered a durable project quirk or command fix that would save 5+ minutes next time, log it:

~/.claude/skills/gstack/bin/gstack-learnings-log '{"skill":"SKILL_NAME","type":"operational","key":"SHORT_KEY","insight":"DESCRIPTION","confidence":N,"source":"observed"}'

Do not log obvious facts or one-time transient errors.

Telemetry (run last)

After workflow completion, log telemetry. Use skill name: from frontmatter. OUTCOME is success/error/abort/unknown.

PLAN MODE EXCEPTION — ALWAYS RUN: This command writes telemetry to ~/.gstack/analytics/, matching preamble analytics writes.

Run this bash:

_TEL_END=$(date +%s)
_TEL_DUR=$(( _TEL_END - _TEL_START ))
rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true
# Session timeline: record skill completion (local-only, never sent anywhere)
~/.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":"'"$_TEL_DUR"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null || true
# Local analytics (gated on telemetry setting)
if [ "$_TEL" != "off" ]; then
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-usage.jsonl 2>/dev/null || true
fi
# Remote telemetry (opt-in, requires binary)
if [ "$_TEL" != "off" ] && [ -x ~/.claude/skills/gstack/bin/gstack-telemetry-log ]; then
  ~/.claude/skills/gstack/bin/gstack-telemetry-log \
    --skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \
    --used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null &
fi

Replace SKILL_NAME, OUTCOME, and USED_BROWSE before running.

In plan mode before ExitPlanMode: if the plan file lacks ## GSTACK REVIEW REPORT, run ~/.claude/skills/gstack/bin/gstack-review-read and append the standard runs/status/findings table. With NO_REVIEWS or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run /autoplan". If a richer report exists, skip.

PLAN MODE EXCEPTION — always allowed (it's the plan file).

Setup Browser Cookies

Import logged-in sessions from your real Chromium browser into the headless browse session.

CDP mode check

First, check if browse is already connected to the user's real browser:

$B status 2>/dev/null | grep -q "Mode: cdp" && echo "CDP_MODE=true" || echo "CDP_MODE=false"

If CDP_MODE=true: tell the user "Not needed — you're connected to your real browser via CDP. Your cookies and sessions are already available." and stop. No cookie import needed.

How it works

  1. Find the browse binary
  2. Run cookie-import-browser to detect installed browsers and open the picker UI
  3. User selects which cookie domains to import in their browser
  4. Cookies are decrypted and loaded into the Playwright session

Steps

1. Find the browse binary

SETUP (run this check BEFORE any browse command)

_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
B=""
[ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse"
[ -z "$B" ] && B="$HOME/.claude/skills/gstack/browse/dist/browse"
if [ -x "$B" ]; then
  echo "READY: $B"
else
  echo "NEEDS_SETUP"
fi

If NEEDS_SETUP:

  1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait.
  2. Run: cd <SKILL_DIR> && ./setup
  3. If bun is not installed:
    if ! command -v bun >/dev/null 2>&1; then
      BUN_VERSION="1.3.10"
      BUN_INSTALL_SHA="bab8acfb046aac8c72407bdcce903957665d655d7acaa3e11c7c4616beae68dd"
      tmpfile=$(mktemp)
      curl -fsSL "https://bun.sh/install" -o "$tmpfile"
      actual_sha=$(shasum -a 256 "$tmpfile" | awk '{print $1}')
      if [ "$actual_sha" != "$BUN_INSTALL_SHA" ]; then
        echo "ERROR: bun install script checksum mismatch" >&2
        echo "  expected: $BUN_INSTALL_SHA" >&2
        echo "  got:      $actual_sha" >&2
        rm "$tmpfile"; exit 1
      fi
      BUN_VERSION="$BUN_VERSION" bash "$tmpfile"
      rm "$tmpfile"
    fi
    
$B cookie-import-browser

This auto-detects installed Chromium browsers and opens an interactive picker UI in your default browser where you can:

  • Switch between installed browsers
  • Search domains
  • Click "+" to import a domain's cookies
  • Click trash to remove imported cookies

Tell the user: "Cookie picker opened — select the domains you want to import in your browser, then tell me when you're done."

3. Direct import (alternative)

If the user specifies a domain directly (e.g., /setup-browser-cookies github.com), skip the UI:

$B cookie-import-browser comet --domain github.com

Replace comet with the appropriate browser if specified.

4. Verify

After the user confirms they're done:

$B cookies

Show the user a summary of imported cookies (domain counts).

Notes

  • On macOS, the first import per browser may trigger a Keychain dialog — click "Allow" / "Always Allow"
  • On Linux, v11 cookies may require secret-tool/libsecret access; v10 cookies use Chromium's standard fallback key
  • Cookie picker is served on the same port as the browse server (no extra process)
  • Only domain names and cookie counts are shown in the UI — no cookie values are exposed
  • The browse session persists cookies between commands, so imported cookies work immediately