Skip to content

About

Code-structure-centric context layer for AI coding agents

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Segmently Modules

What it is for

An AI coding agent is an excellent worker with amnesia and a memory of limited size: every session starts knowing nothing about your project, and only so much fits into its context. Segmently Modules solves both problems:

  1. It writes the notes for starting work on any part of the project — a specific page or a server feature: what that part does, its rules, where its code lives.
  2. It finds the notes a task needs before the work starts, so the agent reads those and not the whole repository.
  3. It brings the notes up to date when the work is done — what changed, what was decided, what was found.
  4. It keeps the notes per role — developer, QA, designer, product owner, architect — so the agent reads only the notes it needs right now: its memory is limited.

The notes are plain Markdown in your repository; the skills write, find and update them, and the segmently-modules command line checks them, in CI too.

Under the hood it is a code-structure-centric context layer for AI coding agents: a module registry, per-module interface docs and per-role context files, maintained by a CLI and agent skills.

Segmently Modules keeps a registry of your code's functional modules (modules/registry.json), one MODULE.md plus role docs (roles/developer.md, roles/qa.md, …) per module, and rules that map code files to modules. With that, an agent asks "what do I read before this task?" (context), "which modules does this change touch?" (discover), and CI asks "did the code change without its docs?" (lint --changed). Every verb prints a JSON envelope with --json and uses exit codes a pipeline can branch on (docs/cli-contract.md).

Status: 0.x — the JSON contract (docs/cli-contract.md) is versioned per verb, and a minor release that changes it says so in CHANGELOG.md. Python ≥ 3.9, no dependency; git for coverage, lint --changed and --from-diff. MIT licensed (LICENSE); contributions: CONTRIBUTING.md; security reports: SECURITY.md.

Install with one prompt

Paste the block for your agent into a fresh session. It checks git and Python, installs the plugin and ends with one message of two steps for you: type /reload-plugins (Claude Code; in Codex, restart it) — an agent cannot reload its own plugins — then paste the request it gives you, the start of the module setup.

Claude Code — the plugin carries the skills and the command line:

Set up Segmently Modules for Claude Code on this machine, then stop and give me the two next steps.

Marketplace: segmently-ai/segmently-modules-plugins#stable. Plugin: segmently-modules@segmently-modules.

Run the steps in order and show me the exact output of every command:
1. git --version and python3 --version — git must answer, and Python must be 3.9 or newer. On macOS, if either one asks for the command line developer tools, run xcode-select --install, ask me to finish the installer it opens, then run both again. If Python is still missing or older than 3.9, tell me how to get Python 3.9 or newer on this operating system and stop there.
2. claude plugin marketplace add segmently-ai/segmently-modules-plugins#stable --scope user
   claude plugin install segmently-modules@segmently-modules --scope user
   If the marketplace is already there, run claude plugin marketplace update segmently-modules and then claude plugin update segmently-modules@segmently-modules --scope user.
3. claude plugin list — the output must name segmently-modules. If it does not, say so plainly and do not continue.
4. Do not use the skills in this session yet. Claude Code picks a newly installed plugin up only after /reload-plugins, which only I can type, or in a new session. Do not try to reload or restart anything yourself and do not start another Claude Code process. End with one separate message to me that holds only the text below, word for word:

Setup is done. Two steps for you:
1. Type /reload-plugins in this chat (or restart Claude Code in the repository you want to work on).
2. Then paste this request:
"Use the module-assistant skill to set Segmently Modules up in this repository:
- it has a module registry another tool or team already wrote: adopt it with the module-adopt skill;
- it has code but no module registry: run segmently-modules setup, then map the code into modules and write their notes with the module-init skill;
- it is a new repository: run segmently-modules setup, then the module-create skill for the first module.
The setup also adds the Segmently Modules section to CLAUDE.md and AGENTS.md, so every session knows the skills and the module system."

Codex — the plugin carries the skills; the command line comes from npm:

Set up Segmently Modules for Codex on this machine, then stop and give me the two next steps.

Marketplace: segmently-ai/segmently-modules-plugins on ref stable. Plugin: segmently-modules@segmently-modules.

Run the steps in order and show me the exact output of every command:
1. git --version and python3 --version — git must answer, and Python must be 3.9 or newer. On macOS, if either one asks for the command line developer tools, run xcode-select --install, ask me to finish the installer it opens, then run both again. If Python is still missing or older than 3.9, tell me how to get Python 3.9 or newer on this operating system and stop there.
2. npm install -g @segmently/modules, then segmently-modules --version — it must print segmently-modules and a version. Without npm, run uv tool install git+https://github.com/segmently-ai/segmently-modules.git@v0.3.0 instead.
3. codex plugin marketplace add segmently-ai/segmently-modules-plugins --ref stable
   codex plugin add segmently-modules@segmently-modules
   If the marketplace is already there, run codex plugin marketplace upgrade segmently-modules and then codex plugin add segmently-modules@segmently-modules again.
4. List the installed plugins and show me that segmently-modules is among them. If it is not, say so plainly and do not continue.
5. Do not use the skills in this session yet. Codex picks a newly installed plugin up only in a new session. Do not try to reload or restart anything yourself and do not start another Codex process. End with one separate message to me that holds only the text below, word for word:

Setup is done. Two steps for you:
1. Restart Codex in the repository you want to work on.
2. Then paste this request:
"Use the module-assistant skill to set Segmently Modules up in this repository:
- it has a module registry another tool or team already wrote: adopt it with the module-adopt skill;
- it has code but no module registry: run segmently-modules setup, then map the code into modules and write their notes with the module-init skill;
- it is a new repository: run segmently-modules setup, then the module-create skill for the first module.
The setup also adds the Segmently Modules section to CLAUDE.md and AGENTS.md, so every session knows the skills and the module system."

What goes into CLAUDE.md. Nothing goes into CLAUDE.md by hand: segmently-modules setup (the first request above runs it) adds a short "Module docs (Segmently Modules)" section to CLAUDE.md (Claude Code) and AGENTS.md (Codex, Cursor, Copilot; Gemini CLI reads GEMINI.md). It tells every session to read a task's notes before the work (segmently-modules context), to bring them up to date after it (segmently-modules sync-instructions, the module-sync skill), to start module work with segmently-modules next, and it lists the skills. segmently-modules agents-md refreshes the section; the text around it stays yours.

The optional plugins add skills on top of the core one: segmently-modules-ui@segmently-modules (the designer skill) and segmently-modules-qa@segmently-modules (the acceptance-criteria skills) — install them the same way.

Install by hand

Pick the route your agent uses — every one gives the same segmently-modules command line.

Python. Segmently Modules needs Python ≥ 3.9. On macOS the python3 of the Command Line Tools — the package that brings git — is enough; elsewhere any Python 3.9 or newer is, and uvx (or uv tool install) fetches one when there is none.

Claude Code — the plugin carries the skills and the command line:

claude plugin marketplace add segmently-ai/segmently-modules-plugins#stable
claude plugin install segmently-modules@segmently-modules        # the core skills and `segmently-modules` itself
claude plugin install segmently-modules-ui@segmently-modules     # optional: the designer skill
claude plugin install segmently-modules-qa@segmently-modules     # optional: the acceptance-criteria skills

Then run /reload-plugins in Claude Code, or start a new session: an agent picks a newly installed plugin up only then (Codex: a new session).

The segmently-modules plugin also carries the read-only module-chooser subagent (segmently-modules:module-chooser) that the skills hand a segmently-modules choose work order; change how modules are chosen with segmently-modules templates override choose/rules.md. It carries three more agents, module-discover-agent, module-scout-agent and module-research-agent, each of which runs its skill in the agent's own context and returns the skill's output; for Codex, segmently-modules packs sync --agent codex writes the same three into .codex/agents/ (docs/skills.md).

Codex — the plugin carries the skills; install the command line first (a Codex plugin puts nothing on PATH), at the released version the plugin comes from:

uv tool install git+https://github.com/segmently-ai/segmently-modules.git@v0.3.0   # or npm install -g @segmently/modules, below
codex plugin marketplace add segmently-ai/segmently-modules-plugins --ref stable
codex plugin add segmently-modules@segmently-modules

Codex picks the plugin up in a new session.

A repository that keeps the default "repo" delivery and has run segmently-modules packs sync shows a plugin user every built-in skill twice — the plugin's and the copy; builtin_delivery = "plugin" (below) makes packs sync remove the copies it made.

Cursor, Gemini CLI, GitHub Copilot — no plugin: install the command line, set Segmently Modules up in the repository (segmently-modules init enables the core pack; or set [packs] builtin in .segmently-modules/config.toml yourself), then copy the skills into .agents/skills/ — these agents need the default "repo" delivery:

uv tool install git+https://github.com/segmently-ai/segmently-modules.git@v0.3.0
segmently-modules init                                 # once: the config, with [packs] builtin = ["core"]
segmently-modules packs sync --agent cursor            # or --agent gemini, --agent copilot
segmently-modules packs sync --agent cursor --remove   # later: take the copies out again

The dev channel carries every change before a release: #dev instead of #stable, --ref dev, and the marketplace segmently-modules-dev (claude plugin install segmently-modules@segmently-modules-dev). A repository whose agents get the built-in skills from the plugins sets builtin_delivery = "plugin" under [packs], so packs sync does not copy them a second time (docs/skills.md).

The command line alone — from npm (macOS and Linux: the package carries the engine and runs it with your Python 3.9 or newer; Node runs nothing):

npm install -g @segmently/modules       # `segmently-modules` on PATH
npx @segmently/modules --help           # or run it without installing

Or in a virtual environment, from a checkout or the repository:

python3 -m venv .venv && . .venv/bin/activate
pip install /path/to/segmently-modules                       # a checkout
pip install git+https://github.com/segmently-ai/segmently-modules.git@v0.3.0   # or the repository
segmently-modules --help

Or from git, without a checkout (Python 3.9 or newer; no other dependency):

uv tool install git+https://github.com/segmently-ai/segmently-modules.git@v0.3.0   # on PATH; uv fetches a Python when none fits
uvx --from git+https://github.com/segmently-ai/segmently-modules.git@v0.3.0 segmently-modules --version   # or run it without installing
pipx install git+https://github.com/segmently-ai/segmently-modules.git@v0.3.0      # needs a Python 3.9+ already installed

The @v… suffix pins the latest release tag (each stable release moves it); without it you get the engine's main, which the dev channel follows.

The shortest start

segmently-modules setup                       # init, packs sync and the agents-md block in one command (--dry-run first)
segmently-modules next                        # the daily loop: what the repository needs now, with the command for each

segmently-modules setup picks the agents from the skill directories it finds (else claude and codex) and writes CLAUDE.md for Claude and AGENTS.md for every other agent; a later run refreshes the instruction files that already hold the Segmently Modules block. Gemini CLI reads GEMINI.md, so run segmently-modules setup --target GEMINI.md for it. segmently-modules next is read-only: one ranked list of what to fix (lint errors, stale skill copies, a role without docs, …), each item with the Segmently Modules command that fixes it.

A role your team adds — say, a security review of every module — is declared once in .segmently-modules/config.toml (standard = true: every module gets its doc):

[roles.security]
order = 50
standard = true
description = "Threats, secrets and permissions the module touches"
segmently-modules roles add security --all --dry-run   # the plan: the doc each existing module would get
segmently-modules roles add security --all             # write and register them; an existing file is never overwritten

segmently-modules roles list shows, per role, which modules have its doc and which do not.

Greenfield in 5 minutes

A new todo API with three features: tasks, lists, reminders.

mkdir todo && cd todo && git init
segmently-modules init        # .segmently-modules/config.toml (starter: enables the core skills), modules/registry.json, .gitignore lines

Create the modules. A top-level module needs a one-sentence description (20–200 characters) and at least 5 distinct keywords — the terms that route a task to it:

segmently-modules create tasks --non-interactive \
  --description "Task items: create, complete, reorder; the home of a single task." \
  --keywords "task, todo, complete, due, priority"
segmently-modules create lists --non-interactive \
  --description "Task lists: group, share and order tasks in named lists." \
  --keywords "list, group, share, board, folder"
segmently-modules create reminders --non-interactive \
  --description "Reminders: schedule and send notifications before a task is due." \
  --keywords "reminder, notify, schedule, alarm, snooze"

--keywords takes a comma-separated list (repeatable); --keyword (repeatable) adds one keyword at a time — use it for a keyword that itself contains a comma. Each create is its own write: when one in a batch like this fails, the modules before it stay created — fix that one and run it again. create warns (on stderr; it still creates the module) about keywords that route poorly: 3 characters or fewer, a generic word such as data, user or delete (in any form), more than 40 distinct words ([create] max_keywords), or a second form of one word (tasks next to task: one form is enough).

Matching (match, context, discover --task) is by whole words, case-insensitive, and the forms of one word match each other: the keyword save matches a task that says "saving", entry matches "entries" ([match] normalize, on by default; "none" matches exact words only). One form per word is enough; register the words your team actually types (synonyms). (The word boundary only applies on an edge of the keyword that is itself a letter/digit/_; a keyword starting or ending with punctuation, e.g. .epub or c++, matches exactly and can still match inside a longer token on that side.) If nothing reaches [match] min_score, context/match say so (no module matched (try domain terms, or: segmently-modules list) / no keyword matches (try rephrasing with domain terms, or use: list)) and list the near misses — modules with a keyword that almost matches a task word:

no module matched (try domain terms, or: segmently-modules list)
near  reminders                    reminder ~ remind
re-run with the module's own keyword in the task text, or read it directly: segmently-modules show reminders

(context --json carries the same rows as near_misses.) Plain discover --task with no match just omits the module — there is no module-name argument to fall back to (context takes only --task/--task-file, never a module). Re-run with a word that IS one of the module's registered keywords (segmently-modules show <module> prints them on its keys line), add the missing one (segmently-modules registry append tasks keywords '"todos"', JSON value — quote a string), or skip matching and read the module directly: segmently-modules show tasks --role developer.

Each gets modules/<name>/MODULE.md, one doc per standard role and a registry entry. Now wire the code: modules know nothing about code until a [[code_map]] rule (or a code_pointer field) says which files belong to which module.

mkdir -p src/tasks src/lists src/reminders
touch src/tasks/__init__.py src/lists/__init__.py src/reminders/__init__.py
segmently-modules code-map add src --pattern "src/{module}/**"   # {module} = one path segment: src/tasks/x.py -> tasks

code-map add appends the rule to .segmently-modules/config.toml — it never rewrites the file, and refuses an id that already exists in any layer; edit or remove rules there by hand:

[[code_map]]
id = "src"
pattern = "src/{module}/**"

Record a typed relation, then check everything:

segmently-modules registry append reminders related_modules \
  '{"module": "tasks", "relation": "depends-on", "description": "Reminders fire for task due dates"}'
segmently-modules lint                          # 0 error(s), 0 warning(s), 0 info
segmently-modules coverage --fail-under 80      # share of the repo's files that map to a module, unmapped files
segmently-modules show reminders                # docs to read, and `code  src/reminders/**`
git add .gitignore .segmently-modules modules src && git commit -m "modules"

The agent loop — before planning, after the change, and the gate (segmently-modules ci, see CI gate):

segmently-modules context --task "snooze a reminder" --role developer   # what to read, where the code is
BASE=$(git rev-parse HEAD)   # the commit the change starts from — capture BEFORE editing/committing
# … the agent changes src/reminders/snooze.py and commits …
segmently-modules ci --base "$BASE"     # exit 1: step drift failed — MS050, code changed, docs did not
segmently-modules propose --run-id r1 --module reminders --op doc_append \
  --doc modules/reminders/roles/developer.md --reason "document snooze" --value-file - <<'EOF'
## Snooze

`snooze(minutes)` moves the reminder's due time; a snoozed reminder fires once.
EOF
segmently-modules sync --from-diff "$BASE..HEAD" --apply-proposals     # maps the change, runs hooks, applies proposals
git add modules/reminders && git commit -m "docs: snooze"
segmently-modules ci --base "$BASE"     # exit 0: lint passed, drift passed, coverage report-only

Agents never edit the registry or module docs mid-run: they propose, and one sync --apply-proposals (or proposals apply) applies every queued item under the registry lock. Without --run-id it applies every pending proposal file; --run-id r1 applies only that run's (the file propose --run-id r1 queued) — in a pipeline that runs several agents, pass it:

segmently-modules sync --from-diff "$BASE..HEAD" --apply-proposals              # every pending run
segmently-modules sync --from-diff "$BASE..HEAD" --apply-proposals --run-id r1  # only run r1

The registry writers registry and propose refuse values lint would report as errors (an unknown status, an edge without a description or to an unknown module).

When something goes wrong

A refusal writes nothing and says what to fix; a lint finding names its code. Two of each:

segmently-modules registry set reminders status '"shipped"'   # exit 2, nothing written
segmently-modules code-map add notes --glob "src/notes/**" --module notes   # exit 2, nothing written
segmently-modules lint --fail-on warning                      # exit 1 after a hand edit (below)
segmently-modules: error: field 'status': status 'shipped' not in ['active', 'draft', 'planned', 'temporary'] (lint MS003)
segmently-modules: error: code-map add: 'notes' is not a registry module or child (segmently-modules list shows the modules)
WARNING MS052 *: [[code_map]] 'remind': module 'remiders' is not a registry module or child; the rule maps nothing
WARNING MS053 *: [[code_map]] 'reminder-jobs' (-> reminders) and 'src' (-> tasks) both map 1 file(s), e.g. src/tasks/jobs.py — mark the more specific rule exclusive = true or narrow its globs

The fixes: a status from the list ('"active"'); segmently-modules create notes … first, then the rule; for MS052 (a hand-edited rule in .segmently-modules/config.toml), correct its module — the typo remiders; for MS053 (a hand-added rule reminder-jobs with the glob src/*/jobs.py), make it exclusive = true or narrow its glob, so one file maps to one module — then segmently-modules lint --fail-on warning exits 0 again.

A child module for a sub-area, with its own code rule:

segmently-modules create search --parent tasks --non-interactive \
  --description "Full-text search over task titles and notes." --keyword search
segmently-modules code-map add task-search --glob "src/tasks/search/**" --module tasks/search --exclusive

A --glob rule may name a child (--module tasks/search); --exclusive keeps rule src from mapping these files to tasks as well.

segmently-modules show tasks still lists code src/tasks/** — [[code_map]] rules are routing globs, not resolved per-file ownership, so the parent's rule still textually covers src/tasks/search/ too. Prove the split against a real file instead:

segmently-modules discover --files src/tasks/search/index.py
# modify    tasks/search                   via diff
#           update modules/tasks/MODULE.md
#           update modules/tasks/submodules/search/MODULE.md
#           update modules/tasks/submodules/search/roles/developer.md
#           update modules/tasks/roles/developer.md
#           update modules/tasks/submodules/search/roles/qa.md
#           update modules/tasks/roles/qa.md
# file      src/tasks/search/index.py -> tasks/search

Only tasks/search is listed — the file line shows the file maps there and nowhere else. discover --files (space-separated file paths — a directory is refused; a path not on disk is still mapped and reported as not on disk, so a typo shows) is the file-level truth, like sync --dry-run --files; show's / context's code and code_globs lines are routing rules, not a file list.

Brownfield: an existing, layered codebase

cd existing-app
segmently-modules init                      # keeps your .gitignore, appends its lines
segmently-modules coverage                  # everything unmapped: the baseline

(To have Segmently Modules propose the modules from the code first, see Start from existing code; by hand:)

  1. One module per feature (segmently-modules create orders …, segmently-modules create invoices …), plus one per shared layer that has its own rules (segmently-modules create db …).

  2. Map the layers — one rule per per-feature layer. Layered repos keep a feature's code in several places (app/routes/orders/, app/repositories/orders.py, app/models/orders.py, per-feature SQL under a shared directory like app/db/queries/sql/orders.sql, schemas, tests…). Give EVERY per-feature layer its own {module} pattern rule — not just the obvious ones — and mark exclusive any per-feature rule whose files sit inside a shared layer's directory, so a feature change does not silently also count as a change to the shared module:

    segmently-modules code-map add routes --pattern "app/routes/{module}/**"
    segmently-modules code-map add repositories --pattern "app/repositories/{module}.py" --exclusive
    segmently-modules code-map add queries-sql --pattern "app/db/queries/sql/{module}.sql" --exclusive
    segmently-modules code-map add db --module db --glob "app/db/**" --glob "app/repositories/**"

    repositories is exclusive so app/repositories/orders.py maps to orders only, not also to db; queries-sql is exclusive because its per-feature files live INSIDE the shared app/db/ tree — without that rule they silently map to db, not orders. db keeps the base classes, sessions and the rest.

    Files of one feature that are not named after it (app/jobs/nightly_totals.py, app/api/order_export.py for orders) take ONE rule with a --glob per path (--glob repeats):

    segmently-modules code-map add orders-extra --module orders --glob "app/jobs/nightly_totals.py" --glob "app/api/order_export.py"

    exclusive wins only over NON-exclusive rules. Two exclusive rules that route one file to different modules are still an MS053 overlap:

    segmently-modules code-map add repositories --pattern "app/repositories/{module}.py" --exclusive
    segmently-modules code-map add db-repositories --module db --glob "app/repositories/**" --exclusive  # MS053

    Both claim app/repositories/orders.py (for orders and for db): keep one of them exclusive, or narrow the other's globs.

    Check the rules against real files, one per layer: segmently-modules discover --files app/db/queries/sql/orders.sql (its file line should read -> orders, not -> db) — the same command used to verify the child-module split above.

  3. Iterate on segmently-modules coverage until the unmapped list is only what belongs to no module (exclude it with [coverage] exclude = [...]), then look at segmently-modules coverage --json's per-module counts: a shared/catch-all module with a suspiciously large file count is the smell of a missing per-feature rule (see the SQL example above) — segmently-modules code-map files db lists exactly which files it holds and through which rule; plain segmently-modules lint reports two rules that route one file to two modules as MS053. Then gate CI with segmently-modules ci (next section) and your coverage target.

  4. Optional per-module layout — one modules/<name>/module.json per module instead of one shared file (fewer merge conflicts in big teams):

    segmently-modules index split               # writes modules/<name>/module.json for every module
    # then set [paths] registry_layout = "per-module" in .segmently-modules/config.toml
    segmently-modules list                      # same modules, now read from the module files
    segmently-modules index build --check       # in CI: exit 1 when the generated index is stale

Adopt an existing registry

A repository whose registry and module docs another tool wrote — no .segmently-modules/ yet — needs a team config so the engine reads it without surprises (its roles, extra fields, a timestamp key, where the code lives). adopt infers it and never changes the registry or a doc:

segmently-modules adopt --dry-run     # the config it would write, each key with an `# adopt:` line saying why
segmently-modules adopt               # writes .segmently-modules/config.toml; lint runs in report mode
segmently-modules init                # adds the .gitignore lines (lock file, proposals, init); keeps the config
segmently-modules lint --fail-on warning
git add .segmently-modules/config.toml .gitignore && git commit -m "segmently-modules: read the existing registry"

Review the report first: roles (order, standard when 80 % of the modules carry one), fields (type, scope, kind = "code_pointer" when their values name repository paths), the directories under the modules dir that are not modules, the registry's updated_at key, one [[code_map]] rule when half the modules have <prefix>/<module>/ (below half, the best candidate is written commented out and reported as code_map_suggestion), and — commented out, for the team to decide — doc budgets its docs exceed. adopt writes that one file only: segmently-modules init adds the .gitignore lines for the lock file, proposals and init, and keeps your config (adopt's next steps say so while lines are missing). A registry elsewhere: --registry docs/modules/registry.json. With a config already there, adopt writes what is still missing to .segmently-modules/adopt.proposed.toml instead — merge it by hand. The rules and thresholds: docs/configuration.md.

Start from existing code

A codebase without modules yet: init map proposes them from the code — package manifests, source directories, imports, CODEOWNERS and the files that change together:

segmently-modules init map        # the starter files, then .segmently-modules/init/preflight.json and proposal.json
# edit .segmently-modules/init/proposal.json: each candidate's include, name and paths (merge, split, drop)
segmently-modules init confirm    # gate 3: checks the proposal and freezes it as confirmed.json
segmently-modules init fanout     # one work item per module: .segmently-modules/init/work/<module>.json with its prompt
segmently-modules init status     # the phases, the modules and the next step

Then one writer per module documents its code into .segmently-modules/init/staging/<module>/ — three ways to drive them, over the same state:

  • The module-init skill in an agent session: it runs the whole flow, dispatches one subagent per module ([init] max_parallel at a time) and stops at both gates for you.
  • One agent, one module at a time: segmently-modules init next claims a module and prints its prompt; the agent writes the files; segmently-modules init done <module> checks them.
  • CI: an executor command gets each prompt on stdin — segmently-modules init run --executor "<command>".
segmently-modules init reconcile  # the staging registry: import edges, shared keywords, duplicate names
segmently-modules eval routing --prompt   # the task writer's prompt: purpose paragraphs and files, never keywords
# a writer puts [{"task": …, "module": …}] into .segmently-modules/init/routing-tasks.json
segmently-modules init verify     # lint, invented components, the routing hit rate — nothing moved yet
segmently-modules init finish     # gate 7: the docs, the registry, the code-map rules, the agents' block

In CI, without a person — gate 3 as proposed, gate 7 as a pull request:

segmently-modules init map
segmently-modules init resume --non-interactive --executor "my-writer" --open-pr

init finish never commits (it prints the git add line); --open-pr makes one commit on a new branch and opens the pull request with gh (both titled docs: module docs for <n> module(s) (segmently-modules init), a Conventional Commits subject). An interrupted or failed run continues with segmently-modules init resume. Code outside every package root gets candidates by the source-directory rule too (a top-level tools/, say). When init map notes code files outside every candidate, a manifest in a fixture, docs site or functions folder sits inside a source directory and keeps that directory's code out: add it to [init] exclude and run segmently-modules init map --restart. Modules created by hand after gate 3 are kept as they are. init map refuses a registry that already has modules: use adopt (above). Every phase, the executor contract, the prompt templates and verify's checks: docs/init.md; the [init] keys: docs/configuration.md.

CI gate

segmently-modules ci --base origin/main --fail-under 80

One command, three steps that always all run, so one failure never hides another: lint (plain — config-level findings such as a typo'd [[code_map]] module, MS052, or two rules routing one file to two modules, MS053, appear only here), drift (lint --changed against --base: code changed without its module's docs, MS050) and coverage (fails below --fail-under; without a threshold it only reports). Exit 1 when a step failed, 2 for a usage error. --base must be a real ref — in CI the pull request's target branch (fetch it first), or the "$BASE" captured before a change; against the default HEAD a clean checkout has nothing to compare, and ci says so in its notes. Outside a merge-ref checkout, pass --base "$(git merge-base origin/main HEAD)" so the target branch's own later commits are not counted as changes. Put the team's defaults in [ci] of .segmently-modules/config.toml (fail_on, base, coverage_fail_under), then CI runs a bare segmently-modules ci. --baseline FILE|- takes the --json output of an earlier ci run (- = stdin): a lint or drift finding it already holds is known, and a step fails only on findings that are not (MS050 / MS051 are never known) — module-sync saves the gate before it edits and checks its result this way.

Core skills

Segmently Modules ships agent skills that drive it for you — in Claude Code and Codex. segmently-modules init enables them ([packs] builtin = ["core"] in .segmently-modules/config.toml; add "ui" and "qa" for the designer and QA-acceptance packs). Copy them where the agents read them and commit them:

segmently-modules packs sync --agent claude --agent codex   # .claude/skills/module-*/ and .agents/skills/module-*/
  • module-scout — quick context on the modules a task names (or finds by meaning), while it is discussed;
  • module-discover — the touch-set of a confirmed task or a branch: modules, docs, code files;
  • module-research — one question answered in depth from docs and code, with the gaps;
  • module-sync — after a work session: what it decided, learned and changed written into the docs, keywords and links, ci green;
  • module-roles — a new role's doc added to every existing module, confirmed by a dry run;
  • module-create — a new module or child, documented from its existing code, confirmed by a dry run;
  • module-split — an oversized module split into children (or a split one rebalanced), confirmed before any write;
  • module-lint — the gate explained and its safe findings fixed;
  • module-init — a codebase without modules taken through segmently-modules init, with two stops for you;
  • module-adopt — an existing registry read as it is: the config inferred and explained;
  • module-assistant — the entry point: sets Segmently Modules up, says how to do something, turns next into a plan and carries it out on your OK.

Each one, the ui / qa packs, keeping them current and owning one: docs/skills.md.

Semantic module choice

Keyword routing (segmently-modules match, context, discover --task) needs the task to use the registry's words. To choose modules by MEANING — a task in any language, a synonym, a described behaviour — Segmently Modules hands the choice to the agent you already use:

segmently-modules catalog --json                       # one card per module and child: what an agent reads
segmently-modules choose --task "customers get money back for a returned book" --json   # the work order
segmently-modules choose --apply answer.json --json    # check the agent's answer; prints the picks and their docs

The skills (module-scout, module-discover, module-research, module-sync) do this for you: they run segmently-modules choose, your Claude Code or Codex answers it, and hybrid is the default (keyword and meaning together; say "only lexical" to switch it off). The models and the depth are [search] settings (claude_model, a Claude Code subagent model alias such as sonnet, opus or haiku; codex_model; effort = quick | standard | deep).

For a script or CI, point Segmently Modules at your own agent command and use --match semantic|hybrid (or [match] mode) or segmently-modules choose --task … --run (--task-file FILE|- reads the task from a file or stdin). The command is read ONLY from your environment, as a JSON array run without a shell ({claude_model}, {codex_model}, {effort} and {reasoning} are filled in from [search]; choose --effort overrides effort for one run); the work order arrives on stdin (compact JSON) and as the file $SEGMENTLY_MODULES_WORK_ORDER, the answer's JSON Schema is the file $SEGMENTLY_MODULES_SCHEMA. A repository cannot choose or change the command, and its [match] mode runs it for match, context and discover --task only when you opt in with SEGMENTLY_MODULES_AGENT_ALLOW_REPO_MODE=1 (without it the run is lexical, with a stderr note; --match and choose --run are your own requests): set the opt-in per CI job or per shell session in repositories you trust, not in your shell profile, and keep the command's own permissions read-only. Two examples (check the flags against your agent's --help; they are examples, not a recommendation; codex exec outside a git repository also needs --skip-git-repo-check):

# Claude Code: the answer is the `structured_output` of the JSON envelope
export SEGMENTLY_MODULES_AGENT_COMMAND='["sh", "-c", "claude -p --model {claude_model} --output-format json --json-schema \"$(cat \"$SEGMENTLY_MODULES_SCHEMA\")\""]'

# Codex: the last message is printed to stdout; the schema goes in as a file
export SEGMENTLY_MODULES_AGENT_COMMAND='["sh", "-c", "codex exec -m {codex_model} -c model_reasoning_effort={reasoning} --sandbox read-only --output-schema \"$SEGMENTLY_MODULES_SCHEMA\" -"]'

segmently-modules match --match hybrid "customers get money back for a returned book" --json

Segmently Modules itself holds no model, no API key and no network code, ships no model and suggests none; the agent runs under your credentials, SEGMENTLY_MODULES_AGENT_TIMEOUT (default 300 seconds) stops it, and nothing is cached. The settings and the trust boundary; the JSON.

Packs and skills

A pack is a team's own layer on top of Segmently Modules: roles with their doc templates and agent skills that read those docs. It lives in .segmently-modules/packs/<id>/ and is committed with the repository.

segmently-modules packs new team --role reviewer --skill api-review   # pack.toml, roles/reviewer.md, skills/api-review/SKILL.md
segmently-modules create reviews --non-interactive --role reviewer \
  --description "Customer reviews of books: ratings, comments and moderation." \
  --keywords "review, rating, stars, comment, moderation"
segmently-modules packs sync --agent claude --agent codex   # .claude/skills/api-review/ and .agents/skills/api-review/
segmently-modules agents-md --target CLAUDE.md --target AGENTS.md   # one managed block telling agents how to use segmently-modules

packs sync --check and agents-md --check are the CI lines; segmently-modules eject <skill> takes a skill over (the pack never overwrites it again) and segmently-modules templates list shows where every doc template comes from. The walkthrough, pack.toml reference, conflicts and the pack lint codes (MS060–MS065, MS068 and MS069): docs/writing-a-pack.md.

Reference

  • docs/configuration.md — config layers, every section and key, packs, lint codes, the adopt rules and the [init] keys.
  • Adopt an existing registry and Start from existing code — segmently-modules adopt, segmently-modules init map; docs/init.md — every phase of segmently-modules init, the executor, segmently-modules eval routing.
  • docs/cli-contract.md — every verb's JSON data, exit codes, the files the engine creates, pipeline stages.
  • docs/writing-a-pack.md — packs: roles, templates, agent skills, packs sync, eject, the agents-md block.
  • docs/skills.md — the built-in skills (core, ui, qa): what each one does, enabling, syncing and owning them.
  • segmently-modules <verb> --help — flags and limits of one verb.
  • evals/adoption/ — the adoption evals (a deterministic script and blind-agent prompts).
  • docs/releasing.md — for maintainers: building the plugins, channels and versions, the release and its checks, CI.

About

Code-structure-centric context layer for AI coding agents

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages