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:
$ palm installx palm.yaml is in the 0.1 format palm migrate$ palm migrate --dry-runtargets: [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/skillsi skill tdd: claude gets its own copy in .claude/skillsi skill handoff: claude gets its own copy in .claude/skillsi 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 migratei palm.yaml: source mattpocock/skills added from ~/.palm/config.yaml, needed by 2 entries; commit iti palm.yaml: source mattpocock-2c0db90 added from ~/.palm/config.yaml, needed by 1 entry; commit iti 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/skillsi skill grill-me: claude gets its own copy in .claude/skillsi skill handoff: claude gets its own copy in .claude/skillsi skill tdd: claude gets its own copy in .claude/skills~ .gitignore: .palm/ is now .palm/local/, so .palm/assets/ is committedCommit 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 limitsno 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.yamlBefore you start
Section titled “Before you start”- Commit the current state, so
git diffshows exactly what the migration changed. - Upgrade palm with
npm install -g @paliontech/palm@0.2. palm 0.3 no longer haspalm migrate. - Keep
~/.palm/config.yamlin place until every project is migrated. palm reads its repository list once per project.
-
Preview the migration.
Terminal window palm migrate --dry-runpalm prints the new
palm.yaml, the files it would change and the programs that need your consent. Nothing is written. Add--reviewto page every script those programs run. -
Migrate.
Terminal window palm migratepalm 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 athen:line. Thethen:line is the same command with--allow-exec. -
Read the check.
palm migrateends by runningpalm checkand prints its result. It exits 1 when the check fails, so a migration never reports success over a broken setup. -
Commit what palm lists.
Terminal window git statusgit add -Agit 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.
What palm migrate converts
Section titled “What palm migrate converts”| 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.
The global scope
Section titled “The global scope”palm migrate -gUnder -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.
Old commands and flags
Section titled “Old commands and flags”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 |