Skip to content

Migrate from palm 0.1

palm 0.2 declares sources in palm.yaml instead of ~/.palm/config.yaml, writes lock version 3 and commits hook scripts. palm migrate converts a project in one command and adopts every file that already matches. It ships with 0.2 only and is removed in 0.3.

When you finish, the project runs on 0.2, palm check passes, and palm has listed every file it changed:

~/project
$ palm install
x palm.yaml is in the 0.1 format
palm migrate
$ palm migrate --dry-run
targets: [claude, codex]
sources:
mattpocock/skills:
ref: v1.2.3
alias: mattpocock
skills: [tdd, handoff]
mattpocock-2c0db90:
url: https://github.com/mattpocock/skills.git
ref: v1.2.0
skills: [grill-me]
- would remove .claude/skills/grill-me/agents/openai.yaml: palm 0.1 copied it; palm 0.2 writes agents/openai.yaml only into .agents/skills
- would remove .claude/skills/handoff/agents/openai.yaml: palm 0.1 copied it; palm 0.2 writes agents/openai.yaml only into .agents/skills
- would remove .claude/skills/tdd/agents/openai.yaml: palm 0.1 copied it; palm 0.2 writes agents/openai.yaml only into .agents/skills
i skill tdd: claude gets its own copy in .claude/skills
i skill handoff: claude gets its own copy in .claude/skills
i skill grill-me: claude gets its own copy in .claude/skills
Warnings
! skill grill-me was pinned to v1.2.0; palm.yaml declares source mattpocock-2c0db90 for it at that ref (mattpocock/skills tracks v1.2.3), as --as mattpocock-2c0db90 would
$ palm migrate
i palm.yaml: source mattpocock/skills added from ~/.palm/config.yaml, needed by 2 entries; commit it
i palm.yaml: source mattpocock-2c0db90 added from ~/.palm/config.yaml, needed by 1 entry; commit it
i keep ~/.palm/config.yaml until every project is migrated; palm migrate reads it
~ palm.yaml and palm.lock.yaml now use the palm 0.2 format
- removed .claude/skills/grill-me/agents/openai.yaml: palm 0.1 copied it; palm 0.2 writes agents/openai.yaml only into .agents/skills
- removed .claude/skills/handoff/agents/openai.yaml: palm 0.1 copied it; palm 0.2 writes agents/openai.yaml only into .agents/skills
- removed .claude/skills/tdd/agents/openai.yaml: palm 0.1 copied it; palm 0.2 writes agents/openai.yaml only into .agents/skills
i skill grill-me: claude gets its own copy in .claude/skills
i skill handoff: claude gets its own copy in .claude/skills
i skill tdd: claude gets its own copy in .claude/skills
~ .gitignore: .palm/ is now .palm/local/, so .palm/assets/ is committed
Commit palm.yaml, palm.lock.yaml, .claude/ and .gitignore together.
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)
✓ in-repo sources match 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 are committed
✓ 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 limits
no problems
Warnings
! skill grill-me was pinned to v1.2.0; palm.yaml declares source mattpocock-2c0db90 for it at that ref (mattpocock/skills tracks v1.2.3), as --as mattpocock-2c0db90 would
$ git status --short
D .claude/skills/grill-me/agents/openai.yaml
D .claude/skills/handoff/agents/openai.yaml
D .claude/skills/tdd/agents/openai.yaml
M .gitignore
M palm.lock.yaml
M palm.yaml
  • Commit the current state, so git diff shows exactly what the migration changed.
  • Upgrade palm with npm install -g @paliontech/palm@0.2. palm 0.3 no longer has palm migrate.
  • Keep ~/.palm/config.yaml in place until every project is migrated. palm reads its repository list once per project.
  1. Preview the migration.

    Terminal window
    palm migrate --dry-run

    palm prints the new palm.yaml, the files it would change and the programs that need your consent. Nothing is written. Add --review to page every script those programs run.

  2. Migrate.

    Terminal window
    palm migrate

    palm validates everything and asks for consent before it writes a single file. If the project has hooks or stdio MCP servers, it shows each one and asks once. Your yes goes into the new lock, so teammates are not asked again. Without a terminal it stops before any write and prints a review: and a then: line. The then: line is the same command with --allow-exec.

  3. Read the check.

    palm migrate ends by running palm check and prints its result. It exits 1 when the check fails, so a migration never reports success over a broken setup.

  4. Commit what palm lists.

    Terminal window
    git status
    git add -A
    git commit -m "Migrate to palm 0.2"

    The report names every file it changed, and every output folder palm 0.1 left out of git that you now commit.

palm 0.1 palm 0.2
a repository registered in ~/.palm/config.yaml a source in palm.yaml, keyed owner/repo for GitHub, else by the alias, with its URL, root, layout and locked ref
a local origin with a path and a root an in-repo source at ./<path>/<root>
a registration alias that differs from the key alias: on the source
tdd@mattpocock#v1.2.3 in a kind list tdd under the source’s skills:; the ref moves to the source
entries of one source pinned to different refs the most common ref wins, and palm names the others
a plugin with uninstalled members a plugins: entry with exclude:
a command entry a skill of the same name
an MCP server from the MCP registry an entry under mcp:, copied from the rendered .mcp.json or harness file
an entry installed with --target beyond the project’s set per-entry targets:, with a note
an entry from ~/.palm/mine a warning that names the folder to copy the file into, ./agent-kit or, under -g, ~/.palm/kit
a hook named after its 0.1 origin the 0.2 name, matched by source and entity path, with its trust carried over; palm prints the rename
.palm/hooks/<name>/, ignored by git .palm/assets/<source>/<name>/, committed; .palm/hooks/ is removed after the move
a hook from an in-repo source no copy: it runs in place from your repository, and palm says so
.palm/ in .gitignore .palm/local/ and palm.local.yaml
comments in palm.yaml kept above the nearest key that survives, or under # from palm 0.1: at the end
lock version 1 or 2 lock version 3

After the conversion palm runs a bare install, which adopts every file that already matches and restores any that are missing. A file palm 0.1 copied into a skill folder that 0.2 no longer writes there, such as agents/openai.yaml in .claude/skills/<name>/ (0.2 writes it only into .agents/skills), is removed while it still matches the source, and palm says so. It never deletes or unlinks a harness file such as .mcp.json or .claude/settings.json. An MCP server or hook palm 0.1 merged into .mcp.json or .cursor/mcp.json is adopted by its key, your own entries stay, and a symlinked file stays a link. The report ends with the check result and the files to commit.

Terminal window
palm migrate -g

Under -g, palm rewrites absolute paths in ~/.palm/palm.lock.yaml as tokens, such as <claude>/skills/tdd, so the lock can live in a dotfiles repository. A path written under another machine’s home also becomes a token when it matches a harness home layout. palm writes through a symlinked ~/.palm/palm.yaml or harness config and keeps the link. It leaves ~/.palm/config.yaml in place and says you can delete it once every project is migrated. In project scope it says to keep that file until every project is migrated, because palm migrate reads it.

The 0.1 grammar keeps working for one release as hidden aliases.

palm 0.1 palm 0.2
palm install skill tdd@mattpocock palm install mattpocock/skills tdd; the alias resolves against the declared sources by repository name
palm install skill tdd@mattpocock#v1.2.0 palm install mattpocock/skills#v1.2.0 tdd
palm install origin mattpocock/skills palm install mattpocock/skills; palm prints the new form, one line per repository, and runs it
palm uninstall skill tdd palm remove tdd
palm doctor, palm audit palm check
palm outdated palm update --dry-run
palm why, palm find palm describe <name>, palm describe <path>
palm search, palm install mcp <registry name> no registry: paste the server’s README block with palm install mcp --snippet -; see Add MCP servers
palm config get, palm config set none; the global targets live in ~/.palm/palm.yaml
palm create wizard, ~/.palm/mine palm create <kind> <name> into ./agent-kit

palm doctor, audit, outdated, why, find, search and config print one line naming the replacement and exit 2.

Removed flags print their replacement too.

palm 0.1 flag palm 0.2
palm install --frozen palm check; the old flag prints it and runs it
--from <repo>#<ref> <names> palm install <repo>#<ref> <names>
--ref <ref> #<ref> after the source, such as palm install mattpocock/skills#v1.2.3 tdd
--project nothing: project scope is the default
--alias <name> --as <name>
--target on palm install --targets; both spellings work on palm install and palm init