Install for six harnesses
On many teams one developer uses Claude Code, another uses Cursor, and a CI job runs Codex. Each harness wants the same agent (subagent) in a different folder and format. palm writes all six from one command, records every file in one lock, and tells you what each harness could not take.
When you finish, the agent exists once per harness format and the skill twice:
Folder.agents/
Folderskills/
Foldersdk-helper/
- …
Folder.claude/
Folderagents/
- agent-sdk-verifier-py.md
Folderskills/
Foldersdk-helper/
- …
Folder.codex/
Folderagents/
- agent-sdk-verifier-py.toml
Folder.cursor/
Folderagents/
- agent-sdk-verifier-py.md
Folder.gemini/
Folderagents/
- agent-sdk-verifier-py.md
Folder.github/
Folderagents/
- agent-sdk-verifier-py.agent.md
Folder.opencode/
Folderagents/
- agent-sdk-verifier-py.md
- palm.lock.yaml
- palm.yaml
The skill appears twice because Claude Code reads .claude/skills, which Cursor reads too, and the other four share .agents/skills.
The sessions on this page ran against palm’s fixture that mirrors anthropics/claude-plugins-official.
Before you start
Section titled “Before you start”- The project is a git repository.
- You accept that the Gemini CLI and OpenCode placements are unverified. They follow each harness’s documentation and source, checked on 2026-09-28, and have not run against a live CLI in palm’s tests yet.
-
Declare all six targets.
Terminal window palm init --target claude,codex,copilot,cursor,gemini,opencode -
Install the agent and the skill it uses.
Terminal window palm install anthropics/claude-plugins-official agent-sdk-verifier-py sdk-helper~/project $ palm install anthropics/claude-plugins-official agent-sdk-verifier-py sdk-helperi agent agent-sdk-verifier-py preloads mcp context7, not installed: palm install anthropics/claude-plugins-official mcp:context7i ref main saved to palm.yaml; edit ref: to pin a tag+ skill sdk-helper .agents/skills/sdk-helper/, .claude/skills/sdk-helper/ 2 files from anthropics/claude-plugins-official mainclaude gets its own copy in .claude/skillscursor reads .claude/skills; no second copy+ agent agent-sdk-verifier-py .claude/agents/agent-sdk-verifier-py.md, .codex/agents/agent-sdk-verifier-py.toml +4 6 files from anthropics/claude-plugins-official main.codex/agents/agent-sdk-verifier-py.toml: dropped model (sonnet), tools, skills, mcpServers, color (not supported by Codex).github/agents/agent-sdk-verifier-py.agent.md: dropped model (sonnet), tools: Bash(python -m pytest:*) restriction (all of execute), mcpServers, skills, color (not supported by GitHub Copilot).cursor/agents/agent-sdk-verifier-py.md: dropped model (sonnet), tools, skills, mcpServers, color (not supported by Cursor).gemini/agents/agent-sdk-verifier-py.md: dropped model (sonnet), tools: Bash(python -m pytest:*) restriction (all of run_shell_command), skills, color (not supported by Gemini CLI).opencode/agents/agent-sdk-verifier-py.md: dropped model (sonnet), color (green), tools: Bash(python -m pytest:*) restriction (all of bash), skills (not supported by OpenCode)2 installed. Commit palm.yaml, palm.lock.yaml, .claude/, .codex/, .cursor/, .gemini/, .github/, .opencode/ and .agents/ together.Each
iline names what one harness has no place for, such as a model field for Codex or an argument restriction for Copilot. palm records the same notes in the lock, andpalm describe agent-sdk-verifier-pyshows them later. -
Compare the formats palm wrote.
~/project $ cat .claude/agents/agent-sdk-verifier-py.md---name: agent-sdk-verifier-pydescription: "Use this agent to verify a Python Agent SDK app. Examples: <example>Context: user created an app</example>"model: sonnettools: Read, Grep, Glob, Bash(python -m pytest:*)skills:- sdk-helpermcpServers:- context7color: green---You are a Python Agent SDK application verifier.$ cat .codex/agents/agent-sdk-verifier-py.tomlname = "agent-sdk-verifier-py"description = "Use this agent to verify a Python Agent SDK app. Examples: <example>Context: user created an app</example>"developer_instructions = """You are a Python Agent SDK application verifier."""$ cat .github/agents/agent-sdk-verifier-py.agent.md---name: agent-sdk-verifier-pydescription: "Use this agent to verify a Python Agent SDK app. Examples: <example>Context: user created an app</example>"tools:- read- search- execute- context7/*---You are a Python Agent SDK application verifier.Harness File What palm changes Claude Code .claude/agents/<name>.mdnothing for a Claude Code agent; from another format, keys Claude Code does not define are dropped with a note Codex .codex/agents/<name>.tomlTOML with name,descriptionanddeveloper_instructionsGitHub Copilot .github/agents/<name>.agent.mdCopilot tool names such as readandexecute, MCP servers ascontext7/*Cursor .cursor/agents/<name>.mdreadonly: trueonly when no tool in the list writes files or runs commandsGemini CLI .gemini/agents/<name>.mdstrict frontmatter with kind: localand Gemini tool namesOpenCode .opencode/agents/<name>.mdmode: subagentand apermissionmap that denies what the tool list leaves out -
Install kinds that some harnesses cannot hold.
Terminal window palm install anthropics/claude-plugins-official new-sdk-apppalm install anthropics/claude-plugins-official hook:agent-sdk-dev --dry-run~/project $ palm install anthropics/claude-plugins-official new-sdk-appi ref main saved to palm.yaml; edit ref: to pin a tag+ skill new-sdk-app .agents/skills/new-sdk-app/, .claude/skills/new-sdk-app/ 2 files from anthropics/claude-plugins-official mainfrom command new-sdk-app.md: installed as a skill, which a harness may also load on its own when it looks relevantclaude gets its own copy in .claude/skillscursor reads .claude/skills; no second copy1 installed. Commit palm.yaml, palm.lock.yaml, .agents/ and .claude/ together.$ palm install anthropics/claude-plugins-official hook:agent-sdk-dev --dry-runThis install adds 1 program that will run on your machine.1. hook agent-sdk-dev from anthropics/claude-plugins-official (commit bc94689, main, 2026-09-28)PreToolUse Write|Edit CLAUDE_PLUGIN_ROOT="$CLAUDE_PROJECT_DIR"/.palm/assets/anthropics__claude-plugins-official/agent-sdk-dev/plugins/agent-sdk-dev python3 "$CLAUDE_PROJECT_DIR"/.palm/assets/anthropics__claude-plugins-official/agent-sdk-dev/plugins/agent-sdk-dev/hooks/guard.pycursor: CURSOR_PLUGIN_ROOT="$CURSOR_PROJECT_DIR"/.palm/assets/anthropics__claude-plugins-official/agent-sdk-dev/plugins/agent-sdk-dev CLAUDE_PLUGIN_ROOT="$CURSOR_PROJECT_DIR"/.palm/assets/anthropics__claude-plugins-official/agent-sdk-dev/plugins/agent-sdk-dev python3 "$CURSOR_PROJECT_DIR"/.palm/assets/anthropics__claude-plugins-official/agent-sdk-dev/plugins/agent-sdk-dev/hooks/guard.pytargets: claude (.claude/settings.json), codex (.codex/hooks.json), copilot (.github/hooks/agent-sdk-dev.json), cursor (.cursor/hooks.json), gemini (.gemini/settings.json)skipped: opencode (OpenCode hooks are JS plugins; hook agent-sdk-dev not installed)scripts: 2 files, 321 B -> .palm/assets/anthropics__claude-plugins-official/agent-sdk-dev/ (committed with your repo)plugins/agent-sdk-dev/hooks/guard.py 644 12 B sha256:3a66aebd... 1 more (--review shows every script)palm never runs this itself. If you say yes, its hash goes into palm.lock.yaml,so teammates and CI install it without being asked; any change asks again.+ would install hook agent-sdk-dev .github/hooks/agent-sdk-dev.json, .palm/assets/anthropics__claude-plugins-official/agent-sdk-dev/plugins/agent-sdk-dev/ +4 3 files +4 merged from anthropics/claude-plugins-official mainOpenCode hooks are JS plugins; hook agent-sdk-dev not installedopencode: skippeddry run: 1 would install; nothing written.The command file installs as a skill everywhere, with a note about
$ARGUMENTS. A harness without skill commands loses the/new-sdk-appcall, and the note says so too. The hook lands in five harnesses. OpenCode has no declarative hooks, so palm skips it there and says so.
These are the combinations palm skips.
| Kind | Harness | Scope | Why |
|---|---|---|---|
| hook | OpenCode | both | OpenCode hooks are JavaScript plugins |
hook with a matcher that has arguments, such as Bash(git commit*) |
GitHub Copilot | both | Copilot matchers cannot hold arguments |
| instruction | Cursor | global | Cursor keeps user rules in its settings |
An on-request or manual rule is not skipped in Claude Code and OpenCode, but installs always-on there until 0.3, with a notice per rule.
palm describe target <target> prints where each kind goes for one harness, skips included.
palm describe target opencodeOne entity, one carrier
Section titled “One entity, one carrier”Several harnesses read the same files, and palm keeps each entity loaded once per harness.
With claude and cursor, a skill lives only in .claude/skills, because Cursor reads it there.
Codex reads instructions from AGENTS.md, which Cursor, OpenCode and Copilot also read.
palm 0.2 still writes Cursor’s own .cursor/rules file too, and palm check warns about that double load. palm 0.3 records one carrier per harness and drops the second copy.
The skill copies palm chose above never warn, because palm check uses the same facts as the install.
Check the result
Section titled “Check the result”palm describe agent-sdk-verifier-pypalm checkpalm describe lists the file each target received and every note palm recorded.
Next steps
Section titled “Next steps”- Share a team baseline, so every developer gets the same six harnesses.
- The targets matrix lists every path for every kind.
- Why native files per harness explains the design.