tare-cli 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tare_cli-0.2.0/.gitignore +9 -0
- tare_cli-0.2.0/CONCEPT.md +308 -0
- tare_cli-0.2.0/LICENSE +21 -0
- tare_cli-0.2.0/PKG-INFO +505 -0
- tare_cli-0.2.0/README.md +481 -0
- tare_cli-0.2.0/pyproject.toml +48 -0
- tare_cli-0.2.0/src/tare/__init__.py +1 -0
- tare_cli-0.2.0/src/tare/agents.py +672 -0
- tare_cli-0.2.0/src/tare/calibrate.py +98 -0
- tare_cli-0.2.0/src/tare/capsule.py +246 -0
- tare_cli-0.2.0/src/tare/cli.py +312 -0
- tare_cli-0.2.0/src/tare/cliff.py +183 -0
- tare_cli-0.2.0/src/tare/dashboard.html +269 -0
- tare_cli-0.2.0/src/tare/dashboard.py +216 -0
- tare_cli-0.2.0/src/tare/fake.py +183 -0
- tare_cli-0.2.0/src/tare/journal.py +35 -0
- tare_cli-0.2.0/src/tare/judge.py +108 -0
- tare_cli-0.2.0/src/tare/overview.html +78 -0
- tare_cli-0.2.0/src/tare/probe.py +273 -0
- tare_cli-0.2.0/src/tare/recipe.py +102 -0
- tare_cli-0.2.0/src/tare/room.py +67 -0
- tare_cli-0.2.0/src/tare/swap.py +219 -0
- tare_cli-0.2.0/src/tare/trail.py +203 -0
- tare_cli-0.2.0/src/tare/usage.py +237 -0
- tare_cli-0.2.0/tests/test_agents.py +9 -0
- tare_cli-0.2.0/tests/test_agy.py +47 -0
- tare_cli-0.2.0/tests/test_calibrate.py +95 -0
- tare_cli-0.2.0/tests/test_cliff.py +171 -0
- tare_cli-0.2.0/tests/test_dashboard.py +150 -0
- tare_cli-0.2.0/tests/test_fake.py +68 -0
- tare_cli-0.2.0/tests/test_judge.py +42 -0
- tare_cli-0.2.0/tests/test_pi.py +90 -0
- tare_cli-0.2.0/tests/test_probe.py +221 -0
- tare_cli-0.2.0/tests/test_room.py +112 -0
- tare_cli-0.2.0/tests/test_swap.py +133 -0
- tare_cli-0.2.0/tests/test_usage.py +103 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# tare: concept
|
|
2
|
+
|
|
3
|
+
tare starts a coding agent in an isolated room without your personal setup, and proves the room
|
|
4
|
+
clean before the run. It prints `tare: 0.00`, names every leak and where it came from, or says
|
|
5
|
+
that it could not see your setup (`tare: not proven (blind)`). It refuses to start the agent
|
|
6
|
+
until the reading is `tare: 0.00`, unless you pass `--allow-dirty`. It supports Claude Code, Codex, Pi
|
|
7
|
+
and the Antigravity CLI (`agy`) on Linux and WSL.
|
|
8
|
+
|
|
9
|
+
This document describes the design and the measurements behind it. The [README](README.md)
|
|
10
|
+
explains the words this document uses: room, probe, reading, leak, declared, dirty twin, check, tail and
|
|
11
|
+
handoff. Every claim marked **measured** was observed on WSL2. The section
|
|
12
|
+
[Measurements](#measurements) lists the agent versions and links each result.
|
|
13
|
+
|
|
14
|
+
## Why
|
|
15
|
+
|
|
16
|
+
Skill and agent evaluations compare runs with a skill against runs without it. If the agent
|
|
17
|
+
brings your own instructions, memories, skills or connected accounts into both runs, the
|
|
18
|
+
comparison measures your machine, not the skill. Evaluation frameworks that drive several agent
|
|
19
|
+
CLIs exist (see [Prior art](#prior-art)), but they expect you to provide a clean environment.
|
|
20
|
+
None of them checks that the environment is clean.
|
|
21
|
+
|
|
22
|
+
## Three layers
|
|
23
|
+
|
|
24
|
+
tare keeps your setup out in three layers. Each layer closes a gap that the one before leaves
|
|
25
|
+
open.
|
|
26
|
+
|
|
27
|
+
### 1. Context: nothing of your setup reaches the model
|
|
28
|
+
|
|
29
|
+
A separate config directory (`CLAUDE_CONFIG_DIR`, `CODEX_HOME`) and a separate `HOME` remove
|
|
30
|
+
your instructions, memories, plugins, hooks and skills. That is not enough.
|
|
31
|
+
|
|
32
|
+
- **Measured:** the login brings context that lives in no config directory. With only a
|
|
33
|
+
separate config directory, a Claude Code session still had the connected accounts
|
|
34
|
+
(mail, calendar, documents) as live tools, the account's skills and the account email.
|
|
35
|
+
`--strict-mcp-config` and `--setting-sources project,local` removed the connected accounts and
|
|
36
|
+
the account skills. The email stays with a subscription login. An API key login without OAuth
|
|
37
|
+
should remove it, but that has not been tested.
|
|
38
|
+
- Codex: `CODEX_HOME` does not move `~/.agents/skills`, so Codex still reads your real skills
|
|
39
|
+
there. Account plugins can also bring personal skills back after the login. tare starts Codex with `--disable remote_plugin` and an empty
|
|
40
|
+
home directory.
|
|
41
|
+
- Claude Code's own bundled skills stay visible. They belong to the product, not to you.
|
|
42
|
+
|
|
43
|
+
### 2. Containment: nothing of yours within reach
|
|
44
|
+
|
|
45
|
+
- **Measured:** with the context layer alone, any process in the session can still read your
|
|
46
|
+
real `~/.claude/CLAUDE.md`, `~/.claude/.credentials.json`, `~/.codex/auth.json` and the
|
|
47
|
+
project's `.env` files. An agent with shell access and skipped permission prompts is one `cat`
|
|
48
|
+
away.
|
|
49
|
+
- So tare runs the agent in a room built with bubblewrap (user namespaces, no root). The room
|
|
50
|
+
mounts an empty `/home`, then only the room's own home directory and the project. Your real
|
|
51
|
+
files do not exist inside. On WSL, `/etc/resolv.conf` points into `/mnt/wsl`, so the room
|
|
52
|
+
mounts `/mnt/wsl` read-only, or DNS fails.
|
|
53
|
+
- **Measured:** the first prototype (`prototypes/bwrap-room.sh`) passed the calling shell's
|
|
54
|
+
environment into the room, and a secret-like variable was visible inside. tare therefore
|
|
55
|
+
clears the environment and passes only an allowlist (`TERM`, `COLORTERM`, `LANG`, `LC_ALL`).
|
|
56
|
+
- The room holds a usable login on purpose, a copy of yours. **Measured:** a stale copy fails to
|
|
57
|
+
renew (`OAuth session expired`), so tare takes a fresh copy at every start and deletes it
|
|
58
|
+
afterwards.
|
|
59
|
+
|
|
60
|
+
### 3. Proof: measured, not asked
|
|
61
|
+
|
|
62
|
+
- Asking the agent what it sees is a self-report, and the agent can refuse. **Measured:** Claude
|
|
63
|
+
Code in a room refused a scripted request to list the home directory and search for
|
|
64
|
+
credential files, and called it reconnaissance. That is correct behaviour, but useless for a
|
|
65
|
+
probe. The probe must not depend on the agent's cooperation or honesty.
|
|
66
|
+
- **Reach:** a plain script runs inside the room and looks for your files and inherited
|
|
67
|
+
environment variables.
|
|
68
|
+
- **Context:** tare points the real agent CLI at a fake model server on your machine. The
|
|
69
|
+
server keeps the request, which is the context the agent CLI put together, and answers "ok".
|
|
70
|
+
The idea is the blank run from analytical chemistry, which runs the whole procedure without a
|
|
71
|
+
sample to see what the procedure itself brings in.
|
|
72
|
+
- **Control:** the same agent run in your real setup, the dirty twin, must show your context. The
|
|
73
|
+
risk was that features that come with the login (connected accounts, account skills) would
|
|
74
|
+
not load against a fake server, so the probe would read clean while a real run is not.
|
|
75
|
+
**Measured:** for Claude Code this risk did not occur. Against the fake model server, the
|
|
76
|
+
dirty twin still loaded the connected accounts, account skills, plugin skills, hook output,
|
|
77
|
+
global instructions, memories and the email. The room loaded none of them except the email.
|
|
78
|
+
Pointing Claude Code at a custom base URL turns its tool search off and puts every tool schema
|
|
79
|
+
into the request. So the probe and the runs set `ENABLE_TOOL_SEARCH=true` to see the context as
|
|
80
|
+
a normal run does.
|
|
81
|
+
|
|
82
|
+
## The parts of tare
|
|
83
|
+
|
|
84
|
+
### Room
|
|
85
|
+
|
|
86
|
+
A room is a bubblewrap sandbox for one agent run: an empty `/home` with the room's own home
|
|
87
|
+
directory at `/home/tare`, a fresh copy of the login, the agent's executable, the project at
|
|
88
|
+
`/work`, and the environment allowlist. `tare claude` and the other agent commands mount your
|
|
89
|
+
project directly, so the agent changes your real files. Calibrate, Swap and Cliff give every run
|
|
90
|
+
its own copy of the project. The room has network access and a working login. It keeps your setup out of the measurement. It does not protect your machine from a hostile
|
|
91
|
+
agent.
|
|
92
|
+
|
|
93
|
+
Claude Code may replace its login token when it renews it, which could log out your real
|
|
94
|
+
session. This has not been tested, so tare refuses to start when the copy would need renewal
|
|
95
|
+
within the next hour. **Measured:** the Antigravity CLI's Google login keeps its refresh token
|
|
96
|
+
when it renews, so a room may renew its own copy.
|
|
97
|
+
|
|
98
|
+
### Probe and reading
|
|
99
|
+
|
|
100
|
+
The probe has the three parts of layer 3: the agent in the room against the fake model server,
|
|
101
|
+
the dirty twin, and the reach script. It sorts what it finds into **kinds of context**,
|
|
102
|
+
each checked on its own: instructions, memories, home path, MCP servers (connected accounts count
|
|
103
|
+
here), skills, plugins, extensions, instruction files above the project, the account email, and
|
|
104
|
+
reach.
|
|
105
|
+
|
|
106
|
+
- A kind of context counts only when you have it. tare learns that from your files, for example
|
|
107
|
+
a global instructions file or a skill folder.
|
|
108
|
+
- If you have a kind of context and the dirty twin does not show it, the probe could not see
|
|
109
|
+
it. tare then runs the dirty twin once more after 10 seconds. If the second dirty twin still
|
|
110
|
+
does not show that kind of context, the reading is `tare: not proven (blind)`. **Measured:**
|
|
111
|
+
with six runs starting together, a dirty twin sent its request before its MCP servers were
|
|
112
|
+
connected.
|
|
113
|
+
- Every probe makes no paid model call, because both the room and the dirty twin talk to the
|
|
114
|
+
fake model server.
|
|
115
|
+
|
|
116
|
+
### Agents
|
|
117
|
+
|
|
118
|
+
Each agent needs its own way to the fake model server, its own login copy and its own markers:
|
|
119
|
+
lines of your own files that the probe looks for in a request.
|
|
120
|
+
|
|
121
|
+
| Agent | How the room is set up | Way to the fake model server | Kinds of context the dirty twin showed on the measuring machine |
|
|
122
|
+
|---|---|---|---|
|
|
123
|
+
| Claude Code | `CLAUDE_CONFIG_DIR` and `HOME` in the room, a copy of `.credentials.json`, `--strict-mcp-config --setting-sources project,local` | `ANTHROPIC_BASE_URL` | instructions, home path, MCP servers, skills, plugins, email, reach |
|
|
124
|
+
| Codex | `CODEX_HOME` and `HOME` in the room, a copy of `auth.json` only, `--disable remote_plugin` | `-c openai_base_url=<server>/v1` keeps the ChatGPT login | instructions, memories, home path, skills, reach |
|
|
125
|
+
| Pi | `PI_CODING_AGENT_DIR` and `HOME` in the room, copies of `auth.json` and `models.json`, a minimal `settings.json`, no flags | a provider of its own (`tare`, api `anthropic-messages`), because Pi has no base-URL variable | instruction files above the project, extensions, home path, reach |
|
|
126
|
+
| Antigravity CLI | `HOME` in the room, a copy of `antigravity-oauth-token` and the chosen model, no flags | `CLOUD_CODE_URL` | home path, reach. Global rules (`~/.gemini/GEMINI.md`) and global skills (`~/.gemini/config/skills/`) showed after copies were placed in the setup for the test, because the measuring machine had none. |
|
|
127
|
+
|
|
128
|
+
What each agent needed:
|
|
129
|
+
|
|
130
|
+
- **Codex:** without `--disable enable_request_compression`, the request arrives compressed.
|
|
131
|
+
Codex tries a websocket five times before it falls back to HTTPS, and it refuses an override
|
|
132
|
+
of its built-in provider that would stop this. So each Codex probe waits about 8 seconds. **Measured:** the captured
|
|
133
|
+
request holds more than `codex debug prompt-input` shows, because Codex's own view leaves out
|
|
134
|
+
the memories. Memories load only when your `config.toml` enables `[features] memories`. Hooks
|
|
135
|
+
did not fire in one-shot runs, and the first request offered no tools from configured MCP
|
|
136
|
+
servers, so the probe cannot check those two kinds of context for Codex. The room has no
|
|
137
|
+
`config.toml` or `hooks.json` of yours, so neither can come in. A fresh `CODEX_HOME` means
|
|
138
|
+
Codex's default model. Pass `-m` when you compare runs.
|
|
139
|
+
- **Pi:** a fresh agent directory is clean on its own and keeps the project's `AGENTS.md`, so the
|
|
140
|
+
room uses no flags. `--no-context-files` would drop the project's `AGENTS.md`. tare finds Pi's
|
|
141
|
+
extension tools by comparing the dirty twin's tools with a run that uses `--no-extensions`.
|
|
142
|
+
With standard input left open, Pi waits for piped input and never answers, so tare closes it.
|
|
143
|
+
- **Antigravity CLI:** the fake model server speaks Google's Cloud Code `v1internal` API and
|
|
144
|
+
offers one model. It lists that model in the groups the CLI shows models in
|
|
145
|
+
(`agentModelSorts`), because the CLI rejects a model that no group lists. The
|
|
146
|
+
CLI writes into `~/.gemini` on every run, so its dirty twin runs with an overlay over
|
|
147
|
+
`~/.gemini`. A user namespace mounts the overlay, and every write goes to a temporary file
|
|
148
|
+
system that disappears after the run. **Measured:** `~/.gemini` kept its fingerprint (paths,
|
|
149
|
+
sizes, modification times) through every dirty twin. The CLI writes each skill's path into
|
|
150
|
+
its skill list, so the probe compares skill lines without the path. Without that, a skill that
|
|
151
|
+
leaked into the room would not match yours, because its path differs.
|
|
152
|
+
- **Instruction files above the project:** Claude Code's one-shot mode, which the probe uses, did
|
|
153
|
+
not load `~/AGENTS.md`. Pi loaded it. So for Claude Code the probe does not show whether an
|
|
154
|
+
interactive session in your real setup loads these files. A room has no parent directories, so these files
|
|
155
|
+
cannot reach a room.
|
|
156
|
+
- **Long prompts:** Linux limits a single argument to about 128 KiB. tare passes the task to
|
|
157
|
+
every agent as an argument, so a longer task fails. Pi could read it from a file with `@file`.
|
|
158
|
+
|
|
159
|
+
### Capsules, trail and handoff
|
|
160
|
+
|
|
161
|
+
Calibrate, Swap and Cliff need a run they can stop and continue. During a recorded run, a hook
|
|
162
|
+
archives the workspace after every tool call. Each archive is a **capsule**. The hook comes from
|
|
163
|
+
`--settings` for Claude Code, from the room's `hooks.json` for Codex (with
|
|
164
|
+
`--dangerously-bypass-hook-trust`), from a small extension for Pi, and from a global
|
|
165
|
+
`PostToolUse` hook in the room's `~/.gemini/config/hooks.json` for the Antigravity CLI.
|
|
166
|
+
|
|
167
|
+
A run continues from a capsule in one of two ways:
|
|
168
|
+
|
|
169
|
+
- **Its own saved session.** Claude Code resumes the conversation cut after the step. Codex
|
|
170
|
+
resumes a session file cut after the step, with `codex exec resume <id>`. Pi resumes with
|
|
171
|
+
`--session`. **Measured:** a resumed Codex session kept its id and finished the remaining plan
|
|
172
|
+
from step 1.
|
|
173
|
+
- **A handoff.** The **trail** is a record of a run in the same format for every agent: the task,
|
|
174
|
+
the messages, the tool calls and their results. tare writes a handoff from any prefix of it, so
|
|
175
|
+
any agent can continue any run without reading another agent's session format. The Antigravity
|
|
176
|
+
CLI stores its sessions in a format that tare cannot cut, so it always continues with a
|
|
177
|
+
handoff. Its trail comes from `transcript_full.jsonl`.
|
|
178
|
+
|
|
179
|
+
### Calibrate
|
|
180
|
+
|
|
181
|
+
`tare calibrate` starts each side (an agent with its arguments) several times from a fresh copy
|
|
182
|
+
of the project and reports each side's pass rate with a 95% interval (Wilson). A side can have
|
|
183
|
+
its own prompt, so two skills that start with different commands compare in one call. Without a
|
|
184
|
+
check, a run counts as finished when its agent exits with 0, and tare keeps its workspace for
|
|
185
|
+
scoring elsewhere. **Measured:** in a field test that compared two ideation skills, 18 rooms all
|
|
186
|
+
read `tare: 0.00`, including a skill that started `claude -p` inside the room (see
|
|
187
|
+
[Measurements](#measurements)).
|
|
188
|
+
|
|
189
|
+
### Judge
|
|
190
|
+
|
|
191
|
+
The judge scores results that no test can decide, such as a web page. tare opens the page in
|
|
192
|
+
headless Google Chrome inside a room with the workspace read-only and no home directory, and
|
|
193
|
+
takes a screenshot. A judge agent (Claude Code with Sonnet by default) then scores the page from
|
|
194
|
+
the screenshot, the source and a rubric, in a fresh room without any agent or model names.
|
|
195
|
+
**Measured:** one test page scored 55, 60, 58, 58, 66 and 62 in six judgements. `tare judge-noise`
|
|
196
|
+
therefore refuses a threshold that lies inside a page's range of scores. On the same page the
|
|
197
|
+
judge found a real one-cent rounding bug and an overflow.
|
|
198
|
+
|
|
199
|
+
### Swap
|
|
200
|
+
|
|
201
|
+
Swap cuts two runs at several points. At each cut, each agent continues each run's workspace
|
|
202
|
+
by handoff. Swap reports a state effect (how much the state of the workspace matters), a model
|
|
203
|
+
effect (which agent does better), and, where an agent can continue its own saved session, the
|
|
204
|
+
handoff cost. At cut 0 both workspaces are the untouched project, so the state effect there must
|
|
205
|
+
be zero. Swap checks this, and the check is called the null check. When the state effect and the
|
|
206
|
+
model effect are within 0.1 of each other, Swap says they explain the failure about equally.
|
|
207
|
+
|
|
208
|
+
**Measured:** against scripted models with a known truth, the null check passed and the blame
|
|
209
|
+
passed from the model to the workspace between cut 0 and cut 0.5, as the scripts were written
|
|
210
|
+
to cause.
|
|
211
|
+
|
|
212
|
+
### Cliff
|
|
213
|
+
|
|
214
|
+
Cliff restarts a failed run from its capsules and names the step after which it no longer
|
|
215
|
+
succeeds. The baseline is the set of tails from the start. A step counts as good while its
|
|
216
|
+
tails pass at least half as often as the baseline. Cliff halves the range between the last good
|
|
217
|
+
and the first bad step, then adds tails to the two neighbours until their intervals separate or
|
|
218
|
+
the budget is spent. It reports a model gap instead of a step only when the upper end of the
|
|
219
|
+
baseline's 95% interval lies below 0.2.
|
|
220
|
+
|
|
221
|
+
**Measured:** against a scripted model whose wrong step is known, Cliff found step 4 with
|
|
222
|
+
separated intervals in 18 tails. Cliff stays experimental, because neither of two real test
|
|
223
|
+
rounds had a failure that sat in one step (see [Measurements](#measurements)). Swap already
|
|
224
|
+
shows, at three cuts, how often an agent passes when it continues its own workspace. When a real
|
|
225
|
+
Swap shows that rate dropping between two cuts, Cliff can narrow the drop down to one step. Only
|
|
226
|
+
then does Cliff get new experiments.
|
|
227
|
+
|
|
228
|
+
### Tokens and cost
|
|
229
|
+
|
|
230
|
+
Each adapter reads its agent's own stream after a run into one shape: all input tokens with the
|
|
231
|
+
cached ones included, the cached part, cache writes, output, reasoning, the cost where the agent
|
|
232
|
+
reports it, and the model where the stream names it. The agents count differently: Claude Code
|
|
233
|
+
and Pi report the cache apart from the input, Codex within it. A check that runs an agent itself
|
|
234
|
+
(`tare judge`) appends that agent's usage to a file that tare names in `TARE_USAGE_LOG`, so the
|
|
235
|
+
judge counts too. Where an agent reports no cost, tare estimates it from a price table and says
|
|
236
|
+
so, with the table's source and date. Totals keep count of runs whose cost stays unknown. A
|
|
237
|
+
subscription login is marked, because its cost is notional.
|
|
238
|
+
|
|
239
|
+
**Measured:** a calibrate run with one Haiku run, one Codex run with gpt-6.1-sol and a Sonnet
|
|
240
|
+
judge read 186.4k tokens in and $0.093 in total, the Codex part estimated from LiteLLM's table.
|
|
241
|
+
|
|
242
|
+
### Run directory, dashboard and recipes
|
|
243
|
+
|
|
244
|
+
Calibrate, Swap and Cliff write everything into a run directory: a journal (one JSON line per
|
|
245
|
+
event), a `recipe.json`, a `usage.json` with the totals, and the live output of every agent. The dashboard reads only the run
|
|
246
|
+
directory, so `tare watch` shows a finished run the same way as a live one. The recipe holds the
|
|
247
|
+
command, a fingerprint of the project and the agent versions. `tare rerun` repeats a run and
|
|
248
|
+
names what has changed since.
|
|
249
|
+
|
|
250
|
+
## Measurements
|
|
251
|
+
|
|
252
|
+
All measurements ran on WSL2 on 2026-10-04 and 2026-10-05.
|
|
253
|
+
|
|
254
|
+
| What | Agent and version | Result | Source |
|
|
255
|
+
|---|---|---|---|
|
|
256
|
+
| Dirty twin and room, fake model server | Claude Code 2.1.289 | the dirty twin showed every kind of context, the room only the email | [results](experiments/dirty-twin/RESULTS.md) |
|
|
257
|
+
| Dirty twin and room | Codex CLI 0.160.0 | the room read `tare: 0.00` | [results](experiments/dirty-twin-codex/RESULTS.md) |
|
|
258
|
+
| Dirty twin and room | Pi 1.0.2 | the room read `tare: 0.00` without flags | [results](experiments/dirty-twin-pi/RESULTS.md) |
|
|
259
|
+
| Dirty twin and room | Antigravity CLI 1.2.16 | the room read `tare: 0.00` without flags, and `~/.gemini` stayed unchanged | [results](experiments/dirty-twin-agy/RESULTS.md) |
|
|
260
|
+
| Rooms given copies of real settings on purpose | all four | Claude Code 4 leaks, Codex 6, Pi 5, Antigravity CLI 3, each named with its source | the results above |
|
|
261
|
+
| Scripted Cliff and Swap | Claude Code against scripted models | Cliff found step 4. Swap passed the null check and found the blame passing from the model to the workspace between cut 0 and cut 0.5 | `experiments/cliff-scripted`, `experiments/swap-scripted` |
|
|
262
|
+
| Real task 1: a data migration | Claude Code with Sonnet and Haiku, Codex | Deleting the source file after a wrong-encoding import was planned as the point of no return. Swap showed that the workspace could still be repaired. Haiku passed about 1 in 14 runs, Codex with gpt-6.1-sol 4 of 4 | [results](experiments/migration/RESULTS.md) |
|
|
263
|
+
| Real task 2: a web page judged by Sonnet | Claude Code with Haiku, Codex with gpt-6.1-sol | Swap confirmed all four predictions of the plan written before the runs. Cliff called a failed run unlucky, and a later rescoring of the same page confirmed it | [results](experiments/html/RESULTS.md) |
|
|
264
|
+
| Field test: two ideation skills compared | Claude Code 2.1.289 with Opus 5.5 | all 18 rooms read `tare: 0.00`, including a skill that started `claude -p` inside the room | not published |
|
|
265
|
+
|
|
266
|
+
## Open questions and ideas
|
|
267
|
+
|
|
268
|
+
- **Account email:** in a clean room the email reached the first request in 3 of 6 runs, which
|
|
269
|
+
suggests a race with the loading of the account profile. tare declares it whenever it appears.
|
|
270
|
+
- **Reused config:** a separate but reused config directory once loaded connected accounts, while
|
|
271
|
+
a fresh room never did. Cached account data is the suspected cause. Not tested.
|
|
272
|
+
- **Claude Code login renewal:** whether a renewal inside the room logs out the real session. Not
|
|
273
|
+
tested, so tare avoids it.
|
|
274
|
+
- **Codex handoffs:** Codex can run several commands in one tool call, which makes its handoffs
|
|
275
|
+
long.
|
|
276
|
+
- **Cost:** every tail is a full agent run, so a Cliff search or a Swap costs as much as its tails.
|
|
277
|
+
- **macOS:** a room built on Seatbelt (`sandbox-exec`), which Claude Code and Codex already use
|
|
278
|
+
for their own sandboxes. In progress (epic #85), not in a release yet.
|
|
279
|
+
- **Other probes, not built:** weighing the first request's input tokens before and after adding
|
|
280
|
+
junk to the real setup, and file tripwires that report which secret files a run opened.
|
|
281
|
+
- **Docker:** could contain files where bubblewrap is missing, but does nothing against context
|
|
282
|
+
that comes with the login.
|
|
283
|
+
- **Copilot CLI:** checked once but not supported. Its `--available-tools` ignores an empty list
|
|
284
|
+
without a warning, so only a list that names no real tool turns its tools off.
|
|
285
|
+
|
|
286
|
+
## Prior art
|
|
287
|
+
|
|
288
|
+
Checked on 2026-10-04.
|
|
289
|
+
|
|
290
|
+
- Multi-agent evaluation frameworks: UiPath/coder_eval (Claude Code, Codex, Antigravity,
|
|
291
|
+
OpenCode and Pi, in a temporary directory or Docker), google/skill-reach (skill routing across
|
|
292
|
+
Antigravity, Claude Code, Goose and Pi), mgechev/skillgrade (Docker and graders),
|
|
293
|
+
`claude plugin eval` (A/B with and without a plugin). The documentation of coder_eval states
|
|
294
|
+
that the caller provides a clean environment. None of them documents removing the agent's own
|
|
295
|
+
user context or proving that it is gone.
|
|
296
|
+
- Isolation by hand inside test suites, for example setting `CODEX_HOME`, `HOME` and
|
|
297
|
+
`CLAUDE_CONFIG_DIR` in a project's tests (hamza-aziz-ai/codex-claude-council PR #11).
|
|
298
|
+
- Fake model servers that could serve as a building block: Aetheria-LabsJP/puppetllm,
|
|
299
|
+
CopilotKit/llmock, litellm's agent harness.
|
|
300
|
+
- Orchestrators that run several agent CLIs side by side (Google Scion, agent-manager) isolate
|
|
301
|
+
processes, not user context.
|
|
302
|
+
|
|
303
|
+
tare is meant to sit underneath such frameworks. They run the evaluation, and tare provides the
|
|
304
|
+
clean room.
|
|
305
|
+
|
|
306
|
+
## Name
|
|
307
|
+
|
|
308
|
+
The command is `tare`. The package is called `tare-cli`, because `tare` is taken on PyPI and npm.
|
tare_cli-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andre Ratzenberger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|