Skip to content

Customizing Growlight

What growlight init scaffolds is a default, not a standard. This page lists the knobs in rough order of how often you will reach for them — the same theme as the rest of the garden: make it your own.

The loop drains exactly what you queue, so curating the backlog is directing the loop. Change it through soft-fig’s write verbs (from a Claude session, or the CLI/TUI), never by hand-editing queue files.

  • A task is one self-contained piece of work. A milestone is a larger effort broken into ordered slices that the loop takes one at a time.
  • Order is priority. Reordering reprioritizes the loop.
  • Status is the control surface: queued, active, paused, blocked (needs your decision), deferred (finished except for a human-only step), done.
  • Hold an item for yourself. A > Fleet: no line in an item’s doc keeps the fleet from claiming it. It stays queued, shows under held in softfig growlight status, and is claimed only when you remove the line.

config/growlight.toml has a queue key that picks which model growlightd schedules from:

queue = Model Edit it with
"legacy" (default) A backlog table with named queues. MCP: add_backlog_item, add_slice, set_item_status, reorder_backlog_item, add_queue.
"v2" Per-item state files; every queue bound to a repo. MCP: queue_add_project, queue_add_entry, queue_update_entry, queue_drop, slice_insert, slice_update. CLI: softfig growlight queue … / slice ….

An unknown value is refused at arm time. Both families are in the MCP verb reference; in practice you describe the work to Claude and it fires the right verb, as in the Starter Prompts.

v2 keeps state in three kinds of TOML file under growlight/backlog/:

  • queue.toml — [[project]] rows (a name bound to a repo path and its merge branch) and [[entry]] rows, in list order. Each entry has a kind (milestone, task, or a generated restack), a project, a lane (urgent always drains first, then normal), a status, and optional after links (ids that must be done first). Branches are named feat/<id> for milestones and fix/<id> for tasks.
  • queue-archive.toml — rows that finished (done) or were dropped.
  • milestones/<id>/slices.toml — one milestone’s slice order and status.

The softfig growlight queue subcommands (show, project add, add, move, lane, after, status, drop, pick) and slice (insert, move, status) wrap those verbs, and most take --dry-run to validate and print the would-be result without writing. The files are strictly validated: a malformed one is refused, never half-read.

A queue can be bound to a repository, so its work runs in that repo’s directory: the garden’s queue writes through MCP while a project’s queue commits to its own git repo on feature branches. In v2 the binding is the [[project]] row. In legacy, bind with add_queue and file items into it. An item can also name a specific checkout in a > Worktree: line.

A fleet member can be pinned to one queue (pin = "name" in config/growlight.toml) or left free to take ready work from any queue. Keeping a repo in its own queue is also a safety boundary: a fleet draining the default queue will not wander into one reserved for human-present work.

Each fleet member picks backend = "claude" (default) or "opencode" with a required model; see Running → Backends. An item can also declare which model should work on it with a > Model: line in its doc (for example > Model: reasoning, flash), which softfig growlight start --model auto honors. Match the model to the item’s difficulty and cost, not to the garden.

The numbers live in growlight/session-policy.md, a plain editable file the protocol enforces. Defaults:

Budget Default What it does
Context (per session) roll at ~50%, hard stop ~60% Ends the session on a clean baton before quality degrades.
Session (5-hour) reserve at 85% Stops starting work near the account limit, leaving room for a tidy handoff.
Weekly guard at 90% The outer backstop.

The daemon applies the same thresholds as its admission policy; softfig growlight status prints the values in force. Metered opencode members are not counted against the Anthropic windows. To cap spend, bound the roster rather than trusting a single number.

  • Concurrency. growlightd runs at most two agents by default. Change it with --max-concurrent-agents on the daemon (edit ExecStart in your unit). Start low on a small device: contention comes from builds, not from waiting on the API.
  • Build caps. softfig growlight resources set adjusts each agent’s --build-jobs, --memory-high and --cpu-weight live: a soft throttle, never a kill.
  • Bounded runs. max_iterations = 1 in growlight.toml stops the fleet after that many completed chunks, which is handy for a first supervised unattended run.

growlight/protocol.md is the contract injected into every session, kept fixed within a run so a fresh session picks up instantly. It is yours to edit (a tighter context band, a different handoff ritual, an extra standing rule), knowing every later session inherits the change. Change it on purpose and record why with a decision.

Back to Overview · Running Growlight.