seed is a Terraform-inspired, spec-driven filesystem orchestration tool.
It captures directory trees, plans changes, applies them safely, syncs drift, scaffolds projects from reusable templates, and can also execute manifest-driven repository or service maintenance.
Think Terraform for directory trees, plus template scaffolding and workspace maintenance.
Highlights
- Multiple spec inputs:
.tree,.seed, YAML, JSON, DOT, image OCR, and stdin - Deterministic planning with exportable plans:
seed plan spec.seed --out plan.json - Safe execution of immutable plans:
seed apply plan.json - Drift workflows:
diff,sync,match, snapshots, and spec history - Template variables in paths and content:
<varname>/and{{var}} - Project-local template registration under
.seed/templates/ - Reusable template registry with versions, locking, content sources, and built-in templates
- Copier-style template config support: questions, defaults, answers files, excludes, skip-if-exists, and gated tasks
- Manifest-driven repository/service/system maintenance with
seed maintain - Structure locking, watch mode, state locks, hooks, Graphviz export, and shell completion
Install
pip install seed-cli pip install "seed-cli[image]" # OCR/image parsing pip install "seed-cli[ui]" # rich terminal output
Python >=3.10 is required.
Quick Start
Capture an existing directory, preview a plan, then apply it:
seed capture --out project.tree seed plan project.tree --out plan.json seed apply plan.json
For direct spec execution:
seed register project.tree seed apply project.tree seed diff project.tree
For repository or service automation:
seed maintain maintenance.yml seed maintain maintenance.yml --execute
Commands
seed --help groups commands by workflow so related tasks are easier to scan.
| Group | Commands | Description |
|---|---|---|
| Plan & Apply | plan, diff, apply, sync, match |
Preview, compare, and apply filesystem changes |
| Templates | register, create, templates (template) |
Register, instantiate, and manage reusable specs |
| State & History | capture, revert, specs, lock |
Capture state, recover snapshots, inspect history, and enforce structure versions |
| Maintenance | doctor, maintain, hooks |
Lint specs, run repository/service maintenance, and install hooks |
| Export & Utilities | export, utils |
Export trees/plans/DOT output and run helper tools |
Core Workflow
Immutable Plans
seed plan dir_structure.tree --out plan.json seed apply plan.json
seed apply also accepts a spec directly:
seed apply dir_structure.tree
When you apply a spec with template placeholders such as <name>/ or
features/<name>.ts, seed apply
first runs seed register semantics: it writes the supporting files under
.seed/templates/ and .seed/templates/project/, then removes any stale
literal placeholder paths like features/<name>/ left behind by older runs.
Drift Detection
seed diff dir_structure.tree seed sync dir_structure.tree --dangerous seed match dir_structure.tree --dangerous
sync deletes extras not in the spec. match also creates missing paths while
respecting directories marked with ....
Partial Plans
seed plan dir_structure.tree --target scripts/
seed plan dir_structure.tree --targets "services/*"
seed plan dir_structure.tree --target-mode exactSpec Syntax
Use .tree for simple filesystem specs, or .seed when you want the same tree-shaped format plus richer inline metadata such as kinds, tags, and URLs.
Basic Example
@include base.tree
scripts/
├── build.py @generated
├── notes.txt @manual
├── cache/ ...
└── docs/ ?
Markers
@include file.tree: include another spec@generated: generated file@manual: manually maintained file?: optional file or directory...: allow extras inside a directory<varname>: template placeholder in a path segment or filename{{var}}: variable interpolation in file contents
.seed also supports inline metadata markers:
!kind: semantic kind marker such as!service,!doc, or!template+tag: repeatable tags such as+remote +shared-> URL: attach a metadata URL to a node; on directory nodes this can be used as a template content source
Example:
vendor/
└── api/ !service +remote -> https://github.com/acme/repo.git
Structured YAML and JSON specs can also carry metadata with either a
metadata object or top-level kind, tags, and url fields.
Variable Usage
seed plan spec.tree --vars project_name=myapp seed apply spec.tree --vars project_name=myapp seed create spec.tree project_name=myapp
Templates
Template Directories
Define repeating structures with template variables:
files/
├── <version_id>/
│ ├── data.json
│ └── meta/
└── ...
Placeholders can also appear in path-per-line specs or filenames, and templates can include more than one placeholder:
features/<domain>/<name>/route.ts
features/<name>.ts
Create instances:
seed create releases.tree version_id=v3 seed create component.tree domain=billing name=invoices seed create releases.tree version_id=v3 --dry-run
Project-Local Templates
Use seed register to mirror any .tree or .seed spec into the project-level
.seed/templates/ directory. When the spec contains placeholders anywhere in a
path, it also extracts the outermost placeholder subtree into
.seed/templates/project/. seed apply <spec> runs the same registration step
automatically before execution.
seed register releases.tree seed apply releases.tree
That lets you create from either a path-based project template:
seed create --template .seed/templates/releases.tree version_id=v3
or a registered project template name:
seed create --project version_id version_id=v3
Template Registry
Manage reusable templates stored under ~/.seed/templates/ by default, or
under $SEED_HOME/templates/ when SEED_HOME is set.
seed templates list seed templates add ./template.tree --name my-template seed templates add ./template.seed --name service-template seed templates show my-template seed templates use my-template target-folder seed templates versions my-template --add ./updated.tree --name v2 seed templates lock my-template seed templates update my-template seed templates remove my-template
seed templates list also shows project-local templates discovered from
.seed/templates/project/, before global registry templates. seed templates use <name> <folder> resolves a visible project template first, then falls back
to the global registry. The singular alias seed template use ... is also
accepted.
Built-in templates include fastapi, python-package, and node-typescript.
Template Content Sources
Templates can point at a local directory, a GitHub tree URL, or a git
repository URL so seed can fetch real file contents alongside the structure
spec. Repository sources are cloned without their .git metadata.
seed templates add ./fastapi --name fastapi \ --content-url https://github.com/tiangolo/full-stack-fastapi-template/tree/master/backend/app seed templates add ./service.seed --name service \ --content-url https://github.com/acme/service-skeleton.git seed templates update fastapi seed templates update --all seed templates update fastapi --content-url /path/to/local/files
Templates that include a source.json file with {"content_url": "..."} are
fetched automatically when installed. .seed directory nodes can also declare
their own content sources inline:
vendor/
└── api/ !service +remote -> https://github.com/acme/api-client.git
Copier-Style Scaffolding
seed templates use supports template config files named copier.yml,
copier.yaml, .seed-template.yml, or .seed-template.yaml.
Supported workflow features include:
- promptable questions and defaults
--data-filefor JSON/YAML answers--defaultsand--non-interactive--answers-fileor_answers_file_excludeand_skip_if_exists_tasks, which only execute with--unsafe--overwritefor existing files
Example:
seed templates use python-package \ --base ./myapp \ --data-file answers.yml \ --defaults \ --answers-file .seed/answers.yml \ --overwrite
If a template defines _tasks, they are shown but skipped unless you opt into
execution:
seed templates use python-package --unsafe
Repository & System Maintenance
seed maintain orchestrates repository, service, system, and project upkeep
from YAML or JSON manifests.
Built-in maintenance goals include:
- repositories:
ensure_path,git_fetch,git_status,git_pull_ff_only - services:
ensure_paths,compose_pull,compose_up,launchctl_restart - custom actions with
tool,args,cwd,env, or shell commands
You can point seed maintain at a manifest file or a directory containing
maintenance.yml, project.yml, or service.yml.
Workspace Manifest
targets: - name: seed-cli kind: repository path: ./repos/seed-cli goals: - ensure_path - git_fetch - git_status - name: notes-api kind: service path: ./systems/services/notes-api config_dir: ./systems/services/notes-api/config data_dir: ./local/services/notes-api compose_file: compose.yml deploy_engine: docker-compose launch_agent: user/com.example.notes-api goals: - ensure_paths - compose_pull - compose_up - launchctl_restart
project.yml
name: product-x type: project path: ~/work/projects/active/product-x maintenance: goals: - git_fetch - git_status repos: - name: web-app path: repos/web-app - name: api path: repos/api
service.yml
name: notes-api type: service path: ~/systems/services/notes-api config_dir: ~/systems/services/notes-api/config data_dir: ~/local/services/notes-api compose_file: compose.yml deploy_engine: docker-compose launch_agent: user/com.example.notes-api maintenance: goals: - ensure_paths - compose_pull - compose_up - launchctl_restart actions: - tool: python args: ["scripts/rebuild_index.py"] cwd: "{{path}}"
Run the planner first, then execute:
seed maintain ./workspace seed maintain ./workspace --execute
Snapshots, Spec History, and Locks
Snapshots are created automatically before apply, sync, and match:
seed revert --list seed revert seed revert abc123 --dry-run
Applied structures are also captured as versioned specs:
seed specs list seed specs show seed specs diff v1 v3 seed specs watch
seed specs watch polls the workspace and writes a new .seed/specs/vN.tree
whenever the filesystem structure changes, so manual file creation after an
initial apply advances the internal reference automatically.
Lock a filesystem structure and watch it for drift:
seed lock set spec.tree
seed lock list
seed lock status
seed lock watch
seed lock upgrade v2 --dry-run
seed lock downgrade v1 --dangerousExport, Hooks, and Utilities
Export current state or a plan:
seed export tree --out structure.tree seed export json --out structure.json seed export dot --out structure.dot seed plan spec.tree --dot > plan.dot
Install git hooks:
seed hooks install seed hooks install --hook pre-push
Utilities:
seed utils extract-tree screenshot.png --out spec.tree seed utils state-lock seed utils state-lock --force-unlock
Shell Autocomplete
Click provides shell completion for Bash, Zsh, and Fish. Generate the completion
script from the installed seed entry point:
# zsh eval "$(_SEED_COMPLETE=zsh_source seed)" # bash eval "$(_SEED_COMPLETE=bash_source seed)" # fish _SEED_COMPLETE=fish_source seed | source
Then reload your shell and use tab completion:
seed <TAB> seed templates <TAB> seed lock <TAB>
Safety Model
seed is designed to be safe by default:
- destructive workflows require explicit dangerous flags
- execution state is lock-protected with heartbeat renewal
- plans are validated before writes and deletes
- template tasks require explicit
--unsafe - answers files and execution targets are constrained to the base directory
- git maintenance refuses
git pull --ff-onlyon dirty worktrees
Philosophy
seed-cli is:
- Declarative
- Deterministic
- Auditable
- Safe by default
License
Modified MIT. See LICENSE.md.
