Config
Config
One config file feeds every kind of project: a single-file script, a multi-module tree, or a pyproject package.
Sources, nearest first:
pyscriptc.tomlat or above the source, holding a[pyscriptc]table (or the keys at the file root).pyproject.tomlat or above the source, holding a[tool.pyscriptc]table. A pyproject without that table does not shadow anything; discovery keeps walking up.- The script’s own PEP 723 inline metadata (
# /// script), read forrequires-pythonanddependencies.
Nearest directory wins between the two TOML sources.
Project config wins over PEP 723 for the keys it sets; PEP 723 is the only source of script dependency metadata.
Keys
[tool.pyscriptc]
entry = "main" # entry point used by project mode
src = "src" # module root(s), project mode
checker = "pyrefly" # preflight type checker
driver = "clang" # C toolchain driver
target = "" # zig cc cross-compilation triple
fail-on = "any" # exit rule for pyscriptc coverage
stub-path = "stubs" # extra stub roots, relative to this file
ffi = "ffi.toml" # extern manifests, relative to this file
[tool.pyscriptc.imports]
orjson = "replace" # curated native replacement
sqlite3 = "extern" # C ABI via an ffi.toml manifest
numpy = "island" # embedded CPython, marks the binary as libpython-linked
rich = "refuse" # always a compile error naming the lane
"*" = "compile" # default
[tool.pyscriptc.island]
embed = "auto" # host | bundle | auto: where the embedded CPython's libpython comes from
stdlib = "safe" # safe | minimal: stdlib trim of a bundle
The accepted keys, their types and their allowed values:
| Key | Type | Values | What it does |
|---|---|---|---|
entry |
string |
entry point function or module stem, used by project mode | |
src |
string or list |
module root, used by project mode | |
checker |
string |
pyrefly or mypy or pyright | type checker run before compiling |
driver |
string |
clang or zig | C toolchain driver |
target |
string |
cross-compilation triple for zig cc |
|
fail-on |
string |
blockers or any | exit code rule for pyscriptc coverage |
stub-path |
string or list |
extra stub roots, relative to this file | |
ffi |
string or list |
extern manifests, relative to this file | |
imports |
table |
import lane per top-level module name | |
fallback |
table or string or boolean |
fallback mode settings: definitions, or the tier cpython |
|
island |
table |
embedded CPython settings: embed and stdlib |
| Lane | What it does |
|---|---|
compile |
compile from source, and stop with a lane hint when it fails |
replace |
a curated native replacement covers this import |
extern |
bound through the C ABI, with an ffi.toml manifest |
island |
run through embedded CPython; the binary needs libpython |
refuse |
refuse the compile with a message naming the lane |
Without a matching entry the lane is compile.
Unknown keys, wrong value types and unknown lanes are PS3102 errors naming the offending key (pyscriptc explain PS3102).
Import lanes
imports maps a top-level module name to a lane.
An exact name wins over *; without either, the lane is compile, so the zero-config single-file product is unchanged.
The refuse lane is enforced while compiling: an import routed to refuse stops the compile with PS2002, naming the lane and the policy site.
The other lanes are recorded in config and reported by pyscriptc config.
The island lane is what --fallback=cpython (alias --island) acts on; see Runtime pack for what a libpython-linked binary carries.
PEP 723
A script may open with:
# /// script
# requires-python = ">=3.14"
# dependencies = ["orjson>=13"]
# ///
The block is parsed as TOML.
More than one # /// script block is an error.
requires-python and dependencies are validated and reported by pyscriptc config; resolving the dependencies is the separate pyscriptc deps command.
Each dependency is also mapped to a lane, shown by pyscriptc config as dependency-lanes in its JSON.
The [imports] table wins when it names the distribution or its import name; otherwise the offline import classifier decides.
Project mode
A pyproject with a [project.scripts] table builds one binary per console script:
pyscriptc build [DIR] # every script
pyscriptc build DIR --script NAME # one script
The binary is written to <project>/build/<name> (or --out-dir).
The module path resolves against the project’s module roots: src, default src, falling back to the project root when the directory does not exist (a flat layout).
pyscriptc config DIR --json reports the scripts.
CLI interaction
pyscriptc compile fills unset --checker, --driver, --target and --fail-on from config; an explicit flag always wins, and a note on stderr names the config origin.
pyscriptc coverage reads fail-on the same way.
Run pyscriptc config SOURCE to see the resolved merge for any source.