AI Agents in Soli Projects
soli new scaffolds a project that's ready for AI coding agents (Claude Code, Cursor, Aider, Copilot CLI, Codex CLI) from the first commit. This page describes what ships and how to use it.
What you get
Every fresh soli new myapp project includes:
| Path | Purpose |
|---|---|
| CLAUDE.md | Root agent guide — verification loop, built-in capability index (need → builtin → docs/ file), footgun cheatsheet, recipes |
| AGENTS.md | Tool-agnostic stub pointing other agents to CLAUDE.md |
| app/controllers/CLAUDE.md | Controller-specific rules: auto-loaded models, named route helpers, mass-assignment |
| app/models/CLAUDE.md | Model rules: don't override CRUD; safe where / @sdbql{} forms |
| app/views/CLAUDE.md | Escaping, locals, helpers, indent |
| app/middleware/CLAUDE.md | Shape and directive comments |
| tests/CLAUDE.md | BDD DSL, controller HTTP client, coverage gate |
| db/migrations/CLAUDE.md | Migration naming and up/down requirements |
| .claude/settings.json | Permissions allowlist for safe soli subcommands |
| .claude/commands/soli-verify.md | /soli-verify — lint + test + coverage |
| .claude/commands/soli-test.md | /soli-test [path] — one spec or full suite |
| .claude/commands/soli-resource.md | /soli-resource <name> — full RESTful resource |
The per-directory CLAUDE.md files are picked up automatically by Claude Code as the agent works in that directory; you don't need to import them. Other agents read the root CLAUDE.md (and AGENTS.md as a fallback).
The verification loop
Every agent working in a Soli project should run, before reporting a task complete:
$ soli lint <files-you-changed> $ soli test tests/<the-relevant-spec>.sl $ soli test --coverage --coverage-min 90 $ soli serve . --dev # if a UI/route changed, hit it in a browser
The /soli-verify slash command bundles soli lint + soli test --coverage --coverage-min 90. If any step fails, the rule is to fix the root cause — never weaken assertions, lower the coverage gate, or skip hooks.
Slash commands
| Command | What it does |
|---|---|
| /soli-verify | Full pre-merge check (lint + test with coverage gate) |
| /soli-test [path|all] | One spec for fast feedback, or the full suite with coverage |
| /soli-resource <singular> | Scaffolds model + migration + controller + views + route + spec |
/soli-resource post prefers soli generate scaffold post (model, controller, views, migration, routes, and a controller E2E spec under tests/controllers/), then soli db:migrate up. Piece-by-piece: hand-write the model, soli db:migrate generate create_posts, hand-write the controller, add resources("posts"), and stub views/specs.
Permissions
.claude/settings.json pre-allows the safe, read-only-or-sandboxed soli subcommands an agent uses constantly: soli lint, soli test, soli serve, soli generate, soli db:migrate, soli run. This removes the per-prompt approval tax without granting blanket access. Destructive things (git push, package mutations, anything outside the project) are deliberately left to require explicit approval.
Keeping docs up to date
Agent guides and the language reference under docs/ are embedded in the soli binary at compile time. After upgrading soli, refresh an existing project:
$ soli update docs # from the project root $ soli update docs ./myapp # or point at a project path
This rewrites root CLAUDE.md / AGENTS.md, every per-directory CLAUDE.md, .claude/settings.json + slash commands, and the whole docs/ language tree. Custom edits in those paths are replaced. Keep project-specific notes elsewhere (or re-apply them after the update). .claude/settings.local.json is never touched.
Typical flow: soli update (self-update the CLI) then soli update docs (refresh this project).
Migrating an older project
If the project was created before agent scaffolding existed, soli update docs is enough — it creates missing host directories and writes the full kit. Then run /soli-verify.
Customizing
The shipped files are starting points. Common additions that survive an update:
- Project-specific notes in a file you own (e.g.
docs/project.md) and a pointer you re-add after updates. - Stop hook in
.claude/settings.local.json(not the shippedsettings.json). - Extra slash commands under
.claude/commands/with your own names — only the threesoli-*.mdcommands are rewritten.
Don't store secrets in the shipped .claude/settings.json. Use .claude/settings.local.json (gitignored) for per-machine overrides.