Intelligent, Composable Primitives for Infrastructure.
Build infrastructure using composable primitives in Python - intelligence handles the parts you find tedious, you control what matters.
Clockwork provides intelligent primitives that adapt to how you want to work.
The insight: What's tedious is personal.
- Some people love writing container configs, others just want containers running
- Some enjoy crafting nginx rules, others prefer describing requirements
- Some care about specific image versions, others just need something that works
Your choice:
- Specify everything → Full control, zero intelligence
- Specify key details → Intelligence fills gaps
- Describe what you need → Intelligence handles implementation
Clockwork gives you flexibility to work how you prefer, on what you prefer.
flowchart LR
A[main.py<br/>Pydantic Models] --> B[Load]
B --> C[Complete<br/>Intelligence]
C --> D[Pulumi Compile]
D --> E[Deploy]
Same primitive, different levels of control - you choose per resource:
Full control (No intelligence):
nginx = AppleContainerResource(
description="Nginx web server",
name="my-nginx",
image="nginx:1.25-alpine",
ports=["8080:80"],
volumes=["/configs:/etc/nginx"]
)
# You specified everything - intelligence does nothingHybrid (Intelligence assists):
nginx = AppleContainerResource(
description="web server with caching enabled",
ports=["8080:80"] # You care about the port
# Intelligence picks image, generates config with caching
)Fast (Intelligence handles implementation):
nginx = AppleContainerResource(
description="web server for static files",
assertions=[HealthcheckAssert(url="http://localhost:8080")]
)
# Intelligence handles everything, assertions verify behaviorNo custom DSL. No YAML files. Just Python with adjustable intelligent assistance.
- Pure Python: No custom DSL or YAML, just Pydantic models
- Composable: Mix and match primitives like building blocks
- Flexible: You choose how much intelligence handles vs how much you specify
- Intelligent: Intelligence-powered completion adapts to your needs
- Functionally Deterministic: Assertions validate behavior, ensuring reliable outcomes
- Type-safe: Full IDE support with Pydantic validation
- Composite Resources: Build higher-level abstractions by composing basic resources into reusable groups
Before getting started, ensure you have:
- Python 3.12 or higher - Required for modern Python features
- uv package manager - Fast Python package installer and resolver
- Git - For cloning the repository
- Apple Containers (macOS) - For container resources
First, install the uv package manager if you don't have it:
curl -LsSf https://astral.sh/uv/install.sh | shuv tool install git+https://github.com/kessler-frost/clockworkThis installs clockwork as a global CLI tool. Create your main.py and start building (see Quick Start below).
In your main.py:
from clockwork.resources import FileResource
article = FileResource(
name="article.md",
description="Write about the Fibonacci sequence and its mathematical properties",
directory="output"
)Create a .env file:
# Get a free API key from OpenRouter: https://openrouter.ai/keys
# Or use LM Studio locally (set CW_BASE_URL=http://localhost:1234/v1, no key needed)
# For local models, qwen/qwen3-coder-30b works exceptionally well
CW_API_KEY=your-api-key-here
CW_MODEL=meta-llama/llama-4-scout:free # Free tier model
# See Configuration section below for all optionsDeploy:
uv run clockwork applyfrom clockwork.resources import FileResource, AppleContainerResource
from clockwork.assertions import HealthcheckAssert
# Intelligently-generated content
article = FileResource(
name="game_of_life.md",
description="Write about Conway's Game of Life",
directory="scratch"
)
# User-provided content
readme = FileResource(
name="README.md",
content="# My Project\n\nGenerated with Clockwork!",
directory="scratch"
)
# Container with health check
nginx = AppleContainerResource(
description="web server for static files",
ports=["8080:80"],
assertions=[HealthcheckAssert(url="http://localhost:8080")]
)uv run clockwork applyAfter your first deployment:
- Explore other resources: Try
AppleContainerResource,GitRepoResource - Add assertions: Validate your deployments with
HealthcheckAssert,PortAccessibleAssert - Connect resources: Use
.connect()to link services with automatic configuration - Build composites: Group related resources with
BlankResourcefor reusable patterns - Check examples: Browse
examples/directory for real-world patterns
Run uv run clockwork --help to see all available commands.
Currently available:
Creates files with optional intelligently-generated content.
FileResource(
name="article.md",
description="About...", # what intelligence should write
directory="path/to/dir", # where to create
content=None, # if set, skips completion
mode="644" # file permissions
)Clockwork provides container resources for macOS:
| Resource | Platform | Runtime |
|---|---|---|
AppleContainerResource |
macOS only | Apple Containers CLI (native runtime) |
Supports intelligence-powered image suggestion when image is not specified (e.g., nginx:alpine, redis:alpine).
Example Usage:
resource = AppleContainerResource(
name="web-server",
description="A lightweight web server for testing and demos",
ports=["8080:80"] # Host port 8080 -> Container port 80
)Clones and manages Git repositories with optional intelligently-suggested repository URLs. Automatically clones repositories and keeps them updated.
GitRepoResource(
name="fastapi-repo",
description="FastAPI Python web framework repository",
dest="./repos/fastapi" # Where to clone
)Intelligence-Powered: When repo_url is not specified, intelligence suggests appropriate repository URLs (e.g., official GitHub repositories).
Smart Defaults: Intelligence picks sensible values for branch (main/master) and destination directory if not specified.
Key Properties:
repo_url: Git repository URL (e.g.,https://github.com/tiangolo/fastapi.git)dest: Destination directory for cloning (e.g.,./repos/fastapi)branch: Git branch to checkout (e.g.,main,master,develop)pull: Update repository if it already exists (default:True)
Use Cases:
- Clone dependencies or third-party libraries
- Set up project scaffolding from template repositories
- Download configuration or data repositories
- Maintain local mirrors of remote repositories
Validate deployed resources with type-safe assertion classes:
from clockwork.assertions import (
HealthcheckAssert,
PortAccessibleAssert,
ContainerRunningAssert,
)
nginx = AppleContainerResource(
name="nginx-web",
ports=["8080:80"],
assertions=[
ContainerRunningAssert(),
PortAccessibleAssert(port=8080),
HealthcheckAssert(url="http://localhost:8080"),
]
)Run assertions:
uv run clockwork assertAvailable Assertion Classes:
- HTTP/Network:
HealthcheckAssert,PortAccessibleAssert - Container:
ContainerRunningAssert - File:
FileExistsAssert,FileContentMatchesAssert
All assertions are type-safe, Pydantic-based validators with no completion costs.
All commands must be run from the clockwork directory where your main.py is located.
Discovering Commands: Use --help to explore available commands and options:
# Show all available commands
uv run clockwork --help
# Show options for a specific command
uv run clockwork apply --help
uv run clockwork destroy --help
uv run clockwork assert --helpAvailable Commands:
# Full deployment
uv run clockwork apply
# Plan resources without deploying
uv run clockwork plan
# Validate deployed resources
uv run clockwork assert
# Destroy deployed resources (removes working directories by default)
uv run clockwork destroy
# Destroy but keep working directories created by resources
uv run clockwork destroy --keep-files
# Custom model
uv run clockwork apply --model "anthropic/claude-haiku-4.5"
# Show version
uv run clockwork versionDeclare dependencies between resources for proper deployment ordering and intelligence-powered auto-configuration.
How it works:
from clockwork.resources import AppleContainerResource
# Create independent resources
postgres = AppleContainerResource(
name="postgres-db",
description="PostgreSQL database",
image="postgres:15-alpine",
ports=["5432:5432"]
)
redis = AppleContainerResource(
name="redis-cache",
description="Redis cache",
image="redis:7-alpine",
ports=["6379:6379"]
)
# Connect API to dependencies (chained)
api = AppleContainerResource(
name="api-server",
description="FastAPI backend with database and cache",
ports=["8000:8000"]
).connect(postgres).connect(redis)
# Result: postgres and redis deploy before api
# Intelligence auto-generates DATABASE_URL and REDIS_URL environment variablesBenefits:
- Automatic Deployment Ordering: Resources deploy in dependency order (topological sort)
- Intelligence Context Awareness: Connected resources share context (name, image, ports, env vars)
- Auto-Configuration: Intelligence generates connection strings, URLs, and configuration
- Cycle Detection: Prevents circular dependencies before deployment
- Independent Lifecycles: Each resource can be updated/destroyed separately
See examples/composite-resources/ for examples showing resource connections within composites.
Build reusable groups of related resources with BlankResource - organize infrastructure into logical units with atomic lifecycle management.
from clockwork.resources import BlankResource, AppleContainerResource
# Create a composite web application
webapp = BlankResource(
name="webapp",
description="Web application with database and cache"
).add(
AppleContainerResource(name="db", image="postgres:15-alpine", ports=["5432:5432"]),
AppleContainerResource(name="cache", image="redis:7-alpine", ports=["6379:6379"]),
AppleContainerResource(name="api", description="API server", ports=["8000:8000"])
)
# Access and modify children
webapp.children["db"].ports = ["5433:5432"]
webapp.children["api"].connect(webapp.children["db"], webapp.children["cache"]).add() - Composition (atomic lifecycle):
- Resources deploy/destroy together as one unit
- Organized under single parent in Pulumi hierarchy
- Use for: resources that belong together (app + config + db)
.connect() - Dependencies (independent lifecycle):
- Resources deploy in dependency order
- Intelligence receives context for auto-configuration
- See Resource Connections section above for details
Accessing Children:
# Dict-style access
db = webapp.children["db"]
# Safe access
maybe_cache = webapp.children.get("cache")
# Iterate
for name, resource in webapp.children.items():
print(f"{name}: {resource.image}")See examples/composite-resources/ for detailed examples:
- simple-webapp/ - Basic composition patterns
- nested-composites/ - Hierarchical structures
- mixed-pattern/ - Combining
.add()and.connect() - post-creation-overrides/ - Modifying after composition
Clockwork uses .env files for configuration via Pydantic Settings.
For a minimal setup, see the Quick Start section above. For all available options, see the table below.
| Setting | Default | Description |
|---|---|---|
CW_API_KEY |
None | API key (required for cloud models) |
CW_MODEL |
meta-llama/llama-4-scout:free |
Model for intelligent completion (default, free). Recommended upgrade: anthropic/claude-haiku-4.5 for better quality |
CW_BASE_URL |
https://openrouter.ai/api/v1 |
API endpoint (OpenRouter, LM Studio, etc.) |
CW_COMPLETION_MAX_RETRIES |
3 |
Maximum retry attempts for intelligent resource completion |
CW_PULUMI_CONFIG_PASSPHRASE |
clockwork |
Pulumi passphrase for state encryption (also accepts PULUMI_CONFIG_PASSPHRASE) |
CW_LOG_LEVEL |
INFO |
Logging level |
Override via CLI:
uv run clockwork apply --model "anthropic/claude-haiku-4.5"State Management: Pulumi stores state in ~/.pulumi/ directory (user's home directory) when using the Automation API. This state tracks all deployed resources and their configurations.
Model Requirements: Models must support tool calling (function calling). Most modern models from OpenRouter, OpenAI, Anthropic, and local models served via LM Studio support this feature.
Local Model Recommendation: For local inference via LM Studio, qwen/qwen3-coder-30b provides excellent results. When using LM Studio (http://localhost:1234), Clockwork automatically loads your specified model - no manual loading required.
Platform-Specific Resources:
- AppleContainerResource: macOS only - requires Apple Containers CLI
- Questions & Discussions: GitHub Discussions - Ask questions, share ideas, and discuss best practices
- Bug Reports & Feature Requests: GitHub Issues - Report bugs or request new features
- Contributing: See Development section below for setup instructions
Make sure you're in the clockwork directory, then explore these examples:
# Composite resources - Grouping and hierarchical structures
# Demonstrates: BlankResource, .add() composition, nested composites
cd examples/composite-resources/simple-webapp
uv run clockwork apply
uv run clockwork assert
uv run clockwork destroy
# Nested composites - Hierarchical resource structures
cd examples/composite-resources/nested-composites
uv run clockwork plan
# Mixed patterns - Combining .add() and .connect()
cd examples/composite-resources/mixed-pattern
uv run clockwork plan
# File connections - Demonstrates FileConnection patterns
cd examples
uv run python file-connection-example.pySee examples/composite-resources/ directory for more patterns and documentation.
# Install dependencies including dev tools
uv sync --all-groups
# Install pre-commit hooks
uv run pre-commit install
# Run pre-commit on all files (optional)
uv run pre-commit run --all-files
# Run tests
uv run pytest tests/ -v
# Lint and format code
uv run ruff check --fix .
uv run ruff format .
# Clean up example outputs
rm -rf scratch/This project uses pre-commit with Ruff for code quality:
- Ruff linter: Checks code for errors, style issues, and import sorting
- Ruff formatter: Formats code according to Google Python Style Guide
- Standard hooks: Trailing whitespace, EOF fixing, YAML/TOML validation
After installation, hooks run automatically on git commit. To run manually:
uv run pre-commit run --all-filesSee ROADMAP.md for upcoming features.