mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-07 14:06:42 +02:00
feat: support repo-local Codex installs (#317)
Changes gen-skill-docs.ts to use dynamic $GSTACK_ROOT/$GSTACK_BIN/$GSTACK_BROWSE variables in generated Codex preambles instead of hardcoded ~/.codex/ paths. Renames GSTACK_DIR → SOURCE_GSTACK_DIR/INSTALL_GSTACK_DIR throughout setup for clarity. Supports both global (~/.codex/skills/) and repo-local (.agents/skills/) Codex installs. Co-authored-by: pengwk <pengwk@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,10 @@ if ! command -v bun >/dev/null 2>&1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GSTACK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
SKILLS_DIR="$(dirname "$GSTACK_DIR")"
|
||||
BROWSE_BIN="$GSTACK_DIR/browse/dist/browse"
|
||||
INSTALL_GSTACK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
SOURCE_GSTACK_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||
INSTALL_SKILLS_DIR="$(dirname "$INSTALL_GSTACK_DIR")"
|
||||
BROWSE_BIN="$SOURCE_GSTACK_DIR/browse/dist/browse"
|
||||
CODEX_SKILLS="$HOME/.codex/skills"
|
||||
CODEX_GSTACK="$CODEX_SKILLS/gstack"
|
||||
|
||||
@@ -67,13 +68,14 @@ migrate_direct_codex_install() {
|
||||
|
||||
echo "Migrating direct Codex install to $migrated_dir to avoid duplicate skill discovery..."
|
||||
mv "$gstack_dir" "$migrated_dir"
|
||||
GSTACK_DIR="$migrated_dir"
|
||||
SKILLS_DIR="$(dirname "$GSTACK_DIR")"
|
||||
BROWSE_BIN="$GSTACK_DIR/browse/dist/browse"
|
||||
SOURCE_GSTACK_DIR="$migrated_dir"
|
||||
INSTALL_GSTACK_DIR="$migrated_dir"
|
||||
INSTALL_SKILLS_DIR="$(dirname "$INSTALL_GSTACK_DIR")"
|
||||
BROWSE_BIN="$SOURCE_GSTACK_DIR/browse/dist/browse"
|
||||
}
|
||||
|
||||
if [ "$INSTALL_CODEX" -eq 1 ]; then
|
||||
migrate_direct_codex_install "$GSTACK_DIR" "$CODEX_GSTACK"
|
||||
migrate_direct_codex_install "$SOURCE_GSTACK_DIR" "$CODEX_GSTACK"
|
||||
fi
|
||||
|
||||
ensure_playwright_browser() {
|
||||
@@ -81,12 +83,12 @@ ensure_playwright_browser() {
|
||||
# On Windows, Bun can't launch Chromium due to broken pipe handling
|
||||
# (oven-sh/bun#4253). Use Node.js to verify Chromium works instead.
|
||||
(
|
||||
cd "$GSTACK_DIR"
|
||||
cd "$SOURCE_GSTACK_DIR"
|
||||
node -e "const { chromium } = require('playwright'); (async () => { const b = await chromium.launch(); await b.close(); })()" 2>/dev/null
|
||||
)
|
||||
else
|
||||
(
|
||||
cd "$GSTACK_DIR"
|
||||
cd "$SOURCE_GSTACK_DIR"
|
||||
bun --eval 'import { chromium } from "playwright"; const browser = await chromium.launch(); await browser.close();'
|
||||
) >/dev/null 2>&1
|
||||
fi
|
||||
@@ -96,24 +98,24 @@ ensure_playwright_browser() {
|
||||
NEEDS_BUILD=0
|
||||
if [ ! -x "$BROWSE_BIN" ]; then
|
||||
NEEDS_BUILD=1
|
||||
elif [ -n "$(find "$GSTACK_DIR/browse/src" -type f -newer "$BROWSE_BIN" -print -quit 2>/dev/null)" ]; then
|
||||
elif [ -n "$(find "$SOURCE_GSTACK_DIR/browse/src" -type f -newer "$BROWSE_BIN" -print -quit 2>/dev/null)" ]; then
|
||||
NEEDS_BUILD=1
|
||||
elif [ "$GSTACK_DIR/package.json" -nt "$BROWSE_BIN" ]; then
|
||||
elif [ "$SOURCE_GSTACK_DIR/package.json" -nt "$BROWSE_BIN" ]; then
|
||||
NEEDS_BUILD=1
|
||||
elif [ -f "$GSTACK_DIR/bun.lock" ] && [ "$GSTACK_DIR/bun.lock" -nt "$BROWSE_BIN" ]; then
|
||||
elif [ -f "$SOURCE_GSTACK_DIR/bun.lock" ] && [ "$SOURCE_GSTACK_DIR/bun.lock" -nt "$BROWSE_BIN" ]; then
|
||||
NEEDS_BUILD=1
|
||||
fi
|
||||
|
||||
if [ "$NEEDS_BUILD" -eq 1 ]; then
|
||||
echo "Building browse binary..."
|
||||
(
|
||||
cd "$GSTACK_DIR"
|
||||
cd "$SOURCE_GSTACK_DIR"
|
||||
bun install
|
||||
bun run build
|
||||
)
|
||||
# Safety net: write .version if build script didn't (e.g., git not available during build)
|
||||
if [ ! -f "$GSTACK_DIR/browse/dist/.version" ]; then
|
||||
git -C "$GSTACK_DIR" rev-parse HEAD > "$GSTACK_DIR/browse/dist/.version" 2>/dev/null || true
|
||||
if [ ! -f "$SOURCE_GSTACK_DIR/browse/dist/.version" ]; then
|
||||
git -C "$SOURCE_GSTACK_DIR" rev-parse HEAD > "$SOURCE_GSTACK_DIR/browse/dist/.version" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -126,18 +128,18 @@ fi
|
||||
# .agents/ is no longer committed — generated at setup time from .tmpl templates.
|
||||
# bun run build already does this, but we need it when NEEDS_BUILD=0 (binary is fresh
|
||||
# but .agents/ hasn't been generated yet, e.g., fresh clone).
|
||||
AGENTS_DIR="$GSTACK_DIR/.agents/skills"
|
||||
AGENTS_DIR="$SOURCE_GSTACK_DIR/.agents/skills"
|
||||
NEEDS_AGENTS_GEN=0
|
||||
if [ ! -d "$AGENTS_DIR" ]; then
|
||||
NEEDS_AGENTS_GEN=1
|
||||
elif [ -n "$(find "$GSTACK_DIR" -maxdepth 2 -name 'SKILL.md.tmpl' -newer "$AGENTS_DIR" -print -quit 2>/dev/null)" ]; then
|
||||
elif [ -n "$(find "$SOURCE_GSTACK_DIR" -maxdepth 2 -name 'SKILL.md.tmpl' -newer "$AGENTS_DIR" -print -quit 2>/dev/null)" ]; then
|
||||
NEEDS_AGENTS_GEN=1
|
||||
fi
|
||||
|
||||
if [ "$NEEDS_AGENTS_GEN" -eq 1 ] && [ "$NEEDS_BUILD" -eq 0 ]; then
|
||||
echo "Generating .agents/ skill docs..."
|
||||
(
|
||||
cd "$GSTACK_DIR"
|
||||
cd "$SOURCE_GSTACK_DIR"
|
||||
bun install --frozen-lockfile 2>/dev/null || bun install
|
||||
bun run gen:skill-docs --host codex
|
||||
)
|
||||
@@ -147,7 +149,7 @@ fi
|
||||
if ! ensure_playwright_browser; then
|
||||
echo "Installing Playwright Chromium..."
|
||||
(
|
||||
cd "$GSTACK_DIR"
|
||||
cd "$SOURCE_GSTACK_DIR"
|
||||
bunx playwright install chromium
|
||||
)
|
||||
|
||||
@@ -161,7 +163,7 @@ if ! ensure_playwright_browser; then
|
||||
fi
|
||||
echo "Windows detected — verifying Node.js can load Playwright..."
|
||||
(
|
||||
cd "$GSTACK_DIR"
|
||||
cd "$SOURCE_GSTACK_DIR"
|
||||
# Bun's node_modules already has playwright; verify Node can require it
|
||||
node -e "require('playwright')" 2>/dev/null || npm install --no-save playwright
|
||||
)
|
||||
@@ -255,7 +257,7 @@ create_agents_sidecar() {
|
||||
|
||||
# Sidecar directories that skills reference at runtime
|
||||
for asset in bin browse review qa; do
|
||||
local src="$GSTACK_DIR/$asset"
|
||||
local src="$SOURCE_GSTACK_DIR/$asset"
|
||||
local dst="$agents_gstack/$asset"
|
||||
if [ -d "$src" ] || [ -f "$src" ]; then
|
||||
if [ -L "$dst" ] || [ ! -e "$dst" ]; then
|
||||
@@ -266,7 +268,7 @@ create_agents_sidecar() {
|
||||
|
||||
# Sidecar files that skills reference at runtime
|
||||
for file in ETHOS.md; do
|
||||
local src="$GSTACK_DIR/$file"
|
||||
local src="$SOURCE_GSTACK_DIR/$file"
|
||||
local dst="$agents_gstack/$file"
|
||||
if [ -f "$src" ]; then
|
||||
if [ -L "$dst" ] || [ ! -e "$dst" ]; then
|
||||
@@ -315,10 +317,16 @@ create_codex_runtime_root() {
|
||||
}
|
||||
|
||||
# 4. Install for Claude (default)
|
||||
SKILLS_BASENAME="$(basename "$SKILLS_DIR")"
|
||||
SKILLS_BASENAME="$(basename "$INSTALL_SKILLS_DIR")"
|
||||
SKILLS_PARENT_BASENAME="$(basename "$(dirname "$INSTALL_SKILLS_DIR")")"
|
||||
CODEX_REPO_LOCAL=0
|
||||
if [ "$SKILLS_BASENAME" = "skills" ] && [ "$SKILLS_PARENT_BASENAME" = ".agents" ]; then
|
||||
CODEX_REPO_LOCAL=1
|
||||
fi
|
||||
|
||||
if [ "$INSTALL_CLAUDE" -eq 1 ]; then
|
||||
if [ "$SKILLS_BASENAME" = "skills" ]; then
|
||||
link_claude_skill_dirs "$GSTACK_DIR" "$SKILLS_DIR"
|
||||
link_claude_skill_dirs "$SOURCE_GSTACK_DIR" "$INSTALL_SKILLS_DIR"
|
||||
echo "gstack ready (claude)."
|
||||
echo " browse: $BROWSE_BIN"
|
||||
else
|
||||
@@ -330,26 +338,26 @@ fi
|
||||
|
||||
# 5. Install for Codex
|
||||
if [ "$INSTALL_CODEX" -eq 1 ]; then
|
||||
if [ "$CODEX_REPO_LOCAL" -eq 1 ]; then
|
||||
CODEX_SKILLS="$INSTALL_SKILLS_DIR"
|
||||
CODEX_GSTACK="$INSTALL_GSTACK_DIR"
|
||||
fi
|
||||
mkdir -p "$CODEX_SKILLS"
|
||||
|
||||
create_codex_runtime_root "$GSTACK_DIR" "$CODEX_GSTACK"
|
||||
create_codex_runtime_root "$SOURCE_GSTACK_DIR" "$CODEX_GSTACK"
|
||||
# Install generated Codex-format skills (not Claude source dirs)
|
||||
link_codex_skill_dirs "$GSTACK_DIR" "$CODEX_SKILLS"
|
||||
link_codex_skill_dirs "$SOURCE_GSTACK_DIR" "$CODEX_SKILLS"
|
||||
|
||||
echo "gstack ready (codex)."
|
||||
echo " browse: $BROWSE_BIN"
|
||||
echo " codex skills: $CODEX_SKILLS"
|
||||
fi
|
||||
|
||||
# 6. Create .agents/ sidecar symlinks (useful for Codex/Gemini/Cursor workspace-local)
|
||||
# 6. Create .agents/ sidecar symlinks for the real Codex skill target.
|
||||
# The root Codex skill ends up pointing at $SOURCE_GSTACK_DIR/.agents/skills/gstack,
|
||||
# so the runtime assets must live there for both global and repo-local installs.
|
||||
if [ "$INSTALL_CODEX" -eq 1 ]; then
|
||||
# Detect repo root: if we're inside a skills directory, go up two levels
|
||||
if [ "$SKILLS_BASENAME" = "skills" ]; then
|
||||
REPO_ROOT="$(dirname "$SKILLS_DIR")"
|
||||
else
|
||||
REPO_ROOT="$GSTACK_DIR"
|
||||
fi
|
||||
create_agents_sidecar "$REPO_ROOT"
|
||||
create_agents_sidecar "$SOURCE_GSTACK_DIR"
|
||||
fi
|
||||
|
||||
# 7. First-time welcome + legacy cleanup
|
||||
|
||||
Reference in New Issue
Block a user