convene 0.1.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.
@@ -0,0 +1,65 @@
1
+ name: Measurement
2
+ description: Report a number — a confirmation, a contradiction, or a new result
3
+ labels: ["measurement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Measurements are the most valuable thing you can contribute here.
9
+ A run that **contradicts** a table in FINDINGS.md is worth more than
10
+ another confirmation of it.
11
+
12
+ Every claim needs its sample size and the build it came from. See
13
+ [CONTRIBUTING.md](../blob/develop/CONTRIBUTING.md#the-claim-standard).
14
+ - type: input
15
+ id: claude-version
16
+ attributes:
17
+ label: Claude Code version
18
+ description: "`claude --version`"
19
+ placeholder: "2.1.237 (Claude Code)"
20
+ validations: { required: true }
21
+ - type: input
22
+ id: platform
23
+ attributes:
24
+ label: OS and architecture
25
+ placeholder: "macOS 15.3 arm64 / Ubuntu 24.04 x86_64 / Windows 11"
26
+ validations: { required: true }
27
+ - type: dropdown
28
+ id: auth
29
+ attributes:
30
+ label: Auth mode
31
+ options: ["login (subscription)", "sandbox_token (subscription)", "api_key"]
32
+ validations: { required: true }
33
+ - type: dropdown
34
+ id: topic
35
+ attributes:
36
+ label: Which claim does this touch?
37
+ options:
38
+ - "1. -p uses the subscription login / --bare does not"
39
+ - "2. Prompt cache — the ~9.5x, or where the threshold sits"
40
+ - "3. Concurrency ceiling"
41
+ - "4. Multi-turn cost and behaviour"
42
+ - "5. Auth failure returning success"
43
+ - "6. Lockdown flags worth ~88x"
44
+ - "A question FINDINGS.md lists as unmeasured"
45
+ - "Something not covered yet"
46
+ validations: { required: true }
47
+ - type: textarea
48
+ id: numbers
49
+ attributes:
50
+ label: The numbers
51
+ description: >
52
+ Token counts and costs, not just costs — a cost claim without tokens
53
+ cannot be checked. Say how many runs (n) each row represents.
54
+ render: text
55
+ placeholder: |
56
+ n=3 bursts per row, claude-sonnet-5, effort=low
57
+ n=20 wall=31.4s errors=7 (5x rate_limit, 2x overloaded)
58
+ validations: { required: true }
59
+ - type: textarea
60
+ id: command
61
+ attributes:
62
+ label: How to reproduce it
63
+ description: The exact command, ideally `convene bench ...`
64
+ render: shell
65
+ validations: { required: true }
@@ -0,0 +1,41 @@
1
+ name: Tool problem
2
+ description: convene itself is broken, or does something it shouldn't
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ **If a call started billing API credits instead of your subscription,
9
+ say so in the title** — that is the most serious class of bug here.
10
+
11
+ Please run `convene doctor` first and paste the output; it answers
12
+ most of what would otherwise be a round trip.
13
+ - type: textarea
14
+ id: doctor
15
+ attributes:
16
+ label: "`convene doctor` output"
17
+ description: Redact the email if you like — the plan and auth method are what matter.
18
+ render: text
19
+ validations: { required: true }
20
+ - type: input
21
+ id: version
22
+ attributes:
23
+ label: convene and Python versions
24
+ placeholder: "convene 0.1.0, Python 3.12.4"
25
+ validations: { required: true }
26
+ - type: textarea
27
+ id: what-happened
28
+ attributes:
29
+ label: What happened, and what you expected
30
+ validations: { required: true }
31
+ - type: textarea
32
+ id: repro
33
+ attributes:
34
+ label: Smallest reproduction
35
+ render: python
36
+ validations: { required: true }
37
+ - type: textarea
38
+ id: traceback
39
+ attributes:
40
+ label: Traceback or error output
41
+ render: text
@@ -0,0 +1,46 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+ - run: pip install -e ".[dev]"
22
+ # The `live` marker is excluded by default in pyproject. CI has no Claude
23
+ # Code login, and tests that spend money must never run unattended.
24
+ - run: pytest -q
25
+ - run: ruff check src tests claude_cli.py
26
+ - run: ruff format --check src tests claude_cli.py
27
+
28
+ scope-guard:
29
+ # The scope rule in the README is load-bearing, so it is enforced rather
30
+ # than merely documented: no HTTP server, no OpenAI-compatible endpoint,
31
+ # and never the --bare flag.
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+ - name: No --bare flag anywhere in the package
36
+ run: |
37
+ if grep -rn -- '"--bare"' src/; then
38
+ echo "::error::--bare forces API-key auth and never reads OAuth."
39
+ exit 1
40
+ fi
41
+ - name: No network server in the package
42
+ run: |
43
+ if grep -rnE '^\s*(import|from)\s+(http\.server|socketserver|flask|fastapi|uvicorn|aiohttp)\b' src/; then
44
+ echo "::error::convene exposes no network endpoint. See README > Scope."
45
+ exit 1
46
+ fi
@@ -0,0 +1,55 @@
1
+ name: Release
2
+
3
+ # Publishes to PyPI when a version tag is pushed.
4
+ #
5
+ # Uses PyPI Trusted Publishing, so there is no API token in this repo and
6
+ # nothing to leak or rotate. One-time setup on PyPI:
7
+ #
8
+ # pypi.org -> Your projects -> Publishing -> Add a new pending publisher
9
+ # PyPI project name : convene
10
+ # Owner : YashShelar007
11
+ # Repository : convene
12
+ # Workflow name : release.yml
13
+ # Environment : pypi
14
+ #
15
+ # Then: git tag v0.1.0 && git push origin v0.1.0
16
+
17
+ on:
18
+ push:
19
+ tags: ["v*"]
20
+
21
+ jobs:
22
+ build:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ - uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+ - run: pip install build
30
+ - run: python -m build
31
+ - name: Tag must match the version in pyproject
32
+ run: |
33
+ tag="${GITHUB_REF_NAME#v}"
34
+ pkg=$(ls dist/*.tar.gz | sed -E 's/.*convene-(.*)\.tar\.gz/\1/')
35
+ if [ "$tag" != "$pkg" ]; then
36
+ echo "::error::tag $tag does not match built version $pkg"
37
+ exit 1
38
+ fi
39
+ - uses: actions/upload-artifact@v4
40
+ with:
41
+ name: dist
42
+ path: dist/
43
+
44
+ publish:
45
+ needs: build
46
+ runs-on: ubuntu-latest
47
+ environment: pypi
48
+ permissions:
49
+ id-token: write # required for Trusted Publishing
50
+ steps:
51
+ - uses: actions/download-artifact@v4
52
+ with:
53
+ name: dist
54
+ path: dist/
55
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,32 @@
1
+ # Credentials and machine identity. Never commit these.
2
+ data/
3
+ *.oauth-token
4
+ oauth-token
5
+ .credentials.json
6
+
7
+ # Call logs and ledgers contain your prompts, costs and account activity.
8
+ logs/
9
+ *.log
10
+ *.sqlite3
11
+ *.db
12
+
13
+ # Local expert registries may hold proprietary prompts.
14
+ experts.local.toml
15
+ convene.local.toml
16
+
17
+ # Python
18
+ __pycache__/
19
+ *.py[cod]
20
+ *.egg-info/
21
+ build/
22
+ dist/
23
+ .venv/
24
+ venv/
25
+ .pytest_cache/
26
+ .ruff_cache/
27
+ .mypy_cache/
28
+
29
+ # macOS
30
+ .DS_Store
31
+
32
+ scratch/
@@ -0,0 +1,136 @@
1
+ # Contributing
2
+
3
+ This repo's product is **verified claims about an undocumented interface**, and
4
+ a small library that acts on them. The code is thin; the value is in knowing
5
+ which assertions are backed by how much evidence. That shapes everything below.
6
+
7
+ ## Branches
8
+
9
+ | Branch | What it means |
10
+ |---|---|
11
+ | `main` | Claims that have been verified, and code that has been run. Treat it as published. |
12
+ | `develop` | Integration. New measurements and features land here first. |
13
+
14
+ - `develop` is the **default branch**. Open PRs against it.
15
+ - `main` changes only by PR from `develop`, tagged on merge.
16
+ - Maintainers push to `develop` directly for doc fixes and verified findings.
17
+ Outside contributions come as PRs.
18
+
19
+ Releases are tagged when a **claim set** changes — a new measurement, a
20
+ retraction, a corrected derivation — or when the API changes. The version
21
+ people cite should match what they read.
22
+
23
+ ## The claim standard
24
+
25
+ The most useful contribution here is usually a measurement, not a patch. It is
26
+ also the easiest thing to get wrong, because a single lucky run looks exactly
27
+ like a law.
28
+
29
+ **Every empirical claim carries its sample size and the build it came from.**
30
+
31
+ - Good: "cache engages between 914 and 1232 total prompt tokens
32
+ (claude-sonnet-5, Claude Code 2.1.237, macOS arm64, n=1 per size across 8
33
+ sizes)"
34
+ - Not good: "the cache threshold is 1024 tokens"
35
+
36
+ If you can't reach n>1, say so. "Observed once" is a fine claim.
37
+ "Anthropic changed X" is not, unless you have both sides of the change.
38
+
39
+ Claims about *cost* must report the tokens too. `total_cost_usd` is a
40
+ client-side list-price estimate, not a bill, and on subscription auth it is an
41
+ accounting figure rather than a charge. A cost claim without the token counts
42
+ cannot be checked.
43
+
44
+ ## What's most wanted
45
+
46
+ The open questions are listed at the bottom of [FINDINGS.md](FINDINGS.md). The
47
+ highest-value ones:
48
+
49
+ 1. **The real concurrency ceiling.** n=20 is simply the largest burst anyone
50
+ has tried. Where does it actually start erroring, and what does the envelope
51
+ look like when it does?
52
+ 2. **A Linux or Windows column.** Every number in FINDINGS.md is macOS arm64.
53
+ 3. **Cache TTL.** Warm reads were ~30s apart. How long does an entry live?
54
+ 4. **A build newer than 2.1.237** — especially one where `--bare` has become
55
+ the default for `-p`, which would break subscription auth entirely.
56
+ 5. **Counter-examples.** A run that contradicts a table in FINDINGS.md is worth
57
+ more than another confirmation of it.
58
+
59
+ Reproduce the existing numbers first:
60
+
61
+ ```bash
62
+ convene bench
63
+ ```
64
+
65
+ ## Scope: what will be declined
66
+
67
+ convene runs the first-party `claude` binary locally, under the user's own
68
+ login. It is not a proxy. Three properties are load-bearing, and PRs that
69
+ change any of them will be declined regardless of quality:
70
+
71
+ - **No network endpoint.** No HTTP server, no OpenAI-compatible shim, no
72
+ daemon that other machines or programs can call. See *Scope* in the README
73
+ for why — this is the exact shape Anthropic blocked in 2026.
74
+ - **No credential extraction or forwarding.** The library reads no token files
75
+ it did not create, and sends credentials nowhere.
76
+ - **No silent API-key fallback.** `AuthMode.API_KEY` must never be selected
77
+ implicitly, and the key-stripping in `subprocess_env` must not be weakened.
78
+
79
+ Feature ideas inside scope are in [ROADMAP.md](ROADMAP.md).
80
+
81
+ ## Hard rules for the code
82
+
83
+ Each corresponds to a way this has already gone wrong, or would.
84
+
85
+ - **Never pass `--bare`.** It forces API-key auth and never reads OAuth. It
86
+ would silently move billing from a subscription to API credits.
87
+ - **Never weaken the `is_error` check.** Auth failure arrives as
88
+ `subtype: "success"` with exit code 0. `subtype == "success"` alone does not
89
+ catch it. Pinned by `tests/test_runtime.py`.
90
+ - **Never drop a lockdown flag** without a measurement showing the cost is
91
+ unchanged. They are worth ~88x together.
92
+ - **Never strip `--session-id`/`--resume` calls of session persistence.**
93
+ `--no-session-persistence` makes a session unresumable, which defeats the
94
+ point of a durable session.
95
+ - **Keep the core dependency-free.** A tool for reducing spend should not drag
96
+ in a tree of transitive dependencies. `tomllib` is why the floor is 3.11.
97
+ - **Normalise costs, don't pass them through.** Live sessions report cumulative
98
+ cost, durable ones report per-call. `Turn.cost_usd` is always incremental.
99
+
100
+ ## Releasing
101
+
102
+ Releases go out through PyPI Trusted Publishing — there is no API token in this
103
+ repo. The one-time PyPI setup is documented at the top of
104
+ [`.github/workflows/release.yml`](.github/workflows/release.yml).
105
+
106
+ After that, a release is:
107
+
108
+ ```bash
109
+ # on develop, with FINDINGS.md and the version in pyproject.toml both current
110
+ gh pr create --base main --head develop
111
+ # once merged:
112
+ git checkout main && git pull
113
+ git tag v0.1.1 && git push origin v0.1.1
114
+ ```
115
+
116
+ The workflow refuses to publish if the tag does not match the version in
117
+ `pyproject.toml`, so bump that in the same PR.
118
+
119
+ ## Testing a change
120
+
121
+ ```bash
122
+ pip install -e ".[dev]"
123
+ pytest # 46 tests, no spend, no network
124
+ ruff check src tests
125
+ ```
126
+
127
+ Tests that make real calls are marked `live` and excluded by default. Run them
128
+ before anything touching the runtime, sessions, or auth:
129
+
130
+ ```bash
131
+ pytest -m live # a few cents, needs a working `claude` login
132
+ ```
133
+
134
+ If you change a documented number, change FINDINGS.md in the same PR and say in
135
+ the description which command you actually ran. A number in the docs that no
136
+ test or bench command reproduces is a bug.
@@ -0,0 +1,239 @@
1
+ # Findings
2
+
3
+ Measured behaviour of `claude -p` used as an inference endpoint. Everything
4
+ here carries its sample size and the build it came from, because this document
5
+ is the product — the code is a thin wrapper around these facts.
6
+
7
+ Reproduce any of it with:
8
+
9
+ ```bash
10
+ convene bench
11
+ ```
12
+
13
+ **Environment for every measurement below unless stated otherwise:** Claude
14
+ Code **2.1.237**, macOS 15 (arm64), subscription auth (`authMethod:
15
+ claude.ai`, Max plan), model `claude-sonnet-5`, `effort=low`, calls locked down
16
+ with the flag set in [`runtime.py`](src/convene/runtime.py).
17
+
18
+ ---
19
+
20
+ ## 1. `claude -p` uses your subscription login. `--bare` does not.
21
+
22
+ This is the most widely repeated wrong claim about headless Claude Code, and
23
+ it appears in blog posts and search summaries as *"the `-p` flag bypasses OAuth
24
+ and requires an `ANTHROPIC_API_KEY`."*
25
+
26
+ It is false, and Anthropic's own documentation says which half is true. From
27
+ [the headless docs](https://code.claude.com/docs/en/headless), on `--bare`:
28
+
29
+ > Set `ANTHROPIC_API_KEY` before running it, because bare mode doesn't use your
30
+ > subscription login.
31
+
32
+ > In bare mode, Claude Code never reads OAuth credentials or the system keychain.
33
+
34
+ So the API-key requirement belongs to `--bare`, not to `-p`. A plain `-p` run
35
+ reads your OAuth login normally. Every call in this document was made with no
36
+ API key in the environment (n≈150 calls, all succeeded).
37
+
38
+ **This is why convene never passes `--bare`,** despite it being faster to
39
+ start and despite Anthropic recommending it for scripted calls.
40
+
41
+ ### The forward risk
42
+
43
+ The same page says:
44
+
45
+ > `--bare` is the recommended mode for scripted and SDK calls, and will become
46
+ > the default for `-p` in a future release.
47
+
48
+ If that lands and there is no opt-out, subscription auth through this library
49
+ breaks. `convene doctor` probes for it with a real call rather than comparing
50
+ version strings, because the failure will not announce itself.
51
+
52
+ ---
53
+
54
+ ## 2. The prompt cache works, and it is worth ~9.5x
55
+
56
+ Same ~4.4k-token system prompt, three **separate processes**, no session
57
+ resumption, ~30s apart (n=1 per row):
58
+
59
+ | | `cache_creation` | `cache_read` | `input_tokens` | cost | elapsed |
60
+ |---|---:|---:|---:|---:|---:|
61
+ | cold | 4434 | 0 | 2 | **$0.02670** | 7.1s |
62
+ | warm | 243 | 4191 | 2 | **$0.00281** | 6.5s |
63
+ | warm | 243 | 4191 | 2 | **$0.00281** | 6.5s |
64
+
65
+ **9.5x cheaper**, and the cache survives process death because it lives
66
+ server-side keyed on the prompt prefix.
67
+
68
+ The practical consequence inverts ordinary prompt advice: a long, *stable*
69
+ system prompt is the cheap option, and a short one you retune per call is the
70
+ expensive one. This is the entire argument for the expert registry.
71
+
72
+ Confirmed independently on a real workload — the `triage` expert in
73
+ [`examples/experts.toml`](examples/experts.toml), 5 support tickets, warm-up
74
+ enabled (n=1 run):
75
+
76
+ ```
77
+ t1 cache_read= 0 $0.01311 <- cold, creates the entry
78
+ t2 cache_read=1504 $0.00469
79
+ t3 cache_read=1504 $0.00454
80
+ t4 cache_read=1504 $0.00469
81
+ t5 cache_read=1504 $0.00520
82
+ ```
83
+
84
+ 2.8x on a prompt a quarter the size of the synthetic one. The effect scales
85
+ with system-prompt length.
86
+
87
+ ### Where the cache starts
88
+
89
+ Sweeping one system prompt's length, one call per size (n=1 per row):
90
+
91
+ | system prompt chars | total `input_tokens` | `cache_creation` | cached? |
92
+ |---:|---:|---:|:--|
93
+ | 285 | 354 | 0 | no |
94
+ | 570 | 434 | 0 | no |
95
+ | 1140 | 594 | 0 | no |
96
+ | 1710 | 754 | 0 | no |
97
+ | 2280 | 914 | 0 | no |
98
+ | 3420 | 2 | 1232 | **yes** |
99
+ | 5700 | 2 | 1872 | yes |
100
+ | 14820 | 2 | 241 (+4191 read) | yes |
101
+
102
+ The transition sits between **914 and 1232 total prompt tokens**, consistent
103
+ with the 1024-token minimum Anthropic documents for Sonnet and Opus. Haiku's
104
+ documented minimum is 2048; **that has not been measured here.**
105
+
106
+ Two things this table shows that are easy to miss:
107
+
108
+ - The threshold applies to the **whole prompt**, not the system prompt alone.
109
+ A locked-down call carries ~150 tokens of harness before your text.
110
+ - Once a cache entry exists, `input_tokens` collapses to **2**. Almost the
111
+ entire prompt moves into the cache accounting.
112
+
113
+ ### Chars per token, and why the lint under-estimates
114
+
115
+ The sweep above gives 2.78–3.04 chars/token, but it repeats one sentence, and
116
+ repetitive text tokenises unusually well. The structured `triage` prompt —
117
+ markdown headings, short lines, lists — measured **2.2 chars/token** (2976
118
+ chars against ~1354 system tokens).
119
+
120
+ `convene experts lint` uses 2.9, which therefore *under*-estimates real
121
+ prompts. That is deliberate: a false "might be too short to cache" warning
122
+ costs nothing, while false reassurance costs money on every call.
123
+
124
+ ---
125
+
126
+ ## 3. Concurrency runs much further than "about 5"
127
+
128
+ Identical trivial calls, one burst per row, no retries (n=1 burst per row):
129
+
130
+ | n | wall | per-call min / med / max | errors |
131
+ |---:|---:|---:|---:|
132
+ | 1 | 6.3s | 6.3 / 6.3 / 6.3 | 0 |
133
+ | 5 | 6.8s | 6.4 / 6.6 / 6.8 | 0 |
134
+ | 10 | 9.9s | 7.0 / 7.2 / 9.8 | 0 |
135
+ | 20 | 12.1s | 8.9 / 10.4 / 12.0 | 0 |
136
+
137
+ Throughput climbs from 0.16 to 1.65 calls/second — about **10x** — with zero
138
+ rate-limit errors. Latency degrades gracefully rather than failing.
139
+
140
+ **This is not a discovered ceiling.** Nobody has found where it actually
141
+ breaks; 20 is simply the largest burst tested. convene defaults to 12 as a
142
+ deliberate midpoint that leaves headroom for the interactive Claude Code
143
+ sharing the same rate-limit pool. If you find the real limit,
144
+ [open an issue](https://github.com/YashShelar007/convene/issues).
145
+
146
+ Each concurrent call is a full Node process, so local RAM becomes the binding
147
+ constraint before long.
148
+
149
+ ---
150
+
151
+ ## 4. Multi-turn works, two ways, and they cost differently
152
+
153
+ Three-turn conversation, "my favourite number is 41" → "+1?" → "×2?". Both
154
+ kinds answered 42 then 82, so both retained state (n=1 each):
155
+
156
+ | | turn 1 | turn 2 | turn 3 | total |
157
+ |---|---:|---:|---:|---:|
158
+ | `LiveSession` (one hot process) | 3.2s / $0.00099 | 2.3s / $0.00113 | 5.8s / $0.00130 | **$0.00342** |
159
+ | `Session` (`--session-id` + `--resume`) | 3.6s / $0.00257 | 3.4s / $0.00840 | 3.2s / $0.00388 | **$0.01485** |
160
+
161
+ The hot process was **4.3x cheaper** for the same conversation, because
162
+ `--resume` re-establishes context from disk on every turn.
163
+
164
+ Use `Session` anyway when the conversation must outlive the program — it is on
165
+ disk and resumable tomorrow, from any working directory since Claude Code
166
+ 2.1.223. Use `LiveSession` when it does not.
167
+
168
+ ### The cost-reporting trap
169
+
170
+ The two paths report `total_cost_usd` differently, and neither documents it:
171
+
172
+ ```
173
+ LiveSession 0.000987 -> 0.002121 -> 0.003417 cumulative per session
174
+ Session 0.000990 -> 0.001130 -> 0.001300 per call
175
+ ```
176
+
177
+ Summing the raw field across a live session's turns **triple-counts**.
178
+ convene's `Turn.cost_usd` is always the incremental cost; the raw figure stays
179
+ on `turn.result.cost_usd`. Pinned by
180
+ [`tests/test_sessions.py`](tests/test_sessions.py).
181
+
182
+ Input tokens grow as history accumulates (299 → 363 → 417 on a trivial
183
+ conversation). A long session is a growing prompt, not a free one.
184
+
185
+ ---
186
+
187
+ ## 5. Auth failure does not look like a failure
188
+
189
+ The single nastiest behaviour in this interface. On an expired or missing
190
+ login, the CLI returns:
191
+
192
+ ```json
193
+ {"subtype": "success", "is_error": true, "result": "Not logged in · Please run /login"}
194
+ ```
195
+
196
+ …and exits **0**.
197
+
198
+ Neither the exit code nor `subtype` catches it. `is_error` is the only reliable
199
+ signal, which is why `decode_envelope` checks `subtype != "success" or
200
+ is_error`. That same condition also catches `error_*` subtypes such as
201
+ `error_max_structured_output_retries`.
202
+
203
+ Do not "simplify" it to `subtype == "success"`. Pinned by
204
+ [`tests/test_runtime.py`](tests/test_runtime.py).
205
+
206
+ ---
207
+
208
+ ## 6. The lockdown flags are worth ~88x
209
+
210
+ Measured on an identical one-word prompt (n=1, carried forward from this
211
+ project's predecessor and re-checkable with `convene doctor --lockdown`):
212
+
213
+ ```
214
+ locked down in= 144 cache_create= 0 cost=$0.00051
215
+ plain -p in= 2 cache_create= 9504 cost=$0.04478 88x
216
+ ```
217
+
218
+ A default `claude -p` loads the full agent system prompt, every tool
219
+ definition, your skills, MCP servers, project settings and `CLAUDE.md`. The gap
220
+ depends on how much you have configured, so re-measure on your own machine:
221
+
222
+ ```bash
223
+ convene doctor --lockdown
224
+ ```
225
+
226
+ ---
227
+
228
+ ## What has not been measured
229
+
230
+ Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
231
+
232
+ 1. **The real concurrency ceiling.** n=20 is the largest burst tried.
233
+ 2. **Haiku's cache threshold.** Documented as 2048 tokens; unverified here.
234
+ 3. **Cache TTL on this path.** Warm reads were ~30s apart. How long an entry
235
+ survives is unknown.
236
+ 4. **Linux and Windows.** Every number above is macOS arm64.
237
+ 5. **Rate-limit behaviour at the weekly cap.** No measurement of what a
238
+ subscription limit looks like in the envelope.
239
+ 6. **Whether `--bare` has become the `-p` default** in any build after 2.1.237.
convene-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yash Shelar
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.