Skip to content

Commit 8ddfab2

Browse files
garrytanclaude
andauthored
feat: multi-agent support — gstack works on Codex, Gemini CLI, and Cursor (v0.9.0) (garrytan#226)
* refactor: host-aware gen-skill-docs + --host codex generation Refactor gen-skill-docs.ts for multi-agent support: - Add Host type, HostPaths interface, HOST_PATHS config - Decompose generatePreamble() into 7 composable sub-functions - Replace all hardcoded .claude/skills/gstack paths with ctx.paths - Replace static findTemplates() list with dynamic filesystem scan - Add --host codex|agents flag (aliases, same output) - Add processTemplate host routing to .agents/skills/gstack-*/ - Add codexSkillName() with double-prefix prevention - Add transformFrontmatter() — keeps only name + description for Codex - Add extractHookSafetyProse() — converts hooks to inline advisory - Add body text path rewriting for remaining hardcoded paths - Exclude /codex skill from Codex generation (self-referential) Claude output is unchanged (verified via --dry-run). SKILL.md is an open standard: .agents/skills/ works on Codex, Gemini CLI, and Cursor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: generate Codex/Gemini/Cursor skills into .agents/skills/ Generated 21 skill files for the open SKILL.md standard: - Output: .agents/skills/gstack-*/SKILL.md (one per skill) - Frontmatter: name + description only (no allowed-tools/version) - No .claude/skills/ paths in any generated file - /codex skill excluded (Claude wrapper, self-referential on Codex) - Hook skills (careful/freeze/guard) get inline safety prose - Build script generates both hosts: bun run build Supported agents (all read .agents/skills/): - Codex CLI - Gemini CLI - Cursor Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: dual-host setup + find-browse for Codex/Gemini/Cursor - setup: add --host codex|claude|auto flag, install to ~/.codex/skills/ when targeting Codex, auto-detect installed agents - find-browse: priority chain .codex > .agents > .claude (both workspace-local and global) - dev-setup/teardown: create .agents/skills/gstack symlinks for dev mode Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: Codex generation tests + CI + docs for multi-agent support Tests (28 new): - Codex output path routing, frontmatter validation (name+description only) - No .claude/skills/ path leaks in Codex output (regression guard) - /codex skill exclusion, hook→prose conversion, multiline YAML - --host agents alias, dynamic template discovery - Codex skill validation + $B command validation - find-browse priority chain verification - Replace static ALL_SKILLS list with dynamic filesystem scan CI: - Add Codex freshness check to skill-docs workflow Docs: - AGENTS.md: Codex-facing project instructions - README: multi-agent installation section - CONTRIBUTING: dual-host development workflow - CHANGELOG: v0.9.0 multi-agent support entry Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: Codex E2E test harness — verify skills work on Codex CLI New test infrastructure: - CodexSessionRunner: spawns codex exec, parses JSONL stream, returns structured results (output, reasoning, toolCalls, tokens) - JSONL parser ported from Python (codex/SKILL.md.tmpl) to TypeScript - Temp HOME skill installation for Codex discovery testing E2E tests (gated behind EVALS=1 + codex + OPENAI_API_KEY): - codex-discover-skill: installs skill, verifies Codex finds it - codex-review-findings: runs gstack-review via Codex, validates output Integrates with existing eval infrastructure: - Diff-based test selection via touchfiles - Eval persistence via EvalCollector - bun run test:codex / test:codex:all convenience scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: bump VERSION to 0.9.0 to match CHANGELOG Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Codex sidecar paths + setup installs generated skills Two bugs found by Codex adversarial review: 1. Sidecar path mismatch: generated Codex skills referenced .agents/skills/gstack-review/checklist.md but setup creates sidecars at .agents/skills/gstack/review/. Fixed path rewriter to emit .agents/skills/gstack/review/ (matching setup layout). 2. Setup installed Claude-format source dirs for Codex global install instead of the generated Codex-format skills. Split link_skill_dirs into link_claude_skill_dirs (source dirs for Claude) and link_codex_skill_dirs (generated .agents/skills/ gstack-* dirs for Codex). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: comprehensive Codex path rewriting + setup install tests 17 new tests covering: - Sidecar path rewriting: .claude/skills/review → .agents/skills/gstack/review/ (catches the bug where checklist.md was unreachable at gstack-review/) - All 4 path rewrite rules tested individually across all skills - Greptile triage sidecar path correctness - Ship skill sidecar paths for pre-landing review - Claude output regression guard: zero Codex paths in any Claude skill - Setup script validation: separate link functions for Claude vs Codex, link_codex_skill_dirs reads from .agents/skills/, create_agents_sidecar links runtime assets (bin, browse, review, qa) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: regenerate Codex skills after investigate rename merge Remove stale gstack-debug, add gstack-investigate, regenerate all Codex skills to pick up changes merged from main (investigate rename, platform-agnostic templates, review helpers). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Codex E2E uses ~/.codex/ auth, not OPENAI_API_KEY - Remove OPENAI_API_KEY gate from test prerequisites - Copy real ~/.codex/ auth config into temp HOME so codex can authenticate - Increase review test timeout to 540s (codex does thorough 60+ tool call reviews) - Document in CLAUDE.md that Codex uses its own auth config Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3b22fc3 commit 8ddfab2

42 files changed

Lines changed: 12241 additions & 143 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/gstack-browse/SKILL.md

Lines changed: 457 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
name: careful
3+
description: |
4+
Safety guardrails for destructive commands. Warns before rm -rf, DROP TABLE,
5+
force-push, git reset --hard, kubectl delete, and similar destructive operations.
6+
User can override each warning. Use when touching prod, debugging live systems,
7+
or working in a shared environment. Use when asked to "be careful", "safety mode",
8+
"prod mode", or "careful mode".
9+
---
10+
<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->
11+
<!-- Regenerate: bun run gen:skill-docs -->
12+
> **Safety Advisory:** This skill includes safety checks that check bash commands for destructive operations (rm -rf, DROP TABLE, force-push, git reset --hard, etc.) before execution. When using this skill, always pause and verify before executing potentially destructive operations. If uncertain about a command's safety, ask the user for confirmation before proceeding.
13+
14+
15+
# /careful — Destructive Command Guardrails
16+
17+
Safety mode is now **active**. Every bash command will be checked for destructive
18+
patterns before running. If a destructive command is detected, you'll be warned
19+
and can choose to proceed or cancel.
20+
21+
```bash
22+
mkdir -p ~/.gstack/analytics
23+
echo '{"skill":"careful","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
24+
```
25+
26+
## What's protected
27+
28+
| Pattern | Example | Risk |
29+
|---------|---------|------|
30+
| `rm -rf` / `rm -r` / `rm --recursive` | `rm -rf /var/data` | Recursive delete |
31+
| `DROP TABLE` / `DROP DATABASE` | `DROP TABLE users;` | Data loss |
32+
| `TRUNCATE` | `TRUNCATE orders;` | Data loss |
33+
| `git push --force` / `-f` | `git push -f origin main` | History rewrite |
34+
| `git reset --hard` | `git reset --hard HEAD~3` | Uncommitted work loss |
35+
| `git checkout .` / `git restore .` | `git checkout .` | Uncommitted work loss |
36+
| `kubectl delete` | `kubectl delete pod` | Production impact |
37+
| `docker rm -f` / `docker system prune` | `docker system prune -a` | Container/image loss |
38+
39+
## Safe exceptions
40+
41+
These patterns are allowed without warning:
42+
- `rm -rf node_modules` / `.next` / `dist` / `__pycache__` / `.cache` / `build` / `.turbo` / `coverage`
43+
44+
## How it works
45+
46+
The hook reads the command from the tool input JSON, checks it against the
47+
patterns above, and returns `permissionDecision: "ask"` with a warning message
48+
if a match is found. You can always override the warning and proceed.
49+
50+
To deactivate, end the conversation or start a new one. Hooks are session-scoped.

.agents/skills/gstack-design-consultation/SKILL.md

Lines changed: 556 additions & 0 deletions
Large diffs are not rendered by default.

.agents/skills/gstack-design-review/SKILL.md

Lines changed: 934 additions & 0 deletions
Large diffs are not rendered by default.

.agents/skills/gstack-document-release/SKILL.md

Lines changed: 550 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
name: freeze
3+
description: |
4+
Restrict file edits to a specific directory for the session. Blocks Edit and
5+
Write outside the allowed path. Use when debugging to prevent accidentally
6+
"fixing" unrelated code, or when you want to scope changes to one module.
7+
Use when asked to "freeze", "restrict edits", "only edit this folder",
8+
or "lock down edits".
9+
---
10+
<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->
11+
<!-- Regenerate: bun run gen:skill-docs -->
12+
> **Safety Advisory:** This skill includes safety checks that verify file edits are within the allowed scope boundary before applying, and verify file writes are within the allowed scope boundary before applying. When using this skill, always pause and verify before executing potentially destructive operations. If uncertain about a command's safety, ask the user for confirmation before proceeding.
13+
14+
15+
# /freeze — Restrict Edits to a Directory
16+
17+
Lock file edits to a specific directory. Any Edit or Write operation targeting
18+
a file outside the allowed path will be **blocked** (not just warned).
19+
20+
```bash
21+
mkdir -p ~/.gstack/analytics
22+
echo '{"skill":"freeze","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
23+
```
24+
25+
## Setup
26+
27+
Ask the user which directory to restrict edits to. Use AskUserQuestion:
28+
29+
- Question: "Which directory should I restrict edits to? Files outside this path will be blocked from editing."
30+
- Text input (not multiple choice) — the user types a path.
31+
32+
Once the user provides a directory path:
33+
34+
1. Resolve it to an absolute path:
35+
```bash
36+
FREEZE_DIR=$(cd "<user-provided-path>" 2>/dev/null && pwd)
37+
echo "$FREEZE_DIR"
38+
```
39+
40+
2. Ensure trailing slash and save to the freeze state file:
41+
```bash
42+
FREEZE_DIR="${FREEZE_DIR%/}/"
43+
STATE_DIR="${CLAUDE_PLUGIN_DATA:-$HOME/.gstack}"
44+
mkdir -p "$STATE_DIR"
45+
echo "$FREEZE_DIR" > "$STATE_DIR/freeze-dir.txt"
46+
echo "Freeze boundary set: $FREEZE_DIR"
47+
```
48+
49+
Tell the user: "Edits are now restricted to `<path>/`. Any Edit or Write
50+
outside this directory will be blocked. To change the boundary, run `/freeze`
51+
again. To remove it, run `/unfreeze` or end the session."
52+
53+
## How it works
54+
55+
The hook reads `file_path` from the Edit/Write tool input JSON, then checks
56+
whether the path starts with the freeze directory. If not, it returns
57+
`permissionDecision: "deny"` to block the operation.
58+
59+
The freeze boundary persists for the session via the state file. The hook
60+
script reads it on every Edit/Write invocation.
61+
62+
## Notes
63+
64+
- The trailing `/` on the freeze directory prevents `/src` from matching `/src-old`
65+
- Freeze applies to Edit and Write tools only — Read, Bash, Glob, Grep are unaffected
66+
- This prevents accidental edits, not a security boundary — Bash commands like `sed` can still modify files outside the boundary
67+
- To deactivate, run `/unfreeze` or end the conversation
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
name: guard
3+
description: |
4+
Full safety mode: destructive command warnings + directory-scoped edits.
5+
Combines /careful (warns before rm -rf, DROP TABLE, force-push, etc.) with
6+
/freeze (blocks edits outside a specified directory). Use for maximum safety
7+
when touching prod or debugging live systems. Use when asked to "guard mode",
8+
"full safety", "lock it down", or "maximum safety".
9+
---
10+
<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->
11+
<!-- Regenerate: bun run gen:skill-docs -->
12+
> **Safety Advisory:** This skill includes safety checks that check bash commands for destructive operations (rm -rf, DROP TABLE, force-push, git reset --hard, etc.) before execution, and verify file edits are within the allowed scope boundary before applying, and verify file writes are within the allowed scope boundary before applying. When using this skill, always pause and verify before executing potentially destructive operations. If uncertain about a command's safety, ask the user for confirmation before proceeding.
13+
14+
15+
# /guard — Full Safety Mode
16+
17+
Activates both destructive command warnings and directory-scoped edit restrictions.
18+
This is the combination of `/careful` + `/freeze` in a single command.
19+
20+
**Dependency note:** This skill references hook scripts from the sibling `/careful`
21+
and `/freeze` skill directories. Both must be installed (they are installed together
22+
by the gstack setup script).
23+
24+
```bash
25+
mkdir -p ~/.gstack/analytics
26+
echo '{"skill":"guard","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
27+
```
28+
29+
## Setup
30+
31+
Ask the user which directory to restrict edits to. Use AskUserQuestion:
32+
33+
- Question: "Guard mode: which directory should edits be restricted to? Destructive command warnings are always on. Files outside the chosen path will be blocked from editing."
34+
- Text input (not multiple choice) — the user types a path.
35+
36+
Once the user provides a directory path:
37+
38+
1. Resolve it to an absolute path:
39+
```bash
40+
FREEZE_DIR=$(cd "<user-provided-path>" 2>/dev/null && pwd)
41+
echo "$FREEZE_DIR"
42+
```
43+
44+
2. Ensure trailing slash and save to the freeze state file:
45+
```bash
46+
FREEZE_DIR="${FREEZE_DIR%/}/"
47+
STATE_DIR="${CLAUDE_PLUGIN_DATA:-$HOME/.gstack}"
48+
mkdir -p "$STATE_DIR"
49+
echo "$FREEZE_DIR" > "$STATE_DIR/freeze-dir.txt"
50+
echo "Freeze boundary set: $FREEZE_DIR"
51+
```
52+
53+
Tell the user:
54+
- "**Guard mode active.** Two protections are now running:"
55+
- "1. **Destructive command warnings** — rm -rf, DROP TABLE, force-push, etc. will warn before executing (you can override)"
56+
- "2. **Edit boundary** — file edits restricted to `<path>/`. Edits outside this directory are blocked."
57+
- "To remove the edit boundary, run `/unfreeze`. To deactivate everything, end the session."
58+
59+
## What's protected
60+
61+
See `/careful` for the full list of destructive command patterns and safe exceptions.
62+
See `/freeze` for how edit boundary enforcement works.

0 commit comments

Comments
 (0)