Skip to main content
strata init sets up Strata in a repository. It detects your layout, writes a strata.toml matched to how much code you already have, runs an initial check to show the current drift, and offers to install agent skill files. It never guesses silently: every detected path shows where it came from, and nothing is written until you confirm (or pass --yes).
strata init [--yes] [--root PATH ...] [--tests PATH ...] [--tooling PATH ...]
            [--full | --gradual] [--skills | --no-skills] [--name NAME]

What it does

  1. Detects your layout. Package roots come from pyproject.toml metadata (hatch, setuptools, poetry, flit, uv workspaces, the project name), ruff’s src setting, and a directory scan. Test paths come from pytest testpaths and tests/test directories; tooling from scripts, tools, bin, and tasks directories with Python files.
  2. Picks a starting ruleset. An existing codebase starts gradual: select = ["SFL", "SFH", "SFA", "SFN"]. An empty repository gets the full select = ["SF"] and a scaffolded src/<name>/ package plus tests/.
  3. Writes strata.toml and updates your .gitignore to cover Strata’s cache directory.
  4. Measures current drift by running the starting ruleset once and printing per-family fault counts.
  5. Installs agent skill files (.claude/, .opencode/, .agents/) unless you decline; see strata skills.

Options

OptionDescription
--yesAccept every detected choice; required when no terminal is attached.
--root PATHUse these package roots instead of the detected ones. Repeatable.
--tests PATHUse these test paths. Repeatable.
--tooling PATHUse these tooling paths. Repeatable.
--fullStart with the full ruleset (select = ["SF"]) regardless of detection.
--gradualStart with the gradual ruleset regardless of detection.
--skills / --no-skillsInstall or skip agent skill files without prompting.
--name NAMEPackage name for an empty-repository scaffold. Only valid when no Python package is detected.
--full and --gradual are mutually exclusive, as are --skills and --no-skills. --root, --tests, and --tooling only apply when a codebase is detected; --name only applies when none is.

An existing repository

On a repository with code, strata init shows what it detected and why, then confirms before writing:
--> Detecting project layout

    roots    src/acme      pyproject: hatch packages
    tests    tests/        directory scan
    tooling  none detected

    Accept? [Y/n/e] e = edit paths

--> Existing codebase - 1,204 Python files

    Starting with the gradual ruleset: SFL, SFH, SFA, SFN
    Wrote strata.toml

--> Measuring current drift

    SFA  annotations   3,411
    SFL  layers          212
    SFH  hygiene         540
    SFN  naming            2

    Found 4,165 faults across 310 files against the starting ruleset.
    See docs.stratalint.com/adoption for rolling out gradually.

--> Install agent skill files? [Y/n]

    Updated .opencode/skills/strata/SKILL.md
    Updated .claude/skills/strata/SKILL.md
    Updated .agents/skills/strata/SKILL.md

--> Next

    strata check            run anytime
    strata rule SFA001      inspect any code in the output
Answering e at the confirmation lets you edit the paths; n aborts without writing anything. When several package roots are detected, you pick which to include by number. The gradual starting point deliberately holds back the families that imply refactors (SFR roles, SFS shape, SFT tests). Widen select as you go; see Adopting Strata.

An empty repository

With no Python code detected, strata init scaffolds a fresh layout instead. It asks for a package name (or derives it from the directory name, or takes --name), then starts fully enforced from the first commit. With --yes --name Sample-App --no-skills:
--> Empty repository

    Created src/sample_app/__init__.py
    Created tests/
    Wrote strata.toml

--> Found 0 faults

--> Agent skill files - no

    Run strata skills update when you are ready.

--> Next

    strata check            run anytime
    strata rule SFA001      inspect any code in the output

Gitignore handling

Strata’s result cache lives under .strata/, which should not be committed.
  • If a root .gitignore exists and does not already cover the cache path, strata init appends a .strata/ entry to it.
  • An empty repository with no .gitignore gets one created from the standard GitHub Python template, plus the .strata/ entry.
  • An existing repository with no .gitignore gets one containing just the .strata/ entry.

Rerunning is safe

If the directory already has a strata.toml or a [tool.strata] table, strata init changes nothing and exits 0:
Strata configuration already exists: /path/to/repo/strata.toml (nothing to do)
If a parent directory’s configuration would apply here instead, init refuses with an error rather than shadowing it. All writes are transactional: on any failure, files created during the run are rolled back.

Non-interactive use

Prompts require a terminal. In CI or scripts, pass --yes (or make every choice explicit with flags); otherwise init fails:
Interactive initialization requires a TTY; use --yes or explicit options.
strata init --yes --no-skills

Exit codes

CodeMeaning
0Configuration written, or a local configuration already exists.
2Detection, validation, or write failure; declined confirmation; missing TTY.

Quickstart

The manual version of what init automates.

Adopting Strata

Growing from the gradual ruleset to full enforcement.

Configuration

Every key in the file init writes.

strata skills

The agent guidance init offers to install.