CLI Tools Reference¶
Complete reference for ll- command-line tools and related utilities (including mcp-call). Install from PyPI:
See COMMANDS.md for /ll: slash commands and README for overview.
Common Flags¶
These flags appear across multiple tools:
| Flag | Short | Behavior | Used by |
|---|---|---|---|
--dry-run |
-n |
Show what would happen without making changes | ll-auto, ll-parallel, ll-sprint run, ll-deps fix, ll-sync |
--resume |
-r |
Resume from previous checkpoint | ll-auto, ll-parallel, ll-sprint run |
--max-issues |
-m |
Limit number of issues to process (0 = unlimited) | ll-auto, ll-parallel |
--quiet |
-q |
Suppress non-essential output | ll-auto, ll-parallel, ll-sprint run, ll-sync |
--only |
Comma-separated issue IDs to process exclusively | ll-auto, ll-parallel, ll-sprint run |
|
--skip |
Comma-separated issue IDs to exclude | ll-auto, ll-parallel, ll-sprint |
|
--type |
Comma-separated issue types: BUG, FEAT, ENH, EPIC |
ll-auto, ll-parallel, ll-sprint |
|
--config |
Path to project root (default: current directory) | ll-auto, ll-parallel, ll-sprint, ll-sync |
|
--timeout |
-t |
Timeout in seconds per issue | ll-parallel, ll-sprint run |
--handoff-threshold |
Override auto-handoff context threshold (1-100, default: from config) | ll-auto, ll-parallel, ll-sprint run, ll-loop run, ll-loop resume |
|
--context-limit |
Override context window token estimate (default: from config or model-detected) | ll-auto, ll-parallel, ll-sprint run, ll-loop run, ll-loop resume |
|
--json |
-j |
Output as JSON (structured, machine-readable) | Most ll-* CLIs — see individual tool sections |
--format |
-f |
Output format: text, json, markdown |
ll-history, ll-deps, ll-verify-docs, ll-check-links, ll-issues epic-progress |
Project Setup¶
ll-init¶
Initialize little-loops for a project. Detects the project root, selects host adapters, generates a .ll/ll-config.json, and optionally installs hook adapters for supported host CLIs (claude-code, codex, opencode, pi).
When run on a project that already has a .ll/ll-config.json, the interactive wizard pre-populates every field with the existing values so you can review and update without losing previous settings. The headless --yes path preserves existing feature toggles and project fields, applying only the overrides supplied via --enable/--disable.
Flags:
| Flag | Short | Description |
|---|---|---|
--yes |
-y |
Accept all defaults; run non-interactively. Merges existing config values when a config is present. Loop run defaults: clear: true, show_diagrams: "clean". |
--force |
-f |
Reset to template defaults rather than pre-populating from existing config |
--dry-run |
-n |
Preview actions without writing files |
--plan |
Emit a JSON plan {detected, proposed_config, host_options, warnings} without writing anything |
|
--hosts HOST [HOST ...] |
Host harnesses to install adapters for (claude-code, codex, opencode, pi). Defaults to auto-detected hosts. Unknown values produce a warning and are skipped. |
|
--enable FEATURE |
Enable a feature in the headless config (repeatable). Requires --yes/--dry-run/--plan. Valid: decisions, scratch_pad, session_capture, product, analytics, context_monitor, learning_tests, session_digest, prompt_optimization. |
|
--disable FEATURE |
Disable a feature in the headless config (repeatable). Same valid names as --enable. Use --disable prompt_optimization to opt out of the default-on prompt optimizer. |
|
--upgrade |
Act on version drift automatically, then run a host-parameterized surface refresh for every active host: upgrade the pip package, force-regenerate adapter files (e.g. .codex/hooks.json, re-stamping the embedded gen-version), and scope-aware-update the claude-code plugin (auto for project-scoped installs, advise-only for user-scoped). Without this flag, headless mode only warns — including a hint when a generated adapter's gen-version stamp diverges from the installed package. |
|
--root ROOT |
-C |
Project root directory (default: current directory) |
Richer features (parallel, sync, documents, design_tokens, confidence_gate, tdd) carry sub-config and remain interactive-only; they are not accepted by --enable/--disable. Unknown feature names exit 2.
Subcommands:
| Subcommand | Description |
|---|---|
apply --config PLAN |
Apply writes from a --plan JSON output. --config accepts a file path or raw JSON string. Produces the same artifacts as --yes (config, issue dirs, design tokens, issue templates, CLAUDE.md, host adapters, etc.). Accepts --force to overwrite existing configuration keys and overwrite existing host adapter files (e.g. .codex/hooks.json). |
Exit codes: 0 = success, 1 = error (template missing, stdin not a TTY, etc.), 2 = usage error
Interactive TUI screens (omitted when --yes is passed):
The detected project type is shown as a banner line (not a questionary prompt) before Screen 1 starts.
| Screen | Prompt | Notes |
|---|---|---|
| 1 / 6 | Project Basics | Project name, src dir, test/lint/format/type-check commands. Pre-filled from existing config when present, otherwise from project-type detection; command fields offer curated-menu select with "Custom…" fallthrough |
| 2 / 6 | Scan | focus_dirs text entry; confirm/override exclude patterns |
| 3 / 6 | Features | Opt-in checkboxes including github_sync, confidence_gate, tdd, decisions (rules log), scratch_pad (automation context masking), session_capture (PreCompact handoff); profile picker for design_tokens; worktree copy-files toggle; session-digest confirm; prompt-optimization opt-out confirm (default on); loop defaults: "Enable --clear by default?" (default Yes) and "Default diagram mode for ll-loop run?" (default clean) |
| 4 / 6 | Hosts | Defaults to detected hosts |
| 5 / 6 | Settings target | Third "Skip" option skips merge_settings entirely |
| 6 / 6 | CLAUDE.md update | Offers to create .claude/CLAUDE.md (or append to an existing one) with ll CLI command stubs; skipped if a ## little-loops section is already present (ENH-2043, ENH-2092) |
Examples:
ll-init --yes # Non-interactive full init with defaults
ll-init --yes --dry-run # Preview without writing files
ll-init --yes --force # Overwrite existing configuration
ll-init --yes --upgrade # Upgrade stale package/plugin automatically
ll-init --plan # Emit JSON plan without writing
ll-init --hosts claude-code codex # Install adapters for specific hosts
ll-init --yes --enable decisions --enable session_capture # Opt in to extra features
ll-init --yes --disable prompt_optimization # Opt out of prompt optimizer
ll-init apply --config plan.json # Apply writes from a --plan output
Defaults source (ENH-2434): All
ll-initdefaults — TUI field values,--enable/--disablevalid feature names, host detection heuristics, default project commands — are read fromconfig-schema.jsonat the package root, which is also the validation schema for.ll/ll-config.json. Edit defaults there; they're not duplicated between the wizard and the schema. To audit a default, searchconfig-schema.jsonfor the field name; the matchingdefaultvalue is whatll-init --yeswill produce.
Skill Invocation¶
ll-action¶
Thin CLI wrapper for invoking ll skills as one-shot commands with JSON-structured output. Useful for dashboard integrations, shell scripts, and cron jobs that need a single skill result without running a full FSM loop.
Subcommands:
invoke¶
Invokes a skill and streams output as newline-delimited JSON (NDJSON) events by default.
| Flag | Description |
|---|---|
skill |
Skill name (e.g. refine-issue, confidence-check) |
--args ARG [ARG ...] |
Arguments to pass to the skill |
--timeout SECONDS |
Timeout in seconds (default: 300) |
--output FORMAT |
stream-json (default) or json |
stream-json event shapes:
{"event":"action_start","ts":"...","skill":"refine-issue","args":["ENH-353"]}
{"event":"action_output","ts":"...","line":"Analyzing ENH-353..."}
{"event":"action_complete","ts":"...","exit_code":0,"duration_ms":45230}
json output shape (--output json):
capabilities¶
Returns the full CapabilityReport for the configured host. Does not invoke Claude.
{
"host": "claude-code",
"binary": "claude",
"version": "1.0.3",
"capabilities": [
{"name": "streaming", "status": "full", "note": ""},
{"name": "permission_skip", "status": "full", "note": ""},
{"name": "agent_select", "status": "full", "note": ""},
{"name": "tool_allowlist", "status": "full", "note": ""},
{"name": "json_schema", "status": "unsupported", "note": "..."},
{"name": "structured_output", "status": "full", "note": "..."}
],
"hooks": [
{"name": "session_start", "status": "installed", "note": ""}
]
}
list¶
Returns all skills with names, descriptions, and argument hints from the plugin manifest. Does not invoke Claude.
[
{"name":"refine-issue","description":"...","args":"ISSUE_ID [--auto] [--dry-run]"},
{"name":"old-skill","description":"...","args":null}
]
The args field is sourced from the args: frontmatter field in skills/<name>/SKILL.md (with argument-hint: as a fallback alias). It is null when neither field is present.
Exit codes: 0 = success, 1 = error, 124 = timeout
Examples:
ll-action invoke refine-issue --args P2-ENH-1229
ll-action invoke confidence-check --args FEAT-042 --timeout 120
ll-action invoke refine-issue --args P2-ENH-1229 --output json
ll-action invoke link-epics --args --auto # Link all HIGH-confidence orphans to epics non-interactively
ll-action capabilities
ll-action list
ll-harness¶
One-shot runner evaluation CLI that invokes a skill, shell command, MCP tool, or raw Claude prompt, captures its output, and exits 0 (PASS) / 1 (FAIL) / 2 (error/timeout) based on optional criteria.
Runners:
| Runner | Description |
|---|---|
skill |
Invoke a little-loops skill via the active host CLI |
cmd |
Run a shell command and capture its output |
mcp |
Call an MCP tool via JSON-RPC |
prompt |
Send a raw prompt to Claude via the active host CLI |
dsl |
Run a DSL task set and report pass rates with Wilson CI |
Shared evaluator flags:
| Flag | Description |
|---|---|
--exit-code INT |
Expected exit code (FAIL if mismatch) |
--semantic TEXT |
Natural-language criterion evaluated against captured output via LLM |
--timeout SECONDS |
Runner timeout (default: 120) |
--output FORMAT |
text (default) or json |
--verbose |
Show full captured output even on PASS |
mcp-specific flag:
--args JSON — JSON arguments forwarded to the MCP tool (default: {}).
prompt-specific flag:
--model MODEL — Override the Claude model used for the prompt (e.g. claude-haiku-4-5-20251001). Omit to use the host session default.
dsl-specific flag:
--model MODEL — Override the Claude model for all task invocations. Run ll-harness dsl once per model to compare pass rates across models.
Exit codes: 0 = PASS, 1 = FAIL, 2 = internal error / timeout
Examples:
ll-harness skill check-code
ll-harness cmd "echo hello" --exit-code 0
ll-harness mcp my-server:my-tool --args '{"key": "val"}' --semantic "tool returned results"
ll-harness prompt "What is 2+2?" --semantic "response contains a number"
ll-harness skill refine-issue P2-ENH-1229 --semantic "has implementation plan" --output json
ll-harness dsl evals/dsl/my-loop/
ll-harness dsl evals/dsl/my-loop/ --model claude-haiku-4-5-20251001
Diagnostics¶
ll-doctor¶
Probes the active host CLI and reports which little-loops features are supported. Produces a CapabilityReport with one CapabilityEntry per capability (streaming, permission skip, agent selection, tool allowlist, structured output) and one HookEntry per registered hook event.
Flags:
- -j, --json — emit the CapabilityReport as JSON instead of the human-readable table.
Exit codes: 0 = all capabilities supported, 1 = one or more capabilities unsupported.
Example output:
Host: claude (1.2.3)
Binary: /usr/local/bin/claude
Capabilities
────────────────────────────────────────
✓ streaming
✓ permission_skip
✓ agent_select
○ tool_allowlist (flag accepted but not validated)
Hooks
────────────────────────────────────────
✓ pre_tool_use
○ post_tool_use
Analytics Capture
────────────────────────────────────────
✓ skills: ['*']
✓ cli_commands: ['*']
✓ corrections: enabled
✗ file_events: disabled
Examples:
ll-ctx-stats¶
Show context-window analytics for the current project (FEAT-1160). Reads per-tool byte metrics that the post_tool_use hook persists into .ll/history.db (FEAT-1623) and renders a compact summary of how much data was processed by tools vs. how much actually entered the conversation context. Also surfaces skill-health signals (per-skill invocation frequency and correction rate) from ll-logs stats (ENH-1921). Falls back to .ll/ll-context-state.json (token estimates) when the SQLite store is absent so first-time users still get useful output.
When learning_tests.enabled is true, the report also includes a Learning Test Coverage section (ENH-2218) showing total record count, breakdown by status (proven / stale / refuted), and the number of orphaned records (targets with no matching import in the project). Use this section to spot stale coverage before a release.
Flags:
- --db PATH — Use a non-default session database (default .ll/history.db).
- --json — Emit the report as JSON instead of the human-readable summary. The JSON payload includes a skill_health array ([{skill, invocations, corrections, correction_rate}]) when skill events are present, or null when not. When learning tests are enabled it also includes a learning_tests key with {total, proven, stale, refuted, orphans}.
Exit codes: 0 = report rendered (data present or fallback used), 1 = no data found in either the SQLite store or the fallback file.
Examples:
To enable per-tool byte tracking, set "analytics": {"enabled": true} in .ll/ll-config.json.
Issue Processing¶
ll-auto¶
Process all backlog issues sequentially in priority order. On startup, ll-auto prints a header showing the active LLM model name (detected from the Claude CLI stream-json init event).
Context handoff and stale-inflight re-queue: When the agent's context window nears capacity, ll-auto emits a CONTEXT_HANDOFF signal and hands off to a fresh session. On resume (--resume), any issue that was in-flight at handoff time is re-queued at the front of the remaining work list so it is not silently dropped. (1693649e)
Flags:
| Flag | Short | Description |
|---|---|---|
--resume |
-r |
Resume from previous checkpoint |
--dry-run |
-n |
Show what would be processed without running |
--max-issues |
-m |
Limit number of issues (0 = unlimited) |
--quiet |
-q |
Suppress non-essential output |
--only |
Process only these issue IDs (comma-separated) | |
--skip |
Skip these issue IDs (comma-separated) | |
--type |
Process only these types: BUG, FEAT, ENH, EPIC |
|
--config |
Path to project root | |
--category |
-c |
Filter to category: bugs, features, enhancements, epics |
--priority |
-p |
Comma-separated priority levels to process (e.g., P1,P2) |
--label |
Comma-separated labels to process (e.g., fsm,cli,quick-win); matches issues with labels: frontmatter containing any of the specified values |
|
--verbose |
-v |
Show full prompt text; default shows abbreviated 5-line preview |
--idle-timeout |
Kill worker if no output for N seconds (0 to disable) | |
--handoff-threshold |
Override auto-handoff context threshold (1-100) | |
--context-limit |
Override context window token estimate | |
--skip-learning-gate |
Bypass the per-issue learning-test pre-flight gate (for emergency runs when learning_tests.enabled is true) |
Examples:
ll-auto # Process all issues in priority order
ll-auto --max-issues 5 # Process at most 5 issues
ll-auto --resume # Resume from previous state
ll-auto --dry-run # Preview what would be processed
ll-auto --category bugs # Only process bugs
ll-auto --only BUG-001,BUG-002 # Process only specific issues
ll-auto --skip BUG-003 # Skip a specific issue
ll-auto --type BUG # Process only bugs
ll-auto --type BUG,ENH # Process bugs and enhancements
ll-auto --priority P1,P2 # Only process P1 and P2 issues
ll-auto --label quick-win # Only process issues tagged quick-win
ll-auto --handoff-threshold 90 # Trigger handoff at 90% context usage
ll-parallel¶
Process issues concurrently using isolated git worktrees.
Flags:
| Flag | Short | Description |
|---|---|---|
--workers |
-w |
Number of parallel workers (default: from config or 2) |
--priority |
-p |
Comma-separated priorities to process (e.g., P1,P2) |
--worktree-base |
Base directory for git worktrees | |
--cleanup |
-c |
Clean up all worktrees and exit |
--prune-merged-branches |
Delete local feature/* branches already merged into the base branch; use with --dry-run to preview. Squash/rebase-merged branches require the gh CLI for detection. |
|
--merge-pending |
Attempt to merge pending work from interrupted runs | |
--clean-start |
Remove all worktrees and start fresh | |
--ignore-pending |
Report pending work but continue without merging | |
--stream-output |
Stream Claude CLI subprocess output to console | |
--show-model |
Verify and display model on worktree setup | |
--feature-branches |
Enable/disable feature-branch mode (--feature-branches / --no-feature-branches); overrides parallel.use_feature_branches in config for this run |
|
--epic-branches |
Enable/disable per-EPIC integration-branch mode (--epic-branches / --no-epic-branches); overrides parallel.epic_branches.enabled in config for this run |
|
--overlap-detection |
Enable pre-flight overlap detection to reduce merge conflicts | |
--warn-only |
With --overlap-detection, warn instead of serializing |
|
--dry-run |
-n |
Show what would be processed |
--resume |
-r |
Resume from previous checkpoint |
--timeout |
-t |
Timeout in seconds per issue |
--quiet |
-q |
Suppress non-essential output |
--only |
Process only these issue IDs | |
--skip |
Skip these issue IDs | |
--type |
Process only these types: BUG, FEAT, ENH, EPIC |
|
--label |
Comma-separated labels to process (e.g., fsm,quick-win) |
|
--max-issues |
-m |
Limit total issues processed |
--config |
Path to project root | |
--idle-timeout |
Kill worker if no output for N seconds (0 to disable) | |
--handoff-threshold |
Override auto-handoff context threshold (1-100) | |
--context-limit |
Override context window token estimate | |
--verbose |
-v |
Enable verbose output |
--skip-learning-gate |
Bypass per-worktree proof-first-task gate (emergency runs when learning_tests.enabled is true) |
Per-worktree proof-first gate (ENH-2219): When learning_tests.enabled is true, each worktree runs a proof-first-task gate before handing off to the implementation loop. The gate reads learning_tests_required from the issue file; when that field is absent (an unrefined issue), it resolves targets just-in-time by extracting external-API dependencies from the issue text (BUG-2320), so the firewall still fires on the capture-issue → ll-parallel path. A populated field is proven directly — forwarded as targets_csv so proof-first-task proves exactly the registered list rather than re-extracting an independent one (ENH-2405); a JIT-resolved list still goes through the assumption-firewall extraction/classification path. Either way, the gate verifies that every resolved API assumption has a proven (non-stale) record in the registry. If resolution yields no targets, the gate logs "no external dependencies detected" and proceeds (an auditable decision, not a silent skip). Issues that fail the gate are retried once after /ll:explore-api completes; if the retry also fails the issue is skipped and marked blocked. Use --skip-learning-gate for emergency runs when the registry is unavailable.
Config tip: Branch naming and merge behavior are controlled by
parallel.use_feature_branchesinll-config.json. Whentrue, branches are namedfeature/<id>-<slug>and auto-merge is skipped, leaving PR-ready branches for review. Setparallel.push_feature_branches: trueto also push branches to remote after success, andparallel.open_pr_for_feature_branches: trueto open a draft PR viaghand recordpr_url:on the issue. See Configuration reference and the Feature-Branch / PR-Based Workflow guide.Config tip (epic branches): Per-EPIC integration branches are controlled by
parallel.epic_branches.enabledinll-config.json(or--epic-branchesfor one run). Whentrue, children of a single EPIC coalesce their work onto a sharedepic/<EPIC-ID>-<slug>integration branch (parallel.epic_branches.prefix, defaultepic/) instead of per-worker branches. On the EPIC's last child, the integration branch merges back tobase_branchwhenparallel.epic_branches.merge_to_base_on_completeistrue(default), and opens a PR viaghwhenparallel.epic_branches.open_pristrue. Setparallel.epic_branches.verify_before_merge: trueto runtest_cmd/lint_cmdagainst the branch tip before that merge/PR-open — a failure blocks it and leaves the branch open for retry, surfaced in the run summary rather than silently logged. (On theauto-refine-and-implementFSM loop, this check is skipped as redundant when the loop'sverifystate already produced a freshpassedverdict for the same tip — ENH-2630.) See Configuration reference and the Per-EPIC integration branch guide.
Examples:
ll-parallel # Process with default workers
ll-parallel --workers 3 # Use 3 parallel workers
ll-parallel --dry-run # Preview what would be processed
ll-parallel --priority P1,P2 # Only process P1 and P2 issues
ll-parallel --cleanup # Clean up worktrees and exit
ll-parallel --stream-output # Stream Claude output in real-time
ll-parallel --only BUG-001,BUG-002 # Process only specific issues
ll-parallel --type BUG,ENH # Process bugs and enhancements
ll-parallel --overlap-detection # Reduce merge conflicts
ll-parallel --handoff-threshold 85 # Override handoff threshold for this run
ll-sprint¶
Define and execute curated issue sets with dependency-aware ordering.
Subcommands:
ll-sprint create <name>¶
Create a new sprint.
| Argument/Flag | Short | Description |
|---|---|---|
name |
Sprint name (used as filename) | |
--issues |
Required. Comma-separated issue IDs | |
--description |
-d |
Sprint description |
--max-workers |
-w |
Max parallel workers (default: 2) |
--timeout |
-t |
Timeout per issue in seconds (default: 3600) |
--skip |
Issue IDs to exclude | |
--type |
Filter by type: BUG, FEAT, ENH, EPIC |
ll-sprint run <sprint|EPIC-NNN> / ll-sprint r <sprint|EPIC-NNN>¶
Execute a sprint or resolve an EPIC's active children as a sprint.
| Argument/Flag | Short | Description |
|---|---|---|
sprint |
Sprint name or EPIC ID (e.g. EPIC-1234) to resolve and execute |
|
--dry-run |
-n |
Show plan without running |
--feature-branches |
Enable/disable feature-branch mode (--feature-branches / --no-feature-branches); overrides parallel.use_feature_branches in config for this run |
|
--epic-branches |
Enable/disable per-EPIC integration-branch mode (--epic-branches / --no-epic-branches); overrides parallel.epic_branches.enabled in config for this run |
|
--max-workers |
-w |
Max parallel workers |
--timeout |
-t |
Timeout per issue in seconds |
--config |
Path to project root | |
--resume |
-r |
Resume interrupted sprint |
--quiet |
-q |
Suppress non-essential output |
--only |
Issue IDs to process exclusively during execution | |
--skip |
Issue IDs to skip during execution | |
--skip-analysis |
Skip dependency analysis | |
--type |
Filter by type | |
--save |
Write the resolved sprint YAML to .ll/sprints/epic-NNN.yaml before executing (useful for inspect/edit workflows) |
|
--handoff-threshold |
Override auto-handoff context threshold (1-100) | |
--context-limit |
Override context window token estimate | |
--skip-learning-gate |
Bypass the pre-flight learning-test batch gate (see below) |
When an EPIC ID is passed, resolution is the union of the EPIC's relates_to: field (forward) and any issue with parent: EPIC-NNN (backward), deduplicated and filtered to active statuses (open, in_progress, blocked). Resume works using the normalized epic-NNN name stored in .sprint-state.json.
Pre-flight learning-test gate (ENH-2210): When learning_tests.enabled is true, ll-sprint run aggregates all learning_tests_required targets across every issue in the sprint before the first wave runs, checks each target via ll-learning-tests check --stale-aware, and blocks execution if any are missing or stale. This catches assumption gaps for the entire sprint in a single pre-flight pass rather than discovering them mid-wave. Use --skip-learning-gate to bypass when the registry is unavailable.
Milestone write-back: When
ll-sprint runstarts, it writesmilestone: <sprint-name>to the frontmatter of every issue in the sprint. This makes the sprint assignment visible on each issue file and enablesll-issues list --milestonefiltering andll-syncmilestone assignment.
ll-sprint list / ll-sprint l¶
List all sprints.
| Flag | Short | Description |
|---|---|---|
--verbose |
-v |
Show detailed information |
--json |
-j |
Output as JSON array |
ll-sprint show <sprint|EPIC-NNN> / ll-sprint s <sprint|EPIC-NNN>¶
Show sprint details, dependency graph, and health summary. Accepts either a sprint name or an EPIC ID — when passed an EPIC ID, SprintManager.load_or_resolve() resolves the EPIC's active children into a virtual sprint and renders them in dependency wave order.
| Argument/Flag | Short | Description |
|---|---|---|
sprint |
Sprint name or EPIC ID (e.g., EPIC-1773) |
|
--json |
-j |
Output as JSON (includes all fields) |
--config |
Path to project root | |
--skip-analysis |
Skip dependency analysis |
ll-sprint edit <sprint> / ll-sprint e <sprint>¶
Edit a sprint's issue list.
| Argument/Flag | Description |
|---|---|
sprint |
Sprint name |
--add |
Comma-separated issue IDs to add |
--remove |
Comma-separated issue IDs to remove |
--prune |
Remove invalid/completed issue references |
--revalidate |
Re-run dependency analysis after edits |
--config |
Path to project root |
ll-sprint delete <sprint> / ll-sprint del <sprint>¶
Delete a sprint definition.
ll-sprint analyze <sprint> / ll-sprint a <sprint>¶
Analyze sprint for file conflicts between issues.
| Argument/Flag | Short | Description |
|---|---|---|
sprint |
Sprint name | |
--format |
-f |
Output format: text (default), json |
--config |
Path to project root |
Examples:
ll-sprint create sprint-1 --issues BUG-001,FEAT-010 --description "Q1 fixes"
ll-sprint run sprint-1
ll-sprint run sprint-1 --dry-run
ll-sprint list
ll-sprint list --json # JSON array of all sprints
ll-sprint show sprint-1
ll-sprint edit sprint-1 --add BUG-045,ENH-050
ll-sprint edit sprint-1 --remove BUG-001
ll-sprint edit sprint-1 --prune
ll-sprint delete sprint-1
ll-sprint analyze sprint-1 --format json
Loop Automation¶
ll-loop¶
Execute FSM-based automation loops. If the first argument is a loop name (not a subcommand), run is inferred automatically.
Subcommands:
ll-loop run <loop> / ll-loop r <loop>¶
Run a loop.
| Argument/Flag | Short | Description |
|---|---|---|
loop |
Loop name or path | |
input |
(Optional positional) If valid JSON object with keys matching defined context variables, unpacks into those keys; otherwise stored as a string in context[input_key] |
|
--max-steps |
-n |
Override step cap (individual state transitions) |
--max-iterations |
Override full-pass cap (complete loop cycles) | |
--delay |
Sleep N seconds between iterations (useful for recording and to relieve host memory pressure between subprocess spawns). Config-defaultable via loops.run_defaults.delay (ENH-2556); an explicit --delay always overrides the configured default. |
|
--no-llm |
Disable LLM evaluation | |
--no-host-guard |
Disable the adaptive host memory-pressure guard (host_guard: block, ENH-2452). By default the guard samples host memory before each prompt-mode state and adds an extra cooldown / routes / aborts per the loop's host_guard: config. |
|
--host-guard-budget-mb N |
Override host_guard.max_cumulative_subproc_mb: cap on summed peak subprocess RSS (MB) across the run (ENH-2453). 0 disables the budget. |
|
--model |
Default model for host-CLI action states (prompt/slash_command). Per-state model: key overrides this. |
|
--llm-model |
Override model for FSM evaluator/judge states (distinct from --model) |
|
--dry-run |
Show execution plan without running. Diagram rendering is not suppressed — combine with --show-diagrams to preview both the FSM diagram and the execution plan. |
|
--background |
-b |
Run as background daemon |
--follow |
-f |
Stream FSM state transitions to stdout as they fire, in ll-loop history format. Cannot be combined with --background — passing both exits with an error; use ll-logs tail to watch a background loop instead. |
--quiet / --qt |
Suppress progress output | |
--verbose |
-v |
Stream all action output live; default shows a short response head preview |
--queue |
-q |
Wait for conflicting loops to finish; writes a queue entry to <loops_dir>/.queue/<uuid>.json while waiting (see Queue entries) |
--show-diagrams[=MODE] |
Display FSM diagram after each step. MODE is a topology (layered|neighborhood|inline|window) or preset (detailed|summary|clean|local|slim|oneline). Bare flag selects summary (layered, main-path scope). Override individual facets with --diagram-edge-labels=on\|off, --diagram-state-detail=title\|full, --diagram-scope=main\|full. Breaking (ENH-1672): main→summary, full→detailed, mini→clean; old values error with migration hints. Viewport auto-degrades layered→window→neighborhood→inline for preset/default sources (the window rung crops the real layered diagram to ±K layers around the active state with ▲ N layers above/▼ M layers below banners — ENH-2410); explicit topology values disable degradation (window is also selectable explicitly). |
|
--clear |
Clear terminal before each iteration (combine with --show-diagrams for live in-place rendering; suppressed when stdout is not a tty). When combined with --show-diagrams on a tty, the screen splits into a pinned FSM diagram on top and a scrolling action-output region below; on terminals too short for the full diagram the pinned pane falls back first to a windowed view (the real layered diagram cropped to ±K layers around the active state, with ▲ N layers above/▼ M layers below overflow banners — ENH-2410), then to a 1-hop neighborhood view (predecessors → [active] → successors), then to a single-line fsm: ... → [...] → ... status. The pane redraws on SIGWINCH (terminal resize). When a parent loop spawns child loops, the pinned pane shows only the deepest active child loop rather than all nesting levels simultaneously — keeping the pane readable regardless of loop depth. |
|
--builtin |
Load loop from built-ins directory (bypasses project .loops/ lookup) |
|
--context KEY=VALUE |
Override a context variable (repeatable) | |
--program-md PATH |
Load steering directive from a Markdown file (default: .ll/program.md when present); parsed fields injected into context before --context overrides. See program-md reference. |
|
--worktree |
Run loop in an isolated git worktree on a new branch named TIMESTAMP-LOOP-NAME. On exit, if the worktree is clean (no uncommitted changes, no commits ahead of base), the branch is deleted. If pending work is detected (uncommitted changes or commits ahead), the branch is retained and a warning is printed with the branch name for recovery (git checkout BRANCH-NAME). Cannot be combined with --background — passing both exits with an error. |
|
--baseline |
Run a blind A/B comparison: executes primary skill with full evaluation gates (harness arm) and creates a matching ungated invocation (baseline arm) in parallel, then feeds both outputs into a blind LLM judge. Writes ab.json to the run directory and prints a terminal summary with pass-rate delta, Wilson 95% CI bounds [lo, hi] for each arm, and token/duration ratios. Cannot be combined with --worktree — passing both exits with an error. |
|
--baseline-skill |
Override the baseline arm skill (default: extracted from the execute state action). Accepts a full slash command such as /ll:some-skill. |
|
--cross-host |
Re-run the loop on a second available host CLI and append a cross-host comparison table to the baseline report. Requires --baseline. The comparison runs the execute state on the alternate host, then feeds both outputs into the same blind LLM judge. (ENH-2086) |
|
--items |
Number of compare cycles to run (default: iterate with MIMO packing heuristics) | |
--cost-output-json PATH |
Also write the per-state cost report to PATH as machine-readable JSON (same shape as CostReport.write_json — see Per-State Token/Cost Summary). The human-readable table is unaffected. Forwarded through ll-loop run --background re-exec so detached runs honor the flag (BUG-1414). |
|
--handoff-threshold |
Override auto-handoff context threshold (1-100) | |
--context-limit |
Override context window token estimate | |
--no-lock |
Run without acquiring the scope lock, bypassing the conflict check. Caution: this allows concurrent runs that may interfere with each other on shared resources. Use when you need parallel runs that operate on disjoint paths or when testing a loop that would otherwise be blocked by a stale lock you cannot clear. |
Model Header Display (ENH-1805)¶
ll-loop run and ll-loop monitor print a header line showing the active LLM model name on startup, detected from the Claude CLI stream-json init event (same mechanism as ll-auto). The model name appears in the first output line after the logo banner:
ll-loop run general-task "fix the lint warnings"
model: claude-sonnet-4-6
[state transitions follow]
When --llm-model is passed, the header reflects the override model. When the detection fails (e.g., non-Claude host), the field shows unknown.
Per-State Token/Cost Summary (ENH-1797)¶
After a loop run completes, ll-loop run prints a per-state token and cost summary table immediately before the final completion line. The table is produced whenever at least one LLM action (prompt or slash_command) executed during the run.
state invoc input output cache est_cost
────────────────────────────────────────────────────────────────────
execute 3 12 400 2 100 8 500 $0.042
check_semantic 3 3 200 480 2 900 $0.011
────────────────────────────────────────────────────────────────────
TOTAL 6 15 600 2 580 11 400 $0.053
Columns:
| Column | Description |
|---|---|
state |
FSM state name |
invoc |
Number of times the state ran an LLM action |
input |
Total input tokens (prompt + cached) |
output |
Total output tokens |
cache |
Cache read tokens (cache_read_tokens) |
est_cost |
Estimated USD cost (using pricing.py MODEL_PRICING constants; shown as ~$X.XXX (model unknown) when the model is not in the pricing table) |
Shell (action_type: shell) and MCP tool (action_type: mcp_tool) states are omitted from the table — they produce no token usage row in usage.jsonl.
The raw per-iteration data lives at .loops/runs/<run-id>/usage.jsonl (not archived to .loops/.history/). See Output Artifacts for the usage.jsonl schema.
Machine-Readable JSON Output (--cost-output-json, ENH-2477)¶
Pass --cost-output-json PATH to also write the same per-state aggregates as a stable JSON document (built by CostReport.from_usage_jsonl().write_json() at fsm/cost_graph.py). The shape is locked so downstream dashboards can parse without depending on the human-readable table layout:
{
"states": [
{
"state": "execute",
"iterations": 3,
"input_tokens": 12400,
"output_tokens": 2100,
"cache_read_tokens": 8500,
"cache_creation_tokens": 0,
"cost_usd": 0.0421,
"wallclock_ms": 18500
}
],
"totals": {
"iterations": 6,
"input_tokens": 15600,
"output_tokens": 2580,
"cache_read_tokens": 11400,
"cost_usd": 0.0533,
"wallclock_ms": 24300
}
}
State rows are sorted by name. Totals mirror the same metric keys. cost_usd is 0.0 for any state where at least one row used an unknown model (the has_unknown_model flag is surfaced only in the Python API, not the JSON). The flag is forwarded through ll-loop run --background re-exec so detached runs honor the same destination (BUG-1414 prevention).
Note:
agent:,tools:, andmodel:are per-state YAML fields, not CLI flags. See Subprocess Agent and Tool Scoping in the Loops Guide for per-state agent, tool, and model scoping options.
Failure Reason Display¶
When a loop exits a non-success terminal state, ll-loop run prints the failing state's output as a Failure reason block immediately before the completion line. This surfaces failure context that would otherwise be invisible: the alt-screen wipes on teardown, and non-verbose runs never echo per-state stdout inline.
The block is shown when the run was in alt-screen mode or in non-verbose (--quiet) mode. It is suppressed in --verbose mode, where the live renderer already echoed the output. Output is capped at 40 lines to bound scrollback.
Queue entries (.loops/.queue/)¶
When ll-loop run --queue encounters a scope conflict with a running loop, it creates <loops_dir>/.queue/<uuid>.json before entering the wait and removes it on lock acquisition, timeout, error, or process exit (via atexit). The file lets external observers (e.g. a dashboard) enumerate loops that are waiting on a scope lock without scanning process state.
Ordering: When multiple loops are waiting on the same lock, they acquire it in FIFO (arrival) order — the first loop to enqueue is the first to run after the current holder exits.
Entry schema:
{
"id": "<uuid>",
"loopName": "<loop name>",
"enqueuedAt": "<ISO 8601 UTC timestamp>",
"context": {
"waitingFor": "<name of conflicting running loop>",
"scope": ["<scope path>", ...],
"pid": <integer PID of the waiting process>
}
}
Entries are short-lived and ephemeral — treat the directory as a live view, not a history log. Stale entries are possible if a process exits abnormally without running atexit handlers; ll-loop queue list (below) is that cleanup tooling — reading the queue prunes entries whose pid is no longer alive.
ll-loop queue list¶
List pending entries in the process-backed run queue (the .loops/.queue/*.json files documented under Queue entries above). This is the observability surface for loops waiting on a scope lock via ll-loop run --queue.
Pruning side effect: listing the queue calls read_queue_entries(), which unlinks dead-PID entries as a side effect — every rendered entry is alive by construction. Running ll-loop queue list is therefore also the sanctioned way to garbage-collect stale queue files left behind by a process that exited without running its atexit handlers.
Human-readable output prints a Pending queue entries (N): header followed by one line per entry, sorted ascending by enqueue time:
Pending queue entries (2):
a1b2c3d4 my-loop pid=12345 alive 2026-07-13 19:40:00
e5f6a7b8 other-loop pid=12346 alive 2026-07-13 19:41:12
Each line is <short id (first 8 chars)> <loopName> pid=<pid> alive <YYYY-MM-DD HH:MM:SS>. When the queue is empty, it prints Queue is empty.
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Emit the queue as a JSON array (one object per entry, using the entry schema); an empty queue emits []. Exit code is 0 in all cases. |
ll-loop queue remove <id>¶
Cancel a queued waiter: signal its process (SIGTERM) and delete its .loops/.queue/<uuid>.json entry. This is the way to abandon a loop that is blocked waiting on a scope lock via ll-loop run --queue — the counterpart to the read-only ll-loop queue list.
The <id> argument accepts either a full uuid or an 8+-character prefix (the short id shown by ll-loop queue list). Before signaling, remove runs a psutil identity check confirming the entry's context.pid is really a live ll-loop waiter; if the check fails, the entry file is still deleted but no signal is sent (pass --force to signal anyway). The entry file is always deleted whether or not the signal landed, because the waiter's atexit cleanup does not fire on SIGTERM. remove never touches the running lock-holder — that PID lives in a separate .running/ namespace.
Exit codes: 0 on success (entry deleted); 1 when the <id> matches no entry or is an ambiguous prefix matching more than one entry.
| Flag | Short | Description |
|---|---|---|
--force |
Bypass the psutil identity check and signal the tracked pid unconditionally. | |
--json |
-j |
Emit the result as a JSON object: {"id", "removed", "signaled", "identityVerified", "pid"}. |
Bare ll-loop queue (no subcommand): invoking ll-loop queue without a subcommand prints the queue subparser help and exits with code 1.
ll-loop validate <loop> / ll-loop val <loop>¶
Validate a loop definition file.
In addition to structural checks (reachability, evaluator fields, routing consistency), validation applies meta-loop lint rules when a loop is classified as a meta-loop (writes harness artifacts, imports lib/benchmark.yaml, or references yaml_state_editor/replace_action):
- MR-1 (ERROR): A meta-loop must have at least one non-LLM evaluator (
exit_code,output_numeric,output_json,output_contains,convergence,diff_stall,score_stall,action_stall,harbor_scorer,mcp_result). LLM self-grades on harness updates are unreliable (SHOR Table 1: 33–55% accuracy). Triggers aValueError(exit code 1) that blocks the loop from running. - MR-2 (WARNING): A meta-loop should reference a captured baseline value in a later evaluator (
evaluate.previous,evaluate.target, orevaluate.source). This ensures a measure→propose→apply→re-measure spine is present. Does not block validation. - MR-3 (WARNING): A loop writes intermediate artifacts to shared
.loops/tmp/instead of the runner-injected${context.run_dir}/. Concurrent runs (e.g., underll-parallel) will corrupt each other's state. Does not block validation. Suppressed byshared_state_ok: true. - MR-4 (WARNING): An LLM-judged state (action_type:
prompt/slash_command, or an explicitllm_structured/check_semanticevaluator) mapson_yesbut has no route fornoorpartialverdicts — with nonext:orroute:table with a default. The loop silently dead-ends when the judge returnsno/partial; a parent loop reads this as failed. Does not block validation. Suppressed bypartial_route_ok: true. - MR-5 (WARNING): A harness-category loop writes artifact files to a flat path in an iterative generate→evaluate→generate cycle without per-iteration versioning. Intermediate versions are lost; only the final output survives. Add per-iteration snapshots (see oracle
generator-evaluatorfor the snapshot-state pattern) and declareartifact_versioning: true. Does not block validation. Suppressed byartifact_versioning: true(loop snapshots artifacts) orartifact_versioning_ok: true(intentional overwrite). (ENH-1957) - MR-6 (WARNING): A meta-loop has a
shell-type state that writes to the same file path as an LLM-generator state (prompt/slash_commandwithyaml_state_editororreplace_actionmarkers). Hand-patching creates fragile output that diverges from the generator on the next run; fix the generator action so every run produces correct output automatically. Does not block validation. Suppressed bygenerator_fix_ok: truefor intentional post-processing. (ENH-2079) - MR-7 (ERROR): A FSM action string contains an unescaped
${namespace.path:-default}(bash:-parameter-expansion default syntax). The FSM interpolation engine does not support this form and will crash at runtime withPath 'ns.path:-default' not found in context. Use${ns.path:default=value}(engine-native) or$${VAR:-value}(shell-escaped) instead. Blocks the loop from running. Suppressed bybash_default_ok: true. (ENH-2348) - MR-8 (WARNING): A
check_semantic/llm_structuredstate whoseevaluate.promptdoes not contain evidence-contract keywords (verbatim,quote,evidence). Verdicts without verbatim citation requirements default to optimism (SHOR Table 1: 33–55% accuracy; Sonnet 4.6 = 33.4%). States withevaluate.prompt: nullinheritDEFAULT_LLM_PROMPTwhich includes the contract automatically and are not flagged. Does not block validation. Suppressed byevidence_contract_ok: true. (ENH-2342) - MR-9 (ERROR): A shell action string contains
$$(or$$VAR(over-escaped bash). The FSM interpolator only rewrites the brace form$${...}→${...}; bare$(...)and$VARare passed tobash -cuntouched. Doubling them causes the leading$$to expand to the runner's PID, silently corrupting every downstream${captured.*}reference (e.g.echo "$$(pwd)"captures<pid>(pwd)instead of a path). Use single$for command substitution and variables; reserve$$exclusively for the$${VAR}brace form that collides with${ns.path}interpolation. Blocks the loop from running. Suppressed byshell_pid_ok: true. (BUG-2368) - MR-10 (WARNING): A
shell-type state whose inline Python callsjson.loads/json.load, catchesJSONDecodeError/ValueError/bareException, and explicitly exits 0 (sys.exit(0)orexit(0)) — without anon_error:route — silently discards parse failures. The FSM receives exit 0 and treats the state as successful, producing zero results with no log, no stderr, and no non-zero exit code. Addon_error:to the state to route parse failures explicitly. Does not block validation. Suppressed byparse_swallow_ok: truewhen treating a parse failure as an empty result is intentional. (BUG-2383) - MR-11 (WARNING): A
shell-type state pastes a user-controlled${context.input|goal|description|task|prompt|query|topic}value raw into the action body, outside a safe position (single-quoted string, quoted heredoc<<'EOF', or the:shellsuffix).interpolate()substitutes with a barestr(value)and no shell escaping; a value containing",$,`,\, or!breaks bash tokenizing (misrouting the loop toon_error/on_no) or, from an untrusted source, injects commands. Fix by wrapping the placeholder in single quotes, writing it through a quoted heredoc, or using${context.input:shell}to shlex-quote it at interpolation time. Does not block validation. Suppressed byunsafe_context_interpolation_ok: true. (BUG-2622)
MR-1, MR-2, and the multimodal evaluator blind-spot rule are suppressed by setting meta_self_eval_ok: true at the loop top-level (with a justifying comment). MR-3 is suppressed by shared_state_ok: true. MR-4 is suppressed by partial_route_ok: true. MR-5 is suppressed by artifact_versioning: true or artifact_versioning_ok: true. MR-6 is suppressed by generator_fix_ok: true. MR-7 is suppressed by bash_default_ok: true. MR-8 is suppressed by evidence_contract_ok: true. MR-9 is suppressed by shell_pid_ok: true. MR-10 is suppressed by parse_swallow_ok: true. MR-11 is suppressed by unsafe_context_interpolation_ok: true.
- Zero-retry counter pattern (WARNING): Detects states whose
retryconfig setsmax_retries: 0alongside a non-zeroretry_countcounter variable, orretry_countthat is never incremented in any on-error transition. A zero-retry counter pattern means the state will never actually retry despite having retry infrastructure wired — this is almost always a configuration mistake. Does not block validation. - Multimodal evaluator blind-spot (WARNING): Detects harness-loop states that use an LLM multimodal prompt (screenshot/image) evaluated via
output_containsas the sole gate routing directly to a terminal state. LLMs can silently fall back to text-only analysis when reading images, producing verdicts from incomplete information without theoutput_containsevaluator detecting the gap. Consider adding a shell-action verification state (e.g., functional smoke test) between scoring and the terminal. Does not block validation. Suppressed bymeta_self_eval_ok: true. - Unresolvable static
loop:references (ERROR): A state whoseloop:key contains a non-interpolated (static) target name that cannot be resolved to a.yamlfile at definition time will fail identically at runtime (FileNotFoundErrorinresolve_loop_path). Originally a WARNING (BUG-2305) on the theory that some references are intentionally optional, but this theory does not hold — dynamic names containing${...}are already skipped, so any remaining static name either resolves or fails. The validator now emits an ERROR andll-loop validateexits 1, blocking the loop from loading viaload_and_validate. Fix: correct the target name (sub-loops underoracles/require the full relative path, e.g.loop: oracles/verify-confidence-scores, notloop: verify-confidence-scores). (BUG-2400) - Capture reachability (WARNING/ERROR): Detects states that reference
${captured.<var>.*}in their action or evaluator source where the capturing state may not execute on all code paths to the referencing state. Uses dominance analysis (reverse BFS) to check whether every path frominitialto the referencing state passes through at least one of the capturing states. When a variable is produced by more than one state on mutually-exclusive branches (e.g.fifo_popandselect_nextboth captureinput), the validator accepts the reference as safe if the set of capturing states collectively dominates the referencing state — every path must pass through at least one member of the set. Emits an ERROR when the referenced capture variable has no capturing state at all in the current FSM (likely a missingcapture:declaration). Emits a WARNING when a bypassing path exists — the variable may be undefined at runtime if the bypass path is taken. Sub-loop exception: when the loop contains sub-loop states and the variable has no capturing state in the parent FSM, the validator emits a WARNING rather than an ERROR — the capture may legitimately live in a child namespace; the WARNING ensures typos still surface rather than going completely dark. Does not block validation for warnings; errors block validation. (ENH-1961, BUG-1997, ENH-1998)
Flags:
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output validation result as JSON. On success: {"valid": true, "loop": "<name>", "warnings": [...]}. On failure: {"valid": false, "loop": "<name>", "error": "<message>", "warnings": [...]}. Exit code is unchanged (1 for ERROR, 0 for clean/warnings-only). (ENH-2090) |
ll-loop list / ll-loop l¶
List available loops. Discovery is recursive: runnable loops nested under subdirectories of loops/ (e.g. oracles/oracle-capture-issue) are included, while library fragments under loops/lib/ are filtered out via is_runnable_loop(). Output is grouped by category, each category using its own header color via the CATEGORY_COLOR map. Each header carries an inline rollup badge (e.g. 2 built-in, 1 project) and dimensions of the kind/label/description columns are computed once per render to fit terminal_width(default=120). Categories with a dominant name-prefix cluster (≥3 members sharing the apo- prefix, etc.) get a bold subgroup subhead in the parent's category color, with leaves indented one level deeper. Visibility (built-in / project / internal / example) is a first-class column rather than a trailing marker; known label classes (hitl, comparison, generated, meta) get distinct ANSI colors. Output ends with a bold TOTAL: summary line that surfaces loop/category counts plus a dim hidden-tier hint when applicable. All-caps section markers (category headers, subgroup subheads, summary lines) use the _all_caps helper, while body content (name, kind, labels, description) stays mixed case. No body text is rendered with dim/faint ANSI; only the hidden-tier hint keeps dim. CATEGORY_COLOR no longer duplicates the FEAT green ("32") across code-quality and quality — both pick distinct 256-color codes. (ENH-2539, refined in v2 polish)
For nested loops, the displayed identifier is the relative path without the .yaml suffix (e.g. oracles/oracle-capture-issue) — the same string ll-loop run and ll-loop validate accept. Top-level loops continue to display as their bare stem. Override suppression (a project loop hiding a built-in of the same name) keys on the full relative path, not the bare stem — so a project oracles/foo.yaml does not suppress a built-in top-level foo.yaml.
| Flag | Short | Description |
|---|---|---|
--running |
Only show currently running loops | |
--status STATUS |
With --running, filter to loops with the given status (e.g. interrupted, awaiting_continuation) |
|
--builtin |
Only show built-in loops (exclude project .loops/) |
|
--category <cat> |
-c |
Filter to loops with the given category (e.g. apo, issue-management, code-quality) |
--label <tag> |
-l |
Filter to loops that carry the given label tag; repeat for multiple tags (OR match) |
--all / -a |
-a |
Show all loops including internal sub-loops and examples (hidden by default) |
--internal |
Show only internal (delegated-only) sub-loops | |
--examples |
Show only example/template loops | |
--visibility {public,internal,example,all} |
Filter loops by visibility tier: public (routable, default view), internal, example, or all. Composes with --label and --json. |
|
--json / -j |
Output as JSON array. Without --running: each entry includes name (relative-path identifier — e.g. oracles/oracle-capture-issue for nested loops, fix-quality-and-tests for top-level), path, category, labels, visibility ("public" | "internal" | "example"), description, and built_in. With --running: each entry is a LoopState object (loop_name, status, current_state, iteration, updated_at, etc.); instance_id is absent from this output — use ll-loop status <loop> --json to resolve per-instance details |
ll-loop status <loop> / ll-loop st <loop>¶
Show current status of a loop. Aggregates across all running instances of <loop>.
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output loop state as JSON. Returns a single object when one instance is running; returns a JSON array of objects (each including instance_id, pid, pid_source, log_file, events_file) when two or more instances are running. The pid field is populated from the .pid file if present, otherwise falls back to the .lock file. The pid_source field is "pid_file", "lock_file", or null. log_file is a path for both foreground and background runs; null only for background-spawned child processes (--foreground-internal) or pre-ENH-1703 state files. events_file points to the <instance-id>.events.jsonl file, which exists for all run modes |
The human-readable Log: line uses one of three labels:
- Log: <path> — background run with its .log file present (normal case)
- Log: (foreground run — output went to terminal) — legacy fallback only (pre-ENH-1703 instances or instance_id=None runs); foreground runs after ENH-1703 always produce a .log file and display Log: <path> instead
- Log: (expected <path>, missing) — .pid file exists but .log was deleted (something went wrong)
An Events: line follows whenever an <instance-id>.events.jsonl file is found, showing the event count and age of the most recent event regardless of run mode.
Note:
ll-loop statusis not a pure read — it may transparently rewrite orphaned state files. If a state file claimsstatus: runningbut its PID (resolved via.pid→.lock→ embeddedstate.pid) is provably dead, the file is updated in-place tostatus: interruptedwith areconciled_attimestamp. This is a no-op for live processes and is idempotent.
ll-loop stop <loop>¶
Stop a running loop. Terminates all running instances of the named loop (no --instance-id selector).
Termination is process-cohort aware (ENH BUG-2147): before sending any signal, ll-loop stop walks the full descendant tree of the root PID via pgrep -P recursion, collecting every child and grandchild process. Children are terminated first (so the root cannot respawn them), then the root receives SIGTERM. If any member of the cohort is still alive after 10 s, the entire group is escalated to SIGKILL. This ensures that loops spawning child CLIs (e.g. the claude binary launched with start_new_session=True) are reliably cleaned up rather than left as orphans.
Also handles loops in interrupted state that hold an orphaned lock-file PID: if .loops/.running/<loop>.lock exists and its PID is alive, ll-loop stop terminates the full process cohort as above and removes the lock file. This resolves scope conflicts that block subsequent ll-loop run invocations without requiring manual kill + rm. If the lock-file PID is already dead, the stale lock is cleaned up and reported.
ll-loop resume <loop> / ll-loop res <loop>¶
Resume a loop. Resumable statuses are "running", "awaiting_continuation", "interrupted" (Ctrl-C, the runner caught the signal itself), and "user_stopped" (clean ll-loop stop — ENH-2522 wrote a user-stop.marker so the runner can distinguish this from a kernel kill). Loops that died from a kernel/SIGKILL/OOM kill terminate with terminated_by="system_signal" and are not resumable — the runner died mid-state and there is no clean recovery point. When no --instance-id is given, the most recent resumable instance is auto-selected. Use --instance-id to disambiguate when you need a specific instance.
| Flag | Short | Description |
|---|---|---|
--instance-id <id> |
Select a specific instance to resume (auto-detected if omitted) | |
--background |
-b |
Resume as a detached background process |
--context KEY=VALUE |
Override a context variable (repeatable) | |
--show-diagrams[=MODE] |
Display FSM diagram after each step. MODE is a topology (layered|neighborhood|inline|window) or preset (detailed|summary|clean|local|slim|oneline). Bare flag selects summary (layered, main-path scope). Override individual facets with --diagram-edge-labels=on\|off, --diagram-state-detail=title\|full, --diagram-scope=main\|full. Breaking (ENH-1672): main→summary, full→detailed, mini→clean; old values error with migration hints. Viewport auto-degrades layered→window→neighborhood→inline for preset/default sources (the window rung crops the real layered diagram to ±K layers around the active state with ▲ N layers above/▼ M layers below banners — ENH-2410); explicit topology values disable degradation (window is also selectable explicitly). |
|
--clear |
Clear terminal before each iteration (combine with --show-diagrams for live in-place rendering; suppressed when stdout is not a tty). When combined with --show-diagrams on a tty, the screen splits into a pinned FSM diagram on top and a scrolling action-output region below; on terminals too short for the full diagram the pinned pane falls back first to a windowed view (the real layered diagram cropped to ±K layers around the active state, with ▲ N layers above/▼ M layers below overflow banners — ENH-2410), then to a 1-hop neighborhood view (predecessors → [active] → successors), then to a single-line fsm: ... → [...] → ... status. The pane redraws on SIGWINCH (terminal resize). When a parent loop spawns child loops, the pinned pane shows only the deepest active child loop rather than all nesting levels simultaneously — keeping the pane readable regardless of loop depth. |
|
--delay |
Sleep N seconds between iterations (useful for recording and to relieve host memory pressure between subprocess spawns) | |
--no-host-guard |
Disable the adaptive host memory-pressure guard (host_guard: block, ENH-2452) |
|
--handoff-threshold |
Override auto-handoff context threshold (1-100) | |
--context-limit |
Override context window token estimate |
ll-loop monitor <loop>¶
Attach to a running loop and render its FSM state in realtime. Read-only:
tails <instance-id>.events.jsonl and the loop's .log file from disk and
forwards events to the same StateFeedRenderer used by ll-loop run. Ctrl-C
detaches from the rendered stream without sending any signal to the loop
process (use ll-loop stop to terminate the loop). When no instance is running
(no live PID), prints the last-known state of the most recent instance and
exits 0.
ll-loop monitor fix-types # tail events and log
ll-loop monitor fix-types --show-diagrams --clear # pinned FSM diagram + scrolling log
ll-loop monitor fix-types --clear # with clear-screen on redraw
| Flag | Short | Description |
|---|---|---|
--show-diagrams[=MODE] |
Display FSM diagram alongside events (same semantics as ll-loop run). |
|
--diagram-edge-labels |
Override edge-label visibility (on|off). |
|
--diagram-state-detail |
Override state-detail level (title|full). |
|
--diagram-scope |
Override diagram scope (main|full). |
|
--clear |
Pin the FSM diagram and stream events below (TTY only). | |
--no-clear |
Disable terminal clearing between iterations (scroll output instead). | |
--quiet / --qt |
Suppress progress output. | |
--verbose |
-v |
Show full prompt at action start. |
ll-loop history <loop> / ll-loop h <loop>¶
Show execution history for a loop.
| Flag | Short | Description |
|---|---|---|
run_id |
(Optional positional) Archived run ID to inspect; omit to list all archived runs | |
--tail |
-n |
Last N events to show (default: 50) |
--event |
-e |
Filter by event type (e.g. evaluate, route, state_enter) |
--state |
-s |
Filter by state name (matches state, from, or to fields) |
--since |
Filter to events within a time window (e.g. 1h, 30m, 2d) |
|
--verbose |
-v |
Show action output preview and LLM call details (model, latency, prompt, response) |
--full |
Show untruncated prompts and output (implies --verbose) |
|
--json |
-j |
Output events as JSON array |
ll-loop test <loop> / ll-loop t <loop>¶
Run a single test iteration to verify loop configuration.
ll-loop simulate <loop> / ll-loop sim <loop>¶
Trace loop execution interactively without running commands.
| Flag | Short | Description |
|---|---|---|
--scenario |
Auto-select results: all-pass, all-fail, first-fail, alternating |
|
--max-steps |
-n |
Override step cap (default: min of loop config or 20) |
--max-iterations |
Override full-pass cap for simulation |
Runner-injected context variables (run_dir, input, run_timestamp) are populated before simulation begins, matching the behaviour of ll-loop run. Loops that reference ${context.run_dir} in early states can be tested with simulate without errors (BUG-2118).
ll-loop install <loop>¶
Copy a built-in loop to .loops/ for customization.
ll-loop show <loop> / ll-loop s <loop>¶
Show loop details and FSM structure. The header line displays active per-loop config overrides (e.g., config: handoff_threshold=60) when a config: block is present in the loop YAML.
The Commands section at the bottom of the output can be overridden by adding a top-level commands: list to the loop YAML. Each entry is a {cmd, comment} pair; when present, this list replaces the five generic default commands so that loops requiring --param or --context flags can surface copy-paste-ready examples. See docs/generalized-fsm-loop.md for the full commands: schema.
State overview table columns. When --show-diagrams is not in --json mode, the main body of ll-loop show prints a compact state overview table with four columns:
| Column | Meaning |
|---|---|
State |
State name; the initial state is prefixed with →. |
Type |
Action shape: sub-loop (state with a loop: field — renders magenta), shell, agent, llm_structured, check_semantic, etc.; (terminal) states show —. Lets you read at a glance which states delegate to another loop vs run inline logic. |
Action Preview |
First non-blank line of the state's action: source (or [sub-loop: <name>] for delegating states), truncated to fit terminal width. |
Transitions |
Compact routing summary: each on_yes / on_no / on_error / on_partial / next / route.<verdict> label grouped by target (e.g., yes→done, no→retry); emits — when the state has no explicit routing. |
This state-overview table is separate from the --show-diagrams ASCII diagram — the table is always rendered in --clean / --summary / default output as a quick reference; the diagram shows the graph topology when --show-diagrams is enabled.
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output FSM config as JSON |
--resolved |
Expand sub-loop states inline under _subloop key (requires --json) |
|
--show-diagrams[=MODE] |
Display FSM diagram inline. MODE is a topology (layered|neighborhood|inline|window) or preset (detailed|summary|clean|local|slim|oneline). Bare flag selects summary. Override facets with --diagram-edge-labels=on\|off, --diagram-state-detail=title\|full, --diagram-scope=main\|full. Mutually exclusive with --json. |
|
--diagram-edge-labels |
Override edge-label visibility for the diagram (on|off). |
|
--diagram-state-detail |
Override state-detail level for the diagram (title|full). |
|
--diagram-scope |
Override diagram scope (main|full). |
ll-loop fragments <lib>¶
List fragments defined in a library file, showing each fragment's name and description. Resolves the library path relative to .loops/, then falls back to the built-in library directory.
ll-loop fragments lib/common.yaml # list built-in common fragments
ll-loop fragments lib/cli.yaml # list built-in CLI tool fragments
ll-loop fragments lib/benchmark.yaml # list built-in benchmark runner fragment
ll-loop fragments lib/prompt-fragments.yaml # list built-in prompt fragment library
ll-loop fragments lib/harness.yaml # list built-in Playwright screenshot fragment
ll-loop fragments .loops/my-lib.yaml # list project-local fragment library
ll-loop next-loop¶
Inspect .loops/.history/ and suggest the next loop(s) to run, with resolved input parameters where available. Useful for unattended chaining or scheduled follow-up work.
| Flag | Short | Description |
|---|---|---|
--count N |
-n |
Return top N suggestions instead of just one (default: 1) |
--json |
-j |
Output suggestions as a JSON array |
--execute |
Run the top suggestion immediately via the same code path as ll-loop run |
|
--exclude NAME |
Skip the named loop from suggestions (repeatable; useful from on-completion hooks to avoid trivial self-loops) |
Each suggestion includes a scored rationale (run frequency, recency, success rate) and a ready-to-paste shell command. For autodev, the suggested input is automatically resolved to the current set of status: open issue IDs.
JSON output keys: loop, input, context, score, rationale, command
Examples:
ll-loop next-loop # Top suggestion with human-readable output
ll-loop next-loop --count 3 # Top 3 ranked candidates
ll-loop next-loop --json # Machine-readable suggestion
ll-loop next-loop --execute # Run the top suggestion immediately
ll-loop next-loop --exclude autodev # Skip autodev (e.g. from its own on-completion hook)
ll-loop next-loop --count 3 --json # Top 3 as JSON for downstream tooling
ll-loop audit-meta¶
Read meta-eval.jsonl from archived runs and print a summary table of LLM vs. external-evaluator agreement statistics. Useful for diagnosing meta-loops where the LLM judge may be too lenient or agreeing on no-op iterations.
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output stats as a JSON object |
Exit codes: 0 = no divergence flags triggered; 1 = at least one threshold crossed (agreed: false streak ≥ 3, or trivial-agreement streak ≥ 3).
Examples:
ll-loop audit-meta harness-optimize # Human-readable summary table
ll-loop audit-meta harness-optimize --json # JSON output for scripting
ll-loop diagnose-evaluators¶
Scan .loops/.history/*-<loop>/events.jsonl to detect non-discriminating evaluator states whose verdict has near-zero variance across runs. Flags states below --threshold (default 0.05) with pattern-matched recommendations for improving discriminating power.
| Flag | Short | Description |
|---|---|---|
--threshold |
Variance floor below which a state is flagged (default: 0.05) | |
--min-runs |
Minimum runs required for meaningful variance (default: 10) | |
--json |
-j |
Output results as a JSON object; each evaluator entry includes ci_lower and ci_upper (Wilson 95% CI bounds on the pass-rate) |
Exit codes: 0 = no low-variance states found or insufficient data; 1 = at least one non-discriminating evaluator flagged.
Examples:
ll-loop diagnose-evaluators harness-refine-issue # Human-readable report
ll-loop diagnose-evaluators harness-refine-issue --json # JSON output for scripting
ll-loop diagnose-evaluators harness-refine-issue --threshold 0.1 --min-runs 5
ll-loop calibrate-budget¶
Report per-evaluator Bernoulli variance p*(1-p) to decide whether increasing max_steps will improve outcomes. Calls the same analytics engine as diagnose-evaluators but frames output around retry-budget ROI: evaluators below the variance threshold waste iterations and should be fixed before raising max_steps.
| Flag | Short | Description |
|---|---|---|
--threshold |
Variance floor below which a state is flagged (default: 0.05) | |
--min-runs |
Minimum runs required for meaningful variance (default: 10) | |
--json |
-j |
Output results as a JSON object; each evaluator entry includes ci_lower and ci_upper (Wilson 95% CI bounds on the pass-rate) |
Exit codes: 0 = all evaluators healthy or insufficient data; 1 = at least one evaluator flagged (fix before increasing max_steps).
Examples:
ll-loop calibrate-budget rn-refine # Human-readable variance report
ll-loop calibrate-budget rn-refine --json # JSON output for scripting
ll-loop calibrate-budget rn-refine --threshold 0.1 --min-runs 5
ll-loop promote-baseline¶
Promote the latest run's action output as the new comparator baseline. Reads action_output events from the most recent .loops/.history/*-<loop>/events.jsonl and writes the concatenated output to .loops/baselines/<loop>/output.txt. Use this to manually set the baseline after inspecting a run, as an alternative to auto_promote: true.
Arguments:
| Argument | Description |
|----------|-------------|
| loop | Loop name |
Exit codes: 0 = baseline promoted successfully; 1 = no history found or no action_output events.
Examples:
ll-loop edit-routes¶
Render a loop's routing logic as an editable decision table. Opens the table in $EDITOR (or prints to stdout with --dry-run). On save, parses the edited table and writes changes back to the loop YAML, preserving all non-route fields, comments, and YAML structure.
Two rendering modes:
- State × verdict matrix (default) — one row per state, one column per verdict. Used for standard loops.
- Compound decision table (auto-detected or
--decision-table) — used for loops that importlib/policy-router.yamlwith acontext.policy_rulesblock. Renders a condition-columns × action grid where each row is one conjunctive rule, columns are scored dimensions, and the final column is the target action state.
Before opening the editor in verdict-matrix mode, prints warnings for: unreachable states, dead-end states (no outbound routes and not terminal), and missing verdict arms (e.g. on_yes without on_no or default). In decision-table mode, warns on shadowed rules, missing catch-all, and unknown action states.
Arguments:
| Argument | Default | Description |
|----------|---------|-------------|
| loop | | Loop name or path |
| --format {markdown,csv} | markdown | Output format for the table |
| --dry-run | | Print table to stdout without opening editor |
| --no-warnings | | Skip gap/conflict detection output |
| --allow-delete | | Allow deletion of state blocks that were removed from the edited table (default: removed rows are ignored) |
| --decision-table | | Force compound policy-router decision table instead of state × verdict matrix |
State operations via the verdict-matrix table:
- Edit routes — change any cell in the table; the corresponding on_<verdict> field is updated on save.
- Add a terminal stub — add a new row with a state name that doesn't exist yet and leave all verdict cells empty. On save the state is inserted with terminal: true as a placeholder you can expand later.
- Delete a state — remove a row entirely, then re-run with --allow-delete. Without --allow-delete, deleted rows are silently ignored.
Compound decision table format:
| # | confidence | outcome | security | aggregate | → action |
|----|------------|---------|----------|-----------|--------------|
| 1 | — | — | <65 | — | escalate |
| 2 | >=85 | >=75 | — | — | implement |
| 3 | * | * | * | * | deep_repair |
Each condition cell is an operator+value (>=85, <65, ==true). Empty cell (—) means dimension unconstrained in that rule. Catch-all row uses * in all condition columns (first-match-wins, catch-all should be last). Edit cells or reorder rows; save to write changes back to context.policy_rules.
Exit codes: 0 = success or no changes; 1 = parse error or unknown state in edited table (when not a new stub); 2 = loop not found.
Examples:
ll-loop edit-routes rn-implement # Open routing table in $EDITOR
ll-loop edit-routes rn-implement --dry-run # Print table to stdout
ll-loop edit-routes rn-implement --format csv --dry-run # CSV format
ll-loop edit-routes rn-implement --no-warnings # Skip gap warnings
ll-loop edit-routes rn-implement --allow-delete # Apply row deletions
ll-loop edit-routes policy-refine --decision-table # Compound table (explicit)
ll-loop edit-routes policy-refine --dry-run # Auto-detects decision-table mode
Examples:
ll-loop fix-types # Run loop (shorthand for run)
ll-loop run fix-types --worktree # Run in isolated git worktree
ll-loop run fix-types --dry-run # Show execution plan
ll-loop run fix-types --dry-run --show-diagrams # FSM diagram + execution plan
ll-loop run fix-types --dry-run --show-diagrams=detailed # Detailed diagram + plan
ll-loop validate fix-types # Validate loop definition
ll-loop test fix-types # Run single test iteration
ll-loop simulate fix-types # Interactive simulation
ll-loop simulate fix-types --scenario all-pass
ll-loop list # List available loops
ll-loop list --running # List running loops
ll-loop list --json # JSON array of available loops
ll-loop status fix-types # Show loop status
ll-loop status fix-types --json # Loop state as JSON
ll-loop stop fix-types # Stop a running loop
ll-loop resume fix-types # Resume interrupted loop
ll-loop history fix-types # Show execution history
ll-loop history fix-types --tail 20 # Last 20 events
ll-loop history fix-types --verbose # Include LLM call details
ll-loop history fix-types --full # Untruncated output
ll-loop history fix-types --json # JSON output
ll-loop history fix-types <run_id> # Inspect a specific archived run
ll-loop install fix-types # Install built-in loop
ll-loop show fix-types # Show loop details
ll-loop show fix-types --json # FSM config as JSON
ll-loop show fix-types --json --resolved # FSM config with sub-loop states expanded
ll-loop fragments lib/common.yaml # List built-in common fragments with descriptions
ll-loop fragments lib/cli.yaml # List built-in CLI tool fragments with descriptions
ll-loop fragments lib/benchmark.yaml # List built-in benchmark runner fragment
ll-loop fragments lib/prompt-fragments.yaml # List built-in prompt fragment library
ll-loop fragments lib/harness.yaml # List built-in Playwright screenshot fragment
ll-loop next-loop # Suggest next loop from history
ll-loop next-loop --count 3 --json # Top 3 suggestions as JSON
ll-loop audit-meta fix-types # Summarize meta-eval agreement stats
ll-loop audit-meta fix-types --json # JSON output
See LOOPS_GUIDE for loop configuration details.
Issue Management¶
ll-issues¶
Issue management and visualization utilities.
Subcommands:
ll-issues next-id / ll-issues ni¶
Print the next globally unique issue number across all types.
| Flag | Description |
|---|---|
--count N / -n N |
Print N consecutive IDs starting at max+1, one per line (default: 1). Must be a positive integer; 0 or negative values exit with code 2. |
--config |
Path to project root |
ll-issues list / ll-issues l¶
List issues with optional filters.
| Flag | Description |
|---|---|
--type |
Filter by type: BUG, FEAT, ENH, EPIC |
--priority |
Filter by priority: P0–P5, or comma-separated e.g. P1,P2 |
--label |
Filter by label from labels: frontmatter; repeatable for OR match |
--milestone |
Filter by milestone name from milestone: frontmatter (exact match) |
--group-by |
Group output by type (default, existing four-bucket view) or epic (group child issues under their parent ID, with an "Unparented" bucket for issues without a parent: field; each EPIC bucket header includes a (N/M done · K blocked) progress badge). The (N/M done) denominator is the EPIC's full transitive descendant set, including nested EPICs — a nested EPIC child is rendered as its own row in a Sub-EPICs (k) sub-section beneath the parent heading, each carrying its own (j/m done) rollup, so the badge and the visible list always agree (BUG-2480). |
--status |
Filter by status: open (default), in_progress, blocked, deferred, done, cancelled, all. Note: synonyms in on-disk frontmatter are normalized on read, but --status arguments must use canonical values (argparse validates choices before normalization runs). |
--parent EPIC-NNN |
Filter to the full transitive descendant set of the given EPIC or issue ID (e.g. --parent EPIC-101) — grandchildren nested under an intermediate (often done) FEAT/ENH are included, resolved via the same cycle-safe walker as epic-progress. Still --status-gated (default open), so completed descendants are not re-surfaced. |
--flat |
Output flat list for scripting |
--json / -j |
Output as JSON array; each entry includes id, title, priority, type, status, path, labels, milestone, and parent (the parent EPIC or issue ID when set) |
--include-summary |
When combined with --json, adds a "summary" key to each JSON object containing the plain text of the issue's ## Summary section (empty string if absent). No-op without --json. |
--sort / -s |
Sort by field: priority (default), id, type, title, created, completed, confidence, outcome, refinement |
--asc |
Sort ascending |
--desc |
Sort descending |
--limit / -n |
Cap output at N issues (must be ≥ 1) |
--config |
Path to project root |
ll-issues count / ll-issues c¶
Count issues. Outputs a single integer by default, or a JSON object with breakdowns.
| Flag | Description |
|---|---|
--type |
Filter by type: BUG, FEAT, ENH, EPIC |
--priority |
Filter by priority: P0–P5, or comma-separated e.g. P1,P2 |
--status |
Filter by status: open (default), in_progress, blocked, deferred, done, cancelled, all. Note: synonyms in on-disk frontmatter are normalized on read, but --status arguments must use canonical values (argparse validates choices before normalization runs). |
--json / -j |
Output JSON with total, status, by_type, and by_priority breakdowns |
--config |
Path to project root |
ll-issues show <issue_id> / ll-issues s <issue_id>¶
Show summary card for a single issue. Accepts short form (518), type-prefixed (FEAT-518), or full (P3-FEAT-518). Searches all type directories regardless of status.
The card includes: ID, title, priority, status, effort, risk, confidence scores, dimension scores (Cmplx, Tcov, Ambig, Chsrf — when present), source (discovered_by), integration file count, labels, captured_at / completed_at timestamps (when present), session history, and path.
Rendering is scanning-first (ENH-2574): the title is bold, borders/field labels/the Path line are dimmed, status is colored per state, and the inter-field separator is · rather than the border glyph. Several rows are pruned or collapsed for signal:
- Source is omitted when
discovered_byis absent or when its value ismanual(the default case). - Norm/Fmt collapse into a single
Needs: formattingrow, shown only when the file is actually missing required sections — nothing renders when formatting is already correct. captured_at/completed_atrender date-only (theT00:00:00Ztime component is dropped);Captured atis omitted entirely when it's the same calendar date asDiscovered.- Once the capture/discovery/relationships/history/closure block has 4 or more rows, labels right-pad into a column so every row's value starts at the same position.
The card also surfaces, when present in frontmatter (ENH-2535):
- Closure context —
closing_note/cancelled_reason/deferred_reasonplusclosed_by,closed_at,deferred_date(only when status isdone,cancelled, ordeferred). - Relationships —
parent(with epic title when resolvable),relates_to,depends_on,blocked_by,blocks,supersedes,decomposed_into,affects,focus_area. - Discovery —
discovered_date(distinct fromcaptured_at),discovered_commit(short-SHA, first 7 chars),discovered_branch,discovered_source,discovered_external_repo. - Decision coupling — when
decision_needed: trueis paired withdecision_ref(e.g.,ARCHITECTURE-049), the card rendersDecision needed → ARCHITECTURE-049; explicitDecision needed: nofordecision_needed: false.
| Flag | Description |
|---|---|
--json / -j |
Output issue fields as JSON (includes source, norm, fmt keys) |
ll-issues path <issue_id> / ll-issues p <issue_id>¶
Print the relative file path for an issue ID. Accepts short form (1009), type-prefixed (FEAT-1009), or full (P3-FEAT-1009). Searches all type directories regardless of status. Exits 0 on match, 1 if not found.
| Flag | Description |
|---|---|
--json / -j |
Output as JSON object {"path": "..."} |
ll-issues search [query] / ll-issues sr [query]¶
Search issues with filters and sorting.
| Argument/Flag | Description |
|---|---|
query |
(Optional) Text to match against title and body (case-insensitive) |
--type |
Filter by type: BUG, FEAT, ENH, EPIC (repeatable) |
--priority |
Filter by priority: P0–P5 or range e.g. P0-P2 (repeatable) |
--status |
Filter by status: open (default), in_progress, blocked, deferred, done, cancelled, all |
--include-completed |
Include issues of all statuses (alias for --status all) |
--label |
Filter by label tag (repeatable) |
--since |
Only issues on or after DATE (YYYY-MM-DD) |
--until |
Only issues on or before DATE (YYYY-MM-DD) |
--date-field |
Date field to filter on: discovered (default) prefers captured_at frontmatter (sub-day resolution) and falls back to discovered_date; updated uses the last ## Session Log entry timestamp, falling back to file mtime |
--sort |
Sort field: priority (default), id, date, type, title, created, completed, confidence, outcome, refinement |
--asc / --desc |
Sort direction |
--format |
Output format: table (default), list, ids |
--limit |
Cap results at N |
--json / -j |
Output as JSON array; each entry includes id, title, priority, type, status, path, labels, milestone, and parent |
ll-issues sequence / ll-issues seq¶
Suggest a dependency-ordered implementation sequence.
| Flag | Description |
|---|---|
--type |
Filter by issue type: BUG, FEAT, ENH, EPIC |
--limit |
Maximum issues to show (default: 10) |
--json / -j |
Output sequence as JSON array |
--config |
Path to project root |
ll-issues impact-effort / ll-issues ie¶
Display an impact vs. effort matrix for active issues.
| Flag | Description |
|---|---|
--type |
Filter by type: BUG, FEAT, ENH, EPIC |
--json / -j |
Output as JSON object with quadrant keys |
ll-issues refine-status / ll-issues rs¶
Show refinement depth table sorted by commands touched. Columns: ID, Pri, size, Title, source, norm, fmt, per-command session indicators (✓/—), Ready (confidence score), conf (outcome confidence), cmplx (complexity score 0–25), tcov (test coverage score 0–25), ambig (ambiguity score 0–25), chsrf (change surface score 0–25), total.
| Argument/Flag | Description |
|---|---|
ISSUE-ID |
(Optional) Filter to a single issue by ID (e.g. FEAT-873, BUG-525). Ignores --type when set. Exits 1 if the issue is not found. |
--type |
Filter by type: BUG, FEAT, ENH, EPIC (ignored when ISSUE-ID is provided) |
--format |
Output format: table (default), json (NDJSON) |
--json / -j |
Output as JSON array; with ISSUE-ID outputs a single JSON object instead |
--no-key |
Suppress the key/legend section at the bottom of output |
--config |
Path to project root |
The Norm column checks filenames against ^P[0-5]-(BUG|FEAT|ENH|EPIC)-[0-9]{3,}-[a-z0-9-]+\.md$. JSON output includes a "normalized": true/false boolean field per record.
Narrow terminal support: When the table exceeds the available terminal width, columns are automatically elided in priority order. The default drop sequence is source → norm → fmt → size → chsrf → ambig → tcov → cmplx → confidence → ready → total; any remaining command columns are then dropped rightmost-first. id, priority, and title are always pinned. The title column maintains a minimum width of 20 characters. The drop order is configurable via refine_status.elide_order in ll-config.json — see CONFIGURATION.md.
ll-issues next-action / ll-issues na¶
Print the next refinement action needed across all active issues. Designed for FSM loop integration — exits 1 when work remains, exits 0 when all issues are ready.
Output format: <ACTION> <issue-id> (one line), or ALL_DONE.
| Action token | Meaning |
|---|---|
NEEDS_FORMAT |
Issue file does not match template v2.0 structure |
NEEDS_VERIFY |
/ll:verify-issues has not been run on this issue |
NEEDS_SCORE |
Confidence/outcome score is missing |
NEEDS_REFINE |
Score is below threshold and refine-cap not reached |
| Flag | Default | Description |
|---|---|---|
--refine-cap N |
5 |
Max /ll:refine-issue runs before moving on |
--ready-threshold N |
85 |
Minimum readiness score to consider issue ready |
--outcome-threshold N |
70 |
Minimum outcome confidence score to consider issue ready |
--skip / -s ISSUE_ID[,...] |
— | Comma-separated issue IDs to exclude (e.g. ENH-929,BUG-001); absent --skip preserves existing behavior |
--config |
(auto) | Override the config file path |
Config-driven defaults:
next-actionreadscommands.confidence_gate.readiness_thresholdfrom.ll/ll-config.jsonbefore falling back to the CLI default of85. Setcommands.confidence_gate.readiness_threshold: 90in your project config to raise the bar globally without passing--ready-thresholdon every call. The--ready-thresholdflag still overrides the config value when provided explicitly.
ll-issues next-issue / ll-issues nx¶
Print the issue ranked highest by outcome confidence and readiness score. Designed for FSM loop integration — use this to pick the best issue to work on next based on implementation readiness rather than raw priority.
Sort order: Config-driven via issues.next_issue.strategy (default: confidence_first — outcome_confidence desc, confidence_score desc, priority asc). Issues without scores are ranked below all scored issues.
Dependency filter: By default (ENH-2436), issues whose Blocked By references a non-terminal (done/cancelled) issue are filtered out before ranking, so the returned ID is always actionable. Pass --include-blocked to revert to the legacy behavior (return any active issue, blocked or not).
EPIC exclusion: EPIC-type ids are never returned (BUG-2638). EPICs are umbrella containers meant to be decomposed via scope resolution (SprintManager.load_or_resolve), not implemented as leaves; the exclusion applies to all output modes (--json, --path, --include-blocked).
Exit codes: 0 = issue found, 1 = no active issues OR every active issue is currently blocked. The all-blocked case emits Error: No ready issues (N blocked, 0 ready) on stderr.
| Flag | Description |
|---|---|
--json / -j |
Output a JSON object: {id, path, outcome_confidence, confidence_score, priority}. With --include-blocked, the row also carries blocked (bool), blocked_by (sorted list of issue IDs), and pending_prerequisites (sorted list of still-open soft depends_on targets). blocked reflects hard blocked_by edges only, so the three states are distinguishable: hard-blocked (blocked: true), soft-deferred (blocked: false with a non-empty pending_prerequisites), and ready (blocked: false, pending_prerequisites: []). |
--path |
Output only the file path (useful for shell scripting: $(ll-issues next-issue --path)) |
--skip / -s ISSUE_ID[,...] |
Comma-separated issue IDs to exclude (e.g. FEAT-007,BUG-001); absent --skip preserves existing behavior |
--include-blocked |
Include issues with unresolved blockers in the ranked output. With --json, each row carries blocked, blocked_by, and pending_prerequisites fields. |
--config |
Path to project root |
ll-issues next-issues [N] / ll-issues nxs [N]¶
Print all active issues in ranked order by outcome confidence and readiness score. Designed for FSM loop integration — use this to get a ranked list of all issues, not just the top one.
Sort order: Config-driven via issues.next_issue.strategy (default: confidence_first — outcome_confidence desc, confidence_score desc, priority asc). Issues without scores are ranked below all scored issues.
Dependency filter: By default (ENH-2436), issues whose Blocked By references a non-terminal (done/cancelled) issue are filtered out before ranking. Pass --include-blocked to revert to the legacy behavior.
EPIC exclusion: EPIC-type ids are never returned (BUG-2638), in any output mode. EPICs are decomposed via scope resolution, not ranked as implementable leaves.
Exit codes: 0 = at least one unblocked issue found, 1 = no active issues OR every active issue is currently blocked. The all-blocked case emits Error: No ready issues (N blocked, 0 ready) on stderr.
| Flag/Arg | Description |
|---|---|
N |
Optional count — limit output to top N issues |
--json / -j |
Output a JSON array of objects: {id, path, outcome_confidence, confidence_score, priority}. With --include-blocked, each row also carries blocked (bool), blocked_by (sorted list), and pending_prerequisites (sorted list of still-open soft depends_on targets). As with next-issue, blocked reflects hard blocked_by edges only, so hard-blocked, soft-deferred, and ready rows are distinguishable. |
--path |
Output file paths instead of issue IDs |
--include-blocked |
Include issues with unresolved blockers in the ranked list. With --json, each row carries blocked, blocked_by, and pending_prerequisites fields. |
--config |
Path to project root |
ll-issues skip <issue_id> / ll-issues sk¶
Deprioritize an active issue by bumping its priority prefix and appending a ## Skip Log entry. Use this to move refinement failures or blocked issues out of the active queue without completing or deleting them.
| Argument / Flag | Short | Description |
|---|---|---|
<issue_id> |
Issue to deprioritize. Accepts numeric ID (955), type+ID (FEAT-955), or full prefix (P3-FEAT-955) |
|
--priority |
-p |
Target priority P0–P5 (default: P5) |
--reason TEXT |
Reason text appended to the ## Skip Log entry in the issue file |
Behavior:
- Renames the issue file with the new priority prefix (e.g., P3-FEAT-955 → P5-FEAT-955) using git mv for tracked files to preserve history, falling back to an atomic rename for untracked files
- Appends a ## Skip Log section with ISO timestamp and the provided reason (or "No reason provided" if omitted)
- If the issue is already at the target priority, the file is not renamed but the Skip Log entry is still appended
- Works on issues in any type directory (bugs/, features/, enhancements/, epics/)
- Prints the new file path to stdout on success
Examples:
ll-issues skip FEAT-955 # Deprioritize to P5 (default)
ll-issues skip 955 --priority P4 # Deprioritize to P4
ll-issues skip BUG-042 --reason "retry after CI fix" # With reason
ll-issues sk ENH-123 -p P3 --reason "blocked on upstream change"
ll-issues finalize-decomposition <parent> [children...] / ll-issues fd¶
Close a decomposed parent issue and re-link its children to the parent's EPIC. Sets the parent's status to done, optionally moves it to its type directory, and updates the EPIC's child references.
| Argument/Flag | Description |
|---|---|
parent |
Decomposed parent issue ID (e.g., ENH-123) |
children |
(Optional) Child issue IDs as positional arguments |
--children-file PATH |
File with one child ID per line (e.g., the children_<id>.txt artifact from rn-decompose) |
--issues-dir DIR |
Issues base directory (default: .issues) |
--no-move |
Do not move the closed parent into the completed directory; update status only |
--config |
Path to project root |
Examples:
ll-issues finalize-decomposition ENH-123 ENH-124 ENH-125 # Close ENH-123; re-link children
ll-issues fd ENH-123 --children-file run_dir/children_ENH-123.txt # Load children from file
ll-issues fd ENH-123 --no-move # Status-only close; no file move
ll-issues append-log <issue_path> <log_command> / ll-issues al¶
Append a session log entry to an issue file.
| Argument | Description |
|---|---|
issue_path |
Path to the issue markdown file |
log_command |
Command name to record (e.g., /ll:refine-issue) |
ll-issues sections <type> / ll-issues sec <type>¶
Print the JSON content of the per-type section template for <type>. Resolves via 4-tier precedence — explicit issues.templates_dir config → <project_root>/.ll/templates/ (project-deployed copy) → bundled wheel templates — so project-local overrides (deployed via ll-init --deploy-templates) are returned automatically. Skills and commands should call this instead of reading scripts/little_loops/templates/{type}-sections.json directly.
| Argument/Flag | Description |
|---|---|
type |
Issue type: bug, feat, enh, or epic |
--path |
Output only the resolved file path (useful for shell scripting) |
Examples:
ll-issues sections bug # Print bug-sections.json content
ll-issues sections feat --path # Print resolved path (for shell scripting)
ll-issues sec enh # Alias: sec
ll-issues sections epic --path # Resolved path to epic-sections.json
Examples:
ll-issues next-id
ll-issues list --type FEAT --priority P2
ll-issues list --priority P1,P2 # Filter by multiple priorities
ll-issues list --json # JSON array of all active issues
ll-issues list --type BUG --json # JSON filtered by type
ll-issues count # Total active issue count
ll-issues count --json # JSON with breakdowns
ll-issues count --type BUG # Count bugs only
ll-issues count --status done # Count done issues
ll-issues count --status all # Total across all statuses
ll-issues show FEAT-518
ll-issues show 518
ll-issues show FEAT-518 --json # Issue fields as JSON
ll-issues path 1009 # Resolve numeric ID to file path
ll-issues path FEAT-1009 # Resolve TYPE-NNN to file path
ll-issues path P3-FEAT-1009 # Resolve full ID to file path
ll-issues path FEAT-1009 --json # Output as {"path": "..."}
ll-issues search "caching" # Search by keyword
ll-issues search --type BUG --priority P0-P2 # Filter bugs by priority range
ll-issues search --since 2026-01-01 --json # Issues since date as JSON
ll-issues sequence --limit 10
ll-issues sequence --json # Ordered sequence as JSON
ll-issues impact-effort
ll-issues impact-effort --type BUG # Only bugs
ll-issues impact-effort --json # JSON object with quadrant arrays
ll-issues impact-effort --json --type BUG # Filtered JSON output
ll-issues refine-status
ll-issues refine-status FEAT-873 # Single-issue view
ll-issues refine-status FEAT-873 --json # Single issue as JSON object
ll-issues refine-status --type BUG --format json
ll-issues next-action # Next refinement action needed (exits 1 if work remains)
ll-issues next-action --refine-cap 3 # Lower the refine-cap
ll-issues next-action --ready-threshold 90 # Stricter readiness threshold
ll-issues next-action --skip ENH-929,BUG-001 # Exclude specific issues from consideration
ll-issues next-issue # Highest-confidence issue ID
ll-issues next-issue --json # As JSON: {id, path, outcome_confidence, confidence_score, priority}
ll-issues next-issue --path # File path only (for shell scripting)
ll-issues next-issue --skip FEAT-007,BUG-001 # Exclude specific issues from consideration
ll-issues next-issues # All active issues in ranked order
ll-issues next-issues 5 # Top 5 ranked issues
ll-issues nxs --json # Ranked list as JSON array
ll-issues nxs --path # Ranked list as file paths
ll-issues skip FEAT-955 # Deprioritize to P5
ll-issues skip BUG-042 --priority P4 --reason "retry after CI fix"
ll-issues append-log .issues/bugs/P2-BUG-123-foo.md /ll:refine-issue
ll-issues anchor-sweep --dry-run # Preview file:line rewrites
ll-issues anchor-sweep # Rewrite file:line refs in active issues
ll-issues asw --dry-run # Alias: asw
ll-issues set-status ENH-1725 in_progress # Transition status
ll-issues sst BUG-042 done # Alias: sst
ll-issues epic-progress EPIC-1773 # EPIC progress summary (text)
ll-issues ep EPIC-1773 --format json # EPIC progress as JSON
ll-issues ep EPIC-1773 --format markdown # EPIC progress as markdown
ll-issues clusters / ll-issues cl¶
Visualize issue dependency clusters. Walks all relationship types across active issues by default and renders each connected component. The default tree layout draws an indented, multi-root dependency tree (├──/└── connectors) in which every edge is shown — hub/parent hierarchies (e.g. one EPIC with many parent: children) render with the hub at the root and depth shown naturally, and DAG cross-edges or cycle back-edges appear as ⤷ cross-references rather than being demoted to a trailing skip-edge list.
Flags:
| Flag | Default | Description |
|---|---|---|
--layout {tree,list,boxes} |
tree |
Diagram layout. tree (default): indented multi-root dependency tree with every edge shown inline. list: one line per issue with edge annotations (compact). boxes: legacy vertical box-stack with arrows between consecutive boxes and a trailing skip-edge list. An explicit --layout overrides --compact. |
--compact / --summary |
off | Alias for --layout list. |
--edges SET |
all |
Relationship types to follow. Aliases: all (all types), blocking (blocked_by+blocks only — legacy behaviour), hard (blocked_by+blocks+depends_on). Or a comma-separated list of: blocked_by,blocks,depends_on,relates_to,parent. |
--status SET |
active |
Issue statuses to include. Aliases: active (open/in_progress/blocked), +deferred (active + deferred), all (everything except cancelled). Or a comma-separated list of canonical status values. |
--cluster N |
— | Render only the Nth cluster (1-indexed). |
--limit N |
— | Render at most N clusters; the footer reports how many were suppressed. |
--include-orphans |
off | Include 1-issue clusters (isolated issues with no relationships). |
--min-connections N |
0 | Only show clusters where at least one issue has N or more connections. |
--json / -j |
off | Output as JSON array. Each element has cluster_index, issue_count, issues, and edges (with relationship values: blocked_by, blocks, depends_on, relates_to, parent). Output is identical across all --layout values. |
Examples:
ll-issues clusters # Indented dependency tree (default), active issues
ll-issues clusters --layout list # Compact one-line-per-issue view
ll-issues clusters --layout boxes # Legacy vertical box-stack
ll-issues clusters --edges=blocking # Legacy view: blocked_by/blocks only
ll-issues clusters --status=+deferred # Include deferred issues
ll-issues clusters --status=all # All statuses except cancelled
ll-issues clusters --json | jq '[.[] | {n: .issue_count, types: [.edges[].relationship] | unique}]'
ll-issues cl --include-orphans # Show isolated issues too
ll-issues anchor-sweep / ll-issues asw¶
Scan all active issue files (bugs/, features/, enhancements/, epics/) for bare file:line references outside code fences and rewrite them to enclosing function/class/section anchors. Uses a language-agnostic regex backwards-scan (no AST) covering Python, TypeScript, JavaScript, Go, Rust, Ruby, Java, C#, and Markdown.
| Flag | Description |
|---|---|
--dry-run |
Print what would change without modifying files |
--issues-dir DIR |
Issues base directory (default: .issues) |
Behavior:
- Scans backwards from the cited line number to find the nearest enclosing def/func/fn/function/class/struct/# heading.
- Replaces file.py:42 with `file.py` (near function `foo`).
- References inside code fences are skipped.
- References with no resolvable anchor are left unchanged with a warning.
- Always run --dry-run before the first production sweep.
Examples:
ll-issues anchor-sweep --dry-run
ll-issues anchor-sweep
ll-issues anchor-sweep --issues-dir custom/issues
ll-issues asw --dry-run
ll-issues fingerprint / ll-issues fp¶
Extract a structured fingerprint from an issue file for cross-theme conflict detection. Returns JSON with the issue id, files_to_modify (file paths from the Integration Map), and key_terms (significant words after stop-word filtering). Used by /ll:audit-issue-conflicts --cross-theme Phase 2b to identify cross-batch overlap pairs without an LLM call.
| Argument | Description |
|---|---|
issue_path |
Path to the issue file (absolute or relative to project root) |
Output (JSON):
{"id": "ENH-1801", "files_to_modify": ["scripts/config.py"], "key_terms": ["authentication", "conflict"]}
Examples:
ll-issues fingerprint .issues/enhancements/P3-ENH-1801-example.md
ll-issues fp .issues/bugs/P2-BUG-042-example.md
ll-issues check-flag / ll-issues cf¶
Exit 0 if a named boolean frontmatter field in the issue equals true. Designed for use as a shell gate in FSM loop states.
| Argument | Description |
|---|---|
issue_id |
Issue ID (e.g., 518, FEAT-518, P3-FEAT-518) |
field |
Frontmatter field name (e.g., decision_needed) |
Examples:
ll-issues check-flag 518 decision_needed # Exit 0 if decision_needed: true
ll-issues cf FEAT-518 implementation_ready # Exit 0 if implementation_ready: true
FSM loop use: Use as a shell action with evaluate: {type: exit_code} to branch on a single frontmatter boolean without an LLM call.
ll-issues check-decidable¶
Exit 0 if an issue has >=1 enumerable option to decide between (ENH-2443). Deterministic (no-LLM) companion to /ll:decide-issue --validate-only — re-implements the same option-extraction patterns in pure Python (count_enumerable_options), so FSM shell states can pre-check decidability without dispatching an LLM call. Mirrors the ll-issues format-check / ensure_formatted precedent (ENH-2426).
| Argument | Description |
|---|---|
issue_id |
Issue ID (e.g., 518, FEAT-518, P3-FEAT-518) |
Examples:
ll-issues check-decidable FEAT-398 # Exit 1 (OPTIONS_MISSING) — no enumerable options
ll-issues check-decidable ENH-277 # Exit 0 — 2+ options found
FSM loop use: The check_decision_decidable gate in rn-remediate.yaml (and its parity insertion in autodev.yaml) calls this as a shell action with evaluate: {type: exit_code}, routing to a bounded /ll:refine-issue --auto deposit-options retry on exit 1 rather than letting decide run with nothing to score.
ll-issues check-open-questions¶
Coverage-aware decidability probe (ENH-2446). Companion to check-decidable — exits 0 only when both (a) every option block in ## Proposed Solution carries a > **Selected:** or ### Decision Rationale marker AND (b) no bullet items in ## Edge Cases / ## Confidence Check Notes / ## Open Questions carry an open-question signal (Q:, ?, open question, needs decision, decision needed, open decision, unresolved decision, decision point) without a ✅ RESOLVED / ✔ RESOLVED / **RESOLVED** / > **RESOLVED** marker. Exits 1 with OPEN_QUESTIONS_REMAIN: <ID> — N open question(s) and M unresolved option(s); run /ll:refine-issue <ID> --auto otherwise.
Closes the mixed-issue gap that the count-based check-decidable misses: an issue with already-resolved options PLUS unresolved free-form questions previously routed straight to decide (an idempotent no-op) and bypassed deposit_options entirely.
| Argument | Description |
|---|---|
issue_id |
Issue ID (e.g., 2446, ENH-2446, P2-ENH-2446) |
Examples:
ll-issues check-open-questions FEAT-2339 # Exit 1 (mixed: 0 unresolved options + N open questions)
ll-issues check-open-questions ENH-2446 # Exit 0 — no unresolved decision surface
FSM loop use: The check_decision_decidable gate in rn-remediate.yaml:263 (and its parity insertion in autodev.yaml:211) chains this probe BEFORE check-decidable (check-open-questions || check-decidable) so the coverage gap is caught before the count-based fallback runs. Pair with the open_question_stall evaluator (open_question_stall_gate fragment in lib/common.yaml) for progress-gated re-fire.
ll-issues format-check¶
Deterministic (no-LLM) structural linter for issue formatting (ENH-2426). Grades an issue against its type template and reports gaps in four classes: missing (a required section header absent entirely), renamed (a present section header is deprecated with an extractable canonical replacement, e.g. Proposed Fix → Proposed Solution), empty (a required header present with a whitespace-only body), and boilerplate (a required section's body still equals its creation_template). Fails open — an unresolved template or unreadable issue file reports no gaps (exit 0) rather than blocking.
| Argument/Flag | Default | Description |
|---|---|---|
issue_id |
(required) | Issue ID (e.g., 2426, ENH-2426, P3-ENH-2426) |
--format {text,json} |
text |
Output format |
Examples:
ll-issues format-check ENH-2426 # text report, exit 0/1
ll-issues format-check ENH-2426 --format json # {"missing": [...], "renamed": [...], "empty": [...], "boilerplate": [...]}
FSM loop use: The ensure_formatted gate in rn-remediate.yaml calls this as a shell action with evaluate: {type: exit_code}, routing to /ll:format-issue only when a gap is found — replacing the older missing-headers-only inline check.
ll-issues check-readiness / ll-issues cr¶
Exit 0 if an issue's confidence_score and outcome_confidence frontmatter fields both meet the configured thresholds. Reads thresholds from commands.confidence_gate in ll-config.json, falling back to --readiness / --outcome CLI args.
| Argument/Flag | Default | Description |
|---|---|---|
issue_id |
(required) | Issue ID (e.g., 518, FEAT-518, P3-FEAT-518) |
--readiness N |
90 |
Fallback readiness threshold when not set in ll-config.json |
--outcome N |
75 |
Fallback outcome confidence threshold when not set in ll-config.json |
Examples:
ll-issues check-readiness 518 # Use thresholds from ll-config.json
ll-issues cr FEAT-518 --readiness 85 # Override readiness threshold
ll-issues check-readiness 518 --readiness 80 --outcome 70
FSM loop use: Use as a shell gate in refine-to-ready-issue-style loops to branch without an LLM call. Pair with ll-issues show --json when you need the raw scores.
ll-issues set-scores / ll-issues ss¶
Write confidence_score, outcome_confidence, and the four per-dimension scores into an issue's YAML frontmatter. Writes idempotently: existing fields are overwritten, unrelated keys are preserved, and missing frontmatter is created from scratch. If no score flags are provided, returns 0 with a warning and writes nothing.
| Argument/Flag | Default | Description |
|---|---|---|
issue_id |
(required) | Issue ID (e.g., 518, FEAT-518, P3-FEAT-518) |
--confidence N |
None |
Overall readiness score (0–100) |
--outcome N |
None |
Outcome confidence score (0–100) |
--score-complexity N |
None |
Complexity dimension score (0–25) |
--score-test-coverage N |
None |
Test-coverage dimension score (0–25) |
--score-ambiguity N |
None |
Ambiguity dimension score (0–25) |
--score-change-surface N |
None |
Change-surface dimension score (0–25) |
Examples:
ll-issues set-scores BUG-1307 --confidence 95 --outcome 80
ll-issues ss FEAT-518 --confidence 88 --outcome 72 --score-complexity 22 --score-test-coverage 20 --score-ambiguity 25 --score-change-surface 15
Used by: /ll:confidence-check Phase 4 to persist scores deterministically instead of a free-form Edit call.
ll-issues set-status / ll-issues sst¶
Transition an issue to a new status value. Validates the target status against the canonical enum, updates the status: frontmatter field in-place, and prints the before→after transition to stdout.
| Argument | Description |
|---|---|
issue_id |
Issue ID (e.g., 518, ENH-518, P3-ENH-518) |
status |
New status value: open, in_progress, blocked, deferred, done, cancelled |
--cascade |
Propagate status to issues with parent: <EPIC-ID> (EPIC closure only; only valid with done/cancelled). Only follows parent: edges — relates_to:, blocked_by:, and other relationship types are not traversed. |
--cascade-to <status> |
Status to apply to cascaded children (default: deferred) |
Examples:
ll-issues set-status ENH-1725 in_progress # ENH-1725: open → in_progress
ll-issues sst BUG-042 done # BUG-042: in_progress → done
ll-issues set-status FEAT-100 blocked
ll-issues set-status EPIC-042 cancelled --cascade # Close EPIC + defer children
ll-issues set-status EPIC-042 done --cascade --cascade-to done # Close EPIC + all children
ll-issues epic-progress <epic_id> / ll-issues ep <epic_id>¶
Show a progress summary for an EPIC and all its child issues. Aggregates child statuses into a completion bar, counts by status, surfaces the oldest open child, and lists any blocked children with their blocked_by links.
| Argument/Flag | Short | Default | Description |
|---|---|---|---|
epic_id |
(required) | EPIC ID to summarize (e.g., EPIC-1773) |
|
--format |
-f |
text |
Output format: text, json, or markdown |
--config |
Path to project root |
Sample text output:
EPIC-1773: Audit & simplify built-in FSM loops
Progress: ████████░░░░░░░░ 8/12 resolved (67%)
Status: 2 in_progress • 1 blocked • 1 open • 8 done
Oldest open: ENH-1641 (24 days)
Blocked: ENH-1820 → blocked_by BUG-1701
The "resolved" count on the Progress line is done + cancelled (terminal states). When cancelled issues are present, a breakdown is appended: e.g., 8/12 resolved (67%) (7 done, 1 cancelled). The Status line always shows individual status buckets including the raw done and cancelled counts separately.
Rollup semantics (BUG-2441): The child set is collected by walking the
parent:chain transitively, so grandchildren (and any deeper descendants) of the EPIC roll up into the Progress and Status counts — not just direct children. This matches the bucketing behavior ofll-issues list --bucket epic. Note:ll-sprint's EPIC resolution still counts direct children only; for a sprint-aware breakdown usell-sprint show.Nested EPIC visibility (BUG-2480): a nested EPIC (a
type: EPICchild of another EPIC) counts toward its parent's(N/M done)denominator and is rendered as its own row in aSub-EPICs (k)sub-section underll-issues list --group-by epic, carrying its own(j/m done)rollup from a separatecompute_epic_progresscall. The nested EPIC's own descendants (grandchildren of the outer EPIC) are bucketed under the nested EPIC, not the outer one — so they appear once, either under the outer EPIC's leaf rows or under the nested EPIC's own heading, never duplicated.
Examples:
ll-issues epic-progress EPIC-1773 # Text summary (default)
ll-issues ep EPIC-1773 --format json # JSON object with counts and child list
ll-issues ep EPIC-1773 --format markdown # Markdown-formatted summary
ll-issues decisions¶
Manage rules, decisions, and exceptions log.
Sub-sub-commands:
| Sub-command | Description |
|---|---|
list |
List decisions log entries (with optional filters) |
add |
Add a new rule, decision, or exception entry |
outcome <ID> |
Record the outcome of a decision entry |
generate |
Generate entries from completed issues |
sync |
Sync active rules to .ll/ll.local.md |
suggest-rules |
Analyze decision entries and surface candidates ready for promotion to rules |
promote <ID> |
Convert a decision entry into an enforced rule (rewrites entry in-place; auto-syncs when --enforcement required) |
extract-from-completed |
Extract rules from completed issues via LLM; appends RuleEntry records to the decisions log as .ll/decisions.d/*.json fragments with deduplication |
list flags:
| Flag | Description |
|---|---|
--type |
Filter by entry type: rule, decision, exception |
--category |
Filter by category string |
--label |
Filter by label |
--no-outcome |
Show only DecisionEntry records with no outcome |
--before <ISO-8601> |
Show entries with timestamp before this date |
--scope <scope> |
Filter DecisionEntry records by scope |
--active-only |
Exclude entries superseded by a newer entry |
--enforcement |
Filter rule/coupling entries by enforcement level: required or advisory |
--format / -f |
Output format: text (default), json |
add flags:
| Flag | Applies to | Description |
|---|---|---|
--type |
all | Entry type: rule, decision, exception (required) |
--category |
all | Category string (required) |
--rule |
rule, decision | Rule or decision text (required for these types) |
--rationale |
all | Why this entry applies (required) |
--issue |
all | Related issue ID |
--label |
all | Comma-separated labels |
--enforcement |
rule | required or advisory (default: advisory) |
--rule-ref |
exception | Rule being excepted (required for exception) |
--alternatives-rejected |
decision, exception | Alternatives considered |
--supersedes |
rule | ID of the rule this supersedes |
--scope |
decision | issue (default) or project |
--id |
all | Explicit entry ID (auto-generated if omitted) |
outcome flags:
| Flag | Description |
|---|---|
<ID> |
Entry ID to record outcome for (positional, required) |
--result |
Outcome: worked, did_not_work, mixed, reversed (required) |
--notes |
Free-text notes about the outcome |
--measured-at <ISO-8601> |
When the outcome was measured (default: now) |
--force |
Overwrite an existing outcome |
generate flags:
| Flag | Description |
|---|---|
--from |
Source to generate from: completed (default). Scans issue type directories (.issues/bugs/, .issues/features/, .issues/enhancements/, .issues/epics/) for files with status: done frontmatter, skips entries already present in the decisions log (both .ll/decisions.yaml and .ll/decisions.d/*.json fragments), and appends new decision entries (as fragments) for each issue not yet logged. |
sync flags:
No additional flags. Reads active required rules from the decisions log (both .ll/decisions.yaml and .ll/decisions.d/*.json fragments) and writes them to the ## Active Rules section in .ll/ll.local.md. Creates .ll/ll.local.md if absent. Silently skips when the decisions log is absent (neither tier present).
suggest-rules flags:
No additional flags. Analyzes decision entries and clusters them by category and shared token overlap to surface candidates with recurring patterns. Requires at least 3 decision entries to produce output (exits 1 with a message if fewer).
promote flags:
| Flag | Description |
|---|---|
<ID> |
ID of the decision entry to promote (positional, required) |
--enforcement |
Enforcement level for the new rule: required (default) or advisory. When required, auto-runs sync to push the rule into .ll/ll.local.md immediately. |
extract-from-completed flags:
| Flag | Description |
|---|---|
--since YYYY-MM-DD |
Only process issues completed on or after this date |
--issue ID |
Only extract from this specific issue (e.g. ENH-2151) |
--dry-run |
Print candidates without writing to decisions.yaml |
--min-confidence FLOAT |
Minimum LLM confidence to accept a candidate (default: 0.7) |
ll-issues decisions list
ll-issues decisions list --type rule --active-only
ll-issues decisions list --type rule --enforcement required --active-only # only enforced rules
ll-issues decisions list --no-outcome
ll-issues decisions add --type=decision --category=architecture --rule="Use atomic_write" --rationale="Prevents partial state"
ll-issues decisions outcome dec-001 --result=worked --notes="No incidents in 30 days"
ll-issues decisions generate # Generate from completed issues (default)
ll-issues decisions generate --from completed # Explicit source
ll-issues decisions sync # Sync active rules → .ll/ll.local.md
ll-issues decisions suggest-rules # Surface decision candidates for promotion
ll-issues decisions promote dec-007 # Promote dec-007 → required rule (auto-sync)
ll-issues decisions promote dec-007 --enforcement advisory # Promote as advisory rule
ll-issues decisions extract-from-completed # Extract rules from all completed issues via LLM
ll-issues decisions extract-from-completed --since 2026-01-01 # Only issues completed since date
ll-issues decisions extract-from-completed --issue ENH-2151 # Only one issue
ll-issues decisions extract-from-completed --dry-run # Preview candidates without writing
ll-deps¶
Cross-issue dependency discovery and validation.
Global flags:
| Flag | Short | Description |
|---|---|---|
--issues-dir |
-d |
Path to issues directory (default: .issues) |
--intent QUERY |
Intent query for output filtering (no-op until FTS5 ranking lands) | |
--intent-limit N |
Max lines for intent-filtered output (default: 50) |
Subcommands:
ll-deps analyze¶
Full dependency analysis combining file overlaps and validation.
| Flag | Short | Description |
|---|---|---|
--format |
-f |
Output format: text (default), json |
--graph |
Include ASCII dependency graph | |
--sprint |
Restrict analysis to issues in named sprint |
ll-deps validate¶
Validate existing dependency references only (broken refs, cycles, stale completed refs).
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output as JSON (serializes ValidationResult fields) |
--sprint |
Restrict validation to named sprint |
ll-deps fix¶
Auto-fix broken refs, stale refs, and missing backlinks.
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview fixes without modifying files |
--sprint |
Restrict fixes to named sprint |
ll-deps apply¶
Write proposed dependency relationships to issue files. Re-runs analysis internally and writes accepted proposals (above a confidence threshold) to ## Blocked By sections. Backlinks are intentionally not written — run ll-deps fix afterward to add missing ## Blocks entries.
| Flag | Short | Description |
|---|---|---|
--min-confidence |
Minimum confidence to apply (default: 0.7) |
|
--dry-run |
-n |
Preview without writing |
--sprint |
Restrict to issues in named sprint | |
<source> <relation> <target> |
Explicit pair: FEAT-001 blocks FEAT-002 or FEAT-001 blocked-by FEAT-002 |
ll-deps tree¶
Render an EPIC's child issue hierarchy as a Unicode box-drawing tree with dependency edges.
| Flag | Short | Description |
|---|---|---|
--epic |
EPIC issue ID to render (required, e.g. EPIC-1773) |
|
--format |
-f |
Output format: text (default), json |
JSON output (--format json) emits {"root": "EPIC-NNN", "nodes": [...], "edges": [...]}.
Exits 0 on success; exits non-zero if the EPIC is not found.
Examples:
ll-deps analyze # Full analysis with markdown output
ll-deps analyze --format json # JSON output
ll-deps analyze --graph # Include ASCII dependency graph
ll-deps analyze --sprint my-sprint # Analyze only sprint issues
ll-deps validate # Validation only
ll-deps validate --json # JSON output
ll-deps validate --sprint my-sprint # Validate sprint issue deps
ll-deps fix # Auto-fix broken refs and backlinks
ll-deps fix --dry-run # Preview fixes
ll-deps apply # Apply proposals >= 0.7 confidence
ll-deps apply --min-confidence 0.5 # Lower threshold
ll-deps apply --dry-run # Preview only (no writes)
ll-deps apply --sprint my-sprint # Sprint-scoped apply
ll-deps apply FEAT-001 blocks FEAT-002 # Manual explicit pair
ll-deps apply FEAT-001 blocked-by FEAT-002 # Manual explicit pair (inverse)
ll-deps tree --epic EPIC-1773 # Text tree with ├──/└── connectors
ll-deps tree --epic EPIC-1773 -f json # Structured JSON (root, nodes, edges)
ll-code¶
Structural code queries (callers, callees, imports, impact) via a pluggable CodeQueryProvider
protocol (FEAT-2576). Ships with a grep/AST fallback provider that requires no external
index — every subcommand works out of the box. Graph-backed providers (e.g. ENH-2613's
codegraph, a read-only reader over a .codegraph/codegraph.db index) register in the same
resolver and take priority under --provider auto.
Global flags:
| Flag | Short | Description |
|---|---|---|
--provider |
Provider name (fallback, codegraph), or auto (default) to pick the first available |
|
--json |
-j |
Output as JSON: {provider, freshness, query, results: [CodeRef...]} |
Subcommands:
| Subcommand | Description |
|---|---|
status |
Provider name, availability, freshness, capabilities |
callers-of <symbol> |
Who calls this symbol (heuristic on fallback, exact on codegraph) |
callees-of <symbol> |
What this symbol calls (exact) |
importers-of <module> |
Who imports this module/file (heuristic on fallback, exact on codegraph) |
defines <path> |
Symbols defined in a file (exact) |
references <symbol> |
All reference sites — defs + uses (heuristic on fallback, exact on codegraph) |
impact-of <paths...> [--depth N] |
Reverse transitive closure of files impacted by changes to paths (default depth: 2; fallback only — codegraph has no edge kind mapping to this verb) |
Every result carries a confidence (exact or heuristic) and provider field. Exit codes:
0 = hits, 1 = no hits, 2 = provider error.
status freshness fields (codegraph provider): the detail string reports
indexed_at (index build time, ISO 8601), head_moved (commits landed since the index was
built), dirty_files (uncommitted/untracked file count), and the active policy
(code_query.staleness, ENH-2612). Enforcement: strict makes a stale index report
available: false (the resolver falls through to fallback automatically); warn (default)
serves stale results with freshness: stale; off always reports freshness: fresh.
Examples:
ll-code status # provider name, availability, freshness
ll-code callers-of little_loops.issue_manager.IssueManager.load
ll-code --json callers-of <symbol> # machine-readable output for skills/loops
ll-code --provider fallback callers-of <symbol> # force a specific provider
ll-code --provider codegraph status # inspect the codegraph index's freshness
ll-code impact-of little_loops/state.py --depth 3
History & Analysis¶
ll-history¶
Display summary statistics and analysis for completed issues.
When present in issue frontmatter, captured_at and completed_at are preferred over the legacy discovered_date field and Resolution body regex / git-log fallbacks; the JSON serialization of CompletedIssue includes both fields at sub-day ISO 8601 resolution.
Global flags:
| Flag | Short | Description |
|---|---|---|
--intent QUERY |
Intent query for output filtering (no-op until FTS5 ranking lands) | |
--intent-limit N |
Max lines for intent-filtered output (default: 50) |
Subcommands:
ll-history summary¶
Show issue statistics for completed issues.
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output as JSON |
--directory |
-d |
Path to issues directory (default: .issues) |
When the unified session DB (.ll/history.db, FEAT-1112) contains issue_events rows, summary reads from the DB instead of re-parsing every completed-issue file. An empty/absent DB falls back to file parsing — no behavior change for projects without recorded events (ENH-1621). As of ENH-1691, ll-auto writes issue lifecycle events live during each run via AutoManager's internal SQLiteTransport; ll-session backfill is retained for importing historical data captured before ENH-1691. Only the summary subcommand is DB-backed; analyze and export still scan the files because they need bodies and git history.
ll-history analyze¶
Full analysis with trends, subsystems, and debt metrics.
| Flag | Short | Description |
|---|---|---|
--format |
-f |
Output format: text (default), json, markdown, yaml |
--directory |
-d |
Path to issues directory |
--period |
-p |
Trend grouping: weekly, monthly (default), quarterly |
--compare |
-c |
Compare last N days to previous N days |
--since |
Only analyze issues completed on or after DATE (YYYY-MM-DD) | |
--until |
Only analyze issues completed on or before DATE (YYYY-MM-DD) |
ll-history export <topic>¶
Export topic-filtered excerpts from completed issue history.
| Argument/Flag | Short | Description |
|---|---|---|
topic |
Topic, area, or system to export | |
--output |
Write to file instead of stdout | |
--format |
-f |
Format: narrative (default), structured |
--directory |
-d |
Path to issues directory |
--since |
Only include issues completed after DATE (YYYY-MM-DD) | |
--min-relevance |
Minimum relevance score (default: 0.5) | |
--type |
Filter by type: BUG, FEAT, ENH, EPIC |
|
--scoring |
Relevance method: intersection (default), bm25, hybrid |
ll-history sessions <ISSUE_ID>¶
List sessions that co-occurred with the given issue's active period. Queries the issue_sessions VIEW (v5 schema, ENH-1711) which joins issue_events to message_events via overlapping timestamps. Issues processed after ENH-1839 populate captured_at immediately on live events; a prior ll-session backfill pass (or ENH-1830 auto-backfill) is only needed for older issues.
| Flag | Description |
|---|---|
--limit N |
Maximum results (default: 20) |
--json / -j |
Output as JSON array |
Examples:
ll-history sessions ENH-1710 # Sessions that touched ENH-1710
ll-history sessions ENH-1710 --json # JSON output
Examples (all subcommands):
ll-history summary # Summary statistics
ll-history summary --json # JSON output
ll-history analyze # Full analysis report
ll-history analyze --format markdown # Markdown report
ll-history analyze --compare 30 # Compare last 30 days to previous
ll-history export "session log" # Export excerpts for topic
ll-history export "sprint CLI" --output docs/arch/sprint.md
ll-history sessions ENH-1710 # Sessions that touched ENH-1710
ll-history sessions ENH-1710 --json # JSON output
ll-history root¶
Show the project-root summary node — the top-level condensed node that covers all sessions in the project (ENH-1955). Requires ll-session backfill with compaction and cross-session condensation enabled.
| Flag | Description |
|---|---|
--expand |
Expand and display all messages under the root node |
--limit N |
Maximum messages to show with --expand (default: 20) |
--json / -j |
Output root node metadata + message count as JSON |
Examples:
ll-history root # Show root node metadata
ll-history root --expand # Show metadata + first 20 messages
ll-history root --expand --limit 5 # Show metadata + first 5 messages
ll-history root --json # JSON output
ll-workflows¶
Identify multi-step workflow patterns from user message history. Steps 2 and 3 of the /ll:analyze-workflows pipeline.
Subcommands:
ll-workflows analyze¶
Analyze workflows from messages and Step 1 patterns.
| Flag | Short | Description |
|---|---|---|
--input |
-i |
Input JSONL file with user messages (default: .ll/workflow-analysis/step1-patterns.jsonl) |
--patterns |
-p |
Required. Input YAML from Step 1 (workflow-pattern-analyzer) |
--output |
-o |
Output YAML file (default: .ll/workflow-analysis/step2-workflows.yaml) |
--verbose |
-v |
Show verbose analysis output |
The Python API (analyze_workflows()) accepts an optional db_path argument that prefers the unified session store's message_events table over the JSONL input when populated (ENH-1621); an empty/missing DB transparently falls back to the JSONL file. The --patterns YAML is a generated analysis artifact and stays a file input.
Examples:
# Use conventional path (no --input needed if ll-messages wrote to the default location)
ll-messages --output .ll/workflow-analysis/step1-patterns.jsonl
ll-workflows analyze --patterns .ll/workflow-analysis/step1-patterns.yaml
# Explicit input
ll-workflows analyze -i messages.jsonl -p patterns.yaml -o output.yaml
ll-workflows analyze --input .ll/user-messages.jsonl \
--patterns .ll/workflow-analysis/step1-patterns.yaml
ll-workflows propose¶
Run Step 3 automation proposals from workflow analysis output. Invokes the workflow-automation-proposer skill and writes the proposals to a file. Use this as a CLI-native fallback when the interactive skill invocation is unavailable (e.g., disable-model-invocation breakage).
| Flag | Short | Description |
|---|---|---|
--patterns |
-p |
Required. Step 1 patterns YAML (from ll-messages or workflow-pattern-analyzer) |
--workflows |
-w |
Required. Step 2 workflows YAML (from ll-workflows analyze) |
--output |
-o |
Output path (default: .ll/workflow-analysis/step3-proposals.yaml or .json) |
--format |
-f |
Output format: yaml (default) or json |
Examples:
# Full pipeline — Steps 1, 2, 3 non-interactively
ll-messages --output .ll/workflow-analysis/step1-patterns.jsonl
ll-workflows analyze --patterns .ll/workflow-analysis/step1-patterns.yaml
ll-workflows propose \
--patterns .ll/workflow-analysis/step1-patterns.yaml \
--workflows .ll/workflow-analysis/step2-workflows.yaml
# JSON output at a custom path
ll-workflows propose \
--patterns step1.yaml \
--workflows step2.yaml \
--output out.json \
--format json
Synchronization¶
ll-sync¶
Sync local .issues/ files with GitHub Issues.
Global flags:
| Flag | Description |
|---|---|
--config |
Path to project root |
--quiet |
Suppress non-essential output |
--dry-run |
Show what would happen without making changes |
Subcommands:
ll-sync status¶
Show sync status between local issues and GitHub.
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output as JSON (serializes SyncStatus.to_dict()) |
ll-sync push [issue_ids...]¶
Push local issues to GitHub. If no IDs given, pushes all. When an issue has a milestone: frontmatter field, ll-sync push passes it to gh issue create/edit --milestone <name> to assign the issue to the matching GitHub milestone (by title).
ll-sync pull¶
Pull GitHub Issues to local.
| Flag | Short | Description |
|---|---|---|
--labels |
-l |
Filter by labels (comma-separated) |
ll-sync diff [issue_id]¶
Show differences between local and GitHub issues. Omit issue_id for a summary of all synced issues.
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output as JSON (serializes SyncResult.to_dict()) |
ll-sync close [issue_ids...]¶
Close GitHub issues for completed local issues.
| Flag | Description |
|---|---|
--all-completed |
Close all GitHub issues whose local counterparts have status: done or status: cancelled |
ll-sync reopen [issue_ids...]¶
Reopen GitHub issues for locally-active issues. After a successful reopen, the issue's status frontmatter is updated to open; the file stays in its type directory (bugs/, features/, etc.).
| Flag | Description |
|---|---|
--all-reopened |
Reopen all GitHub issues whose local counterparts are not closed on GitHub |
Examples:
ll-sync status # Show sync status
ll-sync status --json # Sync status as JSON
ll-sync push # Push all local issues to GitHub
ll-sync push BUG-123 # Push specific issue
ll-sync pull # Pull GitHub Issues to local
ll-sync diff BUG-123 # Show diff for specific issue
ll-sync diff # Diff summary for all synced issues
ll-sync diff --json # Diff summary as JSON
ll-sync close ENH-123 # Close GitHub issue for ENH-123
ll-sync close --all-completed # Close all completed issues on GitHub
ll-sync reopen BUG-042 # Reopen GitHub issue for BUG-042
ll-sync reopen --all-reopened # Reopen all issues moved back to active locally
Requires "sync": { "enabled": true } in .ll/ll-config.json.
Utilities¶
ll-messages¶
Extract user messages from Claude Code session logs.
Flags:
| Flag | Short | Description |
|---|---|---|
--limit |
-n |
Maximum messages to extract (default: 100) |
--since |
Include only messages after this date (YYYY-MM-DD or ISO) | |
--output |
-o |
Output file path (default: .ll/user-messages-{timestamp}.jsonl) |
--cwd |
Working directory to use (default: current directory) | |
--exclude-agents |
Exclude agent session files (agent-*.jsonl) |
|
--stdout |
Print to stdout instead of writing to file | |
--verbose |
-v |
Print verbose progress information |
--include-response-context |
Include metadata from assistant responses | |
--skip-cli |
Exclude CLI commands from output | |
--commands-only |
Extract only CLI commands, no user messages | |
--tools |
Comma-separated tools to extract commands from (default: Bash) |
|
--skill |
Filter to sessions where this skill was invoked (e.g. capture-issue) |
|
--examples-format |
Output (input, output) training pairs instead of raw messages (requires --skill); mutually exclusive with --sft-format |
|
--sft-format |
Output conversation turns in SFT training format as JSON-lines (chatml, alpaca, sharegpt); mutually exclusive with --examples-format |
|
--context-window |
Number of context turn-pairs per window in --examples-format or --sft-format (default: 3) |
Examples:
ll-messages # Last 100 messages to file
ll-messages -n 50 # Last 50 messages
ll-messages --since 2026-01-01 # Messages since date
ll-messages -o output.jsonl # Custom output path
ll-messages --stdout # Print to terminal
ll-messages --include-response-context # Include response metadata
ll-messages --skip-cli # Exclude CLI commands
ll-messages --commands-only # Extract only CLI commands
ll-messages --skill capture-issue # Filter to sessions where /ll:capture-issue was invoked
ll-messages --skill capture-issue --examples-format --since 2026-01-01 -o examples.jsonl
ll-messages --skill refine-issue --examples-format --context-window 5 --stdout
ll-messages --sft-format chatml --stdout
ll-messages --sft-format sharegpt --context-window 3 --since 2026-05-01 --stdout
ll-messages --sft-format alpaca --output data/sft/raw.jsonl
ll-logs¶
Discover and extract ll-relevant JSONL entries from Claude Code session logs. Also generates logs/index.md after extraction. The sequences subcommand mines tool-chain n-grams for workflow analysis. The stats subcommand aggregates per-skill invocation frequency and correction rate from .ll/history.db. The dead-skills subcommand cross-references the skill catalog against the log corpus to flag never-invoked and rarely-invoked skills. The scan-failures subcommand mines failed ll-* Bash calls to propose bug issue files.
Subcommands:
| Subcommand | Description |
|---|---|
discover |
List all Claude projects with ll activity (one path per line, sorted) |
tail |
Stream live events from an active loop session |
extract |
Extract ll-relevant JSONL records to logs/<slug>/<session-id>.jsonl |
sequences |
Extract tool-chain n-grams of ll invocations from JSONL logs |
stats |
Aggregate skill invocation frequency and correction rate from history.db |
dead-skills |
Cross-reference skill catalog against log corpus to flag never/rarely-invoked skills |
scan-failures |
Mine failed ll-* Bash calls from session logs; cluster by error signature; optionally create bug issues |
diff |
Compare two sessions' ll-invocation behavior: skills added/removed, per-skill count deltas, and unified sequence diff |
eval-export |
Export EvalFixture v1 records reconstructed from session logs for use with ll-harness |
loop-fleet |
Aggregate cross-project loop-run outcomes for built-in loop improvement |
discover flags:
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output as JSON: {"paths": [...]} |
tail flags:
| Flag | Description |
|---|---|
--loop NAME |
Loop name to tail (required) |
--project DIR |
Project root to tail loops from (default: CWD) |
extract flags:
| Flag | Description |
|---|---|
--all |
Extract all projects with ll activity |
--project DIR |
Working directory of the target project |
--cmd TOOL |
Filter to records containing this ll- tool name (e.g. ll-history) |
sequences flags:
| Flag | Short | Description |
|---|---|---|
--all |
Analyze all projects with ll activity | |
--project DIR |
Working directory of the target project | |
--min-len N |
Minimum n-gram length (default: 2) | |
--min-count M |
Minimum occurrence count to include (default: 1) | |
--top N |
Limit output to top N chains by frequency | |
--window-days D |
Only consider records within D days of latest record | |
--json |
-j |
Output as JSON: [{"chain": [...], "count": N, "edges": [{"from": "...", "to": "...", "freq": f, "pmi": 1.23, "lift": 3.4}], "pmi": 1.23, "lift": 3.4}]; pmi/lift are optional additive fields; lift < 1.0 signals a frequency-prior-equivalent pair |
--all and --project are mutually exclusive for extract, sequences, stats, dead-skills, scan-failures, and eval-export.
stats flags:
| Flag | Short | Description |
|---|---|---|
--all |
Aggregate across all projects with ll activity | |
--project DIR |
Working directory of the target project | |
--window-days D |
Only consider records within D days of latest record | |
--sort {freq,corrections} |
Sort by invocation frequency or correction count (default: freq) | |
--json |
-j |
Output as JSON: [{"skill": str, "invocations": int, "corrections": int, "correction_rate": float}] |
dead-skills flags:
| Flag | Short | Description |
|---|---|---|
--all |
Aggregate across all projects; catalog loaded from current directory | |
--project DIR |
Working directory of the target project (also used as catalog root) | |
--window-days D |
Only consider records within D days of latest record | |
--threshold N |
Skills with invocations ≤ N are "rarely" invoked (default: 3) | |
--json |
-j |
Output as JSON: [{"skill": str, "invocations": int, "tier": "never"\|"rarely"}] |
scan-failures flags:
| Flag | Short | Description |
|---|---|---|
--all |
Scan all projects with ll activity | |
--project DIR |
Working directory of the target project | |
--window-days D |
Only consider records within D days of latest record | |
--capture |
Create BUG issue files for each failure cluster. When combined with --all, scopes capture to Path.cwd() by default — foreign-project clusters are reported but not filed. Use --capture-foreign to also create issues for clusters from other projects |
|
--capture-foreign |
When --capture --all is active, also create BUG issues for failure clusters from projects outside the current working directory |
|
--json |
-j |
Output as JSON: [{"tool": str, "count": int, "normalized_sig": str, "sample_error": str, "session_ids": [...]}] |
diff flags:
| Flag | Short | Description |
|---|---|---|
SESSION_A |
First session ID or JSONL file path (positional) | |
SESSION_B |
Second session ID or JSONL file path (positional) | |
--json |
-j |
Output diff as JSON object |
eval-export flags:
| Flag | Short | Description |
|---|---|---|
--project DIR |
Project working directory (default: cwd) | |
--skill NAME |
Filter exported fixtures to this skill name | |
--issue ID |
Filter to fixtures where this issue ID appears in session context | |
--limit N |
Cap output record count (0 = unlimited) | |
--out PATH |
Write output to file (default: stdout) | |
--json |
-j |
JSON output instead of default YAML |
Examples:
ll-logs discover # List all projects with ll activity
ll-logs discover --json # Output paths as JSON array
ll-logs tail --loop my-loop # Stream live events from an active loop session
ll-logs extract --all # Extract all projects to logs/
ll-logs extract --project /path/to/proj # Extract one project to logs/<slug>/
ll-logs extract --all --cmd ll-history # Filter to ll-history invocations
ll-logs sequences --all # Find all tool-chain bigrams (default min-len=2)
ll-logs sequences --project /path -j # Output n-grams as JSON for one project
ll-logs sequences --all --top 10 # Top 10 most frequent chains
ll-logs sequences --all --min-len 3 --min-count 3 # Trigrams appearing ≥3 times
ll-logs stats --all # Skill frequency/correction table across all projects
ll-logs stats --project /path --json # JSON stats for one project
ll-logs stats --all --sort corrections # Sort by correction count (highest first)
ll-logs stats --all --window-days 30 # Limit to last 30 days of data
ll-logs dead-skills --project /path/to/proj --json # List never/rarely-invoked skills as JSON
ll-logs dead-skills --project . --threshold 5 # Skills with <=5 invocations
ll-logs dead-skills --all --window-days 90 # Dead skills across all projects, last 90 days
ll-logs scan-failures --all # Report all failed ll-* calls across all projects
ll-logs scan-failures --project /path --json # JSON failure clusters for one project
ll-logs scan-failures --all --window-days 30 # Only failures from last 30 days
ll-logs scan-failures --all --capture # Create BUG issues for each failure cluster
ll-logs diff SESSION_A SESSION_B # Compare behavioral diff between two sessions
ll-logs diff SESSION_A SESSION_B --json # Diff output as JSON
ll-logs eval-export --project . # Export all fixtures from current project (YAML)
ll-logs eval-export --skill refine-issue --json # JSON fixtures for refine-issue only
ll-logs eval-export --issue ENH-1710 --limit 10 # Up to 10 fixtures touching ENH-1710
Companion loop — ll-logs-telemetry-digest (FEAT-1925)
A project-local FSM loop that orchestrates the full ll-logs analysis pipeline in a single unattended run:
1. Refreshes the log corpus (ll-logs extract)
2. Runs stats, sequences, scan-failures, and dead-skills subcommands
3. Triages findings into issue files
4. Writes a digest artifact to .loops/runs/ll-logs-telemetry-digest-<timestamp>/digest.md
Subcommands not yet available are skipped gracefully via capability detection — the loop gains depth as new subcommands land.
ll-session¶
Query the unified session store (SQLite + FTS5) — the per-project .ll/history.db populated by SQLiteTransport, AutoManager (live-writes issue lifecycle events during ll-auto runs), and ll-session backfill (for historical data captured before ENH-1691). Lets operators search and inspect session activity without re-parsing the scattered JSON/markdown sources the analyze-* skills read.
Global flags:
| Flag | Description |
|---|---|
--db PATH |
Path to the session database (default: .ll/history.db) |
Subcommands:
| Subcommand | Description |
|---|---|
search |
FTS5 full-text query with BM25-ranked results |
recent |
Most recent rows for an event kind; optionally filtered by issue |
skill-stats |
Per-skill invocation/completion/success-rate rollup from skill_events completion columns; --since DATE bounds the window (ENH-2460) |
backfill |
Seed the database from existing on-disk sources; --since DATE uses incremental JSONL-only mode (ENH-1830); --snapshots seeds the issue_snapshots table from .issues/ files (ENH-2151); --extract-decisions runs extract-from-completed after backfill (ENH-2152); --max-sessions N caps how many sessions are compacted in this run (newest first, useful for large DBs) (ENH-2252) |
export |
Dump selected history tables as JSONL to stdout or a file — for visualization, external tooling, or backup (ENH-2252) |
related |
Issue events for a given issue ID |
path |
Resolve the JSONL file path for a session ID |
grep |
Regex search over message_events with optional summary-node scope filtering; condensed nodes use recursive CTE for N-level DAG traversal (ENH-1955) |
expand |
Return all message_events covered by a given summary node ID; condensed nodes use recursive CTE for N-level DAG traversal (ENH-1955) |
describe |
Show metadata (level, block span, parent) for a summary node |
rebuild |
Re-derive the JSONL-cache tables (tool_events, message_events, …) from raw_events; idempotent (ENH-2581) |
compact |
Sweep raw_events past the retention max-age into per-session retention summary nodes; --and-prune also deletes and VACUUMs (ENH-2581) |
recompress |
Rewrite legacy uncompressed raw_events payloads (raw_line/parsed_json) as zlib BLOBs and VACUUM; idempotent, off-hot-path maintenance (ENH-2624) |
prune |
Delete raw event rows older than configured analytics.retention max-age and VACUUM the DB |
grep flags:
| Flag | Description |
|---|---|
PATTERN |
Regex pattern (required, positional; case-insensitive) |
--summary-id ID |
Restrict search to messages covered by this summary node ID |
--limit N |
Maximum results (default: 50) |
--json |
Output results as a JSON array |
expand flags:
| Flag | Description |
|---|---|
SUMMARY_ID |
Summary node ID to expand (required, positional) |
--json |
Output message events as a JSON array |
describe flags:
| Flag | Description |
|---|---|
NODE_ID |
Summary node ID to describe (required, positional) |
--json |
Output metadata as a JSON object |
search flags:
| Flag | Description |
|---|---|
--fts QUERY |
FTS5 match query (required) |
--kind {tool,file,issue,loop,correction,message,skill,cli,commit,test_run} |
Filter results by event kind (optional) |
--limit N |
Maximum results (default: 20) |
--json / -j |
Output results as a JSON array |
recent flags:
| Flag | Description |
|---|---|
--kind {tool,file,issue,loop,correction,message,skill,cli,snapshot,commit,test_run} |
Event kind to list (required unless --issue is given). skill rows include exit_code/success/duration_ms when a completion-side host recorded them (ENH-2460). snapshot and the full choice list are now sourced from VALID_KINDS, the single source of truth (ENH-2581) |
--issue ID |
Filter to sessions that co-occurred with this issue (e.g. ENH-1710). Without --kind, lists sessions directly from the issue_sessions view. Issues processed after ENH-1839 populate captured_at immediately; a prior backfill pass is only needed for older issues. |
--limit N |
Maximum rows (default: 20) |
--json |
Output as a JSON array |
backfill flags:
backfill ingests session JSONL lines into raw_events only (ENH-2581) —
issue/loop-state/commit data is still written directly. The JSONL-derived
cache tables (tool_events, message_events, assistant_messages,
skill_events, sessions) are populated by a separate rebuild (or
backfill --rebuild in the same call).
| Flag | Description |
|---|---|
--since DATE |
Incremental mode: only process JSONL files modified on or after DATE (ENH-1830) |
--host HOST |
Filter to a single host source: claude-code, codex, opencode, or pi |
--rebuild |
Also materialize the JSONL-derived cache tables from raw_events in this call (ENH-2581) |
--snapshots |
Also seed the issue_snapshots table from .issues/ files (ENH-2151) |
--extract-decisions |
Run extract-from-completed on issue history after backfill (ENH-2152) |
--max-sessions N |
Cap the number of sessions compacted in this run (newest first); useful for large DBs that would otherwise time out (ENH-2252) |
rebuild flags:
| Flag | Description |
|---|---|
--config PATH |
Path to ll-config.json (default: auto-resolve from cwd) |
--json |
Output row counts as JSON |
Wipes and re-derives tool_events, message_events, assistant_messages,
skill_events, sessions, user_corrections, summary_nodes/
summary_spans, and their search_index rows from raw_events. Idempotent.
Issue/loop/commit/cli/file/test_run tables are outside raw_events's scope
and are untouched (ENH-2581).
compact flags:
| Flag | Description |
|---|---|
--and-prune |
Also delete the newly-compacted raw_events rows and VACUUM afterward |
--config PATH |
Path to ll-config.json (default: auto-resolve from cwd) |
--json |
Output result summary as JSON |
Sweeps raw_events rows past analytics.retention.raw_event_max_age_days
into per-session kind='retention' summary_nodes rows (a deterministic
one-liner, not an LLM summary) and marks them compacted=1 so prune can
delete them safely later (ENH-2581).
recompress flags:
| Flag | Description |
|---|---|
--batch N |
Rows to rewrite per transaction (default: 2000) |
--json |
Output result summary as JSON |
New raw_events rows written by backfill already store raw_line/parsed_json
as zlib-compressed BLOBs (~2.9× smaller per row). recompress is a one-time
maintenance sweep that converts pre-existing uncompressed TEXT rows (written
before ENH-2624) to the compressed form and VACUUMs afterward. The read path
(rebuild) transparently decompresses either representation, so the command is
idempotent and byte-lossless — running it twice is a no-op on the second pass.
export flags:
| Flag | Description |
|---|---|
--tables TYPE [TYPE…] |
Tables to include (default: all non-message tables). Choices: session, issue_event, issue_snapshot, skill_event, loop_event, correction, summary_node, message_event, commit_event, test_run_event |
--since DATE |
Only rows at or after this ISO 8601 date/datetime |
--include-messages |
Also include message_events (potentially large); ignored when --tables is given explicitly |
-o / --output FILE |
Write output to FILE instead of stdout |
Examples:
ll-session search --fts "rate limit" # Full-text search, BM25-ranked
ll-session recent --kind loop # Recent loop events
ll-session recent --kind commit # Recent git commits (ENH-2458)
ll-session recent --kind test_run # Recent pytest runs (ENH-2459)
ll-session skill-stats --since 2026-06-01 # Per-skill success rates (ENH-2460)
ll-session recent --issue ENH-1710 # Sessions that touched ENH-1710
ll-session recent --kind message --issue ENH-1710 # Messages from those sessions
ll-session backfill # Ingest on-disk sources (raw_events + issues/loops/commits)
ll-session backfill --rebuild # Ingest, then materialize cache tables in one call
ll-session backfill --since 2026-01-01 # Incremental JSONL backfill since date
ll-session backfill --max-sessions 50 # Compact at most 50 sessions this run
ll-session rebuild # Re-derive cache tables from raw_events (ENH-2581)
ll-session compact --and-prune # Sweep+summarize old raw_events, then delete (ENH-2581)
ll-session path <session_id> # Resolve JSONL file path for a session ID
ll-session grep "error" # Regex search over messages
ll-session grep "traceback" --summary-id 5 # Search within a summary node's span
ll-session expand 5 # List messages covered by summary node 5
ll-session describe 5 # Show metadata for summary node 5
ll-session export # Dump all non-message tables to stdout as JSONL
ll-session export --tables issue_event loop_event -o history.jsonl # Selective export to file
ll-session export --since 2026-01-01 --include-messages # Full dump since date
ll-session prune --dry-run # Preview what would be pruned without deleting
ll-session prune # Delete old raw events and VACUUM
ll-session prune --json # Prune result as JSON
ll-session recompress # Compress legacy raw_events payloads and VACUUM (ENH-2624)
ll-session recompress --batch 5000 # Rewrite 5000 rows per transaction
prune flags:
| Flag | Description |
|---|---|
--dry-run |
Report rows that would be deleted without actually deleting them |
--json |
Output result summary as JSON |
Pruning is dual-gated by analytics.retention config: both min_project_age_days and min_db_size_mb must be exceeded before any rows are deleted (defaults: 365 days, 800 MB). Only raw_events rows already marked compacted=1 (by compact) past raw_event_max_age_days are deleted (ENH-2581) — issue/loop/commit/cli/file/test_run tables and uncompacted raw_events rows are never pruned. See analytics.retention in CONFIGURATION.md.
ll-history-context¶
Query .ll/history.db for user corrections and FTS5 matches related to an issue ID and print a ready-to-inject ## Historical Context markdown block. Returns empty output (exit 0) when the DB is missing, has no matches, or all rows are stale (>30 days old).
Pass --project instead of an issue ID to print the project-wide context digest that session_start would inject (dry-run / config-tuning mode, ENH-1907).
Flags:
| Flag | Description |
|---|---|
ISSUE_ID |
Issue ID to query (optional, e.g. ENH-1708). Mutually exclusive with --project. |
--project |
Print the project-wide context digest (dry-run of session-start injection). |
--file PATH |
Also include recent file events for this path (issue-mode only) |
--db PATH |
Path to the session database (default: .ll/history.db) |
--effort |
Output a ## Effort Context block with per-issue session count and cycle time (ENH-1905) |
--for-skill NAME |
Exit 0 with no output if NAME is not in history.planning_skills (ENH-1909) |
When learning_tests.enabled is true and the queried issue has learning_tests_required declared, an additional ## Learning Test Evidence block is appended (ENH-2217). The block lists each declared target with its current registry status (proven / stale / refuted / missing), so planning skills that call ll-history-context automatically surface assumption coverage without an extra ll-learning-tests check call.
Output cap: At most 5 rows are rendered in issue mode. Project mode respects history.session_digest.char_cap (default 1200 chars).
Effort Context block: When --effort is passed, a ## Effort Context section is appended after the ## Historical Context block (or emitted alone when no corrections/FTS matches exist). It includes the session count and cycle time (first-to-last session span in days) for the queried issue, plus a velocity table of recently completed issues drawn from recent_issue_velocity(). Returns empty output when the DB is absent or the issue has no recorded sessions.
Examples:
ll-history-context ENH-1708 # Corrections matching the issue ID
ll-history-context ENH-1708 --file src/foo.py # Also include recent file events
ll-history-context ENH-9999 # Returns empty output when no matches
ll-history-context --project # Print project-wide digest (dry-run)
ll-history-context --project --db .ll/history.db # Use a specific DB path
ll-gitignore¶
Suggest and apply .gitignore patterns based on untracked files.
Flags:
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview suggestions without modifying .gitignore |
--json |
-j |
Output as JSON (serializes GitignoreSuggestion fields) |
--quiet |
-q |
Suppress non-essential output |
--config |
Path to project root (default: current directory) |
Examples:
ll-gitignore # Show suggestions and apply approved patterns
ll-gitignore --json # Output suggestions as JSON
ll-gitignore --dry-run # Preview suggestions without modifying .gitignore
ll-gitignore --quiet # Suppress non-essential output
ll-migrate¶
One-time migration script that moves all issues from completed/ and deferred/ directories into their type-based directories, backfills completed_at: for older completed files, and sets correct status: frontmatter. Part of the ENH-1390 status-decoupling migration.
Flags:
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview all planned moves without modifying files |
--config |
-C |
Path to project root (default: current directory) |
Examples:
ll-migrate --dry-run # Preview all planned moves (strongly advised before running)
ll-migrate # Execute migration
ll-migrate --config /path/to/project # Run for a specific project
ll-migrate-relationships¶
One-time migration script that renames deprecated relationship frontmatter keys in all .md files under .issues/: parent_issue: → parent: and related: → relates_to:. Part of the ENH-1434 relationship field standardization.
Flags:
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview all planned renames without modifying files |
--config |
-C |
Path to project root (default: current directory) |
Examples:
ll-migrate-relationships --dry-run # Preview all planned renames
ll-migrate-relationships # Execute migration
ll-migrate-relationships --config /path/to/project # Run for a specific project
ll-migrate-labels¶
One-time migration script that reads the freeform ## Labels body section from all .md files under .issues/ and writes the labels as a labels: YAML list in frontmatter. Part of the ENH-1392 labels field addition.
Flags:
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview all planned migrations without modifying files |
--config |
-C |
Path to project root (default: current directory) |
Examples:
ll-migrate-labels --dry-run # Preview all planned migrations
ll-migrate-labels # Execute migration
ll-migrate-labels --config /path/to/project # Run for a specific project
ll-migrate-status¶
One-time migration script that reads the status: frontmatter field from all .md files under .issues/ and rewrites any non-canonical synonyms (e.g. completed, wip) to their canonical equivalents. Uses the authoritative STATUS_SYNONYMS map from frontmatter.py. Part of the ENH-1551 cleanup pass.
Flags:
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview all planned normalizations without modifying files |
--config |
-C |
Path to project root (default: current directory) |
Examples:
ll-migrate-status --dry-run # Preview all planned normalizations
ll-migrate-status # Execute migration
ll-migrate-status --config /path/to/project # Run for a specific project
ll-verify-docs¶
Verify that documented counts (commands, agents, skills, loops) match actual file counts.
Flags:
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output as JSON |
--format |
-f |
Output format: text (default), json, markdown |
--fix |
Auto-fix count mismatches in documentation files | |
--directory |
-C |
Base directory (default: current directory) |
Exit codes: 0 = all counts match, 1 = mismatches found, 2 = error
Examples:
ll-verify-docs # Check and show results
ll-verify-docs --json # Output as JSON
ll-verify-docs --format markdown # Markdown report
ll-verify-docs --fix # Auto-fix mismatches
ll-verify-skill-budget¶
Check that the total skill description token footprint stays within the Claude Code listing budget.
Scans all skills/*/SKILL.md frontmatter description fields. Skips skills with disable-model-invocation: true. Token estimate: len(description) // 4. Exits 1 if total exceeds the threshold.
Flags:
| Flag | Short | Description |
|---|---|---|
--threshold |
Token budget threshold (default: 2000; overrides ll-config.json) | |
--json |
-j |
Output as JSON |
--directory |
-C |
Base directory (default: current directory) |
Exit codes: 0 = under budget, 1 = over budget
Examples:
ll-verify-skill-budget # Check against default 2000-token budget
ll-verify-skill-budget --json # Output as JSON
ll-verify-skill-budget --threshold 1500 # Custom threshold
ll-verify-skills¶
Check that no SKILL.md file exceeds the 500-line limit.
Scans all skills/*/SKILL.md files. Skips skills with disable-model-invocation: true. Exits 1 if any file exceeds the limit.
Flags:
| Flag | Short | Description |
|---|---|---|
--limit |
Maximum lines per SKILL.md (default: 500) | |
--json |
-j |
Output as JSON |
--directory |
-C |
Base directory (default: current directory) |
Exit codes: 0 = all within limit, 1 = violations found
Examples:
ll-verify-skills # Check against default 500-line limit
ll-verify-skills --limit 400 # Custom limit
ll-verify-skills --json # Output as JSON
ll-verify-triggers¶
Validate skill description trigger accuracy against should-fire and should-NOT-fire phrasings. Reports per-skill precision/recall and a cross-skill collision matrix.
Flags:
| Flag | Short | Description |
|---|---|---|
--json |
Output as JSON | |
--directory |
-C |
Base directory (default: current directory) |
--precision-threshold |
Minimum precision required (default: 0.5) | |
--recall-threshold |
Minimum recall required (default: 0.5) |
Exit codes: 0 = all skills meet thresholds, no collisions; 1 = threshold miss or collision detected.
Examples:
ll-verify-triggers # Validate all skills against default thresholds
ll-verify-triggers --json # Machine-readable JSON output
ll-verify-triggers --precision-threshold 0.8 --recall-threshold 0.6
ll-verify-package-data¶
Lint the little_loops package source for __file__-escape patterns that break non-editable installs, and verify every declared asset is accessible via importlib.resources in the current installation. Both gates must pass for exit 0.
Two checks run by default:
__file__-escape lint — regex-scans every.pyfile underlittle_loops/forPath(__file__).parents[N]or.parent.parent...chains whose traversal depth exits the package directory. Reports violations with file and line number.- Manifest completeness check — verifies every asset in
PACKAGE_DATA_ASSETS(package_data.py) is reachable viaimportlib.resources. Catches assets missing from the wheel (e.g., omitted fromMANIFEST.inorpyproject.toml).
Flags:
| Flag | Short | Description |
|---|---|---|
--json |
Output as JSON | |
--directory |
-C |
Project root containing the little_loops package (default: cwd) |
--lint-only |
Run only the __file__-escape lint (skip manifest check) |
|
--manifest-only |
Run only the manifest completeness check (skip lint) |
Exit codes: 0 = no escape violations and all assets accessible; 1 = one or more violations or missing assets.
Examples:
ll-verify-package-data # Run both checks from cwd
ll-verify-package-data --json # Machine-readable JSON output
ll-verify-package-data --lint-only # Lint only (no manifest check)
ll-verify-package-data --manifest-only # Manifest check only
ll-verify-package-data -C /path/to/root # Run from a specific project root
ll-verify-design-tokens¶
Structural lint for half-flipped design-token theme profiles. A profile's themes/dark.json (or any theme) that inverts the foreground/background pair — overriding both surface and text to move onto a near-black surface — but leaves border/action falling through to the light-tuned semantic.json defaults produces harsh gridlines, muddy accents, and a danger == action.primary collision. This lint catches that class at authoring time.
For every profile under the profiles directory, each theme that performs a full inversion (overrides both surface and text) must override every semantic color group semantic.json defines (border, action). A theme that does not invert (e.g. a light.json restating only surface) is exempt.
Flags:
| Flag | Short | Description |
|---|---|---|
--json |
Output as JSON | |
--directory |
-C |
Project root to discover the profiles directory under (default: cwd) |
--profiles-dir |
Explicit path to a design-token profiles/ directory (overrides -C discovery) |
Exit codes: 0 = every inverting theme overrides all semantic color groups; 1 = one or more half-flipped themes (or no profiles directory found).
Note: Run against the bundled little-loops templates, this currently flags
editorial-mono, a known-incomplete profile pending a follow-on. Point--profiles-dirat a complete profile set, or completeeditorial-mono, to gate CI on exit 0.
Examples:
ll-verify-design-tokens # Auto-discover profiles dir from cwd
ll-verify-design-tokens --json # Machine-readable JSON output
ll-verify-design-tokens --profiles-dir DIR # Lint a specific profiles directory
ll-verify-design-tokens -C /path/to/root # Discover under a specific project root
ll-verify-decisions¶
Validate the decisions log by loading .ll/decisions.yaml through load_decisions() and re-globbing the derived .ll/decisions.d/*.json fragment directory in a strict second pass (bypassing the read path's silent skip of malformed fragments), asserting no YAML/JSON syntax errors, missing required fields, or unknown entry-type discriminators in either tier. Gates the three transport-layer corruption checks (ENH-2589): the pre-commit hook (ENH-2590), the pytest CI gate (ENH-2591), and the Claude Code PreToolUse hook (ENH-2592) all delegate to this binary and rely on its exit-code contract.
The validator catches three corruption classes:
- YAML syntax corruption (e.g. an unescaped
""inside a double-quotedrationale:scalar →yaml.YAMLError). - Schema drift — entries missing required fields (
id,result/measured_atfor outcomes, etc.) →KeyError. - Unknown
typediscriminator →ValueError("Unknown entry type").
Flags:
| Flag | Description |
|---|---|
--config-root |
Project root whose decisions log (.ll/decisions.yaml + .ll/decisions.d/) to validate (default: cwd). Equivalent to BRConfig.project_root. |
Exit codes: 0 = loadable via load_decisions() and schema-clean; 1 = any caught yaml.YAMLError/KeyError/ValueError, with a single-line ERROR: <path>: <ExcType>: <msg> on stderr.
Examples:
ll-verify-decisions # Validate .ll/decisions.yaml + .ll/decisions.d/ from cwd
ll-verify-decisions --config-root /repo # Validate under a specific project root
See CONTRIBUTING.md § Decisions YAML Validation for the pre-commit wiring and docs/guides/DECISIONS_LOG_GUIDE.md § Validation for the full three-layer defense model.
ll-verify-kinds¶
Assert every CREATE TABLE in session_store._MIGRATIONS is either registered in _KIND_TABLE (so recent()/search --kind can query it) or explicitly listed in _KINDLESS_TABLES (support tables with no "recent by kind" concept — meta, search_index, sessions, assistant_messages, summary_nodes, summary_spans, raw_events, correction_retirements). Catches the case a new *_events table is added without registering its kind — the gap this issue fixed for snapshot (ENH-2581).
Exit codes: 0 = every table is registered or explicitly kindless; 1 = one or more tables are neither, listed on stderr.
Examples:
ll-verify-des-audit¶
Walk the source tree and verify every event-emit site maps to a registered DES variant — the F5 adoption gate (ENH-2475). The audit reads every emit-call string literal in scripts/little_loops/, then checks each against the canonical DES_VARIANTS registry (defined in little_loops.observability.schema). Exit 0 means every currently-emitted event type has a registered variant; exit 1 means a new event was emitted without being registered — block F5's gen_ai.usage.* adoption until the variant is added.
Flags:
| Flag | Short | Description |
|---|---|---|
--json |
Output as JSON | |
--directory |
-C |
Project root to discover the source directory under (default: cwd) |
--source-dir |
Explicit path to a little_loops source/ directory (overrides -C discovery) |
Exit codes: 0 = every emit site maps to a registered DES variant; 1 = one or more uncovered event types (or source dir not found).
Examples:
ll-verify-des-audit # Auto-discover source dir from cwd
ll-verify-des-audit --json # Machine-readable JSON output
ll-verify-des-audit --source-dir DIR # Walk a specific source directory
ll-verify-des-audit -C /path/to/root # Discover under a specific project root
ll-check-links¶
Check markdown documentation for broken links.
Flags:
| Flag | Short | Description |
|---|---|---|
--json |
-j |
Output as JSON |
--format |
-f |
Output format: text (default), json, markdown |
--directory |
-C |
Base directory (default: current directory) |
--ignore |
Ignore URL patterns — repeatable | |
--timeout |
HTTP request timeout in seconds (default: 10) | |
--workers |
-w |
Maximum concurrent HTTP requests (default: 10) |
--verbose |
-v |
Show verbose output |
Exit codes: 0 = all links valid, 1 = broken links found, 2 = error
Examples:
ll-check-links # Check all markdown files
ll-check-links --json # Output as JSON
ll-check-links --format markdown # Markdown report
ll-check-links -C docs/ # Check specific directory
ll-check-links --ignore 'http://localhost.*' # Ignore pattern
ll-check-links --timeout 30 --workers 5 # Custom timeout and concurrency
ll-create-extension¶
Scaffold a new little-loops extension project directory. Generates a ready-to-install Python package with an LLExtension implementation, a pyproject.toml registered under the little_loops.extensions entry point, and a starter test using LLTestBus.
Arguments:
| Argument | Description |
|---|---|
name |
Extension name in kebab-case (e.g. my-dashboard-ext) |
The name is automatically converted: hyphens become underscores for the package directory (my_dashboard_ext) and each word is capitalized for the class name (MyDashboardExt).
Flags:
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview files that would be created without writing them |
Generated layout:
<name>/
├── pyproject.toml # Package metadata + little_loops.extensions entry point
├── <pkg_name>/
│ ├── __init__.py
│ └── extension.py # LLExtension implementation stub
└── tests/
└── test_extension.py # Starter test using LLTestBus
Generated file contents:
pyproject.toml — wires automatic extension discovery via the little_loops.extensions entry point group:
[project.entry-points."little_loops.extensions"]
my-dashboard-ext = "my_dashboard_ext.extension:MyDashboardExt"
<pkg_name>/extension.py — skeleton implementing the LLExtension protocol:
class MyDashboardExt:
"""MyDashboardExt extension.
Implement on_event to handle little-loops lifecycle events.
Optional mixin Protocols (InterceptorExtension, ActionProviderExtension,
EvaluatorProviderExtension, LLHookIntentExtension) are opt-in — implement
their methods to activate.
"""
def on_event(self, event: LLEvent) -> None:
"""Handle an incoming event."""
# See docs/reference/EVENT-SCHEMA.md for all available event types and payload fields
pass
tests/test_extension.py — starter test using LLTestBus:
class TestMyDashboardExt:
def test_receives_events(self) -> None:
"""Extension receives events via LLTestBus replay."""
bus = LLTestBus([])
ext = MyDashboardExt()
bus.register(ext)
bus.replay()
assert bus.delivered_events == []
Dry-run output:
[DRY RUN] Would create: my-dashboard-ext/
pyproject.toml
my_dashboard_ext/__init__.py
my_dashboard_ext/extension.py
tests/test_extension.py
Exit codes: 0 = scaffold created successfully, 1 = directory already exists or error
Examples:
ll-create-extension my-dashboard-ext # Scaffold extension
ll-create-extension my-dashboard-ext --dry-run # Preview without writing files
After scaffolding:
cd my-dashboard-ext
pip install -e . # Install with entry point registration
python -m pytest tests/ # Run starter tests
See also: Write a little-loops hook — full authoring walkthrough for the
LLHookIntentExtensionProtocol, including the adapter flow and pure-function + subprocess testing patterns.
ll-artifact¶
Generate self-contained, human-facing HTML artifacts from project data. All project-derived inputs are stamped into the page at generation time, so the output works over file:// with no runtime fetch.
Subcommands:
| Subcommand | Description |
|---|---|
policy-builder |
Emit a visual builder for policy-router / rubric FSM loop YAML |
Exit codes: 0 = artifact generated successfully, 1 = error
ll-artifact policy-builder¶
Emit policy-router-builder.html — a single self-contained page for visually authoring Decision Table and Rubric loop YAML. The page inlines three project-derived blobs: design-token CSS variables (light + dark, from load_design_tokens / render_as_css_vars_themed), the canonical predicate grammar (policy_rules.grammar_spec()), and the skill/command catalog (from skills/*/SKILL.md + commands/*.md). It renders a live YAML preview, shadow / zero-condition / unknown-action validation hints, Copy/Download, and a light/dark theme toggle.
Flags:
| Flag | Short | Description |
|---|---|---|
--output |
-o |
Output directory (default: config.artifacts.default_output_dir, normally .) |
Examples:
ll-artifact policy-builder # Write policy-router-builder.html to the default output dir
ll-artifact policy-builder -o build/ # Write to a custom directory
Note: Generated YAML can be validated with
ll-loop validate <name>after downloading. Decision Table output importslib/rubric-router.yamlthenlib/policy-router.yaml; Rubric output imports onlylib/rubric-router.yaml.
ll-generate-schemas¶
Internal: Maintainer/developer tool. End users do not need to run this directly.
Generate JSON Schema (draft-07) files for all 38 LLEvent types and write them to docs/reference/schemas/.
Flags:
| Flag | Short | Description |
|---|---|---|
--output |
-o |
Output directory (default: docs/reference/schemas/ relative to cwd) |
Exit codes: 0 = schemas generated successfully, 1 = error
Examples:
ll-generate-schemas # Write to docs/reference/schemas/
ll-generate-schemas -o path/to/schemas/ # Custom output directory
Note: Run this after modifying
SCHEMA_DEFINITIONSinscripts/little_loops/generate_schemas.pyor adding a newLLEventtype. See CONTRIBUTING.md for the full schema maintenance workflow.
ll-generate-skill-descriptions¶
Release utility: Run before tagging a release to batch-refresh skill descriptions.
Auto-generate concise (≤100 character) descriptions for LLM-discoverable skills using the Claude CLI. For each skills/*/SKILL.md that does not have disable-model-invocation: true, it extracts trigger keywords and a body excerpt, prompts Claude to produce a single-line description, and optionally writes it back to the frontmatter.
Dry-run by default (previews proposed descriptions without modifying files).
Flags:
| Flag | Description |
|---|---|
--apply |
Write generated descriptions back to SKILL.md frontmatter |
--quiet |
Suppress per-skill output; only print final summary |
Exit codes: 0 = success (no errors), 1 = one or more skills failed or skills directory not found
Examples:
ll-generate-skill-descriptions # Dry-run: preview proposed descriptions
ll-generate-skill-descriptions --apply # Write descriptions back to SKILL.md files
ll-generate-skill-descriptions --quiet # Suppress per-skill output
See also: CONTRIBUTING.md New Skill Checklist for the classification policy and when to run this tool.
ll-adapt¶
Unified host-parameterized adapter. Dispatches to a host-specific emitter via --host <host> and generates all skill, command, and agent artefacts for that host in one pass.
Flags:
| Flag | Description |
|---|---|
--host HOST |
Target host (e.g. codex, omp) — required |
--apply |
Write changes (default: dry-run) |
--dry-run |
Explicit dry-run alias |
--only NAME |
Restrict agent processing to a single agent stem |
--quiet |
Suppress per-entry output; only print final summary |
Exit codes: 0 = success (no errors), 1 = unknown host or one or more entries failed
Examples:
ll-adapt --host codex # Dry-run: preview all Codex artefacts
ll-adapt --host codex --apply # Write Codex artefacts
ll-adapt --host codex --only codebase-analyzer --apply # Single agent
ll-adapt-skills-for-codex¶
Deprecated alias — use
ll-adapt --host codexinstead. This entry point remains available as a convenience alias but is no longer the documented path.
Adapt ll's skills/*/SKILL.md files for the Codex Skills API and bridge every commands/*.md slash command into a Codex-discoverable skills/ll-<name>/ entry.
Skills adaptation (in-place). For each skills/<name>/SKILL.md, inserts name: (the directory slug) and metadata.short-description: (first line of the existing description: field, ≤80 chars) into the SKILL.md frontmatter, and creates agents/openai.yaml with display_name and short_description under an interface: block. Uses targeted string manipulation — no YAML roundtrip — to preserve existing frontmatter formatting.
Commands bridge (synthesized). For each commands/<name>.md, synthesizes a wrapper skills/ll-<name>/SKILL.md (with name: ll-<name>, the source command's description: copied verbatim, and a derived metadata.short-description:) plus a matching agents/openai.yaml. The ll- namespace prefix prevents collisions with skills sharing a base name (e.g. commit). Commands whose frontmatter declares disable-model-invocation: true are skipped, mirroring the skills-adapter contract. Multi-line descriptions are emitted as YAML block scalars so the synthesized frontmatter parses cleanly. Bridged ll-<name>/ entries are committed in-repo and discovered by Codex via the same Skills API path as adapted real skills.
Dry-run by default (previews proposed changes without modifying files).
Flags:
| Flag | Description |
|---|---|
--apply |
Write skill frontmatter updates and create bridged skills/ll-<name>/ directories on disk |
--quiet |
Suppress per-entry output; only print final summary |
Exit codes: 0 = success (no errors), 1 = one or more entries failed or skills/ directory not found
Examples:
ll-adapt-skills-for-codex # Dry-run: preview proposed skill + command changes
ll-adapt-skills-for-codex --apply # Write frontmatter, bridge commands → skills/ll-<name>/
ll-adapt-skills-for-codex --quiet # Suppress per-entry output
ll-adapt-agents-for-codex¶
Deprecated alias — use
ll-adapt --host codexinstead. This entry point remains available as a convenience alias but is no longer the documented path.
Generate .codex/agents/*.toml files from agents/*.md so Codex CLI can select ll subagents via --agent <name>.
For each agents/<name>.md, reads the agent's name and description from its frontmatter (falling back to the H1 heading), then writes a TOML file to .codex/agents/<name>.toml with name, description, model, and developer_instructions fields. Uses an idempotent marker comment (# generated by ll-adapt) to detect and skip previously generated files unless --force is passed. User-edited TOML files (files lacking the marker) are never overwritten.
Dry-run by default (previews proposed changes without writing files).
Flags:
| Flag | Description |
|---|---|
--apply |
Write .codex/agents/*.toml files to disk |
--force |
Overwrite previously generated files even if already up-to-date |
--quiet |
Suppress per-entry output; only print final summary |
Exit codes: 0 = success (no errors), 1 = one or more entries failed or agents/ directory not found
Examples:
ll-adapt-agents-for-codex # Dry-run: preview proposed agent TOML changes
ll-adapt-agents-for-codex --apply # Write .codex/agents/*.toml files
ll-adapt-agents-for-codex --force --apply # Regenerate all files (including up-to-date)
mcp-call¶
Thin CLI wrapper for direct MCP tool invocation via JSON-RPC. Reads .mcp.json from the current directory, spawns the MCP server subprocess, performs the JSON-RPC initialize handshake, calls tools/call, and writes the MCP response envelope to stdout.
Arguments:
| Argument | Description |
|---|---|
server/tool-name |
MCP server name and tool name joined by / (e.g., pencil/batch_get) |
params_json |
Tool parameters as a JSON object string |
--timeout SECONDS |
Request timeout in seconds (default: 30). Exit code 124 on timeout. |
Exit codes: 0 = success, 1 = tool error, 2 = usage/config error, 124 = timeout, 127 = server or tool not found in .mcp.json
Examples:
mcp-call pencil/batch_get '{"patterns": ["**/*.pen"]}'
mcp-call my-server/my-tool '{"key": "value"}'
mcp-call pencil/batch_design '{"nodes": [...]}' --timeout 120
ll-learning-tests¶
Query and manage the learning test registry. Skills and loops call this via Bash to check coverage before proceeding.
Subcommands:
| Subcommand | Description |
|---|---|
check <target> [--stale-aware] |
Print record JSON; exit 1 if not found or (with --stale-aware) if the record is stale |
list |
Print all records as a JSON array |
mark-stale <target> |
Set status=stale; exit 1 if not found |
orphans [--mark-stale] |
List records whose target package is not imported by any project file; optionally mark them all stale |
prove <target> |
Trigger proving via ready-to-implement-gate (retry-then-/ll:explore-api); print the refreshed record; exit 0 if proven, 1 otherwise (ENH-2430) |
Examples:
ll-learning-tests check "Anthropic SDK streaming"
ll-learning-tests check "Anthropic SDK streaming" --stale-aware # exit 1 if stale
ll-learning-tests list
ll-learning-tests list | jq -r '.[] | "\(.status)\t\(.target)"'
ll-learning-tests mark-stale "Anthropic SDK streaming"
ll-learning-tests orphans # list orphaned records
ll-learning-tests orphans --mark-stale # atomically mark all orphans stale
ll-learning-tests prove "Anthropic SDK streaming" # trigger proving directly, no issue file required
ll-learning-tests --help
Exit codes: 0 = success, 1 = target not found (or stale with --stale-aware)
See Also¶
- COMMANDS.md —
/ll:slash commands reference - ARCHITECTURE.md — System design
- LOOPS_GUIDE.md — FSM loop configuration guide
- API.md — Python module API reference
- write-a-hook.md — hook authoring guide for
LLHookIntentExtension