agy-insights 0.0.0-stage → 0.4.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Miguel González
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.
package/README.es.md ADDED
@@ -0,0 +1,169 @@
1
+ # agy-insights
2
+
3
+ [English](README.md) · **Español**
4
+
5
+ Te muestra qué contexto le estás mandando a **Antigravity** de forma repetida o innecesaria, a partir del historial que Antigravity CLI guarda en tu equipo. Tú decides qué hacer con ello.
6
+
7
+ - Se ejecuta solo en tu máquina y no envía nada a ningún sitio.
8
+ - No cambia nada: te dice qué pegar y dónde, y lo haces tú si quieres.
9
+ - Solo propone mecanismos oficiales de Antigravity.
10
+ - Funciona con cualquier editor, en Windows, macOS y Linux.
11
+
12
+ ```sh
13
+ npx agy-insights # informe HTML en el navegador
14
+ npx agy-insights --text # resumen en la terminal
15
+ ```
16
+
17
+ Solo necesitas Node.js 20 o superior y haber usado Antigravity CLI (`agy`) en el equipo. La salida sale en español o en inglés según el idioma del sistema; puedes forzarlo con `--lang es` o `--lang en`.
18
+
19
+ ## Por qué
20
+
21
+ Cada fichero que lee el agente y cada salida de comando entra en el contexto y se reenvía en los turnos siguientes de la conversación. La cuota es una bolsa común, así que cada lectura innecesaria la gasta para todos. Esta herramienta te enseña dónde se va ese contexto: relecturas, carpetas de compilación, salidas de tests enormes y sesiones demasiado largas.
22
+
23
+ ## Requisitos
24
+
25
+ - **Node.js 20 o superior** (`node --version`).
26
+ - Haber usado **Antigravity CLI** (`agy`) en este equipo. El historial está en `~/.gemini/antigravity-cli/conversations` (en Windows, `%USERPROFILE%\.gemini\antigravity-cli\conversations`).
27
+
28
+ ## Instalar
29
+
30
+ No tiene dependencias. Elige una forma:
31
+
32
+ **Con `npx`, sin instalar nada:**
33
+
34
+ ```sh
35
+ npx agy-insights
36
+ npx agy-insights --text
37
+ ```
38
+
39
+ Para fijar una versión: `npx agy-insights@0.4.0`.
40
+
41
+ **Instalándolo globalmente:**
42
+
43
+ ```sh
44
+ npm install -g agy-insights
45
+ agy-insights
46
+ ```
47
+
48
+ **Clonando el repositorio:**
49
+
50
+ ```sh
51
+ git clone https://github.com/migohe14/agy-insights.git
52
+ ```
53
+
54
+ Y ejecútalo con `node agy-insights/agy-insights.js` en lugar de `npx agy-insights`. Para actualizar: `git pull` dentro de la carpeta.
55
+
56
+ ## Usar
57
+
58
+ ```sh
59
+ npx agy-insights
60
+ ```
61
+
62
+ Analiza todo tu historial, guarda un informe HTML en la carpeta temporal y lo abre en el navegador.
63
+
64
+ | Para… | Ejecuta |
65
+ |---|---|
66
+ | Ver solo un proyecto | `npx agy-insights --project C:\dev\mi-proyecto` |
67
+ | Ver el proyecto de la carpeta actual | `npx agy-insights --project .` |
68
+ | Un resumen en la terminal | `npx agy-insights --text` |
69
+ | El resumen con rutas y exclusiones | `npx agy-insights --text --paths` |
70
+ | Un mapa del proyecto para pegar en `AGENTS.md` (carpetas, ficheros grandes, carpetas generadas; ~20 líneas aunque el repo sea grande) | `npx agy-insights --map --project <carpeta>` |
71
+ | Elegir el idioma (español o inglés) | `npx agy-insights --lang es` |
72
+ | Guardar el informe en otro sitio | `npx agy-insights --out informe.html --no-open` |
73
+ | Ver todas las opciones | `npx agy-insights --help` |
74
+
75
+ El informe da dos cifras:
76
+
77
+ - **Consumo real**: los tokens que Antigravity anota en el registro de cada conversación (`~/.gemini/antigravity-cli/brain/<id>/.system_generated/logs/transcript.jsonl`), subagentes incluidos. Se muestra sin caché y con caché, porque no sabemos si la cuota cuenta igual la caché. Es la cifra que sirve para comparar entre compañeros.
78
+ - **«~tokens»**: estimados a partir del tamaño guardado de cada paso. Sirven para comparar qué ficheros, carpetas o comandos pesan más, pero se quedan cortos frente al consumo real, porque cada llamada al modelo vuelve a enviar el contexto acumulado.
79
+
80
+ ## Leer el informe
81
+
82
+ Arriba están los totales. Debajo, **Qué está pasando** reúne los hallazgos; al final, el detalle por proyecto, tipo de fichero, carpeta, fichero, herramienta y comando. El proyecto de cada fichero se detecta por su carpeta `.git`.
83
+
84
+ | Hallazgo | Qué significa | Qué hacer |
85
+ |---|---|---|
86
+ | El agente vuelve a leer lo que ya tenía | Lee otra vez un trozo de fichero que ya estaba en la conversación | Sesiones más cortas, una por tarea, o `/compact`. No excluyas el fichero: lo necesita. |
87
+ | Ficheros generados, compilados o de dependencias | Lecturas de `bin/`, `obj/`, `dist/`, `node_modules`, migraciones, lockfiles o logs | Si no hacían falta, exclúyelos (ver abajo) |
88
+ | Los mismos ficheros entran en muchas sesiones | Un fichero se lee en varias conversaciones distintas | Si es código central es normal; si es grande, dile al agente qué parte mirar |
89
+ | Comandos con salidas muy largas | La salida de tests o builds entra entera | Pide ejecutar solo el test o proyecto afectado |
90
+ | Sesiones muy largas | Todo lo acumulado se reenvía en cada turno | Una conversación nueva por tarea |
91
+
92
+ ## Excluir algo
93
+
94
+ Despliega **Cómo excluirlo** en una propuesta. Verás el fichero exacto, dónde va el texto y un botón **Copiar**. Hay tres opciones, de más a menos fuerte:
95
+
96
+ ### 1. Denegar la lectura (permiso de Antigravity)
97
+
98
+ Es lo único que impide de verdad que el agente lea una ruta. Usa los [permisos oficiales](https://antigravity.google/docs/permissions).
99
+
100
+ 1. Abre `~/.gemini/antigravity-cli/settings.json` (en Windows, `%USERPROFILE%\.gemini\antigravity-cli\settings.json`).
101
+ 2. Pega la regla dentro de `"permissions"` → `"deny"`. Si no existen, créalas; si existen, añade la regla sin borrar nada:
102
+
103
+ ```json
104
+ {
105
+ "model": "Gemini 3.8 Flash (Medium)",
106
+ "permissions": {
107
+ "deny": [
108
+ "read_file(C:\\dev\\mi-proyecto\\src\\Infra\\obj)"
109
+ ]
110
+ }
111
+ }
112
+ ```
113
+
114
+ 3. Guarda y reinicia `agy`.
115
+
116
+ Denegar la lectura de una ruta también impide escribir en ella, y la regla vale para todos tus proyectos. Úsala para carpetas que el agente no deba tocar nunca, como salidas de compilación.
117
+
118
+ ### 2. `.antigravityignore`
119
+
120
+ Es el fichero de exclusión de Antigravity, en la raíz del proyecto. Su efecto no está documentado: está confirmado que oculta los ficheros del autocompletado con `@`, pero no que impida al agente leerlos.
121
+
122
+ ### 3. Regla en `AGENTS.md`
123
+
124
+ Una línea en el `AGENTS.md` del proyecto, pidiendo al modelo que no lea algo o que limite una salida. Es una indicación, no un bloqueo. Las reglas se envían en cada petición y también gastan tokens, así que mantenlas cortas. `AGENTS.md` suele estar en el repositorio del equipo: revisa el cambio antes de subirlo.
125
+
126
+ ## Configurar
127
+
128
+ Copia `agy-insights.example.json` a `~/.agy-insights.json` (o pásalo con `--config`) y ajústalo. Es tu configuración personal:
129
+
130
+ | Clave | Para qué sirve | Por defecto |
131
+ |---|---|---|
132
+ | `lang` | Idioma de la salida: `es` o `en` (`--lang` tiene prioridad) | el del sistema |
133
+ | `conversationsDir` | Otra carpeta de historial | la de Antigravity CLI |
134
+ | `customKinds` | Tipos de fichero propios: `{ "regex": "etiqueta" }` | ninguno |
135
+ | `crossSessionMin` | A partir de cuántas conversaciones avisa de un fichero repetido | 3 |
136
+ | `heavyOutputTokens` | A partir de qué tamaño medio avisa de un comando | 2000 |
137
+ | `longSessionTokens` | A partir de qué tamaño avisa de una sesión larga | 100000 |
138
+
139
+ ## Privacidad
140
+
141
+ - Todo se calcula en tu equipo; no se envía nada.
142
+ - El historial se lee desde una copia temporal y nunca se modifica.
143
+ - No escribe en `~/.gemini`, no instala hooks ni plugins y no toca tu `.gitignore` ni tus proyectos.
144
+ - Lo único que escribe es el informe HTML, en la carpeta temporal o donde digas con `--out`.
145
+ - El informe contiene rutas de tus proyectos. No lo compartas sin revisarlo.
146
+ - **No compartas los ficheros `.db` del historial**: contienen el código que leyó el agente.
147
+
148
+ ## Deshacer
149
+
150
+ - **Permiso**: borra la línea `read_file(…)` de `"deny"` en `settings.json` y reinicia `agy`.
151
+ - **.antigravityignore y AGENTS.md**: borra las líneas que añadiste.
152
+
153
+ ## Problemas frecuentes
154
+
155
+ **«No hay conversaciones»**. Si usaste `--project`, puede que trabajaras con Antigravity desde otra carpeta: prueba sin `--project`. Si tampoco aparecen, comprueba que existe la carpeta del historial.
156
+
157
+ **«No se reconoce el formato del historial»**. Probablemente una versión nueva de Antigravity ha cambiado cómo guarda las conversaciones. Ejecuta `npx agy-insights@latest`; si sigue igual, [abre una incidencia](https://github.com/migohe14/agy-insights/issues).
158
+
159
+ **Uso la app o el IDE de Antigravity, no el CLI**. Por ahora solo se lee el historial del CLI.
160
+
161
+ **El navegador no se abre**. La ruta del informe aparece en la terminal; ábrela a mano.
162
+
163
+ ## Estado
164
+
165
+ Versión piloto. El formato del historial de Antigravity no está documentado, así que algunos datos pueden fallar con versiones nuevas. Si ves algo raro, [abre una incidencia](https://github.com/migohe14/agy-insights/issues). Para contribuir, mira [docs/how-it-works.md](docs/how-it-works.md) (en inglés).
166
+
167
+ ## Licencia
168
+
169
+ [MIT](LICENSE)
package/README.md CHANGED
@@ -1,3 +1,169 @@
1
- # Temporary Holding Version
1
+ # agy-insights
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **English** · [Español](README.es.md)
4
+
5
+ Shows which context you are sending to **Antigravity** repeatedly or needlessly, based on the history Antigravity CLI keeps on your machine. You decide what to do about it.
6
+
7
+ - Runs only on your machine and sends nothing anywhere.
8
+ - Changes nothing: it tells you what to paste and where, and you do it if you want.
9
+ - Only proposes official Antigravity mechanisms.
10
+ - Works with any editor, on Windows, macOS and Linux.
11
+
12
+ ```sh
13
+ npx agy-insights # HTML report in the browser
14
+ npx agy-insights --text # summary in the terminal
15
+ ```
16
+
17
+ All you need is Node.js 20 or later and to have used Antigravity CLI (`agy`) on this machine. The output is in English or Spanish, following your system language; force it with `--lang en` or `--lang es`.
18
+
19
+ ## Why
20
+
21
+ Every file the agent reads and every command output enters the context and is resent on the following turns of the conversation. Quota is a shared pool, so every unnecessary read spends it for everyone. This tool shows you where that context goes: re-reads, build folders, huge test outputs and sessions that run too long.
22
+
23
+ ## Requirements
24
+
25
+ - **Node.js 20 or later** (`node --version`).
26
+ - Having used **Antigravity CLI** (`agy`) on this machine. The history lives in `~/.gemini/antigravity-cli/conversations` (on Windows, `%USERPROFILE%\.gemini\antigravity-cli\conversations`).
27
+
28
+ ## Install
29
+
30
+ It has no dependencies. Pick one:
31
+
32
+ **With `npx`, nothing to install:**
33
+
34
+ ```sh
35
+ npx agy-insights
36
+ npx agy-insights --text
37
+ ```
38
+
39
+ To pin a version: `npx agy-insights@0.4.0`.
40
+
41
+ **Globally:**
42
+
43
+ ```sh
44
+ npm install -g agy-insights
45
+ agy-insights
46
+ ```
47
+
48
+ **From the repository:**
49
+
50
+ ```sh
51
+ git clone https://github.com/migohe14/agy-insights.git
52
+ ```
53
+
54
+ Then run it with `node agy-insights/agy-insights.js` instead of `npx agy-insights`. To update: `git pull` inside the folder.
55
+
56
+ ## Usage
57
+
58
+ ```sh
59
+ npx agy-insights
60
+ ```
61
+
62
+ Analyzes your whole history, saves an HTML report in the temp folder and opens it in the browser.
63
+
64
+ | To… | Run |
65
+ |---|---|
66
+ | See only one project | `npx agy-insights --project C:\dev\my-project` |
67
+ | See the project in the current folder | `npx agy-insights --project .` |
68
+ | Get a summary in the terminal | `npx agy-insights --text` |
69
+ | Get the summary with paths and exclusions | `npx agy-insights --text --paths` |
70
+ | Get a project map to paste into `AGENTS.md` (folders, large files, generated folders; ~20 lines even for a large repo) | `npx agy-insights --map --project <folder>` |
71
+ | Choose the language (English or Spanish) | `npx agy-insights --lang es` |
72
+ | Save the report somewhere else | `npx agy-insights --out report.html --no-open` |
73
+ | See all options | `npx agy-insights --help` |
74
+
75
+ The report gives two figures:
76
+
77
+ - **Real usage**: the tokens Antigravity records in each conversation's log (`~/.gemini/antigravity-cli/brain/<id>/.system_generated/logs/transcript.jsonl`), subagents included. It is shown with and without cache, because it is unknown whether the quota counts cache the same way. This is the figure to compare between teammates.
78
+ - **"~tokens"**: estimated from the stored size of each step. Useful to compare which files, folders or commands weigh the most, but they fall short of real usage, because every model call resends the accumulated context.
79
+
80
+ ## Reading the report
81
+
82
+ The totals are at the top. Below, **What's happening** lists the findings; at the end, the details by project, file type, folder, file, tool and command. The project of each file is detected through its `.git` folder.
83
+
84
+ | Finding | What it means | What to do |
85
+ |---|---|---|
86
+ | The agent re-reads what it already had | It reads again a chunk of a file that was already in the conversation | Shorter sessions, one per task, or `/compact`. Don't exclude the file: the agent needs it. |
87
+ | Generated, build or dependency files are being read | Reads from `bin/`, `obj/`, `dist/`, `node_modules`, migrations, lockfiles or logs | If they weren't needed, exclude them (see below) |
88
+ | The same files enter many sessions | A file is read in several different conversations | Normal for core code; if it is large, tell the agent which part to look at |
89
+ | Commands with very long output | The full output of tests or builds enters the context | Ask it to run only the affected test or project |
90
+ | Very long sessions | Everything accumulated is resent on every turn | A new conversation per task |
91
+
92
+ ## Excluding something
93
+
94
+ Expand **How to exclude it** on a proposal. You'll see the exact file, where the text goes and a **Copy** button. There are three options, from strongest to weakest:
95
+
96
+ ### 1. Deny reading it (Antigravity permission)
97
+
98
+ This is the only thing that actually stops the agent from reading a path. It uses the [official permissions](https://antigravity.google/docs/permissions).
99
+
100
+ 1. Open `~/.gemini/antigravity-cli/settings.json` (on Windows, `%USERPROFILE%\.gemini\antigravity-cli\settings.json`).
101
+ 2. Paste the rule inside `"permissions"` → `"deny"`. Create them if they don't exist; if they do, add the rule without removing anything:
102
+
103
+ ```json
104
+ {
105
+ "model": "Gemini 3.8 Flash (Medium)",
106
+ "permissions": {
107
+ "deny": [
108
+ "read_file(C:\\dev\\my-project\\src\\Infra\\obj)"
109
+ ]
110
+ }
111
+ }
112
+ ```
113
+
114
+ 3. Save and restart `agy`.
115
+
116
+ Denying reads on a path also blocks writing to it, and the rule applies to all your projects. Use it for folders the agent should never touch, such as build output.
117
+
118
+ ### 2. `.antigravityignore`
119
+
120
+ Antigravity's exclusion file, at the project root. Its effect is undocumented: it is confirmed to hide files from `@` completion, but not to stop the agent from reading them.
121
+
122
+ ### 3. A rule in `AGENTS.md`
123
+
124
+ A line in the project's `AGENTS.md` asking the model not to read something or to limit an output. It is an instruction, not a block. Rules are sent with every request and cost tokens too, so keep them short. `AGENTS.md` usually lives in the team repository: review the change before pushing it.
125
+
126
+ ## Configuration
127
+
128
+ Copy `agy-insights.example.json` to `~/.agy-insights.json` (or pass it with `--config`) and adjust it. It is your personal configuration:
129
+
130
+ | Key | What it does | Default |
131
+ |---|---|---|
132
+ | `lang` | Output language: `en` or `es` (`--lang` takes precedence) | the system's |
133
+ | `conversationsDir` | Another history folder | Antigravity CLI's |
134
+ | `customKinds` | Your own file types: `{ "regex": "label" }` | none |
135
+ | `crossSessionMin` | From how many conversations a repeated file is reported | 3 |
136
+ | `heavyOutputTokens` | From what average size a command is reported | 2000 |
137
+ | `longSessionTokens` | From what size a session is reported as long | 100000 |
138
+
139
+ ## Privacy
140
+
141
+ - Everything is computed on your machine; nothing is sent.
142
+ - The history is read from a temporary copy and never modified.
143
+ - It does not write to `~/.gemini`, installs no hooks or plugins, and does not touch your `.gitignore` or your projects.
144
+ - The only thing it writes is the HTML report, in the temp folder or wherever `--out` says.
145
+ - The report contains paths from your projects. Review it before sharing.
146
+ - **Don't share the history `.db` files**: they contain the code the agent read.
147
+
148
+ ## Undo
149
+
150
+ - **Permission**: remove the `read_file(…)` line from `"deny"` in `settings.json` and restart `agy`.
151
+ - **.antigravityignore and AGENTS.md**: remove the lines you added.
152
+
153
+ ## Troubleshooting
154
+
155
+ **"No conversations"**. If you used `--project`, you may have worked with Antigravity from another folder: try without `--project`. If they still don't show up, check that the history folder exists.
156
+
157
+ **"The history format is not recognized"**. A new Antigravity version has probably changed how it stores conversations. Run `npx agy-insights@latest`; if it persists, [open an issue](https://github.com/migohe14/agy-insights/issues).
158
+
159
+ **I use the Antigravity app or IDE, not the CLI**. For now only the CLI history is read.
160
+
161
+ **The browser doesn't open**. The report path is printed in the terminal; open it manually.
162
+
163
+ ## Status
164
+
165
+ Pilot version. Antigravity's history format is undocumented, so some data may break with new versions. If you see something odd, [open an issue](https://github.com/migohe14/agy-insights/issues). To contribute, see [docs/how-it-works.md](docs/how-it-works.md).
166
+
167
+ ## License
168
+
169
+ [MIT](LICENSE)
@@ -0,0 +1,10 @@
1
+ {
2
+ "conversationsDir": "",
3
+ "customKinds": {
4
+ "/Legacy/": "legacy code",
5
+ "\\.resx$": "resources"
6
+ },
7
+ "crossSessionMin": 3,
8
+ "heavyOutputTokens": 2000,
9
+ "longSessionTokens": 100000
10
+ }
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ // agy-insights: shows which context is sent to Antigravity repeatedly or needlessly, from the local
3
+ // Antigravity CLI history. Read-only: the only file it writes is the HTML report, in the temp folder
4
+ // (or wherever --out says).
5
+ const fs = require('fs');
6
+ const os = require('os');
7
+ const path = require('path');
8
+ const { spawn } = require('child_process');
9
+ const { analyze, DEFAULT_DIR } = require('./lib/history');
10
+ const { findings, DEFAULTS } = require('./lib/findings');
11
+ const report = require('./lib/report');
12
+ const { buildMap } = require('./lib/map');
13
+ const { t, setLang, detect } = require('./lib/i18n');
14
+
15
+ function parseArgs(argv) {
16
+ const opts = { open: true };
17
+ for (let i = 0; i < argv.length; i++) {
18
+ const a = argv[i];
19
+ const value = () => {
20
+ if (i + 1 >= argv.length) fail(t.missingValue(a));
21
+ return argv[++i];
22
+ };
23
+ if (a === '--help' || a === '-h') opts.help = true;
24
+ else if (a === '--project') opts.project = absolute(value());
25
+ else if (a === '--text') opts.text = true;
26
+ else if (a === '--paths') opts.paths = true;
27
+ else if (a === '--map') opts.map = true;
28
+ else if (a === '--out') opts.out = path.resolve(value());
29
+ else if (a === '--no-open') opts.open = false;
30
+ else if (a === '--dir') opts.dir = path.resolve(value());
31
+ else if (a === '--config') opts.config = path.resolve(value());
32
+ else if (a === '--lang') opts.lang = value();
33
+ else fail(t.unknownOption(a));
34
+ }
35
+ return opts;
36
+ }
37
+
38
+ // History paths may come from Windows ("C:\..."): keep those as they are on any OS.
39
+ const absolute = (p) => (/^[A-Za-z]:[\\/]/.test(p) ? p : path.resolve(p));
40
+
41
+ function fail(msg) {
42
+ console.error(msg);
43
+ process.exit(1);
44
+ }
45
+
46
+ function loadConfig(file) {
47
+ const target = file || path.join(os.homedir(), '.agy-insights.json');
48
+ if (!fs.existsSync(target)) {
49
+ if (file) fail(t.configNotFound(file));
50
+ return {};
51
+ }
52
+ try {
53
+ return JSON.parse(fs.readFileSync(target, 'utf8'));
54
+ } catch (e) {
55
+ return fail(t.cannotRead(target, e.message));
56
+ }
57
+ }
58
+
59
+ function openInBrowser(file) {
60
+ const [cmd, args] = process.platform === 'darwin' ? ['open', [file]]
61
+ : process.platform === 'win32' ? ['cmd', ['/c', 'start', '""', file]]
62
+ : ['xdg-open', [file]];
63
+ try {
64
+ spawn(cmd, args, { stdio: 'ignore', detached: true, windowsHide: true }).on('error', () => {}).unref();
65
+ } catch { /* the path is printed anyway */ }
66
+ }
67
+
68
+ async function main() {
69
+ const argv = process.argv.slice(2);
70
+ // Language first, so that option errors are already in it.
71
+ if (!(argv.includes('--lang') && setLang(argv[argv.indexOf('--lang') + 1]))) setLang(detect());
72
+ const opts = parseArgs(argv);
73
+ if (opts.lang && !setLang(opts.lang)) fail(t.badLang(opts.lang));
74
+ if (opts.help) return console.log(t.help(DEFAULT_DIR));
75
+ const cfg = loadConfig(opts.config);
76
+ if (!opts.lang && cfg.lang && !setLang(cfg.lang)) fail(t.badLang(cfg.lang));
77
+
78
+ if (opts.map) opts.project = opts.project || process.cwd();
79
+ const r = await analyze({
80
+ dir: opts.dir || cfg.conversationsDir || DEFAULT_DIR,
81
+ workspaces: opts.project ? [opts.project] : [],
82
+ customKinds: cfg.customKinds || {},
83
+ });
84
+ if (opts.map) {
85
+ const m = buildMap(opts.project, { ...cfg.map, history: r.files });
86
+ console.log(m.block);
87
+ return console.error(t.mapDone(m.tokens, path.join(opts.project, 'AGENTS.md')));
88
+ }
89
+ const found = findings(r, {
90
+ crossSessionMin: cfg.crossSessionMin ?? DEFAULTS.crossSessionMin,
91
+ heavyOutputTokens: cfg.heavyOutputTokens ?? DEFAULTS.heavyOutputTokens,
92
+ longSessionTokens: cfg.longSessionTokens ?? DEFAULTS.longSessionTokens,
93
+ });
94
+
95
+ if (opts.text) return process.stdout.write(report.text(r, found, { scope: opts.project, paths: opts.paths }));
96
+
97
+ const stamp = new Date().toISOString().slice(0, 16).replace(/[-:T]/g, '');
98
+ const out = opts.out || path.join(os.tmpdir(), 'agy-insights', `${t.reportName}-${stamp}.html`);
99
+ fs.mkdirSync(path.dirname(out), { recursive: true });
100
+ fs.writeFileSync(out, report.html(r, found, { scope: opts.project }));
101
+ console.log(t.done(r.conversations, found.length, out));
102
+ if (opts.open) openInBrowser(out);
103
+ }
104
+
105
+ main().catch((e) => fail(`Error: ${e.message}`));
@@ -0,0 +1,98 @@
1
+ # How it works
2
+
3
+ For whoever maintains or extends agy-insights.
4
+
5
+ ## Principles
6
+
7
+ Every change must respect them:
8
+
9
+ 1. **Read-only.** Nothing is written to `~/.gemini` or to the developer's projects. The history is copied to a temp folder before opening it, because `agy` keeps those databases open. The only thing written is the report.
10
+ 2. **The developer decides.** The tool proposes text to paste; it never applies it.
11
+ 3. **Only official Antigravity mechanisms** for exclusions: permissions (`read_file` in `permissions.deny`), `.antigravityignore` and rules in `AGENTS.md`. No hooks, plugins, `.gitignore` or `.ignore`.
12
+ 4. **Fail visibly.** If the history format changes, the report must say so instead of showing wrong data.
13
+ 5. **Nothing to install.** Only Node 20 or later; SQLite ships in `vendor/`.
14
+
15
+ ## Layout
16
+
17
+ ```
18
+ agy-insights.js command: options, configuration, writes the report and opens the browser
19
+ lib/history.js reads the history and aggregates reads, commands, projects and sessions
20
+ lib/findings.js turns the analysis into findings (the 5 detectors)
21
+ lib/fixes.js builds the text of each exclusion; writes nothing
22
+ lib/map.js project map for AGENTS.md (--map); writes nothing
23
+ lib/i18n.js every user-facing message, in English and Spanish, and language detection
24
+ lib/report.js HTML report (static, copy buttons only) and text summary
25
+ vendor/sql.js/ SQLite in WebAssembly (version in VERSION, MIT license in LICENSE)
26
+ test/fake-history.js generates fake histories in the same format as real ones
27
+ test/*.test.js tests (node --test)
28
+ ```
29
+
30
+ ## The Antigravity CLI history
31
+
32
+ It is undocumented; this is what has been observed in `agy` 1.4.x.
33
+
34
+ - One SQLite database per conversation: `~/.gemini/antigravity-cli/conversations/<uuid>.db`, in WAL mode.
35
+ - Table `steps`: one row per step. `step_payload` is a protobuf message. Tool calls store the name (`view_file`, `run_command`, `grep_search`…) followed by their JSON arguments, for example `{"AbsolutePath":"C:\\dev\\...\\X.cs","StartLine":301,"EndLine":380}`, preceded by a `call_NNN` id.
36
+ - Each call takes two steps with the same id: the model response that requests it (`step_type` 15) and the result (`step_type` 132), which repeats name and arguments and adds the file content or command output. `lib/history.js` counts the call once per id and adds the size of both steps, which approximates what entered the context.
37
+ - Table `gen_metadata`: configuration of each model call, including the model name.
38
+ - Next to the history, `../brain/<id>/.system_generated/logs/transcript.jsonl`: one JSON line per step. `PLANNER_RESPONSE` lines are model calls and carry `input_tokens`, `cache_read_tokens` and `output_tokens`; failed steps have `status: "ERROR"`. Subagents have their own conversation and transcript. `realUsage()` in `lib/history.js` adds those figures up (it only reads the file). The total printed by `agy -p --output-format json` does not include subagents; this one does.
39
+
40
+ `lib/history.js` does not depend on a protobuf schema. It walks the message, collects every string, and treats as a tool call any JSON preceded (within 3 strings) by a `snake_case` name. That way it survives minor format changes. If there are more than 50 steps and no recognized call, it sets `formatUnrecognized` and the report warns about it.
41
+
42
+ ### SQLite
43
+
44
+ - With Node 22.13 or later, `node:sqlite` is used, which also reads the `-wal` file.
45
+ - With earlier versions, `sql.js` from `vendor/` is used. It doesn't read the `-wal`, so the last steps of an open conversation may be missing.
46
+
47
+ To update `sql.js`: copy `dist/sql-wasm.js`, `dist/sql-wasm.wasm` and `LICENSE` from the new version of the npm package and update `VERSION`.
48
+
49
+ ### Projects
50
+
51
+ The project of each file is detected by walking up its path until a folder with `.git` is found, if the path exists on the machine. With `--project`, that folder is used directly. Windows paths (`C:\...`) are normalized to `/` internally and returned with `\` in exclusions, because `agy` matches permission paths literally.
52
+
53
+ ## Languages
54
+
55
+ All user-facing text lives in `lib/i18n.js`, in an `en` and an `es` table with the same keys (a test checks it). Modules read it through `t`, which always points at the current language. The language comes from `--lang`, then the `lang` config key, then the system locale (`LC_ALL`, `LC_MESSAGES`, `LANG`, `LANGUAGE`, or `Intl`): Spanish if it starts with `es`, English otherwise. Numbers follow it too (`en-US` / `es-ES`).
56
+
57
+ Built-in file kinds are stable ids (`build`, `logs`, `generated`, `code .cs`…) and are only turned into text when shown, with `kindLabel()`. Kinds from `customKinds` are shown as the user wrote them.
58
+
59
+ To add a message, add it to both tables. To add a language, add a table and teach `detect()` to pick it.
60
+
61
+ ## Adding a file type
62
+
63
+ In `lib/history.js`, function `kind()`, returning a new id and its label in both tables of `lib/i18n.js`. If it is a type that rarely needs to be read, also add it to `NON_SOURCE`, and its `.antigravityignore` patterns to `KIND_PATTERNS` in `lib/findings.js`. Each developer can add their own types without touching the code with `customKinds` in their configuration.
64
+
65
+ ## Adding a detector
66
+
67
+ In `lib/findings.js`. A finding is `{ id, level: 'info' | 'warn', title, why, suggestion, tokens, items }`, and each `item` is `{ label, tokens, detail, fixes }`. `fixes` are built with `lib/fixes.js`. Never propose excluding source code: the agent needs it.
68
+
69
+ Add a case to `test/fake-history.js` and a test.
70
+
71
+ ## Tests
72
+
73
+ ```sh
74
+ npm test
75
+ ```
76
+
77
+ They cover the analysis with a fake history, the five detectors, the rule format, that excluding source code is never proposed, that the history is not changed, project detection through `.git`, the unknown-format warning, HTML escaping, the project map and the full command. CI runs them on Linux, Windows and macOS with Node 20 (sql.js) and Node 22 (node:sqlite).
78
+
79
+ To generate a sample history and try the report by hand:
80
+
81
+ ```sh
82
+ node test/fake-history.js test/tmp/history
83
+ node agy-insights.js --dir test/tmp/history
84
+ ```
85
+
86
+ ## npm package
87
+
88
+ `package.json` defines the command (`bin`) and which files go into the package (`files`: the command, `lib/`, `vendor/`, `docs/` and the sample configuration; not the tests). It is published on the public npm registry as `agy-insights`. The package only contains the tool; the histories it analyzes stay on each user's machine.
89
+
90
+ - **Try the package locally**: `npm pack`, then `npx --yes --package=./agy-insights-<version>.tgz agy-insights --help`.
91
+ - **From the repository**, unpublished: `npx --yes github:migohe14/agy-insights`. With no dependencies and no build step, npm installs it straight from git.
92
+ - **Release a version**: `npm version <patch|minor|major>` (updates `package.json` and creates the `v…` tag) and `git push --follow-tags`. The `.github/workflows/publish.yml` workflow runs the tests and `npm publish --provenance`. It needs the `NPM_TOKEN` secret in the GitHub repository (an npm *Automation* or *Granular* token with publish permission).
93
+
94
+ ## To do
95
+
96
+ - Confirm with `agy` that a `read_file` `deny` rule blocks the read.
97
+ - Test with real histories from several developers (Windows and macOS).
98
+ - Also read the history of the Antigravity app and IDE, if they use the same format.