Skip to content

How palm reads a repository

palm scans a source when it first fetches a commit. The scan finds every entity the repository offers, and palm caches the result as the source’s index, keyed by the commit. Authors publish in many layouts, and palm reads them with no palm-specific file.

Terminal window
palm install anthropics/claude-plugins-official
palm describe source anthropics/claude-plugins-official

The first command lists the index and saves nothing. The second shows how palm read a declared source.

~/project
$ palm describe source anthropics/claude-plugins-official
source anthropics/claude-plugins-official
url https://github.com/anthropics/claude-plugins-official.git
ref main
sha bc94689
detected marketplace
installed 1
offers 2 skills, 1 agent, 1 hook, 3 MCP servers, 3 plugins
Warnings
! anthropics/claude-plugins-official: plugin clangd-lsp: lspServers not supported by palm (ignored)
! anthropics/claude-plugins-official: plugin "clangd-lsp" at plugins/clangd-lsp has no installable components; skipped
! anthropics/claude-plugins-official: remote plugin "42crunch" (https://github.com/42Crunch-AI/claude-plugins.git (plugins/api-security-testing)@faf5305385de) not fetched: declare it: palm install 42Crunch-AI/claude-plugins/plugins/api-security-testing#faf5305385de8afed9468904e8639be737aff39e <names>
! anthropics/claude-plugins-official: remote plugin "agentforce-adlc" (https://github.com/SalesforceAIResearch/agentforce-adlc.git@09bf1539d41f) not fetched: declare it: palm install SalesforceAIResearch/agentforce-adlc#09bf1539d41f9ff355ba3eb5d05d4a75813423bb <names>
! anthropics/claude-plugins-official: plugin "npm-plugin": unsupported source npm:@acme/plugin; skipped

detected names the rule that matched, here marketplace. The index warnings list what the scan found and will not install, each with the reason or the command that installs it from its own repository. A listing prints the notes you act on in full, such as a file the layout misses, and counts the rest in one line. palm describe source <source> prints them all, for a source palm.yaml declares or one you only typed.

The first rule that matches decides how palm reads the repository.

Order Rule Reported as Applies when
1 Layout descriptor descriptor the source has a layout: in palm.yaml
2 APM package apm the root has an apm.yml and an .apm/ folder
3 Marketplace marketplace the repository has a marketplace.json for Claude Code, Cursor, Copilot or Codex
4 Plugin manifest plugin-manifest the root has a Claude Code, Cursor, Agent Plugins, Codex or Gemini CLI plugin manifest
5 Conventions convention none of the above, so palm looks for SKILL.md, agents/, rules/, hooks/ and similar paths

A marketplace entry with a relative path becomes a plugin, scanned at that path. An entry that points back at the source itself is skipped without a warning. A plugin manifest picks one format and never merges two. The scan rules list every file name and pattern.

Warning Meaning
remote plugin "<name>" ... not fetched A marketplace entry points at another repository. palm prints the palm install line that declares it as a source of its own.
lspServers are not installed by palm The plugin has a part palm does not install.
npm sources are not supported A marketplace entry comes from a place palm cannot fetch.
does not declare A plugin manifest omits skills that sit in its folder. palm indexes them as standalone skills.
not a valid slug A skill’s name cannot be a folder name. palm uses the slugified folder name.
hidden-unicode A file holds invisible characters. See the security model.
unresolvable-reference A hook or MCP command names a script that is not in the source. palm refuses that entity.
secret-literal An MCP value or hook command holds something shaped like a secret. palm writes a reference instead.
not indexed Files shaped like agents, hooks or MCP configs sit outside the folders palm scans. The line names the layout: that indexes them, such as add layout: { agents: [people/*.md] }.
skipped (ignored name ...) A SKILL.md sits under a folder name palm ignores, such as skills/test. The line names the layout: that includes it.
matches nothing A glob in your layout: matched no file.

palm never fetches another repository on its own. You decide whether it becomes a source.

After the rules run, palm resolves every path a hook or MCP command names. ${CLAUDE_PLUGIN_ROOT} and its variants, ${extensionPath} and relative paths such as ./scripts/check.sh are resolved against the source. The directory that holds the hook definition, plus every file a command names, becomes the entity’s closure, the set of files palm copies to .palm/assets/.

palm also reads each script once for literal paths, such as $CLAUDE_PLUGIN_ROOT/skills/x/SKILL.md, ../x or "$(dirname "$0")/../x". Files found that way join the closure, and the consent review lists them as reads:. A read palm cannot resolve prints a warning at install, because the script may fail without it.

A reference that resolves to nothing, such as $(...), ~/... or a missing file, refuses the entity and prints the line.

x hook do-stop-guard from agency: cannot relocate "./scripts/do-stop-guard.sh"
no such file under .apm/hooks/ in source agency at 8145505
a hook command must name a file relative to its hooks.json, ${CLAUDE_PLUGIN_ROOT}, or the project dir

palm never merges a command it could not resolve, so a clone without palm never runs a script that is not there.

Auto-detection skips folders that hold tests, fixtures, evals, examples, templates, docs and build output. It also skips install outputs, such as .claude/skills or .agents/skills, because another tool committed those copies, and any output folder it reaches through a symlink. Root AGENTS.md, CLAUDE.md and GEMINI.md guide the repository’s own contributors, so palm skips them too. Inside a skill’s folder those files are the skill’s own content, and palm copies them with it. A skill copy leaves out tests and fixtures, harness folders and .env files, as the scan rules list.

Only the top-most SKILL.md in a folder tree is a skill. Everything below a skill’s folder is that skill’s content, including a nested references/x/SKILL.md.

palm includes other dot folders. openai/skills keeps its skills in skills/.curated, and palm finds them.

A layout descriptor tells palm where a source keeps its entities. It goes on the source in palm.yaml, and palm records it in the lock so every machine builds the same index.

palm.yaml
sources:
openai/skills:
ref: main
layout: { skills: ["skills/.curated/*"] }
skills: [gh-address-comments]

Write one when a repository keeps entities in folders palm skips, or when you want only part of it. The layout descriptor reference lists every key.