Canopydocs v0.4.7

Where settings live

Canopy's configuration is split by what it belongs to: your machine, the repository, or the running state.

LayerLives inTravels with the repo?Hand-editable?
App settingssettings.jsonNoYes, when the app is closed
Repo provisioning<repo>/.worktreemanager.jsonYes, commit itYes
Runtime statestate.jsonNoNo
AppearancelocalStorageNoVia the UI
Worktree contextlocalStorageNoVia the context editor
Pins, multi-selectionlocalStorageNoVia the UI

Paths by platform#

Canopy uses the platform's app-config directory under the bundle identifier com.midhunkumare.canopy.

PlatformSettings and stateLog file
macOS~/Library/Application Support/com.midhunkumare.canopy/~/Library/Logs/com.midhunkumare.canopy/canopy.log
Linux~/.config/com.midhunkumare.canopy/~/.local/share/com.midhunkumare.canopy/logs/canopy.log
Windows%APPDATA%\com.midhunkumare.canopy\the platform log dir, canopy.log

Both settings.json and state.json sit in that directory. Settings → Advanced shows the path with a copy button.

settings.json#

Everything you configure in the platform pages and in the four repository pages that aren't the config file. settings.json & state.json has the shape and every field.

You can edit it by hand while Canopy is closed. While it's open, the backend holds the authoritative copy in memory and rewrites the file on save, so your edit would be overwritten.

state.json#

Runtime bookkeeping, not user configuration:

  • portIndices, each worktree's stable index per repository. This is what keeps ports from shuffling.
  • portOverrides, explicit per-service port overrides.
  • orphans, process-group ids and start times, so a crashed Canopy's leftover services can be swept on the next launch.

Don't hand-edit it. Deleting it is recoverable but disruptive: indices get reassigned, so derived ports change, and any override is lost.

.worktreemanager.json#

In the repository root, and wtm.json is accepted too. Canopy looks in the worktree first, then the main checkout. A committed copy travels per branch, while an uncommitted copy in the main checkout works as a fallback while you're still iterating on it.

Full schema: .worktreemanager.json.

localStorage#

The webview's storage, shared by every Canopy window since they're all the same origin.

KeyContents
canopy.appearance{ theme, density, accent, fontScale }
canopy.ctx.<worktree path>That worktree's agent context: title, body, links, files, PR and issue fields
pins / selection keysWhich worktrees are pinned, and the current multi-selection

Appearance changes broadcast to the other windows through a storage event, so a theme switch applies everywhere at once. Clearing site data for the app resets appearance and loses saved contexts, though .canopy/context.md files already written into worktrees aren't affected.

.canopy/ inside a worktree#

Launch an agent and Canopy writes <worktree>/.canopy/context.md. If the directory is new it also writes a .gitignore beside it that ignores the directory itself. An existing .gitignore is never overwritten.

In-repo worktree roots#

If your worktree root sits inside the repository, which is what the default .worktrees does, Canopy self-ignores it so the worktrees don't turn up as untracked files in the parent checkout.

Backup and migration#

Copy settings.json to bring your repositories, services, agents and commands with you. Leave state.json behind and let the new machine assign its own indices. .worktreemanager.json comes with the repository, which is the whole point of it.

Documentation for Canopy 0.4.7. Controls marked coming soon are present in the interface but have no implementation behind them yet.