Files

Personal content

Everything else in Panama is the desktop. This directory is the person using it.

The problem it solves is small and annoying: an agent skill, an SSH host alias or a set of expansion triggers is worth having on every machine you own, but none of it belongs in the shared configuration, and keeping it in a second repository means remembering to update two things. So it lives here, tracked, and one file says where each piece goes.

What is in here

Path Goes to Why
agents/AGENTS.md ~/.claude/CLAUDE.md, ~/.codex/AGENTS.md, ~/.config/opencode/AGENTS.md Three tools, one file. These were byte-identical copies before this, waiting to disagree.
agents/skills/ ~/.agents/skills, ~/.claude/skills Personal skills live once in the checkout. Both destinations use linkdir so Panama's shipped skills can live beside them. opencode reads both directories itself.
agents/rules/ ~/.claude/rules opencode loads these through instructions in its config, which setup/scripts/link-mcp generates.
agents/commands/ ~/.config/opencode/commands Claude Code carries its commands as plugins, which opencode cannot read. These are the same commands in opencode's own format.
agents/agents/ ~/.config/opencode/agents The same again for subagents.
agents/opencode/config.json read by setup/scripts/link-mcp Not linked. The opencode config is generated from it, because that file also has to carry the MCP servers and their tokens, and a symlink cannot be half written.
ssh/config ~/.ssh/config Host aliases only. Keys are per-machine and are never tracked.
bin/pwswitch ~/.local/bin/pwswitch pwswitch off makes sudo passwordless for an agent session, pwswitch on restores the password.
espanso/identity.yml ~/.config/espanso/match/identity.yml Copied, not linked, because a machine may add its own triggers.

manifest is the authority; this table is a summary of it.

The three kinds

link and copy mean what they say: one symlink, or one copy made only if the destination is empty. linkdir is the third, and it exists because one destination is no longer only ours.

Panama ships its own agent skills now (skills/, linked by setup/scripts/link-skills), and they go to both skill homes. A directory cannot be a symlink to two places, so both personal entries use linkdir: each destination is a real directory, and each child of user/agents/skills/ is linked into it individually.

Two consequences, recorded rather than fixed:

  • A personal skill named like a shipped one shadows it. link-user runs after link-skills and displaces what it finds, so the personal one wins in both skill homes.
  • A new personal skill needs a re-link to appear. The whole-directory link showed a newly created skill instantly; per-child links do not know about a child that did not exist when they were made. Put new shared skills in user/agents/skills/, then run panama update or setup/scripts/link-user. A tool that installs directly into a home skill directory creates a machine-local skill until it is moved into the checkout.

The opencode config is the one destination here that is generated rather than linked or copied. It cannot be a symlink because it has to carry the MCP servers and their tokens, and a token is exactly what cannot live in this repository. So setup/scripts/link-mcp builds the whole file: agents/opencode/config.json supplies everything that is not a secret, agents/mcp/servers supplies the server list, and the machine-local agents/mcp/env supplies the tokens.

The result is ~/.config/opencode/opencode.jsonc, written private and replaced in place. It opens with a comment saying where to edit it, and that comment is the whole warning: hand-edits to the generated file do not survive an upgrade. Put the change in agents/opencode/config.json and it reaches every machine.

Anything already at that path that this stage did not write moves to config/old/, the same promise everything else here makes.

It is off unless you say yes

The installer asks, naming the destinations, and the default is no. Nothing here is linked on a machine that did not answer yes, and the answer is remembered in $XDG_STATE_HOME/panama/user-content so upgrades do not re-ask.

That gating is the whole reason this can be tracked in a repository other people clone. If you are that other person: delete what is in here, put your own in its place, and answer yes. The mechanism is yours, the contents are not.

Adding something

Put the file under user/, add a line to manifest, run:

./setup/scripts/link-user

Anything already at the destination is moved to config/old/ rather than deleted, under a name that says where it came from.

A line can end with linux or darwin to apply only on that OS. The Mac mini is not a Panama desktop, but it runs agents, so it takes the agent half of this directory and skips the SSH config, pwswitch and espanso. Panama's shipped skills describe the Linux desktop, so the Mac runs link-user and link-mcp only, never link-skills.

What does not go in here

Anything secret. This repository is readable by anyone who finds it, and the contract test refuses private keys, tokens and credentials outright. That means no ~/.ssh/id_*, no .credentials.json, no API keys, and no settings.json carrying the names of hosts or people you would rather not publish. Machine state that a tool rewrites on its own does not belong here either; it will churn the git history for no benefit.