ka-telemetry 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. ka_telemetry-0.1.0/LICENSE +202 -0
  2. ka_telemetry-0.1.0/PKG-INFO +224 -0
  3. ka_telemetry-0.1.0/README.md +195 -0
  4. ka_telemetry-0.1.0/ka_telemetry/__init__.py +7 -0
  5. ka_telemetry-0.1.0/ka_telemetry/__main__.py +15 -0
  6. ka_telemetry-0.1.0/ka_telemetry/cli.py +185 -0
  7. ka_telemetry-0.1.0/ka_telemetry/context_gauge.py +87 -0
  8. ka_telemetry-0.1.0/ka_telemetry/flow_usage.py +1305 -0
  9. ka_telemetry-0.1.0/ka_telemetry/receiver.py +391 -0
  10. ka_telemetry-0.1.0/ka_telemetry/run_usage.py +1303 -0
  11. ka_telemetry-0.1.0/ka_telemetry/stream_paths.py +12 -0
  12. ka_telemetry-0.1.0/ka_telemetry/stream_usage.py +1737 -0
  13. ka_telemetry-0.1.0/ka_telemetry/transcript_notes.py +81 -0
  14. ka_telemetry-0.1.0/ka_telemetry/turn_on.py +809 -0
  15. ka_telemetry-0.1.0/ka_telemetry.egg-info/PKG-INFO +224 -0
  16. ka_telemetry-0.1.0/ka_telemetry.egg-info/SOURCES.txt +39 -0
  17. ka_telemetry-0.1.0/ka_telemetry.egg-info/dependency_links.txt +1 -0
  18. ka_telemetry-0.1.0/ka_telemetry.egg-info/entry_points.txt +2 -0
  19. ka_telemetry-0.1.0/ka_telemetry.egg-info/top_level.txt +1 -0
  20. ka_telemetry-0.1.0/pyproject.toml +48 -0
  21. ka_telemetry-0.1.0/setup.cfg +4 -0
  22. ka_telemetry-0.1.0/tests/test_agent_usage.py +5352 -0
  23. ka_telemetry-0.1.0/tests/test_apply_telemetry_env.py +459 -0
  24. ka_telemetry-0.1.0/tests/test_cli.py +392 -0
  25. ka_telemetry-0.1.0/tests/test_context_gauge.py +513 -0
  26. ka_telemetry-0.1.0/tests/test_documentation_examples.py +876 -0
  27. ka_telemetry-0.1.0/tests/test_flow_usage.py +5144 -0
  28. ka_telemetry-0.1.0/tests/test_instrument_run.py +1118 -0
  29. ka_telemetry-0.1.0/tests/test_main_module.py +84 -0
  30. ka_telemetry-0.1.0/tests/test_otel_receiver.py +1277 -0
  31. ka_telemetry-0.1.0/tests/test_package.py +641 -0
  32. ka_telemetry-0.1.0/tests/test_parity.py +659 -0
  33. ka_telemetry-0.1.0/tests/test_release_check_readme.py +312 -0
  34. ka_telemetry-0.1.0/tests/test_release_metrics.py +4596 -0
  35. ka_telemetry-0.1.0/tests/test_release_network.py +618 -0
  36. ka_telemetry-0.1.0/tests/test_run_usage.py +3870 -0
  37. ka_telemetry-0.1.0/tests/test_stream_parity.py +201 -0
  38. ka_telemetry-0.1.0/tests/test_stream_paths.py +56 -0
  39. ka_telemetry-0.1.0/tests/test_transcript_notes.py +345 -0
  40. ka_telemetry-0.1.0/tests/test_turn_on.py +2712 -0
  41. ka_telemetry-0.1.0/tests/test_turn_on_parity.py +779 -0
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,224 @@
1
+ Metadata-Version: 2.4
2
+ Name: ka-telemetry
3
+ Version: 0.1.0
4
+ Summary: Receives the telemetry stream Claude Code can send, reads the transcripts it keeps on this machine, and reports the tokens they record.
5
+ Author: Eyal Golan
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/eyalgo/ka-telemetry
8
+ Project-URL: Source, https://github.com/eyalgo/ka-telemetry
9
+ Project-URL: Issues, https://github.com/eyalgo/ka-telemetry/issues
10
+ Project-URL: Changelog, https://github.com/eyalgo/ka-telemetry/blob/main/RELEASE_NOTES.md
11
+ Project-URL: Built by, https://github.com/eyalgo/kensaiapp
12
+ Keywords: claude-code,telemetry,opentelemetry,observability,tokens
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: System :: Monitoring
25
+ Requires-Python: >=3.11
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Dynamic: license-file
29
+
30
+ # ka-telemetry
31
+
32
+ ka-telemetry is a Python command-line tool and library that receives the telemetry Claude Code sends, reads the transcripts Claude Code keeps, and reports what each agent, background run and workflow step used — tokens and time, and cost where Claude Code reported one — on your own machine. It is for people who run Claude Code with subagents, background runs or workflows and want per-agent numbers without a hosted observability service.
33
+
34
+ How to turn telemetry on, read each report, remove old records and keep the receiver running is in the how-to, [`docs/how-to.md`](docs/how-to.md).
35
+
36
+ ## Built by KensaiApp
37
+
38
+ ka-telemetry was built end to end by [KensaiApp](https://github.com/eyalgo/kensaiapp), a system of AI roles that carries a software change from first ask to merged code on top of Claude Code. Its roles wrote the requirements, the code, the tests and this README; a person made the decisions.
39
+
40
+ ## Install
41
+
42
+ ka-telemetry supports macOS and Linux, and needs Python 3.11 or later. It depends on nothing outside Python's standard library. Install it from the Python Package Index with pipx, which installs a command-line tool written in Python into an environment of its own:
43
+
44
+ ```sh
45
+ pipx install ka-telemetry
46
+ ```
47
+
48
+ If you do not have pipx yet, install it first. On macOS, with Homebrew:
49
+
50
+ ```sh
51
+ brew install pipx
52
+ ```
53
+
54
+ On Linux, install it from your distribution's own package. On Ubuntu 23.04 or later:
55
+
56
+ ```sh
57
+ sudo apt update
58
+ sudo apt install pipx
59
+ ```
60
+
61
+ On another distribution, look for pipx among its own packages.
62
+
63
+ Then run this once, so that the commands pipx installs, `ka-telemetry` among them, are on your PATH:
64
+
65
+ ```sh
66
+ pipx ensurepath
67
+ ```
68
+
69
+ The change takes effect in a new terminal. Open one, then run the install command above.
70
+
71
+ If the Python pipx installs with is older than 3.11, the install does one of two things. It stops with an error and installs nothing, or it installs ka-telemetry with a Python 3.11 or later that pipx chose instead, and says which Python it used. Either way, what pipx prints names ka-telemetry's Python requirement, `>=3.11`, and the rest of its wording differs from one pipx setup to another. If the install stopped, install Python 3.11 or later, then give it to pipx with `--python`, putting the name or the path of the Python you installed in place of `python3.12`:
72
+
73
+ ```sh
74
+ pipx install --python python3.12 ka-telemetry
75
+ ```
76
+
77
+ ## Use the library in your own code
78
+
79
+ To import ka-telemetry's library in your own Python code, install ka-telemetry with pip inside your own virtual environment, with that environment active:
80
+
81
+ ```sh
82
+ python3 -m pip install ka-telemetry
83
+ ```
84
+
85
+ This is for your code to import the library. To run the `ka-telemetry` command, install it with pipx, as the Install section above shows.
86
+
87
+ ## Try it
88
+
89
+ This repository keeps a sample of the telemetry Claude Code sent during a few real sessions, in `tests/stream_parity`. The install above does not bring that sample with it, so get a copy of this repository first and go into it:
90
+
91
+ ```sh
92
+ git clone https://github.com/eyalgo/ka-telemetry.git ka-telemetry-repo
93
+ cd ka-telemetry-repo
94
+ ```
95
+
96
+ Run this example from the top directory of a copy of this repository, the directory that holds the README, which is where those two commands leave you. It prints the per-agent report for one session in that sample, and the block after it is everything the command prints:
97
+
98
+ ```sh
99
+ ka-telemetry agents --dir tests/stream_parity --where session.id=6547733b-af89-40a8-a524-2df28af94cae
100
+ ```
101
+
102
+ ```text
103
+ 2 agent row(s), 1 unreadable line(s) skipped.
104
+ session=6547733b-af89-40a8-a524-2df28af94cae workflow_run_id=None query_source=repl_main_thread agent=None requests=1 models=claude-haiku-4-5-20251001 cost_usd=0.051883
105
+ input=10 output=55 cache_read=27180 cache_creation=24440 duration_ms=1550
106
+ session=6547733b-af89-40a8-a524-2df28af94cae workflow_run_id=None query_source=generate_session_title agent=None requests=2 models=claude-haiku-4-5-20251001 cost_usd=0.001889
107
+ input=1794 output=19 cache_read=0 cache_creation=0 duration_ms=2030
108
+ Total cost_usd: 0.053772
109
+ Every cost here is an estimate: Claude Code's own, in US dollars as Claude Code reported it, or a total, mean or difference of those estimates. None is a bill.
110
+
111
+ subagent_completed counts Agent-tool agents only — a Workflow step's own requests (query_source "agent:builtin:workflow-subagent") emit no subagent_completed record, so this count does not cover them.
112
+ subagent_completed records were read, but none is in a session the rows show. Run without --where to list them.
113
+
114
+ Totals check (claude_code.cost.usage vs summed cost_usd):
115
+ session=6547733b-af89-40a8-a524-2df28af94cae log_cost_usd=0.053772 metric_cost_usd=0.053772
116
+ ```
117
+
118
+ Each row is one source of requests in that session: here the main conversation (`repl_main_thread`) and Claude Code's session-title requests (`generate_session_title`), each with its requests, models, cost and token classes. `--where session.id=…` keeps one session's rows; without it, the report shows every session in the directory. The sample holds one line ka-telemetry cannot read, and the report's first line counts it as skipped.
119
+
120
+ On your own machine, once the receiver has received telemetry, `ka-telemetry agents` with no options reports everything in `~/.ka-telemetry`. The how-to shows how to start the receiver and turn telemetry on.
121
+
122
+ ## What ka-telemetry touches on your machine
123
+
124
+ Each command touches only what is listed under it, and only when you run it.
125
+
126
+ **`ka-telemetry receive`**
127
+
128
+ - Listens on `127.0.0.1`, which only programs on this machine can reach, on the port you give with `--port`.
129
+ - Appends each record it accepts to `logs.jsonl` or `metrics.jsonl` in `~/.ka-telemetry`, or in the directory you name with `--dir`. If that directory does not exist, it creates it when it writes its first record.
130
+ - With `--publish-endpoint PATH`, writes `http://localhost:PORT` to the file `PATH`, replacing what that file held, with `PORT` the port it is listening on. The directory that holds `PATH` must already exist.
131
+ - With `--host` and another address, listens on that address instead, so connections from beyond this machine can reach it. Records that arrive from elsewhere are kept like any other record, and they may be someone else's. The receiver asks for no authentication and writes any JSON it is sent to /v1/logs or /v1/metrics, so with another address anyone who can reach it can add records to these files.
132
+
133
+ **`ka-telemetry agents` and `ka-telemetry check`**
134
+
135
+ - Read `logs.jsonl` and `metrics.jsonl` in `~/.ka-telemetry`, or in the directory you name with `--dir`.
136
+ - Write no file and run no other program.
137
+
138
+ **`ka-telemetry runs`**
139
+
140
+ - Runs `claude agents --json --all`, Claude Code's own command, to list Claude Code's background runs. With `--agents-json FILE`, it reads that list from `FILE` instead and runs no other program.
141
+ - Reads the transcripts under `~/.claude/projects`, or under the directory you name with `--projects-root`.
142
+ - Reads `~/.ka-telemetry/logs.jsonl`, if it is there, to point at the per-agent report for each session that sent telemetry. No option changes this path.
143
+ - Writes no file.
144
+
145
+ **`ka-telemetry steps`**
146
+
147
+ - Reads each workflow run's journal, and its agents' transcripts and meta files, under `~/.claude/projects`, or under the directory you name with `--projects-root`.
148
+ - Reads `~/.ka-telemetry/logs.jsonl`, if it is there, to point at the per-agent report for each session that sent telemetry. No option changes this path.
149
+ - Writes no file and runs no other program.
150
+
151
+ **`ka-telemetry context`**
152
+
153
+ - Reads the one transcript file you name.
154
+ - Writes no file and runs no other program.
155
+
156
+ **`ka-telemetry turn-on`**
157
+
158
+ - Reads the receiver's address from `~/.claude/tools/otel-receiver/endpoint`, or from the file you name with `--endpoint-file`. With `--remove --force`, it does not read it.
159
+ - With `--settings-file PATH`, reads the Claude Code settings file `PATH` and writes into it the five keys that make Claude Code send its telemetry to the receiver, with a record of what it wrote. If `PATH` does not exist, it creates it, as long as the directory that holds it exists. With `--remove`, it takes keys out of `PATH` instead.
160
+ - Writes the new settings to a temporary file beside `PATH` first, then puts that file in place of `PATH` in one step. If `PATH` is a symbolic link, the file the link points to is the one replaced.
161
+ - Without a published address, writes nothing, unless you pass `--remove --force`.
162
+ - With `--print`, touches no settings file and prints the keys for one run. With `--print --prefix`, also runs `git rev-parse` in the directory you run it from, to name the git repository you run it in.
163
+
164
+ ## What ka-telemetry will not touch
165
+
166
+ - Nothing ka-telemetry does deletes, truncates or rewrites a record the receiver wrote. The receiver only appends to its two files, so they grow until you delete them; the how-to shows how.
167
+ - `runs`, `steps` and `context` write no file, and change none of Claude Code's files.
168
+ - `turn-on`: A value you already set on one of the five keys is never overwritten unless you pass --replace, and --remove takes out only what this command wrote unless you pass --force.
169
+ - `turn-on` never turns on Claude Code's logging of prompt text, tool inputs or responses. If you turn that logging on yourself, what Claude Code then sends lands in the receiver's files as received.
170
+ - This tool sends no telemetry and makes no network call except the ones the job you asked for requires.
171
+ - The receiver keeps what it receives in its two files and sends it nowhere else.
172
+
173
+ ## What the files hold about you
174
+
175
+ When you are signed in, Claude Code sends your email address with its telemetry, as the `user.email` attribute, along with account, organisation, installation and session identifiers. The receiver removes every `user.email` attribute from each record before it writes the record, so ka-telemetry never writes that email address to disk. `user.email` is the one field the receiver removes, and it keeps everything else as received.
176
+
177
+ So the account, organisation, installation and session identifiers Claude Code sends do land in the files, and sharing the files — in a bug report, for example — shares those identifiers. If you turn on Claude Code's logging of prompt text, tool inputs or responses, that text lands in the files too, with any email address written inside it.
178
+
179
+ ## Other providers
180
+
181
+ ka-telemetry is built to read Claude Code. Other providers are not fully supported:
182
+
183
+ - Codex and Gemini: ka-telemetry has no reader for either, so it reports nothing they use.
184
+ - Claude Code on a non-Anthropic endpoint, such as a local model: the cost ka-telemetry shows for it is Claude Code's guess.
185
+
186
+ ## Check a release
187
+
188
+ Every release of ka-telemetry has to meet six bars, numbered 1, 2, 3, 5, 7 and 8 among its success metrics. The release check measures all six of them. It measures bars 1, 2 and 3 on the reference set, the recorded telemetry and transcripts this repository keeps in `tests/parity` and `tests/stream_parity` with the figures expected from them. It measures bar 5 by building ka-telemetry from your copy and then running this README's own pipx install command, the first command in the Install section above, as written, on a Python that refuses pip installs as externally managed. What it built is the only package that command can install. It measures bar 7 by running every `ka-telemetry` command, refusing any attempt a command makes to reach beyond this machine, and by checking that the receiver, started with no `--host`, listens only on this machine. It does not watch the programs a command starts, such as the Git that `turn-on` runs. It measures bar 8 on the examples in this README and the how-to. Run it from the top directory of a copy of this repository, the directory that holds the README:
189
+
190
+ ```sh
191
+ python3 tools/release_check.py
192
+ ```
193
+
194
+ It needs Python 3.11 or later with pip, pytest installed for that Python, and Git. It measures the files in your copy as they are, including changes you have not committed, and changes none of them: it works in a temporary directory that it removes before it exits. The settings file `turn-on` writes during the check and the files the receiver writes are in that directory too, and the receiver is stopped before the check ends. For bar 5 it uses the pipx on your PATH, or, when there is none, a pipx of its own that it brings into that directory. What pipx writes during the check is in that directory as well.
195
+
196
+ The check fetches packages over the network with pip in these three steps and in no other, and none of them is part of the install it measures:
197
+
198
+ - Each build of ka-telemetry, one for the install and one for the examples, fetches its build backend.
199
+ - When there is no pipx on your PATH, bringing in the check's own pipx fetches pipx and the packages pipx depends on.
200
+ - Before the install it measures, readying the libraries pipx shares among the environments it makes, pip among them, fetches those libraries. This step runs whether the pipx is yours or the check's own.
201
+
202
+ The install it measures fetches no package: it installs only what it built.
203
+
204
+ It prints one line for each bar it checks: the bar's number, what the bar asks, and then `holds` or `fails`. A bar it could not measure ends `fails` too. For each line that ends `fails`, it writes lines to standard error that begin with the same number and say what did not hold, or what it could not read or run. It exits with status 0 when every line ends `holds`, and with status 1 when any line ends `fails`.
205
+
206
+ ## Support
207
+
208
+ Support is best effort, with no response-time promise. ka-telemetry is maintained while kensaiapp runs on it; kensaiapp is the publisher's own system for building software with Claude Code agents, the counting ka-telemetry does was first written there, and kensaiapp now reads its own telemetry through ka-telemetry. If that stops, the repository is archived visibly rather than left with an open issue tracker. This support posture is a personal promise from the person who publishes ka-telemetry, and no company stands behind it.
209
+
210
+ To report a security problem privately, open the repository's Security tab on GitHub and choose **Report a vulnerability** (https://github.com/eyalgo/ka-telemetry/security/advisories/new); [`SECURITY.md`](SECURITY.md) says the same. Please do not open a public issue for it. Whether outside pull requests are taken is in [`CONTRIBUTING.md`](CONTRIBUTING.md).
211
+
212
+ ## Versions and the public API
213
+
214
+ ka-telemetry follows semantic versioning against its public API, which is: the command names and their options, the exit codes, both output forms (text and `--json`), the layout of the files the receiver writes and the outer fields of each record in them (`signal`, `received_at` and `body`), which settings entries `turn-on` writes, and the library's readers and row types.
215
+
216
+ Two things sit outside the public API, so a change Claude Code makes to either is not a breaking change in ka-telemetry: the content of each record, which is what Claude Code sent less the dropped email address, and the names of the settings entries, which are Claude Code's.
217
+
218
+ ka-telemetry is at 0.x, and until 1.0.0 anything may change. kensaiapp now runs on ka-telemetry, so 1.0.0 is declared once someone with no tie to the project has got started from this README.
219
+
220
+ ## Status
221
+
222
+ What each release does is in [`RELEASE_NOTES.md`](RELEASE_NOTES.md).
223
+
224
+ ka-telemetry does not yet state in every report what it read and what it could not read and why, or name every session that has no cost metric to check against and say it received no cost metric for it.
@@ -0,0 +1,195 @@
1
+ # ka-telemetry
2
+
3
+ ka-telemetry is a Python command-line tool and library that receives the telemetry Claude Code sends, reads the transcripts Claude Code keeps, and reports what each agent, background run and workflow step used — tokens and time, and cost where Claude Code reported one — on your own machine. It is for people who run Claude Code with subagents, background runs or workflows and want per-agent numbers without a hosted observability service.
4
+
5
+ How to turn telemetry on, read each report, remove old records and keep the receiver running is in the how-to, [`docs/how-to.md`](docs/how-to.md).
6
+
7
+ ## Built by KensaiApp
8
+
9
+ ka-telemetry was built end to end by [KensaiApp](https://github.com/eyalgo/kensaiapp), a system of AI roles that carries a software change from first ask to merged code on top of Claude Code. Its roles wrote the requirements, the code, the tests and this README; a person made the decisions.
10
+
11
+ ## Install
12
+
13
+ ka-telemetry supports macOS and Linux, and needs Python 3.11 or later. It depends on nothing outside Python's standard library. Install it from the Python Package Index with pipx, which installs a command-line tool written in Python into an environment of its own:
14
+
15
+ ```sh
16
+ pipx install ka-telemetry
17
+ ```
18
+
19
+ If you do not have pipx yet, install it first. On macOS, with Homebrew:
20
+
21
+ ```sh
22
+ brew install pipx
23
+ ```
24
+
25
+ On Linux, install it from your distribution's own package. On Ubuntu 23.04 or later:
26
+
27
+ ```sh
28
+ sudo apt update
29
+ sudo apt install pipx
30
+ ```
31
+
32
+ On another distribution, look for pipx among its own packages.
33
+
34
+ Then run this once, so that the commands pipx installs, `ka-telemetry` among them, are on your PATH:
35
+
36
+ ```sh
37
+ pipx ensurepath
38
+ ```
39
+
40
+ The change takes effect in a new terminal. Open one, then run the install command above.
41
+
42
+ If the Python pipx installs with is older than 3.11, the install does one of two things. It stops with an error and installs nothing, or it installs ka-telemetry with a Python 3.11 or later that pipx chose instead, and says which Python it used. Either way, what pipx prints names ka-telemetry's Python requirement, `>=3.11`, and the rest of its wording differs from one pipx setup to another. If the install stopped, install Python 3.11 or later, then give it to pipx with `--python`, putting the name or the path of the Python you installed in place of `python3.12`:
43
+
44
+ ```sh
45
+ pipx install --python python3.12 ka-telemetry
46
+ ```
47
+
48
+ ## Use the library in your own code
49
+
50
+ To import ka-telemetry's library in your own Python code, install ka-telemetry with pip inside your own virtual environment, with that environment active:
51
+
52
+ ```sh
53
+ python3 -m pip install ka-telemetry
54
+ ```
55
+
56
+ This is for your code to import the library. To run the `ka-telemetry` command, install it with pipx, as the Install section above shows.
57
+
58
+ ## Try it
59
+
60
+ This repository keeps a sample of the telemetry Claude Code sent during a few real sessions, in `tests/stream_parity`. The install above does not bring that sample with it, so get a copy of this repository first and go into it:
61
+
62
+ ```sh
63
+ git clone https://github.com/eyalgo/ka-telemetry.git ka-telemetry-repo
64
+ cd ka-telemetry-repo
65
+ ```
66
+
67
+ Run this example from the top directory of a copy of this repository, the directory that holds the README, which is where those two commands leave you. It prints the per-agent report for one session in that sample, and the block after it is everything the command prints:
68
+
69
+ ```sh
70
+ ka-telemetry agents --dir tests/stream_parity --where session.id=6547733b-af89-40a8-a524-2df28af94cae
71
+ ```
72
+
73
+ ```text
74
+ 2 agent row(s), 1 unreadable line(s) skipped.
75
+ session=6547733b-af89-40a8-a524-2df28af94cae workflow_run_id=None query_source=repl_main_thread agent=None requests=1 models=claude-haiku-4-5-20251001 cost_usd=0.051883
76
+ input=10 output=55 cache_read=27180 cache_creation=24440 duration_ms=1550
77
+ session=6547733b-af89-40a8-a524-2df28af94cae workflow_run_id=None query_source=generate_session_title agent=None requests=2 models=claude-haiku-4-5-20251001 cost_usd=0.001889
78
+ input=1794 output=19 cache_read=0 cache_creation=0 duration_ms=2030
79
+ Total cost_usd: 0.053772
80
+ Every cost here is an estimate: Claude Code's own, in US dollars as Claude Code reported it, or a total, mean or difference of those estimates. None is a bill.
81
+
82
+ subagent_completed counts Agent-tool agents only — a Workflow step's own requests (query_source "agent:builtin:workflow-subagent") emit no subagent_completed record, so this count does not cover them.
83
+ subagent_completed records were read, but none is in a session the rows show. Run without --where to list them.
84
+
85
+ Totals check (claude_code.cost.usage vs summed cost_usd):
86
+ session=6547733b-af89-40a8-a524-2df28af94cae log_cost_usd=0.053772 metric_cost_usd=0.053772
87
+ ```
88
+
89
+ Each row is one source of requests in that session: here the main conversation (`repl_main_thread`) and Claude Code's session-title requests (`generate_session_title`), each with its requests, models, cost and token classes. `--where session.id=…` keeps one session's rows; without it, the report shows every session in the directory. The sample holds one line ka-telemetry cannot read, and the report's first line counts it as skipped.
90
+
91
+ On your own machine, once the receiver has received telemetry, `ka-telemetry agents` with no options reports everything in `~/.ka-telemetry`. The how-to shows how to start the receiver and turn telemetry on.
92
+
93
+ ## What ka-telemetry touches on your machine
94
+
95
+ Each command touches only what is listed under it, and only when you run it.
96
+
97
+ **`ka-telemetry receive`**
98
+
99
+ - Listens on `127.0.0.1`, which only programs on this machine can reach, on the port you give with `--port`.
100
+ - Appends each record it accepts to `logs.jsonl` or `metrics.jsonl` in `~/.ka-telemetry`, or in the directory you name with `--dir`. If that directory does not exist, it creates it when it writes its first record.
101
+ - With `--publish-endpoint PATH`, writes `http://localhost:PORT` to the file `PATH`, replacing what that file held, with `PORT` the port it is listening on. The directory that holds `PATH` must already exist.
102
+ - With `--host` and another address, listens on that address instead, so connections from beyond this machine can reach it. Records that arrive from elsewhere are kept like any other record, and they may be someone else's. The receiver asks for no authentication and writes any JSON it is sent to /v1/logs or /v1/metrics, so with another address anyone who can reach it can add records to these files.
103
+
104
+ **`ka-telemetry agents` and `ka-telemetry check`**
105
+
106
+ - Read `logs.jsonl` and `metrics.jsonl` in `~/.ka-telemetry`, or in the directory you name with `--dir`.
107
+ - Write no file and run no other program.
108
+
109
+ **`ka-telemetry runs`**
110
+
111
+ - Runs `claude agents --json --all`, Claude Code's own command, to list Claude Code's background runs. With `--agents-json FILE`, it reads that list from `FILE` instead and runs no other program.
112
+ - Reads the transcripts under `~/.claude/projects`, or under the directory you name with `--projects-root`.
113
+ - Reads `~/.ka-telemetry/logs.jsonl`, if it is there, to point at the per-agent report for each session that sent telemetry. No option changes this path.
114
+ - Writes no file.
115
+
116
+ **`ka-telemetry steps`**
117
+
118
+ - Reads each workflow run's journal, and its agents' transcripts and meta files, under `~/.claude/projects`, or under the directory you name with `--projects-root`.
119
+ - Reads `~/.ka-telemetry/logs.jsonl`, if it is there, to point at the per-agent report for each session that sent telemetry. No option changes this path.
120
+ - Writes no file and runs no other program.
121
+
122
+ **`ka-telemetry context`**
123
+
124
+ - Reads the one transcript file you name.
125
+ - Writes no file and runs no other program.
126
+
127
+ **`ka-telemetry turn-on`**
128
+
129
+ - Reads the receiver's address from `~/.claude/tools/otel-receiver/endpoint`, or from the file you name with `--endpoint-file`. With `--remove --force`, it does not read it.
130
+ - With `--settings-file PATH`, reads the Claude Code settings file `PATH` and writes into it the five keys that make Claude Code send its telemetry to the receiver, with a record of what it wrote. If `PATH` does not exist, it creates it, as long as the directory that holds it exists. With `--remove`, it takes keys out of `PATH` instead.
131
+ - Writes the new settings to a temporary file beside `PATH` first, then puts that file in place of `PATH` in one step. If `PATH` is a symbolic link, the file the link points to is the one replaced.
132
+ - Without a published address, writes nothing, unless you pass `--remove --force`.
133
+ - With `--print`, touches no settings file and prints the keys for one run. With `--print --prefix`, also runs `git rev-parse` in the directory you run it from, to name the git repository you run it in.
134
+
135
+ ## What ka-telemetry will not touch
136
+
137
+ - Nothing ka-telemetry does deletes, truncates or rewrites a record the receiver wrote. The receiver only appends to its two files, so they grow until you delete them; the how-to shows how.
138
+ - `runs`, `steps` and `context` write no file, and change none of Claude Code's files.
139
+ - `turn-on`: A value you already set on one of the five keys is never overwritten unless you pass --replace, and --remove takes out only what this command wrote unless you pass --force.
140
+ - `turn-on` never turns on Claude Code's logging of prompt text, tool inputs or responses. If you turn that logging on yourself, what Claude Code then sends lands in the receiver's files as received.
141
+ - This tool sends no telemetry and makes no network call except the ones the job you asked for requires.
142
+ - The receiver keeps what it receives in its two files and sends it nowhere else.
143
+
144
+ ## What the files hold about you
145
+
146
+ When you are signed in, Claude Code sends your email address with its telemetry, as the `user.email` attribute, along with account, organisation, installation and session identifiers. The receiver removes every `user.email` attribute from each record before it writes the record, so ka-telemetry never writes that email address to disk. `user.email` is the one field the receiver removes, and it keeps everything else as received.
147
+
148
+ So the account, organisation, installation and session identifiers Claude Code sends do land in the files, and sharing the files — in a bug report, for example — shares those identifiers. If you turn on Claude Code's logging of prompt text, tool inputs or responses, that text lands in the files too, with any email address written inside it.
149
+
150
+ ## Other providers
151
+
152
+ ka-telemetry is built to read Claude Code. Other providers are not fully supported:
153
+
154
+ - Codex and Gemini: ka-telemetry has no reader for either, so it reports nothing they use.
155
+ - Claude Code on a non-Anthropic endpoint, such as a local model: the cost ka-telemetry shows for it is Claude Code's guess.
156
+
157
+ ## Check a release
158
+
159
+ Every release of ka-telemetry has to meet six bars, numbered 1, 2, 3, 5, 7 and 8 among its success metrics. The release check measures all six of them. It measures bars 1, 2 and 3 on the reference set, the recorded telemetry and transcripts this repository keeps in `tests/parity` and `tests/stream_parity` with the figures expected from them. It measures bar 5 by building ka-telemetry from your copy and then running this README's own pipx install command, the first command in the Install section above, as written, on a Python that refuses pip installs as externally managed. What it built is the only package that command can install. It measures bar 7 by running every `ka-telemetry` command, refusing any attempt a command makes to reach beyond this machine, and by checking that the receiver, started with no `--host`, listens only on this machine. It does not watch the programs a command starts, such as the Git that `turn-on` runs. It measures bar 8 on the examples in this README and the how-to. Run it from the top directory of a copy of this repository, the directory that holds the README:
160
+
161
+ ```sh
162
+ python3 tools/release_check.py
163
+ ```
164
+
165
+ It needs Python 3.11 or later with pip, pytest installed for that Python, and Git. It measures the files in your copy as they are, including changes you have not committed, and changes none of them: it works in a temporary directory that it removes before it exits. The settings file `turn-on` writes during the check and the files the receiver writes are in that directory too, and the receiver is stopped before the check ends. For bar 5 it uses the pipx on your PATH, or, when there is none, a pipx of its own that it brings into that directory. What pipx writes during the check is in that directory as well.
166
+
167
+ The check fetches packages over the network with pip in these three steps and in no other, and none of them is part of the install it measures:
168
+
169
+ - Each build of ka-telemetry, one for the install and one for the examples, fetches its build backend.
170
+ - When there is no pipx on your PATH, bringing in the check's own pipx fetches pipx and the packages pipx depends on.
171
+ - Before the install it measures, readying the libraries pipx shares among the environments it makes, pip among them, fetches those libraries. This step runs whether the pipx is yours or the check's own.
172
+
173
+ The install it measures fetches no package: it installs only what it built.
174
+
175
+ It prints one line for each bar it checks: the bar's number, what the bar asks, and then `holds` or `fails`. A bar it could not measure ends `fails` too. For each line that ends `fails`, it writes lines to standard error that begin with the same number and say what did not hold, or what it could not read or run. It exits with status 0 when every line ends `holds`, and with status 1 when any line ends `fails`.
176
+
177
+ ## Support
178
+
179
+ Support is best effort, with no response-time promise. ka-telemetry is maintained while kensaiapp runs on it; kensaiapp is the publisher's own system for building software with Claude Code agents, the counting ka-telemetry does was first written there, and kensaiapp now reads its own telemetry through ka-telemetry. If that stops, the repository is archived visibly rather than left with an open issue tracker. This support posture is a personal promise from the person who publishes ka-telemetry, and no company stands behind it.
180
+
181
+ To report a security problem privately, open the repository's Security tab on GitHub and choose **Report a vulnerability** (https://github.com/eyalgo/ka-telemetry/security/advisories/new); [`SECURITY.md`](SECURITY.md) says the same. Please do not open a public issue for it. Whether outside pull requests are taken is in [`CONTRIBUTING.md`](CONTRIBUTING.md).
182
+
183
+ ## Versions and the public API
184
+
185
+ ka-telemetry follows semantic versioning against its public API, which is: the command names and their options, the exit codes, both output forms (text and `--json`), the layout of the files the receiver writes and the outer fields of each record in them (`signal`, `received_at` and `body`), which settings entries `turn-on` writes, and the library's readers and row types.
186
+
187
+ Two things sit outside the public API, so a change Claude Code makes to either is not a breaking change in ka-telemetry: the content of each record, which is what Claude Code sent less the dropped email address, and the names of the settings entries, which are Claude Code's.
188
+
189
+ ka-telemetry is at 0.x, and until 1.0.0 anything may change. kensaiapp now runs on ka-telemetry, so 1.0.0 is declared once someone with no tie to the project has got started from this README.
190
+
191
+ ## Status
192
+
193
+ What each release does is in [`RELEASE_NOTES.md`](RELEASE_NOTES.md).
194
+
195
+ ka-telemetry does not yet state in every report what it read and what it could not read and why, or name every session that has no cost metric to check against and say it received no cost metric for it.
@@ -0,0 +1,7 @@
1
+ """ka_telemetry reads the transcripts Claude Code keeps on this machine and reports the tokens
2
+ they record: per background run, per workflow step, and the current context size of one
3
+ transcript. The readers sit in the modules of this package; this file holds no implementation."""
4
+
5
+ from ka_telemetry import context_gauge, flow_usage, run_usage
6
+
7
+ __all__ = ["context_gauge", "flow_usage", "run_usage"]