Extensions

Extensions are opt-in, agent-agnostic add-ons that compose Thurbox through the public thurbox-cli surface — they never extend the binary. The core knows a declarative manifest format , never any specific extension, so the same machinery installs and manages any of them.

Overview #

An extension is a directory with a single extension.toml manifest plus the files it ships (specs, scripts, config templates). One command installs it: thurbox-cli fetches the manifest, lays the files down under a home directory, registers any agents the extension needs in agents.toml , then creates — and keeps alive — the sessions and automations the extension declares.

  • Data, not binary. Nothing about an extension is compiled in; the core reads a manifest and acts on it.
  • Agent-neutral. Extensions reach coding agents only through agents.toml aliases you remap to any CLI (claude, codex, antigravity, opencode, vibe, …).
  • Self-healing. While an extension is active, deleting its session or automation is a no-op — Thurbox recreates it. Deactivating is the real off-switch.

Four extensions ship today: flow , forge , ci-shepherd , and renovate . Each has its own page (see Available extensions ). The commands and manifest fields below are generic; the examples use flow.

One extension ships built in: agent hooks . Unlike the others it's embedded in the binary and auto-activated , wiring each agent's lifecycle hooks to thurbox-cli session signal so the session list shows working/blocked/done/idle. It still installs through the same manifest machinery shown here.

Install #

Install an extension by name from the official source:

bash
thurbox-cli extension install flow

That single command is the whole installer. It resolves the source, fetches the manifest and payload, writes them under the extension home ( ~/.config/thurbox/extensions/<name> by default; --home <dir> to override), registers the extension's agents, writes the resolved manifest to ~/.config/thurbox/extensions/<name>.toml , and activates it. It is idempotent — re-running refreshes shipped files while keeping your own data (seeded files you've edited, agent tweaks).

Heads up: The flow extension is experimental and under active testing — its behavior, spec, and manifest may change between releases.

Lifecycle commands #

All extension management lives under thurbox-cli extension (alias ext ):

Command What it does
install <name|url|dir> Fetch + lay down files, register agents, write manifest, and activate.
uninstall <name> Reverse an install: tear down the session/automation, remove the extension's agents, and delete the manifest. Add --purge to also delete the home dir.
activate <name> (Re)create the declared sessions/automations and mark the extension active.
deactivate <name> Tear down resources and stop self-heal (the off-switch). Add --force to kill tmux/worktrees, --purge to also drop the manifest.
list Show installed extensions with their active / healthy state.
status [<name>] Per-resource presence for one extension (or all).

Install vs. activate. install also lays down files and registers agents; activate only (re)creates the runtime resources from an already-installed manifest. Use deactivate to switch an extension off but keep it installed for a later activate .

Sources & versioning #

The install target can be three things:

  • A bare name ( flow ) — fetched from the official source over curl / wget , pinned to your binary's release tag (dev builds track main ), so a fetched extension always matches the binary reading it.
  • A local directory ( ./extensions/flow ) — installs from a checkout.
  • An http(s):// base URL — installs from your own source.
bash
thurbox-cli extension install ./extensions/flow
thurbox-cli extension install https://example.com/ext/flow --home ~/work/flow

Safety: payload paths are validated against traversal (no absolute paths or .. ), a config template you've edited isn't overwritten on reinstall (use --force ), and payload files are fetched as text (specs, scripts, JSON) — not binaries.

Self-healing #

An installed extension is recorded in an active set . On TUI startup and on every automation tick, Thurbox re-ensures each active extension's declared sessions and automations exist — so deleting them by hand (TUI Ctrl+D , a clean , or thurbox-cli session/automation delete ) is a no-op: they come back. This is what makes an extension hard to half-remove by accident.

  • deactivate <name> removes the extension from the active set, so self-heal stops resurrecting it — the real off-switch.
  • Headless self-heal (while the TUI is closed) rides the automation heartbeat, so it needs [features] automations = true ; with automations off, healing happens at the next TUI startup only.

The manifest #

An extension is fully described by its extension.toml . It has two halves: an install spec (what to lay down) and a runtime spec (what to keep alive). The {home} token is substituted with the resolved home directory.

extension.toml
name = "flow"
description = "Focus-protecting triage agent"
config_version = 1
# home = "~/flow"               # OPTIONAL; default is under the config dir
                                # ({home} is substituted everywhere it appears)

# install spec ---------------------------------------------------------------
[[agents]]                      # registered in agents.toml (existing kept)
name = "flow"
command = "claude"
args = ["--model", "claude-haiku-4-5"]

[[files]]                       # fetched from the source, written under home
path = "FLOW.md"
[[files]]
path = "scripts/create-task.sh"
executable = true               # chmod +x
[[files]]
path = "repos.md"
if_absent = true                # seed once; never clobbered on reinstall
[[files]]
path = ".claude/settings.json"
source = "claude-settings.json" # source path differs from dest
substitute = true               # replace {home} in the content

[[symlinks]]                    # never clobbers a real file at `link`
link = "CLAUDE.md"
target = "FLOW.md"

# runtime spec (ensured on activate, self-healed if deleted) -----------------
[[sessions]]
name = "flow"
agent = "flow"
repo_path = "{home}"            # resolved to the absolute home at install

# [[automations]] is an OPTIONAL runtime resource (flow itself ships none —
# it is purely event-driven). An extension that wants a scheduled tick declares:
[[automations]]
name = "example-tick"
trigger = "cron:*/10 * * * *"   # same grammar as `automation create --trigger`
session_ref = "flow"            # must match a [[sessions]] name above
prompt = "tick"
Section Purpose
home Default install directory; overridable with --home .
[[agents]] Agent definitions appended to agents.toml (existing names are kept).
[[files]] Payload files written under home . Flags: executable , if_absent (seed once), substitute ( {home} in content), and source (when the source path differs from the destination).
[[symlinks]] Symlinks created under home (never clobber a real file).
[[sessions]] Sessions ensured on activate and self-healed if deleted.
[[automations]] Automations ensured on activate; session_ref names a session above.

Authoring an extension #

  1. Create a directory with an extension.toml and the files it references ( [[files]] paths are relative to both the source and the home dir).
  2. Build the behavior on the thurbox-cli surface ( session , task , automation ) plus standard tools — no core changes, no vendor lock-in.
  3. Test locally with thurbox-cli extension install ./your-ext , then publish the directory (e.g. under extensions/<name>/ ) so install <name> can fetch it.

For the exact config-file locations and the metadata key that tracks active extensions, see the configuration reference .

Available extensions #

Each extension has its own page with what it does, how to install it, and how to use it. They are grouped by what they do:

Built in

Ships embedded in the binary and is active by default — no install step.

Triage & workflow

Agents that decide what to work on next and surface patterns in how you work.

Repository automation

Workers that keep your repos green and up to date by opening review PRs.

Issue tracker sync

Bidirectionally mirror an external tracker's issues into the task list — no agent, just a deterministic 15-minute sync.