Tooling and configuration for managing a bunch of repositories and packages.
- Bun
- TypeScript 7
- Oxlint & Oxfmt
- Commitlint
- Conventional Commit
- Semantic Release
- Forgejo Actions
- Gum
regime <check|sync|promote|templates> [path] [--yes] [--full]
If [path] is omitted, the current working directory is used. Regime discovers all regime.config.json files recursively under the target path (skipping node_modules and .git).
Compares managed files against their templates and reports differences. For each regime.config.json found:
- overwrite files: reports
missingordiffers - merge json / merge jsonc files: reports field-level diffs -- missing fields, wrong values, and what the expected value should be
- merge lines files: reports required template lines that are missing from the target
By default only problems are shown. Pass --full to also print fields/files that are already in sync.
Writes template-managed files into each project. For each regime.config.json found:
- overwrite files: created or replaced with the template content (with variable interpolation)
- merge json / merge jsonc files: deep-merged so that template-required fields are present while preserving any extra fields the project has added
- merge lines files: missing template lines are appended while preserving existing lines, comments, whitespace, and order
Files and directories are created if they don't exist. Files already in sync are skipped silently.
Interactively promotes a local file change back into a template. Only applies to overwrite-strategy files that differ from their template.
- Presents a filterable list of changed files (via
gum filter) - If the template chain has multiple templates, asks which template to write to (via
gum choose) - De-interpolates variable values back into
<<varname>>placeholders - Shows a diff of the proposed change
- Asks for confirmation (skip with
--yes) - Writes the updated file into the template directory
Requires gum to be installed.
Lists all available templates as a tree showing inheritance relationships. Pass --full to also list the files each template provides.
A project places a regime.config.json in its root (or in each workspace package):
{
"templates": ["profile/library", "workflow/mirror", "adapts-to/bun"],
"vars": {
"repo": "my-project"
}
}templates-- a string or array of template names (paths relative totemplates/); prefix a name with!to exclude that template from the resolved inheritance chainvars-- key-value pairs for<<key>>interpolation in template file contents and filenames
Template exclusions are exact template names and also apply to inherited templates. For example, "templates": ["profile/library", "!include/license"] uses the profile/library chain without syncing include/license.
Each template is a directory under templates/ containing:
.regime-template.json-- metadata (inheritance and file strategies)- Any other files -- the template content synced into target repos
A .regime-template.json looks like:
{
"inherits": ["shared/package"],
"patterns": {
"package.json": "merge json",
"tsconfig.*.json": "merge json"
}
}inherits-- parent templates resolved first (depth-first; parents before children)patterns-- maps file paths or globs to a file strategy
| Strategy | Behavior |
|---|---|
overwrite (default) |
Template file replaces the target file entirely. |
merge json |
Deep-merged into existing JSON. Template values win for shared keys; target-only keys are preserved; arrays are unioned (template items first, then unique target items). |
merge jsonc |
Like merge json but parses/writes JSONC (JSON with comments and trailing commas). |
merge lines |
Appends missing exact template lines to line-oriented files such as .gitignore, preserving existing content and order. |
When multiple templates in a chain provide the same file:
- overwrite: the last template in the chain wins
- merge json / merge jsonc: all template versions are merged in chain order, then merged into the target
- merge lines: missing exact lines from all template versions are appended to the target
Template files can contain <<varname>> placeholders in both their content and filenames (including directory components). These are replaced with values from the project's vars during check and sync.
For example, a template file named <<repo>>.code-workspace with vars: { "repo": "route" } produces route.code-workspace in the target.
The promote command reverses this (de-interpolation), replacing concrete values back into <<varname>> placeholders before writing to the template. Undeclared variables emit a warning and remain as-is.
When updating existing JSON/JSONC files, regime detects and preserves the file's existing indentation style. New files default to 2-space indent (JSON) or tab indent (JSONC).
templates/
shared/ foundational building blocks
include/ files included by inheritance only (not used directly)
profile/ complete project profiles (composed from shared + include)
adapts-to/ runtime/platform adapters
tool/ dev tooling (commitlint, husky, oxc)
workflow/ Forgejo CI workflows
Standalone library:
{
"templates": ["profile/library", "profile/workspace", "tool/oxc", "tool/commitlint", "tool/husky", "workflow/mirror", "workflow/publish-npm", "adapts-to/bun"],
"vars": { "repo": "route" }
}Monorepo root:
{
"templates": ["profile/monorepo/root", "profile/workspace", "tool/oxc", "tool/commitlint", "tool/husky", "workflow/mirror", "workflow/publish-npm"],
"vars": { "repo": "toolkit" }
}Monorepo workspace package:
{
"templates": ["profile/monorepo/library"],
"vars": { "repo": "toolkit" }
}