clawck 0.4.3 → 0.5.2

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 (77) hide show
  1. package/README.md +81 -9
  2. package/dist/cli/index.js +29 -44
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/core/atp.d.ts +1 -1
  5. package/dist/core/atp.d.ts.map +1 -1
  6. package/dist/core/atp.js +1 -1
  7. package/dist/core/atp.js.map +1 -1
  8. package/dist/core/clawck.d.ts.map +1 -1
  9. package/dist/core/clawck.js +14 -0
  10. package/dist/core/clawck.js.map +1 -1
  11. package/dist/core/config.d.ts +10 -0
  12. package/dist/core/config.d.ts.map +1 -0
  13. package/dist/core/config.js +58 -0
  14. package/dist/core/config.js.map +1 -0
  15. package/dist/core/database.d.ts +13 -0
  16. package/dist/core/database.d.ts.map +1 -1
  17. package/dist/core/database.js +151 -65
  18. package/dist/core/database.js.map +1 -1
  19. package/dist/core/errors.d.ts +19 -0
  20. package/dist/core/errors.d.ts.map +1 -0
  21. package/dist/core/errors.js +40 -0
  22. package/dist/core/errors.js.map +1 -0
  23. package/dist/core/logger.d.ts +14 -0
  24. package/dist/core/logger.d.ts.map +1 -0
  25. package/dist/core/logger.js +39 -0
  26. package/dist/core/logger.js.map +1 -0
  27. package/dist/core/pricing.d.ts +28 -0
  28. package/dist/core/pricing.d.ts.map +1 -0
  29. package/dist/core/pricing.js +48 -0
  30. package/dist/core/pricing.js.map +1 -0
  31. package/dist/core/runtime.d.ts +9 -0
  32. package/dist/core/runtime.d.ts.map +1 -1
  33. package/dist/core/runtime.js +33 -0
  34. package/dist/core/runtime.js.map +1 -1
  35. package/dist/core/sync.d.ts.map +1 -1
  36. package/dist/core/sync.js +3 -0
  37. package/dist/core/sync.js.map +1 -1
  38. package/dist/core/types.d.ts +14 -3
  39. package/dist/core/types.d.ts.map +1 -1
  40. package/dist/core/types.js +1 -1
  41. package/dist/core/types.js.map +1 -1
  42. package/dist/core/webhooks.d.ts.map +1 -1
  43. package/dist/core/webhooks.js +5 -2
  44. package/dist/core/webhooks.js.map +1 -1
  45. package/dist/dashboard/index.js +3 -3
  46. package/dist/hooks/adapters.d.ts.map +1 -1
  47. package/dist/hooks/adapters.js +3 -2
  48. package/dist/hooks/adapters.js.map +1 -1
  49. package/dist/hooks/handler.d.ts.map +1 -1
  50. package/dist/hooks/handler.js +7 -5
  51. package/dist/hooks/handler.js.map +1 -1
  52. package/dist/hooks/types.d.ts +1 -0
  53. package/dist/hooks/types.d.ts.map +1 -1
  54. package/dist/index.d.ts +5 -0
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +12 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/reports/html.d.ts +2 -2
  59. package/dist/reports/html.d.ts.map +1 -1
  60. package/dist/reports/html.js +238 -84
  61. package/dist/reports/html.js.map +1 -1
  62. package/dist/reports/pdf.d.ts.map +1 -1
  63. package/dist/reports/pdf.js +5 -4
  64. package/dist/reports/pdf.js.map +1 -1
  65. package/dist/server/api.d.ts.map +1 -1
  66. package/dist/server/api.js +57 -18
  67. package/dist/server/api.js.map +1 -1
  68. package/dist/server/mcp.d.ts.map +1 -1
  69. package/dist/server/mcp.js +3 -3
  70. package/dist/server/mcp.js.map +1 -1
  71. package/docs/api-reference.md +380 -0
  72. package/docs/deployment.md +140 -0
  73. package/docs/deprecation-policy.md +32 -0
  74. package/docs/migration-guide.md +78 -0
  75. package/docs/security.md +70 -0
  76. package/docs/versioning.md +49 -0
  77. package/package.json +6 -3
@@ -0,0 +1,380 @@
1
+ # API Reference
2
+
3
+ ## Overview
4
+
5
+ - **Base URL:** `http://localhost:3456` (default port, configurable via `--port` or `PORT` env var)
6
+ - **Content-Type:** `application/json` for all request/response bodies
7
+ - **Error format:** `{ "error": "description" }` with appropriate HTTP status code
8
+ - **No API versioning prefix** — endpoints are at `/api/*` directly
9
+
10
+ ---
11
+
12
+ ## Health
13
+
14
+ ### GET /api/health
15
+
16
+ Health check.
17
+
18
+ **Response:** `200 OK`
19
+ ```json
20
+ { "status": "ok", "version": "0.4.3", "spec": "0.2.0" }
21
+ ```
22
+
23
+ ### GET /api/stats
24
+
25
+ Quick database statistics.
26
+
27
+ **Response:** `200 OK`
28
+ ```json
29
+ {
30
+ "total_entries": 150,
31
+ "running": 2,
32
+ "clients": 5,
33
+ "projects": 12,
34
+ "agents": 3
35
+ }
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Time Tracking
41
+
42
+ ### POST /api/start
43
+
44
+ Start tracking a task. Returns the created entry with a generated UUID.
45
+
46
+ **Request body:**
47
+ | Field | Type | Required | Description |
48
+ |-------|------|----------|-------------|
49
+ | task | string | yes | Task description |
50
+ | project | string | no | Project name |
51
+ | client | string | no | Client name |
52
+ | category | string | no | One of: `research`, `content`, `code`, `data_entry`, `design`, `communication`, `analysis`, `testing`, `planning`, `other` |
53
+ | agent | string | no | Agent identifier |
54
+ | model | string | no | LLM model name |
55
+ | tags | string[] | no | Arbitrary tags |
56
+
57
+ **Response:** `201 Created` — full `ClawckEntry` object
58
+
59
+ ### POST /api/stop
60
+
61
+ Stop a running task.
62
+
63
+ **Request body:**
64
+ | Field | Type | Required | Description |
65
+ |-------|------|----------|-------------|
66
+ | id | string | yes | Entry ID |
67
+ | status | string | no | `completed` or `failed` (default: `completed`) |
68
+ | summary | string | no | Summary of work done |
69
+ | tokens_in | number | no | Input tokens consumed |
70
+ | tokens_out | number | no | Output tokens generated |
71
+ | cost_usd | number | no | Estimated cost in USD |
72
+ | tool_calls | number | no | Number of tool calls made |
73
+
74
+ **Response:** `200 OK` — updated `ClawckEntry` object
75
+ **Error:** `404` if entry not found
76
+
77
+ ### POST /api/log
78
+
79
+ Log a completed task retroactively (task already finished, recording it after the fact).
80
+
81
+ **Request body:**
82
+ | Field | Type | Required | Description |
83
+ |-------|------|----------|-------------|
84
+ | task | string | yes | Task description |
85
+ | duration_minutes | number | yes | How long the task took |
86
+ | project | string | no | Project name |
87
+ | client | string | no | Client name |
88
+ | category | string | no | Task category |
89
+ | agent | string | no | Agent identifier |
90
+ | model | string | no | LLM model name |
91
+ | summary | string | no | Summary of work done |
92
+ | tokens_in | number | no | Input tokens consumed |
93
+ | tokens_out | number | no | Output tokens generated |
94
+ | cost_usd | number | no | Estimated cost |
95
+ | tags | string[] | no | Tags |
96
+
97
+ **Response:** `201 Created` — full `ClawckEntry` object
98
+
99
+ ---
100
+
101
+ ## Entries
102
+
103
+ ### GET /api/entries
104
+
105
+ Query entries with filters.
106
+
107
+ **Query parameters:**
108
+ | Param | Type | Description |
109
+ |-------|------|-------------|
110
+ | client | string | Filter by client |
111
+ | project | string | Filter by project |
112
+ | agent | string | Filter by agent |
113
+ | category | string | Filter by category |
114
+ | status | string | Filter by status (`running`, `completed`, `failed`, `paused`) |
115
+ | from | string | Start date (ISO 8601) |
116
+ | to | string | End date (ISO 8601) |
117
+ | limit | number | Max entries (default: 500) |
118
+
119
+ **Response:** `200 OK` — array of `ClawckEntry` objects
120
+
121
+ ### GET /api/entries/:id
122
+
123
+ Get a single entry by ID.
124
+
125
+ **Response:** `200 OK` — `ClawckEntry` object
126
+ **Error:** `404` if not found
127
+
128
+ ### PATCH /api/entries/:id
129
+
130
+ Update fields on an existing entry.
131
+
132
+ **Request body:** Any subset of entry fields (task, project, client, category, status, summary, tokens_in, tokens_out, cost_usd, tool_calls, tags, agent, approved)
133
+
134
+ **Response:** `200 OK` — updated `ClawckEntry` object
135
+ **Error:** `404` if not found
136
+
137
+ ### POST /api/entries/:id/approve
138
+
139
+ Mark an entry as approved.
140
+
141
+ **Response:** `200 OK` — updated `ClawckEntry` object with `approved: true`
142
+ **Error:** `404` if not found
143
+
144
+ ### GET /api/running
145
+
146
+ Get all currently running entries.
147
+
148
+ **Response:** `200 OK` — array of `ClawckEntry` objects with `status: "running"`
149
+
150
+ ---
151
+
152
+ ## Reporting
153
+
154
+ ### GET /api/timesheet
155
+
156
+ Get a timesheet summary for a date range.
157
+
158
+ **Query parameters:**
159
+ | Param | Type | Description |
160
+ |-------|------|-------------|
161
+ | from | string | Start date (ISO 8601, default: 7 days ago) |
162
+ | to | string | End date (ISO 8601, default: now) |
163
+ | client | string | Filter by client |
164
+ | project | string | Filter by project |
165
+ | agent | string | Filter by agent |
166
+
167
+ **Response:** `200 OK` — `TimesheetSummary` object with aggregated stats, breakdowns by client/agent/project/category, and individual rows
168
+
169
+ ### POST /api/reports/generate
170
+
171
+ Generate a report (terminal JSON, HTML, or PDF).
172
+
173
+ **Request body:**
174
+ | Field | Type | Required | Description |
175
+ |-------|------|----------|-------------|
176
+ | period | string | no | `day`, `week`, `month`, `year`, `custom` |
177
+ | from | string | no | Start date (ISO 8601) |
178
+ | to | string | no | End date (ISO 8601) |
179
+ | days | number | no | Number of days back from now |
180
+ | style | string | no | `full`, `short`, `visual`, `text`, `table`, `calendar` (default: `full`) |
181
+ | format | string | no | `terminal`, `html`, `pdf` (default: `terminal`) |
182
+ | filters | object | no | `{ client?, project?, agent? }` |
183
+ | name | string | no | Report name (for saved reports) |
184
+ | save | boolean | no | Whether to save the report to the database |
185
+
186
+ **Response:** `200 OK`
187
+ - For `pdf` format without `save`: raw PDF binary with `Content-Type: application/pdf`
188
+ - Otherwise: `{ "content": "...", "metadata": { ... } }` (plus `"id"` if saved)
189
+
190
+ ### GET /api/reports
191
+
192
+ List saved reports.
193
+
194
+ **Query parameters:**
195
+ | Param | Type | Description |
196
+ |-------|------|-------------|
197
+ | limit | number | Max results (default: 50) |
198
+ | offset | number | Pagination offset (default: 0) |
199
+
200
+ **Response:** `200 OK` — array of `StoredReport` objects (without content)
201
+
202
+ ### GET /api/reports/:id
203
+
204
+ Get a saved report by ID (without content blob).
205
+
206
+ **Response:** `200 OK` — `StoredReport` object
207
+ **Error:** `404` if not found
208
+
209
+ ### DELETE /api/reports/:id
210
+
211
+ Delete a saved report.
212
+
213
+ **Response:** `200 OK` — `{ "ok": true }`
214
+ **Error:** `404` if not found
215
+
216
+ ---
217
+
218
+ ## Baselines
219
+
220
+ ### GET /api/baselines
221
+
222
+ List all personal baselines.
223
+
224
+ **Response:** `200 OK` — array of `PersonalBaseline` objects
225
+
226
+ ### POST /api/baselines
227
+
228
+ Create a personal baseline.
229
+
230
+ **Request body:**
231
+ | Field | Type | Required | Description |
232
+ |-------|------|----------|-------------|
233
+ | category | string | yes | Task category |
234
+ | task_type | string | yes | Task type label |
235
+ | description | string | no | Description |
236
+ | my_minutes | number | yes | Your personal time for this task type |
237
+
238
+ **Response:** `201 Created` — `PersonalBaseline` object
239
+
240
+ ### DELETE /api/baselines/:id
241
+
242
+ Delete a personal baseline.
243
+
244
+ **Response:** `200 OK` — `{ "ok": true }`
245
+ **Error:** `404` if not found
246
+
247
+ ### GET /api/compare/:entryId
248
+
249
+ Compare an entry against industry and personal benchmarks.
250
+
251
+ **Response:** `200 OK` — comparison object with benchmark data
252
+ **Error:** `404` if entry not found
253
+
254
+ ---
255
+
256
+ ## Import/Export
257
+
258
+ ### GET /api/export/atp
259
+
260
+ Export entries as an ATP (Agent Time Protocol) envelope.
261
+
262
+ **Query parameters:**
263
+ | Param | Type | Description |
264
+ |-------|------|-------------|
265
+ | from | string | Start date (default: 7 days ago) |
266
+ | to | string | End date (default: now) |
267
+
268
+ **Response:** `200 OK` — ATP JSON envelope (see `docs/atp-spec-v0.2.md`)
269
+
270
+ ### POST /api/import/atp
271
+
272
+ Import entries from an ATP envelope.
273
+
274
+ **Request body:** ATP JSON envelope
275
+
276
+ **Response:** `200 OK` — `{ "ingested": 10, "total": 12 }`
277
+
278
+ ### POST /api/ingest
279
+
280
+ Bulk import/merge entries. Entries are upserted by UUID — duplicates are updated, new entries are created.
281
+
282
+ **Request body:** Single `ClawckEntry` object or array of entries
283
+
284
+ **Response:** `200 OK` — `{ "ingested": 5, "total": 5 }`
285
+
286
+ ---
287
+
288
+ ## Sync
289
+
290
+ ### GET /api/sync/status
291
+
292
+ Get sync status for configured remote sources.
293
+
294
+ **Response:** `200 OK`
295
+ ```json
296
+ { "enabled": true, "states": [{ "source_name": "...", "last_sync_at": "...", "last_status": "success", "entries_synced": 42 }] }
297
+ ```
298
+
299
+ ### POST /api/sync/trigger
300
+
301
+ Manually trigger a sync from all remote sources.
302
+
303
+ **Response:** `200 OK` — `{ "states": [...] }`
304
+ **Error:** `400` if no remote sources configured
305
+
306
+ ---
307
+
308
+ ## Filter Options
309
+
310
+ ### GET /api/clients
311
+
312
+ List distinct client names.
313
+
314
+ **Response:** `200 OK` — `["acme-corp", "internal"]`
315
+
316
+ ### GET /api/projects
317
+
318
+ List distinct project names.
319
+
320
+ **Response:** `200 OK` — `["website-rebuild", "grant-research"]`
321
+
322
+ ### GET /api/agents
323
+
324
+ List distinct agent identifiers.
325
+
326
+ **Response:** `200 OK` — `["claude-agent", "research-bot"]`
327
+
328
+ ---
329
+
330
+ ## ClawckEntry Object
331
+
332
+ The core data model returned by most endpoints:
333
+
334
+ ```json
335
+ {
336
+ "id": "550e8400-e29b-41d4-a716-446655440000",
337
+ "agent": "research-agent-01",
338
+ "model": "claude-sonnet-4-20250514",
339
+ "client": "acme-corp",
340
+ "project": "grant-research",
341
+ "task": "Research NEA grant opportunities",
342
+ "category": "research",
343
+ "start": "2026-03-08T10:00:00.000Z",
344
+ "end": "2026-03-08T10:05:30.000Z",
345
+ "status": "completed",
346
+ "tokens_in": 25000,
347
+ "tokens_out": 3500,
348
+ "cost_usd": 0.12,
349
+ "tool_calls": 8,
350
+ "summary": "Found 12 matching grants",
351
+ "tags": ["grants", "nea"],
352
+ "source": "mcp",
353
+ "spec_version": "0.2.0",
354
+ "created_at": "2026-03-08T10:00:00.000Z",
355
+ "updated_at": "2026-03-08T10:05:30.000Z",
356
+ "approved": false,
357
+ "agent_runtime_ms": 15200,
358
+ "wall_clock_ms": 330000
359
+ }
360
+ ```
361
+
362
+ ---
363
+
364
+ ## MCP Tools
365
+
366
+ Clawck's MCP server (started via `clawck mcp`) exposes these tools over stdio:
367
+
368
+ | Tool | Required Inputs | Description |
369
+ |------|----------------|-------------|
370
+ | `clawck_start_task` | `task` | Start tracking a task |
371
+ | `clawck_stop_task` | `id` | Stop a running task |
372
+ | `clawck_log_task` | `task`, `duration_minutes` | Log completed work retroactively |
373
+ | `clawck_status` | (none) | Get running entries and stats |
374
+ | `clawck_timesheet` | (none) | Get timesheet summary (defaults to last 7 days) |
375
+ | `clawck_get_entry` | `id` | Get a single entry |
376
+ | `clawck_query_entries` | (none) | Query entries with filters |
377
+ | `clawck_update_entry` | `id` | Update an existing entry |
378
+ | `clawck_list_metadata` | `type` | List clients, projects, or agents |
379
+
380
+ All tools return JSON with an `ok` boolean. See `src/server/mcp.ts` for full input schemas.
@@ -0,0 +1,140 @@
1
+ # Deployment Guide
2
+
3
+ ## Local Development
4
+
5
+ ```bash
6
+ # Watch mode (auto-recompile on changes)
7
+ npm run dev
8
+
9
+ # Start the server directly via tsx
10
+ npm run serve
11
+
12
+ # Run tests
13
+ npm test
14
+ ```
15
+
16
+ ## Production Deployment
17
+
18
+ ### Build and Run
19
+
20
+ ```bash
21
+ npm run build # Compile TypeScript to dist/
22
+ npm start # Run dist/cli/index.js
23
+ # or
24
+ clawck serve --port 3456
25
+ ```
26
+
27
+ ### Environment Variables
28
+
29
+ | Variable | Description | Default |
30
+ |----------|-------------|---------|
31
+ | `CLAWCK_DIR` | Path to the data directory | `.clawck` (relative to cwd) |
32
+ | `PORT` | Server port (can also use `--port` flag) | `3456` |
33
+
34
+ ### systemd Example
35
+
36
+ ```ini
37
+ [Unit]
38
+ Description=Clawck Time Tracking Server
39
+ After=network.target
40
+
41
+ [Service]
42
+ Type=simple
43
+ User=clawck
44
+ WorkingDirectory=/opt/clawck
45
+ Environment=CLAWCK_DIR=/opt/clawck/data
46
+ ExecStart=/usr/bin/node /opt/clawck/dist/cli/index.js serve --port 3456
47
+ Restart=on-failure
48
+
49
+ [Install]
50
+ WantedBy=multi-user.target
51
+ ```
52
+
53
+ ### pm2 Example
54
+
55
+ ```bash
56
+ pm2 start dist/cli/index.js --name clawck -- serve --port 3456
57
+ pm2 save
58
+ ```
59
+
60
+ ## Data Directory Structure
61
+
62
+ The data directory (default `.clawck/`, override with `CLAWCK_DIR` or `-d` flag) contains:
63
+
64
+ ```
65
+ .clawck/
66
+ clawck.db # SQLite database (all entries, baselines, reports, sync state)
67
+ config.json # Configuration file
68
+ hooks/
69
+ sessions/ # Hook session state files (JSON, one per active session)
70
+ hook-errors.log # Append-only log of hook processing errors
71
+ ```
72
+
73
+ ### Database File
74
+
75
+ `clawck.db` is a standard SQLite database. It uses WAL mode (`journal_mode = WAL`), which creates two additional files during operation:
76
+
77
+ - `clawck.db-wal` — Write-Ahead Log
78
+ - `clawck.db-shm` — Shared memory file
79
+
80
+ These are normal and are managed automatically by SQLite. Do not delete them while the server is running.
81
+
82
+ ### Database Pragmas
83
+
84
+ - **`journal_mode = WAL`** — Enables concurrent reads while writing. Multiple processes can read the database simultaneously, but only one can write at a time.
85
+ - **`synchronous = NORMAL`** — In WAL mode, this provides good durability without the performance cost of `FULL`. Data is safe against application crashes; a power loss during a write could lose the most recent transaction.
86
+
87
+ ## Backup and Restore
88
+
89
+ ### File Copy (Simplest)
90
+
91
+ Stop the server and copy the database file:
92
+
93
+ ```bash
94
+ # Stop clawck first, then:
95
+ cp .clawck/clawck.db .clawck/clawck.db.bak
96
+ ```
97
+
98
+ ### SQLite .backup (While Running)
99
+
100
+ If you cannot stop the server, use SQLite's built-in backup command:
101
+
102
+ ```bash
103
+ sqlite3 .clawck/clawck.db ".backup '/path/to/backup/clawck.db'"
104
+ ```
105
+
106
+ This creates a consistent snapshot even while the database is in use.
107
+
108
+ ### ATP Export (Portable)
109
+
110
+ Export entries as a JSON envelope for platform-independent backup:
111
+
112
+ ```bash
113
+ # Via CLI
114
+ clawck export --format json --days 365 > backup.json
115
+
116
+ # Via API
117
+ curl http://localhost:3456/api/export/atp?from=2025-01-01T00:00:00Z > backup-atp.json
118
+ ```
119
+
120
+ Import into a new instance:
121
+
122
+ ```bash
123
+ curl -X POST http://localhost:3456/api/import/atp \
124
+ -H "Content-Type: application/json" \
125
+ -d @backup-atp.json
126
+ ```
127
+
128
+ ### Automated Backup (cron)
129
+
130
+ ```bash
131
+ # Daily backup at 2 AM
132
+ 0 2 * * * sqlite3 /opt/clawck/data/clawck.db ".backup '/opt/clawck/backups/clawck-$(date +\%Y\%m\%d).db'"
133
+ ```
134
+
135
+ ### Restore
136
+
137
+ 1. Stop the server
138
+ 2. Replace `clawck.db` with the backup file
139
+ 3. Delete any stale `-wal` and `-shm` files
140
+ 4. Start the server — migrations will auto-apply if the backup is from an older version
@@ -0,0 +1,32 @@
1
+ # Deprecation Policy
2
+
3
+ ## During 0.x (current)
4
+
5
+ - Breaking changes may happen in **minor** versions (e.g., 0.5.0 → 0.6.0)
6
+ - All breaking changes are documented in [CHANGELOG.md](../CHANGELOG.md)
7
+ - Experimental features (labeled in README) may change without notice
8
+
9
+ ## Post 1.0 (planned)
10
+
11
+ - Breaking changes require a **major** version bump
12
+ - Deprecated features receive at least **1 minor version** deprecation notice before removal
13
+ - Deprecation notices appear in:
14
+ - CHANGELOG.md
15
+ - Console warnings at runtime (via structured logger)
16
+
17
+ ## Config Keys
18
+
19
+ - Deprecated config keys will log a warning for **2 minor versions** before removal
20
+ - The warning includes the replacement key/approach
21
+
22
+ ## Experimental Features
23
+
24
+ Features labeled "Experimental" in the README:
25
+ - May change behavior, API shape, or be removed without a deprecation cycle
26
+ - Current experimental features: webhooks, multi-agent sync, pricing estimation
27
+
28
+ ## Stable Surface
29
+
30
+ Features labeled "Stable" in the README:
31
+ - Will follow the deprecation policy above
32
+ - Current stable surfaces: CLI commands, REST API, MCP tools, SQLite storage, ATP export/import
@@ -0,0 +1,78 @@
1
+ # Migration Guide
2
+
3
+ ## Database Schema Migrations
4
+
5
+ Clawck uses a versioned migration system to evolve the SQLite schema. Migrations run automatically on startup — no manual steps required.
6
+
7
+ ### How It Works
8
+
9
+ 1. A `schema_version` table stores a single integer indicating the current version.
10
+ 2. On startup, Clawck compares the stored version against `ClawckDB.SCHEMA_VERSION`.
11
+ 3. Any pending migrations run inside a single transaction — all-or-nothing.
12
+ 4. Legacy databases (created before the migration system) are auto-detected: Clawck probes for columns and tables to infer the correct starting version.
13
+
14
+ ### Migration Table
15
+
16
+ | Version | Added In | What It Does |
17
+ |---------|----------|--------------|
18
+ | 1 | v0.1.0 | Initial schema: `entries` table with all core columns, `sync_state` table, indexes on agent/client/project/status/start |
19
+ | 2 | v0.3.0 | Adds `approved` column (INTEGER, default 0) to `entries` |
20
+ | 3 | v0.3.0 | Adds `agent_runtime_ms` and `wall_clock_ms` columns (INTEGER, nullable) to `entries` |
21
+ | 4 | v0.3.0 | Creates `personal_baselines` table (id, category, task_type, description, my_minutes, timestamps) |
22
+ | 5 | v0.3.0 | Creates `reports` table (id, name, period, period_start, period_end, style, format, content BLOB, metadata, created_at) with index on created_at |
23
+
24
+ ### Checking the Current Version
25
+
26
+ **Programmatically:**
27
+
28
+ ```typescript
29
+ const db = new ClawckDB(config);
30
+ console.log(db.getSchemaVersion()); // e.g., 5
31
+ ```
32
+
33
+ **Via SQLite directly:**
34
+
35
+ ```bash
36
+ sqlite3 .clawck/clawck.db "SELECT version FROM schema_version"
37
+ ```
38
+
39
+ ### Database Pragmas
40
+
41
+ Clawck sets these pragmas on every connection:
42
+
43
+ - `journal_mode = WAL` — Write-Ahead Logging for better concurrent read performance
44
+ - `synchronous = NORMAL` — Balances durability with write speed (safe for WAL mode)
45
+
46
+ ## Upgrading Between Releases
47
+
48
+ ### General Upgrade Steps
49
+
50
+ 1. Stop the running Clawck server
51
+ 2. Pull the new version (`npm update -g clawck` or `git pull && npm install`)
52
+ 3. Build (`npm run build`)
53
+ 4. Start the server (`clawck serve` or `npm start`)
54
+
55
+ Migrations run automatically on first startup after upgrade. No manual database changes needed.
56
+
57
+ ### Version-Specific Notes
58
+
59
+ #### v0.1.0 to v0.3.0
60
+
61
+ - **4 new migrations** (2–5) will auto-apply. The `entries` table gains three new columns (`approved`, `agent_runtime_ms`, `wall_clock_ms`), and two new tables (`personal_baselines`, `reports`) are created.
62
+ - **Spec version changed** from 0.1.0 to 0.2.0. New entries use the updated spec. Existing entries retain their original `spec_version` value.
63
+ - **New config fields** available: `patterns`, `default_pattern`, `runtime_estimation`, `use_industry_benchmarks`, `personal_rate_usd`. All are optional with sensible defaults.
64
+
65
+ #### v0.3.0 to v0.4.x
66
+
67
+ - No schema changes (still version 5).
68
+ - Bug fixes to hook handling, CLI output, and runtime calculation.
69
+ - The `--verbose` flag was added to CLI commands.
70
+
71
+ ### Rollback
72
+
73
+ There is no automated downgrade path. To roll back:
74
+
75
+ 1. Stop Clawck
76
+ 2. Restore the database file from a backup taken before the upgrade (see `docs/deployment.md` for backup guidance)
77
+ 3. Install the older version of Clawck
78
+ 4. Start the server
@@ -0,0 +1,70 @@
1
+ # Security
2
+
3
+ This document describes Clawck's current security posture. Clawck is designed as a local/trusted-network tool — it does not include built-in authentication or authorization.
4
+
5
+ ## Authentication
6
+
7
+ **Clawck has no built-in authentication.** The REST API and dashboard are open to anyone who can reach the server. This is by design for local development use.
8
+
9
+ If you expose Clawck beyond localhost, place it behind a reverse proxy with authentication:
10
+
11
+ ```nginx
12
+ # nginx example
13
+ server {
14
+ listen 443 ssl;
15
+ server_name clawck.internal.example.com;
16
+
17
+ # Add your auth method (basic auth, OAuth proxy, etc.)
18
+ auth_basic "Clawck";
19
+ auth_basic_user_file /etc/nginx/.htpasswd;
20
+
21
+ location / {
22
+ proxy_pass http://127.0.0.1:3456;
23
+ }
24
+ }
25
+ ```
26
+
27
+ ## CORS
28
+
29
+ CORS is wide open by default (`cors()` with no restrictions). All origins, methods, and headers are allowed. To restrict this, you would need to modify `src/server/api.ts` and pass a configuration object to the `cors()` middleware.
30
+
31
+ ## Input Handling
32
+
33
+ - **SQL injection:** All database queries use prepared statements via better-sqlite3. No string interpolation is used in SQL.
34
+ - **JSON validation:** Express `express.json()` middleware parses request bodies. Invalid JSON returns a 400 error.
35
+ - **Entry IDs:** UUIDs are generated via the `uuid` package (v4). ID prefix lookups use parameterized `LIKE` queries.
36
+
37
+ ## Hook System
38
+
39
+ - **Execution context:** Platform hooks (`clawck hook start`, `clawck hook stop`) run as CLI commands in the calling process's context — they inherit the user's permissions and environment.
40
+ - **Session files:** Hook state is stored as JSON files in `.clawck/hooks/sessions/`. These are local to the data directory and are read/written by the CLI process.
41
+ - **Error logging:** Hook errors are appended to `.clawck/hooks/hook-errors.log`. This file grows without rotation — monitor its size in long-running deployments.
42
+
43
+ ## MCP Server
44
+
45
+ The MCP server runs on stdio (stdin/stdout) and inherits the trust model of the parent process. It does not open network ports. The parent process (e.g., Claude Code, Cursor) controls access.
46
+
47
+ ## Data Sensitivity
48
+
49
+ Time entries may contain:
50
+ - **Task descriptions** — can include sensitive project names, client names, or work details
51
+ - **Cost data** — token usage and estimated USD costs
52
+ - **Agent identifiers** — which models and agents are being used
53
+
54
+ The SQLite database file (`.clawck/clawck.db`) contains all of this data. Treat it with the same care as any business data.
55
+
56
+ ## Webhooks
57
+
58
+ Webhook payloads are sent via HTTP POST to configured URLs. Payloads include entry details (task, client, project, cost). If webhook URLs point to external services, entry data leaves your network. Configure webhook URLs to trusted endpoints only.
59
+
60
+ ## Summary
61
+
62
+ | Area | Status |
63
+ |------|--------|
64
+ | Authentication | None — use a reverse proxy if exposed |
65
+ | Authorization | None — all API endpoints are open |
66
+ | CORS | Open to all origins |
67
+ | SQL injection | Protected (prepared statements) |
68
+ | Transport encryption | None — use a reverse proxy with TLS |
69
+ | MCP | stdio-based, inherits parent trust |
70
+ | Data at rest | Unencrypted SQLite file |