chargehandBLOCK
Runs your request on coding agents (Claude Code, OpenCode) and returns an answer whose every citation is checked against a pinned commit. CLI, HTTP and MCP.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
[](https://github.com/Egoushka/chargehand/actions/workflows/ci.yml) [](https://scorecard.dev/viewer/?uri=github.com/Egoushka/chargehand) [](https://github.com/Egoushka/chargehand/releases) [](LICENSE)
chargehand turns a request into a typed Task Spec, runs it on one or more coding-agent sessions (OpenCode or Claude Code), and returns a result contract with evidence for every claim. People call it from a CLI; programs call it over HTTP or MCP.
Status: before 1.0 (the release badge shows the version). Workers are read-only by default; the code preset (since 0.8.0) makes one write a branch that passes its tests in a sandbox. See the changelog for what shipped, the roadmap for what comes next, and benchmarks for how it performs. The guide walks through using it, and what it does, and how we know gives each capability's status with its evidence.
Why
Coding agents answer in prose. A program that calls one needs something it can check: claims tied to files at a commit, diffs, session messages or caller inputs, plus a confidence and the exact prompt chain behind the answer.
chargehand keeps control flow (task graph, budgets, retries, parallelism) in code, not in a prompt. Each worker's context stays small, cached and disposable.
Non-goals: its own agent loop, direct calls to model providers, parallelism for its own sake.
How a run works
- Intake reads
request/v1and writes a Task Spec with one action. - The action decides what happens next:
answerruns one worker session.split
e25fa847faf5OBSERVED · 2026-10-14Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add chargehand-console --env ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} --env CHARGEHAND_E2E_PUSH_KEY=${CHARGEHAND_E2E_PUSH_KEY} --env CHARGEHAND_SPIKE_OAUTH_ITEM=${CHARGEHAND_SPIKE_OAUTH_ITEM} --env CLAUDE_CODE_OAUTH_TOKEN=${CLAUDE_CODE_OAUTH_TOKEN} -- npx -y [email protected]{
"mcpServers": {
"chargehand-console": {
"command": "npx",
"args": [
"-y",
"[email protected]"
],
"env": {
"ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}",
"CHARGEHAND_E2E_PUSH_KEY": "${CHARGEHAND_E2E_PUSH_KEY}",
"CHARGEHAND_SPIKE_OAUTH_ITEM": "${CHARGEHAND_SPIKE_OAUTH_ITEM}",
"CLAUDE_CODE_OAUTH_TOKEN": "${CLAUDE_CODE_OAUTH_TOKEN}"
}
}
}
}Trust audit
BLOCKgrade D · trust 64/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (9 observation(s))
- Network
- declared (10 observation(s))
- Shell
- declared (2 observation(s))
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (25)
field() { python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(eval(sys.argv[2]))" "$1" "$2" 2>/dev/null || echo ""; }field() { python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(eval(sys.argv[2]))" "$1" "$2" 2>/dev/null || echo ""; }curl -fsS "http://127.0.0.1:$DOCKER_PROXY_PORT/_ping" > /dev/null 2>&1 && break
curl -fsS "http://127.0.0.1:$DOCKER_PROXY_PORT/_ping" > /dev/null 2>&1 || fail "the socket proxy does not answer on 127.0.0.1:$DOCKER_PROXY_PORT (is OrbStack running, and the chargehand-docker-proxy c
def q: gsub("@"; "@") | gsub("<"; "<") | gsub("\r?\n|\r"; " ");.private-terms.example
import { accountsQuery } from '../../api/accounts';import type { AccountBody } from '../../api/common';import { formatDateTime, formatTime } from '../../lib/format';import { useIsPhone } from '../../shell/useIsPhone';} from '../../ui';
[InlineData("169.254.169.254", false)] // cloud metadata| C5 | Does an `http` entry with `headers` connect? | `<cfg>` = `{"mcpServers":{"ch":{"type":"http","url":"http://127.0.0.1:<port>/v1/mcp","headers":{"Authorization":"Bearer <key>"}}}}` against an own| O8 | Does a `remote` entry send `headers`? | `PUT` of `{"config":{"type":"remote","url":"http://127.0.0.1:<port>/v1/mcp","headers":{"Authorization":"Bearer <key>"}}}` against an own `chargehand serv- A place to push the branches. Nothing is ever pushed to an upstream. Either **a fork you own of each repository**, named as in the set (`guard-clauses`, `commander-js`, `more-itertools`, `joda-money
- The operator console's **Analytics** and **Learning** screens (ADR 0056, CHARGEHAND-208), at `/console/analytics` and `/console/learning`. Analytics reads `GET /v1/analytics` (`analytics/v1`) and `G
- The operator console's **Start a batch** screen (ADR 0056, CHARGEHAND-208), at `/console/new`. A preset, a repository from `GET /v1/repositories` with the commit filled from its HEAD, and a list of
- Actions on pull requests and tasks for the console (CHARGEHAND-214, third change): `POST /v1/batches/{id}/tasks/{task}/cancel`, `.../retry` and `.../session/stop`, and `POST /v1/pulls/{owner}/{repo}- Several runners (ADR 0058, CHARGEHAND-212), third change: a runner on another machine. A runner with `workspace: bundle` is sent the repository as a git bundle of the pinned commit (`git bundle crea
- A web UI at `/ui/` (ADR 0054, CHARGEHAND-203), off unless `http.ui` is `true`. Plain HTML, CSS and ES modules embedded in the server, no build step, no third-party code. Sign in by pasting an API ke
- The first deployment of driven sessions on a VPS is recorded (ADR 0039, the driven guide, the roadmap; CHARGEHAND-156): a draft pull request on the fourth attempt, the four defects each attempt foun
- The sandbox a writing run's tests will execute in (ADR 0035): `sandbox-exec` on macOS, `bwrap` on Linux, behind one interface; profile field `sandbox` (`kind`, `network`, `env`). A command may write
in a draft pull request. Open is the substituted credential (a gateway; until then the model credential is in the
ask-before-reading-`.env` rules no longer apply: a worker read `*.env.*` files without asking (found during the
Gates applied: no_behavioural_pass.
e25fa847faf5full audit observations/trust-audit/mcp-server/egoushka__chargehand.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-14 | e25fa847faf5 | BLOCK | D | 64 | first audit |
Questions
What is the chargehand MCP server?
Runs your request on coding agents (Claude Code, OpenCode) and returns an answer whose every citation is checked against a pinned commit. CLI, HTTP and MCP.
Is chargehand safe to connect to an agent?
No — not without reading the findings first. The audit graded it D (64/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on.
What credentials does chargehand need?
It reads ANTHROPIC_API_KEY, CHARGEHAND_E2E_PUSH_KEY, CHARGEHAND_SPIKE_OAUTH_ITEM, CLAUDE_CODE_OAUTH_TOKEN and OPENCODE_SERVER_PASSWORD from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does chargehand run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as chargehand-console at 0.0.0.
How current is this page?
The grade is for one exact copy of the source (e25fa847faf5), read on 2026-10-14. The repository is watched and re-audited when it changes.