Skip to content

feat(skills): Skill Packs — reusable skill bundles + sandbox context files - #147

Merged
DIodide merged 1 commit into
stagingfrom
feat/skill-packs
Jun 21, 2026
Merged

feat(skills): Skill Packs — reusable skill bundles + sandbox context files#147
DIodide merged 1 commit into
stagingfrom
feat/skill-packs

Conversation

@DIodide

@DIodide DIodide commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What

A Skill Pack is a creatable entity that bundles a set of skills with optional AGENTS.md and CLAUDE.md context. You attach packs to a harness (multiple allowed) instead of picking loose skills.

  • New Skill Packs manage screen — sidebar icon + /skill-packs route (create/edit/delete, with the existing skill catalog picker + AGENTS.md/CLAUDE.md editors + an @AGENTS.md import checkbox).
  • A skill-pack picker in the harness create and edit flows (additive — loose skills still work).
  • For agentic (ACP) harnesses, the gateway writes the context to the sandbox root and materializes each skill so the agent loads it:
    • AGENTS.md<sandbox>/AGENTS.md (Claude Code, Codex, Cursor)
    • CLAUDE.md<sandbox>/CLAUDE.md (Claude Code), optionally led by @AGENTS.md
    • each skill's cached SKILL.md → ~/.claude/skills/<slug>/SKILL.md (Claude Code) — this is the first time skills actually reach ACP agents
  • The default OpenRouter loop unions pack skills into its skill manifest.

Design decisions (confirmed)

  • Multiple packs per harness — skills unioned, AGENTS.md/CLAUDE.md concatenated (per-pack header).
  • Materialize SKILL.md files so Claude Code's skill system loads them dynamically.

How it flows

harness.skillPackIdsbuildHarnessStreamConfig (owner) / resolveForCollab (collaborator) → HarnessConfig.skill_pack_ids → gateway resolves via skillPacks:resolveForGateway (owner-scoped) → context written to the sandbox. Best-effort throughout — a Convex hiccup never blocks a session.

Stale-context handling

Context files are marked Harness-managed (a sentinel first line on AGENTS.md/CLAUDE.md; a .harness-managed file in each skills dir). On a reused sandbox (attach/revive) the gateway prunes only Harness-managed context before writing the current set — so removing a skill or detaching a pack actually clears it, while user-authored files are never touched.

Verification

3-dimension adversarial multi-agent review:

  • Cross-user access: defended — resolveForGateway is owner-keyed on every path (owner ACP, collaborator ACP, collaborator default loop); a stored foreign/nonexistent pack id is inert.
  • Path traversal: defended — _skill_dir_slug collapses separators to dashes, rejects ./.., bounds length; .md paths are fixed constants.
  • Lifecycle (found + fixed): the review caught stale SKILL.md/AGENTS.md/CLAUDE.md lingering in persistent sandboxes after a skill/pack removal → fixed with the sentinel-guarded prune above.

Tests: new skillPacks.test.ts (Convex), test_skill_packs.py (FastAPI: context injection + slug + prune). Full suites: Convex 203, FastAPI 341, frontend 235. tsc / biome / ruff clean on changed files.

Notes for review

  • Backward compatible: harnesses with no packs are unaffected; loose-skills UI stays in both flows.
  • Per-harness markdown size isn't capped (per-pack is 50k; a harness can attach up to 50 packs) — provision-time cost only; can add a total cap later if needed.
  • Worth a manual smoke test on staging: create a pack with a skill + AGENTS.md/CLAUDE.md, attach to a Claude Code harness in a workspace, confirm the files land at the sandbox root and ~/.claude/skills, then remove the skill and confirm it's pruned on the next session.

…files

A Skill Pack bundles a set of skills with optional AGENTS.md / CLAUDE.md
context. Attach multiple packs to a harness (instead of, or alongside, loose
skills). For agentic (ACP) harnesses the gateway writes the context to the
sandbox root and materializes each skill's SKILL.md so Claude Code loads it.

New 'Skill Packs' manage screen (sidebar icon + /skill-packs route) to
create/edit/delete packs; a pack picker in the harness create + edit flows.

Convex:
- skillPacks table + CRUD (skillPacks.ts); harnesses carry skillPackIds
  (create/update/duplicate/resolveForCollab); remove() detaches harnesses.
- internalQuery resolveForGateway: concatenates AGENTS.md/CLAUDE.md per pack,
  unions skills (de-duped), joins cached SKILL.md — owner-scoped.

FastAPI:
- HarnessConfig.skill_pack_ids; resolve_skill_pack_context (Convex client).
- session_manager._attach_skill_pack_context writes AGENTS.md (all agentic),
  CLAUDE.md + optional @AGENTS.md import (claude-code), and
  ~/.claude/skills/<slug>/SKILL.md (claude-code), on create AND revive.
  Path-slug sanitized; best-effort (never blocks a session).
- Re-provision PRUNES previously Harness-managed context (sentinel-marked)
  before writing, so removed skills / detached packs clear from persistent
  sandboxes without touching user-authored files.
- Default OpenRouter loop (chat.py) unions pack skills into its skill manifest.

Frontend:
- manage-tabs Skill Packs nav; /skill-packs route (list + editor reusing the
  skill picker + AGENTS.md/CLAUDE.md + @import checkbox); SkillPackPicker;
  harness-stream sends skill_pack_ids; onboarding + harness-edit attach packs.

Adversarially verified (multi-agent): cross-user access + path traversal are
defended; fixed the stale-context lifecycle bug found in review. Tests: Convex
203, FastAPI 341 (incl. new skillPacks/context-injection/prune tests), frontend
235; tsc/biome/ruff clean on changed files.
@claude

claude Bot commented Jun 21, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@DIodide
DIodide merged commit 6acaf53 into staging Jun 21, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant