seed-cli logo

seed-cli

Declarative filesystem management for developers

seed-cli

Terraform for your filesystem

Define, version, and replicate directory structures declaratively

Browse Recipes →

Declarative

Define your filesystem structure in simple, readable spec files

Snapshots

Capture and restore directory states at any point in time

Versioning

Track changes, lock versions, and safely upgrade structures

Templates

Reusable specs with variables for consistent project scaffolding


Quick Start

1. Install

pip install seed-cli

2. Capture existing structure

seed capture --out project.tree

3. Preview changes

seed plan project.tree

4. Apply the spec

seed apply project.tree

Global Options

Available on all commands:

seed [command] --verbose          # Enable verbose logging
seed [command] --debug            # Enable debug logging
seed [command] --ignore PATTERN   # Extra ignore patterns (glob)
seed [command] --targets PATTERN  # Extra targets (glob)
seed [command] --target-mode {prefix,exact}  # Target matching mode

Core Commands

seed plan <spec>

Parse spec and generate execution plan. Runs plugin parse + plan lifecycle and outputs the planned changes without modifying the filesystem.

--base BASE Base directory (default: current directory)
--vars VARS Template variables (key=value)
--out OUT Output plan to file (JSON format)
--dot Output plan as Graphviz DOT format
--no-skip Hide SKIP lines in output for cleaner view
# Preview what would be created
seed plan project.tree

# With template variables
seed plan project.tree --vars environment=prod

# Export plan as JSON
seed plan project.tree --out plan.json

# Export as Graphviz DOT
seed plan project.tree --dot > plan.dot

seed apply <spec>

Acquire state lock, run hooks (pre_apply, post_apply), execute plan, and run plugin build lifecycle. Creates files and directories as specified.

--base BASE Base directory (default: current directory)
--dangerous Allow dangerous operations
--dry-run Show what would be executed without making changes
--yes, -y Create all optional items (marked with ?) without prompting
--skip-optional Skip all optional items (marked with ?) without prompting
# Apply spec to current directory
seed apply project.tree

# Apply to specific directory
seed apply project.tree --base ./myproject

# Preview without making changes
seed apply project.tree --dry-run

# Auto-create all optional items
seed apply project.tree --yes

# Skip all optional items
seed apply project.tree --skip-optional

seed diff <spec>

Compare spec with filesystem and show missing, extra, and drifted paths. Useful for detecting drift from your intended structure.

--base BASE Base directory (default: current directory)
--ignore PATTERN Ignore paths matching pattern (can be repeated)
--no-sublevels Hide extras inside directories defined in the spec
# Compare spec with current directory
seed diff project.tree

# Ignore certain patterns
seed diff project.tree --ignore "*.pyc" --ignore "__pycache__"

# Only show top-level extras
seed diff project.tree --no-sublevels

seed capture

Capture current filesystem state as a spec file. Useful for creating initial specs from existing projects.

--base BASE Base directory (default: current directory)
--json Output in JSON format
--dot Output in Graphviz DOT format
--out OUT Output file path (prints to stdout if not specified)
# Capture to file
seed capture --out project.tree

# Capture specific directory
seed capture --base ./src --out src.tree

# Output as JSON
seed capture --json --out project.json

# Output as Graphviz DOT
seed capture --dot --out project.dot

seed create <spec> <values...>

Create a new instance of a template directory structure. Use with specs containing <varname>/ template patterns.

--base BASE Base directory (default: current directory)
--dry-run Preview what would be created
# Create new version directory from template
seed create releases.tree version_id=v3

# Preview without creating
seed create releases.tree version_id=v3 --dry-run

# Multiple variables
seed create project.tree name=myapp env=production

Sync & Match

These commands modify the filesystem to match your spec exactly, including deleting extra files. Use with caution.

seed sync <spec> dangerous

Same as apply, but also deletes extraneous files. Plugins may veto deletions. Requires --dangerous flag.

--base BASE Base directory (default: current directory)
--dangerous Required flag to enable sync (not required with --dry-run)
--dry-run Show what would be executed without making changes
--yes, -y Create all optional items (marked with ?) without prompting
--skip-optional Skip all optional items (marked with ?) without prompting
# Preview what would be synced
seed sync project.tree --dry-run

# Actually sync (deletes extra files!)
seed sync project.tree --dangerous

# Sync with auto-create optionals
seed sync project.tree --dangerous --yes

seed match <spec> dangerous

Modify filesystem to match the spec. Creates missing items and deletes extras. Use ... in spec to mark directories where extra files are allowed.

--base BASE Base directory (default: current directory)
--dangerous Required flag (will create/delete files). Not required with --dry-run
--dry-run Preview changes without modifying filesystem
--yes, -y Create all optional items (marked with ?) without prompting
--skip-optional Skip all optional items (marked with ?) without prompting
# Preview what would change
seed match project.tree --dry-run

# Match filesystem to spec (creates and deletes!)
seed match project.tree --dangerous

# Match specific directory
seed match project.tree --base ./target --dangerous

Protecting Directories from Deletion

Use ... to mark directories where extra files should be preserved:

project/
├── src/
│   └── main.py
├── data/       ...   # Extra files here won't be deleted
└── config.yaml

Spec Syntax

Spec files use an intuitive tree-like syntax. Supports .tree, .yaml, .json, .dot, and even images.

Basic Structure

project/
├── src/
│   ├── main.py
│   └── utils/
│       └── helpers.py
├── tests/
│   └── test_main.py
├── config.yaml
└── README.md

Annotations

scripts/
├── build.py      @generated
├── config.json   @manual
├── cache/        ...
└── docs/?

Template Variables

Create reusable specs with dynamic values:

<project_name>/
├── src/
│   └── <module_name>/
│       └── __init__.py
├── <environment>/
│   └── config.yaml
└── README.md

Using Variables

# With seed plan/apply
seed apply spec.tree --vars project_name=myapp module_name=core

# With seed create
seed create spec.tree project_name=myapp environment=prod

Includes

Import other spec files to compose larger structures:

@include base.tree
@include ./shared/common.tree

project/
├── custom/
└── specific.py

Template Registry

Manage reusable spec templates from GitHub or local sources.

seed templates add <source>

Add a template from GitHub URL or local file path. Supports fetching real file contents from a content source.

--name, -n NAME Name for the template (default: derived from URL/filename)
--version, -v VERSION Version name (default: auto-increment)
--content-url URL Fetch file contents from a local path or GitHub tree URL
# From GitHub
seed templates add https://github.com/user/template-repo

# From local file
seed templates add ./my-templates/python-project.tree

# With custom name
seed templates add ./template.tree --name my-template

# With specific version
seed templates add ./template.tree --name my-template --version v1.0

# With content from GitHub
seed templates add ./fastapi --name fastapi \
  --content-url https://github.com/tiangolo/full-stack-fastapi-template/tree/master/backend/app

# With content from a local directory
seed templates add ./my-template --name myapp --content-url /path/to/local/files

seed templates list

List all stored templates with their versions and lock status.

seed templates list

seed templates use <name>

Apply a template to the filesystem. Creates the directory structure defined in the template.

--version, -v VERSION Version to use (default: current)
--base BASE Base directory (default: current directory)
--vars VARS Template variables (key=value)
--yes, -y Apply without prompting
--dry-run Show plan without applying
# Use template in current directory
seed templates use python-project

# Use in specific directory
seed templates use python-project --base ./myproject

# With variables
seed templates use python-project --vars name=myapp version=1.0

# Preview without applying
seed templates use python-project --dry-run

# Use specific version
seed templates use python-project --version v2

seed templates show <name>

Show the content of a template.

--version, -v VERSION Version to show (default: current)
# Show current version
seed templates show python-project

# Show specific version
seed templates show python-project --version v1

seed templates versions <name>

Manage template versions. List versions, add new versions, or set current version.

--add PATH Add a new version from file
--name VERSION Name for the new version (with --add)
--set-current VERSION Set version as current
# List versions
seed templates versions python-project

# Add new version
seed templates versions python-project --add ./updated.tree --name v2

# Set current version
seed templates versions python-project --set-current v2

seed templates lock <name>

Lock or unlock a template to prevent/allow updates.

--version, -v VERSION Version to set as current before locking
--unlock Unlock instead of lock
# Lock template
seed templates lock python-project

# Lock at specific version
seed templates lock python-project --version v1

# Unlock template
seed templates lock python-project --unlock

seed templates update <name>

Re-fetch content from a template's content source. Use --all to update every template that has a content URL. Use --content-url to change where content is fetched from.

--all Update all templates with content sources
--content-url URL Set a new content source (local path or GitHub tree URL)
# Re-fetch content for a template
seed templates update fastapi

# Update all templates
seed templates update --all

# Change content source
seed templates update myapp --content-url https://github.com/owner/repo/tree/develop/src

# Switch from GitHub to local directory
seed templates update myapp --content-url /path/to/local/files

seed templates remove <name>

Remove a template from the registry.

seed templates remove python-project

Content Sources (source.json)

Templates can include a source.json file that tells seed where to fetch real file contents from. When a template with a source.json is installed, seed automatically downloads the files.

{
  "content_url": "https://github.com/owner/repo/tree/main/src"
}

Content sources support both local directory paths and GitHub tree URLs. The built-in fastapi, python-package, and node-typescript templates ship with source.json and auto-fetch content on first use.

Changing a Template's Content Source

Use seed templates update with --content-url to point a template at a different source. This updates both meta.json and source.json in ~/.seed/templates/<name>/.

# Point to a different repo/branch
seed templates update myapp \
  --content-url https://github.com/owner/repo/tree/develop/src

# Switch to a local directory
seed templates update myapp --content-url /path/to/local/files

Versioning & Locking

Lock filesystem structures to a spec. Supports versioning and watch mode to prevent drift.

seed lock set <spec>

Set the active structure spec. Creates a version if needed.

--base BASE Base directory
--version, -v VERSION Version name (default: auto-increment)
# Set lock with auto-versioning
seed lock set project.tree

# Set lock with specific version name
seed lock set project.tree --version v1.0

# Set lock for specific directory
seed lock set project.tree --base ./myproject

seed lock watch

Watch filesystem and enforce structure continuously. Runs as a daemon to detect and report drift.

--base BASE Base directory
--interval INTERVAL Check interval in seconds
# Start watching with default interval
seed lock watch

# Watch with custom interval (every 5 seconds)
seed lock watch --interval 5

# Watch specific directory
seed lock watch --base ./myproject

seed lock list

List available structure versions.

--base BASE Base directory
seed lock list

seed lock status

Show current structure lock status including active version and any drift.

--base BASE Base directory
seed lock status

seed lock upgrade <version> dangerous

Upgrade to a newer structure version. Applies changes to bring filesystem to the new version.

--base BASE Base directory
--dangerous Apply changes (required)
--dry-run Preview changes
# Preview upgrade
seed lock upgrade v2 --dry-run

# Apply upgrade
seed lock upgrade v2 --dangerous

seed lock downgrade <version> dangerous

Downgrade to an older structure version.

--base BASE Base directory
--dangerous Apply changes (required)
--dry-run Preview changes
# Preview downgrade
seed lock downgrade v1 --dry-run

# Apply downgrade
seed lock downgrade v1 --dangerous

Snapshots & Specs History

Snapshots are created automatically before apply/match/sync operations. Use them to undo changes.

Revert Command

seed revert [snapshot_id]

Revert filesystem to a previous snapshot. Snapshots are created automatically before apply/match/sync operations.

--base BASE Base directory (default: current directory)
--list List available snapshots
--dry-run Preview what would be reverted
--delete ID Delete a specific snapshot
# List all snapshots
seed revert --list

# Revert to latest snapshot
seed revert

# Revert to specific snapshot
seed revert abc123

# Preview revert
seed revert abc123 --dry-run

# Delete a snapshot
seed revert --delete abc123

Specs History

View and manage automatically captured spec versions.

seed specs list

List all captured spec versions with timestamps and metadata.

--base BASE Base directory
seed specs list

seed specs show [version]

Show content of a spec version.

--base BASE Base directory
version Version to show (e.g., 1 or v1). Default: latest
# Show latest spec
seed specs show

# Show specific version
seed specs show v1
seed specs show 2

seed specs diff <v1> <v2>

Compare two spec versions to see what changed.

--base BASE Base directory
# Compare two versions
seed specs diff v1 v2
seed specs diff 1 3

Utilities

Doctor

seed doctor <spec>

Lint spec file and optionally auto-fix issues. Checks for syntax errors, invalid paths, and common mistakes.

--base BASE Base directory (default: current directory)
--fix Automatically fix issues when possible
# Check spec for issues
seed doctor project.tree

# Auto-fix issues
seed doctor project.tree --fix

Export

seed export <format>

Export filesystem state or plan in various formats: tree, json, plan, or dot.

--input INPUT Input spec or plan file (default: capture from filesystem)
--out OUT Output file path (required)
--base BASE Base directory (default: current directory)
# Export current filesystem as tree
seed export tree --out structure.tree

# Export as JSON
seed export json --out structure.json

# Export as Graphviz DOT
seed export dot --out structure.dot

# Export existing spec to different format
seed export json --input project.tree --out project.json

Hooks

seed hooks install

Install git hooks (e.g., pre-commit) to automatically validate filesystem structure on commits.

--hook HOOK Hook name to install (default: pre-commit)
# Install default pre-commit hook
seed hooks install

# Install specific hook
seed hooks install --hook pre-push

Utils

seed utils extract-tree <image>

Extract tree structure from an image using OCR. Useful for converting screenshots of directory structures into spec files.

--out OUT Output .tree file path (default: image path with .tree extension)
--vars VARS Template variables (key=value)
--raw Output raw OCR text without cleaning (for debugging)
# Extract from screenshot
seed utils extract-tree screenshot.png

# Specify output path
seed utils extract-tree screenshot.png --out project.tree

# Debug OCR output
seed utils extract-tree screenshot.png --raw

seed utils state-lock

Manage execution state locks for concurrent access control. Use if a process crashed and left a stale lock.

--base BASE Base directory
--renew Renew existing lock
--force-unlock Force unlock (use if process crashed)
# Check lock status
seed utils state-lock

# Force unlock after crash
seed utils state-lock --force-unlock

# Renew existing lock
seed utils state-lock --renew