Scherzo turns tracker tasks into supervised, repeatable coding-agent workflows. The production tracker adapter is Linear today: Scherzo polls tasks from Linear, selects them by workflow labels, prepares per-run workspaces, executes YAML DAGs made of pi agent steps and shell command steps, retains artifacts, and hands results back through the tracker.
Scherzo is a Gleam/Erlang daemon and command-line tool. It is currently best suited for teams that are comfortable running their own local automation, reviewing agent output, and adapting repository-local YAML, prompts, schemas, and workspace policy.
Use Scherzo when you want to:
- run the same agent workflow for every eligible task instead of one-off chats;
- route tasks by labels such as
workflow:implementationorworkflow:research; the current production task source is the Linear adapter; - isolate implementation attempts in workspace-driver-managed directories;
- combine agent steps, command validation steps, review steps, and tracker task updates;
- retain artifacts and operator-visible events for inspection and recovery; and
- start cautiously with
doctorand--oncebefore daemon mode.
Scherzo is not a hosted product, a sandbox, or a stable multi-tracker platform. It currently ships one production tracker adapter, Linear, and uses pi for agent execution. Do not use it as unattended production automation until your repository-specific workflow, workspace driver, Linear policy, credentials, and validation commands have been reviewed by an operator.
Workflow files and workspace drivers are trusted local configuration. Scherzo enforces workspace cwd/root containment, but it does not provide a VM or container boundary.
If you are adapting Scherzo to another repository, start with the guided adopter path:
- Getting started — from minimal repo config to a cautious
--oncerun, including YAML editor schema setup. - Simplified YAML migration guide — old/new config examples and upgrade checklist.
- Example orchestrator config — complete source-tree example.
- Packaged no-op driver example — artifact-only/research workflows.
- Packaged jj driver example — implementation workflows with the bundled jj driver.
- Example workflows — YAML DAGs and prompt templates.
The usual first run is:
scherzo --version
LINEAR_API_KEY=lin_api_... scherzo doctor .scherzo/scherzo.yaml
LINEAR_API_KEY=lin_api_... scherzo --once .scherzo/scherzo.yaml
LINEAR_API_KEY=lin_api_... scherzo .scherzo/scherzo.yaml
scherzoctl psThe packaged scherzo launcher is the foreground daemon command and translates terminal Ctrl-C into Scherzo's graceful SIGTERM shutdown path. The deprecated scherzo-start alias has been removed; replace old scherzo-start <config> or nix run .#scherzo-start -- <config> usage with scherzo <config> or nix run .#scherzo -- <config>. When working from this source checkout, run non-daemon entrypoints through devenv, for example direnv exec . gleam run -- doctor .scherzo/scherzo.yaml or direnv exec . scripts/scherzoctl ps.
Keep the specs as normative references. The getting-started guide intentionally links to them instead of duplicating the full command and schema contracts.
A typical consuming repository uses this layout:
.scherzo/
scherzo.yaml # orchestrator/runtime config
workflows/
implementation.yaml # workflow DAG
research.yaml # workflow DAG
prompts/
implement.md # prompt template
research.md # prompt template
schemas/ # public YAML schemas and optional structured-output schemas
scripts/ # optional validators or custom workspace drivers
This repository dogfoods the same shape under .scherzo/ and keeps reusable examples under examples/.
- Orchestrator config (
.scherzo/scherzo.yaml) owns tracker settings, polling, top-level workflow routes, workspace drivers, agent runtime settings, task-update policy, artifact limits, and tracker readiness checks. In this repository those checks target Linear throughtracker.linear.check_setup. - Workspace drivers decide where each step runs. Bundled packaged drivers include
scherzo-workspace-noopfor artifact-only workflows andscherzo-workspace-jjfor jj-backed implementation workspaces. Custom drivers must follow the workspace driver spec. - Workflow DAGs are YAML files routed by task metadata, currently workflow labels on Linear tasks. Steps infer agent vs command behavior from
promptorrun, run in lanes selected byrun_in, and userecoveryfor bounded step remediation. - Structured output lets an agent step return a required JSON artifact and validate it with baseline checks, JSON Schema validators, command validators, or both.
- Operator observability includes daemon logs, retained artifacts, and outbound tracker updates; with the current production adapter those updates are Linear comments. Operator control is local through
scherzoctlcommands such asps,session,events,attach,pause,resume,retry,park,abort, andprompt.
Workspace drivers decide where workflow steps run and what isolation/publish behavior they get. The normative contract is docs/specs/WORKSPACE_DRIVER_SPEC.md; migration notes for unsupported legacy workspace hooks/profile config are in docs/runbooks/workspace-driver-migration.md.
In config, workspace.driver selects the built-in noop or jj driver, or a named entry under workspace.drivers. Named entries use type: noop, type: jj, or type: custom; custom entries provide command plus optional timeout and env, while type: jj supports friendly fields such as publish_remote, github_repo, and fetch_base that map to the driver environment. Workflows request capabilities with workspace.requires, and Scherzo exposes driver context such as SCHERZO_WORKSPACE_DRIVER and SCHERZO_WORKSPACE_CAPABILITIES to steps. Driver-specific settings may live in env, for example SCHERZO_JJ_WORKSPACE_PUBLISH_REMOTE or SCHERZO_PR_DRAFT, but driver env is not a secret store. SCHERZO_PR_DRAFT accepts only true or false; when unset, PR publication keeps the driver's default draft behavior.
Use the checked-in operator skill when supervising Scherzo from pi: /skill:scherzo-operator or pi --skill .pi/skills/scherzo-operator. Start with read-only summaries first, using SCHERZO_CONTROL_FILE when needed and exact task/issue ids or session ids from JSON inspection, for example scripts/scherzoctl ps --json.
This repository uses .envrc/devenv. In a fresh checkout, approve the environment once:
direnv allow .Common source-checkout commands:
# Deterministic unit suite
direnv exec . gleam test
# Shell-heavy script/workflow/daemon/process/driver contract suite
direnv exec . scherzo-test-contract
# CI-friendly shards are also available, for example:
direnv exec . scherzo-test-contract runtime
# Production lint gates
direnv exec . gleam run -m glinter
direnv exec . gleam run -m scherzo_lint
# Source/build identity for bug reports and operator logs
direnv exec . gleam run -- --version
# Readiness validation before dispatching work
LINEAR_API_KEY=lin_api_... direnv exec . gleam run -- doctor .scherzo/scherzo.yaml
# Cautious one-task run; with the current production adapter this dispatches one eligible Linear task
LINEAR_API_KEY=lin_api_... direnv exec . gleam run -- --once .scherzo/scherzo.yaml
# Ctrl-C-friendly packaged daemon mode and control UI
LINEAR_API_KEY=lin_api_... nix run .#scherzo -- .scherzo/scherzo.yaml
direnv exec . scripts/scherzoctl psEvery PR should run the deterministic unit suite before review:
direnv exec . gleam test
# equivalent explicit wrapper:
direnv exec . scherzo-test-unitShell-heavy script, workflow-helper, renderer, daemon/service, port/process, pi-client, and workspace-driver contract coverage is explicit so the default loop stays unit-scoped:
direnv exec . scherzo-test-contractFor CI or local runners with per-command timeouts, run the contract shards separately. The test runner serializes suites with test/.tmp-suite-lock and resets test/tmp at suite start, so parallel suite invocations wait instead of sharing scratch space; do not clean test/tmp manually while another suite is active:
direnv exec . scherzo-test-contract runtime
direnv exec . scherzo-test-contract orchestrator
direnv exec . scherzo-test-contract tracker
direnv exec . scherzo-test-contract workflow
direnv exec . scherzo-test-contract repositoryRun the contract suite or the relevant shards when changing helper scripts such as .scherzo/workflows/scripts/scherzo-review or .scherzo/workflows/scripts/scherzo-implementation, ExecPlan HTML rendering, daemon/service behavior, port/pi-client process boundaries, workspace driver scripts, or before relying on repository confidence from the final gate.
The explicit integration suites are opt-in because they have required dependencies outside the normal unit and contract loops: scherzo-test-local-integration exercises local jj/workspace behavior, and scherzo-test-real-pi-validation uses the devenv-provided pi plus working model/provider credentials.
For the full local gate used by dogfood implementation workflows, run scripts/scherzo-ci. It runs formatting, production lint, workflow contracts, the unit and contract suites, and nix flake check; local-integration and real-pi-validation remain explicit because of their external dependency requirements. Pass a target (for example scripts/scherzo-ci unit) to run a subset.
direnv exec . scripts/scherzo-ciScherzo is in active development and is dogfooded for real project work. Expect rough edges:
- Runtime configuration and workflow definitions are YAML-only and may still change. Markdown is supported for prompt templates, not runtime workflow definitions.
- Linear and
piare the first-class integrations today. - Workspaces, credentials, model/provider settings, schemas, tracker-adapter capabilities, and validators are intentionally explicit repository policy.
- Operators should expect to inspect logs, retained artifacts,
scherzoctloutput, and tracker comments when something goes wrong. In this repository those tracker comments are Linear comments.
Scherzo is licensed under Apache-2.0. See LICENSE for the full license text.