Skip to main content

shell-cli

The guarded local operations plane for AI agents.

An agent harness has to touch the local machine constantly — read a file, write one, run a command, run the tests, run a linter, fire a hook, drive git, invoke a trusted CLI. Every harness reimplements that surface, and reimplements its safety model with it, usually worse each time.

shell-cli provides one place to plan, authorize, execute, observe, and record a local operation. It does not decide why, when, or which — that is the calling harness's job. It is not another agent: it contains no model, planner, memory, web browser, or domain workflow. It is the execution substrate beneath them.

colleague is the first consumer, not the owner. colleague imports shell-cli; shell-cli imports nothing from colleague.

Repo token shell-cli, console command shell, import package shell, PyPI distribution shell-cli.

⚠️ A guard, not a sandbox

Read this before you rely on anything here.

The execution gate is best-effort. It inspects the command string it is handed, so it is bypassable by sh -c, pipelines, shell expansion, here-docs, and any interpreter that takes code as an argument. There is no namespace, container, or seccomp isolation.

It protects against accidental and careless model behaviour. It does not protect against an adversarial one, and it is not a security boundary to put untrusted input behind.

A container runner is planned, and when it lands it will be described separately: a declared boundary with a documented profile, recorded per operation. It will not retroactively change what the host path above provides. The two claims stay textually separate on purpose.

Full detail — assets, actors, known bypasses, and what real isolation would require — in docs/threat-model.md. The same posture is readable in-band via shell explain safety, and tests/test_honesty.py fails the build if any shipped surface drops the disclaimer or claims isolation.

Status

The operation core is built, and the CLI has started catching up to it. The library has Operation, OperationResult, Environment, the ported policy evaluator, the evidence contract, and a HostRunner with real execution — fs.read, fs.list, fs.stat, fs.write, fs.edit, fs.media, process.exec, and process.shell are all built and green.

The CLI exposes the introspection verbs (whoami, learn, explain, overview, doctor, cli), two operation-aware nouns — policy check/policy explain evaluate the same gate execute() uses, and operation show retrieves persisted evidence — and two groups whose verbs execute operations: shell fs read|list|stat|write|edit|media and shell process exec|shell. They front operations.execute() rather than reimplementing anything, so the CLI and the library share one engine. Mutation and execution verbs preview by default and require --apply, and the flag is derived from each kind's registered intent rather than hand-maintained. process shell accepts the project profile only — a raw string is re-interpreted by a shell after the gate read it, so it cannot honestly carry control-plane trust.

shell env describe renders the selected environment's two axes and the runner's posture. env create/env destroy are deliberately absent until the lifecycle engine exists, rather than shipped as a facade.

Still library-only: the git noun group does not exist yet, and neither does a container runner or colleague delegation. Publishing is gated on the full quality suite plus a built-wheel smoke test.

Issue #1 is the source of truth for scope; the converged spec and the buildable plan live in docs/specs/ and docs/plans/.

The model

An operation is any local observation, mutation, process invocation, or environment lifecycle action. The boundary is work-affecting I/O — not every internal byte a runtime writes. Every operation follows one lifecycle:

intent -> Operation -> policy + preview -> environment backend
       -> result + evidence -> caller

Environments have two independent axes

"Host", "worktree" and "container" are not one overloaded mode. A workspace axis selects what may be observed and changed; a runner axis selects what executes it.

The Container rows are a design target, not a description of shipped behaviour. HostRunner is built and is what every shipped operation runs through today; ContainerRunner does not exist yet. The Intended guarantee column says what each combination provides for the Host rows now, and what the Container rows are meant to provide once built — read the Container rows as a specification and do not rely on them as a present-tense security property.

Workspace Runner Intended guarantee Built?
Checkout Host Guarded host execution; no isolation Yes
Worktree Host Reviewable/recoverable changes; no process isolation Yes
Checkout Container Execution isolation against the selected checkout No
Worktree Container Preferred autonomous mode No

When the container rows are built, their actual profile gets measured and recorded per operation, and documented separately from the host claim above. Until then the honest summary of what shell-cli isolates is: nothing.

Three operation profiles

Every subprocess declares why it is running, because not all of them deserve equal trust.

  • project — executes repository-controlled code: model-issued commands, tests, linters, repo hooks.
  • control — executes trusted control-plane programs: git mechanics, neighbouring AgentCulture CLIs, the container engine itself. Argv vectors only; raw shell strings are not appropriate here.
  • observe — structured reads confined to the selected root.

Evidence is a product surface

Every operation produces a structured record suitable for the model, the operator, telemetry, and an external validator: what was requested and how it normalized, the policy verdict, the environment and runner, timing and exit status, separately captured stdout/stderr with truncation markers, and the known filesystem/git effects — plus an honest marker for whether that effect list is complete. Secrets are never recorded, and a failure to capture evidence never turns an executed action into an unrecorded success.

Constraints that hold it together

  • Pure-stdlib core, zero base dependencies. dependencies = [], guarded by a test. colleague allow-lists exactly its sanctioned base deps; a third-party dependency here means colleague cannot import this package at all. Optional integrations go behind extras.
  • A guard, not a sandbox — see above.
  • Mutation and execution preview by default. The CLI requires --apply; imported callers must pass apply=True explicitly. A preview is never reported as success — it gets its own status.
  • Library first, CLI second. The CLI is a front end over the same operation engine, never a second implementation.
  • Every PR bumps the version — every push to main publishes to PyPI. See docs/release-runbook.md.

Quickstart

uv sync
uv run pytest -n auto                 # run the test suite
uv run shell whoami                   # identity from culture.yaml
uv run shell learn                    # self-teaching prompt (add --json)
uv run shell explain safety           # the safety posture, in-band
uv run teken cli doctor . --strict    # the agent-first rubric gate CI runs

CLI

Verb What it does
whoami Report this agent's nick, version, backend, and model from culture.yaml.
learn Print a structured self-teaching prompt.
explain <path> Markdown docs for any noun/verb path (explain safety for the threat model).
overview Read-only descriptive snapshot of the agent.
doctor Check the agent-identity invariants (prompt-file-present, backend-consistency).
cli overview Describe the CLI surface itself.

Every command supports --json. Results go to stdout, errors/diagnostics to stderr (never mixed). Exit codes: 0 success, 1 user error, 2 environment error, 3+ reserved.

Non-goals

shell-cli is deliberately not a general agent layer. It owns local operation mechanics and nothing else:

  • reasoning, planning, roles, or agent orchestration — colleague's job
  • model APIs or prompt construction
  • web search and navigation semantics — webglass-cli owns them, as a separate repository and a separate colleague capability seam. shell-cli does not embed a browser and does not model web actions as local operations. Only provider-neutral artifact transfer crosses between the two: a file webglass produces is just a file shell-cli can be asked to read.
  • memory semantics — eidetic-cli owns them
  • PR policy, acceptance judgment, or handoff decisions
  • claiming containers are perfect isolation, or that worktrees contain anything

Repo furniture

  • Mesh identity — culture.yaml (suffix + backend) and the matching resident prompt file (AGENTS.colleague.md, since this agent runs backend: colleague). CLAUDE.md is the Claude Code prompt and the contributor guide.
  • The canonical guildmaster skill kit under .claude/skills/, vendored cite-don't-import. Provenance and the re-sync procedure: docs/skill-sources.md.
  • Build + deploy baseline — pytest, lint, the agent-first rubric gate, and PyPI Trusted Publishing wired into GitHub Actions.

License

Apache 2.0 — see LICENSE.

Metadata

Release files for shell-cli 0.14.0

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

Source distribution (sdist)

Source distribution for shell-cli 0.14.0
File Size Uploaded Provenance
shell_cli-0.14.0.tar.gz 590.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for shell-cli 0.14.0
File Interpreter ABI Platform
shell_cli-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 737.6 kB

Release files / shell_cli-0.14.0.tar.gz

Download URL shell_cli-0.14.0.tar.gz
Size 590.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1017a0ac175767da95cb0fe8c2fbaee8a441e0b51b5ea8b1681c7e3ed6b8fc01
BLAKE2b-256 checksum
How to use checksums
42f95061fc8d021aa0e9da6be8b66e435afcfabde7fb3748303939fb7d592c88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / shell_cli-0.14.0-py3-none-any.whl

Download URL shell_cli-0.14.0-py3-none-any.whl
Size 147.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1421c4de9729189416a09907ba0bdd15a6bbd491bbbee78bd6ee7017accd117a
BLAKE2b-256 checksum
How to use checksums
3f3aac37507b8c37e07b2d719b4b5c313c566a835ddfa4cf0f78ab1f295f4e66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for shell-cli 0.14.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

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