Docs > Change
Pane packs
A pane is a tab in Shift’s inspector that your project owns: a few lines of text, live values from the session, and commands that run through the same allowlisted machinery as the agent’s own runs. You declare it once, in .shift/panes.scm, and every Shift session opened in that folder shows it.
The file is Scheme the way a theme pack is Scheme: one form, read with read and never evaluated. There is no code to load, no plugin API to version, and nothing a pane can do that the session could not already do.
The shape
Shift’s own repository ships this pack. It adds a SHIFT tab beside Work, Diff, Session, Model and Log.
;; .shift/panes.scm
((pane "shift" "SHIFT"
(text "Shift checkout health")
(field source.loaded)
(field session.model)
(field usage.prompt)
(command "git" "status" "--short")
(command "git" "log" "--oneline" "-3")
(command "make" "test")))
Grammar
PACK = ( PANE ... ) ; up to 4 panes, one form per file
PANE = ( pane NAME TITLE ROW ... ) ; 1 to 24 rows
ROW = ( text STRING ) ; up to 120 printable characters
| ( field FIELD ) ; a live value, redrawn live
| ( source SECTION ) ; a built-in sidebar section
| ( command STRING ... ) ; argv of 1 to 16 strings, not a shell line
NAME = "[a-z0-9-]{1,16}" ; not work, diff, session, model or log
TITLE = up to 12 printable characters ; the tab label
Names are what /pane run NAME and the tab strip use; titles are what you read. Comments and whitespace are yours to use. Anything outside this grammar, including any other list head, is rejected as a whole: an invalid pack is reported and skipped, and the last valid one stays loaded.
Fields
A field row names one of these symbols. It shows the label and the current value, or a dash before the session has reported it.
| Field | Shows |
|---|---|
| session.name | The durable session name. |
| session.provider | The provider serving the model. |
| session.model | The model the next turn will use. |
| session.mode | The tool policy: manual, plan or autopilot. |
| session.turn | The turn counter. |
| usage.prompt | Prompt tokens in the last reported round. |
| usage.limit | The context limit the session budgets against. |
| usage.round | The model round within the current turn. |
| usage.max_rounds | The round ceiling for a turn. |
| receipt.status | The last turn’s receipt status. |
| receipt.duration_ms | How long the last turn took, in milliseconds. |
| source.loaded | The Shift checkout the running image was loaded from. |
| source.process | The Shift checkout the process started with. |
Sources
A source row borrows one of the sections the built-in tabs are made of, so a project can compose its own status tab: skills next to the git status it cares about, or the running jobs beside a checklist.
| Source | Shows |
|---|---|
| session | Name, provider/model, mode and turn. |
| skills | Skills with source and loaded state; clicking loads one. |
| plugins | Installed plugins with their state and what each contributes. |
| sessions | Durable sessions with status marks; clicking an idle one switches. |
| peers | The MCP endpoint and attached peers. |
| servers | MCP servers the session can reach, with state and tool counts; clicking connects one. |
| receipt | The latest turn’s receipt. |
| telemetry | Exact context and round values. |
| source | The Shift checkout the session and process loaded. |
| jobs | Background jobs while they run. |
| runs | The run history the Log tab shows. |
| models | The provider’s models; clicking switches. |
Commands
A command row is an argv, not a shell line, and it runs only when the session’s run allowlist already permits that prefix: the same rule that governs the agent’s run tool. Otherwise the row reports which /allow-run prefix is missing. Clicking a command row runs it; /pane run NAME runs every command row in the pane and /pane run NAME ROW one of them. Output shows under the row and in the Log tab, bounded to 300 lines or 16 KiB per run.
./bin/shift-agent --allow-run "git status" --allow-run "git log" --allow-run "make test"
shift> /pane run shift
Loading, precedence, checking
- The pack loads whenever Shift runs in the project and reloads within half a second when the file changes.
- An explicit panes preference, from /ui or the agent’s ui tool, takes precedence over the file. It carries the same panes as JSON objects with name, title and rows, validated by the same rules.
- The file is committable. Shift’s own .gitignore keeps the rest of the state directory private and allows only the pack.
- ./bin/shift-agent --check-panes lints the pack the way a session loads it and exits non-zero with the reason; pass a path to check another file.
$ ./bin/shift-agent --check-panes
pane shift: 7 rows
.shift/panes.scm: ok
Panes never load Python or Scheme code and never widen what the session may run. Details live in the terminal guide.