prehello 0.1.0 → 1.0.0
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.
- package/CHANGELOG.md +46 -8
- package/README.md +73 -417
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/adapters/common.js +3 -3
- package/dist/adapters/cursor.js +20 -2
- package/dist/adapters/gemini-cli.js +214 -0
- package/dist/adapters/github-copilot.js +249 -0
- package/dist/adapters/index.js +16 -0
- package/dist/adapters/skills.js +10 -0
- package/dist/agents.js +54 -0
- package/dist/calibrate.js +265 -0
- package/dist/cli.js +144 -7
- package/dist/context.js +4 -6
- package/dist/diff.js +182 -0
- package/dist/mcp/configs.js +1 -1
- package/dist/model.js +3 -6
- package/dist/render/card.js +5 -4
- package/dist/render/markdown.js +1 -1
- package/dist/render/sarif.js +2 -2
- package/dist/render/terminal.js +8 -19
- package/dist/safe-write.js +2 -0
- package/dist/scan.js +5 -11
- package/dist/text/imports.js +7 -2
- package/dist/tokens/families.js +48 -16
- package/dist/version.js +5 -0
- package/package.json +8 -4
- package/spec/calibration.json +33 -0
- package/spec/cursor.json +1 -1
- package/spec/gemini-cli.json +17 -0
- package/spec/github-copilot.json +14 -0
package/README.md
CHANGED
|
@@ -4,81 +4,87 @@
|
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
6
|
<a href="https://github.com/PIYUSH-KUMAR1809/prehello/actions/workflows/ci.yml"><img src="https://github.com/PIYUSH-KUMAR1809/prehello/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/prehello"><img src="https://img.shields.io/npm/v/prehello" alt="npm version"></a>
|
|
7
8
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License: MIT"></a>
|
|
8
|
-
<img src="https://img.shields.io/badge/node-%E2%89%
|
|
9
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A522-brightgreen" alt="Node 22 or newer">
|
|
9
10
|
<img src="https://img.shields.io/badge/platform-linux%20%7C%20macos%20%7C%20windows-lightgrey" alt="Linux, macOS and Windows">
|
|
10
11
|
</p>
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<sub>A share card (<code>--card=card.png</code>). Sample data shaped like a real Cursor setup, not a real machine.</sub>
|
|
16
|
-
</p>
|
|
17
|
-
|
|
18
|
-
Every Claude Code, Cursor or Codex session starts with a pile of rules, skills, plugin listings and MCP servers already sitting
|
|
19
|
-
in the context window, before you type a word. **prehello** scans your repo and your home-directory agent config and tells you
|
|
20
|
-
**how many tokens that is, which plugin or skill folder is responsible, and roughly what removing the top few would save.**
|
|
13
|
+
Every **Claude Code, Cursor, Codex, GitHub Copilot and Gemini CLI** session starts with rules, skills, plugin listings and MCP servers already
|
|
14
|
+
in the context window, before you type a word. **prehello** scans your repo and your user-level agent config and tells you
|
|
15
|
+
**how many tokens that is, which plugin or file is responsible, and roughly what removing the top few would save.**
|
|
21
16
|
|
|
22
17
|
- **Local and read-only.** No network, no telemetry, no API key, no child processes. Nothing leaves your machine.
|
|
23
|
-
- **Honest numbers.** Every count is an estimate (`~`). What it cannot measure is listed, never shown as 0.
|
|
24
|
-
- **Actionable.** A ranked "what to cut" list, a share card, a
|
|
25
|
-
|
|
26
|
-
## Try it
|
|
18
|
+
- **Honest numbers.** Every count is an estimate (`~`) with a published error band. What it cannot measure is listed, never shown as 0.
|
|
19
|
+
- **Actionable.** A ranked "what to cut" list, a share card, a PR comment on every pull request, a badge, SARIF and a `--max-tokens` CI gate.
|
|
27
20
|
|
|
28
21
|
```sh
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
node dist/cli.js ~/code/your-project # scan a project plus your user-level agent config
|
|
33
|
-
node dist/cli.js # or: scan the current folder
|
|
34
|
-
node dist/cli.js ~/code/your-project --card=card.png # also write a PNG share card
|
|
22
|
+
npx prehello # this folder plus your user-level agent config
|
|
23
|
+
npx prehello ~/code/your-project # a specific project
|
|
24
|
+
npx prehello --card=card.png # also write a PNG share card
|
|
35
25
|
```
|
|
36
26
|
|
|
37
|
-
Needs Node
|
|
27
|
+
Needs Node 22 or newer, on Linux, macOS or Windows. `npm install -g prehello` installs it as `prehello`.
|
|
38
28
|
|
|
39
29
|
## What it prints
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
<p align="center"><img src="https://raw.githubusercontent.com/PIYUSH-KUMAR1809/prehello/main/docs/images/scan.png" width="760" alt="prehello terminal output: per-agent totals for Claude Code, Cursor, Codex, GitHub Copilot and Gemini CLI, the what-to-cut list, measured vs not measured, and top offenders"></p>
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
prehello 0.1.0 · this folder + user config · window 200k
|
|
45
|
-
Token counts are ESTIMATES (o200k BPE with per-agent scaling priors), shown with
|
|
46
|
-
~. Not exact for any model.
|
|
33
|
+
<sub>A real run of prehello 1.0 on a demo setup built from the bundled test fixtures (`test/fixtures/`), not anyone's real machine.</sub>
|
|
47
34
|
|
|
48
|
-
|
|
35
|
+
Below this first screen come a per-agent breakdown (always-on / conditional / deferred / on-demand), findings, and a Context Grade
|
|
36
|
+
(a heuristic of this tool, not a standard). The full output is in [docs/REFERENCE.md](docs/REFERENCE.md).
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
the measured always-on total, in 4 groups.
|
|
53
|
-
Top 3 groups = 94% of that. Removing them would save about 4.2k tokens
|
|
54
|
-
(2.1% of a 200k window); estimate, not a promise.
|
|
55
|
-
1. plugin analytics-kit (40 skills) ~2.2k 44%
|
|
56
|
-
2. plugin design-kit (24 skills) ~1.3k 26%
|
|
57
|
-
3. plugin cloud-kit (14 skills) ~719 14%
|
|
38
|
+
> **Read the numbers as "what YOUR config adds".** The agent's built-in system prompt and tool definitions are not on disk, so no static
|
|
39
|
+
> scanner can see them. prehello's total is the part *you* control. For the exact live total in one Claude Code session, use `/context`.
|
|
58
40
|
|
|
59
|
-
|
|
60
|
-
Cursor measured 4 of 4 (100%): 2 skills listings, 1 instruction file, 1 rule
|
|
61
|
-
...
|
|
62
|
-
```
|
|
41
|
+
**The share card** (`--card=card.png`) holds no paths or file contents:
|
|
63
42
|
|
|
64
|
-
|
|
65
|
-
Context Grade (a heuristic of this tool, not a standard). The full output is under [Reference](#reference) (collapsed).
|
|
43
|
+
<p align="center"><img src="https://raw.githubusercontent.com/PIYUSH-KUMAR1809/prehello/main/docs/images/card.png" width="640" alt="prehello share card: Skills and plugins cost at least ~4.9k tokens before hello, with a treemap of plugins"></p>
|
|
66
44
|
|
|
67
|
-
|
|
68
|
-
> they are usually the largest fixed chunk of the context window and are not on disk, so no static scanner can see them. prehello's total is the part
|
|
69
|
-
> *you* control. For the exact live total in one Claude Code session, use `/context`.
|
|
45
|
+
## What 559 public repos load before hello
|
|
70
46
|
|
|
71
|
-
|
|
47
|
+
The [State of agent context 2026](docs/BENCHMARK.md) benchmark checked 2,041 public GitHub repos; 559 ship agent files. prehello ran on each with an
|
|
48
|
+
empty HOME, so only the repo's own files count.
|
|
72
49
|
|
|
73
|
-
The
|
|
50
|
+
- The median repo adds **~2.2k tokens** before hello. p90 is ~8.4k, the largest ~53k.
|
|
51
|
+
- **20.4%** have both CLAUDE.md and AGENTS.md at the root, so Claude Code ignores the AGENTS.md.
|
|
52
|
+
- **16.6%** have an instruction file longer than the agent's documented guideline; **3.4%** have an AGENTS.md chain Codex truncates at 32 KiB.
|
|
53
|
+
- Stars don't predict size (Spearman 0.05), but they do predict adoption: **47%** of 10k+ star repos ship agent files, vs **17%** at 20–99 stars.
|
|
74
54
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="https://raw.githubusercontent.com/PIYUSH-KUMAR1809/prehello/main/benchmark/charts/always-on-by-agent.png" width="420" alt="Always-on tokens per agent across 559 repos">
|
|
57
|
+
<img src="https://raw.githubusercontent.com/PIYUSH-KUMAR1809/prehello/main/benchmark/charts/mistakes.png" width="420" alt="Common agent-file mistakes across 559 repos">
|
|
58
|
+
</p>
|
|
59
|
+
|
|
60
|
+
Data, scripts and how to reproduce it are in [`benchmark/`](benchmark/) and [docs/BENCHMARK.md](docs/BENCHMARK.md).
|
|
61
|
+
|
|
62
|
+
## A PR comment on every pull request
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# .github/workflows/prehello.yml
|
|
66
|
+
on: pull_request
|
|
67
|
+
permissions: { contents: read, pull-requests: write }
|
|
68
|
+
jobs:
|
|
69
|
+
context-diff:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
with: { fetch-depth: 0, persist-credentials: false }
|
|
74
|
+
- uses: PIYUSH-KUMAR1809/prehello@v1
|
|
75
|
+
with: { fail-above: 2k } # optional
|
|
76
|
+
```
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
<p align="center"><img src="https://raw.githubusercontent.com/PIYUSH-KUMAR1809/prehello/main/docs/images/pr-comment.png" width="640" alt="The prehello PR comment: a table of base, head and change per agent"></p>
|
|
79
|
+
|
|
80
|
+
One sticky comment per PR, updated on every push. Fork PRs fall back to the job summary. Details, inputs and the README badge
|
|
81
|
+
(`--badge badge.json`, a shields.io endpoint) are in [docs/github-action.md](docs/github-action.md).
|
|
82
|
+
|
|
83
|
+
## How accurate is it?
|
|
84
|
+
|
|
85
|
+
Counts use the o200k tokenizer with per-agent factors from published measurements. Bands: Codex ±3%, Claude Code ±15%,
|
|
86
|
+
Cursor and Copilot −3% to +15% (model unknown), Gemini CLI −3% to +64% (unvalidated). Sources and caveats are in [docs/ACCURACY.md](docs/ACCURACY.md).
|
|
87
|
+
`prehello calibrate --file ctx.txt` compares the estimate with your own Claude Code `/context` reading, per category.
|
|
82
88
|
|
|
83
89
|
## Outputs
|
|
84
90
|
|
|
@@ -90,28 +96,33 @@ whether you use it or not. That is what the cut list is for, and removing a plug
|
|
|
90
96
|
| GitHub code scanning / IDEs | `--sarif=prehello.sarif` |
|
|
91
97
|
| Machine-readable | `--json` (add `--redact` before sharing it: no paths or names) |
|
|
92
98
|
| A budget gate in CI | `--max-tokens 16k` (exit code 2 above it) |
|
|
99
|
+
| What a PR changes | `--save base.json` / `--save head.json`, then `prehello diff base.json head.json` (`--markdown`, `--fail-above 2k`) |
|
|
100
|
+
| A PR comment on every pull request | the GitHub Action: `uses: PIYUSH-KUMAR1809/prehello@v1` ([docs/github-action.md](docs/github-action.md)) |
|
|
101
|
+
| A README badge | `--badge badge.json` (shields.io endpoint JSON; see [docs/github-action.md](docs/github-action.md#badge)) |
|
|
102
|
+
| Check the estimate against Claude Code | `prehello calibrate --file ctx.txt` (paste `/context` output; see [docs/ACCURACY.md](docs/ACCURACY.md)) |
|
|
93
103
|
| Suggestions, changing nothing | `--fix` (dry run) |
|
|
94
104
|
| Count Cursor "User Rules" you paste in | `--paste-user-rules rules.txt` |
|
|
95
|
-
| Also count agent files inside test-fixture folders | `--include-fixtures` (skipped by default; see [
|
|
105
|
+
| Also count agent files inside test-fixture folders | `--include-fixtures` (skipped by default; see [docs/REFERENCE.md](docs/REFERENCE.md)) |
|
|
96
106
|
|
|
97
107
|
`node dist/cli.js --help` lists every flag. PNG cards need the optional package `@resvg/resvg-wasm`; if it is missing, prehello prints how to install it
|
|
98
108
|
and exits 1 without a stack trace, and the SVG card and everything else keep working.
|
|
99
109
|
|
|
100
110
|
## Agents covered
|
|
101
111
|
|
|
102
|
-
Claude Code, Cursor, Codex, and plain `AGENTS.md` files.
|
|
112
|
+
Claude Code, Cursor, Codex, GitHub Copilot (CLI and VS Code), Gemini CLI, and plain `AGENTS.md` files. What is scanned for each is in [docs/REFERENCE.md](docs/REFERENCE.md). Not yet: Windsurf, Cline.
|
|
103
113
|
|
|
104
114
|
## FAQ
|
|
105
115
|
|
|
106
116
|
**Does it send anything anywhere?** No. No network, no telemetry, no API key, no child processes. A test runs the CLI with a guard that blocks and records any
|
|
107
117
|
network, DNS or child-process attempt. It writes only the output files you name (`--card=`, `--json=`, `--markdown=`, `--sarif=`).
|
|
108
118
|
|
|
109
|
-
**Is the token count exact?** No, and it says so. It counts with the o200k tokenizer and applies a per-agent factor. The
|
|
110
|
-
|
|
119
|
+
**Is the token count exact?** No, and it says so. It counts with the o200k tokenizer and applies a per-agent factor. The Claude factors come from
|
|
120
|
+
published `count_tokens` measurements (a small sample, see [docs/ACCURACY.md](docs/ACCURACY.md)), not from prehello's own runs, so every
|
|
121
|
+
total carries an error band and a `~`. `prehello calibrate` compares the estimate with your own Claude Code `/context` reading.
|
|
111
122
|
|
|
112
123
|
**Why is my total smaller than what `/context` shows?** `/context` also sees the built-in system prompt, built-in tool definitions and the conversation. prehello only sees what is on disk.
|
|
113
124
|
|
|
114
|
-
**Why not just use `/context`?** If you only use Claude Code and want the true number for one live session, do. prehello works before a session, covers Cursor and
|
|
125
|
+
**Why not just use `/context`?** If you only use Claude Code and want the true number for one live session, do. prehello works before a session, covers Cursor, Codex, Copilot and Gemini CLI too,
|
|
115
126
|
runs in CI, and ranks *which plugin or skill folder* to remove.
|
|
116
127
|
|
|
117
128
|
**Does it start my MCP servers?** No. It lists their names and counts. Sizes come only from a small measured catalog (`spec/mcp-weights.json`, 7 servers) or a file you give it; every other server stays "unmeasured".
|
|
@@ -122,16 +133,16 @@ runs in CI, and ranks *which plugin or skill folder* to remove.
|
|
|
122
133
|
|
|
123
134
|
**Why does it say "Skipped N fixture folders"?** A repo that tests agent tooling keeps sample `AGENTS.md`, `CLAUDE.md`, `.cursor/rules` and skills under `test/fixtures/` and similar. No agent loads those, so prehello skips such folders by default and says how many it skipped (only folders where it found agent files). `--include-fixtures` counts them; scanning a folder that is itself inside a fixtures folder never skips anything.
|
|
124
135
|
|
|
125
|
-
**Does it work on Windows?** Yes. CI runs the full suite on Ubuntu, Windows and macOS with Node
|
|
136
|
+
**Does it work on Windows?** Yes. CI runs the full suite on Ubuntu, Windows and macOS with Node 22, 24 and 26. See [docs/REFERENCE.md](docs/REFERENCE.md).
|
|
126
137
|
|
|
127
138
|
## Limitations
|
|
128
139
|
|
|
129
|
-
- Token counts are **estimates**; Claude and Cursor
|
|
140
|
+
- Token counts are **estimates**; the Claude factors rest on about 10 published measurements, and Cursor's model is unknown (see [docs/ACCURACY.md](docs/ACCURACY.md)).
|
|
130
141
|
- The built-in system prompt, built-in tools, Cursor User and Team Rules (unless pasted), claude.ai connectors, hook output and anything injected at runtime are **never measured**.
|
|
131
142
|
- Loading rules come from the agents' public docs and announcements, not from their source, and were **not re-verified against live installs**; items where sources disagree are labelled `assumed`.
|
|
132
|
-
-
|
|
143
|
+
- Five agents plus `AGENTS.md` are covered (Copilot and Gemini CLI token factors are unvalidated), and MCP server sizes exist for just 7 servers.
|
|
133
144
|
|
|
134
|
-
Full list: [
|
|
145
|
+
Full list: [docs/REFERENCE.md](docs/REFERENCE.md).
|
|
135
146
|
|
|
136
147
|
## How it differs
|
|
137
148
|
|
|
@@ -148,364 +159,9 @@ What prehello focuses on: a per-plugin / per-skill-folder **cut list**, **unmeas
|
|
|
148
159
|
(`documented`, `observed`, `assumed`), a share card that holds no paths or file contents, and a CI gate. What it does **not** do: live sessions, dollar cost,
|
|
149
160
|
linting your instructions against your code, or exact token counts.
|
|
150
161
|
|
|
151
|
-
## Reference
|
|
152
|
-
|
|
153
|
-
Long-form details, collapsed. Everything here describes the current CLI. Commands below say `prehello`; from a source checkout run `node dist/cli.js` instead (after the npm release, `npx prehello`).
|
|
154
|
-
|
|
155
|
-
<details>
|
|
156
|
-
<summary><b>Full sample output (fixture, not a real machine)</b></summary>
|
|
157
|
-
|
|
158
|
-
```text
|
|
159
|
-
prehello 0.1.0 · this folder + user config · window 200k
|
|
160
|
-
Token counts are ESTIMATES (o200k BPE with per-agent scaling priors), shown with
|
|
161
|
-
~. Not exact for any model.
|
|
162
|
-
|
|
163
|
-
Before your first message: Cursor ~5k tokens
|
|
164
|
-
|
|
165
|
-
What to cut (estimates)
|
|
166
|
-
Cursor skills, plugins and MCP servers add ~4.5k tokens before hello: 90% of
|
|
167
|
-
the measured always-on total, in 4 groups.
|
|
168
|
-
Top 3 groups = 94% of that. Removing them would save about 4.2k tokens
|
|
169
|
-
(2.1% of a 200k window); estimate, not a promise.
|
|
170
|
-
1. plugin analytics-kit (40 skills) ~2.2k 44%
|
|
171
|
-
2. plugin design-kit (24 skills) ~1.3k 26%
|
|
172
|
-
3. plugin cloud-kit (14 skills) ~719 14%
|
|
173
|
-
|
|
174
|
-
Measured vs. not measured (always-on items)
|
|
175
|
-
Cursor measured 4 of 4 (100%): 2 skills listings, 1 instruction file, 1 rule
|
|
176
|
-
|
|
177
|
-
Top offenders (always on, estimates)
|
|
178
|
-
1. AGENTS.md 326 6.6% ████████████
|
|
179
|
-
2. .cursor/rules/always.mdc 164 3.3% ██████
|
|
180
|
-
3. skill "analytics-task-12" 59 1.2% ██
|
|
181
|
-
4. skill "analytics-task-26" 59 1.2% ██
|
|
182
|
-
5. skill "analytics-task-3" 59 1.2% ██
|
|
183
|
-
|
|
184
|
-
── Cursor ───────────────────────────────────────────────────────────── Grade A
|
|
185
|
-
estimate model: o200k; model unknown, so midpoint of GPT-like (×1.0) and
|
|
186
|
-
Claude-like (×1.5) priors; band wide: GPT-like −3% to Claude-like +20%
|
|
187
|
-
ALWAYS ON before hello ~5k tokens (3.9k–7.1k) ≈ 2.5% of 200k
|
|
188
|
-
Skills listing (78 skills from 3 plugins) 4,226 85% ████████████
|
|
189
|
-
AGENTS.md 326 6.6% ▌
|
|
190
|
-
Skills listing (5 user skills) 248 5.0% ▌
|
|
191
|
-
.cursor/rules (alwaysApply) 164 3.3%
|
|
192
|
-
DEFERRED (stub now, body on demand) ~4.7k tokens (3.6k–6.7k)
|
|
193
|
-
Skill bodies (78 skills from 3 plugins) 4,383 94% ████████████
|
|
194
|
-
Skill bodies (5 user) 280 6.0% ▌
|
|
195
|
-
not measurable from disk: User Rules and Team Rules (stored in Cursor, not on
|
|
196
|
-
disk; paste them with --paste-user-rules to count them) · built-in system
|
|
197
|
-
prompt and tools · plugin install state (3 plugins found under
|
|
198
|
-
~/.cursor/plugins)
|
|
199
|
-
|
|
200
|
-
Never measured: the agent's built-in system prompt and built-in tool
|
|
201
|
-
definitions; server-side / org rules, Cursor User & Team Rules, claude.ai
|
|
202
|
-
connectors; MCP servers whose tools are only known at runtime (no server is
|
|
203
|
-
started by default); files outside the scanned locations; anything the agent
|
|
204
|
-
injects dynamically (hooks, memory/RAG plugins).
|
|
205
|
-
Context Grade (Cursor): A — heuristic, not a standard. See: prehello explain
|
|
206
|
-
grade
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
</details>
|
|
210
|
-
|
|
211
|
-
<details>
|
|
212
|
-
<summary><b>How to read the output</b></summary>
|
|
213
|
-
|
|
214
|
-
- `~` means *estimated*. Ranges in brackets are the error band of the estimation model, not a confidence interval of truth.
|
|
215
|
-
- **Measured vs. not measured.** Every agent gets a line saying how many always-on items were measured and which were not
|
|
216
|
-
(for example MCP servers whose tool schemas only exist at runtime). `unmeasured` is **never shown as 0**.
|
|
217
|
-
- If any always-on item is unmeasured, or the scan stopped at its budget, the always-on total becomes a **lower bound** (`≥` in the terminal, "at least" on the card)
|
|
218
|
-
and the grade is **capped at B and marked provisional**. If nothing could be measured there is **no grade at all** and the output says so, instead of a flattering "A".
|
|
219
|
-
- **Top offenders** ranks the biggest always-on items across agents (shown when there are at least three).
|
|
220
|
-
- An agent that is installed but has nothing on disk gets an explicit "installed, but nothing that loads before hello was found.
|
|
221
|
-
This is NOT a score of 0" message plus where prehello looked. An empty machine gets a "what I looked for / what to try" screen.
|
|
222
|
-
- Agents found only inside the repo (for example an `AGENTS.md` committed by a teammate, with no sign you use that agent)
|
|
223
|
-
are collapsed and excluded from the headline, card and grade (use `--agent` to include them).
|
|
224
|
-
- **Running it from a folder that is not a project** (no `.git`, no agent files, for example your home folder) and with a huge tree:
|
|
225
|
-
prehello warns and does **not** print token totals for random nested files it happened to find first.
|
|
226
|
-
|
|
227
|
-
</details>
|
|
228
|
-
|
|
229
|
-
<details>
|
|
230
|
-
<summary><b>Test-fixture folders (<code>--include-fixtures</code>)</b></summary>
|
|
231
|
-
|
|
232
|
-
The project walk (nested `AGENTS.md` / `CLAUDE.md`, `.cursor/rules`, `.cursor/skills`, `.claude/skills`, `.agents/skills`) **skips test-fixture folders by default**, for every agent, so a
|
|
233
|
-
repository like prehello's own does not list its sample files as "conditional" context.
|
|
234
|
-
|
|
235
|
-
| Folder name (any depth below the scanned folder, any letter case) | Skipped |
|
|
236
|
-
| --- | --- |
|
|
237
|
-
| `fixtures`, `__fixtures__`, `fixture`, `testdata`, `test-data`, `__mocks__`, `__snapshots__` | always |
|
|
238
|
-
| `snapshots`, `golden`, `goldens` | only below a `test`, `tests`, `__tests__`, `spec`, `e2e` or `cypress` folder |
|
|
239
|
-
|
|
240
|
-
- **Never skipped:** the scanned project's own top-level files, files found by walking *up* from the scanned folder, user-level config, and anything when the scanned folder is itself inside such a folder (so `prehello test/fixtures/x/project` works as before).
|
|
241
|
-
- **Said out loud:** when at least one skipped folder held agent files, the terminal report, Markdown (full and compact) and SARIF (`runs[0].properties.prehello.fixtureFoldersSkipped`) carry one line / one number, never a path. `--json` gets `scan.fixturesSkipped` (a count; the field is absent when it is 0, so the JSON is otherwise unchanged). It is not a warning and does not change the exit code. Folders that held no agent files are not counted; looking inside a skipped folder to count it is bounded and reads no file.
|
|
242
|
-
- `--include-fixtures` turns the skip off.
|
|
243
|
-
|
|
244
|
-
</details>
|
|
245
|
-
|
|
246
|
-
<details>
|
|
247
|
-
<summary><b>Share cards (SVG and PNG), sample cards and how PNG works</b></summary>
|
|
248
|
-
|
|
249
|
-
`--card=file.svg` or `--card=file.png` (the extension picks the format; `--card` alone writes `prehello-card.svg`, or `.png` with
|
|
250
|
-
`--card-format png`). **Write the file name with `=`: `--card=card.png`.** `--card card.png` (a space) is not accepted: the name would be read as the
|
|
251
|
-
project folder, so prehello stops with a hint before scanning. A card holds the same groups as the "What to cut" list on its treemap
|
|
252
|
-
(`plugin <name>`, `18 Cursor-managed skills`, `MCP server <name>`), plus generic labels for your instruction files and rules
|
|
253
|
-
(`CLAUDE.md`, `rule file x14`), counts, the version and a date. Small tiles are merged into `other (N smaller)`. It never contains paths or file contents.
|
|
254
|
-
**Plugin and MCP server names are on the card by default** (they are what makes it readable); add `--card-anonymize` before sharing
|
|
255
|
-
if a name is private, and they become `plugin 1`, `MCP server 1`.
|
|
256
|
-
|
|
257
|
-
| Flag | Meaning |
|
|
258
|
-
| --- | --- |
|
|
259
|
-
| `--card-headline cut` (default) | Leads with "Skills & plugins cost ~X tokens before hello" and "cut the top N: save ~Y (estimate)". The always-on total is the first chip. |
|
|
260
|
-
| `--card-headline total` | Leads with "~X tokens load before hello". |
|
|
261
|
-
| `--card-theme dark\|light`, `--card-size og\|square` | Colours; 1200x630 link-preview shape or 1080x1080 square (square puts the headline on two lines). |
|
|
262
|
-
| `--card-scale 1\|2` | PNG only. 1 = 1200x630 / 1080x1080, 2 = double that (default, sharper on phones). |
|
|
263
|
-
| `--card-anonymize` | Show plugin and MCP server names as `plugin 1` / `MCP server 1` (implied by `--redact`). |
|
|
264
|
-
| `--card-agent <id>` | Which agent the card is about (default: the one with the largest measured load). |
|
|
265
|
-
|
|
266
|
-
The cut headline needs measured always-on data **and** a saving of at least 500 estimated tokens; otherwise the card silently
|
|
267
|
-
uses the total headline (and an all-unmeasured setup says "N MCP servers load before hello, token cost unmeasured"). Every
|
|
268
|
-
headline is checked before it is drawn: it keeps the `~`, says "estimate", and says "at least" when the total is a lower bound.
|
|
269
|
-
|
|
270
|
-
**How PNG works.** The card SVG is rasterised locally with [`@resvg/resvg-wasm`](https://github.com/yisibl/resvg-js) (MPL-2.0; one
|
|
271
|
-
package, about 2.5 MB, WebAssembly, so no native binaries, no build step and the same result on macOS, Linux and Windows).
|
|
272
|
-
It is an *optional* dependency: if it is not installed (for example `npm install --omit=optional`), `--card=x.png` **never crashes**: it prints how to
|
|
273
|
-
install it (to stderr), writes no card and exits 1, while everything else you asked for (the report, `--json`, `--markdown`) is still produced, and SVG cards keep working.
|
|
274
|
-
The message marks how *this* copy of prehello was installed and lists the other ways:
|
|
275
|
-
|
|
276
|
-
```text
|
|
277
|
-
prehello: PNG cards need the optional package @resvg/resvg-wasm, which is not installed here, so no card was written (...).
|
|
278
|
-
Install it, then run the same command again:
|
|
279
|
-
global install of prehello: npm install -g @resvg/resvg-wasm
|
|
280
|
-
project install: npm install @resvg/resvg-wasm (run it in the project that has prehello in node_modules)
|
|
281
|
-
one-off with npx: npx --package prehello --package @resvg/resvg-wasm -- prehello --card=card.png
|
|
282
|
-
Or skip PNG: an SVG card needs no extra install, e.g. --card=card.svg
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
A globally installed prehello also finds a globally installed engine (`npm install -g @resvg/resvg-wasm`, checked with the npm global layout). The text is drawn with a font that ships inside prehello
|
|
286
|
-
(three weights of [Inter](https://github.com/rsms/inter), subsetted to about 31 KB each, SIL OFL 1.1, licence in `assets/fonts/OFL.txt`).
|
|
287
|
-
System fonts are never used, so the glyphs are the same on every machine, and a test checks that every character on a card exists in those fonts.
|
|
288
|
-
The PNG carries a `Software: prehello <version>` text chunk, which is how prehello recognises its own file before replacing it.
|
|
289
|
-
|
|
290
|
-
Sample cards (regenerate with `node scripts/make-sample-cards.mjs docs` after `npm run build`). **These are made from test-fixture
|
|
291
|
-
and synthetic data, not from a real machine; the numbers are illustrations of the format.**
|
|
292
|
-
|
|
293
|
-

|
|
294
|
-
|
|
295
|
-
Square, light theme, same fixture:
|
|
296
|
-
|
|
297
|
-

|
|
298
|
-
|
|
299
|
-
A synthetic Cursor setup shaped like a real Mac scan (one big plugin, a small one, 18 Cursor-managed skills). The treemap tiles are the same groups as the headline and the "What to cut" list:
|
|
300
|
-
|
|
301
|
-

|
|
302
|
-
|
|
303
|
-
A synthetic "heavy" Claude Code setup (35 own skills, 6 plugins, 14 rules, 8 unmeasured MCP servers), which shows the lower-bound wording:
|
|
304
|
-
|
|
305
|
-

|
|
306
|
-
|
|
307
|
-
An SVG version of the first card is in `docs/sample-card-fixture.svg`.
|
|
308
|
-
|
|
309
|
-
</details>
|
|
310
|
-
|
|
311
|
-
<details>
|
|
312
|
-
<summary><b>Markdown report (<code>--markdown</code>)</b></summary>
|
|
313
|
-
|
|
314
|
-
`--markdown` prints a report you can paste into a GitHub issue or PR, Slack, or a README; `--markdown=report.md` writes it to a file instead
|
|
315
|
-
(the file name must end in `.md` or `.markdown`; the same safe-write rules as `--card` and `--json` apply: no symlinks, no replacing a file prehello did
|
|
316
|
-
not write unless `--force`, never a file it scanned). On stdout it *replaces* the terminal report, so it composes with other output files
|
|
317
|
-
(`--markdown --json=out.json`), but `--json` and `--fix` cannot share stdout with it. With a file name the normal terminal report still prints.
|
|
318
|
-
|
|
319
|
-
It contains: a title, the headline (the same cut-first headline as the card: `~` on every estimate, "at least" for lower bounds, an unmeasured item is
|
|
320
|
-
"not measured", never 0), per agent a table of what loads before hello, the Context Grade (provisional when something is unmeasured), "What to cut",
|
|
321
|
-
a "Measured vs not measured" list, and a footer with the prehello version and "estimates". `--markdown-compact` is the short version for a PR comment
|
|
322
|
-
(headline, one line per agent, the first things to cut; it implies `--markdown`). `--agent`, `--window`, `--card-headline` and `--max-tokens` (exit code 2)
|
|
323
|
-
behave as everywhere else.
|
|
324
|
-
|
|
325
|
-
**Privacy.** Same contract as the card: no file paths, no file contents, no findings or warnings text (those name files), no home directory. Plugin, MCP server and skill-folder
|
|
326
|
-
*names* are shown (they make the report useful); `--card-anonymize` (alias `--anonymize`, implied by `--redact`) turns them into "plugin 1" / "MCP server 1".
|
|
327
|
-
Every name is placed in an inline code span with control and bidi characters stripped, secrets scrubbed and pipes escaped, so a hostile name such as
|
|
328
|
-
`](http://evil)`, `<img onerror=...>`, `@everyone` or a backtick run cannot become a link, HTML, a mention or a broken table. prehello's own text is plain ASCII, so it survives any
|
|
329
|
-
console code page.
|
|
330
|
-
|
|
331
|
-
Example (`--markdown-compact`, test fixture, not a real machine):
|
|
332
|
-
|
|
333
|
-
```md
|
|
334
|
-
## prehello report: what your coding agent loads before you say hello
|
|
335
|
-
|
|
336
|
-
**Skills & plugins cost ~4.5k tokens before hello**
|
|
337
|
-
|
|
338
|
-
Cursor: top 3 of 4 groups - cut them, save ~4.2k (estimate).
|
|
339
|
-
|
|
340
|
-
- **Cursor**: ~5k tokens always on (2.5% of 200k), grade A
|
|
341
|
-
|
|
342
|
-
Cut first (Cursor, estimates): `plugin analytics-kit` ~2.2k, `plugin design-kit` ~1.3k, `plugin cloud-kit` ~719
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
</details>
|
|
346
|
-
|
|
347
|
-
<details>
|
|
348
|
-
<summary><b>SARIF (GitHub code scanning, IDEs)</b></summary>
|
|
349
|
-
|
|
350
|
-
`--sarif` prints a [SARIF 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html) log on stdout (it *replaces* the terminal report, like `--markdown`);
|
|
351
|
-
`--sarif=report.sarif` (or `.sarif.json`) writes it to a file and the terminal report still prints. The same safe-write rules as the other outputs apply, and
|
|
352
|
-
`--json`, `--fix` and `--markdown` cannot share stdout with it. `--max-tokens` keeps its exit code (2). The output is validated against the OASIS schema in the test suite.
|
|
353
|
-
|
|
354
|
-
Rules (stable ids; every rule has help text; there are no documentation URLs, the text is in the SARIF itself):
|
|
355
|
-
|
|
356
|
-
| Rule | Level | What it reports |
|
|
357
|
-
| --- | --- | --- |
|
|
358
|
-
| `PH001` | note, warning from 5% of the window | an always-loaded file of 2,000+ tokens (or 1%+ of the window): `CLAUDE.md`, `AGENTS.md`, a rule, `MEMORY.md` |
|
|
359
|
-
| `PH002` | note, warning from 5% of the window | a plugin, skills folder or MCP server of 1,000+ tokens before the first message (the "what to cut" groups, up to 10 per agent) |
|
|
360
|
-
| `PH003` | warning | always-on context above `--max-tokens` ("at least" when something is unmeasured); only exists with that flag |
|
|
361
|
-
| `PH004` | note | always-loaded items that could not be measured: cost unknown, not zero, so totals are lower bounds |
|
|
362
|
-
| `PH005` | warning | two context files that are 60%+ the same text |
|
|
363
|
-
| `PH006` | note | a file longer than the agent's documented length guideline |
|
|
364
|
-
| `PH007` | warning | content the agent silently cuts off (Codex 32 KiB, `MEMORY.md` caps, skill description cap) |
|
|
365
|
-
| `PH008` | warning | a file the agent ignores (`AGENTS.md` next to a `CLAUDE.md` for Claude Code; `.md` in `.cursor/rules`) |
|
|
366
|
-
| `PH009` | warning | a line that looks like a secret (line number only, **never the value**; a pattern match, so false positives happen) |
|
|
367
|
-
| `PH010` | note | a skills listing above the agent's listing budget |
|
|
368
|
-
| `PH011` | note | some sources were unreadable or skipped, or the scan hit its budget |
|
|
369
|
-
|
|
370
|
-
Every number is labelled an estimate (`isEstimate: true`, message text says "estimate"); an unmeasured item never carries a number; `at least` marks a lower bound.
|
|
371
|
-
The `properties` bags carry the estimate with its low/high band, the agent and the share of the window. Results for one file are merged across agents.
|
|
372
|
-
|
|
373
|
-
**Locations and privacy.** A `physicalLocation` is written **only for files inside the scanned folder**, as a relative path against `%SRCROOT%` with `startLine` (the line of the
|
|
374
|
-
first possible secret for `PH009`, else 1). So run it from the repository root. User-level items (`~/.claude`, `~/.cursor`, `~/.codex`, managed, plugin, built-in), files that are
|
|
375
|
-
symlinks out of the project, odd or secret-shaped file names, and everything when you scan your home folder get a `logicalLocation` with a generic label ("User CLAUDE.md",
|
|
376
|
-
"plugin 1") and **no path**. `--redact` drops every file location; `--card-anonymize` / `--anonymize` turns plugin and MCP server names into `plugin 1` / `MCP server 1`.
|
|
377
|
-
No file contents, no finding or warning texts (they name user-level paths), no absolute paths and no home directory ever reach the file. GitHub code scanning shows only results that have a file
|
|
378
|
-
location; results without one (user-level items, `PH003`, `PH004`, `PH011`) are kept for IDE viewers and other tools.
|
|
379
|
-
|
|
380
|
-
GitHub Actions, as a non-blocking annotation (add `--max-tokens` if you also want a gate). The snippet uses `npx prehello`, which works once the package is on npm; until then build from source in the job:
|
|
381
|
-
|
|
382
|
-
```yaml
|
|
383
|
-
name: prehello
|
|
384
|
-
on: [pull_request, push]
|
|
385
|
-
permissions:
|
|
386
|
-
contents: read
|
|
387
|
-
security-events: write # needed to upload SARIF
|
|
388
|
-
jobs:
|
|
389
|
-
context-budget:
|
|
390
|
-
runs-on: ubuntu-latest
|
|
391
|
-
steps:
|
|
392
|
-
- uses: actions/checkout@v4
|
|
393
|
-
- uses: actions/setup-node@v4
|
|
394
|
-
with: { node-version: 20 }
|
|
395
|
-
# a CI runner has no agent config in $HOME, so name the agents whose files in the repo you want scanned
|
|
396
|
-
- run: npx prehello --agent claude-code,cursor,codex --sarif=prehello.sarif || test $? -eq 3
|
|
397
|
-
- uses: github/codeql-action/upload-sarif@v4
|
|
398
|
-
if: always()
|
|
399
|
-
with:
|
|
400
|
-
sarif_file: prehello.sarif
|
|
401
|
-
category: prehello
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
Notes: `|| test $? -eq 3` lets "partial results" through (exit 3) but still fails on a real error (1). Add `--max-tokens 16k` and drop the `|| ...` part if over-budget should fail the job (exit 2);
|
|
405
|
-
the SARIF file is still written first. Uploading needs GitHub code scanning (public repos, or GitHub Advanced Security on private ones). This workflow has **not** been run against GitHub code scanning yet.
|
|
406
|
-
|
|
407
|
-
</details>
|
|
408
|
-
|
|
409
|
-
<details>
|
|
410
|
-
<summary><b>CI: <code>--max-tokens</code></b></summary>
|
|
411
|
-
|
|
412
|
-
```sh
|
|
413
|
-
prehello --max-tokens 16k --quiet || echo "always-on context is over budget"
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
Exit code **2** if the always-on estimate of any agent in use is above the limit (a lower bound that already exceeds it counts; the central estimate is what is compared, not the high end of the band).
|
|
417
|
-
The number goes to stderr, so `--json` on stdout stays valid. Exit code 2 wins over exit code 3 (partial results). Not a substitute for a lint: it gates size, not quality.
|
|
418
|
-
|
|
419
|
-
</details>
|
|
420
|
-
|
|
421
|
-
<details>
|
|
422
|
-
<summary><b>Agents covered: what is scanned</b></summary>
|
|
423
|
-
|
|
424
|
-
| Agent | What is scanned |
|
|
425
|
-
| --- | --- |
|
|
426
|
-
| Claude Code | `CLAUDE.md` chain (user → ancestors → project, `@imports`), `AGENTS.md` only when no `CLAUDE.md` is in the tree, `.claude/rules` (path-scoped → conditional), auto-memory `MEMORY.md` (200-line cap), skills (user, project, enabled plugins; listing up front, bodies deferred), plugin commands, subagent listings, MCP servers (`~/.claude.json`, `.mcp.json`, plugins) |
|
|
427
|
-
| Cursor | `AGENTS.md`, `.cursor/rules/*.mdc` by mode (always / glob / agent-requested / manual; plain `.md` is flagged as ignored), nested rules and skills as conditional, skills in `.cursor/skills` and the compatible `.claude`/`.codex`/`.agents` skill folders, installed plugins' skills / rules / MCP, MCP servers, pasted User Rules |
|
|
428
|
-
| Codex | `~/.codex/AGENTS.md` + `AGENTS.override.md` chain from the repo root to the working directory, 32 KiB cap, shadowed files reported, skills (`.agents/skills` up to the repo root, `~/.agents/skills`, `/etc/codex/skills`, `[[skills.config]]` disabling), MCP servers in `config.toml` |
|
|
429
|
-
|
|
430
|
-
</details>
|
|
431
|
-
|
|
432
|
-
<details>
|
|
433
|
-
<summary><b>Honest caveats</b></summary>
|
|
434
|
-
|
|
435
|
-
- **Token counts are estimates.** Counting uses the o200k BPE tokenizer (`gpt-tokenizer`) with a per-agent scaling prior.
|
|
436
|
-
- Codex / OpenAI-family: ×1.0, ±3%.
|
|
437
|
-
- Claude Code: ×1.5 (`--claude-profile legacy` uses ×1.2), ±20%. **The Claude factor and band are priors, not validated against Anthropic's tokenizer.**
|
|
438
|
-
- Cursor: the model is not discoverable from disk, so the estimate is the midpoint between the GPT-like and Claude-like priors, with a wide band. Also **unvalidated**.
|
|
439
|
-
- `--tokenizer heuristic` falls back to chars/3.5 (3.0 for JSON), ±35%.
|
|
440
|
-
- **Never measured:** the agent's built-in system prompt and built-in tool definitions, server-side/org rules, Cursor User & Team Rules
|
|
441
|
-
(unless you paste them), claude.ai connectors, hook output, anything injected dynamically (memory/RAG plugins).
|
|
442
|
-
- **MCP servers.** Names and counts are always listed. Sizes come only from the bundled catalog (`spec/mcp-weights.json`, 7 servers) or your own `--mcp-catalog`.
|
|
443
|
-
The bundled numbers were **actually measured** with `scripts/measure-mcp.cjs`: each package was installed from npm, started offline in a sandbox with a scrubbed
|
|
444
|
-
environment, and asked for `tools/list`. They are raw o200k counts of the tool-list JSON for the stated version, **not** the exact text any agent injects,
|
|
445
|
-
and tool lists change between versions. Every other server stays "unmeasured". The CLI itself never starts a server. `--no-bundled-catalog` turns the catalog off.
|
|
446
|
-
- **Loading rules come from public docs and the agents' own announcements, not from their source code,** and were researched on the date in `spec/*.json`
|
|
447
|
-
(`prehello --about-specs`). They were **not** re-verified against live installs. Where sources disagree the item is labelled `assumed` (see below).
|
|
448
|
-
Treat `ignored`/`truncated` findings as strong hints, not proof.
|
|
449
|
-
- **Confidence labels** on every item: `documented` (a public doc says so), `observed` (seen on a real machine), `assumed` (a best guess; stated as such in the notes).
|
|
450
|
-
Examples of `assumed`: how Cursor and Codex format their skills listing and what it costs, Cursor's `~/.cursor/skills-cursor`, Cursor plugin install state,
|
|
451
|
-
nested `.cursor/rules`, and whether Codex loads MCP schemas upfront.
|
|
452
|
-
- **The Context Grade is a heuristic of this tool**, not a standard. `prehello explain grade` prints the exact rubric.
|
|
453
|
-
- **Windows and macOS:** the full test suite runs in CI on Ubuntu, Windows and macOS with Node 18, 20 and 22, and was green on 2026-10-25 (GitHub-hosted runners only; not tried on a range
|
|
454
|
-
of real Windows consoles, locales or corporate setups). Windows specifics (USERPROFILE home, drive letters, UNC, backslash globs, CRLF/BOM/UTF-16 files, reserved device names, case-insensitive file systems)
|
|
455
|
-
are covered by tests, partly by simulation. Only the three listed agents plus plain `AGENTS.md` are covered.
|
|
456
|
-
|
|
457
|
-
</details>
|
|
458
|
-
|
|
459
|
-
<details>
|
|
460
|
-
<summary><b>Privacy and safety</b></summary>
|
|
461
|
-
|
|
462
|
-
- **Local only, read-only.** No network, no telemetry, no API key, no child processes. The scanner reads files; the only files it ever
|
|
463
|
-
writes are those you explicitly request (`--json=<file>`, `--card=<file.svg|png>`, `--markdown=<file.md>`, `--sarif=<file.sarif>`), and it refuses to overwrite a file it scanned.
|
|
464
|
-
- **Output files are written defensively.** prehello never writes *through a symlink* (not even with `--force`). It replaces an existing
|
|
465
|
-
file only if that file is a previous prehello output (an SVG or PNG it generated, a Markdown file starting with its `<!-- generated by prehello` marker, JSON whose `tool.name` is `prehello`, or a SARIF file whose driver is `prehello`); anything else needs `--force`.
|
|
466
|
-
Directories, other non-regular files and files with extra hard links are refused (hard links need `--force`). The file is opened with `O_NOFOLLOW` and
|
|
467
|
-
checked again after opening, so a link swapped in at the last moment is not followed. A symlinked *parent directory* is not detected: point `--json=`/`--card=` at a path you mean to write.
|
|
468
|
-
- It **never prints file contents** (that includes text passed with `--paste-user-rules`, which is counted and discarded).
|
|
469
|
-
Output contains token counts, file *names/paths*, skill, plugin and MCP server *names*, and line-number locations for findings.
|
|
470
|
-
A line that looks like a secret is reported by location only, never echoed. Terminal control characters in file names are neutralised.
|
|
471
|
-
- Terminal and `--json` shorten paths (`~`, `./`) but keep names. **Use `--redact` before sharing a JSON file.** The SVG and PNG cards and the Markdown report contain no paths or file contents
|
|
472
|
-
(no paths, no file contents, no home directory). They do show plugin and MCP server names as treemap tile labels; use `--card-anonymize` to hide those.
|
|
473
|
-
- **Resource limits.**
|
|
474
|
-
- A single file over **4 MiB** is skipped and shown as *unmeasured* (exit code 3). That matches Claude Code's documented behaviour of skipping a startup `CLAUDE.md` over 4 MiB entirely;
|
|
475
|
-
for other agents it is a safety cap, not their rule. Binary files and symlinks that leave the project are skipped the same way.
|
|
476
|
-
- **Scan budget:** at most **64 MiB** read in total (deterministic; `--scan-budget-mb`) and **20 s** wall clock (`--scan-budget-ms`, a safety net, the one limit that can vary on a slow disk).
|
|
477
|
-
When a budget is hit the scan stops, prints one "results are PARTIAL" warning, every total becomes a lower bound, the grade is provisional, and `--json` has a non-null `partial`.
|
|
478
|
-
- The directory walk stops at 5,000 entries (depth 8) and says so. Test-fixture folders are not walked by default (`--include-fixtures`), so they do not use up that budget.
|
|
479
|
-
- These claims are tested, not just stated: a runtime guard blocks and records any filesystem write, network, DNS, `fetch` or child-process attempt
|
|
480
|
-
while the CLI runs on fixtures; a source scan bans those modules from `src/` and allows write APIs in exactly one file (`src/safe-write.ts`); a network-namespace run is used when the OS allows it; and planted "canary" strings
|
|
481
|
-
prove file contents never reach any output. See `test/safety.test.ts` and `test/sarif.test.ts`. (`scripts/measure-mcp.cjs` is a dev-only helper that is not part of the CLI and not in the package.)
|
|
482
|
-
|
|
483
|
-
</details>
|
|
484
|
-
|
|
485
|
-
<details>
|
|
486
|
-
<summary><b>Platforms</b></summary>
|
|
487
|
-
|
|
488
|
-
prehello runs on Linux, macOS and Windows (Node ≥ 18) and prints the same numbers on all three.
|
|
489
|
-
|
|
490
|
-
- **Home folder.** macOS/Linux: `$HOME`. Windows: `%USERPROFILE%` (Claude Code, Cursor and Codex all take it from the OS; Git Bash's `HOME=/c/Users/me` is not used).
|
|
491
|
-
`CLAUDE_CONFIG_DIR` is honoured everywhere.
|
|
492
|
-
- **Machine-wide files.** macOS `/Library/Application Support/ClaudeCode`, Linux `/etc/claude-code`, Windows `%ProgramFiles%\ClaudeCode` (falls back to `C:\Program Files\ClaudeCode`).
|
|
493
|
-
Cursor is detected by `~/.cursor`, `cursor` on `PATH`, `Cursor.app` (macOS) or `%LOCALAPPDATA%\Programs\cursor\Cursor.exe` (Windows).
|
|
494
|
-
- **Paths in output** always use forward slashes (`./`, `~/`), on Windows too, so JSON and Markdown never contain backslashes or `C:\Users\...`.
|
|
495
|
-
- **Files written by Windows tools** are read correctly: CRLF and a UTF-8 BOM are handled in context files, `--mcp-catalog` and `--paste-user-rules`. A UTF-16 file
|
|
496
|
-
(Windows PowerShell 5's `>` redirection) is reported as "saved as UTF-16, re-save as UTF-8", not as binary.
|
|
497
|
-
- **Redirecting output on Windows.** Windows PowerShell 5 re-encodes `prehello --json > out.json` as UTF-16. Use `--json=out.json` or `--markdown=report.md`; prehello writes UTF-8 itself.
|
|
498
|
-
Output files named like a Windows device (`NUL`, `CON`, `COM1`, ...) or containing a `:` stream marker are refused.
|
|
499
|
-
- **Console.** The legacy Windows console (cmd.exe, classic PowerShell window) and the Linux virtual console cannot draw box/block glyphs, so prehello switches to plain ASCII there
|
|
500
|
-
automatically; `--ascii` (or `PREHELLO_ASCII=1`) forces it. `NO_COLOR`, `--no-color` and `TERM=dumb` turn colour off. The Markdown report is ASCII already.
|
|
501
|
-
- **Install.** From source it is `node dist/cli.js` on every system. Once the package is on npm, `npm install -g prehello` creates a `prehello.cmd` shim on Windows and `npx prehello` works the same everywhere. File modes are not relied on.
|
|
502
|
-
|
|
503
|
-
</details>
|
|
504
|
-
|
|
505
|
-
|
|
506
162
|
## Roadmap
|
|
507
163
|
|
|
508
|
-
Not
|
|
164
|
+
Not yet: `--probe` (starting MCP servers to measure real schemas), history beyond two snapshots, `--apply` / `--patch`, Windsurf and Cline adapters,
|
|
509
165
|
Cursor Team Rules, a catalog beyond the 7 measured servers.
|
|
510
166
|
|
|
511
167
|
## Contributing, security, licence
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -28,6 +28,6 @@ TypeScript (Apache-2.0), vitest (MIT), ajv and ajv-formats (MIT), `@types/*` (MI
|
|
|
28
28
|
|
|
29
29
|
## Documentation
|
|
30
30
|
|
|
31
|
-
The loading rules in `spec/*.json` are facts summarised from the public documentation of Claude Code, Cursor and
|
|
31
|
+
The loading rules in `spec/*.json` are facts summarised from the public documentation of Claude Code, Cursor, Codex, GitHub Copilot and Gemini CLI, each with the URL it came from. No documentation text is copied.
|
|
32
32
|
|
|
33
33
|
The Code of Conduct is the [Contributor Covenant](https://www.contributor-covenant.org) 2.1 (CC BY 4.0).
|
package/dist/adapters/common.js
CHANGED
|
@@ -40,8 +40,8 @@ function loadInstruction(ctx, filePath, o) {
|
|
|
40
40
|
text = (0, comments_1.stripHtmlComments)(text);
|
|
41
41
|
let detail;
|
|
42
42
|
if (o.imports) {
|
|
43
|
-
const roots =
|
|
44
|
-
const res = (0, imports_1.expandImports)(text, filePath, ctx.home, (real) => roots.some((root) => (0, fs_safe_1.isInside)(real, root)), { stripComments: o.stripComments, read: (t) => ctx.read(t, { quiet: true }) });
|
|
43
|
+
const roots = (o.importRoots ?? [ctx.home, ctx.gitRoot ?? ctx.cwd, node_path_1.default.dirname(filePath)]).map(fs_safe_1.realpathOrSelf);
|
|
44
|
+
const res = (0, imports_1.expandImports)(text, filePath, ctx.home, (real) => roots.some((root) => (0, fs_safe_1.isInside)(real, root)), { stripComments: o.stripComments, read: (t) => ctx.read(t, { quiet: true }), maxDepth: o.importMaxDepth, relativeOnly: o.importRelativeOnly });
|
|
45
45
|
text = res.text;
|
|
46
46
|
if (res.imported)
|
|
47
47
|
detail = `(+${res.imported} @import${res.imported > 1 ? "s" : ""})`;
|
|
@@ -50,7 +50,7 @@ function loadInstruction(ctx, filePath, o) {
|
|
|
50
50
|
}
|
|
51
51
|
if (!text.trim())
|
|
52
52
|
return null;
|
|
53
|
-
const key = `${r.realPath}|${o.stripComments ? 1 : 0}${o.imports ? 1 : 0}|${o.transform ? text.length : ""}`;
|
|
53
|
+
const key = `${r.realPath}|${o.stripComments ? 1 : 0}${o.imports ? 1 : 0}|${o.importRoots ? o.importRoots.join(",") : ""}${o.importMaxDepth ?? ""}${o.importRelativeOnly ? "r" : ""}|${o.transform ? text.length : ""}`;
|
|
54
54
|
const raw = ctx.count(key, text);
|
|
55
55
|
if (!o.noAnalyze)
|
|
56
56
|
ctx.analyzeDoc(o.agent, filePath, r.text, afterTransform, raw, o.guidelineLines);
|