Skip to main content
camas-sketch-by-jph

Camas

A task runner with parallel execution, matrix expansion, MCP, and pluggable output effects.

  • For developers: live tree view that updates in place as tasks stream
  • For CI/CD: one definition drives both local runs and CI
  • For LLMs: a closed edit→validate→run loop over structured MCP

 

demo

Example

from camas import Parallel, Sequential

ci = Sequential(
  Parallel(
    "ruff format . --check",
    "npx prettier ."
  ),
  Parallel(
    "ruff check .",
    "mypy .",
    "npx eslint src/",
    "pytest",
    "npx tsc --noEmit"
  ),
)

Nodes also compose with operators (in tasks.py — the camas '<expr>' expression surface does not yet accept them), each shorthand for a group's typed extend/remove: the left operand is the group being extended and the right operand is one child, so check = format_check | lint | typecheck | test keeps typecheck whole and gate = (check - test) | coverage swaps one child (- raises if it isn't a direct child). | extends a plain Parallel and + a plain Sequential; a left operand with fields, of a subclass, or of another kind nests whole instead, so | and + never move a task into or out of a cwd/env/matrix scope on their own — .extend(...) is the explicit way to join one, and passing a group's .tasks (x | y.tasks) the explicit way to merge its children rather than nest it, leaving its scope behind. + binds tighter than | — parenthesize a mixed chain to control its shape. clippy > "sarif" is a Pipe wiring clippy's stdout into sarif (a stage can't nest, so > always extends the left Pipe — new stages join its scope — while a plain right-side Pipe contributes its stages and one with fields, agent_only, or a subclass type raises — pipe its .tasks instead: x > y.tasks); > is a comparison operator, so Python chains a > b > c as (a > b) and (b > c) — parenthesize a chain of more than two: (a > b) > c — and a composed pipe is always truthy, so a boolean context silently passes; compare with ==.

The animated tree above is from a live test fixture — see the walkthrough.

Install

pipx:

pipx install camas

uv:

uv tool install camas

Nix:

nix run github:JPHutchins/camas                     # default
nix run github:JPHutchins/camas#with-github-checks  # adds httpx for the GitHubChecks effect
nix run github:JPHutchins/camas#with-check          # adds ty for `camas --check`
nix run github:JPHutchins/camas#all                 # both extras

Then scaffold a starter tasks.py in your project root:

camas --init

The starter demonstrates leaf tasks, Sequential/Parallel composition, a matrix, a Config default task, and the optional PEP 723 standalone block — cross-platform placeholder commands ready to be swapped for your real ones.

--init also creates a gitignored .camas/ directory beside tasks.py. Camas writes run logs and a per-leaf timing cache there, so camas --list can annotate tasks with an estimated duration; delete the directory to opt out. Rename or relocate it with Config(camas_dir=...).

Want to see the whole authoring surface at once instead of growing the short starter? camas --init --verbose writes a kitchen-sink tasks.py covering every Task/Sequential/Parallel/Config option — path scoping, matrix expansion, agent_format structured output, Config(agent=Claude(fix=..., check=..., default=...)), and a commented recipe for sourcing a matrix axis from your own project's SSOT — each one worked and explained in place. The MCP camas_init tool writes this template by default (pass verbose=false for the short one).

Why camas?

camas is not a build system. camas is for the specific job of running structured trees of shell commands.

Python task runners† just Task Mage camas
Project scope Python projects only Any Any Go projects only Any
Definition language pyproject.toml TOML or @task decorator justfile DSL YAML Go Python (typed AST)
Inline anonymous parallel groups No No No (must be a named task) No Yes
Parallel execution poe yes; Invoke / taskipy no [parallel] attr deps: (parallel) mg.Deps(...) Parallel(...)
Matrix expansion No No for: + parallel:true Go loops matrix=
Coupled (non-cross-product) fan-out No No No Go loops variants=
CLI matrix override (e.g. --PY 3.13) No No No No Yes
Live tree output No No prefixed / group modes No Termtree (default)
Pluggable output renderers No No 3 built-ins No --effects
Type checking on task definitions Partial No Editor schema Yes (Go) mypy / pyright
First release / status 2013–2020, stable 2016, stable 2017, stable 2017, stable 2026, alpha
Ecosystem Moderate (Python) Large Large Moderate None yet

†poethepoet, Invoke, taskipy — pyproject.toml-bound runners that assume a Python project.

If you need... Reach for
Reproducible, hermetic builds Nix
Incremental file-based builds (skip when inputs unchanged) Task
Simple project command menu just
Parameterized tasks (--env=staging, prompts, vars) Task
Go project, build logic in Go Mage
Inline parallel/sequential trees with a live view camas
Pluggable output effects (live tree locally, summary in CI) camas
Matrix runs across versions/platforms, overridable from the CLI camas

CI integration

The renderer is swappable, not the tree. Run the same tasks.py locally with the live Termtree and in CI with Status — one flag changes the output, the pipeline definition is unchanged.

On GitHub Actions, no flag is needed. Camas detects GITHUB_ACTIONS=true and defaults --effects to (Status(output_mode="github"),) — collapsed workflow groups, ISO timestamps with millisecond precision, ANSI colors preserved.

Under an AI coding agent, no flag is needed either. Camas detects agents (the CLAUDECODE env var, or set CAMAS_AGENT=1) and defaults to the line-oriented Status renderer instead of the live Termtree, whose cursor-redraw frames bloat captured output. Prefer the camas mcp server over the CLI from an agent; a Config default_effects always overrides the detection.

- run: uv run camas check

On other CI providers (or to opt into a specific mode), spell it out:

- run: uv run camas check --effects='(Status(output_mode="errors"),)'

See the OutputMode literal and block_for doctests for the per-mode behavior. The status-modes-demo job renders one CI run per mode for visual comparison.

For per-leaf visibility in the PR Checks panel, add the GitHubChecks effect alongside Status (opt-in extra: camas[github_checks]). Each leaf task becomes its own check run, so reviewers see lint / mypy / pytest pass-or-fail individually instead of one monolithic log.

- run: |
    uv run --extra github_checks camas matrix --effects='(
      Status(output_mode="github"),
      GitHubChecks(sha="${{ github.event.pull_request.head.sha || github.sha }}"),
    )'
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

The job needs permissions: checks: write. Defaults read GITHUB_TOKEN, GITHUB_REPOSITORY, and GITHUB_SHA from the Actions env. The pull_request.head.sha override attaches checks to the PR head rather than the synthetic merge commit. See the github-checks-demo job for a working example.

When to use it. Two things it gives you:

  • SSOT between local dev and CI. Your camas matrix terminal view and the PR Checks panel show the same per-leaf shape (lint [PY=3.10], mypy [PY=3.14], …). The matrix definition lives once in tasks.py; CI doesn't re-encode it in YAML.
  • One runner instead of N. Camas-side parallel matrix on a single runner produces the same per-(cell, leaf) granularity that a GHA matrix gets across N runners — at 1/N the minutes and camas gives you efficient task parallelization pushing that runner to 100% utilization as much as possible. Worth it on paid-runner budgets.

The downside is that fork PRs get a read-only GITHUB_TOKEN from GitHub and can't write checks — usually a non-issue for Enterprise teams where contributors have push to the org repo.

When not to bother. OSS gets free runners — just GHA-matrix them in parallel for faster wall-clock time. The cost is small: you give up either SSOT (matrix definition moves into YAML) or per-leaf-UI granularity (one PR check entry per runner instead of per leaf) — pick one. What is a deal-breaker for OSS is fork PRs: external-contributor PRs return 403 from the Checks API, so per-leaf entries silently don't appear. The github-checks-demo job is marked continue-on-error so it doesn't block CI when that happens, but GitHubChecks isn't a workable OSS solution.

GitHub Actions matrix (--github-matrix)

Fan out across N runners without giving up SSOT. camas <task> --github-matrix emits the task's fan-out as the JSON GHA's strategy.matrix consumes, so a discover job can source it from tasks.py and downstream jobs read it with fromJSON — the fan-out lives in one place. This repo dogfoods it: see the discover and check jobs fanning out over .python-version.

Three shapes, one per way a tasks.py fans out:

tasks.py emitted job runs
matrix={"PY": (...)} — a cross product {"PY": ["3.13", "3.14"]} camas <task> with the cell's axes pinned (flags, or job env)
variants=({...}, {...}) — coupled bundles {"include": [{...}, {...}]} same, pinning the cell's keys
a Parallel of named tasks, no axes {"task": ["build", "lint", "test"]} camas ${{ matrix.task }}

The last one is the common CI shape — N independent jobs, no version matrix — and its values are the binding names camas <task> dispatches on, so an emitted job can't 404 in CI. Compose a YAML-side axis (os, which a shell command can't change from inside a job anyway) with either object-of-arrays form:

strategy:
  matrix:
    os: [ubuntu-latest, macos-latest]
    task: ${{ fromJSON(needs.discover.outputs.matrix).task }}

--github-matrix=axes|variants|tasks pins the shape; pin it in your discover step so a later tasks.py refactor fails there instead of quietly handing the workflow a differently-shaped object. Whatever the shape, camas checks the emitted object against the task's real run-set — each job must run exactly its own cell's leaves, and the jobs together every leaf exactly once — so a fan-out with no faithful projection (independent fan-outs in one tree, a plain leaf beside matrixed siblings) is rejected rather than silently widened or narrowed.

Machine-readable report (Ctrf)

For a CI artifact or input to an AI code review, add the Ctrf effect (opt-in extra: camas[ctrf]). It writes the run as a CTRF JSON report — each leaf a test with status, duration, output, command, and exit code. path= writes a file; the default is stdout.

uv run --extra ctrf camas check --effects='(Status(output_mode="errors"), Ctrf(path="ctrf-report.json"))'

Config

Bind a Config in tasks.py and bare camas (no arguments) runs its default_task:

from camas import Config, Sequential, Task

lint = Task("ruff check .")
test = Task("pytest")
ci = Sequential(lint, test, name="ci")

_ = Config(default_task=ci)

Now camas runs ci, camas --dry-run previews it, and the default's matrix axes stay overridable (camas --PY 3.13). With no Config (or no default_task), bare camas prints the full help — task listing, effects, hints — and exits non-zero.

github_task is the CI counterpart, falling back to default_task when unset; it runs under GITHUB_ACTIONS=true. Paired with the automatic Status effect, one bare camas does the right thing in both places:

_ = Config(
  default_task=ci,                            # bare `camas` locally
  github_task=Sequential(ci, "pytest --cov"), # bare `camas` under GitHub Actions
)

Config is discovered by type, so the binding's name never matters — _ by convention. Defining two is an error.

Leaf color (leaf_color)

camas runs every leaf on a pipe, so a tool that probes for a terminal drops its color — and the tree, and any CI log that renders ANSI, lose it. camas therefore forces color on in the leaf environment (FORCE_COLOR=1, CLICOLOR_FORCE=1), which is why camas lint stays colored where a bare lint | cat would not.

That environment is inherited, so it also reaches commands your leaf spawns for itself — including one whose output the leaf captures and asserts on. A test checking that a CLI prints Passes: 1, failures: 1 passes when run by hand and fails under camas, because the string arrives wrapped in ANSI. When a leaf's output is data rather than display, turn the forcing off:

_ = Config(leaf_color=False) # project-wide
check = Task("cargo test -p mycli", env={"NO_COLOR": "1"}) # or just this leaf

NO_COLOR wins over both, per no-color.org. leaf_color=False only stops camas from forcing — a leaf that asks for color itself (env={"FORCE_COLOR": "1"}, or an exported one) still gets it.

Because github_task reproduces CI, running it before a push catches a CI failure locally. If it is a named task, a one-line git hook guards every push:

echo 'exec camas check' > .git/hooks/pre-push && chmod +x .git/hooks/pre-push

git push --no-verify still bypasses it deliberately. An LLM agent needs no hook — when a github_task is declared, camas_list reports it as github_default, so the agent runs camas_run with that name before pushing. The field is null when no github_task is set; camas never infers it from your CI workflow files.

Time budget (--under)

Once camas has timed a task's leaves (the .camas/ cache, surfaced by camas --list), camas --under=<duration> runs only the leaves whose estimate fits a wall-clock budget — the fast inner-loop subset, picked for you instead of by hand.

camas --under=1s            # budget the Config default task
camas --under=500ms check   # budget a named task or expression

It runs the mutating leaves first, in sequence, then the read-only rest in parallel — so formatters never race a checker over the same files. Mark a leaf that writes the workspace with mutates=True:

fix = Task("ruff check --fix .", mutates=True)
fmt = Task("ruff format .", mutates=True)
lint = Task("ruff check .")
$ camas --under=1s --dry-run
Time budget 1.00s — running 6 leaf(s) (0 unmeasured), excluded 2 over budget.
  over budget: pyright ~4.57s, coverage ~20.98s
fix → fmt → (mypy | ty | zuban | pyrefly)

Durations are 1s, 500ms, 2m, 1h, or a bare number of seconds. Only leaves measured to exceed the budget are excluded; a leaf with no recorded timing yet runs anyway (and is thereby measured) — skipping it would keep it forever untimed. The budget is per-leaf: a measured leaf runs when its own estimate fits, so the parallel group's wall-clock stays near the budget.

For agents, camas_run exposes the same budget as its under argument (omit task to budget the project default), and the response's budget field reports what was selected and excluded — a tight, time-boxed validate loop over structured MCP.

Path scoping (--paths)

camas <task> --paths <path>… scopes a run to changed paths instead of the whole tree. A command opts in by writing the {paths} placeholder and declaring its scope with paths= — a directory prefix, or a (changed) -> paths callable. A Sequential/Parallel may carry paths= too: it's the default scope for descendant {paths} commands that set none (the same way env/cwd propagate into a group's leaves):

py = Task("ruff format {paths}", mutates=True, paths="src")
web = Task("prettier --write {paths}", mutates=True, paths="web")
# the group's paths="." is the default for both children (neither sets its own):
autofix = Sequential(Task("ruff check --fix {paths}", mutates=True), Task("ruff format {paths}", mutates=True), paths=".")
_ = Config(agent=Claude(fix=Sequential(py, web, autofix)))

--paths works on any task — camas check --paths src/a.py. Without it, every {paths} resolves to its full-run default (ruff format src); with it, each {paths} command runs only over the changed files it covers, and one covering none is dropped. A command without {paths} can't be narrowed, so its paths= is a no-op and it always runs — unless it declares when= (below), camas errs on correctness (a tool it can't narrow might be affected by the edit). --paths is repeatable, or comma-separated.

A command that can't take {paths} (cargo build, nix flake check, ctest) is scoped with when= instead — a directory-prefix string or Path (coerced to its POSIX prefix), a tuple of those, or a (changed) -> bool callable. On a scoped run a leaf whose when= doesn't match the changed set is dropped; a full run never consults it. Like paths=, a group's when= is the default for descendant leaves that set none. A leaf with a cwd but no when= gates on its cwd directory — the monorepo file-tree default; set when="." to opt back into always-run:

build = Task("cargo build", when="src")                # runs only when src/ changed
flake = Task("nix flake check", when=("flake.nix", "nix"))
tests = Task("cargo test", cwd="code-gen")             # when= defaults to "code-gen"

A paths= callable is called with () on a full run — one that filters the changed set would return () and strip the command's arguments entirely (a formatter reading stdin on no args hangs). by_suffix(suffixes, default=...) is the safe factory: it filters the changed files by suffix on a scoped run and returns default on a full run:

tidy = Task("clang-tidy {paths}", paths=by_suffix((".c", ".h"), default=("src",)))

camas --check (and the MCP camas_check) flags both authoring mistakes as advisory warnings: a leaf whose own paths= can never apply (no {paths} token — use when= instead) and a {paths} callable that goes empty on a full run.

For the Claude Code plugin, you register the auto-fix node — whatever you named it — to Config.agent.fix; the camas_gate MCP tool settles that node over the changed files before it checks, and a Stop hook runs it at every turn end — deterministically, at zero model tokens, and never between an agent's edits, so a half-finished edit (an import not yet used) survives until the agent gates. The headless camas mcp gate stays read-only, so CI checks exactly what was committed. Run camas mcp init --claude to write the full Claude Code setup in one command (.mcp.json + the Stop autofix and async nudge hooks + the tiered camas-fixer agents + gate skill), resolving the launcher for your project (uv run camas/uv run tasks.py, uvx, or a PATH camas) and pinning it — to tasks.py's PEP 723 block when present, else to the running camas release version (a dev/local build is left unpinned, since it isn't published to pin against). The launcher it picks is the one that can still see your project's tools: a uv.lock/PEP 723 project gets uv run, and a camas that is part of the project's environment — installed into a virtual environment, or provided by a flake devShell out of /nix/store — is preferred over uvx, which is isolated from both and so cannot run ruff/mypy/treefmt/go at all. A global camas is not preferred, since it shares nothing with the project and the pinned uvx entry is more portable. Detection reads where camas itself resolves, not VIRTUAL_ENV/IN_NIX_SHELL, which only report that a shell was entered. When init picks the environment's camas, the entry it commits needs your team in that same environment — activate the venv, or enter the devShell, before starting the client — and init says so. Pass --launcher uv|uvx|camas to force a strategy instead. For a bare .mcp.json for any MCP client, camas mcp init alone (same launcher/pin resolution, no Claude Code files). Either path warns when git excludes a file it just wrote: a repo whose .gitignore covers .claude/ can only commit .mcp.json, so the autofix/gate loop stays per-developer — every teammate re-runs camas mcp init --claude in their own clone — until that rule is opened up, and the warning prints the .gitignore lines that do it. Or wire it by hand:

// .claude/settings.json
{ "hooks": { "Stop": [
  { "hooks": [{ "type": "command", "command": "camas mcp fix" }] } ] } }

camas mcp fix runs the registered Config.agent.fix node (not a task named fix — that's just camas fix, your own task); it reads the changed files from --paths or a PostToolBatch event on stdin, and a Stop event names none, so the fix covers the whole tree. With no fix registered it is a clean no-op, so the hook is harmless without it. It is synchronous, so it holds the turn until it has run and can never race the agent's next edit. camas mcp init --claude also writes a second Stop hook, camas mcp gate --under 5s --nudge (async: true, asyncRewake: true) — a headless, time-boxed check that first waits for the sibling fix to mark the prompt settled (Claude Code runs a Stop event's hooks in parallel), stays silent when green, and otherwise wakes the main agent with a reminder to delegate to the camas-fixer ladder (see the gate skill), without ever blocking the turn. The nudge is self-limiting: at most one wake per prompt (it honors the Stop event's stop_hook_active and tracks the prompt_id it last nudged), and a configuration state — no check node registered, a tasks.py load error, a missing camas[mcp] extra — exits 0 silently instead of waking the agent over something a rewake cannot fix. The launcher runs in your project's environment — camas mcp init --claude resolves and pins it: to tasks.py's PEP 723 declaration (dependencies = ["camas>=X.Y"]) when present, else to the running camas release version; re-run camas mcp init --claude after bumping either to keep it current.

Drift gate (Clean)

Clean keeps committed generated code up to date: it runs the generator, then fails if the working tree changed.

from camas import Clean, Task

openapi = Clean(Task("make update-openapi", mutates=True))

openapi is a Sequential of three leaves: a check that the tree is clean, the generator, and the same check again. A dirty tree fails the first check and skips the generator. A failed second check prints the drift: the git diff of the changed tracked files, staged or not, then the git status --porcelain lines, untracked files included.

  • check= replaces the whole-tree default with any task or command string whose exit 0 means clean. check="git diff --exit-code -- schema/" scopes the gate to one directory, but git diff doesn't see untracked files, so a generator that adds files needs a check that does. A check can't carry {paths}.
  • before=False drops the first check. A tree that starts dirty then fails as drift.
  • The default check reads git's view of the whole tree, where ignored paths don't count, so nothing else may write while a gate runs. A formatter sequenced before a gate fails the gate's first check whenever it changes a file, and two gates under one Parallel see each other's writes. Run the gates first, in sequence:
from camas import Clean, Sequential, Task

generators = Sequential(
  Clean(Task("go generate ./...", mutates=True)),
  Clean(Task("make update-openapi", mutates=True)),
)

When Parallel doesn't help

Parallel runs in the time of its slowest leaf only when the machine has room for every leaf at once. It pays for independent work, such as distinct tools or a long emulator or integration run overlapped with quick static checks, and across CI runners, each with its own cores and build directory. In these cases, keep the work in one leaf or in sequence:

  • Leaves that each fill the CPU. Multicore tools on one machine share the same cores, so golangci-lint beside another Go linter, or cargo clippy beside cargo test on a warm cache, gains little over running them in sequence. --jobs N caps a fan-out that oversubscribes the machine; it can't make one faster.
  • Leaves behind one build lock. Concurrent cargo commands over one target/ wait on cargo's build-directory lock. Keep the batched invocation (cargo hack, cargo-batch, an xtask) as a single leaf.
  • A tool with its own scheduler. Three nix build .#attr leaves evaluate the flake three times; one nix build .#a .#b .#c evaluates it once and schedules the builds itself.
  • Leaves that write the tree. mutates=True orders leaves only under --under. In a normal run, mutating leaves in one Parallel race each other and their read-only siblings, and a Clean gate fails on writes it didn't make. Run them first, in sequence:
from camas import Parallel, Sequential, Task

dev = Sequential(
  Task("ruff format .", mutates=True),
  Task("ruff check --fix .", mutates=True),
  Parallel("mypy .", "pytest"),
)

To fan out across machines, let camas split the outer axes (target, chip, toolchain version) over CI runners with --github-matrix and keep each tool's batched invocation inside one leaf.

Monorepos

A tasks.py composes others with Project. Binding one imports a child tasks.py as a task node — a self-contained child project — and mounts the child's own tasks under the binding name:

from camas import Claude, Config, Parallel, Project

libs = Project("libs")            # camas libs, camas libs.search.lint, ...
api  = Project("services/api")    # name the handle whatever you like

_ = Config(
    default_task=Parallel(libs, api, name="all"),      # each child's default_task, in parallel
    github_task=Parallel(libs, api, name="ci"),        # each child's github_task
    agent=Claude(
        fix=Parallel(libs, api, name="fix"),           # each child's fix node
        check=Parallel(libs, api, name="check"),       # each child's check node
    ),
)

Name each composite (or bind it to a variable) so camas_list can report it as the default — an anonymous inline Parallel/Sequential in a Config task field surfaces as null, and camas --check flags that papercut.

A reference composes the child's matching field: the same bare libs grabs the child's default_task in default_task, its github_task in github_task, its fix node in agent.fix, its check node in agent.check — the slot the reference sits in selects which field of the child's own Config it contributes. So a Parallel of references in any slot is that slot composed across the monorepo, each child contributing its own. A binding name resolves by context instead — camas libs runs whatever a bare camas runs in that directory (its default locally, its github_task under CI, its agent default under an agent). camas libs.search.lint reaches a task the child exposes (because libs/tasks.py itself did search = Project("search")), and expressions compose across namespaces (camas '{libs.search.lint, api.deploy}').

Nodes stay anchored where they were authored: a leaf's cwd and its paths=/when= scopes are relative to its own tasks.py, rebased across the boundary no matter where camas is invoked from. Because a leaf's when= defaults to its cwd, a scoped run (the gate, or --paths) automatically runs only the children whose directory changed — no per-leaf when= anywhere in a child's tasks.py. Children are referenced by path relative to the importing file and live within its directory. The monorepo fixture exercises the permutations.

Effects plugins

Define an Effect in your tasks.py and it's discovered automatically — usable by name from --effects and listed under camas --effects. See examples/effect-plugin/ for a typed Tail effect that streams per-task output as it arrives.

Versioning

The public API is published through versioned namespaces — camas.v0 today, camas.v1 and beyond later. Import from a generation to pin the API shape: a name a generation exports is never removed or changed within that generation. The scheme tracks semver — v0 pairs with camas 0.x and is as loose as semver says 0.x is (the surface prefers to grow; breaking changes stay possible until 1.0, made deliberately and noted in releases). At 1.0 a generation freezes: a breaking change forces the next camas.vN, and published generations keep shipping, so a tasks.py or effect plugin pinned to one keeps working across upgrades.

The top-level camas namespace is the unversioned alias for the latest generation: from camas import Task, Sequential, Parallel, Effect, Config re-exports that generation's five headline definers and is kept 1:1 with its package surface. The rest of the public API for a generation — TaskNode, the TaskEvent stream, LeafState, Completion — lives in that generation's submodules, e.g. from camas.v0.task_event import TaskEvent. Everything under camas.core / camas.main is internal — it consumes whatever generations are installed and carries no stability promise.

To pin a minimum camas feature level, use your dependency declaration (camas>=0.x in pyproject.toml, or PEP 723 inline metadata) — the import path covers API shape; the package pin covers feature availability.

Standalone tasks.py (PEP 723)

For a non-Python project that wants a single-file task runner — no pyproject.toml, no venv to manage — give tasks.py a PEP 723 header and a run_cli(globals()) entry point, then run it with any PEP 723-aware tool:

# /// script
# requires-python = ">=3.11"
# dependencies = ["camas>=0.1.8"]
# ///
"""Build tasks for my project."""

from camas import Parallel, Task, run_cli

lint = Task("ruff check .")
test = Task("pytest")
check = Parallel(lint, test)

if __name__ == "__main__":
    run_cli(globals())
uv run tasks.py check     # uv reads the header, builds an ephemeral env, runs
uv run tasks.py --list    # every camas flag still works
pipx run tasks.py test

run_cli(globals()) introspects the module for Task / Sequential / Parallel and Effect bindings — exactly what camas does when it auto-discovers a tasks.py — so the standalone file behaves identically to a discovered one: camas <task> --help, --dry-run, matrix overrides, and --check all work and cite the file. run_cli is part of the stable surface (from camas import run_cli, or from camas.v0 import run_cli to pin the generation); it's imported lazily, so a plain from camas import Task doesn't pull it in.

The header owns version pinning (dependencies = ["camas>=0.1.8"]) and the interpreter floor (requires-python); it's inert to camas --check and to auto-discovery, which read the module the same way with or without it.

Reference

  • examples/ — full project layouts under test coverage. The canonical reference for how to structure tasks.py, use [tool.camas.tasks] in pyproject.toml, drive a matrix from .python-version, or scope a 2-axis matrix from the CLI.
  • src/camas/ — typed Python with thorough docstrings. camas --help and camas <task> --help link back here.
  • camas with no args runs the Config default task (or prints the full help when none is defined); camas <task> --help shows the expanded tree, matrix axes, and override flags.

Walkthrough

The animated tree at the top is generated from this tasks.py:

examples/tauri-app/tasks.py — Rust + TypeScript + Python in one tree
from pathlib import Path

from camas import Config, Parallel, Sequential, Task

src_tauri = Path("src-tauri")
python_sdk = Path("python-sdk")
node = Path("node_modules/.bin")

frontend = Sequential(
    f"{node}/prettier --write .",
    Parallel(
        f"{node}/eslint src/",
        f"{node}/tsc --noEmit",
        f"{node}/vitest run",
    ),
)

backend = Sequential(
    Task("cargo fmt --all", cwd=src_tauri),
    Parallel(
        Task("cargo clippy --all-targets --locked -- -D warnings", cwd=src_tauri),
        Task("cargo test --all-targets --locked", cwd=src_tauri),
    ),
)

sdk = Sequential(
    Task("uv run ruff check --fix .", cwd=python_sdk),
    Task("uv run ruff format .", cwd=python_sdk),
    Parallel(
        Task("uv run mypy .", cwd=python_sdk),
        Task("uv run pytest", cwd=python_sdk),
    ),
)

all = Parallel(frontend, backend, sdk)

fix = Parallel(
    f"{node}/prettier --write .",
    Task("cargo fmt --all", cwd=src_tauri),
    Sequential(
        Task("uv run ruff check --fix .", cwd=python_sdk),
        Task("uv run ruff format .", cwd=python_sdk),
    ),
)

build = Parallel(
    Task("npm run tauri build {FLAG}"),
    matrix={"FLAG": ("-- --debug", "")},
    help="Debug and release builds (FLAG='-- --debug' debug, FLAG='' release)",
)

_ = Config(default_task=all)
$ cd examples/tauri-app

List the tasks —

$ camas --list
output
Available tasks from .../tauri-app/tasks.py:
  all       frontend | backend | sdk
  backend   cargo fmt --all, cargo clippy --all-targets --locked -- -D warnings | cargo test --all-targets --locked
  build     Debug and release builds (FLAG='-- --debug' debug, FLAG='' release)  [matrix: FLAG×2 (-- --debug..)]
  fix       node_modules/.bin/prettier --write . | cargo fmt --all | (uv run ruff check --fix ., uv run ruff format .)
  frontend  node_modules/.bin/prettier --write ., node_modules/.bin/eslint src/ | node_modules/.bin/tsc --noEmit | node_modules/.bin/vitest run
  sdk       uv run ruff check --fix ., uv run ruff format ., uv run mypy . | uv run pytest

Preview what all would run —

$ camas --dry-run all
output
all ∥
┃ frontend →
┃ ├─ node_modules/.bin/prettier --write .
┃ └─ node_modules/.bin/eslint src/ | node_modules/.bin/tsc --noEmit | node_modules/.bin/vitest run
┃   ┃ node_modules/.bin/eslint src/
┃   ┃ node_modules/.bin/tsc --noEmit
┃   ┃ node_modules/.bin/vitest run
┃ backend →
┃ ├─ cargo fmt --all  (cwd: src-tauri)
┃ └─ cargo clippy --all-targets --locked -- -D warnings | cargo test --all-targets --locked
┃   ┃ cargo clippy --all-targets --locked -- -D warnings  (cwd: src-tauri)
┃   ┃ cargo test --all-targets --locked  (cwd: src-tauri)
┃ sdk →
┃ ├─ uv run ruff check --fix .  (cwd: python-sdk)
┃ ├─ uv run ruff format .  (cwd: python-sdk)
┃ └─ uv run mypy . | uv run pytest
┃   ┃ uv run mypy .  (cwd: python-sdk)
┃   ┃ uv run pytest  (cwd: python-sdk)

Tree-symbol key: ∥ ends a Parallel header, → ends a Sequential. Children hang off ┃ (parallel siblings, run concurrently) or ├─ / └─ (sequential steps, short-circuit on first failure).

Discover a task's matrix axes and override flags —

$ camas build --help
output
usage: camas build [-h] [--dry-run | --github-matrix [SHAPE]] [--effects EFFECTS] [--FLAG VAL[,VAL...]]

Debug and release builds (FLAG='-- --debug' debug, FLAG='' release)

runs the 'build' task:
build ∥
┃ npm run tauri build -- --debug [FLAG=-- --debug]: npm run tauri build -- --debug  FLAG=-- --debug
┃ npm run tauri build  [FLAG=]: npm run tauri build   FLAG=

Matrix axes (override with --AXIS VAL[,VAL...]):
  --FLAG  -- --debug,

Pin the matrix from the CLI —

$ camas build --dry-run --FLAG '-- --debug'
output
build ∥
┃ npm run tauri build -- --debug [FLAG=-- --debug]: npm run tauri build -- --debug  FLAG=-- --debug

Metadata

Release files for camas 0.1.31

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for camas 0.1.31
File Size Uploaded
camas-0.1.31.tar.gz 262.6 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for camas 0.1.31
File
camas-0.1.31-cp314-cp314-win_arm64.whl CPython 3.14 CPython 3.14 Windows ARM64 Details
camas-0.1.31-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
camas-0.1.31-cp314-cp314-musllinux_1_2_x86_64.whl CPython 3.14 CPython 3.14 Linux musl 1.2+ x86-64 Details
camas-0.1.31-cp314-cp314-musllinux_1_2_aarch64.whl CPython 3.14 CPython 3.14 Linux musl 1.2+ ARM64 Details
camas-0.1.31-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
camas-0.1.31-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.14 CPython 3.14 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
camas-0.1.31-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
camas-0.1.31-cp313-cp313-win_arm64.whl CPython 3.13 CPython 3.13 Windows ARM64 Details
camas-0.1.31-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
camas-0.1.31-cp313-cp313-musllinux_1_2_x86_64.whl CPython 3.13 CPython 3.13 Linux musl 1.2+ x86-64 Details
camas-0.1.31-cp313-cp313-musllinux_1_2_aarch64.whl CPython 3.13 CPython 3.13 Linux musl 1.2+ ARM64 Details
camas-0.1.31-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
camas-0.1.31-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 Details
camas-0.1.31-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
camas-0.1.31-cp312-cp312-win_arm64.whl CPython 3.12 CPython 3.12 Windows ARM64 Details
camas-0.1.31-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
camas-0.1.31-cp312-cp312-musllinux_1_2_x86_64.whl CPython 3.12 CPython 3.12 Linux musl 1.2+ x86-64 Details
camas-0.1.31-cp312-cp312-musllinux_1_2_aarch64.whl CPython 3.12 CPython 3.12 Linux musl 1.2+ ARM64 Details
camas-0.1.31-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
camas-0.1.31-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 Details
camas-0.1.31-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
camas-0.1.31-cp311-cp311-win_arm64.whl CPython 3.11 CPython 3.11 Windows ARM64 Details
camas-0.1.31-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
camas-0.1.31-cp311-cp311-musllinux_1_2_x86_64.whl CPython 3.11 CPython 3.11 Linux musl 1.2+ x86-64 Details
camas-0.1.31-cp311-cp311-musllinux_1_2_aarch64.whl CPython 3.11 CPython 3.11 Linux musl 1.2+ ARM64 Details
camas-0.1.31-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
camas-0.1.31-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 Details
camas-0.1.31-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details

Total release size: 28.9 MB

Release files / camas-0.1.31.tar.gz

Download URL camas-0.1.31.tar.gz
Size 262.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c6191de6246b977268d450bf1574b36b5942063b51a5abd2480720dbb0470309
BLAKE2b-256 checksum
How to use checksums
05054c367507b34ce163725feeb562e366b51f1ec72f224655a9fb1301b6664e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp314-cp314-win_arm64.whl

Download URL camas-0.1.31-cp314-cp314-win_arm64.whl
Size 685.2 kB
Tags CPython 3.14 Windows ARM64
SHA-256 checksum
How to use checksums
934b91509ef3b559eb9599bf59182233a58a651e3b12719789ff500124538c67
BLAKE2b-256 checksum
How to use checksums
4d4dd08e67650bea2b807838149a8dfa3f43677f9e07d54b973950245df2636d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp314-cp314-win_amd64.whl

Download URL camas-0.1.31-cp314-cp314-win_amd64.whl
Size 716.3 kB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
017c2f993ba088897b6d0bb4360fb3b85e19315662f87d77dfe120d9e81e28f8
BLAKE2b-256 checksum
How to use checksums
c75e6c6110af488074e90b7c54c8c125696e1f0b3ac48813863a5c0cc1f44779
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp314-cp314-musllinux_1_2_x86_64.whl

Download URL camas-0.1.31-cp314-cp314-musllinux_1_2_x86_64.whl
Size 1.3 MB
Tags CPython 3.14 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
ca6d939ed8f0bc2fc3f77b63bce9b30e970b885aa5ae5a49c8f78ca4bf376bd6
BLAKE2b-256 checksum
How to use checksums
19055f5c3c28bfd27b0b937728104e8e7b51ecc986430b6eb32da986caa83534
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp314-cp314-musllinux_1_2_aarch64.whl

Download URL camas-0.1.31-cp314-cp314-musllinux_1_2_aarch64.whl
Size 1.2 MB
Tags CPython 3.14 Linux musl 1.2+ ARM64
SHA-256 checksum
How to use checksums
270809effb6503ed8adfb3c14a83249fafbd0f048606146119c51f0b0f5e71b9
BLAKE2b-256 checksum
How to use checksums
0df39d093501102b96de00c483f059dcdb77753f4b2af82551c8d70ceb416c16
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL camas-0.1.31-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.3 MB
Tags CPython 3.14 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
9e366ba0f5bda4d257b093580fd84a050a0c6e6f34fb8fc3f57a7b3c693ef275
BLAKE2b-256 checksum
How to use checksums
f4271dd64c01a2d48926da22d7488c35ccaeb49458ba114590ab835bc27ec93e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL camas-0.1.31-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 1.2 MB
Tags CPython 3.14 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
c3fb279923b6fc021b38232fd664e60272041089b7d340535bc4490205f3d74d
BLAKE2b-256 checksum
How to use checksums
e3bb6f7c94aa64a4ee34e69291a8bf4c25f47e5720e36e7a3397f2a876e3ae71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp314-cp314-macosx_11_0_arm64.whl

Download URL camas-0.1.31-cp314-cp314-macosx_11_0_arm64.whl
Size 855.2 kB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d286c8b1067d659bc18b6c1b7ac1654a0e7b7f489a10992bea18d60f973668cd
BLAKE2b-256 checksum
How to use checksums
bc5c52e1c25ff0ab1e70ad369eb4225099a84b19ae3221506254b74557ea7990
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp313-cp313-win_arm64.whl

Download URL camas-0.1.31-cp313-cp313-win_arm64.whl
Size 672.5 kB
Tags CPython 3.13 Windows ARM64
SHA-256 checksum
How to use checksums
e6ce88633d30a5a3530253f6cbd2e25403a3a7085032aadf2eabb62b143c34ae
BLAKE2b-256 checksum
How to use checksums
55132987482dc5fb1683443bc831d4dda251d909db7d254cf09339b12c70bea4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp313-cp313-win_amd64.whl

Download URL camas-0.1.31-cp313-cp313-win_amd64.whl
Size 705.3 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
b61afbe49da8dde97cfcdd9ae577aa7740ca3945848603920d03ad04a573d101
BLAKE2b-256 checksum
How to use checksums
1264ca20e727917b64063aac04340c8c44247422bfafd88d0a5bbd05695e2de2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp313-cp313-musllinux_1_2_x86_64.whl

Download URL camas-0.1.31-cp313-cp313-musllinux_1_2_x86_64.whl
Size 1.3 MB
Tags CPython 3.13 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
f6892f7f82fb114a1665948fcd66a831374cd87f314d9e8c6e206e8451afdd22
BLAKE2b-256 checksum
How to use checksums
87d322032d3a2178f4e17b0e4afbe241807200aeeeef1e902117fda89f6aa220
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp313-cp313-musllinux_1_2_aarch64.whl

Download URL camas-0.1.31-cp313-cp313-musllinux_1_2_aarch64.whl
Size 1.2 MB
Tags CPython 3.13 Linux musl 1.2+ ARM64
SHA-256 checksum
How to use checksums
710d5b405746cdd68334940d7813f31c924becfccdf0cb95cabb5327cbd8ed52
BLAKE2b-256 checksum
How to use checksums
365e72f80bb31d0bbfef6cb4559dd3c3f64eb861a0a3bc4f849939978e2dedfb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL camas-0.1.31-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.3 MB
Tags CPython 3.13 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
df87cf9537d2cee598edb3818d4e3d4bb11ad15ea8ea354f77a14a562f87d63a
BLAKE2b-256 checksum
How to use checksums
cde93c593d001c5f49075c9df71c59d458430bc30bcb4f2a014246a26b41f173
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL camas-0.1.31-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 1.2 MB
Tags CPython 3.13 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
51dc51af4c87c0c77f3afd0a6da23799b9ff090e38ee648bb25bb9f4d2bd1b7a
BLAKE2b-256 checksum
How to use checksums
c40ed4bf64174888bce600225c25a5249a67d2ff63a6ec6f31222fdda27e6812
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp313-cp313-macosx_11_0_arm64.whl

Download URL camas-0.1.31-cp313-cp313-macosx_11_0_arm64.whl
Size 853.7 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
69d07c2b752dc182cced2a9e410df07a4dc528c26776aa2f31bcc966b89594e4
BLAKE2b-256 checksum
How to use checksums
ff6fb370c849acdf01239fc0d173a239b87f49e66e903f6211d8903e648fc4e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp312-cp312-win_arm64.whl

Download URL camas-0.1.31-cp312-cp312-win_arm64.whl
Size 672.7 kB
Tags CPython 3.12 Windows ARM64
SHA-256 checksum
How to use checksums
09b6b958e0737da0105b96bec9000d179b46a6662e00a378538365fc24ba2103
BLAKE2b-256 checksum
How to use checksums
655dbb8813855094b975a4a74fb33195a0441f9c1f80a288fb814fe131543c5f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp312-cp312-win_amd64.whl

Download URL camas-0.1.31-cp312-cp312-win_amd64.whl
Size 701.8 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
4a59fa2160b143399ef3edd8550694a03246eb0aaa5d6f0dbfe57e45e13c8bf1
BLAKE2b-256 checksum
How to use checksums
fd944f92e046d4b94bef4dd089b1d23553f787e4ef0e2b83fde059b6561c8cd3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp312-cp312-musllinux_1_2_x86_64.whl

Download URL camas-0.1.31-cp312-cp312-musllinux_1_2_x86_64.whl
Size 1.3 MB
Tags CPython 3.12 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
73002b496ad51fe51f7e8c2f1ce84cbe34cd41646c786936e51fc929804d03bc
BLAKE2b-256 checksum
How to use checksums
9c70f1e02ffb6da80d541308fbca54b326ea890c6821cbd3ea3562b07013e298
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp312-cp312-musllinux_1_2_aarch64.whl

Download URL camas-0.1.31-cp312-cp312-musllinux_1_2_aarch64.whl
Size 1.2 MB
Tags CPython 3.12 Linux musl 1.2+ ARM64
SHA-256 checksum
How to use checksums
a301f996cc20daecee7b83979e5e84a52c78ff11e3679426fc269ef82a3f1235
BLAKE2b-256 checksum
How to use checksums
612fe9577bff917d246387f921a75d33653756ddbd93efaceac95f36de25e7bf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL camas-0.1.31-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.3 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
fd92eaa672aab0115396a87dd71654026119d62e5594a1014ff3009bb2f94dc7
BLAKE2b-256 checksum
How to use checksums
9db9e2693b07be99a476aa548f8e121eecadc4b0614c77ef8b3991eb0654a504
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL camas-0.1.31-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 1.2 MB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
6ce838ed44eba4fcbecc85b2d814f72a4a2f8b4b8b30abcfe0c7122559e92f36
BLAKE2b-256 checksum
How to use checksums
0e7aeec1e39998e2b914de8dbec93815dee2b0297d3757076c0c786a58d71e5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp312-cp312-macosx_11_0_arm64.whl

Download URL camas-0.1.31-cp312-cp312-macosx_11_0_arm64.whl
Size 879.4 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
6866e93875a52e96a387a41ac2d78f39569d826da426ee716f97d36028220fb2
BLAKE2b-256 checksum
How to use checksums
752316dd318074ca12b78a2589d57e7159f4d9fbc24de0f8ce46d886483b33b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp311-cp311-win_arm64.whl

Download URL camas-0.1.31-cp311-cp311-win_arm64.whl
Size 669.6 kB
Tags CPython 3.11 Windows ARM64
SHA-256 checksum
How to use checksums
ecfc7120ba5cccb441a0d55287e2466577c9fd640841c93892f0ab34cd729a5d
BLAKE2b-256 checksum
How to use checksums
cb6b5b7dd371a2982f3deb487e591337151bedf8f7db1049b9440464307f3ca3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp311-cp311-win_amd64.whl

Download URL camas-0.1.31-cp311-cp311-win_amd64.whl
Size 701.5 kB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
fd59258a32002cbda738a6d6e6fed65f72b77127d1867bd8d273f54abe9a9dfe
BLAKE2b-256 checksum
How to use checksums
ff4e490a3f02e85a17356ca626856dcab0024a97db3e8771e0a0fb841c2f793e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp311-cp311-musllinux_1_2_x86_64.whl

Download URL camas-0.1.31-cp311-cp311-musllinux_1_2_x86_64.whl
Size 1.2 MB
Tags CPython 3.11 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
522762164cc8a48ed65b08b3cab18a9e4a3801eec9a773051d0445e924a2aba3
BLAKE2b-256 checksum
How to use checksums
fe5c13316bf98d445ef8359875a005859fc7f43f0e89ee755d50655439c0ebf5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp311-cp311-musllinux_1_2_aarch64.whl

Download URL camas-0.1.31-cp311-cp311-musllinux_1_2_aarch64.whl
Size 1.2 MB
Tags CPython 3.11 Linux musl 1.2+ ARM64
SHA-256 checksum
How to use checksums
60734a11fd59f7c3a19da49bed1e9138926d49c656dc24017509e03f68da2659
BLAKE2b-256 checksum
How to use checksums
dd07d13fae521a6a36d949f6dc5e436dbff6aee71568a0f3316d03db2feab4b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL camas-0.1.31-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.2 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
006b8940d1517b573f8d45ef7e90207bbf6bdeb3ae5764fb4778b1c104d2eb70
BLAKE2b-256 checksum
How to use checksums
b3b173d5d2eb0ac247a74704b39a9595b999321eeb3861142443b370e3540259
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL camas-0.1.31-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 1.2 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
72781e63ccb37bef0bebfe655fb009cf9b4994a2037d6d9ec393eb61987e6fa5
BLAKE2b-256 checksum
How to use checksums
898746d8300684ac9fe9d0fcb7c1b10e14284de15f5350dcf0d1bfd4e6a93da8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / camas-0.1.31-cp311-cp311-macosx_11_0_arm64.whl

Download URL camas-0.1.31-cp311-cp311-macosx_11_0_arm64.whl
Size 877.2 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
86178f6aaa528277fe502703a50bff8f4b69c090b252e8b2fc8ea8e5bb7d6204
BLAKE2b-256 checksum
How to use checksums
c5579d13f278e9365abdb8321cbc38341f1b63efc3d38664004ec3e439fe4fe7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page