Built-in Actions¶
Built-in actions live in their respective presets. Use the short form <preset_package>.<ClassName> as the source when declaring actions in pyproject.toml or preset.toml.
lint¶
Run linting across the workspace and report diagnostics.
- Source:
fine_lint.LintAction - Scope:
workspace— dispatched once and routed to the workspace root project; the handler fans outlint_filesper project internally - Default handler execution: concurrent
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
target |
"project" | "files" |
"project" |
Lint the whole workspace (target="project") or specific files |
file_paths |
list[ResourceUri] |
[] |
Files to lint (required when target="files") |
project_paths |
list[Path] \| None |
None |
Restrict the workspace operation to these project paths; None means all workspace projects |
Result: list of diagnostics (file, line, column, message, severity)
lint_files¶
Lint a specific set of files. Internal action dispatched by lint.
- Source:
fine_lint.LintFilesAction - Default handler execution: concurrent
The built-in LintFilesDispatchHandler groups the given files by language and dispatches one call per language to the matching language subaction — any action declaring PARENT_ACTION = LintFilesAction and the corresponding LANGUAGE. Files of unknown language are skipped.
lint_python_files¶
Lint Python source files and report diagnostics. Language-specific subaction of lint_files.
- Source:
fine_python_lang.LintPythonFilesAction - Default handler execution: concurrent
Payload fields: same as lint_files.
Register Python linting tools (ruff, mypy, …) as handlers for this action.
audit_code¶
Run all registered on-demand code audit tools and aggregate results. Peer of inspect_code (see ADR-0044): same result shape and target="files" existence-check guarantee, but invoked at deliberate checkpoints (explicit CLI/MCP call, precommit, CI) rather than per-keystroke, so its handlers may be whole-project and slow.
- Source:
fine_audit_code.AuditCodeAction - Scope:
workspace— dispatched once and routed to the workspace root project; bridge handlers (e.g.check_imports) fan out per project internally - Default handler execution: concurrent
Payload fields: same shape as inspect_code (target, file_paths, project_paths).
Result: list of diagnostics (file, line, column, message, severity)
check_imports¶
Check a project's import graph against configured architectural contracts (e.g. import-linter). Internal category action bridged onto audit_code.
- Source:
fine_check_imports.CheckImportsAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
src_artifact_def_path |
ResourceUri \| None |
None |
Path to the artifact definition file (e.g. pyproject.toml). None = the current project's own definition file |
Whole-project scope: analyzes the full import graph, not individual files — a violation is a relationship between modules, not a property of one file. A project with no import-graph tooling configured is a no-op (empty messages, not an error).
The built-in CheckImportsDispatchHandler detects the project's language (via get_src_artifact_language) and dispatches to the matching language subaction — any action declaring PARENT_ACTION = CheckImportsAction and the corresponding LANGUAGE.
check_python_imports¶
Check Python import-graph contracts (e.g. import-linter) and report diagnostics. Language-specific subaction of check_imports.
- Source:
fine_python_lang.CheckPythonImportsAction - Default handler execution: concurrent
Payload fields: same as check_imports.
Register Python import-graph tools (import-linter, …) as handlers for this action.
format¶
Format a source artifact or specific files.
- Source:
fine_format.FormatAction - Default handler execution: sequential
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
save |
bool |
true |
Write formatted content back to disk |
target |
"project" | "files" |
"project" |
Format the whole source artifact (target="project") or specific files |
file_paths |
list[Path] |
[] |
Files to format (required when target="files") |
Note
The save payload field controls whether changes are written to disk. The built-in SaveFormatFileHandler reads this flag. If you omit the save handler from your preset, files won't be written regardless.
format_files¶
Format a specific set of files. Internal action dispatched by format.
- Source:
fine_format.FormatFilesAction - Default handler execution: sequential
The built-in FormatFilesIterateHandler iterates over all files and delegates each to format_file. Language routing is handled by format_file via its dispatch handler — format_files has no language awareness.
format_file¶
Format a single file. Item-level action; handlers run sequentially as a pipeline.
- Source:
fine_format.FormatFileAction - Default handler execution: sequential
Payload fields:
| Field | Type | Description |
|---|---|---|
file_path |
ResourceUri |
The single file to format |
save |
bool |
Whether to write the result back to disk |
Run context kwargs (FormatFileCallerRunContextKwargs):
| Field | Type | Default | Description |
|---|---|---|---|
file_editor_session |
IFileEditorSession \| None |
None |
Shared session from a parent action. If absent, the context opens its own. |
file_info |
FileInfo \| None |
None |
Pre-read file content. If absent, the context reads the file itself (with block=True). |
When called standalone (e.g. IDE on-save), no kwargs are needed — the context creates its own session and reads the file. When called from format_files, the iterate handler passes the parent session. When called from the dispatch handler into a language subaction, both session and file info are passed to avoid redundant reads.
Result fields:
| Field | Type | Description |
|---|---|---|
changed |
bool |
Whether the file content was modified |
code |
str |
The formatted content |
Handlers read and update run_context.file_info to pass formatted content to the next handler in the pipeline.
format_python_file¶
Format a single Python file. Language-specific item-level subaction of format_file.
- Source:
fine_python_lang.FormatPythonFileAction - Default handler execution: sequential
Payload fields: same as format_file.
Register Python formatting tools (ruff, isort, …) as handlers for this action. Handler order matters — they run sequentially as a pipeline.
precommit¶
Run configured code quality checks on git-staged files before commit. This action is not registered by default; add it through the fine_precommit preset or declare tool.finecode.action.precommit yourself.
- Source:
fine_git_hooks.PrecommitAction - Default handler execution: sequential
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
file_paths |
list[Path] |
[] |
Explicit file list. Empty means auto-detect staged files from git (done by StagedFilesDiscoveryHandler). |
Result fields:
| Field | Type | Description |
|---|---|---|
action_results |
dict[str, RunActionResult] |
Results keyed by action name (for example, "lint"). The overall return_code is ERROR if any sub-result is an error. |
Run context (PrecommitRunContext):
| Field | Type | Description |
|---|---|---|
staged_files |
list[Path] \| None |
Populated by StagedFilesDiscoveryHandler. None = discovery has not run (bridge handlers raise); [] = no staged files (bridge handlers skip). |
Handler roles:
StagedFilesDiscoveryHandler— must be first; detects staged files viagit diff --cached --name-only --diff-filter=ACMRand writes torun_context.staged_files.- Bridge handlers (for example,
LintPrecommitBridgeHandler) — each delegates to one existing action passing staged files. Register additional bridge handlers to run more tools.
One orchestrator per repository
When multiple projects share a single git repository, only the project at
the repository root runs precommit checks. StagedFilesDiscoveryHandler
detects this automatically: if the current project directory does not match
the git repository root, it sets staged_files = [] and returns — all
bridge handlers skip. See ADR-0031.
See Using Git Hooks for setup instructions.
list_tests¶
Discover tests and return their hierarchical structure without running them.
- Source:
fine_test.ListTestsAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
file_paths |
list[Path] |
[] |
Files or directories to search. Empty means the handler uses its own defaults (e.g. testpaths in pytest.ini). |
Result fields:
| Field | Type | Description |
|---|---|---|
tests |
list[TestItem] |
Tree of discovered tests. Each node carries a test_id usable in run_tests. |
run_tests¶
Execute tests and return structured pass/fail results.
- Source:
fine_test.RunTestsAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
file_paths |
list[Path] |
[] |
Test files or directories to run. Empty means handler defaults. |
test_ids |
list[TestId] |
[] |
Specific tests to run, obtained from list_tests. |
markers |
list[str] |
[] |
Marker/tag names to filter (e.g. ["unit", "slow"]). Handlers map these to runner-specific flags. |
Result fields:
| Field | Type | Description |
|---|---|---|
test_results |
list[TestCaseResult] |
One entry per executed test with outcome, duration, and failure message. |
build_artifact¶
Build a distributable artifact (e.g. a Python wheel).
- Source:
fine_src_artifacts.BuildArtifactAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
src_artifact_def_path |
Path \| None |
None |
Path to the artifact definition. If omitted, builds the current source artifact. |
Result fields:
| Field | Type | Description |
|---|---|---|
src_artifact_def_path |
Path |
Path of the artifact that was built |
build_output_paths |
list[Path] |
Paths of the generated build outputs |
get_src_artifact_version¶
Get the current version of a source artifact.
- Source:
fine_src_artifacts.GetSrcArtifactVersionAction
Default handler in this repo: fine_python_setuptools_scm.GetSrcArtifactVersionSetuptoolsScmHandler
get_dist_artifact_version¶
Get the version of a distributable artifact.
- Source:
fine_dist_artifacts.GetDistArtifactVersionAction
get_src_artifact_language¶
Get the primary programming language of a source artifact. Used by language-aware dispatch handlers (e.g. lock_dependencies) to route to the appropriate language-specific subaction.
- Source:
fine_src_artifacts.GetSrcArtifactLanguageAction
Payload fields:
| Field | Type | Description |
|---|---|---|
src_artifact_def_path |
Path |
Path to the artifact definition file |
Result fields:
| Field | Type | Description |
|---|---|---|
language |
str |
Language identifier, e.g. "python", "javascript", "rust" |
get_src_artifact_registries¶
List available registries for publishing an artifact.
- Source:
fine_src_artifacts.GetSrcArtifactRegistriesAction
lock_dependencies¶
Lock the dependencies of a source artifact.
- Source:
fine_src_artifacts.LockDependenciesAction
Payload fields:
| Field | Type | Description |
|---|---|---|
src_artifact_def_path |
Path |
Path to the artifact definition file (e.g. pyproject.toml, package.json) |
output_dir |
Path |
Directory where lock files will be written. The handler decides filenames. |
Result fields:
| Field | Type | Description |
|---|---|---|
lock_file_paths |
list[Path] |
All lock files generated — one entry for single-lock, N entries for multi-lock |
| --- |
lock_python_dependencies¶
Lock Python dependencies for a specific Python version and platform. Language-specific subaction of lock_dependencies.
- Source:
fine_python_lang.LockPythonDependenciesAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
src_artifact_def_path |
Path |
Path to the artifact definition file (e.g. pyproject.toml) |
|
output_dir |
Path |
Directory where lock files will be written | |
target_python_version |
str \| None |
None |
Python version to target, e.g. "3.11". Defaults to the running interpreter. |
target_platform |
str \| None |
None |
Wheel platform tag to target, e.g. "linux_x86_64". Defaults to the current platform. |
Result fields: same as lock_dependencies.
target_python_version and target_platform are typically used for target projection or target-specific lock generation.
See the Designing Actions Rules and Designing Actions Reference for the rationale behind generic vs. language-specific actions.
publish_artifact¶
Publish a built artifact.
- Source:
fine_dist_artifacts.PublishArtifactAction
publish_artifact_to_registry¶
Publish an artifact to a specific registry.
- Source:
fine_dist_artifacts.PublishArtifactToRegistryAction
is_artifact_published_to_registry¶
Check whether a specific version of an artifact is already published.
- Source:
fine_dist_artifacts.IsArtifactPublishedToRegistryAction
verify_artifact_published_to_registry¶
Verify that publishing succeeded by checking the registry.
- Source:
fine_dist_artifacts.VerifyArtifactPublishedToRegistryAction
list_src_artifact_files_by_lang¶
List source files grouped by programming language.
- Source:
fine_src_artifacts.ListSrcArtifactFilesByLangAction
group_src_artifact_files_by_lang¶
Group source files by language (internal, used by language-aware actions).
- Source:
fine_src_artifacts.GroupSrcArtifactFilesByLangAction
create_envs¶
Create virtual environments for all envs discovered from the project's dependency-groups.
- Source:
fine_envs.CreateEnvsAction
install_envs¶
Install handler dependencies into virtualenvs.
- Source:
fine_envs.InstallEnvsAction
The python -m finecode prepare-envs CLI command runs create_envs and install_envs in sequence.
install_deps_in_env¶
Install dependencies into a specific environment.
- Source:
fine_envs.InstallDepsInEnvAction
sync_toolchains¶
Derive each environment's toolchain axis from the project's declared support range and write it into the project definition file.
- Source:
fine_envs.SyncToolchainsAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
project_def_path |
Path \| None |
None |
Project definition file declaring the envs. None means the current project. |
save |
bool |
True |
Write the derived axis to the file. False derives and reports without writing. |
Result fields:
| Field | Type | Description |
|---|---|---|
axes |
list[EnvToolchainAxis] |
Per env: declared, derived, and whether it changed |
saved |
bool |
Whether a derived axis was written |
A toolchain is the implementation-and-version a project is executed against; in Python it is an interpreter. Every ecosystem declares its support range somewhere (requires-python, engines, required_ruby_version), and a language handler expands that range into toolchain identities. The action dispatches on project language to the matching subaction.
The axis is materialized — written to the file rather than recomputed on each run — so that config resolution stays a pure read of already-declared data. See ADR-0053 for why, and note the consequence: the axis is wholly generated, so extra toolchains are configured as inputs to the source (extra_interpreters) rather than hand-added to its output.
check_toolchains¶
Check whether each environment's materialized toolchain axis still matches what the source derives. Fails with a non-zero return code on drift.
- Source:
fine_envs.CheckToolchainsAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
project_def_path |
Path \| None |
None |
Project definition file declaring the envs. None means the current project. |
Result fields:
| Field | Type | Description |
|---|---|---|
stale_axes |
list[EnvToolchainAxis] |
Envs whose declared axis differs from the derived one |
A generated, committed axis can go stale — the support range changes, or the source learns about a newer toolchain. That is the same staleness a lock file has, and it is caught the same way: re-derive and compare. Wire this into precommit and CI. Runs sync_toolchains with save = False and reports what would change.
sync_python_interpreters¶
Derive an environment's Python interpreter axis from requires-python. Language-specific subaction of sync_toolchains.
- Source:
fine_python_lang.SyncPythonInterpretersAction - Handler:
fine_python_package_info.SyncPythonInterpretersPyHandler - Preset:
fine_python_envs
Payload fields: same as sync_toolchains. Result fields: same as sync_toolchains.
Handler config:
| Field | Type | Default | Description |
|---|---|---|---|
envs |
list[str] |
[] |
Envs whose interpreter axis is derived. Empty means none — the action is a no-op. |
max_supported_python |
str \| None |
None |
Cap the newest CPython to derive. None means no cap beyond what is obtainable. |
extra_interpreters |
list[str] |
[] |
Interpreters beyond the derived CPython rows, e.g. ["pypy@3.11"]. |
requires-python is a specifier, not an enumeration, so it is expanded against the set of obtainable interpreters (see list_obtainable_toolchains below). An open upper bound (>=3.11) — the correct form for a published package — is bounded by that set rather than rejected. The result therefore depends on something outside the specifier, which is exactly why it is persisted.
requires-python constrains version only and carries no implementation, so the derived axis is CPython-only. PyPy and friends are configured via extra_interpreters.
Matrices stay opt-in: with no envs configured, nothing is derived and every action keeps running in a single environment with an unchanged result shape.
list_obtainable_toolchains¶
List the toolchains the environment provisioner is able to obtain.
- Source:
fine_envs.ListObtainableToolchainsAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
include_prereleases |
bool |
False |
Include prerelease toolchains (e.g. a Python beta). |
Result fields:
| Field | Type | Description |
|---|---|---|
toolchains |
list[str] |
Canonical identities, e.g. cpython@3.13 — no patch level, variant, or platform tag |
"Obtainable" is deliberately not "installed". This reports what the provisioner can get — a property of a locked dependency — not what happens to be present on this machine. Only the former may feed a derived matrix axis: an axis sourced from local installs would differ between developers on the same commit. Whether a toolchain is available here is a separate question, and would be a separate action.
The provisioner is the authority because deriving a version it cannot obtain yields an axis whose environments cannot be created. This is what sync_toolchains expands requires-python against.
list_obtainable_python_interpreters¶
Language-specific subaction of list_obtainable_toolchains. Backed by uv.
- Source:
fine_python_lang.ListObtainablePythonInterpretersAction - Handler:
fine_python_uv.UvListObtainablePythonInterpretersHandler - Preset:
fine_python_envs
Payload and result fields: same as list_obtainable_toolchains.
Handler config:
| Field | Type | Default | Description |
|---|---|---|---|
variant |
str |
"default" |
Build variant to report. freethreaded builds are a separate variant the (implementation, version) identity cannot express. |
Runs uv python list --only-downloads, which reports uv's own manifest rather than the machine's installed Pythons. uv's listing is far finer-grained than a matrix axis — patch levels, prereleases, freethreaded variants, platform tags — and all of that is collapsed to one identity per implementation and minor version. Prereleases are excluded by default, so a released beta (cpython-3.15.0b1) never enters an axis.
setup_system¶
Install and configure system-level dependencies and tools.
- Source:
fine_system_setup.SetupSystemAction - Default handler execution: sequential
Handles OS packages, IDE extensions, non-Python language tooling, and any other
dependencies that fall outside Python's package management and cannot be handled
automatically by prepare-envs.
The fine_system_setup preset declares this action with an empty handler list — a
safe no-op until handlers are registered. Add team-shared handlers in a shared preset
or project config; add personal handlers in finecode-user.toml.
Handler contract:
- Check whether the dependency or tool is already present before acting (idempotency).
- Populate
installedon success,skippedwhen already present,failedon error. - All handlers always run; failures are collected and reported in aggregate.
Result fields:
| Field | Type | Description |
|---|---|---|
installed |
list[str] |
Steps that completed installation or configuration |
skipped |
list[str] |
Steps skipped because the dependency or tool was already present |
failed |
list[str] |
Steps that failed; non-empty means return_code is ERROR |
dump_config¶
Dump the resolved configuration for a source artifact that includes FineCode configuration.
- Source:
fine_envs.DumpConfigAction
Also available as python -m finecode dump-config.
init_repository_provider¶
Initialize a repository provider (used in artifact publishing flows).
- Source:
fine_dist_artifacts.InitRepositoryProviderAction
ingest_wal_to_store¶
Ingest write-ahead-log events from one or more generic sources into a durable store.
- Source:
fine_wal_events.IngestWalToStoreAction
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
source_specs |
list[WalSourceSpec] |
Source definitions to ingest from | |
since_ts_iso |
str \| None |
None |
Ignore events older than this ISO8601 UTC timestamp |
store_uri |
ResourceUri \| None |
None |
Destination store URI. If omitted, handler chooses a default path |
WalSourceSpec fields:
| Field | Type | Default | Description |
|---|---|---|---|
source_id |
str |
Stable source identifier used in summaries | |
format |
str |
Source format, e.g. jsonl_events |
|
location_uri |
ResourceUri |
File or directory URI containing events | |
include_glob |
str \| None |
None |
Include pattern for directory scanning |
exclude_glob |
str \| None |
None |
Exclude pattern for directory scanning |
field_mapping |
dict[str, str] \| None |
None |
Optional canonical-to-source mapping (ts, event_type, run_id, action_name, payload) |
Result fields:
| Field | Type | Description |
|---|---|---|
schema_version |
int |
Result schema version |
source_summary |
list[SourceIngestSummary] |
Per-source ingest counters |
events_ingested |
int |
Successfully inserted event count |
events_skipped_duplicate |
int |
Duplicate event count |
events_failed_parse |
int |
Parse/normalization failure count |
first_event_ts_iso |
str \| None |
Earliest inserted event timestamp |
last_event_ts_iso |
str \| None |
Latest inserted event timestamp |
store_uri |
ResourceUri |
Final store URI |
warnings |
list[str] |
Non-fatal ingest warnings |
serve_wal_explorer_from_store (extension action)¶
Start a read-only HTTP API over the WAL DuckDB store and serve until interrupted.
- Source:
fine_wal_events.ServeWalExplorerFromStoreAction - Default handler execution: sequential
Payload fields:
| Field | Type | Default | Description |
|---|---|---|---|
store_uri |
ResourceUri \| None |
None |
Path to the DuckDB store. Defaults to <venv>/state/finecode/wal_explorer/store.duckdb. |
host |
str |
"127.0.0.1" |
Interface to bind the HTTP server to. |
port |
int |
8765 |
Port number. If the default port is already occupied, the handler auto-selects a free port. |
read_only |
bool |
True |
Open the DuckDB store in read-only mode. |
Result fields:
| Field | Type | Description |
|---|---|---|
schema_version |
int |
Store schema version. |
base_url |
str |
Full base URL the server is listening on. |
bound_host |
str |
Resolved host after binding. |
bound_port |
int |
Resolved port after binding. |
store_uri |
ResourceUri |
Resolved store path used. |
warnings |
list[str] |
Non-fatal warnings. |
Endpoints:
| Path | Description |
|---|---|
GET /health |
Server status, schema version, event/run totals. |
GET /runs |
Run summaries. Query params: source_id, from_ts, to_ts, limit. |
GET /timeline |
Ordered event stream. Query params: run_id, source_id, from_ts, to_ts, event_type, limit. |
GET /metrics |
Aggregate counters and duration percentiles. |
GET /events |
Raw event rows. Query params: run_id, source_id, from_ts, to_ts, limit. |
The action runs until its invocation is cancelled. Cancellation triggers deterministic cleanup: HTTP server shutdown and DuckDB connection close.