runledger-ai 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.
Files changed (51) hide show
  1. runledger_ai-0.2.0/LICENSE +203 -0
  2. runledger_ai-0.2.0/PKG-INFO +193 -0
  3. runledger_ai-0.2.0/README.md +164 -0
  4. runledger_ai-0.2.0/pyproject.toml +46 -0
  5. runledger_ai-0.2.0/runledger/__init__.py +2 -0
  6. runledger_ai-0.2.0/runledger/__main__.py +5 -0
  7. runledger_ai-0.2.0/runledger/adapters/__init__.py +74 -0
  8. runledger_ai-0.2.0/runledger/adapters/aider.py +444 -0
  9. runledger_ai-0.2.0/runledger/adapters/claude_code.py +24 -0
  10. runledger_ai-0.2.0/runledger/adapters/codex.py +627 -0
  11. runledger_ai-0.2.0/runledger/adapters/native.py +294 -0
  12. runledger_ai-0.2.0/runledger/cli.py +401 -0
  13. runledger_ai-0.2.0/runledger/client.py +124 -0
  14. runledger_ai-0.2.0/runledger/github.py +487 -0
  15. runledger_ai-0.2.0/runledger/guard.py +875 -0
  16. runledger_ai-0.2.0/runledger/parser.py +258 -0
  17. runledger_ai-0.2.0/runledger/prices.json +103 -0
  18. runledger_ai-0.2.0/runledger/pricing.py +125 -0
  19. runledger_ai-0.2.0/runledger/receipt.py +200 -0
  20. runledger_ai-0.2.0/runledger/risk.py +837 -0
  21. runledger_ai-0.2.0/runledger/server/__init__.py +6 -0
  22. runledger_ai-0.2.0/runledger/server/app.py +1137 -0
  23. runledger_ai-0.2.0/runledger/server/approvals.py +297 -0
  24. runledger_ai-0.2.0/runledger/server/auth.py +184 -0
  25. runledger_ai-0.2.0/runledger/server/budgets.py +144 -0
  26. runledger_ai-0.2.0/runledger/server/dashboard.py +1651 -0
  27. runledger_ai-0.2.0/runledger/server/db.py +972 -0
  28. runledger_ai-0.2.0/runledger/server/exports.py +352 -0
  29. runledger_ai-0.2.0/runledger/summarize.py +189 -0
  30. runledger_ai-0.2.0/runledger_ai.egg-info/PKG-INFO +193 -0
  31. runledger_ai-0.2.0/runledger_ai.egg-info/SOURCES.txt +49 -0
  32. runledger_ai-0.2.0/runledger_ai.egg-info/dependency_links.txt +1 -0
  33. runledger_ai-0.2.0/runledger_ai.egg-info/entry_points.txt +2 -0
  34. runledger_ai-0.2.0/runledger_ai.egg-info/top_level.txt +1 -0
  35. runledger_ai-0.2.0/setup.cfg +4 -0
  36. runledger_ai-0.2.0/tests/test_adapter_aider.py +362 -0
  37. runledger_ai-0.2.0/tests/test_adapter_codex.py +504 -0
  38. runledger_ai-0.2.0/tests/test_adapter_native.py +250 -0
  39. runledger_ai-0.2.0/tests/test_approvals.py +649 -0
  40. runledger_ai-0.2.0/tests/test_auth.py +892 -0
  41. runledger_ai-0.2.0/tests/test_budgets.py +716 -0
  42. runledger_ai-0.2.0/tests/test_dashboard_ui.py +335 -0
  43. runledger_ai-0.2.0/tests/test_exports.py +572 -0
  44. runledger_ai-0.2.0/tests/test_github.py +314 -0
  45. runledger_ai-0.2.0/tests/test_guard.py +909 -0
  46. runledger_ai-0.2.0/tests/test_multiagent_cli.py +229 -0
  47. runledger_ai-0.2.0/tests/test_packaging.py +173 -0
  48. runledger_ai-0.2.0/tests/test_parser_pricing.py +141 -0
  49. runledger_ai-0.2.0/tests/test_risk.py +638 -0
  50. runledger_ai-0.2.0/tests/test_runledger.py +57 -0
  51. runledger_ai-0.2.0/tests/test_server.py +349 -0
@@ -0,0 +1,203 @@
1
+ Copyright 2026 RunLedger
2
+
3
+ Apache License
4
+ Version 2.0, January 2004
5
+ http://www.apache.org/licenses/
6
+
7
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
8
+
9
+ 1. Definitions.
10
+
11
+ "License" shall mean the terms and conditions for use, reproduction,
12
+ and distribution as defined by Sections 1 through 9 of this document.
13
+
14
+ "Licensor" shall mean the copyright owner or entity authorized by
15
+ the copyright owner that is granting the License.
16
+
17
+ "Legal Entity" shall mean the union of the acting entity and all
18
+ other entities that control, are controlled by, or are under common
19
+ control with that entity. For the purposes of this definition,
20
+ "control" means (i) the power, direct or indirect, to cause the
21
+ direction or management of such entity, whether by contract or
22
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
23
+ outstanding shares, or (iii) beneficial ownership of such entity.
24
+
25
+ "You" (or "Your") shall mean an individual or Legal Entity
26
+ exercising permissions granted by this License.
27
+
28
+ "Source" form shall mean the preferred form for making modifications,
29
+ including but not limited to software source code, documentation
30
+ source, and configuration files.
31
+
32
+ "Object" form shall mean any form resulting from mechanical
33
+ transformation or translation of a Source form, including but
34
+ not limited to compiled object code, generated documentation,
35
+ and conversions to other media types.
36
+
37
+ "Work" shall mean the work of authorship, whether in Source or
38
+ Object form, made available under the License, as indicated by a
39
+ copyright notice that is included in or attached to the work
40
+ (an example is provided in the Appendix below).
41
+
42
+ "Derivative Works" shall mean any work, whether in Source or Object
43
+ form, that is based on (or derived from) the Work and for which the
44
+ editorial revisions, annotations, elaborations, or other modifications
45
+ represent, as a whole, an original work of authorship. For the purposes
46
+ of this License, Derivative Works shall not include works that remain
47
+ separable from, or merely link (or bind by name) to the interfaces of,
48
+ the Work and Derivative Works thereof.
49
+
50
+ "Contribution" shall mean any work of authorship, including
51
+ the original version of the Work and any modifications or additions
52
+ to that Work or Derivative Works thereof, that is intentionally
53
+ submitted to Licensor for inclusion in the Work by the copyright owner
54
+ or by an individual or Legal Entity authorized to submit on behalf of
55
+ the copyright owner. For the purposes of this definition, "submitted"
56
+ means any form of electronic, verbal, or written communication sent
57
+ to the Licensor or its representatives, including but not limited to
58
+ communication on electronic mailing lists, source code control systems,
59
+ and issue tracking systems that are managed by, or on behalf of, the
60
+ Licensor for the purpose of discussing and improving the Work, but
61
+ excluding communication that is conspicuously marked or otherwise
62
+ designated in writing by the copyright owner as "Not a Contribution."
63
+
64
+ "Contributor" shall mean Licensor and any individual or Legal Entity
65
+ on behalf of whom a Contribution has been received by Licensor and
66
+ subsequently incorporated within the Work.
67
+
68
+ 2. Grant of Copyright License. Subject to the terms and conditions of
69
+ this License, each Contributor hereby grants to You a perpetual,
70
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
71
+ copyright license to reproduce, prepare Derivative Works of,
72
+ publicly display, publicly perform, sublicense, and distribute the
73
+ Work and such Derivative Works in Source or Object form.
74
+
75
+ 3. Grant of Patent License. Subject to the terms and conditions of
76
+ this License, each Contributor hereby grants to You a perpetual,
77
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
78
+ (except as stated in this section) patent license to make, have made,
79
+ use, offer to sell, sell, import, and otherwise transfer the Work,
80
+ where such license applies only to those patent claims licensable
81
+ by such Contributor that are necessarily infringed by their
82
+ Contribution(s) alone or by combination of their Contribution(s)
83
+ with the Work to which such Contribution(s) was submitted. If You
84
+ institute patent litigation against any entity (including a
85
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
86
+ or a Contribution incorporated within the Work constitutes direct
87
+ or contributory patent infringement, then any patent licenses
88
+ granted to You under this License for that Work shall terminate
89
+ as of the date such litigation is filed.
90
+
91
+ 4. Redistribution. You may reproduce and distribute copies of the
92
+ Work or Derivative Works thereof in any medium, with or without
93
+ modifications, and in Source or Object form, provided that You
94
+ meet the following conditions:
95
+
96
+ (a) You must give any other recipients of the Work or
97
+ Derivative Works a copy of this License; and
98
+
99
+ (b) You must cause any modified files to carry prominent notices
100
+ stating that You changed the files; and
101
+
102
+ (c) You must retain, in the Source form of any Derivative Works
103
+ that You distribute, all copyright, patent, trademark, and
104
+ attribution notices from the Source form of the Work,
105
+ excluding those notices that do not pertain to any part of
106
+ the Derivative Works; and
107
+
108
+ (d) If the Work includes a "NOTICE" text file as part of its
109
+ distribution, then any Derivative Works that You distribute must
110
+ include a readable copy of the attribution notices contained
111
+ within such NOTICE file, excluding those notices that do not
112
+ pertain to any part of the Derivative Works, in at least one
113
+ of the following places: within a NOTICE text file distributed
114
+ as part of the Derivative Works; within the Source form or
115
+ documentation, if provided along with the Derivative Works; or,
116
+ within a display generated by the Derivative Works, if and
117
+ wherever such third-party notices normally appear. The contents
118
+ of the NOTICE file are for informational purposes only and
119
+ do not modify the License. You may add Your own attribution
120
+ notices within Derivative Works that You distribute, alongside
121
+ or as an addendum to the NOTICE text from the Work, provided
122
+ that such additional attribution notices cannot be construed
123
+ as modifying the License.
124
+
125
+ You may add Your own copyright statement to Your modifications and
126
+ may provide additional or different license terms and conditions
127
+ for use, reproduction, or distribution of Your modifications, or
128
+ for any such Derivative Works as a whole, provided Your use,
129
+ reproduction, and distribution of the Work otherwise complies with
130
+ the conditions stated in this License.
131
+
132
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
133
+ any Contribution intentionally submitted for inclusion in the Work
134
+ by You to the Licensor shall be under the terms and conditions of
135
+ this License, without any additional terms or conditions.
136
+ Notwithstanding the above, nothing herein shall supersede or modify
137
+ the terms of any separate license agreement you may have executed
138
+ with Licensor regarding such Contributions.
139
+
140
+ 6. Trademarks. This License does not grant permission to use the trade
141
+ names, trademarks, service marks, or product names of the Licensor,
142
+ except as required for reasonable and customary use in describing the
143
+ origin of the Work and reproducing the content of the NOTICE file.
144
+
145
+ 7. Disclaimer of Warranty. Unless required by applicable law or
146
+ agreed to in writing, Licensor provides the Work (and each
147
+ Contributor provides its Contributions) on an "AS IS" BASIS,
148
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
149
+ implied, including, without limitation, any warranties or conditions
150
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
151
+ PARTICULAR PURPOSE. You are solely responsible for determining the
152
+ appropriateness of using or redistributing the Work and assume any
153
+ risks associated with Your exercise of permissions under this License.
154
+
155
+ 8. Limitation of Liability. In no event and under no legal theory,
156
+ whether in tort (including negligence), contract, or otherwise,
157
+ unless required by applicable law (such as deliberate and grossly
158
+ negligent acts) or agreed to in writing, shall any Contributor be
159
+ liable to You for damages, including any direct, indirect, special,
160
+ incidental, or consequential damages of any character arising as a
161
+ result of this License or out of the use or inability to use the
162
+ Work (including but not limited to damages for loss of goodwill,
163
+ work stoppage, computer failure or malfunction, or any and all
164
+ other commercial damages or losses), even if such Contributor
165
+ has been advised of the possibility of such damages.
166
+
167
+ 9. Accepting Warranty or Additional Liability. While redistributing
168
+ the Work or Derivative Works thereof, You may choose to offer,
169
+ and charge a fee for, acceptance of support, warranty, indemnity,
170
+ or other liability obligations and/or rights consistent with this
171
+ License. However, in accepting such obligations, You may act only
172
+ on Your own behalf and on Your sole responsibility, not on behalf
173
+ of any other Contributor, and only if You agree to indemnify,
174
+ defend, and hold each Contributor harmless for any liability
175
+ incurred by, or claims asserted against, such Contributor by reason
176
+ of your accepting any such warranty or additional liability.
177
+
178
+ END OF TERMS AND CONDITIONS
179
+
180
+ APPENDIX: How to apply the Apache License to your work.
181
+
182
+ To apply the Apache License to your work, attach the following
183
+ boilerplate notice, with the fields enclosed by brackets "[]"
184
+ replaced with your own identifying information. (Don't include
185
+ the brackets!) The text should be enclosed in the appropriate
186
+ comment syntax for the file format. We also recommend that a
187
+ file or class name and description of purpose be included on the
188
+ same "printed page" as the copyright notice for easier
189
+ identification within third-party archives.
190
+
191
+ Copyright [yyyy] [name of copyright owner]
192
+
193
+ Licensed under the Apache License, Version 2.0 (the "License");
194
+ you may not use this file except in compliance with the License.
195
+ You may obtain a copy of the License at
196
+
197
+ http://www.apache.org/licenses/LICENSE-2.0
198
+
199
+ Unless required by applicable law or agreed to in writing, software
200
+ distributed under the License is distributed on an "AS IS" BASIS,
201
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
202
+ See the License for the specific language governing permissions and
203
+ limitations under the License.
@@ -0,0 +1,193 @@
1
+ Metadata-Version: 2.4
2
+ Name: runledger-ai
3
+ Version: 0.2.0
4
+ Summary: A black box recorder for AI coding agents: turn Claude Code runs into shareable receipts.
5
+ Author-email: RunLedger <hello@runledger.site>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://runledger.site
8
+ Project-URL: Source, https://github.com/kodji7202-code/runledger
9
+ Project-URL: Issues, https://github.com/kodji7202-code/runledger/issues
10
+ Project-URL: Documentation, https://github.com/kodji7202-code/runledger/tree/main/docs
11
+ Keywords: ai,coding-agents,claude-code,codex,aider,audit,receipts,guardrails,observability
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Topic :: Software Development :: Quality Assurance
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Dynamic: license-file
29
+
30
+ # RunLedger
31
+
32
+ **Receipts, cost and a real-time guard for AI coding agents.**
33
+
34
+ RunLedger reads the session logs of your coding agents and turns each run into a receipt: what
35
+ changed, what ran, which model did each step, what it cost, and what looked risky. A Claude Code hook
36
+ can stop risky calls before they run, and a small team server collects receipts from the whole team.
37
+
38
+ Version 0.2.0 (unreleased). Python 3.9 or later, no runtime dependencies.
39
+
40
+ ## Quickstart
41
+
42
+ ```bash
43
+ pip install runledger-ai # or `pip install .` from a clone of this repository
44
+ cd ~/my-project # a folder where you ran a coding agent
45
+ runledger receipt --open # latest session as an HTML receipt, opened in your browser
46
+ ```
47
+
48
+ The receipt is saved as `runledger-<first 8 characters of the session id>.html` in the current folder.
49
+ More in [docs/quickstart.md](docs/quickstart.md).
50
+
51
+ ## What you get
52
+
53
+ - **Receipts** as HTML, Markdown or JSON: files changed with lines added and removed, every step in
54
+ plain language, the model, tokens and estimated cost for each step, and a risk score from 0 to 100
55
+ with the reason for each finding.
56
+ - **Summaries with Claude** (`--ai`), optional. This sends session content to Anthropic. See
57
+ [Privacy](#privacy).
58
+ - **A CI gate:** `runledger receipt --fail-on 60` exits with code 2 when the score is 60 or more.
59
+ - **A real-time guard** for Claude Code. It denies, asks or allows each tool call, and it can route
60
+ "ask" decisions to a person on the team server. See [docs/guard.md](docs/guard.md).
61
+ - **A team server:** a shared dashboard, API keys with roles, an audit log, approvals with Slack and
62
+ webhook notifications, team budgets with alerts, and compliance exports. See
63
+ [docs/enterprise.md](docs/enterprise.md) and [docs/api.md](docs/api.md).
64
+ - **Pull request receipts:** one sticky comment per pull request, updated on every push. See
65
+ [docs/github.md](docs/github.md).
66
+
67
+ ## Supported agents
68
+
69
+ | Agent | `--agent` | Status | Reads sessions from |
70
+ | --- | --- | --- | --- |
71
+ | Claude Code | `claude-code` | Stable | `~/.claude/projects/<project>/` |
72
+ | Codex CLI | `codex` | Beta | `$CODEX_HOME/sessions/` (default `~/.codex`) |
73
+ | Aider | `aider` | Beta | `.aider.chat.history.md` in the project folder |
74
+ | Any agent | `native` | Open format | `<project>/.runledger/runs/` |
75
+
76
+ Any agent can write the RunLedger format and get receipts, risk scores and pushes without an adapter.
77
+ The specification is in [docs/format.md](docs/format.md). Details per agent are in
78
+ [docs/agents.md](docs/agents.md).
79
+
80
+ ## Team server in five steps
81
+
82
+ ```bash
83
+ runledger team create myteam --db runledger.db # 1. create the team; prints its API key once
84
+ runledger serve --db runledger.db # 2. start the server on http://127.0.0.1:8787
85
+ # 3. open http://127.0.0.1:8787/?key=YOUR_KEY once, then use the plain address
86
+ export RUNLEDGER_SERVER=http://127.0.0.1:8787 # 4. on each developer's machine
87
+ export RUNLEDGER_API_KEY=YOUR_KEY
88
+ runledger push --user "ana@example.com" # 5. push the latest run
89
+ ```
90
+
91
+ For a shared server, serve it over HTTPS: [docs/self-hosting.md](docs/self-hosting.md) has a Docker
92
+ Compose setup with automatic certificates and a bare-metal setup behind nginx.
93
+ [docs/enterprise.md](docs/enterprise.md) covers roles, key rotation and the audit log.
94
+
95
+ ## Real-time guard in three commands
96
+
97
+ ```bash
98
+ runledger guard install # 1. this project: .claude/settings.json
99
+ runledger guard test '{"session_id":"s1","cwd":"/work/my-app","tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' # 2. see a decision
100
+ runledger guard install --global # 3. or every project: ~/.claude/settings.json
101
+ ```
102
+
103
+ By default the guard **denies** a hardcoded secret written into a file and high-severity commands such
104
+ as `rm -rf`, force pushes, `curl | sh`, `DROP TABLE`, `npm publish` and `kubectl apply`. It **asks**
105
+ before `sudo`, reading a `.env` file, writing outside the project, or deleting a test. Everything else
106
+ is allowed. Two settings files control it: your own `~/.runledger/config.json` may set anything, and a
107
+ project's `.runledger.json` may only make the guard stricter. See [docs/guard.md](docs/guard.md).
108
+
109
+ ## GitHub Action
110
+
111
+ Post a receipt on every pull request. Commit the session files you want reviewed to
112
+ `.runledger/sessions/`, then add this workflow:
113
+
114
+ ```yaml
115
+ name: RunLedger receipt
116
+ on: pull_request
117
+ permissions:
118
+ contents: read
119
+ pull-requests: write
120
+ jobs:
121
+ receipt:
122
+ runs-on: ubuntu-latest
123
+ steps:
124
+ - uses: actions/checkout@v4
125
+ - uses: kodji7202-code/runledger@v0.2.0
126
+ with:
127
+ fail-on: "60" # the job fails at 60 or above; "" never fails
128
+ ```
129
+
130
+ Details, inputs and the exit codes are in [docs/github.md](docs/github.md).
131
+
132
+ ## Privacy
133
+
134
+ RunLedger is local first. `receipt`, `list` and the guard run on your machine. RunLedger has no
135
+ telemetry. The network calls it makes are the ones you ask for: pushing to your team server, the
136
+ guard's approval requests to the server you configure, webhooks you set, the GitHub API in the
137
+ action, and the Anthropic API only when you use `--ai`.
138
+
139
+ What a receipt contains:
140
+
141
+ - the prompts (the first three, in full, in the JSON receipt);
142
+ - each step: the first line of a command (up to 120 characters), file paths and line counts, search
143
+ patterns and URLs, and the step's model, tokens and cost;
144
+ - the risk findings and their reasons.
145
+
146
+ A receipt does **not** contain file contents or command output (only test pass and fail counts).
147
+ **Receipts are not redacted**: a token typed into a command line appears in the receipt. Treat a receipt
148
+ like the session transcript it came from.
149
+
150
+ - **`--ai`** sends the prompts, each step's inputs (up to 600 characters per field, which can include
151
+ file contents being written), each tool result (up to 400 characters) and the agent's final message to
152
+ `api.anthropic.com`. Do not use it on sessions you may not share with that service.
153
+ - **The guard log** (`.runledger/guard.log`) records tool names, commands and paths. It masks known
154
+ token formats and quoted secret values, but **not** unquoted ones such as `API_KEY=...`. Add
155
+ `.runledger/` to your `.gitignore`.
156
+ - **The team server** stores every pushed receipt, including its HTML, in one SQLite file. Anyone with a
157
+ team key can read all of that team's runs. Keys are stored only as hashes. Nothing is deleted
158
+ automatically.
159
+
160
+ ## Pricing
161
+
162
+ Cost figures are estimates from the public Claude API list prices. A subscription is not billed per token,
163
+ so read them as "what this run would cost on the API".
164
+
165
+ Plans: Free, Team at $15 per developer per month, and Enterprise. Details at
166
+ [runledger.site](https://runledger.site).
167
+
168
+ ## Documentation
169
+
170
+ - [Quickstart](docs/quickstart.md): install, first receipt, summaries, CI, hooks, a local team server
171
+ - [Supported agents](docs/agents.md): where each agent's sessions are, and `--agent`
172
+ - [Session format](docs/format.md): the open format for any agent
173
+ - [Real-time guard](docs/guard.md): policy files, approvals, fail-open and fail-closed, the log
174
+ - [Enterprise guide](docs/enterprise.md): roles, API keys, audit, budgets, exports, HTTPS
175
+ - [HTTP API](docs/api.md): every endpoint, with examples and error codes
176
+ - [Self-hosting](docs/self-hosting.md): Docker Compose, bare metal, backups, upgrades
177
+ - [GitHub pull requests](docs/github.md): the action and the comment format
178
+ - [Contributing](CONTRIBUTING.md)
179
+
180
+ ## Development
181
+
182
+ ```bash
183
+ python -m pip install -e . pytest
184
+ python -m pytest -q
185
+ ```
186
+
187
+ ## License and security
188
+
189
+ RunLedger is licensed under the Apache License 2.0; see [LICENSE](LICENSE). To report a security
190
+ problem, email **hello@runledger.site** and do not open a public issue. See [SECURITY.md](SECURITY.md).
191
+
192
+ ---
193
+ RunLedger · [runledger.site](https://runledger.site) · hello@runledger.site
@@ -0,0 +1,164 @@
1
+ # RunLedger
2
+
3
+ **Receipts, cost and a real-time guard for AI coding agents.**
4
+
5
+ RunLedger reads the session logs of your coding agents and turns each run into a receipt: what
6
+ changed, what ran, which model did each step, what it cost, and what looked risky. A Claude Code hook
7
+ can stop risky calls before they run, and a small team server collects receipts from the whole team.
8
+
9
+ Version 0.2.0 (unreleased). Python 3.9 or later, no runtime dependencies.
10
+
11
+ ## Quickstart
12
+
13
+ ```bash
14
+ pip install runledger-ai # or `pip install .` from a clone of this repository
15
+ cd ~/my-project # a folder where you ran a coding agent
16
+ runledger receipt --open # latest session as an HTML receipt, opened in your browser
17
+ ```
18
+
19
+ The receipt is saved as `runledger-<first 8 characters of the session id>.html` in the current folder.
20
+ More in [docs/quickstart.md](docs/quickstart.md).
21
+
22
+ ## What you get
23
+
24
+ - **Receipts** as HTML, Markdown or JSON: files changed with lines added and removed, every step in
25
+ plain language, the model, tokens and estimated cost for each step, and a risk score from 0 to 100
26
+ with the reason for each finding.
27
+ - **Summaries with Claude** (`--ai`), optional. This sends session content to Anthropic. See
28
+ [Privacy](#privacy).
29
+ - **A CI gate:** `runledger receipt --fail-on 60` exits with code 2 when the score is 60 or more.
30
+ - **A real-time guard** for Claude Code. It denies, asks or allows each tool call, and it can route
31
+ "ask" decisions to a person on the team server. See [docs/guard.md](docs/guard.md).
32
+ - **A team server:** a shared dashboard, API keys with roles, an audit log, approvals with Slack and
33
+ webhook notifications, team budgets with alerts, and compliance exports. See
34
+ [docs/enterprise.md](docs/enterprise.md) and [docs/api.md](docs/api.md).
35
+ - **Pull request receipts:** one sticky comment per pull request, updated on every push. See
36
+ [docs/github.md](docs/github.md).
37
+
38
+ ## Supported agents
39
+
40
+ | Agent | `--agent` | Status | Reads sessions from |
41
+ | --- | --- | --- | --- |
42
+ | Claude Code | `claude-code` | Stable | `~/.claude/projects/<project>/` |
43
+ | Codex CLI | `codex` | Beta | `$CODEX_HOME/sessions/` (default `~/.codex`) |
44
+ | Aider | `aider` | Beta | `.aider.chat.history.md` in the project folder |
45
+ | Any agent | `native` | Open format | `<project>/.runledger/runs/` |
46
+
47
+ Any agent can write the RunLedger format and get receipts, risk scores and pushes without an adapter.
48
+ The specification is in [docs/format.md](docs/format.md). Details per agent are in
49
+ [docs/agents.md](docs/agents.md).
50
+
51
+ ## Team server in five steps
52
+
53
+ ```bash
54
+ runledger team create myteam --db runledger.db # 1. create the team; prints its API key once
55
+ runledger serve --db runledger.db # 2. start the server on http://127.0.0.1:8787
56
+ # 3. open http://127.0.0.1:8787/?key=YOUR_KEY once, then use the plain address
57
+ export RUNLEDGER_SERVER=http://127.0.0.1:8787 # 4. on each developer's machine
58
+ export RUNLEDGER_API_KEY=YOUR_KEY
59
+ runledger push --user "ana@example.com" # 5. push the latest run
60
+ ```
61
+
62
+ For a shared server, serve it over HTTPS: [docs/self-hosting.md](docs/self-hosting.md) has a Docker
63
+ Compose setup with automatic certificates and a bare-metal setup behind nginx.
64
+ [docs/enterprise.md](docs/enterprise.md) covers roles, key rotation and the audit log.
65
+
66
+ ## Real-time guard in three commands
67
+
68
+ ```bash
69
+ runledger guard install # 1. this project: .claude/settings.json
70
+ runledger guard test '{"session_id":"s1","cwd":"/work/my-app","tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' # 2. see a decision
71
+ runledger guard install --global # 3. or every project: ~/.claude/settings.json
72
+ ```
73
+
74
+ By default the guard **denies** a hardcoded secret written into a file and high-severity commands such
75
+ as `rm -rf`, force pushes, `curl | sh`, `DROP TABLE`, `npm publish` and `kubectl apply`. It **asks**
76
+ before `sudo`, reading a `.env` file, writing outside the project, or deleting a test. Everything else
77
+ is allowed. Two settings files control it: your own `~/.runledger/config.json` may set anything, and a
78
+ project's `.runledger.json` may only make the guard stricter. See [docs/guard.md](docs/guard.md).
79
+
80
+ ## GitHub Action
81
+
82
+ Post a receipt on every pull request. Commit the session files you want reviewed to
83
+ `.runledger/sessions/`, then add this workflow:
84
+
85
+ ```yaml
86
+ name: RunLedger receipt
87
+ on: pull_request
88
+ permissions:
89
+ contents: read
90
+ pull-requests: write
91
+ jobs:
92
+ receipt:
93
+ runs-on: ubuntu-latest
94
+ steps:
95
+ - uses: actions/checkout@v4
96
+ - uses: kodji7202-code/runledger@v0.2.0
97
+ with:
98
+ fail-on: "60" # the job fails at 60 or above; "" never fails
99
+ ```
100
+
101
+ Details, inputs and the exit codes are in [docs/github.md](docs/github.md).
102
+
103
+ ## Privacy
104
+
105
+ RunLedger is local first. `receipt`, `list` and the guard run on your machine. RunLedger has no
106
+ telemetry. The network calls it makes are the ones you ask for: pushing to your team server, the
107
+ guard's approval requests to the server you configure, webhooks you set, the GitHub API in the
108
+ action, and the Anthropic API only when you use `--ai`.
109
+
110
+ What a receipt contains:
111
+
112
+ - the prompts (the first three, in full, in the JSON receipt);
113
+ - each step: the first line of a command (up to 120 characters), file paths and line counts, search
114
+ patterns and URLs, and the step's model, tokens and cost;
115
+ - the risk findings and their reasons.
116
+
117
+ A receipt does **not** contain file contents or command output (only test pass and fail counts).
118
+ **Receipts are not redacted**: a token typed into a command line appears in the receipt. Treat a receipt
119
+ like the session transcript it came from.
120
+
121
+ - **`--ai`** sends the prompts, each step's inputs (up to 600 characters per field, which can include
122
+ file contents being written), each tool result (up to 400 characters) and the agent's final message to
123
+ `api.anthropic.com`. Do not use it on sessions you may not share with that service.
124
+ - **The guard log** (`.runledger/guard.log`) records tool names, commands and paths. It masks known
125
+ token formats and quoted secret values, but **not** unquoted ones such as `API_KEY=...`. Add
126
+ `.runledger/` to your `.gitignore`.
127
+ - **The team server** stores every pushed receipt, including its HTML, in one SQLite file. Anyone with a
128
+ team key can read all of that team's runs. Keys are stored only as hashes. Nothing is deleted
129
+ automatically.
130
+
131
+ ## Pricing
132
+
133
+ Cost figures are estimates from the public Claude API list prices. A subscription is not billed per token,
134
+ so read them as "what this run would cost on the API".
135
+
136
+ Plans: Free, Team at $15 per developer per month, and Enterprise. Details at
137
+ [runledger.site](https://runledger.site).
138
+
139
+ ## Documentation
140
+
141
+ - [Quickstart](docs/quickstart.md): install, first receipt, summaries, CI, hooks, a local team server
142
+ - [Supported agents](docs/agents.md): where each agent's sessions are, and `--agent`
143
+ - [Session format](docs/format.md): the open format for any agent
144
+ - [Real-time guard](docs/guard.md): policy files, approvals, fail-open and fail-closed, the log
145
+ - [Enterprise guide](docs/enterprise.md): roles, API keys, audit, budgets, exports, HTTPS
146
+ - [HTTP API](docs/api.md): every endpoint, with examples and error codes
147
+ - [Self-hosting](docs/self-hosting.md): Docker Compose, bare metal, backups, upgrades
148
+ - [GitHub pull requests](docs/github.md): the action and the comment format
149
+ - [Contributing](CONTRIBUTING.md)
150
+
151
+ ## Development
152
+
153
+ ```bash
154
+ python -m pip install -e . pytest
155
+ python -m pytest -q
156
+ ```
157
+
158
+ ## License and security
159
+
160
+ RunLedger is licensed under the Apache License 2.0; see [LICENSE](LICENSE). To report a security
161
+ problem, email **hello@runledger.site** and do not open a public issue. See [SECURITY.md](SECURITY.md).
162
+
163
+ ---
164
+ RunLedger · [runledger.site](https://runledger.site) · hello@runledger.site
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ # setuptools 77 is the first release that accepts the SPDX `license` string (PEP 639).
3
+ requires = ["setuptools>=77"]
4
+ build-backend = "setuptools.build_meta"
5
+
6
+ [project]
7
+ name = "runledger-ai"
8
+ version = "0.2.0"
9
+ description = "A black box recorder for AI coding agents: turn Claude Code runs into shareable receipts."
10
+ readme = "README.md"
11
+ license = "Apache-2.0"
12
+ license-files = ["LICENSE"]
13
+ requires-python = ">=3.9"
14
+ authors = [{ name = "RunLedger", email = "hello@runledger.site" }]
15
+ keywords = ["ai", "coding-agents", "claude-code", "codex", "aider", "audit", "receipts", "guardrails", "observability"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: Software Development",
29
+ "Topic :: Software Development :: Quality Assurance",
30
+ ]
31
+ dependencies = []
32
+
33
+ [project.urls]
34
+ Homepage = "https://runledger.site"
35
+ Source = "https://github.com/kodji7202-code/runledger"
36
+ Issues = "https://github.com/kodji7202-code/runledger/issues"
37
+ Documentation = "https://github.com/kodji7202-code/runledger/tree/main/docs"
38
+
39
+ [project.scripts]
40
+ runledger = "runledger.cli:main"
41
+
42
+ [tool.setuptools]
43
+ packages = ["runledger", "runledger.server", "runledger.adapters"]
44
+
45
+ [tool.setuptools.package-data]
46
+ runledger = ["prices.json"]
@@ -0,0 +1,2 @@
1
+ """RunLedger: a black box recorder for AI coding agents."""
2
+ __version__ = "0.2.0"
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())