Skip to content

Make baked overlay tree (agents/skills/plugins/hooks) reachable from CLI at job runtime #259

@cbeaulieu-gt

Description

@cbeaulieu-gt

Problem

Per the empirical verdict on #245, the baked /opt/claude/.claude/ tree in the runtime overlay images (claude-runtime-{review,fix,explain}) is not reachable from the Claude CLI at job runtime. GitHub Actions sets HOME=/github/home at container start, and the CLI's standard discovery chain looks at $HOME/.claude/ rather than /opt/claude/.claude/.

The pr-review composite action already contains a workaround that copies the persona CLAUDE.md from the bake into $HOME/.claude/CLAUDE.md — but the workaround stops there. Agents, skills, plugins, and hooks remain orphaned.

There is also a second structural barrier (originally documented in #245's body): the ALLOWED_TOOLS allowlist passed to claude-code-action@v1 for review runs is currently extremely narrow — Glob, Grep, LS, Read, mcp__github_comment__update_claude_comment, Bash(git add:*), … — and does not include Task or Skill. Even if reachability is fixed, the LLM cannot dispatch baked sub-agents or invoke baked skills in a review run until the allowlist is widened to match the agent set the overlay carries. Reachability and invocability must land together to deliver value; this issue covers both.

Concrete consequence today:

Acceptance criteria

  • Inside any digest-pinned overlay image at job runtime, $HOME/.claude/ resolves to a tree where the full baked agent/skill/plugin/hook set is enumerable by the CLI — not just CLAUDE.md.
  • The verb-specific overlay differentiation is observable: a job running on claude-runtime-review can resolve inquisitor (or another review-only agent) and a job running on claude-runtime-fix cannot, mirroring the expected.yaml inventory contracts.
  • ALLOWED_TOOLS aligned with overlay agent set. The claude-code-action@v1 invocation in each composite action (pr-review/, apply-fix/, lint-failure/, tag-claude/, claude-command-router/ consumers) is updated to include Task and Skill so the LLM can dispatch baked agents and invoke baked skills. Per-verb scoping is preserved: the review allowlist remains write-free (no Edit, no Write, no general Bash(*)); fix-class allowlists permit write tools per their existing scope. The exact allowlist for each overlay must be documented in the runtime spec so future edits don't silently re-narrow it.
  • STAGE 4 overlay smoke (runtime/scripts/smoke-test.sh) gains a reachability probe that runs the CLI under GHA-equivalent env (HOME=/github/home, GHA UID) and asserts at least one baked agent is enumerable. This codifies the gap so it cannot drift back.
  • Remediation does not regress the persona-copy step's behavior — the persona CLAUDE.md must continue to load.
  • Documented in runtime/ README and the runtime spec (§3.4 layer 2) so future overlay edits don't reintroduce the orphan or re-narrow the allowlist.

Design options to evaluate

These should be weighed in the implementation plan, not pre-committed here.

Reachability options

Option Sketch Pros Cons
A. Extend the persona-copy step to mirror the full tree Replace cp .../CLAUDE.md $HOME/.claude/CLAUDE.md with a recursive copy or rsync of /opt/claude/.claude/$HOME/.claude/. Local to the composite action; no entrypoint change; matches the existing pattern. Cost on every job start (size: ~600 KB review + 135 KB shared); collisions with consumer-repo .claude/ need a merge strategy decision.
B. Symlink $HOME/.claude → /opt/claude/.claude in entrypoint Container entrypoint creates the symlink before the action runs. Zero copy cost; single source of truth. Read-only behavior — any CLI write into $HOME/.claude/ would either fail or write into the image's writable layer; needs verification of CLI's expectations. May break consumer-repo overrides.
C. Honor a CLAUDE_HOME env var If the CLI supports a discovery override env var, set CLAUDE_HOME=/opt/claude/.claude in the overlay's ENV. Cleanest; no filesystem manipulation; consumer-repo .claude/ stays addressable separately. Depends on CLI honoring such a var — needs verification (anthropics/claude-code source / docs). If unsupported, ruled out.
D. Hybrid: CLAUDE_HOME if supported, else extended copy Probe (C) first; fall back to (A). Resilient to CLI version drift. Larger blast radius; two code paths to maintain.

Verifying which of A/B/C is viable is part of the remediation plan, not a deliverable of this issue's framing.

ALLOWED_TOOLS options

The allowlist update is mostly mechanical, but the design question is whether the allowlist is per-overlay (declared in the overlay's persona / metadata) or per-composite-action (declared in each action.yml that calls claude-code-action@v1). The latter is where it lives today; moving it to the overlay would centralize "what this verb is allowed to do" alongside the agent set, but requires the composite action to read the overlay's allowlist at invocation time. Implementation plan should pick.

Out of scope

Related

🤖 Generated by Claude Code on behalf of @cbeaulieu-gt

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions