Tmux pilot role authoring
A library of agent skills for developing with Pi in mind.From the repository description
npx -y skills add r3b1s/pi-dev-skills --skill tmux-pilot-role-authoringAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 23 days oldThe repository was created 23 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
10.2 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it
tmux-pilot Role Authoring
A role is two artifacts:
- A YAML entry under
subagent-roles.<name>in the entry config file —$PI_CODING_AGENT_DIR/tmux-pilot.config.yaml, falling back to~/.pi/agent/tmux-pilot.config.yaml. - An optional agent-definition Markdown document (YAML frontmatter +
instruction body) referenced by the role's
agent-definitionkey.
Config is read at spawn time — edits apply to the next spawn, never to a running agent (widget-style is captured on the record at spawn; startup-scoped widget settings apply next session). Role names are matched case-insensitively at spawn.
The canonical, exhaustively commented schema reference is
tmux-pilot.config.example.yaml in the tmux-pilot repo. Templates:
resources/role-config-template.yaml and
resources/agent-definition-template.md.
Naming and schema rules (hard cutover — no legacy keys)
Every tmux-pilot-owned key is lower-kebab-case; controlled enum values too
(overlay, above-editor). External identifiers keep their spelling (model
IDs, provider IDs like opencode-go, harness IDs, role names, tmux keys like
C-c). Legacy camelCase keys (agentDef, guards, new-worktree,
config-dir, maxTurns, stopKeyCombo, …) are not recognized — they
warn and are ignored. Unknown keys at known scopes warn; role names, model
IDs, harness IDs stay open and never warn.
Part 1 — the YAML role entry
Inheritance model (memorize this first)
Every defaultable field resolves model-level > role-level > subagent-global-defaults > hardcoded:
thinking,provider,harness— all three layers.agent-definition,models— role > global only (no per-model form).modelsis a full replacement: a role with its own list loses all global entries. Nomodels:key → inherit the global list.lifecycle-guardsis a shallow per-field merge (role field > global field > hardcoded), EXCEPTturn-thresholds, which is replaced wholesale — defining any role thresholds discards the global list.worktree-enabled— role > global >false. Not allowed per-model.
Role keys
subagent-roles:
reviewer:
thinking: high # off|minimal|low|medium|high|xhigh|max
provider: opencode-go # pi provider id (default for bare-string models)
harness: pi # pi (default) | cmd | claude-code | codex | hermes
agent-definition: reviewer.md
worktree-enabled: false
models: # ordered fallback — first available wins
- deepseek-v4-flash # bare string: inherits role/global
- claude-sonnet-4-20250514: # object: per-model overrides
provider: anthropic
thinking: high
- mimo-v2.5:
harness: cmd # per-model harness override
lifecycle-guards:
max-turns: 25 # 0 = unlimited (hardcoded default)
grace-turns: 5 # extra turns past max before forced stop
session-file-timeout-ms: 60000
max-runtime-ms: 0 # 0 = disabled (default) — recommended
staleness-timeout-ms: 0 # 0 = disabled (default) — recommended
turn-thresholds: # REPLACES the global list wholesale
- at-turns-remaining: 5
action:
type: steer
prompt: >
You have {{turnsRemaining}} turns remaining. Wrap up.
# cleanup-linger-ms: 30000 # keep finished window visible
# harness-config-directory: { path: ~/curated/reviewer, mode: overlay }
# widget-style: { role-color: "#c98f5f", portrait: { glyph: "⚖" } }
# webui-theme: role-pack:inquisitor # web-console presentation only
# sandbox: { enabled: true, filesystem: { write: ["."] } }
Notes that prevent real mistakes:
session-poll-interval-msis global-only (undersubagent-global-defaults.lifecycle-guards) — a role-level value is ignored.- Leave
max-runtime-msandstaleness-timeout-msat 0 unless you specifically want wedge detection; completion is driven by the per-harness lifecycle-end sentinel, and staleness kills agents mid-long-tool-call. - Threshold prompts get
{{turnsRemaining}}and{{agentId}}template variables; the only actiontypeissteer. sandboxmerges per-leaf over the globalsandboxblock; arrays replace wholesale. Linux x64 only, opt-in.
Harness-specific constraints
| Harness | Constraint to respect in the role entry |
|---|---|
pi | Default; full routing support. |
cmd | Full routing; config dir redirect is HOME-based. |
claude-code | Anthropic model ids only (haiku/sonnet/opus/…); provider is ignored — never write one expecting a gateway. |
codex | OpenAI-only; provider ignored with a warning; thinking maps to model_reasoning_effort (off→minimal, xhigh→high); account-global ChatGPT rate limits — max-concurrent-agents is the lever. |
hermes | model/provider map verbatim to -m/--provider; no harness-config-directory support (warned-and-ignored); a user-set hermes max_concurrent_sessions can fail parallel spawns. |
Harness-scoped defaults (stop-key-combo, cleanup-linger-ms,
harness-config-directory) live under harness-global-defaults.<id>, not in
the role; the role-level harness-config-directory / cleanup-linger-ms win
over them when both are set.
Imports
The entry file may imports: other YAML files (paths relative to the
declaring file; globs sorted; maps deep-merge, lists replace, later wins,
entry file wins last). Duplicate role names warn, later declaration wins.
Relative agent-definition paths always resolve from the ENTRY file's
directory, never from the imported file that declared them.
Part 2 — the agent-definition Markdown document
What it is
Runtime role-instruction input. The body is delivered to each new
matching subagent ahead of its task; frontmatter contributes only
description (surfaced in role listings and the web console — every other
frontmatter key is ignored). All current harnesses use prompt-context
delivery: the composed spawn prompt is
[worktree context, if any]
[parent conversation context, if inherited]
# Role Definition
Role: <role>
Source: role|global
--- BEGIN ROLE INSTRUCTIONS ---
<your body, verbatim>
--- END ROLE INSTRUCTIONS ---
# Your Task
<the spawn prompt>
Write the body knowing it lands between those markers: address the agent in second person, define scope/outputs/constraints, and don't restate the task — the task follows it.
Shape
---
description: One-line summary shown in role listings and the web console.
---
You are the <role> agent. <instructions…>
Frontmatter is optional — a plain body with no --- block is valid. If the
file DOES start with ---, the frontmatter must be well-formed:
- Opening
---on its own line, closing---on its own line. - Content between them must parse as a YAML mapping (not a list/scalar).
Validation (spawn-rejecting — fail closed)
A configured definition that is missing, unreadable, not a regular file,
not valid UTF-8, larger than 64 KiB, has malformed frontmatter, or has an
empty body rejects the spawn before any tmux window is created, with a
RoleDefinitionError naming role, source, reference, and resolved path. There
is no fall-through to "spawn without instructions." The document is captured
immutably (content + sha256) at spawn — editing the file never affects a
running agent.
When debugging a rejected spawn, check in order: file exists at the resolved path → regular file → ≤ 64 KiB → UTF-8 → frontmatter delimiters/YAML-mapping → non-empty body after frontmatter.
Path resolution
agent-definition values resolve as:
~/…or~— home-expanded, used as-is.- Absolute path — used as-is (ignores
agent-definition-directory). - Relative path — resolved against
subagent-global-defaults.agent-definition-directory, which itself may be absolute,~-prefixed, or relative (relative resolves against the entry config file's directory /PI_CODING_AGENT_DIR). Unset → the entry config directory itself.
A role without agent-definition inherits the global
subagent-global-defaults.agent-definition-directory + global
agent-definition if one is set; multiple roles may share one document.
Workflow
- Read the current entry config (
~/.pi/agent/tmux-pilot.config.yamlor$PI_CODING_AGENT_DIR/tmux-pilot.config.yaml) and anyimports:it pulls in before editing — respect existing global defaults instead of restating them per-role, and check the role name isn't already declared in an import. - Write/edit the role entry with only the fields that differ from inherited defaults. Kebab-case; no legacy keys.
- If the role needs standing instructions, create the
.mdunder theagent-definition-directoryand reference it by bare filename; otherwise omitagent-definitionentirely. - Sanity-check: valid YAML; model entries either bare strings or single-key maps; thinking values from the enum; harness constraints from the table above; definition file passes the validation checklist.
- Remind the user: changes apply on the next spawn (no restart needed for
routing/guards; widget placement/toggle keys need a new session). The
/tmux-pilot:webuiconsole edits the same entry file with validation, and is the recommended place to repair a definition a spawn rejected.
What ships with it: 3 files
4.6 KB alongside SKILL.md
resources/
- metadata.json669 B