clockwork-cli 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.
- clockwork_cli-0.1.0/LICENSE +21 -0
- clockwork_cli-0.1.0/PKG-INFO +272 -0
- clockwork_cli-0.1.0/README.md +254 -0
- clockwork_cli-0.1.0/pyproject.toml +30 -0
- clockwork_cli-0.1.0/setup.cfg +4 -0
- clockwork_cli-0.1.0/src/clockwork_cli/__init__.py +930 -0
- clockwork_cli-0.1.0/src/clockwork_cli/__main__.py +3 -0
- clockwork_cli-0.1.0/src/clockwork_cli.egg-info/PKG-INFO +272 -0
- clockwork_cli-0.1.0/src/clockwork_cli.egg-info/SOURCES.txt +10 -0
- clockwork_cli-0.1.0/src/clockwork_cli.egg-info/dependency_links.txt +1 -0
- clockwork_cli-0.1.0/src/clockwork_cli.egg-info/entry_points.txt +2 -0
- clockwork_cli-0.1.0/src/clockwork_cli.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Sich
|
|
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,272 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: clockwork-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Mine your Claude Code and Codex session logs to estimate active time
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/danielsich/clockwork
|
|
7
|
+
Project-URL: Repository, https://github.com/danielsich/clockwork
|
|
8
|
+
Keywords: claude,codex,productivity,time-tracking,cli
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Topic :: Utilities
|
|
14
|
+
Requires-Python: >=3.7
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# clockwork
|
|
20
|
+
|
|
21
|
+
A tiny, dependency-free CLI that mines your **Claude Code** and **Codex**
|
|
22
|
+
session logs to estimate how much *active* time you've actually spent — per
|
|
23
|
+
project, per day — and renders it as ASCII bar charts in your terminal.
|
|
24
|
+
|
|
25
|
+
No config, no database, no telemetry. Just Python 3 and the log files those
|
|
26
|
+
tools already write to your machine.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
====================================================
|
|
30
|
+
CLOCKWORK — CLAUDE SESSION ANALYSIS
|
|
31
|
+
====================================================
|
|
32
|
+
Project : ~/dev/clockwork
|
|
33
|
+
First : 2026-06-28 09:12
|
|
34
|
+
Last : 2026-07-05 23:34
|
|
35
|
+
Span : 8 calendar days
|
|
36
|
+
Prompts : 214 total
|
|
37
|
+
Sessions: 19 (idle threshold: 30 min)
|
|
38
|
+
Active : 6 days
|
|
39
|
+
Total : 11h 42m
|
|
40
|
+
====================================================
|
|
41
|
+
|
|
42
|
+
DATE ACTIVE TIME PROMPTS BAR
|
|
43
|
+
----------------------------------------------------
|
|
44
|
+
2026-06-28 2h 05m 38 ████████████████████
|
|
45
|
+
2026-06-29 1h 12m 21 ███████████
|
|
46
|
+
2026-07-01 0h 48m 14 ███████
|
|
47
|
+
...
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## How it works
|
|
51
|
+
|
|
52
|
+
`clockwork` reads the JSONL transcripts each tool writes, extracts the
|
|
53
|
+
timestamps of your **prompts** (not the assistant's replies), and groups them
|
|
54
|
+
into sessions. Any gap longer than the *idle threshold* (default 30 minutes)
|
|
55
|
+
starts a new session. A session's duration is the time from its first to its
|
|
56
|
+
last prompt, split across calendar-day boundaries so a session that crosses
|
|
57
|
+
midnight is credited to each day it spans.
|
|
58
|
+
|
|
59
|
+
**Data sources**
|
|
60
|
+
|
|
61
|
+
| Provider | Location |
|
|
62
|
+
| -------- | -------- |
|
|
63
|
+
| `claude` | `~/.claude/projects/<encoded-path>/*.jsonl` (macOS/Linux)<br>`%APPDATA%\Claude\projects\<encoded-path>\*.jsonl` (Windows) |
|
|
64
|
+
| `codex` | `$CODEX_HOME/sessions/**/rollout-*.jsonl` (default `~/.codex/sessions`) |
|
|
65
|
+
| `both` | merges the two sources per project |
|
|
66
|
+
|
|
67
|
+
> **Note:** "active time" is a proxy. It measures time *within* sessions, so
|
|
68
|
+
> thinking and response time between prompts counts as active, and a session
|
|
69
|
+
> with a single prompt is floored to one minute. Treat the totals as a
|
|
70
|
+
> reasonable estimate, not a stopwatch.
|
|
71
|
+
|
|
72
|
+
> **`both` and path matching:** `both` combines Claude and Codex prompts by
|
|
73
|
+
> project path. Single-project mode (`clockwork both ~/dev/x`) is exact,
|
|
74
|
+
> because it encodes the path you pass. In `all` / `export` / `list`, projects
|
|
75
|
+
> are matched by their displayed path — and Claude stores paths dash-encoded,
|
|
76
|
+
> so one containing spaces or dashes can't always be reversed to match Codex's
|
|
77
|
+
> real path. Such a project may appear as two rows rather than merging.
|
|
78
|
+
|
|
79
|
+
## Requirements
|
|
80
|
+
|
|
81
|
+
- Python 3.7+ (standard library only — no `pip install` needed)
|
|
82
|
+
|
|
83
|
+
## Install
|
|
84
|
+
|
|
85
|
+
**macOS / Linux**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://github.com/danielsich/clockwork.git
|
|
89
|
+
cd clockwork
|
|
90
|
+
chmod +x clockwork
|
|
91
|
+
|
|
92
|
+
# option A: symlink into a directory already on your PATH
|
|
93
|
+
ln -s "$PWD/clockwork" ~/.local/bin/clockwork
|
|
94
|
+
|
|
95
|
+
# option B: just run it directly
|
|
96
|
+
./clockwork claude all
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Windows**
|
|
100
|
+
|
|
101
|
+
```powershell
|
|
102
|
+
git clone https://github.com/danielsich/clockwork.git
|
|
103
|
+
cd clockwork
|
|
104
|
+
|
|
105
|
+
# Run directly with Python (the shebang line is ignored on Windows)
|
|
106
|
+
python clockwork claude all
|
|
107
|
+
|
|
108
|
+
# Or add the directory to your PATH and invoke as:
|
|
109
|
+
python -m clockwork claude all # not needed — just call the script
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
> clockwork looks for Claude logs in `%APPDATA%\Claude\projects` first, then
|
|
113
|
+
> `~\.claude\projects`. One of those will already exist if you have Claude Code
|
|
114
|
+
> installed.
|
|
115
|
+
|
|
116
|
+
## Usage
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
clockwork <provider> <project-path> [idle-min] [options] Analyze one project
|
|
120
|
+
clockwork <provider> all [idle-min] [options] Rank all projects
|
|
121
|
+
clockwork <provider> today [idle-min] [options] Today, all projects
|
|
122
|
+
clockwork <provider> week [idle-min] [options] Last 7 days, all projects
|
|
123
|
+
clockwork <provider> export [idle-min] [options] Bundle all projects as JSON
|
|
124
|
+
clockwork <provider> list [options] List project folders
|
|
125
|
+
|
|
126
|
+
<provider> is one of: claude | codex | both
|
|
127
|
+
|
|
128
|
+
Options:
|
|
129
|
+
--json Emit machine-readable JSON instead of ASCII tables
|
|
130
|
+
--since <when> Only count prompts on/after this point in time
|
|
131
|
+
--until <when> Only count prompts on/before this point in time
|
|
132
|
+
<when> is YYYY-MM-DD, an ISO timestamp, or a relative
|
|
133
|
+
form like 7d (7 days ago) or 2w (2 weeks ago)
|
|
134
|
+
--detail <level> export granularity: raw | sessions | daily (default raw)
|
|
135
|
+
--anonymize export: replace project paths with a hash id + generic name
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Examples
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Time spent on a single project (Claude Code)
|
|
142
|
+
clockwork claude ~/dev/myproject
|
|
143
|
+
|
|
144
|
+
# Same, but treat gaps under 45 min as the same session (Codex)
|
|
145
|
+
clockwork codex ~/dev/myproject 45
|
|
146
|
+
|
|
147
|
+
# Both tools at once — combined time on one project, or ranked across all
|
|
148
|
+
clockwork both ~/dev/myproject
|
|
149
|
+
clockwork both today
|
|
150
|
+
|
|
151
|
+
# Rank every project you've worked on, most time first
|
|
152
|
+
clockwork codex all
|
|
153
|
+
|
|
154
|
+
# List the projects clockwork can see
|
|
155
|
+
clockwork claude list
|
|
156
|
+
|
|
157
|
+
# Daily check-in: everything you did today, across all projects
|
|
158
|
+
clockwork claude today
|
|
159
|
+
|
|
160
|
+
# Your week at a glance (per-project + a day-by-day breakdown)
|
|
161
|
+
clockwork codex week
|
|
162
|
+
|
|
163
|
+
# Only the last 7 days, across all projects
|
|
164
|
+
clockwork claude all --since 7d
|
|
165
|
+
|
|
166
|
+
# A specific date range for one project
|
|
167
|
+
clockwork claude ~/dev/myproject --since 2026-07-01 --until 2026-07-05
|
|
168
|
+
|
|
169
|
+
# Machine-readable output — pipe into jq, a spreadsheet, or a dashboard
|
|
170
|
+
clockwork codex all --json | jq '.projects[] | {project, minutes}'
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The optional trailing number overrides the idle threshold in minutes
|
|
174
|
+
(default `30`). A larger threshold merges short breaks into one session; a
|
|
175
|
+
smaller one splits work into more, shorter sessions.
|
|
176
|
+
|
|
177
|
+
### Daily & weekly summaries
|
|
178
|
+
|
|
179
|
+
`today` and `week` aggregate **every** project into a single check-in instead
|
|
180
|
+
of analyzing one at a time. `today` covers local midnight to now; `week` is a
|
|
181
|
+
rolling 7-day window ending today. Both show a per-project breakdown, and
|
|
182
|
+
`week` adds a day-by-day view so you can see your week at a glance. Day
|
|
183
|
+
boundaries are **local time**, so "today" means your calendar day, not UTC's.
|
|
184
|
+
They honor the optional `idle-min` and pair with `--json`.
|
|
185
|
+
|
|
186
|
+
### Filtering by date
|
|
187
|
+
|
|
188
|
+
`--since` and `--until` restrict which prompts are counted. Each accepts a
|
|
189
|
+
bare date (`2026-07-01`), a full ISO timestamp, or a relative form — `7d`
|
|
190
|
+
(7 days ago) or `2w` (2 weeks ago). A bare `--until` date is inclusive of the
|
|
191
|
+
whole day. This works in every mode (`<project>`, `all`, and `list`-adjacent
|
|
192
|
+
analysis).
|
|
193
|
+
|
|
194
|
+
### JSON output
|
|
195
|
+
|
|
196
|
+
`--json` swaps the ASCII tables for structured JSON on stdout (errors and
|
|
197
|
+
usage still go to stderr), so clockwork composes with `jq`, cron jobs, or any
|
|
198
|
+
dashboard. Exit codes are script-friendly: `0` on success, `1` when nothing
|
|
199
|
+
matched, `2` for bad arguments.
|
|
200
|
+
|
|
201
|
+
## Exporting for external tools
|
|
202
|
+
|
|
203
|
+
`clockwork <provider> export` writes a single **self-describing, versioned**
|
|
204
|
+
JSON bundle covering every project at once — the format a companion web app or
|
|
205
|
+
dashboard would ingest. Unlike `--json` on the analysis commands (which emits
|
|
206
|
+
one pre-aggregated view), the export is designed to be re-analyzed downstream.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Full-fidelity export you can re-analyze anywhere
|
|
210
|
+
clockwork claude export > clockwork.json
|
|
211
|
+
|
|
212
|
+
# Smaller / shareable: grouped sessions only, with paths stripped
|
|
213
|
+
clockwork codex export --detail sessions --anonymize > share.json
|
|
214
|
+
|
|
215
|
+
# Export honors --since/--until too
|
|
216
|
+
clockwork claude export --since 30d > last-month.json
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Detail levels** (`--detail`, default `raw`). Each level is a superset of the
|
|
220
|
+
one below, so a consumer can start with the aggregates and drill down:
|
|
221
|
+
|
|
222
|
+
| Level | Adds | Lets a consumer… |
|
|
223
|
+
| ----- | ---- | ---------------- |
|
|
224
|
+
| `daily` | per-day `minutes` / `prompts` | draw timelines and totals |
|
|
225
|
+
| `sessions` | grouped `sessions` (start/end + prompt count) | re-bucket by timezone / date range |
|
|
226
|
+
| `raw` | every prompt as an epoch-second timestamp | re-apply **any** idle threshold, build hour-of-day heatmaps, streaks — anything |
|
|
227
|
+
|
|
228
|
+
**Privacy.** Paths are included by default (it's your own data). `--anonymize`
|
|
229
|
+
drops the `path`, renames projects to `project-N`, and keeps only a stable
|
|
230
|
+
hash `id` — so an uploaded file leaks nothing identifying while still letting a
|
|
231
|
+
tool tell projects apart across exports.
|
|
232
|
+
|
|
233
|
+
### Export schema (`clockwork/v1`)
|
|
234
|
+
|
|
235
|
+
```jsonc
|
|
236
|
+
{
|
|
237
|
+
"schema": "clockwork/v1",
|
|
238
|
+
"generated_at": "2026-07-06T00:30:00+02:00", // local ISO-8601
|
|
239
|
+
"provider": "claude",
|
|
240
|
+
"idle_threshold_min": 30,
|
|
241
|
+
"detail": "raw", // raw | sessions | daily
|
|
242
|
+
"anonymized": false,
|
|
243
|
+
"daily_tz": "UTC", // the "daily" buckets use UTC calendar dates
|
|
244
|
+
"since": null, // ISO bound if --since was given, else null
|
|
245
|
+
"until": null,
|
|
246
|
+
"projects": [
|
|
247
|
+
{
|
|
248
|
+
"id": "0ac6be84", // stable sha1(path) prefix; survives --anonymize
|
|
249
|
+
"name": "myproject", // basename, or "project-N" when anonymized
|
|
250
|
+
"path": "/Users/you/dev/myproject", // omitted when anonymized
|
|
251
|
+
"totals": {
|
|
252
|
+
"minutes": 1234.76, "prompts": 1646, "sessions": 27,
|
|
253
|
+
"active_days": 12,
|
|
254
|
+
"first": 1780521570, "last": 1782130426 // epoch seconds
|
|
255
|
+
},
|
|
256
|
+
"daily": [ { "date": "2026-06-03", "minutes": 4.34, "prompts": 27 } ],
|
|
257
|
+
"sessions": [ { "start": 1780521570, "end": 1780521830,
|
|
258
|
+
"minutes": 4.34, "prompts": 27 } ], // detail >= sessions
|
|
259
|
+
"prompts": [ 1780521570, 1780521582 ] // detail == raw
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
"totals": { "projects": 6, "minutes": 3392.97, "prompts": 4588, "sessions": 64 }
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
All instants are **UTC-based epoch seconds** (`new Date(sec * 1000)` in JS), so
|
|
267
|
+
the consumer picks the display timezone. The `schema` field is the version
|
|
268
|
+
contract — bump it if the shape ever changes so tools can guard on it.
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
[MIT](LICENSE) © 2026 Daniel Sich
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# clockwork
|
|
2
|
+
|
|
3
|
+
A tiny, dependency-free CLI that mines your **Claude Code** and **Codex**
|
|
4
|
+
session logs to estimate how much *active* time you've actually spent — per
|
|
5
|
+
project, per day — and renders it as ASCII bar charts in your terminal.
|
|
6
|
+
|
|
7
|
+
No config, no database, no telemetry. Just Python 3 and the log files those
|
|
8
|
+
tools already write to your machine.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
====================================================
|
|
12
|
+
CLOCKWORK — CLAUDE SESSION ANALYSIS
|
|
13
|
+
====================================================
|
|
14
|
+
Project : ~/dev/clockwork
|
|
15
|
+
First : 2026-06-28 09:12
|
|
16
|
+
Last : 2026-07-05 23:34
|
|
17
|
+
Span : 8 calendar days
|
|
18
|
+
Prompts : 214 total
|
|
19
|
+
Sessions: 19 (idle threshold: 30 min)
|
|
20
|
+
Active : 6 days
|
|
21
|
+
Total : 11h 42m
|
|
22
|
+
====================================================
|
|
23
|
+
|
|
24
|
+
DATE ACTIVE TIME PROMPTS BAR
|
|
25
|
+
----------------------------------------------------
|
|
26
|
+
2026-06-28 2h 05m 38 ████████████████████
|
|
27
|
+
2026-06-29 1h 12m 21 ███████████
|
|
28
|
+
2026-07-01 0h 48m 14 ███████
|
|
29
|
+
...
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## How it works
|
|
33
|
+
|
|
34
|
+
`clockwork` reads the JSONL transcripts each tool writes, extracts the
|
|
35
|
+
timestamps of your **prompts** (not the assistant's replies), and groups them
|
|
36
|
+
into sessions. Any gap longer than the *idle threshold* (default 30 minutes)
|
|
37
|
+
starts a new session. A session's duration is the time from its first to its
|
|
38
|
+
last prompt, split across calendar-day boundaries so a session that crosses
|
|
39
|
+
midnight is credited to each day it spans.
|
|
40
|
+
|
|
41
|
+
**Data sources**
|
|
42
|
+
|
|
43
|
+
| Provider | Location |
|
|
44
|
+
| -------- | -------- |
|
|
45
|
+
| `claude` | `~/.claude/projects/<encoded-path>/*.jsonl` (macOS/Linux)<br>`%APPDATA%\Claude\projects\<encoded-path>\*.jsonl` (Windows) |
|
|
46
|
+
| `codex` | `$CODEX_HOME/sessions/**/rollout-*.jsonl` (default `~/.codex/sessions`) |
|
|
47
|
+
| `both` | merges the two sources per project |
|
|
48
|
+
|
|
49
|
+
> **Note:** "active time" is a proxy. It measures time *within* sessions, so
|
|
50
|
+
> thinking and response time between prompts counts as active, and a session
|
|
51
|
+
> with a single prompt is floored to one minute. Treat the totals as a
|
|
52
|
+
> reasonable estimate, not a stopwatch.
|
|
53
|
+
|
|
54
|
+
> **`both` and path matching:** `both` combines Claude and Codex prompts by
|
|
55
|
+
> project path. Single-project mode (`clockwork both ~/dev/x`) is exact,
|
|
56
|
+
> because it encodes the path you pass. In `all` / `export` / `list`, projects
|
|
57
|
+
> are matched by their displayed path — and Claude stores paths dash-encoded,
|
|
58
|
+
> so one containing spaces or dashes can't always be reversed to match Codex's
|
|
59
|
+
> real path. Such a project may appear as two rows rather than merging.
|
|
60
|
+
|
|
61
|
+
## Requirements
|
|
62
|
+
|
|
63
|
+
- Python 3.7+ (standard library only — no `pip install` needed)
|
|
64
|
+
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
**macOS / Linux**
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git clone https://github.com/danielsich/clockwork.git
|
|
71
|
+
cd clockwork
|
|
72
|
+
chmod +x clockwork
|
|
73
|
+
|
|
74
|
+
# option A: symlink into a directory already on your PATH
|
|
75
|
+
ln -s "$PWD/clockwork" ~/.local/bin/clockwork
|
|
76
|
+
|
|
77
|
+
# option B: just run it directly
|
|
78
|
+
./clockwork claude all
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Windows**
|
|
82
|
+
|
|
83
|
+
```powershell
|
|
84
|
+
git clone https://github.com/danielsich/clockwork.git
|
|
85
|
+
cd clockwork
|
|
86
|
+
|
|
87
|
+
# Run directly with Python (the shebang line is ignored on Windows)
|
|
88
|
+
python clockwork claude all
|
|
89
|
+
|
|
90
|
+
# Or add the directory to your PATH and invoke as:
|
|
91
|
+
python -m clockwork claude all # not needed — just call the script
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
> clockwork looks for Claude logs in `%APPDATA%\Claude\projects` first, then
|
|
95
|
+
> `~\.claude\projects`. One of those will already exist if you have Claude Code
|
|
96
|
+
> installed.
|
|
97
|
+
|
|
98
|
+
## Usage
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
clockwork <provider> <project-path> [idle-min] [options] Analyze one project
|
|
102
|
+
clockwork <provider> all [idle-min] [options] Rank all projects
|
|
103
|
+
clockwork <provider> today [idle-min] [options] Today, all projects
|
|
104
|
+
clockwork <provider> week [idle-min] [options] Last 7 days, all projects
|
|
105
|
+
clockwork <provider> export [idle-min] [options] Bundle all projects as JSON
|
|
106
|
+
clockwork <provider> list [options] List project folders
|
|
107
|
+
|
|
108
|
+
<provider> is one of: claude | codex | both
|
|
109
|
+
|
|
110
|
+
Options:
|
|
111
|
+
--json Emit machine-readable JSON instead of ASCII tables
|
|
112
|
+
--since <when> Only count prompts on/after this point in time
|
|
113
|
+
--until <when> Only count prompts on/before this point in time
|
|
114
|
+
<when> is YYYY-MM-DD, an ISO timestamp, or a relative
|
|
115
|
+
form like 7d (7 days ago) or 2w (2 weeks ago)
|
|
116
|
+
--detail <level> export granularity: raw | sessions | daily (default raw)
|
|
117
|
+
--anonymize export: replace project paths with a hash id + generic name
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Examples
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Time spent on a single project (Claude Code)
|
|
124
|
+
clockwork claude ~/dev/myproject
|
|
125
|
+
|
|
126
|
+
# Same, but treat gaps under 45 min as the same session (Codex)
|
|
127
|
+
clockwork codex ~/dev/myproject 45
|
|
128
|
+
|
|
129
|
+
# Both tools at once — combined time on one project, or ranked across all
|
|
130
|
+
clockwork both ~/dev/myproject
|
|
131
|
+
clockwork both today
|
|
132
|
+
|
|
133
|
+
# Rank every project you've worked on, most time first
|
|
134
|
+
clockwork codex all
|
|
135
|
+
|
|
136
|
+
# List the projects clockwork can see
|
|
137
|
+
clockwork claude list
|
|
138
|
+
|
|
139
|
+
# Daily check-in: everything you did today, across all projects
|
|
140
|
+
clockwork claude today
|
|
141
|
+
|
|
142
|
+
# Your week at a glance (per-project + a day-by-day breakdown)
|
|
143
|
+
clockwork codex week
|
|
144
|
+
|
|
145
|
+
# Only the last 7 days, across all projects
|
|
146
|
+
clockwork claude all --since 7d
|
|
147
|
+
|
|
148
|
+
# A specific date range for one project
|
|
149
|
+
clockwork claude ~/dev/myproject --since 2026-07-01 --until 2026-07-05
|
|
150
|
+
|
|
151
|
+
# Machine-readable output — pipe into jq, a spreadsheet, or a dashboard
|
|
152
|
+
clockwork codex all --json | jq '.projects[] | {project, minutes}'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The optional trailing number overrides the idle threshold in minutes
|
|
156
|
+
(default `30`). A larger threshold merges short breaks into one session; a
|
|
157
|
+
smaller one splits work into more, shorter sessions.
|
|
158
|
+
|
|
159
|
+
### Daily & weekly summaries
|
|
160
|
+
|
|
161
|
+
`today` and `week` aggregate **every** project into a single check-in instead
|
|
162
|
+
of analyzing one at a time. `today` covers local midnight to now; `week` is a
|
|
163
|
+
rolling 7-day window ending today. Both show a per-project breakdown, and
|
|
164
|
+
`week` adds a day-by-day view so you can see your week at a glance. Day
|
|
165
|
+
boundaries are **local time**, so "today" means your calendar day, not UTC's.
|
|
166
|
+
They honor the optional `idle-min` and pair with `--json`.
|
|
167
|
+
|
|
168
|
+
### Filtering by date
|
|
169
|
+
|
|
170
|
+
`--since` and `--until` restrict which prompts are counted. Each accepts a
|
|
171
|
+
bare date (`2026-07-01`), a full ISO timestamp, or a relative form — `7d`
|
|
172
|
+
(7 days ago) or `2w` (2 weeks ago). A bare `--until` date is inclusive of the
|
|
173
|
+
whole day. This works in every mode (`<project>`, `all`, and `list`-adjacent
|
|
174
|
+
analysis).
|
|
175
|
+
|
|
176
|
+
### JSON output
|
|
177
|
+
|
|
178
|
+
`--json` swaps the ASCII tables for structured JSON on stdout (errors and
|
|
179
|
+
usage still go to stderr), so clockwork composes with `jq`, cron jobs, or any
|
|
180
|
+
dashboard. Exit codes are script-friendly: `0` on success, `1` when nothing
|
|
181
|
+
matched, `2` for bad arguments.
|
|
182
|
+
|
|
183
|
+
## Exporting for external tools
|
|
184
|
+
|
|
185
|
+
`clockwork <provider> export` writes a single **self-describing, versioned**
|
|
186
|
+
JSON bundle covering every project at once — the format a companion web app or
|
|
187
|
+
dashboard would ingest. Unlike `--json` on the analysis commands (which emits
|
|
188
|
+
one pre-aggregated view), the export is designed to be re-analyzed downstream.
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Full-fidelity export you can re-analyze anywhere
|
|
192
|
+
clockwork claude export > clockwork.json
|
|
193
|
+
|
|
194
|
+
# Smaller / shareable: grouped sessions only, with paths stripped
|
|
195
|
+
clockwork codex export --detail sessions --anonymize > share.json
|
|
196
|
+
|
|
197
|
+
# Export honors --since/--until too
|
|
198
|
+
clockwork claude export --since 30d > last-month.json
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Detail levels** (`--detail`, default `raw`). Each level is a superset of the
|
|
202
|
+
one below, so a consumer can start with the aggregates and drill down:
|
|
203
|
+
|
|
204
|
+
| Level | Adds | Lets a consumer… |
|
|
205
|
+
| ----- | ---- | ---------------- |
|
|
206
|
+
| `daily` | per-day `minutes` / `prompts` | draw timelines and totals |
|
|
207
|
+
| `sessions` | grouped `sessions` (start/end + prompt count) | re-bucket by timezone / date range |
|
|
208
|
+
| `raw` | every prompt as an epoch-second timestamp | re-apply **any** idle threshold, build hour-of-day heatmaps, streaks — anything |
|
|
209
|
+
|
|
210
|
+
**Privacy.** Paths are included by default (it's your own data). `--anonymize`
|
|
211
|
+
drops the `path`, renames projects to `project-N`, and keeps only a stable
|
|
212
|
+
hash `id` — so an uploaded file leaks nothing identifying while still letting a
|
|
213
|
+
tool tell projects apart across exports.
|
|
214
|
+
|
|
215
|
+
### Export schema (`clockwork/v1`)
|
|
216
|
+
|
|
217
|
+
```jsonc
|
|
218
|
+
{
|
|
219
|
+
"schema": "clockwork/v1",
|
|
220
|
+
"generated_at": "2026-07-06T00:30:00+02:00", // local ISO-8601
|
|
221
|
+
"provider": "claude",
|
|
222
|
+
"idle_threshold_min": 30,
|
|
223
|
+
"detail": "raw", // raw | sessions | daily
|
|
224
|
+
"anonymized": false,
|
|
225
|
+
"daily_tz": "UTC", // the "daily" buckets use UTC calendar dates
|
|
226
|
+
"since": null, // ISO bound if --since was given, else null
|
|
227
|
+
"until": null,
|
|
228
|
+
"projects": [
|
|
229
|
+
{
|
|
230
|
+
"id": "0ac6be84", // stable sha1(path) prefix; survives --anonymize
|
|
231
|
+
"name": "myproject", // basename, or "project-N" when anonymized
|
|
232
|
+
"path": "/Users/you/dev/myproject", // omitted when anonymized
|
|
233
|
+
"totals": {
|
|
234
|
+
"minutes": 1234.76, "prompts": 1646, "sessions": 27,
|
|
235
|
+
"active_days": 12,
|
|
236
|
+
"first": 1780521570, "last": 1782130426 // epoch seconds
|
|
237
|
+
},
|
|
238
|
+
"daily": [ { "date": "2026-06-03", "minutes": 4.34, "prompts": 27 } ],
|
|
239
|
+
"sessions": [ { "start": 1780521570, "end": 1780521830,
|
|
240
|
+
"minutes": 4.34, "prompts": 27 } ], // detail >= sessions
|
|
241
|
+
"prompts": [ 1780521570, 1780521582 ] // detail == raw
|
|
242
|
+
}
|
|
243
|
+
],
|
|
244
|
+
"totals": { "projects": 6, "minutes": 3392.97, "prompts": 4588, "sessions": 64 }
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
All instants are **UTC-based epoch seconds** (`new Date(sec * 1000)` in JS), so
|
|
249
|
+
the consumer picks the display timezone. The `schema` field is the version
|
|
250
|
+
contract — bump it if the shape ever changes so tools can guard on it.
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
[MIT](LICENSE) © 2026 Daniel Sich
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "clockwork-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Mine your Claude Code and Codex session logs to estimate active time"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.7"
|
|
13
|
+
keywords = ["claude", "codex", "productivity", "time-tracking", "cli"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Topic :: Utilities",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.urls]
|
|
23
|
+
Homepage = "https://github.com/danielsich/clockwork"
|
|
24
|
+
Repository = "https://github.com/danielsich/clockwork"
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
clockwork = "clockwork_cli:main"
|
|
28
|
+
|
|
29
|
+
[tool.setuptools.packages.find]
|
|
30
|
+
where = ["src"]
|