Schema reference
Three TOML file types, all kebab-case on the wire. See DESIGN.md §2 for the full three-tier merge semantics.
Workspace file (*.portagenty.toml)
Section titled “Workspace file (*.portagenty.toml)”The prefix before .portagenty.toml is required — portagenty.toml
by itself is the per-project file, not a workspace file.
# Requiredname = "Agentic stuff"
# Optional — stable identity across folder moves and environments.# Auto-generated by pa init; survives git clone. See DESIGN §11.id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
# Optional — overrides the global default multiplexermultiplexer = "tmux" # or "zellij"
# Optional — projects this workspace covers. Paths accept ~ and ${VAR}.projects = ["~/code/portagenty", "./cyberbase"]
# Optional (auto-maintained) — historical locations the workspace# lived at before it was moved. pa auto-appends on walk-up# re-registration; external tools (portaconv) read this to bridge# state authored at the old path.previous_paths = ["/home/cybersader/code/old-location"]
# Optional — session list. Name collisions resolve workspace-wins.[[session]]name = "claude" # requiredcwd = "~/code/portagenty" # required, supports ~, ${VAR}, relativecommand = "claude" # requiredkind = "claude-code" # optional; see belowenv = { ANTHROPIC_LOG = "debug" } # optional; per-session env vars
[[session]]name = "tests"cwd = "."command = "cargo nextest run"Display name. Also the sanitized base for the mpx session name
([^a-zA-Z0-9_-] → _, clamp 50 chars).
Stable workspace identity (UUIDv4). Auto-generated by pa init and
the onboarding wizard. Optional — old workspace files without one
continue to work. The ID is designed to be committed alongside the
file so external tools (like claudecode-project-sync) can track a
workspace across folder moves and cross-environment access.
multiplexer
Section titled “multiplexer”"tmux" or "zellij". "wezterm" parses but fails at launch time
with a clear “use tmux or zellij” message; see
roadmap rationale.
projects
Section titled “projects”Paths to project roots. Resolved against the workspace file’s
directory for relative entries; ~ expands to $HOME; ${VAR}
expands to the env var.
previous_paths
Section titled “previous_paths”Historical on-disk locations this workspace lived at before. You
don’t write this field by hand — pa auto-appends to it when
walk-up discovery finds the workspace’s stable id previously
registered at a different path (i.e. you moved the folder). The
entries are parent directories, not workspace file paths, because
external tools (portaconv) key conversation histories by the
process cwd, not by the TOML file.
The field uses snake_case on the wire — a deliberate break with
portagenty’s otherwise-kebab-case convention, so the contract with
portaconv (and any other downstream tool reading this field) stays
stable and agent-friendly. Safe to commit alongside id and
projects.
[[session]]
Section titled “[[session]]”Array-of-tables. Order is preserved and drives the default TUI
selection order + pa claim’s default session.
name(required) — unique within the workspace.cwd(required) — absolute,~-prefixed,${VAR}-templated, or relative to the workspace file’s directory.command(required) — the shell command. Runs as-is under a shell, so pipes/redirections work. Caveat: multiplexers spawn commands under a non-interactive shell, which means~/.bashrc/~/.zshrcaliases and functions are NOT loaded. Acommand = "ccry"that resolves toclaude --continuein your interactive shell will fail in a pa session (“command not found” → session immediately exits). Write the literal command ("claude --continue") or promote your alias to a real binary onPATH(see the session commands section below).kind(optional) — one ofclaude-code,opencode,editor,dev-server,shell,other. Drives the TUI’s per-row glyph (display-only in v1.x).env(optional) — string-to-string map. Applied viatmux -e KEY=VAL(tmux) orenv KEY=VAL ... bash -c "<cmd>"in the generated layout (zellij). Iteration order is alphabetical for deterministic diffs.
Per-project file (portagenty.toml at a project root)
Section titled “Per-project file (portagenty.toml at a project root)”A lighter-weight file a project can ship to advertise its own
sessions. Merged into any workspace that references the project via
projects = [...].
[[session]]name = "tests"cwd = "."command = "cargo nextest run"# kind + env work here too, same as workspace sessions.No top-level fields yet — the project’s identity is implicit from the file’s location. Per-project sessions lose to workspace-level sessions on name collision.
Global config ($XDG_CONFIG_HOME/portagenty/config.toml)
Section titled “Global config ($XDG_CONFIG_HOME/portagenty/config.toml)”Machine-local. Not committed. Points at workspaces you open often and sets your default multiplexer.
default-multiplexer = "tmux"
[[project]] # optionalpath = "~/code/portagenty"tags = ["rust", "agentic"]
[[workspace]] # optionalpath = "~/workspaces/agentic.portagenty.toml"default-multiplexer
Section titled “default-multiplexer”"tmux" or "zellij". Fallback when a workspace file doesn’t pin
one. Defaults to "tmux" if unset.
[[project]]
Section titled “[[project]]”Global project registry (optional). tags is recognized by the
loader but the filter view that uses it is still on the roadmap.
[[workspace]]
Section titled “[[workspace]]”Known workspace files — populates (eventually) a TUI home screen selector.
State file ($XDG_STATE_HOME/portagenty/state.toml)
Section titled “State file ($XDG_STATE_HOME/portagenty/state.toml)”Written by pa on every launch. Machine-local, not committed. Not
usually something you edit by hand; schema documented here for
completeness.
[[recent]]workspace-file = "/home/u/code/my.portagenty.toml"session-name = "claude"launched-at-unix = 1700000000Bounded to 50 entries (most-recent first). Dedupes on (workspace, session) so the same session hitting the top twice doesn’t stack.
Session commands: aliases vs real binaries
Section titled “Session commands: aliases vs real binaries”A session’s command = "..." is executed under a non-interactive
shell spawned by the multiplexer (bash -c "<cmd>" under tmux,
a similar path under zellij). Non-interactive shells do NOT source
~/.bashrc / ~/.zshrc — so shell aliases and shell functions
defined there are invisible to pa sessions.
If you have alias ccry='claude --continue' in ~/.bashrc and
write:
[[session]]name = "claude"command = "ccry" # ← WRONG — non-interactive shell can't find thiskind = "claude-code"…the session will launch, the shell will error with ccry: command not found, the process will exit immediately, and the multiplexer
will close the pane. From the user’s perspective: a flash of
something, then they’re back in their parent shell.
Three ways to fix it
Section titled “Three ways to fix it”1. Write the literal command in the TOML.
command = "claude --continue"Simplest. Matches what ccry expands to. Downside: on a project
with no prior Claude conversation, claude --continue errors on
first launch. Works best for projects that have already been
“seeded” with a session.
2. Use command = "claude" + pa’s --resume flag.
command = "claude"kind = "claude-code"Then launch with pa launch claude --resume (or the bundled alias
plr claude via pa snippets install pa-aliases). pa’s kind-aware
--resume transform appends --continue only at invocation time,
so fresh launches work and continued launches work — one TOML
handles both. Takeover-claim version: pa claim claude --resume
(or pcr claude).
3. Promote the alias to a real binary on PATH.
mkdir -p ~/.local/bincat > ~/.local/bin/ccry <<'EOF2'#!/usr/bin/env bashexec claude --continue "$@"EOF2chmod +x ~/.local/bin/ccryNow ccry is a real executable — interactive shells, pa sessions,
cron, any process on PATH can run it. You can keep the shell alias
too or delete it (the binary replaces the alias for interactive use
once PATH prefers ~/.local/bin). Generally the cleanest approach
for shortcuts you want available everywhere.
Why not auto-source ~/.bashrc?
Section titled “Why not auto-source ~/.bashrc?”Tempting, but risky: sourcing user rc files at session spawn
imports env vars (PATH mutations, custom PS1, etc.) that can
fight the multiplexer’s own conventions, shadow the session’s
declared env, or break reproducibility across devices. pa’s
position: the workspace TOML is the single source of truth for
what a session does; don’t let a user’s interactive rc file
silently influence committed workspace behavior.