Projects and tooling

spork-lang 0.6.0

Declare a reproducible Spork project, synchronize its isolated environment, check and test source, then build or publish it.

A Spork project is source plus a spork.it manifest. Commands search the current directory and its parents for the nearest manifest, so the same workflow is available anywhere in the tree.

The manifest#

A typical application declares metadata, a compatible compiler range, Python dependencies, source and test roots, and an entry point:

{:name "weather-report"
 :version "0.1.0"
 :description "Print a small weather report"
 :requires-python ">=3.10"
 :spork-version ">=0.6,<0.7"
 :dependencies ["httpx>=0.27"]
 :dev-dependencies []
 :source-paths ["src"]
 :test-paths ["tests"]
 :main "weather-report.core:main"}

Paths are relative to the directory containing the manifest. Package-specific keys are preserved for installed tools; this site, for example, declares a :site target owned by spork-site.

Synchronize once#

spork sync

Synchronization creates .venv, installs dependencies, and selects a spork-lang toolchain within :spork-version. It pins the compatible active launcher when possible and otherwise asks pip to resolve the declared range. Project-aware commands then delegate to that environment automatically. A globally installed launcher can therefore enter projects that intentionally use different compatible toolchains.

Add and remove requirements without hand-editing the vector:

spork add "httpx>=0.27" rich
spork remove rich
spork sync

Requirements use normal pip syntax and resolve from the Python package ecosystem.

Run the entry point#

Given :main "weather-report.core:main", spork run loads the namespace and invokes main:

(ns weather-report.core)

(defn ^int main [& args]
  (print "arguments:" args)
  0)
spork run london --units metric

Arguments arrive as strings. An integer return value becomes the process status. Override the configured target for one invocation with spork run --main other.namespace:start.

Check before execution#

spork check reads every source and test namespace and reports structural and compilation diagnostics without writing build output.

spork check
spork check --json
spork check --warnings-as-errors

Checks include namespace paths, duplicate declarations, :require exports, Python imports, compiler errors, the configured entry point, generated API declarations, and package command targets. Diagnostics use stable SPK codes and original .spork source locations.

Declare and run tests#

Tests are ordinary top-level declarations. Their bodies are registered when the namespace loads but run only through spork test.

(ns weather-report.core-test
  (:require [weather-report.core :refer [format-temperature]]))

(deftest formats-celsius
  (assert (= (format-temperature 21 :celsius) "21 °C")))

(deftest ^async fetches-report
  (def report (await (fetch-fixture)))
  (assert (= (:status report) :ok)))
spork test

Each declaration runs independently, and test files are isolated in separate processes.

Compile readable Python#

spork build --clean

The default .spork-out directory contains generated Python, original Spork source, and source-map sidecars. The output can be imported without the Spork compiler because generated modules depend on the smaller spork-runtime package.

A source namespace such as src/weather_report/core.spork becomes:

.spork-out/
├── pyproject.toml
└── weather_report/
    ├── core.py
    ├── core.spork
    └── core.spork.map.json

Build a distribution#

Libraries and applications can produce standard Python artifacts:

spork dist --clean
python -m twine check dist/*

The wheel contains compiled Python, source maps, and original .spork files. Normal package metadata comes from spork.it, including dependencies, optional extras, project URLs, classifiers, license information, and generated public APIs.

Extend the command line#

A dependency can own one complete top-level command. Providers declare metadata in their manifest and receive the same project context and source loader as built-in operations.

:commands
{"report" {:main "weather-report.cli:command"
            :description "Generate a weather report"}}

After installation, the package contributes spork report .... Provider discovery inspects package metadata without importing every plugin, and project-local providers outrank providers installed with the active launcher.

This website uses that system rather than a bespoke executable: its dependency on spork-site contributes spork site check, spork site routes, spork site build, and spork site serve.

Everyday command set#

spork repl       project-aware interactive session
spork add        add Python dependencies
spork sync       prepare the isolated project environment
spork run        invoke the configured entry point
spork test       run declared tests
spork check      validate the project without writing output
spork build      compile source namespaces to Python
spork dist       build a wheel and source distribution
spork lsp        start the language server

The complete tooling reference documents manifest fields, diagnostics, generated APIs, command providers, and distribution behavior.