Spec-driven code generation framework: write intent as decorated Python stubs, generate implementations and tests with LLMs.
Project description
Jaunt
William Blake, The Tyger, plate 42 from Songs of Experience (1794). The Metropolitan Museum of Art, Open Access.
Tyger Tyger, burning bright, In the forests of the night; What immortal hand or eye, Could frame thy fearful symmetry?
-- William Blake, via Alfred Bester's The Stars My Destination
Jaunt is a small Python library + CLI for spec-driven code generation:
- Write implementation intent as normal Python stubs decorated with
@jaunt.magic(...). - Optionally write test intent as stubs decorated with
@jaunt.test(...). - Jaunt generates real modules under
__generated__/using the OpenAI Codex CLI (codex exec) as its code-generation engine. - Async support is available for both implementation and test specs through
async defplus thebuild.async_runnersetting. @magicworks on individual class methods too — decorate instance methods,@classmethod,@staticmethod, or@abstractmethodstubs and Jaunt generates only those methods while preserving the rest of the class.- Incremental freshness tracks both module digests and exported dependency APIs, so signature changes, whole-class member changes, and contract docstring edits can invalidate dependents.
Two Modes
Jaunt supports two first-class authoring modes that coexist and are selected by decorator:
- Magic mode (
@jaunt.magic/@jaunt.test): the docstring is canonical and Jaunt generates implementations under__generated__/. - Contract mode (
@jaunt.contract): committed code is canonical and Jaunt derives a committed pytest battery undertests/contract/.
See examples/contract_slugify/ for a Contract-mode walkthrough.
Installation
pip install jaunt
# The base install is batteries-included (rich, watchfiles, pytest,
# pytest-asyncio, anyio). The only optional extra is the MCP server:
pip install 'jaunt[mcp]' # for jaunt mcp serve
# Jaunt drives the external OpenAI Codex CLI, which you install and
# authenticate separately:
# 1. Install the `codex` CLI (see the Codex docs).
# 2. Authenticate it: `codex login`.
Codex Engine
Codex is the sole code-generation engine: Jaunt drives codex exec for
all build/test/skill workflows. It requires the external codex binary on your
PATH, authenticated via codex login. Multi-provider routing is deferred.
Quickstart (This Repo)
Prereqs: uv installed.
uv sync
codex login # authenticate the Codex engine
uv run jaunt --version
For your own project, run tests with the source root importable, e.g. PYTHONPATH=src.
See docs-site/ for rendered docs, or DOCS.md for a plain-text walkthrough.
All examples live under examples/. See examples/README.md for the full list.
Your First Spec
jaunt init creates a starter src/specs.py like this:
import jaunt
@jaunt.magic()
def slugify(text: str) -> str:
"""Convert a string to a URL-safe slug: lowercase, collapse non-alphanumeric runs."""
...
@jaunt.test(targets=slugify)
def test_slugify() -> str:
"""Check words, punctuation, and surrounding spaces."""
...
uv run jaunt build
PYTHONPATH=src uv run jaunt test
Hackathon Demo (JWT Auth)
Headline demo: JWT auth (the "wow gap" example: short spec, real generated glue + tests).
# Generate implementations for @jaunt.magic specs.
uv run jaunt build --root examples/jwt_auth
# Generate pytest tests for @jaunt.test specs and run them.
PYTHONPATH=examples/jwt_auth/src uv run jaunt test --root examples/jwt_auth
For Coding Agents
Point any coding agent (Claude Code, Codex, Cursor, a bare shell, CI) at Jaunt with one command:
jaunt instructions # a tight, project-aware primer to load into context
jaunt instructions --json # {command, ok, text, project} for tooling/MCP
It prints the framework rules (the two modes, the build/test loop, how to write a good spec, the command + exit-code reference) followed by a live snapshot of the current project (resolved paths, engine/model, and which modules are stale). It ships with the package, so the briefing always matches the installed version. Run it before you start working.
Background Daemon
jaunt daemon start runs background codegen with commit-triggered isolated jobs
and auto-commit on green. jaunt daemon stop|status stops or inspects it.
Use jaunt jobs for job records, would-rebuild previews, show <id> [--full],
and retry <id>. jaunt log tails JAUNT_LOG (-n N, --module X), and
jaunt guard warns when agents touch __generated__ via the PreToolUse hook.
Freshness Model
- The full cleaned docstring is part of the spec contract, not just the first summary line.
- For whole-class
@jaunt.magicspecs, Jaunt treats the class signature plus declared members and method signatures as exported API. - Jaunt's freshness model uses that dependency API too, so an upstream contract change can mark downstream modules stale even if their own source file did not change.
Eval Suite
jaunt eval is deferred under the Codex engine (rework pending).
Prompt snapshots:
uv run pytest tests/test_prompt_snapshots.py --snapshot-update
Auto-Generate PyPI Skills (Build)
jaunt build includes a best-effort pre-build step that auto-generates “skills” for external libraries your project imports and injects them into the build prompt.
What happens:
- Scan
paths.source_rootsforimport .../from ... import ...(ignores stdlib, internal modules, and relative imports). - Resolve imports to installed PyPI distributions + versions from the current environment.
- Ensure a skill exists per distribution at:
<project_root>/.agents/skills/<dist-normalized>/SKILL.md
- If missing/outdated, fetch the exact PyPI README for
<dist>==<version>and generateSKILL.mdusing the Codex engine. - Inject the concatenated skills text into the build LLM prompt.
Overwrite rules:
- Jaunt only overwrites a skill if it was previously Jaunt-generated (it has a
<!-- jaunt:skill=pypi ... -->header) and the installed version changed. - If the header is missing, the file is treated as user-managed and will never be overwritten.
Failure mode: warnings to stderr, and the build continues without missing skills.
Docs Site (Fumadocs)
The repository includes a Fumadocs (Next.js) documentation site under docs-site/.
cd docs-site
npm run dev
Publish to PyPI
If you keep your token in .env as UV_PUBLISH_TOKEN=..., load it into your shell first:
set -a
source .env
set +a
Build and validate artifacts:
uv build
uvx twine check dist/*
Upload to PyPI:
uv publish --check-url https://pypi.org/simple/
Dev
uv run ruff check --fix .
uv run ruff format .
uv run ty check
uv run pytest
Final verification before pushing:
uv run ruff check .
uv run ruff format --check .
uv run ty check
uv run pytest
Why "Jaunt"?
Named after jaunting -- teleportation by thought alone -- from Alfred Bester's 1956 novel The Stars My Destination (originally published as Tiger! Tiger!). You think about where you want to be, and you're there.
Jaunt works the same way: describe your intent, and arrive at working code.
The forge-and-furnace imagery you'll find scattered through the codebase comes from William Blake's poem "The Tyger," which Bester used as the novel's epigraph and alternate title. The poem's vision of creation -- hammer, chain, furnace, anvil -- mirrors the act of forging code from pure specification.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jaunt-1.0.0rc6.tar.gz.
File metadata
- Download URL: jaunt-1.0.0rc6.tar.gz
- Upload date:
- Size: 195.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2282e54119ee25cbc129352dedb6903ed2e8be86c01e0134a0c53cfb6d81128
|
|
| MD5 |
a9dafe7fd6f0a515a740a0ce6f1fc1ed
|
|
| BLAKE2b-256 |
e9edc241451618ccc1991475c041fe69b8a79e8ec952aaf8174ee610b06eb018
|
Provenance
The following attestation bundles were made for jaunt-1.0.0rc6.tar.gz:
Publisher:
release.yml on creatorrr/jaunt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jaunt-1.0.0rc6.tar.gz -
Subject digest:
b2282e54119ee25cbc129352dedb6903ed2e8be86c01e0134a0c53cfb6d81128 - Sigstore transparency entry: 2048337452
- Sigstore integration time:
-
Permalink:
creatorrr/jaunt@f581deadf815941b3d2d5c9c7c3d446451bd92a5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/creatorrr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f581deadf815941b3d2d5c9c7c3d446451bd92a5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file jaunt-1.0.0rc6-py3-none-any.whl.
File metadata
- Download URL: jaunt-1.0.0rc6-py3-none-any.whl
- Upload date:
- Size: 244.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9097fb881105cba633c11233b22420858ac3431e1328e634c3fb269e2bce33d9
|
|
| MD5 |
fa202e88f57453d46d4d1e83857d5719
|
|
| BLAKE2b-256 |
daa059b13e18dce424ec0b28d85d9efb0da0ad9b3b0af9d58fa80b616900f96d
|
Provenance
The following attestation bundles were made for jaunt-1.0.0rc6-py3-none-any.whl:
Publisher:
release.yml on creatorrr/jaunt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jaunt-1.0.0rc6-py3-none-any.whl -
Subject digest:
9097fb881105cba633c11233b22420858ac3431e1328e634c3fb269e2bce33d9 - Sigstore transparency entry: 2048337459
- Sigstore integration time:
-
Permalink:
creatorrr/jaunt@f581deadf815941b3d2d5c9c7c3d446451bd92a5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/creatorrr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f581deadf815941b3d2d5c9c7c3d446451bd92a5 -
Trigger Event:
push
-
Statement type: