Skip to main content

Agent-first CLI and agent owning the file-and-shell tool surface for AI coding agents: read, write, edit, list, view media, and gated shell execution, with path confinement and an operator approval policy. Pure-stdlib core, extracted from colleague so any host imports one safe execution layer.

Project description

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

Scaffold, with the release pipeline hardened. The agent-first CLI skeleton (whoami, learn, explain, overview, doctor, cli) is real and green, and publishing is gated on the full quality suite plus a built-wheel smoke test.

No operation, environment, policy, or runner has been built yet. The introspection verbs below are the entire implemented surface today.

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.

Every row below is a design target, not a description of shipped behaviour. Neither runner exists yet. The Intended guarantee column says what each combination is meant to provide once built; today it provides nothing, because there is nothing there. Read it as a specification, and do not rely on any row as a present-tense security property.

Workspace Runner Intended guarantee Built?
Checkout Host Guarded host execution; no isolation No
Worktree Host Reviewable/recoverable changes; no process isolation No
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 semanticswebglass-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 identityculture.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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shell_cli-0.8.7.tar.gz (293.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shell_cli-0.8.7-py3-none-any.whl (26.7 kB view details)

Uploaded Python 3

File details

Details for the file shell_cli-0.8.7.tar.gz.

File metadata

  • Download URL: shell_cli-0.8.7.tar.gz
  • Upload date:
  • Size: 293.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","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}

File hashes

Hashes for shell_cli-0.8.7.tar.gz
Algorithm Hash digest
SHA256 be1bc213ac12ba4112dbe6a0d7f20f9d6c841282b565f3984efe955b2b2297a6
MD5 d493f36caa2adf24c48c765f5d6ca7e3
BLAKE2b-256 c6b36df283aa5dc0d845a11f39cd92752e0835f4446cc8dcc9cecaf13343494a

See more details on using hashes here.

File details

Details for the file shell_cli-0.8.7-py3-none-any.whl.

File metadata

  • Download URL: shell_cli-0.8.7-py3-none-any.whl
  • Upload date:
  • Size: 26.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","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}

File hashes

Hashes for shell_cli-0.8.7-py3-none-any.whl
Algorithm Hash digest
SHA256 bac099e86a74aa696bf568956f48189ca1f7b69bf2a182eeb914845351fe54f3
MD5 18ea1e7219b54387e01a119bf476533c
BLAKE2b-256 ed5d0882f253c99fa8e878ba8f4b3b6af764f484ae68849d83d6d08be1473dc4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page