Getting Started with little-loops¶
What Is little-loops?¶
little-loops turns Claude Code into a structured development workflow engine. The core idea: instead of one-shot prompts, you write issues — Markdown files that travel with your code and serve as rich context for AI-driven implementation. A well-formed issue tells the agent why something needs to change, where in the codebase to look, and how to verify it worked. The agent can then plan, implement, test, and archive the change with minimal back-and-forth from you.
The system has three layers you can use independently or together:
- Issues — Markdown files in
.issues/that capture bugs, features, and enhancements. The atomic unit of work. You can use this layer alone indefinitely. - Sprints — Named batch runs with dependency-aware execution ordering. Useful when you have four or more issues, or issues that must run in sequence.
- Loops — YAML-defined finite-state machine (FSM) automations that run recurring workflows (quality gates, scheduled scans) without repeated prompting.
The core flow in one line: observe → capture → refine → implement → complete.
observe ──→ /ll:capture-issue ──→ /ll:format-issue ──→ /ll:refine-issue ──→ /ll:ready-issue ──→ /ll:manage-issue ──→ /ll:commit
(spot it) (record it) (fix template) (codebase research) (validate it) (implement it) (ship it)
Installation¶
Step 1: Install the Python CLI Tools¶
The CLI tools (ll-init, ll-auto, ll-sprint, ll-loop, etc.) run from your terminal and drive automated execution.
Then run ll-init once per project — see Set Up Your Project below.
Step 2: Install the Plugin¶
The slash commands (/ll:*) run inside Claude Code sessions. Install the plugin from within Claude Code:
# Add the GitHub repository as a marketplace source
/plugin marketplace add BrennonTWilliams/little-loops
# Install the plugin
/plugin install ll@little-loops
For local development, use a local path instead:
Step 3: Verify¶
# Terminal: confirm CLI tools are installed
ll-auto --help
# Claude Code session: confirm plugin is loaded
/ll:help
Set Up Your Project¶
Run ll-init once per project. It auto-detects your project type and generates a starter configuration.
Detected project types: Python, JavaScript/TypeScript, Go, Rust, Java (Maven or Gradle), and .NET. For each type, it infers sensible defaults for test commands, lint commands, and source directories. Unrecognized projects fall back to a generic template.
What gets created:
What else happens: ll-init also appends little-loops state files to your .gitignore (.auto-manage-state.json, .parallel-manage-state.json, .ll/ll-context-state.json, .ll/ll-sync-state.json, .ll/ll-session-events.jsonl) so runtime state never ends up committed.
Flags¶
| Flag | What it does | When to use it |
|---|---|---|
| (none) | Launches an interactive TUI to configure options step by step | Default — works for most projects |
--yes |
Accepts all auto-detected defaults without any confirmation prompts | Fastest path when auto-detection gets it right |
--force |
Overwrites an existing .ll/ll-config.json (TUI now pre-populates from existing values automatically, so --force is rarely needed) |
Forcing a full template reset regardless of existing config |
--dry-run |
Previews what would be generated without writing any files | Checking what ll-init would produce before committing |
--plan |
Emits a JSON plan {detected, proposed_config, host_options, warnings} without writing anything |
CI pipelines, inspection before applying, or piping into ll-init apply --config |
--enable FEATURE |
Enable an optional feature in the headless config (repeatable). Valid (in argparse order): product, analytics, context_monitor, learning_tests, decisions, scratch_pad, session_capture, session_digest, prompt_optimization |
Activating optional features without the TUI |
--disable FEATURE |
Disable a feature (same valid names as --enable) |
Turning off a feature that was auto-enabled |
--upgrade |
Act on version drift automatically, then refresh every active host's integration surface: upgrade the pip package, force-regenerate adapter files (e.g. .codex/hooks.json), and scope-aware-update the claude-code plugin. Default headless mode is warn-only |
CI pipelines or automation where you want hands-free upgrades |
--root / -C |
Set the project root directory (default: current directory) | Running ll-init from a different working directory |
--hosts HOST… |
Wire adapters for additional host CLIs: claude-code, codex, opencode, pi |
Only needed if you use little-loops with multiple AI coding tools |
Key Config Fields¶
The three fields most relevant to beginners:
| Field | Purpose | Example |
|---|---|---|
project.test_cmd |
Command to run tests | pytest scripts/tests/ |
project.lint_cmd |
Command to run lint/format | ruff check scripts/ |
project.src_dir |
Primary source directory | scripts/ |
Start with the auto-detected defaults.
Existing Installation Detection¶
ll-init automatically detects whether little-loops is already installed before writing any config. The detection logic runs in both headless (--yes) and TUI modes:
| Detected state | What ll-init does |
|---|---|
| Not installed (no pip package, no global plugin) | Prints a notice; warns only by default — pass --upgrade to install automatically |
Global plugin (ll@little-loops via claude plugin list --json) |
Reads the plugin version; checks marketplace for drift |
Local dev install (editable pip install -e) |
Reads the installed version; checks PyPI for drift |
PyPI consumer install (pip install little-loops) |
Reads the installed version; checks PyPI for drift |
| Version mismatch (installed ≠ PyPI latest) | Prints a notice with the upgrade command; warns only by default — pass --upgrade to upgrade automatically |
| Stale adapter (generated gen-version ≠ installed package version) | Prints a hint for the affected host (e.g. codex); warns only by default — pass --upgrade to force-regenerate the adapter |
| Up to date | Proceeds silently |
When an existing .ll/ll-config.json is found, the TUI pre-populates every field from its current values so a re-run always starts from your actual config rather than defaults. Use --force to reset to template defaults instead of merging.
After Setup¶
Tune individual settings interactively with /ll:configure — it presents every config option with its current value and lets you edit in-place. For less common options, see the Configuration Reference.
Your First Workflow: Fix a Bug¶
The simplest complete workflow — from observation to committed fix.
Step 1: Capture¶
Describe the bug in plain language. The skill creates a properly formatted issue file.
/ll:capture-issue "login button doesn't respond on mobile Safari"
# → Creates .issues/bugs/P3-BUG-001-login-button-doesnt-respond-on-mobile-safari.md
The file gets a priority prefix (P3), type (BUG), globally unique ID (001), and a kebab-case description. Open it to review — capture fills in what it can from context and leaves placeholders for what it can't determine.
Step 2: Validate (Optional but Recommended)¶
Before implementing, run a quality check. This catches missing context, vague reproduction steps, or implementation gaps that would slow down the agent.
For a trivial bug, skip this step and go straight to implementation. For anything you'll hand off to automated tools, the quality check pays for itself.
Step 3: Implement¶
/ll:manage-issue handles the full implementation cycle: research, plan, implement, run tests, and mark the issue complete.
/ll:manage-issue bug fix BUG-001
# → Researches → plans → implements → runs tests → sets status: done in frontmatter
When it finishes, the issue file remains in .issues/bugs/ with status: done in its frontmatter (the YAML metadata block at the top of the file).
Useful flags: --plan-only (stop after planning, alias --dry-run), --resume (continue from a checkpoint), --gates (pause for manual verification at phase boundaries; disabled by default), --quick (skip deep research and the confidence gate), --force-implement (bypass the confidence gate).
Step 4: Commit¶
Review the diff, approve the commit message, and commit.
The commit message follows conventional commit format. You approve before anything is written to the repo.
Understanding Issue Files¶
A few things that trip up new users:
Filenames¶
P2-BUG-042-sprint-runner-ignores-failed-issues.md
│ │ │ └─ kebab-case description
│ │ └─── globally unique issue number
│ └─────── type: BUG, FEAT, ENH, or EPIC
└────────── priority: P0 (critical) to P5 (low)
IDs are globally unique across all types — you won't have both BUG-007 and FEAT-007.
Status and Priority¶
Priority levels run from P0 (critical, must fix immediately) to P5 (low, nice-to-have). The priority prefix in the filename determines ordering in automated runs — ll-auto and ll-sprint process lower numbers first. You can reassign priority at any time by renaming the file or running /ll:prioritize-issues.
The status field inside the issue file tracks where the issue is in the workflow: open, in_progress, blocked, deferred, done, or cancelled. Automated tools read and update this field; you rarely need to edit it directly. See ISSUE_MANAGEMENT_GUIDE.md for the full table and meanings.
Directory Structure¶
All issues live in type directories regardless of their lifecycle state. Status is tracked via the status frontmatter field.
.issues/
bugs/ ← BUG issues (open, in_progress, done, deferred, etc.)
features/ ← FEAT issues (any status)
enhancements/ ← ENH issues (any status)
epics/ ← EPIC coordination containers (any status)
A completed bug stays in .issues/bugs/ with status: done in its frontmatter — it is not moved.
Use Anchors, Not Line Numbers¶
Code references in issue files use function and class names, not line numbers.
# Correct
Root cause is in function `_run_wave()` in `scripts/little_loops/sprint.py`.
# Wrong — line numbers drift
Root cause is at line 1847 in sprint.py.
Minimal vs. Full Template¶
By default, /ll:capture-issue creates a full v2.0 issue with all sections. Pass --quick to create a minimal issue (Summary + Impact only) when you just want to record an idea quickly.
/ll:capture-issue "login button broken" # full template (default)
/ll:capture-issue "login button broken" --quick # minimal template variant (per creation_variants.minimal in your config)
/ll:format-issue BUG-001 # align issue with template v2.0 (sections, gaps, quality)
Discovering Issues You Didn't Know Existed¶
Three scanning commands find problems proactively. Use the table below to pick the right one:
| You want to find... | Use this command |
|---|---|
| Bugs, tech debt, and error handling gaps in existing code | /ll:scan-codebase |
| Structural problems (bad coupling, missing abstractions, inconsistencies) | /ll:audit-architecture |
| Feature gaps relative to what you said you wanted to build | /ll:scan-product |
| A single issue you spotted yourself | /ll:capture-issue "description" |
/ll:scan-codebase is the right default for most projects. /ll:audit-architecture is especially useful when you've just inherited an unfamiliar codebase and want to understand its systemic problems before diving in. /ll:scan-product reads a goals doc (.ll/ll-goals.md) when one exists; otherwise it discovers goals automatically from your README and roadmap docs.
After Scanning¶
A scan often produces more issues than you want to implement. Two commands to reduce the list:
/ll:prioritize-issues
# → Adds P0-P5 priority prefixes to filenames based on severity and impact
/ll:tradeoff-review-issues
# → Evaluates utility vs. complexity; recommends which to implement, update, or close
When to Escalate¶
| Situation | Tool |
|---|---|
| 1-3 issues, no dependencies | /ll:manage-issue directly |
| 4+ issues, or issues with blockers | /ll:create-sprint + ll-sprint run |
| Recurring quality check (lint, tests, scans) | ll-loop run <loop-name> |
/ll:manage-issue works well for a few issues. It's interactive and handles one issue at a time.
Sprints shine when issues have dependencies. The sprint system computes execution order automatically from blocked_by fields, runs independent issues in parallel, and can resume after interruption.
Loops are for automation you'd otherwise run by hand on a schedule — a nightly quality gate, a weekly scan, a fix-and-verify cycle. You define the workflow once as a YAML file; the FSM engine executes it without prompting.
Quick Reference¶
The ten commands you'll use most often:
| Command | What It Does |
|---|---|
ll-init |
Auto-detect project type and create config + issue directories |
/ll:capture-issue |
Create an issue file from a natural-language description |
/ll:ready-issue |
Validate an issue for implementation readiness |
/ll:manage-issue |
Plan, implement, test, and complete an issue end-to-end |
/ll:commit |
Review diff, propose commit message, and commit with approval |
/ll:scan-codebase |
Static analysis to discover bugs and tech debt |
/ll:prioritize-issues |
Assign P0-P5 priorities to issue files |
/ll:create-sprint |
Create a sprint from active issues for batch execution |
/ll:format-issue |
Validate and normalize issue file structure |
/ll:refine-issue |
Fill knowledge gaps with codebase research |
For the full list: /ll:help or see Command Reference.
What's Next?¶
Once you're comfortable with the basic workflow, each guide covers a deeper area:
| Guide | Go here when... |
|---|---|
| Issue Management Guide | You want the full refinement pipeline: normalize → prioritize → format → refine → verify |
| Sprint Guide | You have multiple issues with dependencies and want batch execution with waves |
| Loops Guide | You want to automate a recurring workflow (quality gate, fix cycle) as an FSM |
| Session Handoff Guide | Your sessions are hitting context limits and you need seamless continuation |
| History & Session Guide | You want to query past sessions, inject historical context into planning, or analyze project trends |
| Decisions Log Guide | You want to record architectural decisions, enforce team rules, or understand how decision_needed gates automation |
Troubleshooting¶
| Problem | Fix |
|---|---|
ll-init doesn't detect your project type (falls back to the generic template) |
Run ll-init with the TUI (no flags) and specify src_dir, test_cmd, and lint_cmd manually. |
/ll:manage-issue says "issue not found" |
Issue IDs are case-sensitive. Run ll-issues list to see exact IDs. Check that the issue has status: open (not done or cancelled). |
Issue doesn't appear in ll-issues list |
The file may have a malformed filename. Run /ll:normalize-issues to fix naming problems. |
| You assigned P1 but the issue isn't being processed first | ll-auto processes by filename priority prefix. Rename the file or run /ll:prioritize-issues to update the prefix. |
| Commands aren't showing up in Claude Code | Run /ll:help — if it returns nothing, the plugin may not be loaded. Re-run /plugin install ll@little-loops. |
For deeper diagnostics, see Troubleshooting.
See Also¶
- README — Installation, feature overview, and configuration summary
- Command Reference — Full slash command reference with arguments and examples
- Configuration Reference — All
ll-config.jsonoptions - Troubleshooting — Common issues and diagnostic commands
Contributing to little-loops? Use the editable dev install instead of the PyPI package: pip install -e "./scripts[dev]". See CONTRIBUTING.md for development setup and guidelines.