Skip to main content

Conning

A control room for your agent's test machines. Your agent (Claude Code, Codex, Cursor...) stays on your own laptop. Conning holds the keys to your lab VMs and gives the agent four lean tools to run commands and move files there. The agent never sees a password, and you approve anything risky.

Status: pre-alpha (M2 done). Running commands, long jobs, remote file reads and transfers work over OpenSSH, with pinned host keys, password or key auth, approvals and leases. You can approve in the agent client, in conn watch or with conn approve; conn doctor checks your setup. Long jobs run detached on Linux, macOS and Windows targets, and conn mcp install sets up claude, codex, cursor, opencode or pi. See docs/design.md for every decision so far.

Why

Putting an agent harness inside every CLI on every remote machine is redundant. Developers already have a capable agent on their own machine. What's missing is a safe, token-lean way for that agent to reach the machines it tests on:

  • No secrets in context. Targets hold references to the OS keychain, op:// or ssh-agent. Secrets are resolved inside Conning at the last moment and never returned by any tool.
  • Lean results. Exit code first, output capped at 8 KB by default (the agent may ask for more, up to a ceiling), with a handle to page the rest. Fan-out to many targets collapses identical results.
  • Guardrails in code, not in the prompt. Each target has a mode (observe, ask, lease). Commands outside the allowlist wait for your approval; "always allow" remembers two words, so systemctl status never lets through systemctl stop.
  • Plain OpenSSH underneath. Linux and Windows (OpenSSH + PowerShell 7), pinned host keys, forwarding forced off.

Install

uv tool install conning        # or: pipx install conning
conn mcp install claude        # or codex, cursor, opencode, pi: adds the server and denies raw ssh/scp

The MCP server needs no install at all:

claude mcp add conning -- uvx conning mcp

The agent's four tools

Tool What it does
targets(filter?, check?) One line per target: name, OS, shell, user, tags, mode. Never a host or secret.
run(target, cmd | argv, wait=30, max_bytes=8192, ...) Runs on one target, a list or tag:<tag>. Exit code first. Still running after wait seconds: returns a job id (wait=0 is async).
read(id, wait?, range?, grep?, signal?) Long-polls a job for new lines, pages a saved output, or reads a remote file.
transfer(source, dest) Copies files between local:<path> and <target>:<path>, checked by sha256.

Agents without MCP can use the same commands through the conn CLI; the output is identical.

For agents: CLI reference

This block is generated by conn help --markdown, so you don't need to call --help. A test keeps it in sync with the code.

conn targets [--check] [filter]
    List targets: name, OS, shell, user, tags, mode. Never hosts or secrets.

conn run [--wait WAIT] [--timeout TIMEOUT] [--cwd CWD] [--shell]
                [--max-bytes MAX_BYTES] [--grep GREP]
                target [argv ...]
    Run a command on one target, a list, or tag:<tag>. Exit code first.

conn read [--wait WAIT] [--range RANGE] [--grep GREP] [--signal {INT,TERM,KILL}]
                 [--max-bytes MAX_BYTES]
                 id
    Page a job (new lines only), a saved output, an approval, or a remote file.

conn transfer source dest
    Copy files: local:<path> to <target>:<path>, or back. sha256 checked.

conn add [--host HOST] [--user USER] [--like TARGET] [--port PORT]
                [--auth {ssh-agent,key,password}] [--secret SECRET] [--key KEY]
                [--os {linux,windows,darwin}] [--mode {observe,ask,lease}] [--tag TAG] [--retry]
                name
    Add a target. Without a terminal it is saved as pending until a human approves it.

conn approve [--always] what
    Human only: make a pending target live, or allow a pending command a:<id>.

conn import [--match MATCH]
    Import hosts from ~/.ssh/config as pending targets (unsafe options dropped).

conn rm name
    Remove a target and its pinned host key.

conn test name
    Probe a target: reachability, OS, shell, pinned host key.

conn lease [--minutes MINUTES] name
    Human only: give a target a full shell for a time box (1-60 minutes).

conn allow target [words ...]
    Human only: let a command run without asking (no words: list the rules).

conn deny target words [words ...]
    Remove an allow rule, so the command asks again.

conn watch [--history HISTORY] [--no-prompt]
    Live control room: every command on every target, job output, approval prompts.

conn doctor
    Check this machine's setup: config and state dirs, ssh, keychain, targets.

conn mcp [--approve-in-client | --no-approve-in-client] <serve|install> ...
    Run the MCP server on stdio, or install it into an agent client.

conn help [--markdown]
    Show this help; --markdown prints the block cached in README.md.

A target is one login on one machine. To use the same machine as another user, add it again: conn add lab-tester --like lab --user tester copies the host, port, OS and tags and asks for the new user's password. conn targets shows which user each target uses.

A target you add with conn add from an agent session is saved as pending. It does nothing until the human runs conn approve <name>, which shows the host, the pinned host-key fingerprint and where the secret comes from.

A command outside a target's allowlist returns status=pending_approval id=a:<id>, and a desktop notification tells the human. They answer in one of three places (allow once, always allow its first two words, or deny), and the agent picks up the result with read a:<id>:

  • In the agent client: any MCP client that supports elicitation shows the question before the command is queued, and an approved command runs in the same call. Clients without it fall back to the two below. If a client would answer such prompts by itself instead of asking you, run the server as conn mcp --no-approve-in-client.
  • In conn watch, which also shows every command and its output as it happens.
  • With conn approve a:<id> in any terminal. When you run conn run yourself at a terminal, it just asks you there and prints the result.

Read-only commands such as uname, hostname, df, ps, ls, ip addr, systemctl status and journalctl run without asking on every target; each is checked so its changing forms (hostname x, ip addr add) still ask, and safe = false in a target's entry turns the list off. conn allow <target> make test lets another command run without asking from then on; conn deny takes it back. Every command, answer and rule change lands in a hash-chained audit log, and conn doctor checks your setup when something doesn't work.

Safety model

Mode What the agent can do Default for
observe The built-in read-only list and allowlisted commands only; everything else is refused. targets tagged shared or prod
ask The built-in read-only list and allowlisted commands run; anything else waits for your approval. new lab targets
lease Any command, for a time box you grant (15 min default, 60 max). never by default
  • No tool returns a secret, adds a live target or changes policy.
  • Secrets travel over stdin or the SSH channel's env, never argv. Output is redacted before it is saved.
  • Remote output is marked untrusted. Shell wrappers (sh -c, python -c, sudo...) and shell syntax (;, |, $(...)) always ask.
  • conn mcp install also denies the agent raw ssh/scp, so it can't go around Conning (pi has no permission rules, so there it only adds the server).
  • The audit log is hash-chained. It runs as your user, so it is tamper-evident, not tamper-proof.

Development

uv sync
uv run pytest --cov=conning      # CI requires 95% coverage on Linux
uv run ruff check && uv run ruff format --check

After changing the CLI, refresh the README block with uv run conn help --markdown.

Docs

License

Apache-2.0

Metadata

Release files for conning 0.2.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 conning 0.2.0
File Size Uploaded
conning-0.2.0.tar.gz 182.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for conning 0.2.0
File Interpreter ABI Platform
conning-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 241.4 kB

Release files / conning-0.2.0.tar.gz

Download URL conning-0.2.0.tar.gz
Size 182.1 kB
Tags Source
SHA-256 checksum
How to use checksums
5212d1df6b86c7eb9f90cbbe6c48a025d12f0046ed396a097a5a5d4cb88ae2df
BLAKE2b-256 checksum
How to use checksums
eb5b2f64af487e8b5411b5ca207b5623f8c0088765126b619e658d6ac0edc382
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 15, 2026.

Transparency log

Release files / conning-0.2.0-py3-none-any.whl

Download URL conning-0.2.0-py3-none-any.whl
Size 59.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a33a2e94777171181ca287719f04f7e716b64bba2e852b6d9fbe09da23710976
BLAKE2b-256 checksum
How to use checksums
eb794d8144d0b1cef5725007f0779146361c58d670008f9ced7413e3e09e13c7
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 15, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

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