Publish your own source
You wrote a skill that turns merged pull requests into release notes, and the next service wants it too.
Start it inside the project with palm create, where every edit is live.
When it proves itself, push the folder as its own repository, tag it, and any project installs it by name.
When you finish, a teammate in another project installs your skill from its tag:
$ palm install acme/agent-kit release-notesi ref ^1.0 saved to palm.yaml (latest tag v1.0.0); edit ref: to track main+ skill release-notes .agents/skills/release-notes/, .claude/skills/release-notes/ 2 files from acme/agent-kit v1.0.0 (claude gets its own copy in .claude/skills)1 installed. Commit palm.yaml, palm.lock.yaml, .agents/ and .claude/ together.$ palm getkind name source ref sha targets files───── ───────────── ────────────── ───────────── ─────── ──────────── ─────skill release-notes acme/agent-kit ^1.0 → v1.0.0 8dcea2c claude,codex 2Before you start
Section titled “Before you start”- A project with targets set, for example
palm init --target claude,codex. - An empty repository on GitHub, or on any git host, for step 4.
-
Create the skill.
Terminal window palm create skill release-notes --description 'Write release notes from the pull requests merged since the last tag.'palm writes a template into
./agent-kit, declares./agent-kitinpalm.yamland installs the skill. It asks nothing and opens no editor.Kind Template skillagent-kit/skills/<name>/SKILL.mdagentagent-kit/agents/<name>.mdinstructionagent-kit/instructions/<name>.mdhookagent-kit/hooks/<name>/hooks.jsonwith an example script--in <dir>picks another folder, and alayout:on that source decides where the template goes. A file that already exists, or a name the source or another source already has, stops withE_CONFLICTbefore palm writes anything. -
Write the skill, and let palm follow.
~/project $ palm create skill release-notes --description 'Write release notes from the pull requests merged since the last tag.'+ wrote agent-kit/skills/release-notes/SKILL.md+ source ./agent-kit → palm.yaml+ skill release-notes .agents/skills/release-notes/, .claude/skills/release-notes/ 2 files (claude gets its own copy in .claude/skills)1 installed. Commit palm.yaml, palm.lock.yaml, agent-kit/, .agents/ and .claude/ together.edit agent-kit/skills/release-notes/SKILL.md, then run: palm install$ cat agent-kit/skills/release-notes/SKILL.md---name: release-notesdescription: Write release notes from the pull requests merged since the last tag.---# Release notesWrite the steps the agent follows when this skill applies.$ printf '\n4. Group the entries by label.\n' >> agent-kit/skills/release-notes/SKILL.md$ palm check✓ manifest and lock agree✓ palm.yaml targets match the lock✓ every entry is rendered✓ every entry is on all its targets✓ generated files match the lock✓ no stray file in a folder palm owns- applied files outside the lock: skipped (global scope only)x 1 in-repo entity changed since the lock✓ no generated path lies inside a source✓ every program palm installed is trusted✓ no foreign command in the hook files palm manages✓ no foreign stdio server in the MCP files palm manages✓ every hook script exists✓ no literal secret in generated files✓ every variable the servers need is set! generated files not committed yet✓ every source is declared✓ no link leaves the scope✓ no hidden Unicode in generated files✓ no harness loads an entity twice✓ no two agents or commands share a name in a harness folder✓ every skill an agent preloads is installed✓ instruction files are within harness limitsx skill release-notes: skill release-notes in source ./agent-kit changed since palm.lock.yaml (content c293a4e → 341192a); fix: palm install, then commit palm.lock.yaml and the files it re-rendered! 2 files (.agents/skills/release-notes/SKILL.md, .claude/skills/release-notes/SKILL.md) are not committed yet (untracked); fix: git add .agents/skills .claude/skills$ palm install~ skill release-notes .agents/skills/release-notes/, .claude/skills/release-notes/ 2 files (claude gets its own copy in .claude/skills)1 re-rendered.The in-repo source is the truth. After an edit,
palm checkfails until you runpalm install, which re-renders the harness copies. Commitagent-kit/, the lock and the generated files together. -
Give it a shape other repositories use.
palm reads a repository without any palm file, so follow the conventions every harness knows.
Put Where skills skills/<name>/SKILL.mdwithnameanddescriptionfrontmatteragents agents/<name>.mdwithnameanddescriptionfrontmatterinstructions instructions/<name>.md,rules/<name>.md,rules/<name>.mdcor<name>.instructions.mdhooks hooks/hooks.json, with scripts next to it referenced as${CLAUDE_PLUGIN_ROOT}/hooks/<file>MCP servers .mcp.jsonwithmcpServersa version a semver tag, or metadata.versionin the frontmatterA
.claude-plugin/plugin.jsonis optional. It lets people select your members as one plugin.A root
hooks/hooks.jsontakes its name from the key the person installing gives your source, such ashook:agent-kit, orhook:acmeafter--as acme. For a name you control, usehooks/<name>/hooks.jsonor a plugin manifest. A relative./script.shin a command is read from the source root, so name scripts as${CLAUDE_PLUGIN_ROOT}/hooks/<file>. The scan rules list every case. -
Copy the folder into its own repository and tag it.
Terminal window cp -R agent-kit ~/src/agent-kitcd ~/src/agent-kitgit init -b maingit add -Agit commit -m "Add the release-notes skill"git remote add github git@github.com:acme/agent-kit.gitgit push -u github maingit tag v1.0.0git push github v1.0.0An undeclared source resolves to its newest tag, and palm writes
ref: ^1.0for the people who install it. Commits afterv1.0.0reach them only when you push the next tag and they runpalm update. -
Switch your own project to the published source.
Terminal window palm remove ./agent-kit release-notespalm install acme/agent-kit release-notesgit rm -r agent-kit./agent-kithad no entries left, so palm dropped it frompalm.yaml. Commit the result.
Check the result
Section titled “Check the result”In another project, a teammate runs one command, as in the session at the top.
palm get shows your tag in the ref column.
To publish a change, commit it, tag v1.1.0 and push the tag.
Each project then runs palm update acme/agent-kit, reviews the plan and commits.
What palm refuses from a source
Section titled “What palm refuses from a source”- A hook command that names a script the repository does not have. Keep scripts inside the repository and reference them relative to the hook file or
${CLAUDE_PLUGIN_ROOT}. - Hidden Unicode such as bidi overrides or tag characters, in any file of an entity.
- A literal secret in an MCP config or hook command. Write
${NAME}instead. A skill that carries a known token shape in a file it copies is refused. A high-entropy value in code only warns, and test folders such astests/andfixtures/are not copied, so a fake key there never refuses. - A skill folder above 200 files or 5 MB, unless the person installing passes
--force. A rootSKILL.mdmakes the whole repository the skill, so keep skills inskills/<name>/. - A symlink that leaves the repository.
palm also warns when a hook script reads a file it cannot resolve.
Refer to such a file by a literal path, such as "$(dirname "$0")/../skills/x/SKILL.md", so palm copies it with the script.
Next steps
Section titled “Next steps”- Scanning and the scan rules show how palm reads a repository.
- Share a team baseline puts your source in every project.
- palm create reference