YYLO CLI

September 10, 2026 ยท View on GitHub

YYLO is a command-line orchestrator for coding agents, repeatable workflows, and receipt-backed repository changes. It is for developers who want a quick agent loop and for project operators who need typed task, validation, merge, and release-readiness boundaries.

YYLO orchestrates work. YYLO Ledger is the independent Git-native Record/task store, and YYLO Benchmark is the independent evaluation/evidence package. yy ledger and yy benchmark delegate to those separately installed CLIs; they are not bundled alternate implementations.

Quick start: install to first successful command

Prerequisites: Node.js 20.10 or newer, npm, and Git.

npm install --global '@yylo/cli@latest'
yy --version

mkdir yylo-demo
cd yylo-demo
git init
yy init --task "Document the onboarding path" --subagent pi
yy watch exec pwd

A successful run prints the installed YYLO version, initializes .juno_task/, then emits a watch receipt with "state":"COMPLETED", "exit_code":0, and nonzero log_bytes. This canary does not contact a model provider. In an empty, unborn Git repository, yy init creates the initial workspace commit, keeps the original branch as the product target, and creates a detached protected integration-owner worktree under the user state directory. Existing or dirty repositories are never committed or rearranged by this bootstrap.

Inspect the initialized workspace and exact command surface:

yy info --json
yy doctor workspace
yy --help

doctor workspace is intentionally nonzero when it finds an actionable topology problem; it never fetches or changes the workspace.

Stable and prerelease channels

The stable npm channel is @latest (0.2.2). Prereleases remain on @next:

# Stable
npm install --global '@yylo/cli@latest'

# Explicit prerelease
npm install --global '@yylo/cli@next'
# Exact local/prerelease candidate for reproducible installs
npm install -g @yylo/cli@0.2.3-rc.1

npm view '@yylo/cli' version dist-tags --json
yy --version

Pin an exact version in CI. Installing @next is an intentional prerelease choice. The first guarded release-helper checkpoint is exact --set v0.1.0-rc.1; later releases must use their separately authorized exact SemVer.

Next: run an agent, manage a typed task, or build a managed workflow.

Install agent skills explicitly

YYLO skill content is versioned independently in the public yylo-dev/yylo-skills repository and is not bundled in @yylo/cli. Install the latest stable release, or pin an exact stable version:

yy skills install
yy skills install --version 2.0.0
yy skills update --force
yy skills status

Only skills install and skills update access the network. Acquisition is staged through npx skills add first and falls back to a shallow exact-tag Git clone. The seven user-intent-first skills (artifact-yylo, ledger-tasks-yylo, plan-ledger-tasks-yylo, ralph-loop-yylo, understand-project-yylo, wiki-yylo, and workflow-yylo) are copied to .agents/skills, .claude/skills, and .pi/skills. Differing canonical directories are refused unless --force is supplied. An explicit install/update retires a legacy YYLO skill only when its local install record and current digest prove it unchanged; customized legacy and unrelated skills are preserved with a warning. skills list and skills status use only the local install record.

What YYLO owns

NeedPublic surfaceBoundary
Agent runyy pi, yy start, and the agent aliases listed by yy --helpProvider credentials and model availability remain external.
Session continuitycontinue, clone, branches, switch, continuityScope state is isolated and explicit; cleanup is planned and reversible.
Observable commands`watch execstatus
Validation evidence`evidence runstatus
Repository topologyinfo, where, doctor workspace, integrationRead-only discovery is separate from guarded sync/repair/push.
Feature lifecycle`task startrun
Protected delivery`merge statusplan
Maintainer releaserepository scripts/release-cli.shPrepare is read-only; publish needs separate authority.
Records/evaluationledger, benchmarkTransparent delegation to independently installed canonical packages.

Run yy --help for the complete top-level inventory of your installed version; each listed command prints its own usage when invoked with -h. The old lifecycle command is removed; use typed task and merge commands.

Beginner agent workflow

Install the coding agent you intend to use and configure its provider credentials separately. Pi is optional and supports multiple providers:

npm install --global '@mariozechner/pi-coding-agent'
yy pi --help
yy pi --no-session 'Summarize this repository and make no changes'

The final command may contact the configured model provider. --no-session prevents Pi session persistence; it does not disable provider usage.

For a reusable prompt or shell-sensitive text, prefer a file:

printf '%s\n' 'Explain the test layout. Do not edit files.' > prompt.md
yy pi --prompt-file prompt.md --no-session

Interactive Pi uses the ypl shortcut:

ypl 'Inspect the current task'

ypl expands to yy pi --live. Live mode requires an interactive terminal and enabled Pi extensions.

Controlled iterations

yy -s pi -m :gpt -i 3 -p 'Implement the next small verified increment'

yy loop -n 2 \
  --step 'yy pi "Implement the next increment"' \
  --step 'npm test'

Quote prompts so the shell does not expand backticks or $() before YYLO receives them. -i bounds iterations inside an agent invocation; yy loop -n bounds the outer command workflow.

The loop's -n/--iterations bounds the outer command workflow; agent -i/--max-iterations still bounds iterations inside an agent invocation. Inline steps are repeatable:

yylo loop -n 5 \
  --step 'yy pi "Implement the next increment"' \
  --step 'yy cc "Inspect and improve your work"' \
  --step 'npm test'

For a reusable workflow, save the same contract as flow.yaml:

iterations: 5
continuity: iteration
on_error: continue
steps:
  - run: yy pi "Implement the next increment"
  - run: yy cc "Inspect and improve your work"
  - run: npm test
yylo loop --workflow flow.yaml

Every step receives one-based loop metadata through YYLO_LOOP_ID, YYLO_ITERATION, YYLO_ITERATION_COUNT, YYLO_STEP, and YYLO_STEP_COUNT.

Models and project shortcuts

yy pi --help is the source of truth for shipped aliases. Current Pi shortcuts include:

ShortcutResolved model
:lunaopenai-codex/gpt-5.6-luna
:solopenai-codex/gpt-5.6-sol
:gpt:sol (Pi default)
:miniopenai-codex/gpt-5.6-terra
:sonnetanthropic/claude-sonnet-4-6
:opusanthropic/claude-opus-4-6

Aliases are subagent-specific; for example, Pi and Codex do not share the same :mini mapping.

Set a per-project default:

yy pi set-default-model :sol

Add project shortcuts in .juno_task/config.json:

{
  "modelShortcuts": {
    "pi": {
      ":team-default": ":sol"
    }
  }
}

Project shortcuts are scoped to the selected subagent and can reference shipped or project shortcuts. Unknown targets, malformed data, and cycles fail with an actionable error. Managed Workflow Runner model authorization is separate: explicit selectors must be exact members of workflowModels; an unflagged yy pi continues to inherit the configured default.

Observable local commands

watch owns bounded execution evidence for an ordinary local command:

yy watch exec npm test
# Use the run ID printed above:
yy watch status RUN_ID
yy watch await RUN_ID

RUN_ID is a placeholder. Status is observation; it does not acquire task, merge, or release authority. Watch evidence includes terminal state and bounded logs rather than requiring terminal-scrollback reconstruction.

Managed workflows and evidence

Fresh yy init installs managed scripts, prompts, and wiki guidance under .juno_task/. Update checksum-managed assets with:

yy scripts update

Locally customized files are preserved and a package candidate is written to a managed-conflict path. --force is an explicit replacement operation and creates backups; inspect conflicts before using it.

Workflow Runner

Use a reviewed YAML workflow for ordered, repeatable steps:

./.juno_task/scripts/workflow_runner.sh \
  --init-example agent-chain .juno_task/workflows/agent-chain.yaml
./.juno_task/scripts/workflow_runner.sh lint \
  --workflow .juno_task/workflows/agent-chain.yaml
./.juno_task/scripts/workflow_runner.sh \
  --workflow .juno_task/workflows/agent-chain.yaml --dry-run \
  --print-output none --no-print-step-stdout

A workflow run retains rendered command identity, stdout/stderr, responses, session IDs, declared receipt hashes, attempts, and terminal manifests. --tmux creates an observer session; it does not detach the producer.

If a producer was interrupted, diagnose before mutation:

./.juno_task/scripts/workflow_runner.sh recover-attempt RUN_DIRECTORY --dry-run
./.juno_task/scripts/workflow_runner.sh doctor RUN_DIRECTORY

RUN_DIRECTORY is the printed durable run path. Recovery resumes only the first invalid step after verifying unchanged successful evidence. Never edit historical manifests to make them reusable.

Task validation evidence

At a clean coherent task commit:

yy task checkpoint TASK_ID
yy evidence run TASK_ID
yy evidence status TASK_ID
yy evidence await TASK_ID

These commands plan and retain exact-input validation evidence. They do not finish or merge the task.

Typed task and merge flow

This section is for repositories initialized with the current controller/task policy. Run lifecycle commands from the registered metadata controller. Never edit the integration-owner checkout.

Managed path

yy task run TASK_ID
yy merge drive --through TASK_ID

TASK_ID is a Ledger task ID. task run executes the controller-owned workflow through QUEUED; merge drive is an explicit fenced target mutation.

Manual implementation path

yy task start TASK_ID
# Change directory to the worktree printed by start.
# Read its AGENTS.md/CLAUDE.md, implement, run focused tests, and commit.
yy task preflight TASK_ID
yy task finish TASK_ID
yy merge status                       # bounded operational summary
yy merge status --detail TASK_ID      # bounded task diagnostics
yy merge status --full                # explicit legacy exhaustive output
yy merge arbiter status
yy merge arbiter run --through TASK_ID

The guarded manual admission order is yy task preflight ID -> yy task finish ID; merge remains a separate queue-owned step.

Safety invariants:

  1. task start freezes the protected target SHA, creates a dedicated branch/worktree, and completes configured dependency hydration before reporting WORKING.
  2. Product edits and focused tests occur only in that task worktree. Controller metadata and integration-owner product bytes are separate authorities.
  3. preflight is read-only and catches closure defects before expensive gates. finish requires a clean committed tip and queues it; it does not merge.
  4. The merge queue owns risk-based review and moved-target composition. Low risk has no semantic reviewer, normal risk at most one, and high risk two sequential reviewers on one frozen candidate. After one repair candidate and one delta-review group, unresolved findings stop as REVIEW_FINDINGS_EXHAUSTED instead of starting an unbounded review loop.
  5. Target mutation is serialized under one fencing owner and expected-old-SHA CAS. Lease age alone never transfers authority.
  6. Conflicts and unrelated dirty bytes are preserved. Use the exact recovery packet and yy merge resolve TASK_ID; do not reset, stash, force, rebase, or squash to bypass it.

Observation commands are safe to repeat:

yy task status TASK_ID
yy task doctor TASK_ID
yy merge plan TASK_ID --json
yy merge status
# When needed:
yy merge status --detail TASK_ID
yy merge status --detail              # active FIFO attempt
yy merge status --full                # exhaustive compatibility/diagnosis
yy merge arbiter status

Bare status is merge-status.summary.v1, capped at 32 KiB and 19 projected rows. Detail remains capped at 32 KiB and identifies omitted diagnostic material; --full is the unbounded merge-status.full.v1 compatibility projection. JSON always includes schema, projection, truncation, and cursor metadata. Interactive status renders those same identifiers; pass --json to force structured output.

yy merge next and yy merge resolve are explicit recovery mutations, not polling commands.

Maintainer npm release

Normal tasks and yy merge own integration. After an ordinary version bump is integrated, maintainers use scripts/release-cli.sh prepare CLI_VERSION BENCHMARK_VERSION, obtain explicit publication approval, and then run the separate publish command. The CLI has no release command.

Receipt-bound workspace relocation

When an entire controller is moved between machines, do not rewrite lifecycle JSON or historical receipts by hand. From a clean physical controller checkout, create and review an external plan, apply it once, then verify its immutable receipt:

node juno-code/scripts/workspace-relocation.mjs plan --controller "$PWD" \
  --map /old/controller=/new/controller --map /old/worktrees=/new/worktrees \
  --output /secure/relocation-plan.json
node juno-code/scripts/workspace-relocation.mjs apply --controller "$PWD" \
  --plan /secure/relocation-plan.json --receipt /secure/relocation-receipt.json
node juno-code/scripts/workspace-relocation.mjs verify --controller "$PWD" \
  --receipt /secure/relocation-receipt.json

The plan binds the Git common directory, HEAD/ref, task-state hash, exact JSON pointers, and old/new physical roots. Apply refuses dirty, stale, tampered, symlinked, replayed, or missing-commit inputs and preserves historical evidence. Scan shipped active surfaces separately with node juno-code/scripts/check-path-portability.mjs; fixtures, immutable receipts, logs, generated output, lockfiles, and security canaries are explicitly excluded rather than rewritten.

Workspace roles and recovery

WorkspaceUse it forDo not use it for
Metadata controllerLedger/task/merge/release orchestration and durable receiptsProduct implementation or target integration edits
Task worktreeScoped implementation, focused tests, coherent commitsPrivate controller state or protected-target mutation
Integration ownerClean latest integrated reads and guarded target ownershipFeature edits, Kanban/session writes, or dirt cleanup

Discover routing without changing it:

yy info --json
yy where controller
yy where integration
yy where target
yy where task TASK_ID
yy doctor workspace

Routing is registration-based and fail-closed; YYLO does not guess a nearby controller, switch branches, or clean a checkout to manufacture compliance.

For integration-owner inspection and guarded refresh:

yy integration status
yy integration sync

integration status observes. integration sync is a mutation: it refuses dirty/diverged/ambiguous state and verifies nested gitlink availability before moving anything. yy integration push is separate remote authority and must not be inferred from sync, merge, or release readiness.

Ledger and Benchmark delegates

Install canonical packages independently:

python3 -m pip install 'yylo-ledger==0.2.0'
npm install --global '@yylo/benchmark@0.1.1-rc.1'

yylo-ledger --help
yy ledger --help
yylo-benchmark --help
yy benchmark --help

Delegation preserves arguments, stdin/stdout/stderr, cwd, exit status, and signals. It never silently chooses a checkout-local or legacy executable. See the Ledger repository and Benchmark repository for package-specific guidance and prerelease boundaries.

Completion and help

yy completion install
yy completion status
yy help
yy --help

Completion supports Bash, Zsh, and Fish. Use the nested help for your installed release rather than copying an option from a different channel.

Source-checkout toolchain (advanced)

A monorepo checkout containing juno-code/ and juno_kanban/ can build isolated source aliases without replacing normal global yy:

./juno-code/scripts/juno-002-source-toolchain.sh install
export PATH="$PWD/.juno_toolchain/juno-002/bin:$PATH"
yy-juno-002 --version
juno-kanban-juno-002 --version
./juno-code/scripts/juno-002-source-toolchain.sh status

yy ledger and its labelled yy kanban compatibility alias use the exact Ledger compatibility policy 0.2.0. The isolated source aliases also enforce the legacy controller package compatibility range juno-kanban >=2.0.5,<3.0.0. Source selection, controller registration, and data history are separate boundaries:

./juno-code/scripts/juno-002-source-toolchain.sh register-controller /path/to/controller controller-branch
./juno-code/scripts/juno-002-source-toolchain.sh controller-status
./juno-code/scripts/juno-002-source-toolchain.sh rollback-selection

The path and branch are placeholders. rollback-selection changes only isolated executable selection. Switching branches never downgrades or restores Ledger data. Back up and migrate a board through Ledger's reviewed data procedures.

Source laneOwnsMust not do
ControllerMetadata, orchestration, prompts, and receiptsProduct implementation or implicit ref changes
Task checkoutScoped implementation and testsProtected-target mutation
Integration ownerGuarded candidate integrationKanban/session writes or unrelated edits
Small fix worktreeExact-base small product repairBypass task/review/candidate boundaries

Development

git clone https://github.com/yylo-dev/yylo.git
cd yylo
npm ci
npm test
npm run typecheck
npm run build
node dist/bin/cli.mjs --help

The monorepo may embed YYLO CLI alongside Benchmark and a Ledger submodule, but each public package has its own manifest, version, release contract, and registry channel. A source checkout version is not evidence that the same version was published.

License

MIT.