Skip to content

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 out lint_files per 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 via git diff --cached --name-only --diff-filter=ACMR and writes to run_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 installed on success, skipped when already present, failed on 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.