@aaa-sentinel/ai-usage 0.1.2 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +339 -324
  2. package/dist/cli.js +541 -146
  3. package/package.json +42 -42
package/README.md CHANGED
@@ -1,324 +1,339 @@
1
- # @aaa-sentinel/ai-usage
2
-
3
- Reports the usage of an **individual Cursor, Claude Code, GitHub Copilot or Codex seat** to
4
- AAA Sentinel, so a personal subscription shows which models it is spent on instead of only a
5
- plan percentage. The prompt, the code and the conversation stay on the laptop.
6
-
7
- - [Who does what](#who-does-what)
8
- - [What leaves your machine](#what-actually-leaves-your-machine)
9
- - [Setup, step by step](#setup-step-by-step)
10
- - [Automatic start](#automatic-start)
11
- - [Per tool](#per-tool)
12
- - [Reading the figures](#reading-the-figures)
13
- - [Troubleshooting](#troubleshooting)
14
- - [Update and remove](#update-and-remove)
15
- - [Environment variables](#environment-variables)
16
-
17
- ## Who does what
18
-
19
- **The person who manages the organization** adds an individual AI connection in AAA Sentinel
20
- (Cursor, Anthropic for Claude Code, Copilot, or OpenAI for Codex) with the email of the person who
21
- uses the tool. In *View connection → Usage agent* they choose **Enroll** and **Copy**: the token is
22
- shown only once. They send it through a private channel, such as a password manager or a direct
23
- message deleted afterwards — never a team channel, a ticket or an email with others in copy.
24
-
25
- **The person who uses the tool** follows the steps below on every computer where they use it, with
26
- the same token. No administrator rights are needed. After step 5 there is nothing to start by hand.
27
-
28
- If the account is yours, you do both parts.
29
-
30
- ## What actually leaves your machine
31
-
32
- One request per day of usage, with **the day, the model and the counters** — input, output,
33
- cache-read and cache-write tokens, and the number of turns — plus a random identifier generated
34
- on this machine that only tells two laptops apart. Each run also asks the server which tool the
35
- connection is for; that request carries nothing but the token.
36
-
37
- Not the prompt, not the code, not the conversation, not your email, not project names and not the
38
- path of a transcript. The CLI reads only the tool its connection is for: a connection enrolled for
39
- Cursor never opens a Claude Code transcript, and `gh` is not called unless the connection is
40
- Copilot.
41
-
42
- The figures are not converted to money and are not added to billed or estimated spend.
43
-
44
- ## Setup, step by step
45
-
46
- Pick the commands for the terminal you use. Install the agent **on the same system where the AI
47
- tool runs**: if you open Cursor or Claude Code on Windows, use a Windows terminal even if you also
48
- have WSL.
49
-
50
- | Terminal | How to open it |
51
- | --- | --- |
52
- | PowerShell (Windows) | Start → type `PowerShell` → Windows PowerShell, PowerShell 7 or a PowerShell tab in Windows Terminal. Not as administrator |
53
- | CMD (Windows) | Start → type `cmd` → Command Prompt. Not as administrator |
54
- | Git Bash (Windows) | Comes with Git for Windows. Start, or right-click a folder → *Open Git Bash here* |
55
- | WSL | Your distribution from Start, or `wsl` in PowerShell. Only if the AI tool runs inside WSL |
56
- | macOS | Applications → Utilities → Terminal, or iTerm2. zsh, bash and fish all work |
57
- | Linux | Any terminal in your desktop session, as your own user (not root) |
58
-
59
- ### 1. Node.js 20 or later
60
-
61
- ```sh
62
- node --version
63
- npm --version
64
- ```
65
-
66
- The first line must start with `v20` or higher. If not:
67
-
68
- | System | Install the LTS |
69
- | --- | --- |
70
- | Windows | `winget install OpenJS.NodeJS.LTS`, or the installer from nodejs.org. Then open a new terminal |
71
- | macOS | `brew install node`, or the installer from nodejs.org |
72
- | Linux, WSL | Many distributions ship old versions. Use [nvm](https://github.com/nvm-sh/nvm): run `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh \| bash`, open a new terminal, then `nvm install --lts`. Inside WSL, the Windows Node does not count |
73
-
74
- ### 2. Install the agent
75
-
76
- ```sh
77
- npm install -g @aaa-sentinel/ai-usage
78
- ```
79
-
80
- Check that the command exists:
81
-
82
- | Terminal | Command |
83
- | --- | --- |
84
- | PowerShell | `Get-Command sentinel-usage` |
85
- | CMD | `where sentinel-usage` |
86
- | Git Bash, WSL, macOS, Linux | `command -v sentinel-usage` |
87
-
88
- If it is not found, **close the terminal and open a new one** — the npm folder is added to `PATH`
89
- when the shell starts. If it is still missing:
90
-
91
- - **Windows**: the folder printed by `npm prefix -g` must be in your user `PATH` (Settings →
92
- System → About → Advanced system settings → Environment Variables).
93
- - **macOS, Linux, WSL**: add it to your shell, then open a new terminal.
94
-
95
- ```sh
96
- # bash / zsh (use ~/.zshrc on macOS)
97
- echo 'export PATH="$(npm prefix -g)/bin:$PATH"' >> ~/.bashrc
98
- # fish
99
- fish_add_path (npm prefix -g)/bin
100
- ```
101
-
102
- - **PowerShell says running scripts is disabled**: type `sentinel-usage.cmd` instead of
103
- `sentinel-usage` in every command. It behaves the same.
104
-
105
- Do not use `sudo` to install or to log in: the token and the automatic start would end up in the
106
- root account and would not see your usage.
107
-
108
- ### 3. The token
109
-
110
- Get it from whoever manages the organization, or, if you manage the connection: *AI connections →
111
- the connection's card → View connection → Usage agent → Enroll → Copy*. If a token already existed
112
- and you do not have it, choose **Rotate token**: the previous one stops working on every computer.
113
-
114
- Each token belongs to one connection — one person and one tool. Treat it like a password.
115
-
116
- ### 4. Connect this computer
117
-
118
- With the token copied to the clipboard, run the line for your terminal. The token is read from the
119
- clipboard, so it stays out of the shell history and out of any file.
120
-
121
- | Terminal | Command |
122
- | --- | --- |
123
- | PowerShell | `Get-Clipboard \| sentinel-usage login` |
124
- | CMD | `powershell -NoProfile -Command Get-Clipboard \| sentinel-usage login` |
125
- | Git Bash | `cat /dev/clipboard \| sentinel-usage login` |
126
- | WSL | `powershell.exe -NoProfile -Command Get-Clipboard \| sentinel-usage login` |
127
- | macOS | `pbpaste \| sentinel-usage login` |
128
- | Linux (Wayland) | `wl-paste \| sentinel-usage login` (needs `wl-clipboard`) |
129
- | Linux (X11) | `xclip -selection clipboard -o \| sentinel-usage login` (needs `xclip`) |
130
-
131
- Expected answer (the CLI prints its messages in Spanish):
132
-
133
- ```text
134
- Agente instalado. El arranque subirá el uso; no hace falta lanzarlo en cada sesión.
135
- ```
136
-
137
- `login` stores the token, installs the Cursor hook and schedules the automatic upload. If any step
138
- fails, nothing is left installed and you can run it again.
139
-
140
- **Without a clipboard** (for example over SSH), create `token.txt` in the current folder with the
141
- token as its only line, then:
142
-
143
- | Terminal | Commands |
144
- | --- | --- |
145
- | PowerShell | `Get-Content -Raw -Encoding utf8 token.txt \| sentinel-usage login` then `Remove-Item token.txt` |
146
- | CMD | `sentinel-usage login < token.txt` then `del token.txt` |
147
- | Git Bash, WSL, macOS, Linux | `sentinel-usage login < token.txt` then `rm token.txt` |
148
-
149
- - On Windows, Notepad adds `.txt` and File Explorer hides extensions, so the file may end up as
150
- `token.txt.txt`. Save it with the name `token` only, or check the real name with `dir`.
151
- - On macOS, TextEdit saves rich text by default: use *Format → Make Plain Text* before saving.
152
-
153
- The token is never accepted as an argument — it would stay in the shell history — and it is never
154
- read from the keyboard, so it is not echoed.
155
-
156
- ### 5. Check that it works
157
-
158
- Use the tool for a moment (one question is enough), then upload without waiting for the next hour:
159
-
160
- ```sh
161
- sentinel-usage report
162
- ```
163
-
164
- ```text
165
- Uso aceptado hasta 2026-10-16.
166
- ```
167
-
168
- `No hay uso nuevo que subir.` means you have not used the tool since `login`. Then:
169
-
170
- ```sh
171
- sentinel-usage status
172
- ```
173
-
174
- ```text
175
- agente: instalado
176
- arranque: sí
177
- herramienta: claude_code
178
- último día aceptado: 2026-10-16
179
- ```
180
-
181
- `herramienta` is the tool this connection reads: `cursor`, `claude_code`, `github_copilot` or
182
- `codex`. In AAA Sentinel the connection's card no longer says *Silent agent* and shows the last
183
- day, the turns and the tokens.
184
-
185
- ## Automatic start
186
-
187
- `login` schedules `sentinel-usage report` at sign-in and every hour while a session is open.
188
-
189
- | System | What is created |
190
- | --- | --- |
191
- | Windows | Two Task Scheduler tasks, `AAA Sentinel AI usage` and `AAA Sentinel AI usage logon`, for your user only, without administrator rights. They run while you are signed in |
192
- | macOS | A LaunchAgent, `com.aaa-sentinel.ai-usage`, in `~/Library/LaunchAgents`. Run `login` from the Terminal of your session, not over SSH |
193
- | Linux | A systemd user timer, `aaa-sentinel-ai-usage.timer`. Needs a session with a systemd user instance |
194
- | WSL | Same as Linux, and WSL needs systemd enabled (below). Runs while WSL is open |
195
-
196
- To enable systemd in WSL, add this to `/etc/wsl.conf` (with `sudo`) and run `wsl --shutdown` from
197
- PowerShell:
198
-
199
- ```ini
200
- [boot]
201
- systemd=true
202
- ```
203
-
204
- `sentinel-usage status` says `arranque: sí` when the automatic start is in place.
205
-
206
- ## Per tool
207
-
208
- - **Cursor.** `login` adds a hook to `~/.cursor/hooks.json` that writes one small file per turn to
209
- a local spool. If Cursor was open, quit it completely and reopen it. If the hook carries token
210
- counters they are reported per model; the stored input excludes cache, which is sent separately.
211
- If the counters are missing, the turn is counted and no token number is invented.
212
- - **Claude Code.** Nothing to configure. The usage counters of the session files in
213
- `~/.claude/projects` (or under `CLAUDE_CONFIG_DIR`) are read — Claude Code in the terminal, VS
214
- Code or JetBrains, as long as it runs on this computer with this user. If Claude Code runs in WSL,
215
- a dev container or a remote machine over SSH, install the agent there. A cost figure that
216
- sometimes comes with the session is not uploaded. A turn here is one call to the model, so a
217
- reply that uses tools counts several.
218
- - **GitHub Copilot.** Needs the [GitHub CLI](https://cli.github.com) signed in to the account that
219
- holds the Copilot plan: `gh auth login`, then `gh auth status` must show that account
220
- (`winget install GitHub.cli` on Windows, `brew install gh` on macOS). Premium requests by model
221
- are read through `gh`; GitHub does not report tokens. This is account usage, not device usage, so
222
- two laptops do not double it. If `gh` answers 401 or 403, an empty row is not written.
223
- - **Codex.** Session counters, only when Codex is signed in with the ChatGPT subscription
224
- (`codex login` → sign in with ChatGPT). If its auth file shows an API key, nothing is attributed
225
- to the individual account: that spend belongs to the organization connection.
226
-
227
- Each user on a computer reports **one** connection: a second `login` with another token replaces
228
- the first. Usage from before `login` is never uploaded.
229
-
230
- ## Reading the figures
231
-
232
- What the organization sees on the connection's card, for the plan's current renewal period:
233
-
234
- | Figure | Meaning |
235
- | --- | --- |
236
- | Turns | Calls to the model. Cursor: a chat or agent turn. Copilot: premium requests |
237
- | Input | New tokens sent to the model, **excluding cache** |
238
- | Cache read | Context the provider already had stored (open code, conversation, instructions) and the model reads again each turn. Usually the largest figure; each token costs a fraction of an input token |
239
- | Cache write | New context stored for later turns. Costs about the same as, or a little more than, input |
240
- | Output | What the model generates. The most expensive kind of token |
241
-
242
- Coding tools resend the same context every turn and the provider serves it from cache, so a
243
- working day can show a few thousand input tokens and millions read from cache. That is normal, not
244
- a measurement error. Add input, cache read and cache write to see how much text the model processed.
245
-
246
- *Silent agent* means the token exists but no usage arrived this period — not a zero. Usage arrives
247
- hourly while the person is signed in; if the computer was off, it arrives when it is switched on
248
- again. An Anthropic connection measures Claude Code, not the claude.ai chat; an OpenAI connection
249
- measures Codex, not the ChatGPT chat.
250
-
251
- ## Troubleshooting
252
-
253
- | You see | What to do |
254
- | --- | --- |
255
- | `sentinel-usage` not recognized / `command not found` | Open a new terminal. Then see step 2 about `PATH`. On Windows you can run the full path: the `npm prefix -g` folder plus `sentinel-usage.cmd` |
256
- | PowerShell: *running scripts is disabled* | Use `sentinel-usage.cmd`, or `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` if your company allows it |
257
- | PowerShell: *The '<' operator is reserved for future use* | PowerShell cannot redirect files with `<`; use the PowerShell line from step 4 |
258
- | `EACCES` from npm on macOS/Linux | Do not use `sudo`. Install Node with nvm, or `npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to `PATH`, install again |
259
- | `EBADENGINE`, or `SyntaxError` when running | Node is older than 20. Update it (step 1) |
260
- | *Redirige el token a la entrada estándar…* | `login` received no token. Use a full command from step 4 |
261
- | *El token no tiene el formato de un alta de uso.* | The clipboard or file does not hold just the token. Copy it again right before the command, or rotate a new one |
262
- | Windows: `token.txt` not found | It was saved as `token.txt.txt`. Check with `dir` |
263
- | Exit code `3` — *No se pudo registrar el arranque* | Windows: a company policy may block Task Scheduler, ask IT. macOS: run `login` in the Terminal of your session, not over SSH. Linux/WSL: no systemd user instance, see [Automatic start](#automatic-start). Nothing is left installed |
264
- | Exit code `4` — *El servidor no reconoce el token* | The token was rotated or the connection was revoked or removed. Get a new token and repeat step 4 |
265
- | *El uso de esta herramienta no corresponde a esta conexión…* | The token was enrolled for a different tool. Use the token of the connection that matches this machine's tool |
266
- | Exit code `5` | Copilot: install `gh` and `gh auth login` to the account that holds Copilot |
267
- | `sentinel-usage: fetch failed` | No route to `https://api.aaa-sentinel.com` on port 443: proxy or firewall. Ask IT. For npm behind a proxy: `npm config set proxy …` and `npm config set https-proxy …` |
268
- | The card stays on *Silent agent* | No usage this period yet. Use the tool, run `sentinel-usage report` and read its message |
269
-
270
- | Exit code | Meaning |
271
- | --- | --- |
272
- | `0` | Done, including "there is no new usage to upload" |
273
- | `1` | Unexpected error, usually the network |
274
- | `2` | Wrong usage: unknown command, malformed token, or a base URL that is not `https` |
275
- | `3` | The startup task could not be registered or removed |
276
- | `4` | The server did not accept a day, or no longer recognizes the token |
277
- | `5` | Copilot: `gh` is missing or lacks permission to read the usage |
278
-
279
- ## Update and remove
280
-
281
- ```sh
282
- npm install -g @aaa-sentinel/ai-usage@latest
283
- ```
284
-
285
- No need to log in again after an update. To remove the agent, **log out first**, then uninstall —
286
- otherwise the scheduled task keeps pointing to a program that no longer exists:
287
-
288
- ```sh
289
- sentinel-usage logout
290
- npm uninstall -g @aaa-sentinel/ai-usage
291
- ```
292
-
293
- Removing the agent does not delete usage already sent. If you switch Node versions with nvm, fnm or
294
- Volta, install the package in the new version and log in again with a rotated token: the automatic
295
- start uses the Node that `login` ran with.
296
-
297
- | Command | What it does |
298
- | --- | --- |
299
- | `sentinel-usage login` | Stores the token read from standard input, installs the Cursor hook and registers the startup task. If any step fails, nothing is left installed |
300
- | `sentinel-usage report` | Uploads the usage that is new since the last accepted day. Run by the startup task; safe to run by hand |
301
- | `sentinel-usage status` | Says whether the agent and the startup task are installed, which tool this connection reports, and the last accepted day. It does not print the token |
302
- | `sentinel-usage logout` | Removes the startup task, the Cursor hook and the token from this machine |
303
-
304
- ## Environment variables
305
-
306
- None is required. The automatic start only sees your permanent user variables on Windows; on
307
- macOS and Linux it does not read the variables of your shell.
308
-
309
- | Variable | Meaning |
310
- | --- | --- |
311
- | `SENTINEL_USAGE_BASE_URL` | Defaults to `https://api.aaa-sentinel.com`. Must be `https` — the token is never sent over plain HTTP |
312
- | `SENTINEL_USAGE_HOME` | Where the token, the state and the spool live. Defaults to `~/.config/aaa-sentinel` |
313
- | `SENTINEL_USAGE_CURSOR_HOOKS` | Path of Cursor's hooks file. Defaults to `~/.cursor/hooks.json` |
314
- | `SENTINEL_USAGE_CLAUDE_DIR` | Claude Code projects folder. Defaults to `projects` under `CLAUDE_CONFIG_DIR` or `~/.claude` |
315
- | `SENTINEL_USAGE_CODEX_HOME` | Codex folder. Defaults to `CODEX_HOME` or `~/.codex` |
316
-
317
- The token is stored in `usage.json` inside `SENTINEL_USAGE_HOME`. On macOS and Linux the file is
318
- readable only by your user (mode 600); on Windows it inherits the permissions of your profile
319
- folder.
320
-
321
- ## License
322
-
323
- MIT — see [LICENSE](LICENSE). The licence covers this client only; access to the API is governed by
324
- the terms of service at <https://app.aaa-sentinel.com>.
1
+ # @aaa-sentinel/ai-usage
2
+
3
+ Reports the usage of an **individual Cursor, Claude Code, GitHub Copilot or Codex seat** to
4
+ AAA Sentinel, so a personal subscription shows which models it is spent on instead of only a
5
+ plan percentage. The prompt, the code and the conversation stay on the laptop.
6
+
7
+ - [Who does what](#who-does-what)
8
+ - [What leaves your machine](#what-actually-leaves-your-machine)
9
+ - [Setup, step by step](#setup-step-by-step)
10
+ - [Automatic start](#automatic-start)
11
+ - [Per tool](#per-tool)
12
+ - [Reading the figures](#reading-the-figures)
13
+ - [Troubleshooting](#troubleshooting)
14
+ - [Update and remove](#update-and-remove)
15
+ - [Environment variables](#environment-variables)
16
+
17
+ ## Who does what
18
+
19
+ **The person who manages the organization** adds an individual AI connection in AAA Sentinel
20
+ (Cursor, Anthropic for Claude Code, Copilot, or OpenAI for Codex) with the email of the person who
21
+ uses the tool. In *View connection → Usage agent* they choose **Enroll** and **Copy**: the token is
22
+ shown only once. They send it through a private channel, such as a password manager or a direct
23
+ message deleted afterwards — never a team channel, a ticket or an email with others in copy.
24
+
25
+ **The person who uses the tool** follows the steps below on every computer where they use it, with
26
+ the same token. No administrator rights are needed. After step 5 there is nothing to start by hand.
27
+
28
+ If the account is yours, you do both parts.
29
+
30
+ ## What actually leaves your machine
31
+
32
+ One request per day of usage, with **the day, the model and the counters** — input, output,
33
+ cache-read and cache-write tokens, and the number of turns — plus a random identifier generated
34
+ on this machine that only tells two laptops apart. Each run also asks the server which tool the
35
+ connection is for; that request carries nothing but the token.
36
+
37
+ Not the prompt, not the code, not the conversation, not your email, not project names and not the
38
+ path of a transcript. The CLI reads only the tool its connection is for: a connection enrolled for
39
+ Cursor never opens a Claude Code transcript, and `gh` is not called unless the connection is
40
+ Copilot.
41
+
42
+ For quota headroom, a Claude Code connection also sends the day's peak share of the 5-hour and
43
+ weekly limits and the end time of any 5-hour window that reached 100 %; a Copilot connection sends
44
+ the month's total of AI credits, without amounts.
45
+
46
+ The CLI sends no money figures. AAA Sentinel shows what the usage would cost at API list prices,
47
+ always apart from billed or estimated spend and never added to them.
48
+
49
+ ## Setup, step by step
50
+
51
+ Pick the commands for the terminal you use. Install the agent **on the same system where the AI
52
+ tool runs**: if you open Cursor or Claude Code on Windows, use a Windows terminal even if you also
53
+ have WSL.
54
+
55
+ | Terminal | How to open it |
56
+ | --- | --- |
57
+ | PowerShell (Windows) | Start → type `PowerShell` → Windows PowerShell, PowerShell 7 or a PowerShell tab in Windows Terminal. Not as administrator |
58
+ | CMD (Windows) | Start → type `cmd` → Command Prompt. Not as administrator |
59
+ | Git Bash (Windows) | Comes with Git for Windows. Start, or right-click a folder → *Open Git Bash here* |
60
+ | WSL | Your distribution from Start, or `wsl` in PowerShell. Only if the AI tool runs inside WSL |
61
+ | macOS | Applications → Utilities → Terminal, or iTerm2. zsh, bash and fish all work |
62
+ | Linux | Any terminal in your desktop session, as your own user (not root) |
63
+
64
+ ### 1. Node.js 20 or later
65
+
66
+ ```sh
67
+ node --version
68
+ npm --version
69
+ ```
70
+
71
+ The first line must start with `v20` or higher. If not:
72
+
73
+ | System | Install the LTS |
74
+ | --- | --- |
75
+ | Windows | `winget install OpenJS.NodeJS.LTS`, or the installer from nodejs.org. Then open a new terminal |
76
+ | macOS | `brew install node`, or the installer from nodejs.org |
77
+ | Linux, WSL | Many distributions ship old versions. Use [nvm](https://github.com/nvm-sh/nvm): run `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh \| bash`, open a new terminal, then `nvm install --lts`. Inside WSL, the Windows Node does not count |
78
+
79
+ ### 2. Install the agent
80
+
81
+ ```sh
82
+ npm install -g @aaa-sentinel/ai-usage
83
+ ```
84
+
85
+ Check that the command exists:
86
+
87
+ | Terminal | Command |
88
+ | --- | --- |
89
+ | PowerShell | `Get-Command sentinel-usage` |
90
+ | CMD | `where sentinel-usage` |
91
+ | Git Bash, WSL, macOS, Linux | `command -v sentinel-usage` |
92
+
93
+ If it is not found, **close the terminal and open a new one** — the npm folder is added to `PATH`
94
+ when the shell starts. If it is still missing:
95
+
96
+ - **Windows**: the folder printed by `npm prefix -g` must be in your user `PATH` (Settings →
97
+ System → About → Advanced system settings → Environment Variables).
98
+ - **macOS, Linux, WSL**: add it to your shell, then open a new terminal.
99
+
100
+ ```sh
101
+ # bash / zsh (use ~/.zshrc on macOS)
102
+ echo 'export PATH="$(npm prefix -g)/bin:$PATH"' >> ~/.bashrc
103
+ # fish
104
+ fish_add_path (npm prefix -g)/bin
105
+ ```
106
+
107
+ - **PowerShell says running scripts is disabled**: type `sentinel-usage.cmd` instead of
108
+ `sentinel-usage` in every command. It behaves the same.
109
+
110
+ Do not use `sudo` to install or to log in: the token and the automatic start would end up in the
111
+ root account and would not see your usage.
112
+
113
+ ### 3. The token
114
+
115
+ Get it from whoever manages the organization, or, if you manage the connection: *AI connections →
116
+ the connection's card → View connection → Usage agent → Enroll → Copy*. If a token already existed
117
+ and you do not have it, choose **Rotate token**: the previous one stops working on every computer.
118
+
119
+ Each token belongs to one connection — one person and one tool. Treat it like a password.
120
+
121
+ ### 4. Connect this computer
122
+
123
+ With the token copied to the clipboard, run the line for your terminal. The token is read from the
124
+ clipboard, so it stays out of the shell history and out of any file.
125
+
126
+ | Terminal | Command |
127
+ | --- | --- |
128
+ | PowerShell | `Get-Clipboard \| sentinel-usage login` |
129
+ | CMD | `powershell -NoProfile -Command Get-Clipboard \| sentinel-usage login` |
130
+ | Git Bash | `cat /dev/clipboard \| sentinel-usage login` |
131
+ | WSL | `powershell.exe -NoProfile -Command Get-Clipboard \| sentinel-usage login` |
132
+ | macOS | `pbpaste \| sentinel-usage login` |
133
+ | Linux (Wayland) | `wl-paste \| sentinel-usage login` (needs `wl-clipboard`) |
134
+ | Linux (X11) | `xclip -selection clipboard -o \| sentinel-usage login` (needs `xclip`) |
135
+
136
+ Expected answer (the CLI prints its messages in Spanish):
137
+
138
+ ```text
139
+ Agente instalado. El arranque subirá el uso; no hace falta lanzarlo en cada sesión.
140
+ ```
141
+
142
+ `login` stores the token, installs the Cursor hook and schedules the automatic upload. If any step
143
+ fails, nothing is left installed and you can run it again.
144
+
145
+ **Without a clipboard** (for example over SSH), create `token.txt` in the current folder with the
146
+ token as its only line, then:
147
+
148
+ | Terminal | Commands |
149
+ | --- | --- |
150
+ | PowerShell | `Get-Content -Raw -Encoding utf8 token.txt \| sentinel-usage login` then `Remove-Item token.txt` |
151
+ | CMD | `sentinel-usage login < token.txt` then `del token.txt` |
152
+ | Git Bash, WSL, macOS, Linux | `sentinel-usage login < token.txt` then `rm token.txt` |
153
+
154
+ - On Windows, Notepad adds `.txt` and File Explorer hides extensions, so the file may end up as
155
+ `token.txt.txt`. Save it with the name `token` only, or check the real name with `dir`.
156
+ - On macOS, TextEdit saves rich text by default: use *Format → Make Plain Text* before saving.
157
+
158
+ The token is never accepted as an argument — it would stay in the shell history — and it is never
159
+ read from the keyboard, so it is not echoed.
160
+
161
+ ### 5. Check that it works
162
+
163
+ Use the tool for a moment (one question is enough), then upload without waiting for the next hour:
164
+
165
+ ```sh
166
+ sentinel-usage report
167
+ ```
168
+
169
+ ```text
170
+ Uso aceptado hasta 2026-10-16.
171
+ ```
172
+
173
+ `No hay uso nuevo que subir.` means you have not used the tool since `login`. Then:
174
+
175
+ ```sh
176
+ sentinel-usage status
177
+ ```
178
+
179
+ ```text
180
+ agente: instalado
181
+ arranque: sí
182
+ herramienta: claude_code
183
+ último día aceptado: 2026-10-16
184
+ ```
185
+
186
+ `herramienta` is the tool this connection reads: `cursor`, `claude_code`, `github_copilot` or
187
+ `codex`. In AAA Sentinel the connection's card no longer says *Silent agent* and shows the last
188
+ day, the turns and the tokens.
189
+
190
+ ## Automatic start
191
+
192
+ `login` schedules `sentinel-usage report` at sign-in and every hour while a session is open.
193
+
194
+ | System | What is created |
195
+ | --- | --- |
196
+ | Windows | Two Task Scheduler tasks, `AAA Sentinel AI usage` and `AAA Sentinel AI usage logon`, for your user only, without administrator rights. They run while you are signed in |
197
+ | macOS | A LaunchAgent, `com.aaa-sentinel.ai-usage`, in `~/Library/LaunchAgents`. Run `login` from the Terminal of your session, not over SSH |
198
+ | Linux | A systemd user timer, `aaa-sentinel-ai-usage.timer`. Needs a session with a systemd user instance |
199
+ | WSL | Same as Linux, and WSL needs systemd enabled (below). Runs while WSL is open |
200
+
201
+ To enable systemd in WSL, add this to `/etc/wsl.conf` (with `sudo`) and run `wsl --shutdown` from
202
+ PowerShell:
203
+
204
+ ```ini
205
+ [boot]
206
+ systemd=true
207
+ ```
208
+
209
+ `sentinel-usage status` says `arranque: sí` when the automatic start is in place.
210
+
211
+ ## Per tool
212
+
213
+ - **Cursor.** `login` adds a hook to `~/.cursor/hooks.json` that writes one small file per turn to
214
+ a local spool. If Cursor was open, quit it completely and reopen it. If the hook carries token
215
+ counters they are reported per model; the stored input excludes cache, which is sent separately.
216
+ If the counters are missing, the turn is counted and no token number is invented.
217
+ - **Claude Code.** Nothing to configure. The usage counters of the session files in
218
+ `~/.claude/projects` (or under `CLAUDE_CONFIG_DIR`) are read — Claude Code in the terminal, VS
219
+ Code or JetBrains, as long as it runs on this computer with this user. If Claude Code runs in WSL,
220
+ a dev container or a remote machine over SSH, install the agent there. A cost figure that
221
+ sometimes comes with the session is not uploaded. A turn here is one call to the model, so a
222
+ reply that uses tools counts several.
223
+ Claude Code passes its 5-hour and weekly limits only to the status line, so the first `report`
224
+ sets `sentinel-usage statusline` as the status line in Claude Code's `settings.json`. If you
225
+ already had one, it keeps running and is what you see; if not, you see the 5-hour and weekly
226
+ usage. Remove or change it and the agent does not put it back; `logout` restores yours.
227
+ - **GitHub Copilot.** Needs the [GitHub CLI](https://cli.github.com) signed in to the account that
228
+ holds the Copilot plan: `gh auth login`, then `gh auth status` must show that account
229
+ (`winget install GitHub.cli` on Windows, `brew install gh` on macOS). Premium requests by model
230
+ are read through `gh`; GitHub does not report tokens. This is account usage, not device usage, so
231
+ two laptops do not double it. If `gh` answers 401 or 403, an empty row is not written. The
232
+ month's AI credits are read the same way and only their total is sent, to compare with the
233
+ credits the plan includes.
234
+ - **Codex.** Session counters, only when Codex is signed in with the ChatGPT subscription
235
+ (`codex login` → sign in with ChatGPT). If its auth file shows an API key, nothing is attributed
236
+ to the individual account: that spend belongs to the organization connection.
237
+
238
+ Each user on a computer can report **one connection per tool**: run `login` once with each token,
239
+ for example the Claude Code one and the Cursor one, and both report. A second token for the same
240
+ tool replaces the first, because the local usage of a tool does not say which account it came from.
241
+ Usage from before `login` is never uploaded.
242
+
243
+ ## Reading the figures
244
+
245
+ What the organization sees on the connection's card, for the plan's current renewal period:
246
+
247
+ | Figure | Meaning |
248
+ | --- | --- |
249
+ | Turns | Calls to the model. Cursor: a chat or agent turn. Copilot: premium requests |
250
+ | Input | New tokens sent to the model, **excluding cache** |
251
+ | Cache read | Context the provider already had stored (open code, conversation, instructions) and the model reads again each turn. Usually the largest figure; each token costs a fraction of an input token |
252
+ | Cache write | New context stored for later turns. Costs about the same as, or a little more than, input |
253
+ | Output | What the model generates. The most expensive kind of token |
254
+
255
+ Coding tools resend the same context every turn and the provider serves it from cache, so a
256
+ working day can show a few thousand input tokens and millions read from cache. That is normal, not
257
+ a measurement error. Add input, cache read and cache write to see how much text the model processed.
258
+
259
+ *Silent agent* means the token exists but no usage arrived this period — not a zero. Usage arrives
260
+ hourly while the person is signed in; if the computer was off, it arrives when it is switched on
261
+ again. An Anthropic connection measures Claude Code, not the claude.ai chat; an OpenAI connection
262
+ measures Codex, not the ChatGPT chat.
263
+
264
+ ## Troubleshooting
265
+
266
+ | You see | What to do |
267
+ | --- | --- |
268
+ | `sentinel-usage` not recognized / `command not found` | Open a new terminal. Then see step 2 about `PATH`. On Windows you can run the full path: the `npm prefix -g` folder plus `sentinel-usage.cmd` |
269
+ | PowerShell: *running scripts is disabled* | Use `sentinel-usage.cmd`, or `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` if your company allows it |
270
+ | PowerShell: *The '<' operator is reserved for future use* | PowerShell cannot redirect files with `<`; use the PowerShell line from step 4 |
271
+ | `EACCES` from npm on macOS/Linux | Do not use `sudo`. Install Node with nvm, or `npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to `PATH`, install again |
272
+ | `EBADENGINE`, or `SyntaxError` when running | Node is older than 20. Update it (step 1) |
273
+ | *Redirige el token a la entrada estándar…* | `login` received no token. Use a full command from step 4 |
274
+ | *El token no tiene el formato de un alta de uso.* | The clipboard or file does not hold just the token. Copy it again right before the command, or rotate a new one |
275
+ | Windows: `token.txt` not found | It was saved as `token.txt.txt`. Check with `dir` |
276
+ | Exit code `3` — *No se pudo registrar el arranque* | Windows: a company policy may block Task Scheduler, ask IT. macOS: run `login` in the Terminal of your session, not over SSH. Linux/WSL: no systemd user instance, see [Automatic start](#automatic-start). Nothing is left installed |
277
+ | Exit code `4` — *El servidor no reconoce el token* | The token was rotated or the connection was revoked or removed. Get a new token and repeat step 4 |
278
+ | *El uso de esta herramienta no corresponde a esta conexión…* | The token was enrolled for a different tool. Use the token of the connection that matches this machine's tool |
279
+ | Exit code `5` | Copilot: install `gh` and `gh auth login` to the account that holds Copilot |
280
+ | `sentinel-usage: fetch failed` | No route to `https://api.aaa-sentinel.com` on port 443: proxy or firewall. Ask IT. For npm behind a proxy: `npm config set proxy …` and `npm config set https-proxy …` |
281
+ | The card stays on *Silent agent* | No usage this period yet. Use the tool, run `sentinel-usage report` and read its message |
282
+
283
+ | Exit code | Meaning |
284
+ | --- | --- |
285
+ | `0` | Done, including "there is no new usage to upload" |
286
+ | `1` | Unexpected error, usually the network |
287
+ | `2` | Wrong usage: unknown command, malformed token, or a base URL that is not `https` |
288
+ | `3` | The startup task could not be registered or removed |
289
+ | `4` | The server did not accept a day, or no longer recognizes the token |
290
+ | `5` | Copilot: `gh` is missing or lacks permission to read the usage |
291
+
292
+ ## Update and remove
293
+
294
+ ```sh
295
+ npm install -g @aaa-sentinel/ai-usage@latest
296
+ ```
297
+
298
+ No need to log in again after an update. To remove the agent, **log out first**, then uninstall —
299
+ otherwise the scheduled task keeps pointing to a program that no longer exists:
300
+
301
+ ```sh
302
+ sentinel-usage logout
303
+ npm uninstall -g @aaa-sentinel/ai-usage
304
+ ```
305
+
306
+ Removing the agent does not delete usage already sent. If you switch Node versions with nvm, fnm or
307
+ Volta, install the package in the new version and log in again with a rotated token: the automatic
308
+ start uses the Node that `login` ran with.
309
+
310
+ | Command | What it does |
311
+ | --- | --- |
312
+ | `sentinel-usage login` | Adds the token read from standard input, installs the Cursor hook and registers the startup task. A token for a tool already reported replaces it. If any step fails, nothing is left installed |
313
+ | `sentinel-usage report` | Uploads, for each connection, the usage that is new since its last accepted day. Run by the startup task; safe to run by hand |
314
+ | `sentinel-usage status` | Says whether the agent and the startup task are installed and, for each connection, which tool it reports and its last accepted day. It does not print tokens |
315
+ | `sentinel-usage logout` | Removes every connection, the startup task, the Cursor hook and the status line from this machine |
316
+ | `sentinel-usage logout cursor` | Removes only that tool (`cursor`, `claude_code`, `github_copilot` or `codex`); the others keep reporting |
317
+
318
+ ## Environment variables
319
+
320
+ None is required. The automatic start only sees your permanent user variables on Windows; on
321
+ macOS and Linux it does not read the variables of your shell.
322
+
323
+ | Variable | Meaning |
324
+ | --- | --- |
325
+ | `SENTINEL_USAGE_BASE_URL` | Defaults to `https://api.aaa-sentinel.com`. Must be `https` — the token is never sent over plain HTTP |
326
+ | `SENTINEL_USAGE_HOME` | Where the token, the state and the spool live. Defaults to `~/.config/aaa-sentinel` |
327
+ | `SENTINEL_USAGE_CURSOR_HOOKS` | Path of Cursor's hooks file. Defaults to `~/.cursor/hooks.json` |
328
+ | `SENTINEL_USAGE_CLAUDE_DIR` | Claude Code projects folder. Defaults to `projects` under `CLAUDE_CONFIG_DIR` or `~/.claude` |
329
+ | `SENTINEL_USAGE_CODEX_HOME` | Codex folder. Defaults to `CODEX_HOME` or `~/.codex` |
330
+ | `SENTINEL_USAGE_NO_STATUSLINE` | With `1`, the Claude Code status line is not set and its quota headroom is not measured |
331
+
332
+ The token is stored in `usage.json` inside `SENTINEL_USAGE_HOME`. On macOS and Linux the file is
333
+ readable only by your user (mode 600); on Windows it inherits the permissions of your profile
334
+ folder.
335
+
336
+ ## License
337
+
338
+ MIT — see [LICENSE](LICENSE). The licence covers this client only; access to the API is governed by
339
+ the terms of service at <https://app.aaa-sentinel.com>.