# TermCanvas puts git worktrees on a zoomable desktop canvas and registers two CLIs to drive it

> An Electron app that lays terminals out spatially under a project, worktree and terminal hierarchy, with a bundled CLI that can create worktrees and dispatch agent prompts from any shell. Unsigned macOS builds, an arm64 naming trap, and a three-binary bin map explain most of what to expect.

**blueberrycongee/termcanvas** — An infinite canvas desktop app for visually managing terminals

- Repository: https://github.com/blueberrycongee/termcanvas
- Website: https://website-ten-mu-37.vercel.app
- Stars: 406 · Forks: 34
- Language: TypeScript
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/blueberrycongee-termcanvas

## The canvas is built on worktrees rather than on window positions

The organising idea is a three-layer hierarchy: projects contain worktrees, worktrees contain terminals. Adding a project makes the app detect its worktrees, and a worktree created from inside a terminal shows up on the canvas without a manual add.

That choice is what separates the app from a tiling window manager. There is no split pane and no tab strip, because the spatial layout is the navigation: you drag tiles, box-select several at once, double-click a title bar to zoom to fit, and pull back out to see the whole arrangement. Annotations live on the same surface, so sketches, callouts and grouping lines sit next to the terminals they describe.

The trade is that state has to persist somewhere, and it does so in a single .termcanvas file you save yourself. The app is a canvas with a saved layout, not a terminal multiplexer with persistence built in.

## Registration writes hook trust state into your Codex config

Two CLIs ship inside the app and neither is on your PATH until you enable it. The route is Settings, then General, then Command line interface, then Register, which adds termcanvas and hydra.

The consequence worth reading twice is that the same step also installs TermCanvas skills and lifecycle hooks for Claude and Codex. For Codex 0.129.0 and newer, the app writes the required hook trust state into ~/.codex/config.toml so the generated hooks are reviewed and trusted, and so they keep emitting terminal lifecycle and telemetry events.

So clicking Register edits a configuration file belonging to another tool. The documentation states it plainly, but it is framed as a convenience step inside a settings panel rather than as a change to an external agent config.

## Intel builds launch on Apple Silicon through Rosetta and stutter

Release filenames carry the architecture, and the two variants behave very differently on an M-series Mac. Files with arm64 in the name, whether the .dmg or the .zip, are native builds. Files without arm64 are Intel builds. They still open on Apple Silicon through Rosetta 2, but panning and zooming the canvas becomes visibly sluggish, which for a canvas application is the whole interface.

The verification step is a system tool rather than anything in the app: open Activity Monitor, find TermCanvas, and read the Kind column. It should say Apple. If it says Intel, the fix is to delete the app and download the other file.

Nothing in the app detects this at startup, so the first person to notice is the one dragging tiles around wondering why the canvas stutters.

## Unsigned builds need the quarantine attribute cleared before they open

macOS can report the app as damaged or refuse to launch it, because the distributed build is unsigned. The documented remedy is one command:

```bash
xattr -cr /Applications/TermCanvas.app
```

The -c flag clears the quarantine attribute and the -r flag applies it recursively, so every file inside the bundle is released. If you installed somewhere other than /Applications, substitute that path.

This is the standard remedy for an unsigned app and it works, but it is also a request to disable a macOS safety check on a binary you did not build. The command has to be typed by the person installing, from a terminal, with the path spelled out, and nothing in it verifies what is being cleared.

## The CLI reference block is cut off mid-argument

The bundled termcanvas command is organised into groups, and the reference collapses the group list into a comment style block:

```
Usage: termcanvas <group> <command> [args]

Groups:
  project        add | list | remove | rescan
  worktree       list | create | remove
  terminal       create | list | status | output | destroy | set-title
  workflow       Lead-driven Hydra workflow over HTTP (init / dispatch / watch …)
  telemetry      get | events
  pin            add | list | show | update | rm
  diff           <worktree-path> [--summary]
  state          dump full canvas state as JSON
```

The block ends mid-word on the last line, at terminal create --worktree with the argument list truncated. The runnable examples that follow it are complete, including project add, a terminal create with a --type and a --prompt, status, telemetry get and a diff with --summary.

So the group inventory is a teaser and the examples carry the actual usage. One documented negative result matters more than the missing text: terminal input is explicitly not a supported dispatch path, and new agent tasks go through terminal create with a prompt.

## Building from source requires pnpm and the lockfile is not optional

Source builds go through four commands:

```bash
git clone https://github.com/blueberrycongee/termcanvas.git
cd termcanvas
pnpm install
pnpm dev
```

pnpm-lock.yaml is named as the canonical lockfile and pnpm 10.33.0 is pinned as the package manager in package.json, so installing with npm or yarn produces a different dependency graph than the one the project expects. A postinstall script runs automatically during pnpm install.

The repository is a pnpm workspace with a pnpm-workspace.yaml, and the tree is wide enough to show how much ships with the app: an electron/ directory for the shell, src/ and components/ for the renderer, cli/ for the binaries, hydra/ for the orchestration toolkit, server/, shared/, skills/, eval/, tests/, headless-runtime/, supabase/, website/ and browse/. Three tsconfig files cover the app, the headless build and Node-side tooling.

## Sign-in sync is the one part that leaves the machine

Usage tracking for Claude and Codex is broken down by model across all projects, with meters for the 5-hour and 7-day rate limits. Keeping those numbers in sync across devices requires signing in, and that is the single feature in this application that sends data off the local machine.

That sits in tension with the rest of the design. Terminals, worktrees, git history and session replays are local, and the .termcanvas layout file is something you save. A signed-in account is what connects your local sessions to another device.

The backend that would support it is visible in the configuration. The env example asks for Supabase project credentials, a VITE_SUPABASE_URL and an anon key, plus GitHub OAuth client id and secret for local development against the Supabase CLI. So the sync path runs through a hosted Supabase project you supply, and an offline-only install is the case where you skip that step.

## Conclusion

Adopt it if your terminal use already follows git worktrees, since the app's structure is the worktree structure rather than a window manager laid on top of it. Before you install, pick the build whose filename contains arm64 if you are on Apple Silicon, and read what the xattr command does before running it, since it clears quarantine on an unsigned app. Verify that registering the CLIs is acceptable in your environment first, because that step also writes hook trust state into your Codex config.

## FAQ

### Which TermCanvas build do I download for an Apple Silicon Mac?

Pick the file with arm64 in its name, either the TermCanvas-X.Y.Z-arm64.dmg or the arm64 mac zip. Files without arm64 are Intel builds that run through Rosetta 2 but lag when panning and zooming the canvas.

### How do I get the termcanvas and hydra commands on my PATH?

Launch the app, go to Settings, then General, then Command line interface, and click Register. That adds termcanvas and hydra to your PATH, and it also installs skills and lifecycle hooks for Claude and Codex.

### What does TermCanvas do when macOS says the app is damaged?

The builds are unsigned, so macOS can block launch. The documented fix is to clear the quarantine attribute with xattr -cr on the installed app path, then launch again.

### Can I dispatch work to an agent terminal from the TermCanvas CLI?

Use termcanvas terminal create with a --prompt argument. The documentation states that termcanvas terminal input is not a supported dispatch path, and for Claude and Codex task automation you start a fresh terminal that way.

### Does TermCanvas store my terminal sessions on a server?

Sessions are kept locally and organised as projects, worktrees and sessions, and layout saves to a .termcanvas file. Syncing usage across devices requires signing in, and the backend is a Supabase project configured through the env example.

## Sources

- [blueberrycongee/termcanvas on GitHub](https://github.com/blueberrycongee/termcanvas)
- [License: MIT](https://github.com/blueberrycongee/termcanvas/blob/main/LICENSE)
- [Project website](https://website-ten-mu-37.vercel.app)
- [README](https://github.com/blueberrycongee/termcanvas/blob/main/README.md)
- [Releases](https://github.com/blueberrycongee/termcanvas/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/blueberrycongee-termcanvas
