Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Fork it. Improve it. Make it yours. And if you want to hate on free open source

## Quick start

Fresh Claude installs default to namespaced commands like `/gstack-office-hours`, `/gstack-review`, `/gstack-qa`, and `/gstack-autoplan` to avoid host command collisions. Run `./setup --no-prefix` if you prefer short forms like the examples below.

1. Install gstack (30 seconds — see below)
2. Run `/office-hours` — describe what you're building
3. Run `/plan-ceo-review` on any feature idea
Expand All @@ -48,10 +50,14 @@ Open Claude Code and paste this. Claude does the rest.

> Install gstack: run **`git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.claude/skills/gstack && cd ~/.claude/skills/gstack && ./setup`** then add a "gstack" section to CLAUDE.md that says to use the /browse skill from gstack for all web browsing, never use mcp\_\_claude-in-chrome\_\_\* tools, and lists the available skills: /office-hours, /plan-ceo-review, /plan-eng-review, /plan-design-review, /design-consultation, /design-shotgun, /design-html, /review, /ship, /land-and-deploy, /canary, /benchmark, /browse, /connect-chrome, /qa, /qa-only, /design-review, /setup-browser-cookies, /setup-deploy, /retro, /investigate, /document-release, /codex, /cso, /autoplan, /careful, /freeze, /guard, /unfreeze, /gstack-upgrade, /learn. Then ask the user if they also want to add gstack to the current project so teammates get it.

Fresh Claude installs now default to namespaced commands like `/gstack-office-hours`, `/gstack-review`, `/gstack-qa`, and `/gstack-autoplan`. That avoids host-command collisions. If you intentionally want short commands, rerun setup with `./setup --no-prefix`.

### Step 2: Add to your repo so teammates get it (optional)

> Add gstack to this project: run **`cp -Rf ~/.claude/skills/gstack .claude/skills/gstack && rm -rf .claude/skills/gstack/.git && cd .claude/skills/gstack && ./setup`** then add a "gstack" section to this project's CLAUDE.md that says to use the /browse skill from gstack for all web browsing, never use mcp\_\_claude-in-chrome\_\_\* tools, lists the available skills: /office-hours, /plan-ceo-review, /plan-eng-review, /plan-design-review, /design-consultation, /design-shotgun, /design-html, /review, /ship, /land-and-deploy, /canary, /benchmark, /browse, /connect-chrome, /qa, /qa-only, /design-review, /setup-browser-cookies, /setup-deploy, /retro, /investigate, /document-release, /codex, /cso, /autoplan, /careful, /freeze, /guard, /unfreeze, /gstack-upgrade, /learn, and tells Claude that if gstack skills aren't working, run `cd .claude/skills/gstack && ./setup` to build the binary and register skills.

For repo-local Claude installs, the same default applies: namespaced commands first. Use `./setup --no-prefix` only if you explicitly want flat command names.

Real files get committed to your repo (not a submodule), so `git clone` just works. Everything lives inside `.claude/`. Nothing touches your PATH or runs in the background.

> **Contributing or need full history?** The commands above use `--depth 1` for a fast install. If you plan to contribute or need full git history, do a full clone instead:
Expand Down Expand Up @@ -274,9 +280,11 @@ Data is stored in [Supabase](https://supabase.com) (open source Firebase alterna

**Stale install?** Run `/gstack-upgrade` — or set `auto_upgrade: true` in `~/.gstack/config.yaml`

**`/autoplan` enters Claude Plan mode?** `cd ~/.claude/skills/gstack && ./setup --prefix` — then use `/gstack-autoplan` instead of `/autoplan`.

**Want shorter commands?** `cd ~/.claude/skills/gstack && ./setup --no-prefix` — switches from `/gstack-qa` to `/qa`. Your choice is remembered for future upgrades.

**Want namespaced commands?** `cd ~/.claude/skills/gstack && ./setup --prefix` — switches from `/qa` to `/gstack-qa`. Useful if you run other skill packs alongside gstack.
**Want namespaced commands?** `cd ~/.claude/skills/gstack && ./setup --prefix` — keeps `/gstack-qa`, `/gstack-review`, and `/gstack-autoplan`. This is the default on fresh installs because it avoids host-command collisions and other skill-pack conflicts.

**Codex says "Skipped loading skill(s) due to invalid SKILL.md"?** Your Codex skill descriptions are stale. Fix: `cd ~/.codex/skills/gstack && git pull && ./setup --host codex` — or for repo-local installs: `cd "$(readlink -f .agents/skills/gstack)" && git pull && ./setup --host codex`

Expand Down
18 changes: 9 additions & 9 deletions setup
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ case "$HOST" in
esac

# ─── Resolve skill prefix preference ─────────────────────────
# Priority: CLI flag > saved config > interactive prompt (or flat default for non-TTY)
# Priority: CLI flag > saved config > interactive prompt (or namespaced default for non-TTY)
GSTACK_CONFIG="$SOURCE_GSTACK_DIR/bin/gstack-config"
export GSTACK_SETUP_RUNNING=1 # Prevent gstack-config post-set hook from triggering relink mid-setup
if [ "$SKILL_PREFIX_FLAG" -eq 0 ]; then
Expand All @@ -59,25 +59,25 @@ if [ "$SKILL_PREFIX_FLAG" -eq 0 ]; then
elif [ "$_saved_prefix" = "false" ]; then
SKILL_PREFIX=0
else
# No saved preference — prompt interactively (or default flat for non-TTY)
# No saved preference — prompt interactively (or default namespaced for non-TTY)
if [ -t 0 ]; then
echo ""
echo "Skill naming: how should gstack skills appear?"
echo ""
echo " 1) Short names: /qa, /ship, /review"
echo " Recommended. Clean and fast to type."
echo " 1) Namespaced: /gstack-qa, /gstack-ship, /gstack-review"
echo " Recommended. Avoids collisions with host commands like /autoplan vs Claude Plan mode."
echo ""
echo " 2) Namespaced: /gstack-qa, /gstack-ship, /gstack-review"
echo " Use this if you run other skill packs alongside gstack to avoid conflicts."
echo " 2) Short names: /qa, /ship, /review"
echo " Shorter to type, but more likely to collide with other skill packs or host commands."
echo ""
printf "Choice [1/2] (default: 1, auto-selects in 10s): "
read -t 10 -r _prefix_choice </dev/tty 2>/dev/null || _prefix_choice=""
case "$_prefix_choice" in
2) SKILL_PREFIX=1 ;;
*) SKILL_PREFIX=0 ;;
2) SKILL_PREFIX=0 ;;
*) SKILL_PREFIX=1 ;;
esac
else
SKILL_PREFIX=0
SKILL_PREFIX=1
fi
# Save the choice for future runs
"$GSTACK_CONFIG" set skill_prefix "$([ "$SKILL_PREFIX" -eq 1 ] && echo true || echo false)" 2>/dev/null || true
Expand Down
19 changes: 13 additions & 6 deletions test/gen-skill-docs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2099,14 +2099,21 @@ describe('setup script validation', () => {
});

test('interactive prompt shows when no config', () => {
expect(setupContent).toContain('Short names');
expect(setupContent).toContain('Namespaced');
expect(setupContent).toContain('Short names');
expect(setupContent).toContain('Choice [1/2]');
});

test('non-TTY defaults to flat names', () => {
// Should check if stdin is a TTY before prompting
expect(setupContent).toContain('-t 0');
expect(setupContent).toContain('Avoids collisions with host commands like /autoplan vs Claude Plan mode.');
});

test('no-config install defaults to namespaced commands', () => {
const promptStart = setupContent.indexOf('# No saved preference');
const promptEnd = setupContent.indexOf('# Save the choice', promptStart);
const promptBlock = setupContent.slice(promptStart, promptEnd);
expect(promptBlock).toContain('1) Namespaced');
expect(promptBlock).toContain('2) Short names');
expect(promptBlock).toContain('2) SKILL_PREFIX=0 ;;');
expect(promptBlock).toContain('*) SKILL_PREFIX=1 ;;');
expect(promptBlock).toMatch(/else\s+SKILL_PREFIX=1\s+fi/);
});

test('cleanup_prefixed_claude_symlinks exists and uses readlink', () => {
Expand Down
Loading