#!/usr/bin/env bash # gstack-paths — output portable state-root paths for skill bash blocks # Usage: eval "$(gstack-paths)" → sets GSTACK_STATE_ROOT, PLAN_ROOT, TMP_ROOT # Or: gstack-paths → prints GSTACK_STATE_ROOT=... etc. # # Resolves three roots with explicit fallback chains so skills work the same # whether installed as a Claude Code plugin (CLAUDE_PLUGIN_DATA / CLAUDE_PLANS_DIR # set), a global ~/.claude/skills/gstack/ install, or a local checkout under # CI / container env where HOME may be unset. # # Chains: # GSTACK_STATE_ROOT: GSTACK_HOME -> CLAUDE_PLUGIN_DATA -> $HOME/.gstack -> .gstack # PLAN_ROOT: GSTACK_PLAN_DIR -> CLAUDE_PLANS_DIR -> $HOME/.claude/plans -> .claude/plans # TMP_ROOT: TMPDIR -> TMP -> .gstack/tmp (and mkdir -p, best-effort) # # Security: output values are not sanitized — callers may receive paths with # shell-special characters if env vars contain them. Skills should always quote # expansions ("$GSTACK_STATE_ROOT", not $GSTACK_STATE_ROOT). set -u # State root: where gstack writes projects/, sessions/, analytics/. if [ -n "${GSTACK_HOME:-}" ]; then _state_root="$GSTACK_HOME" elif [ -n "${CLAUDE_PLUGIN_DATA:-}" ]; then _state_root="$CLAUDE_PLUGIN_DATA" elif [ -n "${HOME:-}" ]; then _state_root="$HOME/.gstack" else _state_root=".gstack" fi # Plan root: where /context-save and /codex consult write plan files. if [ -n "${GSTACK_PLAN_DIR:-}" ]; then _plan_root="$GSTACK_PLAN_DIR" elif [ -n "${CLAUDE_PLANS_DIR:-}" ]; then _plan_root="$CLAUDE_PLANS_DIR" elif [ -n "${HOME:-}" ]; then _plan_root="$HOME/.claude/plans" else _plan_root=".claude/plans" fi # Tmp root: where ephemeral files (codex stderr captures, etc.) live. # Honor TMPDIR / TMP for Windows + container compat; fall back to a # project-local .gstack/tmp so we never write to a system /tmp that may # be read-only or shared. if [ -n "${TMPDIR:-}" ]; then _tmp_root="$TMPDIR" elif [ -n "${TMP:-}" ]; then _tmp_root="$TMP" else _tmp_root=".gstack/tmp" fi # Best-effort mkdir; if it fails (read-only fs, permission denied), the caller # will discover that on their own write attempt. Don't fail the eval here. mkdir -p "$_tmp_root" 2>/dev/null || true echo "GSTACK_STATE_ROOT=$_state_root" echo "PLAN_ROOT=$_plan_root" echo "TMP_ROOT=$_tmp_root"