Pack format reference
See what a pack is for the concept, and
creating and editing a pack for where this file lives and how
you change it. This page covers pack.json's exact shape.
pack.json anatomy
- Required:
id(lowercase slug),version,title(single line),summary(single line),context.markdown, and the three block arraysagents/commands/hooks(each may be empty). - Optional:
attribution({source, url, license}),scope("repo"default,"developer", or"both"),capabilities,skills,onboarding,relatedTo/supersedes(catalog cross-links, never rendered into any file).
A hook's event must be one of the fixed Claude Code lifecycle events
(PreToolUse, PostToolUse,
Notification, UserPromptSubmit,
Stop, SubagentStop,
PreCompact, SessionStart,
SessionEnd). A misspelled event would otherwise pass as a valid string
but never fire. So baselane rejects any event outside this list up front.
A capability's type must be one of memory,
tasks, wiki, graph,
design, or system-map. At most one memory
capability per store may use method files or
native (both would own /remember), and at
most one design capability per store (they all render the single DESIGN.md).
Skills layouts baselane ingests
When baselane install github:owner/repo@ref resolves a repo with no root
pack.json, it looks for skills content instead. It recognizes every
npx-skills-convention SKILL.md layout:
- A single root
SKILL.md: the repo itself is one skill, named after the repo. - One-level
skills/<name>/SKILL.md. - Two-level catalog dirs,
skills/<category>/<name>/SKILL.md: category dirs include dot-prefixed ones like.curated,.experimental,.system. .agents/skills/<name>/SKILL.md.
When the same skill name shows up at more than one depth, the shallowest
SKILL.md wins (shallow-shadows-deep); at equal depth, the alphabetically
first path wins as a deterministic tie-break. Sibling files one level under a winning skill's
directory (references, scripts) travel with it. If the fileset has neither a
pack.json nor any recognizable skills/harness content
(AGENTS.md or anything under .claude/),
install fails outright. There is nothing to install.
Examples
Every example on this page is tested automatically. Valid ones install cleanly. Invalid ones show the error described.
Minimal valid pack
Valid. The smallest object validatePack accepts: id (a lowercase slug), version, title, summary, context.markdown, and the three required arrays — agents, commands, hooks — which may all be empty. Every other field (attribution, scope, capabilities, skills, onboarding, relatedTo, supersedes) is optional.
{
"id": "hello-pack",
"version": "1.0.0",
"title": "Hello Pack",
"summary": "A minimal example pack with no blocks.",
"context": {
"markdown": "## Hello\n\nThis pack ships no agents, commands, or hooks.\n"
},
"agents": [],
"commands": [],
"hooks": []
}
Pack with a skill
Valid. `skills[i]` requires name (slug, ≤ 64 chars), description (single line, ≤ 1024 chars, no XML tags), body (markdown, ≤ 500 lines), and category (slug). Governance fields (userInvocable/disableModelInvocation/allowedTools) are optional and render as kebab-case SKILL.md frontmatter keys.
{
"id": "example-skill-pack",
"version": "1.0.0",
"title": "Example Skill Pack",
"summary": "Ships one skill.",
"context": {
"markdown": "## Example skill pack\n"
},
"skills": [
{
"name": "greeting",
"description": "Greets the user politely.",
"body": "# Greeting\n\nSay hello.\n",
"category": "utility"
}
],
"agents": [],
"commands": [],
"hooks": []
}
Pack with an agent, a command, and a hook
Valid. agents[i] needs name/description/tools/model/prompt. commands[i] needs name/description/argument_hint/prompt. hooks[i] needs event (one of the fixed Claude Code lifecycle events), matcher (may be empty), description, action ("print-reminder" or "run-command"), and message or command depending on the action.
{
"id": "full-block-pack",
"version": "1.0.0",
"title": "Full Block Pack",
"summary": "One of each block type.",
"context": {
"markdown": "## Full block pack\n"
},
"agents": [
{
"name": "reviewer",
"description": "Reviews changes for correctness.",
"tools": [
"Read",
"Grep"
],
"model": "sonnet",
"prompt": "You review diffs for correctness."
}
],
"commands": [
{
"name": "review",
"description": "Run a review pass.",
"argument_hint": "[scope]",
"prompt": "Review $ARGUMENTS."
}
],
"hooks": [
{
"event": "SessionStart",
"matcher": "",
"description": "Remind to read docs at session start.",
"action": "print-reminder",
"message": "Read AGENTS.md before acting."
}
]
}
Pack with a capability
Valid. capabilities[i] needs type (one of memory/tasks/wiki/graph/design/system-map), store ("org" or "repo"), and method (a slug, optionally +-joined for a modifier like "analyze+llm"). At most one memory capability per store may use method "files" or "native" (they'd both own /remember), and at most one design capability per store.
{
"id": "capability-pack",
"version": "1.0.0",
"title": "Capability Pack",
"summary": "Declares a wiki capability.",
"context": {
"markdown": "## Capability pack\n"
},
"capabilities": [
{
"type": "wiki",
"store": "repo",
"method": "baselane"
}
],
"agents": [],
"commands": [],
"hooks": []
}
Pack with scope, attribution, and onboarding
Valid. scope is "repo" (default), "developer", or "both". attribution (source/url/license) credits an imported pack's origin. onboarding[i] needs a unique id, title, description, and an optional command shown (never executed) to the developer post-install.
{
"id": "attributed-pack",
"version": "2.1.0",
"title": "Attributed Pack",
"summary": "Imported from an external skills repo, with an onboarding step.",
"context": {
"markdown": "## Attributed pack\n"
},
"scope": "both",
"attribution": {
"source": "example/skills-repo",
"url": "https://github.com/example/skills-repo",
"license": "MIT"
},
"onboarding": [
{
"id": "first-run",
"title": "Run the CLI once",
"description": "Confirm the pack installed cleanly.",
"command": "baselane drift"
}
],
"agents": [],
"commands": [],
"hooks": []
}
INVALID — id is not a lowercase slug
Invalid. Rejected. `id` must match a lowercase slug pattern (letters, digits, dashes, starting with a letter or digit) — validatePack rejects capitals, spaces, or underscores outright.
{
"id": "Not A Slug!",
"version": "1.0.0",
"title": "Bad Id Pack",
"summary": "id is not a valid slug.",
"context": {
"markdown": "## Bad id\n"
},
"agents": [],
"commands": [],
"hooks": []
}