Feature proposal: get-tree and append-layout commands (i3 parity) #1957
Unanswered
glassbe
asked this question in
feature-ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Motivation
AeroSpace currently has no way to programmatically inspect or construct the container tree. This makes it very difficult to build tooling that arranges windows into preset layouts.
i3 on Linux solves this elegantly with three primitives:
i3-msg -t get_tree— returns the full container hierarchy as queryable JSONi3-save-tree— dumps the current layout to a filei3-msg append_layout <file>— reconstructs the tree from a JSON layout specificationWithout these, the only way to programmatically build a layout in AeroSpace is:
flatten-workspace-tree(reset to flat list)focus --window-id+move leftin a loop (reorder windows)join-withbottom-up (build container hierarchy)layouton each container (set tiles/accordion/orientation)balance-sizesThis is fragile, slow (requires delays between commands), and limited —
join-withalways creates containers with the opposite orientation and tiles layout, so you must fix layouts after the fact.Proposal
1.
get-treecommandDump the workspace tree as JSON.
Example output:
{ "type": "workspace", "name": "1", "children": [ { "type": "container", "layout": "accordion", "orientation": "horizontal", "children": [ { "type": "window", "window-id": 1234, "app-bundle-id": "company.thebrowser.Browser", "app-name": "Arc" }, { "type": "container", "layout": "accordion", "orientation": "vertical", "children": [ { "type": "window", "window-id": 5678, "app-name": "Code" }, { "type": "container", "layout": "tiles", "orientation": "horizontal", "children": [ { "type": "window", "window-id": 9012, "app-name": "Ghostty" }, { "type": "window", "window-id": 9013, "app-name": "Ghostty" } ] } ] } ] } ] }2.
append-layoutcommand (stretch goal)Construct a tree from a JSON layout specification, matching windows by app bundle ID.
This would flatten the workspace, then build the specified tree by creating containers and binding windows to them directly — no need for the fragile join-with dance.
Existing infrastructure
The codebase already has strong foundations for this:
FrozenTreeNode(Sources/AppBundle/tree/frozen/FrozenTreeNode.swift) — an immutable snapshot of the tree that could serve as the serialization model forget-treeLayoutDescription(inMoveCommandTest.swift) — a recursive enum that already serializes the tree structure for test assertionsTilingContainer()constructor +bind()/unbindFromParent()— all the primitives needed to construct a tree programmatically forappend-layoutJsonenum (Sources/AppBundle/model/Json.swift) — custom JSON serialization already used bylist-windows --jsonUse cases
I have a working layout manager (AeroLayout) that currently uses the flatten/move/join workaround. These commands would simplify it from ~500 LOC of engine code to a single
append-layoutcall.Scope
I would be happy to implement this. My suggested phasing:
get-tree— addEncodabletoFrozenTreeNode, create the command (~200 LOC)append-layout— layout spec parser + tree construction (~300-400 LOC)Would love to hear if this direction aligns with the project vision before starting on a PR.
Beta Was this translation helpful? Give feedback.
All reactions