refactor(skills): make skills portable across users/locations via workspace-relative paths + env var overrides
Changes:
- skills/lib.sh:
- HOME_DIR default changed from $HOME to <workspace_root> (workspace self-sufficient)
- Added CLAUDE_PROJECT_DIR / LOCAL_BIN env var pattern (default $HOME, overridable)
- skills/tmux-agent-orchestrate-monitor/scripts/reconcile.sh:
- STATE_DIR moved from $HOME/.cache/... to <workspace>/.cache/tmux-agent-orchestrate-monitor
- skills/tmux-agent-orchestrate-create/scripts/create_session.sh:
- WRAPPER uses $LOCAL_BIN env var (default $HOME/.local/bin)
- 6 SKILL.md: examples and explanations updated to mention env var override capability
User/portability contract:
- Workspace-internal data: .hermes/ + .cache/ (moves with workspace)
- User/system data: $HOME/* (overridable via CLAUDE_PROJECT_DIR, LOCAL_BIN)
- All env vars follow: ${VAR:-default} pattern with documented defaults
Verified on isolated server -L agy-homeport-test (kill-server after):
- syntax check PASS
- E2E: defaults resolve to workspace-relative paths
- E2E: env var override correctly changes paths
- 0 leftover direct $HOME references in code
- Global skill non-interference verified
- Main isolated server -L multi-agent-canary untouched
This commit is contained in:
@@ -16,7 +16,7 @@ set -euo pipefail
|
||||
|
||||
source "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/lib.sh"
|
||||
|
||||
STATE_DIR="${AGENT_SESSIONS_STATE_DIR:-$HOME/.cache/tmux-agent-orchestrate-monitor}"
|
||||
STATE_DIR="${AGENT_SESSIONS_STATE_DIR:-$WORKSPACE_ROOT/.cache/tmux-agent-orchestrate-monitor}"
|
||||
|
||||
ONCE=0
|
||||
EMIT_DIFF=0
|
||||
@@ -54,7 +54,7 @@ if [ "$SUBSCRIBE" = "1" ]; then
|
||||
|
||||
# The MQTT subscribe loop exits 3 to signal "broker unavailable → poll instead".
|
||||
set +e
|
||||
YAML_PATH="$AGENT_SESSIONS_YAML" HOME_DIR="$HOME" \
|
||||
YAML_PATH="$AGENT_SESSIONS_YAML" HOME_DIR="$HOME_DIR" CLAUDE_PROJECT_DIR="$CLAUDE_PROJECT_DIR" LOCAL_BIN="$LOCAL_BIN" \
|
||||
SUB_TIMEOUT="$SUB_TIMEOUT" SUB_IDLE_TIMEOUT="$SUB_IDLE_TIMEOUT" \
|
||||
SKILLS_DIR="$SKILLS_DIR" LIB_SH="$LIB_SH" \
|
||||
"$PYBIN" - <<'PYEOF'
|
||||
@@ -229,6 +229,7 @@ import yaml
|
||||
|
||||
yaml_path = os.environ['YAML_PATH']
|
||||
home = os.environ['HOME_DIR']
|
||||
claude_project_dir = os.environ.get('CLAUDE_PROJECT_DIR', f"{home}/.claude/projects")
|
||||
|
||||
now_iso = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
@@ -374,7 +375,7 @@ for s in d.get('tmux_sessions', []):
|
||||
if not cwd:
|
||||
continue
|
||||
proj_key = cwd.replace('/', '-').replace('_', '-')
|
||||
proj_dir = f"{home}/.claude/projects/{proj_key}"
|
||||
proj_dir = f"{claude_project_dir}/{proj_key}"
|
||||
if not os.path.isdir(proj_dir):
|
||||
continue
|
||||
jsonls = sorted(glob.glob(f"{proj_dir}/*.jsonl"), key=os.path.getmtime, reverse=True)
|
||||
@@ -426,7 +427,7 @@ ai = d.get('agent_identities', {}) or {}
|
||||
cl = (ai.get('claude') or {})
|
||||
if cl.get('session_id'):
|
||||
sid = cl['session_id']
|
||||
if not glob.glob(f"{home}/.claude/projects/*/{sid}.jsonl"):
|
||||
if not glob.glob(f"{claude_project_dir}/*/{sid}.jsonl"):
|
||||
drifts.append({'class': 'D', 'name': '(claude identity cache)',
|
||||
'msg': f"stale UUID in agent_identities.claude.session_id: {sid} (jsonl missing)"})
|
||||
ag = (ai.get('agy') or {})
|
||||
|
||||
Reference in New Issue
Block a user