# Catenary > The IDE for coding agents. Your editor, your terminals and your agents — in one window, talking to each other. Catenary is a desktop IDE (Electron + Chromium) with two lenses on the same work. On the Canvas, an infinite, zoomable surface, terminals, Monaco editors, browsers and AI coding agents are not tabs stacked in a rail — they are panels floating in space, side by side, where you put them. TerminalMap shows the same work as keyboard-driven terminal splits with a session switcher; one shortcut switches between the two and nothing restarts. It exists for one shape of work: running more than one AI coding agent at the same time without losing track of what each of them is doing: a workspace that organizes your projects and the agents in them, and lets those agents talk to each other. ## What is distinctive - **Connection wires** — a line between two panels. By default it is a permission: the agents at each end reach each other with catenary ask, and nothing travels until one of them asks. It can also relay each finished turn automatically, or run both ways as a budgeted conversation. Agents in the same session reach each other even without a wire. It replaces copying a stack trace between windows. - **1-click worktrees** — the New Task button creates an isolated git branch, its own working directory and, given a task, an agent to work in it (with no task, a plain terminal), without touching the code in front of you. Three experiments run in parallel and none of them collide. - **Maestro Mode** — one agent recruits, briefs and wires a team of helpers. Off by default and switched on by a human click. Recruiting or dismissing an agent opens an editable approval card before anything happens on the canvas; wiring two of its agents together is approved on its own, unless they are in different worktrees. - **Monaco editor with diffs** — the editor VS Code is built on, inside the canvas, with a side-by-side diff of everything an agent touched, and a git-aware file tree. - **Local-first** — no account, no telemetry, no sign-up. Catenary runs no model and never routes your prompts: the agents are the CLIs you already installed, with the API keys you already pay for. Canvas state lives in the project folder itself. ## Facts - Current version: 1.2.2 - Platforms: Windows, macOS, Linux - Licence: closed-source, proprietary software. A free tier exists with no time limit; Pro is a one-time payment of US$ 19 (R$ 85 in Brazil) for the 1.x line, not a subscription, and covers up to 2 of the holder's personal computers activated at a time, with a slot freed at any moment from inside the app. - Pro can be bought today. A 7-day trial also runs inside the app: no card, no account. - Licence check: the key is verified offline by a locally checked Ed25519 signature. You start Pro activation, seat removal and redemption of the 7-day trial. An unconfirmed Pro seat retries activation automatically on launch while temporary Pro is active, within a 30-day grace period. Confirmed Pro is verified locally, without periodic server revalidation or heartbeat. Separately, it asks GitHub Releases for updates about 5 s after launch and every 15 minutes while open; that request carries no personal data and never reaches us. - Built by Catenary, Brazil. Support: support@thecatenary.app - Languages: English at https://thecatenary.app, Brazilian Portuguese at https://thecatenary.app/pt --- The complete documentation follows, in reading order. Each article is also served on its own page, at the URL noted above it. --- # Introduction Catenary is the IDE for coding agents: a desktop app with two lenses on the same work. On the **Canvas**, an infinite canvas you can zoom, terminals, editors, browsers and coding agents are not tabs stacked in a rail — they are panels that float in space, side by side, where you put them. **TerminalMap** shows the same work as keyboard-driven terminal splits with a session switcher; ⌥⌘S switches between the two, and nothing restarts. It exists for one shape of work: running several AI coding agents at once (Claude Code, Codex, Antigravity) without losing track of what each of them is doing. ## What it is A native application (Electron + Chromium) that opens a folder on your machine and gives you: - an **infinite canvas** you pan and zoom, with panels positioned in canvas space; - **terminals** backed by a real PTY, where you run `claude`, `codex`, or anything else; - **Monaco**, the editor from VS Code, with side-by-side diffs of what an agent changed; - **browser panels** to watch your dev server while the agent edits it; - **wires** that carry context from one panel into an agent; - **git worktrees** created in one click, so three experiments run in parallel without touching each other. ```media A full pass over the canvas: four panels, two agents working, one wire relaying. ``` ## What it is not It is not a cloud service. Catenary does not run a model, does not proxy your prompts, and has no account system. The agents you run are the CLIs you already have installed, using the API keys you already pay for; the built-in Catenary Agent uses the provider keys you give it. ## Local-first, by construction - No account. Nothing to sign up for. - No telemetry. The app opens no analytics connection. - Your API keys stay on your machine and are never routed through us. - The Pro licence is verified by a locally checked Ed25519 signature. An unconfirmed seat can grant temporary Pro for 30 days; while that Pro is active, activation retries automatically on launch. Confirmed Pro is checked locally, without periodic server revalidation. Canvas state lives in the project you opened, at `.cate/workspace.json` and `.cate/session.json`. Close the folder, reopen it, and everything comes back where you left it. ## Where to go next If you have not installed it yet, start with the [installation guide](/docs/installation). If it is already running, [core concepts](/docs/concepts) is the shortest path to the vocabulary the rest of this documentation uses. --- # Installation guide Catenary ships as a normal desktop installer for Windows, macOS and Linux. This page covers the download, the operating-system warnings you will see, and why they exist. ## Download | System | Formats | | --- | --- | | Windows | NSIS installer (one-click) and ZIP — x64 | | macOS | DMG and ZIP — arm64 and x64 | | Linux | AppImage, DEB and tar.gz — x64 | Builds are published on GitHub Releases. The in-app updater checks the same source, so once installed you do not download anything by hand again. On Windows, install through Windows Package Manager: ```powershell winget install catenary ``` On macOS the quickest route is Homebrew, with one command that also avoids the Gatekeeper warning below: ```bash brew install --cask gionicolas/catenary/catenary ``` It adds the Catenary tap, trusts only this cask (Homebrew requires that since version 6), checks the checksum of the download and installs the app into `/Applications`. ## Windows: the SmartScreen warning On the first run, Windows may show a blue "Windows protected your PC" panel. This is the standard notice for a new executable with no accumulated reputation — not a detection of anything. Click **More info**, then **Run anyway**. ```media The SmartScreen panel, with "More info" and "Run anyway" highlighted. ``` Without a code-signing certificate, SmartScreen counts reputation per file, and every version is a new file. So the warning may come back with each release until the installer is signed. ## macOS: Gatekeeper If you installed with Homebrew, skip this section. If you downloaded the `.dmg`, macOS may say the app "cannot be opened because the developer cannot be verified", or report that the app "is damaged and should be moved to the Trash". **macOS 15 Sequoia and later:** try to open Catenary once and close the warning. Then open **System Settings → Privacy & Security**, click **Open Anyway** next to the message about Catenary, and confirm with your password. **macOS 14 Sonoma and earlier:** right-click (or Control-click) Catenary in Finder, choose **Open**, and confirm in the dialog. Either way you do this once — macOS remembers the decision for that copy. If macOS still refuses to open or claims the file is damaged, open your **Terminal** and run: ```bash xattr -rd com.apple.quarantine /Applications/Catenary.app ``` *(If you didn't move the app to the Applications folder, replace `/Applications/Catenary.app` with the path to the extracted `.app` file).* ```media System Settings → Privacy & Security, with the "Open Anyway" button next to the message about Catenary. ``` ## Why the installers are unsigned Honestly: a Windows code-signing certificate costs around US$ 200 a year, and it has not been bought yet. The plan is to pay for it with Pro licence sales. Until then the installer is unsigned — which is exactly why the two warnings above exist, and why this page exists. ## First launch After a one-screen welcome, Catenary asks how you want to start: **TerminalMap**, with keyboard-driven splits and a session switcher, or **Canvas**, the infinite spatial board. Either way you get a terminal in your Home folder — no project needed. You can switch between the two lenses anytime, and no process restarts. A short tour then points out the lens switcher, the sidebar, and splits and tasks. When you open a project folder, it becomes a workspace, and its state is written to `.cate/` inside that project. No account, no key and no internet connection are required to reach this point. ## Updates Updates arrive through electron-updater from GitHub Releases. Everything in the 1.x line is included in a Pro licence. --- # Bring your setup Coming from VS Code, Cursor or Ghostty? Catenary reads their preference files and shows exactly what it would change before it changes anything. ## Where to start Run **Import Preferences from VS Code / Cursor / Ghostty** from the command palette (⌘K), or click **Import from VS Code, Cursor or Ghostty** at the top of the **Install** tab of the Extensions Hub. Pick the app, and the file picker opens where that app keeps its config. Catenary reads only the file you confirm. You can also browse to any file, or paste its contents. ## What comes along | From | What is imported | | --- | --- | | VS Code or Cursor, `settings.json` | Editor font and size, format on save, minimap; terminal font and size, cursor blink | | VS Code or Cursor, `keybindings.json` | Shortcuts for the actions Catenary has | | Ghostty, `config` | Font, font size, cursor blink and keybinds | Themes, extensions, language-specific blocks, chorded or `when`-scoped keybindings and commands with no Catenary action stay behind. They are listed under **items ignored (no Catenary equivalent)**, so you see what was left out instead of assuming a full migration. ## Choose, then undo Every item has its own checkbox, and **Import Selected** applies only those. A shortcut that is already taken shows **Also bound to** and the action that has it. The source files are only read, never written. Changed your mind? The confirmation offers **Undo**, and **Undo Last Import** in the same dialog brings back the preferences you had before. --- # Core concepts Ten words the rest of this documentation assumes. Read once; the vocabulary is small on purpose. ## Workspace A project folder you opened. Each workspace carries its own canvas, its own panels and its own git state. The recent-projects list in the sidebar switches between them. Per-project state lives inside the project: `.cate/workspace.json` for the canvas layout and `.cate/session.json` for what was running. ## Canvas The infinite surface. Panels have coordinates in *canvas space*; the viewport converts them to screen space using the zoom level and the offset. Panning and zooming never move a panel — they move your view of it. A canvas can also be a panel: a nested canvas inside the parent one. The Canvas is one of two lenses. **TerminalMap** shows the same panels as keyboard-driven terminal splits; ⌥⌘S switches between them, and nothing restarts. ## Panel One unit of work on the canvas. Seven types: **terminal**, **editor**, **browser**, **canvas**, **agent**, **document** and **extension**. A panel either floats as a canvas node — title bar, drag handle, resize corners — or docks into a dock zone as a tab. The same panel record renders both ways, so moving it between the two loses nothing. ## Dock The fixed zones at the edges of the window. Drop a panel there and it becomes a tab; drag it back out and it returns to the canvas. Detached windows are dock windows, and their panels are synced back for session restore. ## Agent A coding agent running inside a terminal panel — `claude`, `codex`, or whichever CLI you launch. Catenary does not replace the agent; it gives it a place to live, a name on the canvas and wires to its peers. ## Wire A connection between two panels. By default it is a permission: the agents at each end can reach each other with `catenary ask`, and nothing travels until one of them asks. It can also relay each finished turn on its own. See [connection wires](/docs/wires). ## Worktree / task An isolated git worktree with its own branch and its own directory, created in one click. Its colour follows it through the sidebar, the dock tabs and its territory on the canvas. See [1-click worktrees](/docs/worktrees). ## Squad A saved formation of agents: roles, presets and the wires between them. Load a squad and the whole team appears already connected. ## Maestro Mode Off by default. When you switch it on, one agent may recruit, brief and wire a team. Recruiting or dismissing an agent stops at an editable approval card before anything appears on the canvas; wiring two of its agents together is approved on its own, unless they are in different worktrees. See [Maestro Mode](/docs/maestro). ## Territory The coloured island drawn under all the panels belonging to the same worktree. Optional — a switch in **Settings, Worktrees** ("Worktree Territories"). ```media The same canvas with territories off, then on. ``` --- # The two lenses Catenary shows the same work in two ways. The **Canvas** is the infinite canvas where panels float and wires connect agents. **TerminalMap** is the terminal orchestrator: a grid of terminal splits with a session switcher, made for the keyboard. ⌥⌘S switches between them at any time. ## Nothing restarts Switching lenses changes the presentation, never the work. The terminals, the agents running in them, the browsers and the editors are the same before and after the switch: nothing is closed, nothing is relaunched. - **Into TerminalMap**, the terminals of the current session become a grid of splits. Editors and browsers wait as tabs in the right dock. - **Back to the Canvas**, every panel returns to where it was. A panel you opened while in TerminalMap lands in the middle of the view. The switcher at the top of the window, **Canvas | TerminalMap**, does the same as the shortcut. Each workspace remembers the lens it was left in. ```media Switching from the Canvas to TerminalMap and back, with an agent still typing. ``` ## The first launch With no saved environment, Catenary opens on **How do you want to start?**, with one card for **TerminalMap** and one for **Canvas**. Either way you get a terminal in your Home folder, with no project to pick. A short tour follows; Esc skips it. To open every project in the same lens, set **Settings, General, Start layout**. The default, **Remember last layout per workspace**, reopens each project as you left it. ## The Sessions Cockpit The sidebar has two tabs at the top, **Sessions** and **Files**. ⇧⌘S jumps to Sessions. Each card there is one work session, and the session you select is the one TerminalMap shows. A card tells you what is happening without opening anything: - the name, then the agent's latest recap or, before there is one, the task it was launched with; - the branch, with `*` when it has uncommitted changes, and the folder; - a dot for the state. | Dot | Means | | --- | --- | | Blue, breathing | An agent is working | | Green | The agent finished its turn and is ready for you | | Amber | A request is waiting: input or approval | | Red | Something failed | The **+** beside a workspace adds a session. Right-click a card for **Rename**, **Go to Request**, **Reveal in Canvas** and **Delete Session**. ## The bell and Jump to Unread An agent that stops to ask for input or approval, or that fails, raises a request. An agent can also raise one on purpose, with the `catenary_request_attention` tool (see [LSP and tools for agents](/docs/agent-tools)). Every pending request, from every workspace, collects under the bell at the left of the title bar. It stays reachable with the sidebar closed, the Files tab open or the workspace archived. Each entry shows its type (**Input**, **Approval** or **Failure**), the session, the workspace and how long it has waited. ⇧⌘U, **Jump to Unread**, takes you to the oldest request you have not seen yet, in whichever workspace it is. ```media An agent in another workspace asks for approval; Jump to Unread lands on it. ``` --- # The infinite canvas The canvas is the whole point. Everything else is a panel on it. ## Panning and zooming | Gesture | Action | | --- | --- | | Two-finger scroll / trackpad drag | Pan | | Command + scroll wheel | Zoom at the pointer | | Right-click drag | Pan from anywhere | | ⌘= / ⌘- / ⌘0 | Zoom in, zoom out, reset | | ⌘1 | Zoom to fit everything | | ⌘2 | Zoom to the selection | | ⌃Space | Toggle select and hand tool | Zoom is clamped between a minimum and a maximum, and it is centred on the pointer rather than on the middle of the window — so you zoom into the panel you are looking at. ```media Zooming into a terminal panel from the full canvas view, then back out. ``` ## Moving and resizing panels Drag a panel by its title bar. Drag any edge or corner to resize. Both operate in canvas space, so a panel keeps its position relative to its neighbours regardless of the zoom you were at when you moved it. `⌘↑ ⌘↓ ⌘← ⌘→` move focus to the panel above, below, left or right of the focused one — spatial navigation, not a tab cycle. `⇧` plus an arrow pans the canvas itself. ## Auto layout `⇧⌘L` arranges the panels of the active canvas into a clean formation. Useful after a squad loads, or when an agent has opened more panels than you were watching. ## Nested canvases A canvas can be a panel inside another canvas. Use it to fold an entire sub-project into one node instead of scattering fifteen panels across the same plane. ## Persistence The canvas is written to `.cate/workspace.json` inside the project, and the running session to `.cate/session.json`. Both are plain, hand-editable JSON. Closing the folder and reopening it restores positions, sizes, zoom, viewport offset and the dock layout. ```media Closing a project with eight panels open and reopening it — everything back in place. ``` --- # Terminals & agents A terminal panel is a real terminal: xterm.js on the front, a native PTY (node-pty) on the back, rendered through WebGL. Anything that runs in your shell runs here. ## Opening one `⌘T` opens a terminal at the centre of the view. It starts in the workspace folder, with your shell and your environment — the same `PATH`, the same profile, the same tools. ```bash # Nothing special is required. Your agent CLI, as you already run it: claude codex ``` ## Splits In TerminalMap, ⌘D splits the focused terminal to the right and ⇧⌘D splits it down. The new pane starts in the folder the old one is in now, even after a `cd`. ⇧⌘↩ zooms one split to the whole area and back, and ⌥⌘← ⌥⌘→ ⌥⌘↑ ⌥⌘↓ move between them. Clicking the **✕** of a terminal, a split or a group closes it right away, with no confirmation, whatever is running in it. ## Agents are just CLIs Catenary does not bundle a model and does not proxy your prompts. The agent you run is the CLI you installed, authenticated the way you already authenticate it. What the canvas adds is a **name**, a **position** and **wires** to its peers. Provider credentials for the built-in agent panel are stored globally under `userData/pi-agent/auth.json` and mirrored into each workspace's `.cate/pi-agent/`. ## Reading state at a glance A panel tells you what it is doing without being opened: - the tab shows the agent's name and, on a task panel, its branch; - a working agent shimmers its status line; - a finished command and an agent waiting for input each get their own activity state on the node. ```media Three agent panels side by side: one working, one waiting for input, one finished. ``` ## Links in the terminal Hold ⌘ and click a `path:line:col` an agent printed, and the file opens in the editor at that line and column. Web links work the same way. By default they open in Catenary's own browser; **Settings, Browser, Open terminal links** can send them to your system browser instead, or keep only `localhost` inside. Hold ⇧⌘ and click to open a link in the other place, and right-clicking one offers **Open in Catenary** and **Open in External Browser**. ## After a restart Reopen Catenary and every terminal comes back with what it was showing, followed by a dim `--- restored session ---` line and a fresh shell. When Catenary knows which conversation an agent was in, it resumes it on its own: `claude --resume `, `codex resume ` and the equivalent for the other agents it knows. When it only knows which agent the terminal runs, it starts a new conversation with it. ## Built to hold up A command that floods the terminal with output does not freeze it: Catenary pauses the process while the terminal catches up. If the graphics card drops the WebGL context, the terminal switches to a slower renderer and goes back to WebGL as soon as it can. ## Talking to peers A terminal wired to another can address it directly through the `catenary` CLI, available inside every terminal panel: ```bash catenary list # peers, boards and connected files catenary ask "Codex 1" "Take the N+1 in the dashboard query" catenary check "Codex 1" # last lines, without interrupting it catenary check "Codex 1" 60 # a custom line count ``` `ask` delivers a prompt. `check` reads without interrupting — use it while a peer is mid-turn instead of sending the same prompt twice. By default, agents in the same session reach each other without a wire and without a confirmation card. `catenary ask --no-wait "Codex 1" "…"` hands the work off and returns at once, instead of waiting for the answer. See [connection wires](/docs/wires) for agents in other sessions. ## Shared boards Boards are persistent notes several agents can read and append to. A terminal sees a board only when a wire connects them (see [boards](/docs/wires#boards)): ```bash catenary board list catenary board read "Spec" catenary board append "Spec" "Refactored /auth; tokens.ts is next" ``` They are the right place for a decision that has to outlive one agent's context window. --- # LSP and tools for agents Catenary runs one language server for your code and shares it between the editor and the agents. It also gives every agent running in a Catenary terminal a set of tools to drive the IDE: open a file, split a terminal, start a task, ask for your attention. There is nothing to configure. ## One language server, shared TypeScript, JavaScript and Python files are served by a local engine: `typescript-language-server` and `pyright`, bundled with the app. There is one server per workspace, worktree and language, and it restarts on its own if it crashes. When the project has its own `typescript` in `node_modules`, that is the one used. Go, Rust, C and C++ use the server you installed: `gopls`, `rust-analyzer` or `clangd` (with `--background-index`), found on the PATH the first time a file of that language opens. Without it, that language simply has no server, and nothing else changes. In the editor it powers completion, hover, go to definition, references, rename, diagnostics and semantic highlighting. ## The same engine, for agents Five read-only tools put that server in the agent's hands: | Tool | What it returns | | --- | --- | | `catenary_lsp_definition` | Where a symbol is defined, by position or by name | | `catenary_lsp_references` | Where it is used | | `catenary_lsp_hover` | The full type signature and its documentation | | `catenary_lsp_document_symbols` | The symbol tree of a file | | `catenary_lsp_diagnostics` | Errors and warnings, for one file or the whole workspace | The agent reads what you see. If the file is open in the editor with unsaved changes, the answer comes from that buffer, not from disk, and every result says which one it used: `source: "buffer"` or `source: "disk"`. While the server is still indexing, the result says that too, and an empty list of diagnostics is not yet a clean bill of health. ## Registered on its own When a terminal starts, Catenary adds a server named `catenary` to the MCP config of each agent CLI installed on the machine: Claude Code, Codex, Antigravity, Cursor and OpenCode. - It only touches agents that have actually run there. - It never replaces a `catenary` entry you wrote yourself. - Outside a Catenary terminal the server lists no tools, so the entry costs nothing elsewhere. Cursor asks once to approve the server. That prompt belongs to Cursor. ## The tools | Tool | What it does | | --- | --- | | `catenary_get_environment` | Describes the session the agent is running in | | `catenary_open_file` | Opens a file in the editor, at a line and column | | `catenary_split_terminal` | Splits the agent's terminal; the new pane starts in the same folder | | `catenary_create_worktree` | Creates an isolated branch | | `catenary_create_task` | A worktree plus a terminal session; with an instruction, it also launches an agent there | | `catenary_capture_preview` | Captures the session's built-in browser | | `catenary_get_canvas_state` | Lists the sessions, panels, branches and open ports of the workspace | | `catenary_request_attention` | Raises a request under the bell. It asks for your attention; it never grants an approval | They obey the same switches as the `catenary` CLI, in **Settings, CLI**: a **Read** and a **Control** column for each surface (Browser, Terminal, Panels, Editor, Notifications, Boards, Maestro). All are on by default. Turn off **Command-line control (Catenary CLI)** and none of the tools works. ## A structured inbox `catenary_delegate_task` queues a message for another agent in the same workspace: an instruction and, if needed, a list of files. Nothing is typed into its terminal. The other agent reads it with `catenary_read_inbox` and confirms it with `catenary_ack_message`. - Reading marks a message as delivered, and acknowledging marks it as received. Neither means the task is done. - Retrying with the same `operationId` never creates a duplicate. - A message nobody reads expires after 24 hours. For a question that needs an answer right now, `catenary ask` is still the shorter path. See [connection wires](/docs/wires). --- # Extensions Hub & MCP The puzzle-piece icon in the sidebar opens the **Extensions Hub**. It has three tabs: **Installed**, **Install** and **MCP**. ## Extensions A Catenary extension can add its own panel, running in an isolated view of its own. Extensions are managed globally: one installed is available in every workspace. - **Installed** lists what you have. Each row turns on and off, and offers **Reinstall** and **Remove**. - **Install** browses the catalog, by category or by search. **Add local folder** loads an extension from a folder on disk that has a manifest. - **Catalog sources** are the URLs the catalog comes from. Only add sources you trust: an extension can run its own code on your machine. Open a row to see what the extension may do, such as **Read workspace info**, **Open & edit files**, **Control the browser** or **Run the agent on your behalf**. Before an extension runs the agent or drives the browser, Catenary asks you. ## The MCP tab The MCP tab shows which MCP servers your agents can reach, and it is honest about what it cannot see. **Configured in this workspace.** The servers the project declares in `.mcp.json` (read by Claude Code) and `.pi/mcp.json` (read by the Catenary Agent). For each one it shows: - the name; - the transport: `stdio`, `http` or `sse`; - the executable name, or the host of the URL. Never the arguments, the environment, the headers or the path of the URL: they routinely carry tokens. Catenary also cannot see whether these servers are connected, because the agent that reads the file is the one that connects. **Catenary MCP.** The built-in server, with the list of the tools it advertises. See [LSP and tools for agents](/docs/agent-tools). **Observed MCP connections.** Every live connection to the Catenary server: the terminal, the workspace, connected or not, when it was last seen, and the tools exposed to that execution. It refreshes every 5 seconds. **Observed agents and listening ports.** What the process monitor sees in each terminal: the agent running there and the ports it listens on. A listening port does not prove that an MCP server is healthy. ```media The MCP tab of a workspace with a .mcp.json and two agents connected to the Catenary server. ``` --- # Connection wires A wire is a line between two panels. By default it is a permission: the two agents can reach each other with `catenary ask`, and nothing travels until one of them asks. It is the answer to copying a stack trace out of one window and pasting it into another. ## Drawing one Drag from the edge of a panel to the panel you want to connect. The line falls into a catenary curve — the shape the product is named after — and a pulse travels along it each time it delivers something. ```media Dragging a wire from a terminal to an agent panel, with the pulse starting up. ``` ## What travels | Source | What reaches the other side | | --- | --- | | Terminal / agent | What one agent asks the other with `catenary ask`; in an automatic conversation, the output of each finished turn | | File or document pin | The path, listed under "Connected files"; the agent reads the file itself | | Board | The board's text, readable and appendable | An agent reads its connections with: ```bash catenary list ``` Connected files appear under **Connected files**; the agent opens them with its ordinary file tools. ## Two behaviours Click a wire to open its card. Under **How this wire works** there are two choices. **AI Agent in control** — the default. The wire is a permission and nothing is sent automatically: either agent calls the other with `catenary ask`, or reads its screen with `catenary check`, when it needs to. Both ends can call, so for these commands the wire has no direction. **Automatic conversation.** When one agent finishes a turn, its output is delivered to the other — costing a turn there. The relayed prompt arrives prefixed with `[catenary]`, so the agent knows the message came over a wire and not from you. Turn on **Both sides respond** and the same wire runs both ways, within an exchange budget. ## Agent to agent The common shape is one agent delegating to another: ```bash # In the Claude terminal, wired to the Codex terminal: catenary ask "Codex 1" "Take the N+1 in the dashboard query. Context attached." catenary check "Codex 1" ``` `ask` waits for the answer and returns it to the agent that asked. In an automatic conversation where both sides respond, the peer answers by writing a line that starts with `@catenary`, and the reply travels back across the same wire. Agents in the same session do not even need a wire. With **Let agents talk without asking** on (the default, in **Settings, Wiring & Maestro**), `ask` reaches them directly. An agent in another worktree always asks you first. ```media Claude delegating to Codex over a wire, and the answer coming back. ``` ## Boards A board is shared Markdown on the canvas: right-click the canvas and pick **New Board**. Its file lives in the project, and on a task branch it goes into that branch's worktree. Wire a terminal to a board and the line turns yellow. That wire is the permission: the terminal now sees the board in `catenary list` and reads and writes it. A terminal with no wire to a board does not know it exists. ```bash catenary board list catenary board read "Board 1" catenary board append "Board 1" "Auth refactor done; tokens.ts is next" ``` `append` adds a signed line and never loses another writer's text. `write` replaces the whole board, so keep it for a board that is yours alone; `edit` replaces one passage. Right-click a board wire for its card. **Disconnect** hides the board from that terminal and leaves the wire dashed, **Connect** gives the access back, and **Disconnect wire** removes the wire. ## Rules that keep it sane - Never re-send a prompt to an agent that is mid-turn. `ask` tells you it is busy; use `check` instead. - Wires are unlimited on both Free and Pro. --- # Maestro Mode & squads Maestro Mode lets one agent build and run a team: recruit peers, brief them, wire them together and follow their progress. It is off by default and switched on by a human click. ## The rule that makes it safe Recruiting an agent or dismissing a finished one opens an **editable approval card** before anything happens on the canvas, and you edit, approve or refuse it (**Deny**). Wiring two of its agents together is approved on its own by default, unless they are in different worktrees. The team organises itself. You stay the one who says yes. ```media An approval card for a recruit action, edited and then approved. ``` ## The commands ```bash catenary maestro status # recruits and remaining slots catenary maestro recruit 2 claude-code "Write tests for src/auth" catenary maestro connect "Claude 1" "Claude 2" # wire two recruits together catenary maestro dismiss "Claude 2" # close a finished recruit ``` The objective passed to `recruit` becomes the new agent's opening prompt. Later instructions go through `catenary ask`. Dismiss a recruit as soon as its objective is done — an idle agent still holds a slot. ## The workflow 1. **Survey.** `catenary list` and `catenary maestro status` — who exists, what is free. 2. **Evaluate.** Trivial work stays with the maestro. Parallelisable work gets delegated. 3. **Delegate.** `recruit` for new hands, `ask` for peers already on the canvas. 4. **Review.** `check` to follow without interrupting; `dismiss` to clean up. ## Helper limits | Plan | Helpers | | --- | --- | | Free | 2 | | Pro | 10 by default, adjustable between 2 and 50, or unlimited | ## Squads A squad is a saved formation: roles, agent presets and the wires between them. Load one and the whole team appears already connected and already briefed with its role prompt. Five squads ship built in — among them **Fullstack Duo**, **TDD Autonomous Squad**, **Fullstack Trio**, **Security & Code Review Squad** and **Enterprise Full Squad**, which puts a Maestro over a Backend, a Frontend, a QA Tester and a Code Reviewer. Every squad has exactly one leader, and the formation — leader on top, team in a row beneath — is derived when the squad loads, so nothing is hand-placed. Loading a squad spends the same helper budget as recruiting by hand, so the plan decides which ones fit: Free loads the four squads of up to three agents, and the five-agent Enterprise Full Squad needs Pro. Building your own is unlimited on Pro: pick the roles, name them whatever your team calls them, and save. ```media Loading the Enterprise Full Squad: five panels and two wires appearing at once. ``` --- # 1-click worktrees The feature that makes parallel agents safe. **New Task** (`⇧⌘N`) creates an isolated git branch, its own working directory and, when you give it a task, an agent to work in it — without touching the code in front of you. ## What one click does 1. Creates a branch from your current HEAD. 2. Creates a real `git worktree` in its own directory, so the files are physically separate. 3. Opens a terminal panel already inside it, with the agent running. 4. Assigns the task a colour that follows it everywhere. The task is optional. Leave it empty and the button becomes **Create Worktree**: the worktree opens in a plain terminal, with no agent, for you to work in by hand. Tasks run side by side, each on its own branch and in its own directory, and none of them can step on the file you have open. How many at once is the one thing the plan decides — two on Free, as many as the machine takes on Pro (see the limits below). ```media Clicking New Task three times: three branches, three agents, three colours. ``` ## The colour is the point The same colour marks the task in the sidebar, on its dock tabs and on its territory on the canvas. When four agents are talking at once, colour is what tells you which branch a given panel belongs to before you read a single word. ## Territories Turn on **Settings, Worktrees, Worktree Territories** and every panel belonging to a task is enclosed in a coloured island. Panels of the same branch merge into one shape; a panel dragged out of the group takes its colour with it. It is off by default: on a busy canvas the islands are information, and on a quiet one they are decoration. The switch is yours. ```media The territories switch flipped on, with two branches forming two islands. ``` ## Finishing a task The branch is an ordinary git branch and the worktree is an ordinary git worktree. The branch menu at the foot of the sidebar lists each task with three actions: **Review Diffs**, which opens a [Monaco](/docs/editor) diff for every file the branch changed, **Create pull request** and **Discard this work…**. Or merge it the way your project merges anything, and remove the worktree when you are done. Nothing about the task is proprietary — if you uninstalled Catenary right now, `git worktree list` would still show exactly what it created. ## Limits | Plan | Parallel tasks | | --- | --- | | Free | 2 | | Pro | Unlimited | --- # Monaco editor & diffs The editor panel is Monaco — the editor VS Code is built on — running inside the canvas. ## Opening files `⇧⌘E` opens an editor panel, `⌘P` is the quick file finder and `⌘S` saves. The file tree in the sidebar (`⇧⌘X`) is git-aware, so a modified file is marked as modified while you are looking at it. TypeScript, JavaScript and Python files get completion, hover, go to definition, references, rename and diagnostics from a local language server, the same one your agents query. Go, Rust, C and C++ files get the same when `gopls`, `rust-analyzer` or `clangd` is installed and on your PATH. See [LSP and tools for agents](/docs/agent-tools). ```media Quick-opening a file from the finder into a new editor panel. ``` ## Reading what an agent changed This is why the editor sits on the canvas next to the agents: a side-by-side diff of everything the agent touched, in the same view where the agent is still working. ```diff export async function refresh(t: Token) { - const res = await fetch(URL, { method: "POST" }) + const res = await withRetry(() => + fetch(URL, { method: "POST", signal })) if (!res.ok) throw new AuthError(res.status) return res.json() as Promise } ``` Read it, keep it or drop it — before it merges anywhere. ```media A diff opening beside the agent that produced it, then being accepted. ``` ## When an agent edits the same file You have unsaved changes, and an agent writes to the same file. Catenary never overwrites what you typed. A strip appears above the editor: **Changed on disk. Your unsaved edits are kept.** | Button | What it does | | --- | --- | | **View diff** | Shows the version on disk against your unsaved changes | | **Reload** | Takes the version on disk | | **Keep mine** | Keeps your buffer; the next save writes it over the disk | | **Keep both** | Merges the two. Edits that do not overlap combine; the ones that do get conflict markers, for you to review before saving | With no unsaved changes there is nothing to protect, and the editor simply reloads. If the file is deleted while it is open, the strip says so and offers **Save to restore**. ## Previews A Markdown file has a **Source | Split | Preview** switch at the top right, and ⇧⌘V toggles the preview. It renders tables and task lists, `> [!NOTE]` callouts, Mermaid diagrams and math, through KaTeX. A Jupyter notebook (`.ipynb`) opens as a notebook, read-only: the Markdown cells as in the preview, the code colored by the editor and the outputs as the notebook saved them. Nothing runs, because there is no kernel. **Open as JSON** shows the raw file. PDF, `.docx` and image files open in a document panel. ## Links in code Hold ⌘ and click a `http://`, `https://` or `mailto:` link in the editor, and it opens in your default browser. ## Search `⇧⌘F` opens content search across the workspace, backed by ripgrep: literal or regex, case and whole-word options, include and exclude globs, and `.gitignore` respected by default. ## Tabs and panels One editor panel holds one file, the same way a terminal panel holds one session. Two files side by side means two panels — that is what the canvas is for. Drop several of them into the same dock zone and they stack as tabs there instead. A single click in the file tree opens a **preview** panel: the next single click reuses it rather than piling up another one. Double-click the file, or edit it, and the panel is kept. --- # Keyboard shortcuts Every binding below is the shipped default, and every one of them is rebindable in **Settings, Shortcuts**. The combinations follow the operating system picked at the top of the sidebar — and on a Mac they are the very glyphs the app itself displays. ## Creating panels | Action | Shortcut | | --- | --- | | New Terminal | ⌘T | | New Browser | ⇧⌘B | | New Editor | ⇧⌘E | | New Catenary Agent | ⇧⌘A | | New Agent Task (worktree) | ⇧⌘N | | New Canvas | ⇧⌘C | | New File | ⌘N | | Close Panel | ⌘W | | Delete Focused Panel | ⌘ Backspace | ## Lenses, splits and sessions | Action | Shortcut | | --- | --- | | Canvas / TerminalMap | ⌥⌘S | | Split Terminal Right / Down | ⌘D / ⇧⌘D | | Split Zoom (Toggle) | ⇧⌘↩ | | Focus Split Left / Right / Above / Below | ⌥⌘← / ⌥⌘→ / ⌥⌘↑ / ⌥⌘↓ | | Sidebar: Sessions | ⇧⌘S | | Jump to Unread | ⇧⌘U | ⌥⌘← and ⌥⌘→ are shared with Next / Previous Workspace. What decides is the focus, not the lens: inside a split terminal they move between its panes, and anywhere else they switch workspace. ## Navigating the canvas | Action | Shortcut | | --- | --- | | Zoom In / Out / Reset | ⌘= / ⌘- / ⌘0 | | Zoom to Fit | ⌘1 | | Zoom to Selection | ⌘2 | | Toggle Select / Hand Tool | ⌃Space | | Auto Layout Canvas | ⇧⌘L | | Focus Next / Previous Panel | ⌃TAB / ⇧⌃TAB | | Navigate Up / Down / Left / Right | ⌘↑ / ⌘↓ / ⌘← / ⌘→ | | Pan Up / Down / Left / Right | ⇧↑ / ⇧↓ / ⇧← / ⇧→ | ## Finding things | Action | Shortcut | | --- | --- | | Command Palette | ⌘K | | Quick Open File | ⌘P | | Toggle Search | ⇧⌘F | | Toggle Sidebar | ⌘B | | Toggle File Explorer | ⇧⌘X | | Toggle Minimap | ⇧⌘M | ## Files and history | Action | Shortcut | | --- | --- | | Save File | ⌘S | | Undo / Redo | ⌘Z / ⇧⌘Z | | Toggle Markdown Preview | ⇧⌘V | | Next / Previous Workspace | ⌥⌘→ / ⌥⌘← | ```media The Settings, Shortcuts panel: rebinding one action and resetting it. ``` ## Rebinding Open **Settings, Shortcuts**, click a binding and press the new combination. Only the bindings you changed are stored; the rest keep following the defaults. An empty binding disables the action, and one click resets it.