// A session described as a file: slosh --layout project.layout // // Name them `*.layout`. The syntax is the same KDL subset the config uses -- // one parser reads both -- so the extension says how to read the file and the // `.layout` says what is in it. Two documents sharing a syntax is only confusing // while nothing says which is which: hand this file to `slosh --check` and it // tells you it is a layout, and hand a config to `--layout` and it says that too. // // The same shape can be sent to a running session over the control socket: // slosh cmd '{"cmd":"apply-layout","path":"/path/to/project.layout"}' // slosh cmd '{"cmd":"apply-layout","kdl":"layout { tab name=\"x\" { pane } }"}' // which is how an orchestrator adds one project tab at a time. layout { // A tab is a project. `purpose` is its identity — declared here, it is // locked: no program running inside can relabel itself into it. A workspace // opened from a project root stamps this itself, so a file checked in with // the project leaves it out and lets where the file *is* say which project // it belongs to. tab name="api" purpose="project:api.a1b2c3" cwd="/home/user/dev/api" { // The tab's panes split into columns by default. pane purpose="agent:main" command="pi" pane split="rows" { // `suspended` means the pane exists, is laid out, and has run // nothing. It starts on its first keystroke. Twelve projects // should not be twelve running dev servers. pane purpose="service:web" command="npm run dev" suspended=true // No command: the configured shell, in the tab's cwd. pane purpose="shell:scratch" } } tab name="notes" cwd="/home/user/notes" { pane command="nvim ." suspended=true } } // The same file, checked in beside the project it describes: no absolute paths // anywhere in it, because a relative `cwd=` means the directory *this file* is // in and a pane with no `cwd=` at all starts there too. Which is what // `save-workspace` writes, and what makes it the same file on another machine. // // layout { // tab name="api" { // pane purpose="agent:main" command="pi" // pane split="rows" { // pane purpose="service:web" cwd="web" command="npm run dev" suspended=true // pane purpose="shell:scratch" // } // } // } // Note on escapes: strings understand \n \t \r \e \\ \" — \e is an ESC, and // there is no \033. A command that needs an escape should use \e.