cc-cockpit 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wallace Martins da Silva
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.
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.4
2
+ Name: cc-cockpit
3
+ Version: 0.2.0
4
+ Summary: Claude Code usage panel for GNOME: tray indicator, local dashboard and terminal summary
5
+ Author: Wallace Martins da Silva
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/wallacemartinss/cc-cockpit
8
+ Project-URL: Issues, https://github.com/wallacemartinss/cc-cockpit/issues
9
+ Keywords: claude,claude-code,usage,gnome,tray,appindicator
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: X11 Applications :: GTK
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Provides-Extra: tray
20
+ Requires-Dist: PyGObject>=3.42; extra == "tray"
21
+ Requires-Dist: pycairo>=1.20; extra == "tray"
22
+ Dynamic: license-file
23
+
24
+ # cc-cockpit
25
+
26
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
27
+
28
+ A Claude Code usage panel for GNOME: a tray indicator with a consumption ring,
29
+ a local dashboard and a terminal summary.
30
+
31
+ Everything is read from what Claude Code already writes under `~/.claude`. It
32
+ makes no network calls, reads no credentials and sends nothing anywhere.
33
+
34
+ The interface follows your OS language — English, Portuguese and Spanish are
35
+ bundled — and can be pinned in the config file or with `--lang`.
36
+
37
+ ## What it shows
38
+
39
+ | | |
40
+ |---|---|
41
+ | **5h block** | how much the current rate-limit window has consumed, time to reset, hourly pace, projection to the end of the block, and how long until the reference ceiling. The window starts at the exact timestamp of its first request — not rounded to the hour — which is what makes the reset match what the CLI reports |
42
+ | **7 days / today / month** | rolling totals, as a percentage of your own historical peak |
43
+ | **Open sessions** | every live CLI instance: name, project, `busy`/`idle`, uptime, RAM, pid, and what that session has consumed |
44
+ | **Projects** | ranked by consumption across the whole history |
45
+ | **Blocks, days and hours** | time series showing when you actually spend |
46
+ | **Token mix** | input / output / cache write 5m / cache write 1h / cache read, with the cache hit rate |
47
+ | **Models, effort and subagents** | where the consumption really goes |
48
+
49
+ Usage is measured in **API-equivalent USD**: what those messages would cost on
50
+ the pay-as-you-go API. On a Pro/Max plan none of it is billed — the number works
51
+ as a weight unit for consumption and shows how much the plan returns.
52
+
53
+ ## Install
54
+
55
+ **Debian / Ubuntu** — the `.deb` pulls in the GTK dependencies by itself:
56
+
57
+ ```bash
58
+ # from the latest release
59
+ sudo apt install ./cc-cockpit_0.2.0_all.deb
60
+ cc-cockpit setup
61
+ ```
62
+
63
+ **Arch** — from the AUR:
64
+
65
+ ```bash
66
+ yay -S cc-cockpit # or: makepkg -si from packaging/PKGBUILD
67
+ cc-cockpit setup
68
+ ```
69
+
70
+ **Any distribution** — pipx, reusing the system GTK bindings:
71
+
72
+ ```bash
73
+ sudo apt install python3-gi python3-cairo gir1.2-ayatanaappindicator3-0.1 # tray only
74
+ pipx install cc-cockpit --system-site-packages
75
+ cc-cockpit setup
76
+ ```
77
+
78
+ `--system-site-packages` is what lets the virtualenv see PyGObject and pycairo.
79
+ Without them the tray is unavailable, and the dashboard and `report` still work.
80
+
81
+ **From a checkout**:
82
+
83
+ ```bash
84
+ git clone https://github.com/wallacemartinss/cc-cockpit
85
+ cd cc-cockpit && ./install.sh
86
+ ```
87
+
88
+ `cc-cockpit setup` registers the GNOME autostart entry, captures the statusline
89
+ (see below), checks the tray dependencies and runs the first collection.
90
+ `cc-cockpit setup --remove` undoes the autostart entry.
91
+
92
+ ```bash
93
+ cc-cockpit # tray + dashboard in the background
94
+ cc-cockpit report # terminal summary
95
+ cc-cockpit serve --open # dashboard only (http://127.0.0.1:8765)
96
+ cc-cockpit json # everything as JSON, for scripting
97
+ cc-cockpit collect # ingest new transcripts and exit
98
+ cc-cockpit config # config path and contents
99
+ cc-cockpit --lang es report
100
+ ```
101
+
102
+ ## The real numbers, from the statusline
103
+
104
+ Two things cannot be derived from local transcripts:
105
+
106
+ 1. **The limit belongs to the account, not to the CLI.** Whatever you consume in
107
+ the Claude app counts against the same window and leaves nothing on disk, so
108
+ a window can start before your first local request.
109
+ 2. **The weekly limit is a fixed window** with its own reset time, not the
110
+ rolling 7 days a local reader would assume.
111
+
112
+ Claude Code pipes a JSON payload into the statusline command on every render,
113
+ and it carries exactly what the plan panel shows:
114
+
115
+ ```json
116
+ "rate_limits": {
117
+ "five_hour": {"used_percentage": 23, "resets_at": 1788800000},
118
+ "seven_day": {"used_percentage": 3, "resets_at": 1788790000}
119
+ }
120
+ ```
121
+
122
+ Register the capture once — no credentials, no undocumented endpoint:
123
+
124
+ ```bash
125
+ cc-cockpit statusline --install
126
+ ```
127
+
128
+ It writes `statusLine` into `~/.claude/settings.json`, keeping a `.bak`. If you
129
+ already had one, it is chained rather than replaced, so its output still shows
130
+ in the CLI. The captured payload also carries the **context window percentage
131
+ per session**, which the dashboard shows next to each open session.
132
+
133
+ From then on the official percentage is the source of truth, and it reveals the
134
+ real ceiling — `local consumption ÷ official percentage` — so the currency
135
+ figures stay meaningful too.
136
+
137
+ ### When there is no statusline data yet
138
+
139
+ Numbers fall back, in order of trust: **official** (statusline) → **anchored**
140
+ (what you typed) → **local estimate**. The middle one exists because a fresh
141
+ install has no capture yet:
142
+
143
+ ```bash
144
+ cc-cockpit sync --block 23% --block-reset 1h55 --week 3% --week-reset 1h15
145
+ cc-cockpit sync # show anchors, samples and implied ceilings
146
+ cc-cockpit sync --reset
147
+ ```
148
+
149
+ Both the tray and the dashboard say which source is in use.
150
+
151
+ ## How it works
152
+
153
+ ```
154
+ ~/.claude/projects/**/*.jsonl transcripts (usage per request)
155
+ ~/.claude/sessions/*.json one entry per live CLI ─┐
156
+ statusline payload (stdin) official rate limits + context ├─> cockpit/
157
+ ~/.local/share/cc-cockpit/events.ndjson <───────────────┘
158
+ ~/.local/share/cc-cockpit/panel.json official snapshot
159
+ ```
160
+
161
+ - `collector.py` reads each transcript **from the last offset**, so a refresh
162
+ costs ~30 ms even with 190 MB of history.
163
+ - Events land in a dedicated NDJSON file. That matters: Claude Code **prunes
164
+ transcripts after ~30 days**, and from the first collection onward cc-cockpit
165
+ keeps the full history.
166
+ - Deduplication by `message.id:requestId`, so resuming a session is not counted
167
+ twice.
168
+ - `sessions.py` validates each pid against `/proc` **and** compares the
169
+ `starttime`, so a recycled pid is never mistaken for a live session.
170
+ - Prices live in `pricing.py`: cache writes at 1.25× (5m) and 2× (1h) of input,
171
+ cache reads at 0.1× (0.025× on Fable 5.1). The transcript separates the two
172
+ cache-write TTLs and the calculation uses that split instead of assuming 5m.
173
+ - `i18n.py` holds one catalogue for all three surfaces, plus locale-aware number
174
+ and currency formatting.
175
+ - `panel.py` keeps the official snapshot and appends a line to
176
+ `panel-history.ndjson` whenever the percentage changes.
177
+
178
+ ## Honest limitations
179
+
180
+ - Without the statusline capture and without `limits`, the percentage is
181
+ relative to your own history, not to the real plan limit.
182
+ - The statusline only refreshes while a CLI session is rendering. That is
183
+ enough — what is not running cannot be consuming — but right after a long
184
+ gap the percentage may lag until the next render.
185
+ - Consumption from the Claude app shows up in the official percentage, never in
186
+ the local currency figures, which read Claude Code transcripts only.
187
+ - Models released after this version fall back to their family price (`opus`,
188
+ `sonnet`, `haiku`, `fable`) until they are added to `pricing.py`.
189
+ - `<synthetic>` rows are responses the CLI generates locally: they show up in
190
+ the request count and cost nothing.
191
+
192
+ ## Packaging
193
+
194
+ `packaging/` holds the `.deb` build script and the Arch `PKGBUILD`; see
195
+ [packaging/README.md](packaging/README.md) for the release flow. A `v*` tag
196
+ builds the wheel, the sdist and the `.deb`, publishes to PyPI and attaches
197
+ everything to the GitHub release.
198
+
199
+ ## License
200
+
201
+ MIT — see [LICENSE](LICENSE).
202
+
203
+ Not affiliated with Anthropic.
@@ -0,0 +1,180 @@
1
+ # cc-cockpit
2
+
3
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
4
+
5
+ A Claude Code usage panel for GNOME: a tray indicator with a consumption ring,
6
+ a local dashboard and a terminal summary.
7
+
8
+ Everything is read from what Claude Code already writes under `~/.claude`. It
9
+ makes no network calls, reads no credentials and sends nothing anywhere.
10
+
11
+ The interface follows your OS language — English, Portuguese and Spanish are
12
+ bundled — and can be pinned in the config file or with `--lang`.
13
+
14
+ ## What it shows
15
+
16
+ | | |
17
+ |---|---|
18
+ | **5h block** | how much the current rate-limit window has consumed, time to reset, hourly pace, projection to the end of the block, and how long until the reference ceiling. The window starts at the exact timestamp of its first request — not rounded to the hour — which is what makes the reset match what the CLI reports |
19
+ | **7 days / today / month** | rolling totals, as a percentage of your own historical peak |
20
+ | **Open sessions** | every live CLI instance: name, project, `busy`/`idle`, uptime, RAM, pid, and what that session has consumed |
21
+ | **Projects** | ranked by consumption across the whole history |
22
+ | **Blocks, days and hours** | time series showing when you actually spend |
23
+ | **Token mix** | input / output / cache write 5m / cache write 1h / cache read, with the cache hit rate |
24
+ | **Models, effort and subagents** | where the consumption really goes |
25
+
26
+ Usage is measured in **API-equivalent USD**: what those messages would cost on
27
+ the pay-as-you-go API. On a Pro/Max plan none of it is billed — the number works
28
+ as a weight unit for consumption and shows how much the plan returns.
29
+
30
+ ## Install
31
+
32
+ **Debian / Ubuntu** — the `.deb` pulls in the GTK dependencies by itself:
33
+
34
+ ```bash
35
+ # from the latest release
36
+ sudo apt install ./cc-cockpit_0.2.0_all.deb
37
+ cc-cockpit setup
38
+ ```
39
+
40
+ **Arch** — from the AUR:
41
+
42
+ ```bash
43
+ yay -S cc-cockpit # or: makepkg -si from packaging/PKGBUILD
44
+ cc-cockpit setup
45
+ ```
46
+
47
+ **Any distribution** — pipx, reusing the system GTK bindings:
48
+
49
+ ```bash
50
+ sudo apt install python3-gi python3-cairo gir1.2-ayatanaappindicator3-0.1 # tray only
51
+ pipx install cc-cockpit --system-site-packages
52
+ cc-cockpit setup
53
+ ```
54
+
55
+ `--system-site-packages` is what lets the virtualenv see PyGObject and pycairo.
56
+ Without them the tray is unavailable, and the dashboard and `report` still work.
57
+
58
+ **From a checkout**:
59
+
60
+ ```bash
61
+ git clone https://github.com/wallacemartinss/cc-cockpit
62
+ cd cc-cockpit && ./install.sh
63
+ ```
64
+
65
+ `cc-cockpit setup` registers the GNOME autostart entry, captures the statusline
66
+ (see below), checks the tray dependencies and runs the first collection.
67
+ `cc-cockpit setup --remove` undoes the autostart entry.
68
+
69
+ ```bash
70
+ cc-cockpit # tray + dashboard in the background
71
+ cc-cockpit report # terminal summary
72
+ cc-cockpit serve --open # dashboard only (http://127.0.0.1:8765)
73
+ cc-cockpit json # everything as JSON, for scripting
74
+ cc-cockpit collect # ingest new transcripts and exit
75
+ cc-cockpit config # config path and contents
76
+ cc-cockpit --lang es report
77
+ ```
78
+
79
+ ## The real numbers, from the statusline
80
+
81
+ Two things cannot be derived from local transcripts:
82
+
83
+ 1. **The limit belongs to the account, not to the CLI.** Whatever you consume in
84
+ the Claude app counts against the same window and leaves nothing on disk, so
85
+ a window can start before your first local request.
86
+ 2. **The weekly limit is a fixed window** with its own reset time, not the
87
+ rolling 7 days a local reader would assume.
88
+
89
+ Claude Code pipes a JSON payload into the statusline command on every render,
90
+ and it carries exactly what the plan panel shows:
91
+
92
+ ```json
93
+ "rate_limits": {
94
+ "five_hour": {"used_percentage": 23, "resets_at": 1788800000},
95
+ "seven_day": {"used_percentage": 3, "resets_at": 1788790000}
96
+ }
97
+ ```
98
+
99
+ Register the capture once — no credentials, no undocumented endpoint:
100
+
101
+ ```bash
102
+ cc-cockpit statusline --install
103
+ ```
104
+
105
+ It writes `statusLine` into `~/.claude/settings.json`, keeping a `.bak`. If you
106
+ already had one, it is chained rather than replaced, so its output still shows
107
+ in the CLI. The captured payload also carries the **context window percentage
108
+ per session**, which the dashboard shows next to each open session.
109
+
110
+ From then on the official percentage is the source of truth, and it reveals the
111
+ real ceiling — `local consumption ÷ official percentage` — so the currency
112
+ figures stay meaningful too.
113
+
114
+ ### When there is no statusline data yet
115
+
116
+ Numbers fall back, in order of trust: **official** (statusline) → **anchored**
117
+ (what you typed) → **local estimate**. The middle one exists because a fresh
118
+ install has no capture yet:
119
+
120
+ ```bash
121
+ cc-cockpit sync --block 23% --block-reset 1h55 --week 3% --week-reset 1h15
122
+ cc-cockpit sync # show anchors, samples and implied ceilings
123
+ cc-cockpit sync --reset
124
+ ```
125
+
126
+ Both the tray and the dashboard say which source is in use.
127
+
128
+ ## How it works
129
+
130
+ ```
131
+ ~/.claude/projects/**/*.jsonl transcripts (usage per request)
132
+ ~/.claude/sessions/*.json one entry per live CLI ─┐
133
+ statusline payload (stdin) official rate limits + context ├─> cockpit/
134
+ ~/.local/share/cc-cockpit/events.ndjson <───────────────┘
135
+ ~/.local/share/cc-cockpit/panel.json official snapshot
136
+ ```
137
+
138
+ - `collector.py` reads each transcript **from the last offset**, so a refresh
139
+ costs ~30 ms even with 190 MB of history.
140
+ - Events land in a dedicated NDJSON file. That matters: Claude Code **prunes
141
+ transcripts after ~30 days**, and from the first collection onward cc-cockpit
142
+ keeps the full history.
143
+ - Deduplication by `message.id:requestId`, so resuming a session is not counted
144
+ twice.
145
+ - `sessions.py` validates each pid against `/proc` **and** compares the
146
+ `starttime`, so a recycled pid is never mistaken for a live session.
147
+ - Prices live in `pricing.py`: cache writes at 1.25× (5m) and 2× (1h) of input,
148
+ cache reads at 0.1× (0.025× on Fable 5.1). The transcript separates the two
149
+ cache-write TTLs and the calculation uses that split instead of assuming 5m.
150
+ - `i18n.py` holds one catalogue for all three surfaces, plus locale-aware number
151
+ and currency formatting.
152
+ - `panel.py` keeps the official snapshot and appends a line to
153
+ `panel-history.ndjson` whenever the percentage changes.
154
+
155
+ ## Honest limitations
156
+
157
+ - Without the statusline capture and without `limits`, the percentage is
158
+ relative to your own history, not to the real plan limit.
159
+ - The statusline only refreshes while a CLI session is rendering. That is
160
+ enough — what is not running cannot be consuming — but right after a long
161
+ gap the percentage may lag until the next render.
162
+ - Consumption from the Claude app shows up in the official percentage, never in
163
+ the local currency figures, which read Claude Code transcripts only.
164
+ - Models released after this version fall back to their family price (`opus`,
165
+ `sonnet`, `haiku`, `fable`) until they are added to `pricing.py`.
166
+ - `<synthetic>` rows are responses the CLI generates locally: they show up in
167
+ the request count and cost nothing.
168
+
169
+ ## Packaging
170
+
171
+ `packaging/` holds the `.deb` build script and the Arch `PKGBUILD`; see
172
+ [packaging/README.md](packaging/README.md) for the release flow. A `v*` tag
173
+ builds the wheel, the sdist and the `.deb`, publishes to PyPI and attaches
174
+ everything to the GitHub release.
175
+
176
+ ## License
177
+
178
+ MIT — see [LICENSE](LICENSE).
179
+
180
+ Not affiliated with Anthropic.
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.4
2
+ Name: cc-cockpit
3
+ Version: 0.2.0
4
+ Summary: Claude Code usage panel for GNOME: tray indicator, local dashboard and terminal summary
5
+ Author: Wallace Martins da Silva
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/wallacemartinss/cc-cockpit
8
+ Project-URL: Issues, https://github.com/wallacemartinss/cc-cockpit/issues
9
+ Keywords: claude,claude-code,usage,gnome,tray,appindicator
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: X11 Applications :: GTK
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Provides-Extra: tray
20
+ Requires-Dist: PyGObject>=3.42; extra == "tray"
21
+ Requires-Dist: pycairo>=1.20; extra == "tray"
22
+ Dynamic: license-file
23
+
24
+ # cc-cockpit
25
+
26
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
27
+
28
+ A Claude Code usage panel for GNOME: a tray indicator with a consumption ring,
29
+ a local dashboard and a terminal summary.
30
+
31
+ Everything is read from what Claude Code already writes under `~/.claude`. It
32
+ makes no network calls, reads no credentials and sends nothing anywhere.
33
+
34
+ The interface follows your OS language — English, Portuguese and Spanish are
35
+ bundled — and can be pinned in the config file or with `--lang`.
36
+
37
+ ## What it shows
38
+
39
+ | | |
40
+ |---|---|
41
+ | **5h block** | how much the current rate-limit window has consumed, time to reset, hourly pace, projection to the end of the block, and how long until the reference ceiling. The window starts at the exact timestamp of its first request — not rounded to the hour — which is what makes the reset match what the CLI reports |
42
+ | **7 days / today / month** | rolling totals, as a percentage of your own historical peak |
43
+ | **Open sessions** | every live CLI instance: name, project, `busy`/`idle`, uptime, RAM, pid, and what that session has consumed |
44
+ | **Projects** | ranked by consumption across the whole history |
45
+ | **Blocks, days and hours** | time series showing when you actually spend |
46
+ | **Token mix** | input / output / cache write 5m / cache write 1h / cache read, with the cache hit rate |
47
+ | **Models, effort and subagents** | where the consumption really goes |
48
+
49
+ Usage is measured in **API-equivalent USD**: what those messages would cost on
50
+ the pay-as-you-go API. On a Pro/Max plan none of it is billed — the number works
51
+ as a weight unit for consumption and shows how much the plan returns.
52
+
53
+ ## Install
54
+
55
+ **Debian / Ubuntu** — the `.deb` pulls in the GTK dependencies by itself:
56
+
57
+ ```bash
58
+ # from the latest release
59
+ sudo apt install ./cc-cockpit_0.2.0_all.deb
60
+ cc-cockpit setup
61
+ ```
62
+
63
+ **Arch** — from the AUR:
64
+
65
+ ```bash
66
+ yay -S cc-cockpit # or: makepkg -si from packaging/PKGBUILD
67
+ cc-cockpit setup
68
+ ```
69
+
70
+ **Any distribution** — pipx, reusing the system GTK bindings:
71
+
72
+ ```bash
73
+ sudo apt install python3-gi python3-cairo gir1.2-ayatanaappindicator3-0.1 # tray only
74
+ pipx install cc-cockpit --system-site-packages
75
+ cc-cockpit setup
76
+ ```
77
+
78
+ `--system-site-packages` is what lets the virtualenv see PyGObject and pycairo.
79
+ Without them the tray is unavailable, and the dashboard and `report` still work.
80
+
81
+ **From a checkout**:
82
+
83
+ ```bash
84
+ git clone https://github.com/wallacemartinss/cc-cockpit
85
+ cd cc-cockpit && ./install.sh
86
+ ```
87
+
88
+ `cc-cockpit setup` registers the GNOME autostart entry, captures the statusline
89
+ (see below), checks the tray dependencies and runs the first collection.
90
+ `cc-cockpit setup --remove` undoes the autostart entry.
91
+
92
+ ```bash
93
+ cc-cockpit # tray + dashboard in the background
94
+ cc-cockpit report # terminal summary
95
+ cc-cockpit serve --open # dashboard only (http://127.0.0.1:8765)
96
+ cc-cockpit json # everything as JSON, for scripting
97
+ cc-cockpit collect # ingest new transcripts and exit
98
+ cc-cockpit config # config path and contents
99
+ cc-cockpit --lang es report
100
+ ```
101
+
102
+ ## The real numbers, from the statusline
103
+
104
+ Two things cannot be derived from local transcripts:
105
+
106
+ 1. **The limit belongs to the account, not to the CLI.** Whatever you consume in
107
+ the Claude app counts against the same window and leaves nothing on disk, so
108
+ a window can start before your first local request.
109
+ 2. **The weekly limit is a fixed window** with its own reset time, not the
110
+ rolling 7 days a local reader would assume.
111
+
112
+ Claude Code pipes a JSON payload into the statusline command on every render,
113
+ and it carries exactly what the plan panel shows:
114
+
115
+ ```json
116
+ "rate_limits": {
117
+ "five_hour": {"used_percentage": 23, "resets_at": 1788800000},
118
+ "seven_day": {"used_percentage": 3, "resets_at": 1788790000}
119
+ }
120
+ ```
121
+
122
+ Register the capture once — no credentials, no undocumented endpoint:
123
+
124
+ ```bash
125
+ cc-cockpit statusline --install
126
+ ```
127
+
128
+ It writes `statusLine` into `~/.claude/settings.json`, keeping a `.bak`. If you
129
+ already had one, it is chained rather than replaced, so its output still shows
130
+ in the CLI. The captured payload also carries the **context window percentage
131
+ per session**, which the dashboard shows next to each open session.
132
+
133
+ From then on the official percentage is the source of truth, and it reveals the
134
+ real ceiling — `local consumption ÷ official percentage` — so the currency
135
+ figures stay meaningful too.
136
+
137
+ ### When there is no statusline data yet
138
+
139
+ Numbers fall back, in order of trust: **official** (statusline) → **anchored**
140
+ (what you typed) → **local estimate**. The middle one exists because a fresh
141
+ install has no capture yet:
142
+
143
+ ```bash
144
+ cc-cockpit sync --block 23% --block-reset 1h55 --week 3% --week-reset 1h15
145
+ cc-cockpit sync # show anchors, samples and implied ceilings
146
+ cc-cockpit sync --reset
147
+ ```
148
+
149
+ Both the tray and the dashboard say which source is in use.
150
+
151
+ ## How it works
152
+
153
+ ```
154
+ ~/.claude/projects/**/*.jsonl transcripts (usage per request)
155
+ ~/.claude/sessions/*.json one entry per live CLI ─┐
156
+ statusline payload (stdin) official rate limits + context ├─> cockpit/
157
+ ~/.local/share/cc-cockpit/events.ndjson <───────────────┘
158
+ ~/.local/share/cc-cockpit/panel.json official snapshot
159
+ ```
160
+
161
+ - `collector.py` reads each transcript **from the last offset**, so a refresh
162
+ costs ~30 ms even with 190 MB of history.
163
+ - Events land in a dedicated NDJSON file. That matters: Claude Code **prunes
164
+ transcripts after ~30 days**, and from the first collection onward cc-cockpit
165
+ keeps the full history.
166
+ - Deduplication by `message.id:requestId`, so resuming a session is not counted
167
+ twice.
168
+ - `sessions.py` validates each pid against `/proc` **and** compares the
169
+ `starttime`, so a recycled pid is never mistaken for a live session.
170
+ - Prices live in `pricing.py`: cache writes at 1.25× (5m) and 2× (1h) of input,
171
+ cache reads at 0.1× (0.025× on Fable 5.1). The transcript separates the two
172
+ cache-write TTLs and the calculation uses that split instead of assuming 5m.
173
+ - `i18n.py` holds one catalogue for all three surfaces, plus locale-aware number
174
+ and currency formatting.
175
+ - `panel.py` keeps the official snapshot and appends a line to
176
+ `panel-history.ndjson` whenever the percentage changes.
177
+
178
+ ## Honest limitations
179
+
180
+ - Without the statusline capture and without `limits`, the percentage is
181
+ relative to your own history, not to the real plan limit.
182
+ - The statusline only refreshes while a CLI session is rendering. That is
183
+ enough — what is not running cannot be consuming — but right after a long
184
+ gap the percentage may lag until the next render.
185
+ - Consumption from the Claude app shows up in the official percentage, never in
186
+ the local currency figures, which read Claude Code transcripts only.
187
+ - Models released after this version fall back to their family price (`opus`,
188
+ `sonnet`, `haiku`, `fable`) until they are added to `pricing.py`.
189
+ - `<synthetic>` rows are responses the CLI generates locally: they show up in
190
+ the request count and cost nothing.
191
+
192
+ ## Packaging
193
+
194
+ `packaging/` holds the `.deb` build script and the Arch `PKGBUILD`; see
195
+ [packaging/README.md](packaging/README.md) for the release flow. A `v*` tag
196
+ builds the wheel, the sdist and the `.deb`, publishes to PyPI and attaches
197
+ everything to the GitHub release.
198
+
199
+ ## License
200
+
201
+ MIT — see [LICENSE](LICENSE).
202
+
203
+ Not affiliated with Anthropic.
@@ -0,0 +1,27 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ cc_cockpit.egg-info/PKG-INFO
5
+ cc_cockpit.egg-info/SOURCES.txt
6
+ cc_cockpit.egg-info/dependency_links.txt
7
+ cc_cockpit.egg-info/entry_points.txt
8
+ cc_cockpit.egg-info/requires.txt
9
+ cc_cockpit.egg-info/top_level.txt
10
+ cockpit/__init__.py
11
+ cockpit/__main__.py
12
+ cockpit/anchors.py
13
+ cockpit/calibration.py
14
+ cockpit/cli.py
15
+ cockpit/collector.py
16
+ cockpit/config.py
17
+ cockpit/desktop.py
18
+ cockpit/i18n.py
19
+ cockpit/icon.py
20
+ cockpit/panel.py
21
+ cockpit/pricing.py
22
+ cockpit/server.py
23
+ cockpit/sessions.py
24
+ cockpit/stats.py
25
+ cockpit/statusline.py
26
+ cockpit/tray.py
27
+ cockpit/web/index.html
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cc-cockpit = cockpit.cli:main
@@ -0,0 +1,4 @@
1
+
2
+ [tray]
3
+ PyGObject>=3.42
4
+ pycairo>=1.20
@@ -0,0 +1 @@
1
+ cockpit
@@ -0,0 +1,3 @@
1
+ """cc-cockpit - Claude Code usage panel."""
2
+
3
+ __version__ = "0.2.0"
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())