Environment Initialization¶
The init command is the core engine of Protostar. It is not a glorified mkdir script; it is a deterministic state-machine designed to safely aggregate configurations, wire complex development tooling together, and construct robust directory architectures in seconds.
Protostar is designed to be run on Day 1 to build your repository's foundation, but it is perfectly safe to re-run on Day 50 to inject a forgotten dependency or adopt a new static analysis tool.
-
State-Aware Aggregation
Protostar doesn't just blindly overwrite files. It parses ASTs, deduplicates
.gitignoreentries, and safely merges configurations. It is perfectly safe to execute on pre-existing codebases. -
Deterministic Velocity
Instead of manually copying boilerplate from old repositories or relying on fragile bash scripts, Protostar guarantees a consistent, idempotent environment. It resolves your exact requested state in a fraction of a second, eliminating configuration drift and forgotten dependencies.
Execution Footprints¶
To understand how Protostar interprets your flags, observe what happens when we execute different domain workflows in an empty directory. Notice how the orchestrator automatically routes tooling configurations, isolates data artifacts, and binds dependencies.
IDE Configuration Footprints
The following repository tree examples assume you have explicitly configured an IDE in your global settings (e.g., ide = "vscode") in addition to globally enabling direnv. This represents the best practice configuration for vscode users scaffolding python environments. If your config remains set to the default None, the .vscode/settings.json file will not be generated, though the universal .vscode/ exclusion will still be safely appended to your .gitignore.
Command: protostar init --python --cli --mypy --pytest --pre-commit --markdownlint
This footprint demonstrates Protostar's ability to wire complex tooling together automatically.
.
├── .gitignore
├── .markdownlint.yaml
├── .pre-commit-config.yaml
├── .python-version
├── pyproject.toml
├── src
├── tests
└── uv.lock
See the generated .gitignore
See the generated .markdownlint.yaml
# Inherit default rules
default: true
# --- Disabled Rules ---
# MD013: Line length
# Rationale: Hard-wrapping text disrupts IDE reading flow, breaks URLs, and creates arbitrary diff churn.
MD013: false
# MD033: Inline HTML
# Rationale: Required for layout elements unsupported by strict Markdown (e.g., <details> blocks, complex tables).
MD033: false
# --- Refined Rules ---
# MD024: Multiple headings with the same content
# Rationale: Allows duplicate subheadings (e.g., "Parameters") under different primary function headings.
MD024:
siblings_only: true
# --- AST/Parser Enforcement ---
# MD031: Fenced code blocks should be surrounded by blank lines
# Rationale: Prevents strict parsers from rendering backticks as raw text instead of <pre><code> blocks.
MD031: true
# MD032: Lists should be surrounded by blank lines
# Rationale: Prevents contiguous text from merging into lists, ensuring correct AST generation.
MD032: true
# --- Structural Consistency ---
# MD003: Heading style
# Rationale: Enforces ATX style (# Heading) exclusively.
MD003:
style: "atx"
# MD004: Unordered list style
# Rationale: Enforces dash markers for consistency across the syntax tree.
MD004:
style: "dash"
# MD009: Trailing spaces
# Rationale: Allows exactly two spaces for hard line breaks; flags arbitrary whitespace.
MD009:
br_spaces: 2
strict: false
# MD029: Ordered list item prefix
# Rationale: Enforces the "one" style (1., 1., 1.) to minimize Git diff noise when rearranging list items.
MD029:
style: "one"
See the generated .pre-commit-config.yaml
repos:
# 1. Generic hooks (configured to ignore Python to avoid formatting conflicts)
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
exclude: \.py$
- id: end-of-file-fixer
exclude: \.py$
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.48.0
hooks:
- id: markdownlint
args: ["--fix"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.11
hooks:
- id: ruff-format
- id: ruff
args: [ --fix ]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.20.1
hooks:
- id: mypy
additional_dependencies:
- typer
- rich
- ruff
- mypy
- pytest
- pytest-cov
- pytest-mock
- pre-commit
See the generated pyproject.toml
[project]
name = "demo-project"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"rich>=15.0.0",
"typer>=0.24.1",
]
[tool.ruff]
line-length = 88
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"UP", # pyupgrade
"RUF", # ruff-specific rules
]
ignore = []
[tool.mypy]
python_version = "3.13"
strict = true
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
[tool.pytest.ini_options]
minversion = "7.0"
addopts = "-ra -q --strict-markers"
testpaths = [
"tests",
]
[dependency-groups]
dev = [
"mypy>=1.20.1",
"pre-commit>=4.5.1",
"pytest>=9.0.3",
"pytest-cov>=7.1.0",
"pytest-mock>=3.15.1",
"ruff>=0.15.11",
]
The Intelligence:
- Dependency Locking: Protostar instantly locked
typerandrichfrom the CLI preset. - AST Configuration: It didn't just dump strings into
pyproject.toml. It constructed the TOML Abstract Syntax Tree (AST), gracefully configuring[tool.ruff],[tool.mypy], and[tool.pytest.ini_options]alongside the dev-dependencies. - Dynamic Hooks: In
.pre-commit-config.yaml, Protostar didn't just add a genericmypyhook. It dynamically evaluated your environment footprint and injected your CLI dependencies directly into Mypy'sadditional_dependenciesblock. This guarantees your CI pipeline won't fail due to missing stubs. - A Note on Speed: Standard Protostar executions take fractions of a second. However, because
--pre-commitwas flagged, Protostar queued apre-commit autoupdatesubprocess at the end of the run to ensure your git hooks are pinned to the absolute latest network releases. This shifts the total execution time to roughly ~4-9 seconds.
Command: protostar init --python --astro
This footprint focuses on managing heavy, serialized data assets and preventing repository bloat.
.
├── .gitattributes
├── .gitignore
├── .python-version
├── data
│ ├── catalogs
│ └── fits
├── notebooks
├── pyproject.toml
├── src
└── uv.lock
See the generated .gitattributes
See the generated .gitignore
See the generated pyproject.toml
[project]
name = "demo-project"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"astropy>=7.2.0",
"astroquery>=0.4.11",
"matplotlib>=3.10.8",
"nbdime>=4.0.4",
"numpy>=2.4.4",
"pandas>=3.0.2",
"photutils>=3.0.0",
"scipy>=1.17.1",
"specutils>=2.3.0",
]
[tool.ruff]
line-length = 88
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"UP", # pyupgrade
"RUF", # ruff-specific rules
]
ignore = []
[dependency-groups]
dev = [
"ruff>=0.15.11",
]
The Intelligence:
- Directory Scaffolding: It dynamically injected
data/catalogsanddata/fits, automatically isolating your telemetry and catalogs from the source code. - Binary Safety: It generated a
.gitattributesfile explicitly marking*.fitsfiles as binary, and configuring*.ipynbfor better text diffing. - Notebook Diffing: It automatically configured
nbdimeat the git level, saving you from parsing unreadable JSON diffs when tracking Jupyter Notebooks. - Artifact Exclusions: The
.gitignorewas populated with*.fits,*.csv, and*.parquet, preventing you from accidentally committing massive telemetry cubes to version control.
Command: protostar init --python --ml --docker
This footprint focuses on containerization and strictly excluding model artifacts.
.
├── .dockerignore
├── .gitignore
├── .python-version
├── data
├── models
├── notebooks
├── pyproject.toml
├── src
└── uv.lock
See the generated .dockerignore
See the generated .gitignore
See the generated pyproject.toml
[project]
name = "demo-project"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"huggingface-hub>=1.11.0",
"scikit-learn>=1.8.0",
"torch>=2.11.0",
"tqdm>=4.67.3",
]
[tool.ruff]
line-length = 88
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"UP", # pyupgrade
"RUF", # ruff-specific rules
]
ignore = []
[dependency-groups]
dev = [
"ruff>=0.15.11",
]
The Intelligence:
- Context Generation: Because
--dockerwas flagged, Protostar read the computed VCS ignores from the ML environment and generated a highly optimized.dockerignore. It strips out.venv,.git, local caches, and test artifacts to keep your container build context incredibly lightweight. - Model Checkpoints: The ML preset aggressively injects ignores for tensor artifacts (
*.pth,*.pt,*.onnx,*.safetensors) and experiment tracking directories (wandb/,mlruns/) to ensure massive model weights never pollute the git tree.
The Python Gravity Well
Protostar is engineered specifically to accelerate Python development pipelines. Its Python scaffolding (specifically leveraging uv) is highly refined, deeply integrated, and serves as the exclusive focus of the engine.
Progressive Scaffolding & Collisions¶
Developers are rightfully terrified of CLI tools that touch their existing configurations. Protostar is engineered specifically to alleviate this anxiety.
Lets say you initialized a machine learning repo yesterday with protostar init --python --ml --docker
But today you remembered you'll be doing quasar analysis, and you want to enforce strict typing with mypy
You simply run protostar init --python --astro --mypy --docker in that existing directory.
Because Protostar detects existing configuration markers (like pyproject.toml), it instantly halts the execution and triggers the Gravitational Anomaly intercept prompt:
Protostar Ignition Sequence Initiated
Gravitational Anomaly: Protostar detected existing configuration files in the workspace.
- pyproject.toml
? How would you like to proceed?
» Merge (Safely injects missing configs; preserves existing user data)
Overwrite (Forces injection; updates existing keys to match Protostar)
Abort (Safely exit without modifying the environment)
If you select Merge, Protostar performs a surgical AST injection.
- It leaves your existing
torchandhuggingface-hubdependencies completely untouched. - It alphabetically merges in
astropy,photutils, andspecutils. - It seamlessly drops the
[tool.mypy]configuration block into the TOML file. - It appends
*.fitsand.mypy_cache/to your existing.gitignore.
See the comparison
[project]
name = "demo-project"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"huggingface-hub>=1.11.0",
"scikit-learn>=1.8.0",
"torch>=2.11.0",
"tqdm>=4.67.3",
]
[tool.ruff]
line-length = 88
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"UP", # pyupgrade
"RUF", # ruff-specific rules
]
ignore = []
[dependency-groups]
dev = [
"ruff>=0.15.11",
]
[project]
name = "demo-project"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"astropy>=7.2.0",
"astroquery>=0.4.11",
"huggingface-hub>=1.11.0",
"matplotlib>=3.10.8",
"nbdime>=4.0.4",
"numpy>=2.4.4",
"pandas>=3.0.2",
"photutils>=3.0.0",
"scikit-learn>=1.8.0",
"scipy>=1.17.1",
"specutils>=2.3.0",
"torch>=2.11.0",
"tqdm>=4.67.3",
]
[tool.ruff]
line-length = 88
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"UP", # pyupgrade
"RUF", # ruff-specific rules
]
ignore = []
[tool.mypy]
python_version = "3.13"
strict = true
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
[dependency-groups]
dev = [
"mypy>=1.20.1",
"ruff>=0.15.11",
]
Curious how Protostar safely merges a pyproject.toml without breaking existing keys or stripping your comments? Read the Mechanics: Executor deep dive.
Strict Footprint Validation
Protostar enforces explicit dependency boundaries for all tooling operations. If you pass an impossible or conflicting configuration matrix via the CLI, Protostar will not crash or dump inert configurations into your repository. It evaluates the topological constraints, drops the invalid tool, and prints a clean diagnostic warning before proceeding with the rest of the valid scaffolding sequence.
The Capabilities Matrix¶
You can mix and match these flags to generate exactly the environment you need. To view this matrix in your terminal at any time, run protostar help init.