@kozilla/pane
v0.2.9
Published
Tile multiple commands into iTerm2 split panes
Readme
pane
Tile multiple commands into iTerm2 split panes. Opens a new tab and runs each command in its own pane, arranged top to bottom.
Using Claude Code? This repo ships a
use-paneskill that teaches Claude Code how to wire@kozilla/paneinto a project (pinned devDependency,.pane/layout,dirresolution rules, wait gates). Drop it into your.claude/skills/and ask Claude to set uppane.
Install
The npm package is @kozilla/pane; the binary it installs is pane.
Node.js projects (recommended)
Pin @kozilla/pane as a devDependency so every contributor and CI run uses the same version, then invoke it via an npm script:
npm install --save-dev @kozilla/pane@<exact-version>{
"scripts": {
"dev": "pane -c .pane/dev.yaml"
},
"devDependencies": {
"@kozilla/pane": "0.2.5"
}
}Pin the exact version (no ^ / ~) — pane drives iTerm2 via AppleScript, and small changes to pane arrangement or wait-gate semantics can subtly shift a working dev setup.
Global (ad-hoc or non-Node projects)
npm install -g @kozilla/paneFrom source
git clone https://github.com/koyeo/pane.git
cd pane
npm install
npm install -g .Usage
pane -c .pane/dev.yamlConfig file (-c / --config)
-c is required. Load commands from a YAML file. Each entry is either a plain string or a mapping:
commands:
- htop
- exec: npm run dev
dir: ..
- exec: npm test
dir: ../packages/web
waitPort: 3000Mapping fields:
exec(required): command to executesleep(optional): delay N seconds before executingwaitPort(optional): wait for a TCP port on localhost to become reachablewaitFile(optional): wait for a file to appear before executingdir(optional): working directory for this pane; relative paths resolve from the config file's directory
Wait conditions are evaluated by the pane process itself — they never inject sleep/nc/loop snippets into the user's shell. The pane's shell only sees the clean exec string once the gates pass.
Multiple wait conditions can be combined. Order: sleep → waitPort → waitFile → exec
There is no top-level dir — set it per command. Panes without dir use the cwd.
Every pane is driven through a fully synchronized sequence — each step waits
for observed state, never timing: pane first waits until a shell process is
attached to the pane's tty, then writes cd <dir>, then waits until the
shell's working directory has actually changed (verified via ps/lsof),
then evaluates the wait gates, and only then writes the exec command. The
cd and the command are separate lines, but the command is never written
before the cd was demonstrably consumed by the shell — so the two can never
merge into one line, no matter how slowly the shell starts. If a pane is
closed while pane is still waiting, it fails with a diagnostic instead of
hanging.
Wait conditions example
commands:
- exec: npm run dev
- exec: npm test
waitPort: 3000 # tests wait for server port
- exec: npm start
waitFile: dist/index.js # wait for build artifact
- exec: npm run smoke
sleep: 5 # delay 5 secondsProject layout: keep configs under .pane/
For projects that use pane regularly, colocate per-workflow YAML files under a top-level .pane/ directory:
your-project/
├── .pane/
│ ├── dev.yaml # full dev stack
│ ├── e2e.yaml # services needed for e2e tests
│ └── debug.yaml # extra inspectors (htop, log tail, …)
├── package.json
└── …Commit shared recipes; leave a .pane/local.yaml slot (gitignored) for personal tweaks.
Working directory (dir)
Each command may set its own dir. Two rules cause every surprise people hit:
- A relative
dirresolves against the YAML file's directory, NOT the current working directory. - Panes without
dirlaunch in the cwdpanewas run from.
Because YAML files live under .pane/, dir: . points at .pane/, not the project root. Use dir: ..:
# .pane/dev.yaml
commands:
- exec: npm run server
dir: .. # project root
- exec: npm run worker
dir: ../packages/worker
waitPort: 3000
- exec: tail -f /var/log/app.log # no dir → cwdThere is no top-level dir; a config that still has one fails to load with a clear error.
Requirements
- macOS
- iTerm2
- Node.js >= 18
License
MIT
