chron-mcp 0.1.24 → 0.1.26

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.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  <div align="center">
2
2
  <img src="assets/chron-icon-png-transperent.png" alt="Chron" width="96" />
3
3
  <h1>Chron</h1>
4
- <p>A timestamped audit trail for every AI conversation stored locally, owned by you.</p>
4
+ <p>Local-first, tamper-evident audit trails for AI conversations, tool calls, code changes, and secrets.</p>
5
5
  </div>
6
6
 
7
- AI tools show when you sent a message. Chron logs when the AI responded too — and keeps a permanent, queryable record of every exchange across every tool you use.
7
+ AI tools show when you sent a message. Chron logs when the AI responded too — and keeps a permanent, queryable, tamper-evident record of the AI work happening across your tools.
8
8
 
9
9
  Works with Claude Desktop, Claude Code, Cursor, Windsurf, and any MCP-compatible AI tool.
10
10
 
@@ -16,9 +16,29 @@ AI tools produce no audit trail by default. You cannot answer:
16
16
  - What did the AI say, and when exactly?
17
17
  - How long did the AI take to respond?
18
18
  - What was the full conversation that produced this output?
19
+ - Which tool calls, command results, and code diffs happened during the session?
20
+ - Did a secret or credential get pasted into an AI prompt?
21
+ - Has this audit record been edited after the fact?
19
22
  - What did I ask Claude last week about this codebase?
20
23
 
21
- Chron fixes that. Every exchange is logged with a precise local datetime (including timezone offset) to a SQLite file you own. No cloud, no vendor lock-in, no data leaving your machine.
24
+ Chron fixes that. Every exchange is logged with a precise local datetime (including timezone offset) to a SQLite file you own. It can hash-chain every event, sign sessions with Ed25519, detect secrets/PII, produce SOC 2 evidence, and stream metadata-only events to your SIEM. No cloud, no vendor lock-in, no message content leaving your machine.
25
+
26
+ ---
27
+
28
+ ## What Chron captures
29
+
30
+ Chron stores a local audit trail of:
31
+
32
+ - User and assistant messages
33
+ - Tool calls and tool results
34
+ - Code changes with file path, operation, and unified diff
35
+ - Session start/resume metadata, including parent session and external refs
36
+ - Secret/PII detections with masked values
37
+ - Hash-chain integrity data
38
+ - Optional Ed25519 session signatures
39
+ - Optional NTP clock attestation metadata
40
+
41
+ Chron's SIEM integrations send only metadata: session starts, role-only message events, and masked secret detections. Message content and raw secret values stay local.
22
42
 
23
43
  ---
24
44
 
@@ -49,6 +69,18 @@ npm install -g chron-mcp
49
69
 
50
70
  First run creates `~/.chron/chron.db` automatically. No database setup, no env vars, no migrations.
51
71
 
72
+ Check your setup:
73
+
74
+ ```bash
75
+ chron doctor
76
+ ```
77
+
78
+ For CI or automation:
79
+
80
+ ```bash
81
+ chron doctor --json
82
+ ```
83
+
52
84
  ---
53
85
 
54
86
  ## CLI
@@ -65,18 +97,61 @@ Commands:
65
97
  secrets List detected secrets across sessions
66
98
  settings View current configuration
67
99
  connect Connect to a SIEM integration (crowdstrike, sentinel, splunk)
100
+ summary Structured summary of a session (timeline, mutations, secrets)
101
+ sign Sign a session with its Ed25519 key — produces a .chron.sig file
102
+ verify Verify a session's hash chain and Ed25519 signature
103
+ prune Delete sessions older than a retention cutoff
104
+ doctor Check your Chron setup — Node version, DB, MCP configs, SIEM
105
+ import Import conversations from external AI tools into Chron
68
106
 
69
107
  Options (history):
70
108
  --limit=<n> Max sessions to show (default: 20)
109
+ --ref=<value> Filter by external_ref prefix (e.g. --ref=jira:ENG-123)
71
110
  <id-prefix> Show full log for the session with this ID prefix
72
111
 
73
112
  Options (report):
74
- --since=<range> Filter by date: 7d, 30d, or YYYY-MM-DD (default: all time)
75
-
76
- Options (export / secrets):
77
- <id-prefix> Scope to a single session
113
+ --since=<range> Filter by date: 7d, 30d, or YYYY-MM-DD (default: all time)
114
+ --format=soc2 Generate SOC 2 HTML evidence package
115
+ --output=<file> Output file for --format=soc2
116
+
117
+ Options (export):
118
+ <id-prefix> Markdown export for a single session
119
+ --signed Tamper-evident bundle (JSONL + manifest + Ed25519 sig)
120
+ --session=<id> Filter bundle to a single session
121
+ --since=<range> Filter bundle by date: 7d, 30d, or YYYY-MM-DD
122
+ --output=<file> Output path (default: bundle.chron.tar.gz)
123
+
124
+ Options (verify):
125
+ <id-prefix> Verify a session's hash chain + Ed25519 signature
126
+ --bundle=<file> Verify a signed bundle offline (no DB needed)
127
+
128
+ Options (prune):
129
+ --older-than=<n>d Cutoff in days (falls back to retention_days in config)
130
+ --dry-run Show what would be deleted without deleting
131
+ --confirm Required flag to actually delete
132
+
133
+ Options (doctor):
134
+ --json Machine-readable JSON output
135
+
136
+ Options (import):
137
+ chatgpt <file> Import from ChatGPT export (.zip or conversations.json)
78
138
  ```
79
139
 
140
+ ### `chron doctor`
141
+
142
+ `chron doctor` validates the pieces that make Chron useful in real life:
143
+
144
+ - Node.js version (v18+ required)
145
+ - Local Chron version vs npm latest
146
+ - `npx chron-mcp --version`
147
+ - DB directory and key directory write access
148
+ - Claude Desktop, Claude Code, Cursor, and Windsurf MCP config presence
149
+ - Whether Chron is configured in each MCP client
150
+ - Optional HTTP mode health check on `/health`
151
+ - Splunk, Sentinel, and LogScale configuration via env vars or `~/.chron/config.json`
152
+
153
+ Warnings for optional integrations do not fail the command. Real failures exit with code `1`.
154
+
80
155
  ---
81
156
 
82
157
  ## What it logs
@@ -186,21 +261,26 @@ Chron ships with `skills/chron.skill.md` — a plain-text instruction file that
186
261
  | `init_session` | Initialize or resume a session — returns session_id, message count, and recent messages in one call |
187
262
  | `start_session` | Create a new named audit session (legacy — prefer `init_session`) |
188
263
  | `log_message` | Record a single message with the current local datetime |
264
+ | `log_tool_call` | Record an AI tool invocation as an audit event |
265
+ | `log_tool_result` | Record tool output and link it to a tool call |
266
+ | `log_code_change` | Record a file edit with operation and unified diff |
189
267
  | `log_exchange` | Log a user/assistant pair atomically (for batch imports) |
190
268
  | `list_sessions` | List all sessions ordered by most recently active |
191
269
  | `get_session_history` | Retrieve the full timestamped log for a session |
192
270
  | `verify_session` | Verify the tamper-evident hash chain — detects any post-log edits |
193
271
  | `scan_prompt` | Scan text for secrets (API keys, credentials) before logging — returns masked detections |
194
272
  | `rehydrate_response` | Restore redacted placeholders in an assistant response back to their original values |
273
+ | `delete_session` | Delete a session and cascade its messages/secrets |
274
+ | `summarize_session` | Return a timeline summary with latency, mutations, secrets, and prod references |
195
275
 
196
276
  ---
197
277
 
198
- ## Tamper-evident hash chaining
278
+ ## Integrity and signing
199
279
 
200
- Every message is linked to the previous one via a SHA-256 chain:
280
+ Every new audit event is linked to the previous one via a SHA-256 chain:
201
281
 
202
282
  ```
203
- content_hash = SHA256(session_id | role | content | created_at | prev_hash)
283
+ content_hash = SHA256(session_id | role | content | created_at | prev_hash | event_type)
204
284
  ```
205
285
 
206
286
  `verify_session` walks the chain and returns:
@@ -209,6 +289,58 @@ content_hash = SHA256(session_id | role | content | created_at | prev_hash)
209
289
 
210
290
  This turns your local log into a verifiable audit artifact. Any edit to a stored message — content, timestamp, or role — breaks the chain and is detected immediately.
211
291
 
292
+ Chron also generates an Ed25519 keypair per new session when possible. The private key stays under `~/.chron/keys`. Use:
293
+
294
+ ```bash
295
+ chron sign <session-id-prefix>
296
+ chron verify <session-id-prefix>
297
+ ```
298
+
299
+ For portable evidence:
300
+
301
+ ```bash
302
+ chron export --signed --session=<session-id-prefix> --output=evidence.chron.tar.gz
303
+ chron verify --bundle=evidence.chron.tar.gz
304
+ ```
305
+
306
+ `chron verify` also reports NTP clock attestation metadata for sessions created with clock-check support.
307
+
308
+ ---
309
+
310
+ ## Secrets and PII detection
311
+
312
+ Chron can detect and mask:
313
+
314
+ - API keys: OpenAI, Anthropic, AWS, Google, GitHub, Slack, Stripe, SendGrid, HuggingFace
315
+ - Private keys, JWTs, URL credentials, password assignments, env-style secrets
316
+ - Credit cards, IBANs, SSNs, DOBs, passports
317
+ - Email addresses, US/E.164 phone numbers, internal RFC-1918 IPs
318
+
319
+ Use:
320
+
321
+ ```bash
322
+ chron secrets
323
+ chron secrets <session-id-prefix>
324
+ ```
325
+
326
+ MCP tools can also call `scan_prompt` before sending content to an AI tool. Redaction uses `$CHRON_*` placeholders and `rehydrate_response` can restore values from the returned token map.
327
+
328
+ ---
329
+
330
+ ## Reports and evidence
331
+
332
+ ```bash
333
+ chron history
334
+ chron summary <session-id-prefix>
335
+ chron report --since=30d
336
+ chron report --format=soc2 --output=soc2-report.html
337
+ chron export <session-id-prefix>
338
+ chron export --signed --since=30d --output=bundle.chron.tar.gz
339
+ chron prune --older-than=90d --dry-run
340
+ ```
341
+
342
+ The SOC 2 report and signed bundles are designed for audit review, legal hold, and incident reconstruction without sending conversation content to Chron infrastructure.
343
+
212
344
  ---
213
345
 
214
346
  ## CrowdStrike LogScale integration
@@ -484,6 +616,7 @@ All six must be set for events to flow. Token refresh is automatic (1-hour Azure
484
616
  | `CHRON_SENTINEL_STREAM` | _(none)_ | Stream name (e.g. `Custom-ChronEvents_CL`) |
485
617
  | `CHRON_SPLUNK_URL` | _(none)_ | Splunk HEC base URL (enables Splunk integration) |
486
618
  | `CHRON_SPLUNK_TOKEN` | _(none)_ | Splunk HEC ingest token |
619
+ | `CHRON_SPLUNK_INSECURE` | _(none)_ | Set to `1` to skip TLS verification for local Splunk/self-signed certs |
487
620
  | `CHRON_RELAY_URL` | _(none)_ | Generic relay endpoint (any SIEM or webhook) |
488
621
  | `CHRON_RELAY_TOKEN` | _(none)_ | Bearer token for generic relay |
489
622
 
@@ -514,6 +647,34 @@ Point your MCP config at the URL:
514
647
 
515
648
  ---
516
649
 
650
+ ## ChatGPT import
651
+
652
+ Bring your existing ChatGPT history into Chron's tamper-evident audit trail.
653
+
654
+ ```bash
655
+ # From a ChatGPT data export ZIP
656
+ chron import chatgpt ~/Downloads/chatgpt-export.zip
657
+
658
+ # Or from an extracted conversations.json
659
+ chron import chatgpt ~/Downloads/conversations.json
660
+ ```
661
+
662
+ **How to get your ChatGPT export:**
663
+ ChatGPT → Settings → Data Controls → Export data → wait for email → download the ZIP.
664
+
665
+ **What gets imported:**
666
+ - One Chron session per conversation, with `ai_tool=chatgpt`
667
+ - Original message timestamps from the export
668
+ - `external_ref=chatgpt:<conversation_id>` on every session (visible in `chron history`)
669
+ - Full SHA-256 hash chain across all imported messages
670
+ - Secret detection runs on all user messages
671
+
672
+ **Re-running is safe** — already-imported conversations are skipped by `external_ref` match.
673
+
674
+ After import, sessions appear in `chron history` and `chron verify` works on them the same as any natively-logged session.
675
+
676
+ ---
677
+
517
678
  ## Your data
518
679
 
519
680
  Your audit log lives at `~/.chron/chron.db` — a single SQLite file on your machine. Query it directly with any SQLite tool:
@@ -73,7 +73,7 @@ The dashboard includes five widgets:
73
73
  - **AI Tool Usage** — breakdown by tool (Claude, Cursor, Windsurf, etc.)
74
74
  - **Secrets Detected by Type** — credential exposures over time
75
75
  - **Sessions by Developer** — per-machine session count with AI tool
76
- - **Credential Exposures** — full table of api_key, jwt, aws_key detections for SOC review
76
+ - **Credential Exposures** — full table of API keys, tokens, passwords, and private-key detections for SOC review
77
77
 
78
78
  ## Step 6 — Set up the API key alert (optional)
79
79
 
@@ -81,7 +81,7 @@ In LogScale, create a **Scheduled Search** using `api-key-alert.lql`:
81
81
 
82
82
  ```
83
83
  event_type = "secret_detected"
84
- | detection_type in ["api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt"]
84
+ | detection_type in ["private_key", "aws_access_key", "anthropic_api_key", "openai_api_key", "google_api_key", "github_token", "slack_token", "stripe_key", "sendgrid_key", "huggingface_token", "jwt", "url_credentials", "password", "credential_pair"]
85
85
  | table([#host, ai_tool, detection_type, masked_value, session_id_prefix, @timestamp])
86
86
  ```
87
87
 
@@ -104,7 +104,7 @@ All events arrive in LogScale with:
104
104
  | `os` | All events: `darwin`, `linux`, `win32` |
105
105
  | `chron_version` | All events |
106
106
  | `role` | `message_logged` only: `user` or `assistant` |
107
- | `detection_type` | `secret_detected` only: `api_key`, `aws_key`, `jwt`, etc. |
107
+ | `detection_type` | `secret_detected` only: `openai_api_key`, `aws_access_key`, `github_token`, `jwt`, etc. |
108
108
  | `masked_value` | `secret_detected` only: e.g. `AKIA****F3K2` |
109
109
 
110
110
  **What is never transmitted:** message content, actual secret values, file paths, or any user-typed text.
@@ -1,5 +1,5 @@
1
1
  // Alert: API key or credential sent to AI tool
2
2
  // Use as a Scheduled Search alert — notify SOC on any match
3
3
  event_type = "secret_detected"
4
- | detection_type in ["api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt"]
4
+ | detection_type in ["private_key", "aws_access_key", "anthropic_api_key", "openai_api_key", "google_api_key", "github_token", "slack_token", "stripe_key", "sendgrid_key", "huggingface_token", "jwt", "url_credentials", "password", "credential_pair"]
5
5
  | table([#host, ai_tool, detection_type, masked_value, session_id_prefix, @timestamp])
@@ -62,5 +62,5 @@ widgets:
62
62
  height: 4
63
63
  query: |
64
64
  event_type = "secret_detected"
65
- | detection_type in ["api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt"]
65
+ | detection_type in ["private_key", "aws_access_key", "anthropic_api_key", "openai_api_key", "google_api_key", "github_token", "slack_token", "stripe_key", "sendgrid_key", "huggingface_token", "jwt", "url_credentials", "password", "credential_pair"]
66
66
  | table([#host, ai_tool, detection_type, masked_value, session_id_prefix, @timestamp])
@@ -113,7 +113,7 @@ All events arrive in `ChronEvents_CL` with:
113
113
  | `ChronVersion` | All events |
114
114
  | `Computer` | All events: developer's machine hostname |
115
115
  | `Role` | `message_logged` only: `user` or `assistant` |
116
- | `DetectionType` | `secret_detected` only: `api_key`, `aws_key`, `jwt`, etc. |
116
+ | `DetectionType` | `secret_detected` only: `openai_api_key`, `aws_access_key`, `github_token`, `jwt`, etc. |
117
117
  | `MaskedValue` | `secret_detected` only: e.g. `AKIA****F3K2` |
118
118
 
119
119
  **What is never transmitted:** message content, actual secret values, file paths, or any user-typed text.
@@ -3,5 +3,5 @@
3
3
  ChronEvents_CL
4
4
  | where TimeGenerated > ago(1h)
5
5
  | where EventType == "secret_detected"
6
- | where DetectionType in ("api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt")
6
+ | where DetectionType in ("private_key", "aws_access_key", "anthropic_api_key", "openai_api_key", "google_api_key", "github_token", "slack_token", "stripe_key", "sendgrid_key", "huggingface_token", "jwt", "url_credentials", "password", "credential_pair")
7
7
  | project TimeGenerated, Computer, AiTool, DetectionType, MaskedValue, SessionIdPrefix
@@ -2,6 +2,6 @@
2
2
  ChronEvents_CL
3
3
  | where TimeGenerated > ago(30d)
4
4
  | where EventType == "secret_detected"
5
- | where DetectionType in ("api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt")
5
+ | where DetectionType in ("private_key", "aws_access_key", "anthropic_api_key", "openai_api_key", "google_api_key", "github_token", "slack_token", "stripe_key", "sendgrid_key", "huggingface_token", "jwt", "url_credentials", "password", "credential_pair")
6
6
  | project TimeGenerated, Computer, AiTool, DetectionType, MaskedValue, SessionIdPrefix
7
7
  | sort by TimeGenerated desc
@@ -122,7 +122,7 @@ All events arrive with `sourcetype=chron:event` and these fields:
122
122
  | `os` | All events: `darwin`, `linux`, `win32` |
123
123
  | `chron_version` | All events |
124
124
  | `role` | `message_logged` only: `user` or `assistant` |
125
- | `detection_type` | `secret_detected` only: `api_key`, `aws_key`, `jwt`, etc. |
125
+ | `detection_type` | `secret_detected` only: `openai_api_key`, `aws_access_key`, `github_token`, `jwt`, etc. |
126
126
  | `masked_value` | `secret_detected` only: e.g. `AKIA****F3K2` |
127
127
 
128
128
  **What is never transmitted:** message content, actual secret values, file paths, or any user-typed text.
@@ -1,3 +1,3 @@
1
1
  sourcetype="chron:event" event_type="secret_detected" earliest=-1h
2
- | where detection_type IN ("api_key","aws_key","gcp_key","azure_key","private_key","jwt")
2
+ | where detection_type IN ("private_key","aws_access_key","anthropic_api_key","openai_api_key","google_api_key","github_token","slack_token","stripe_key","sendgrid_key","huggingface_token","jwt","url_credentials","password","credential_pair")
3
3
  | table _time, host, ai_tool, detection_type, masked_value, session_id_prefix
@@ -1,4 +1,4 @@
1
1
  sourcetype="chron:event" event_type="secret_detected" earliest=-30d
2
- | where detection_type IN ("api_key","aws_key","gcp_key","azure_key","private_key","jwt")
2
+ | where detection_type IN ("private_key","aws_access_key","anthropic_api_key","openai_api_key","google_api_key","github_token","slack_token","stripe_key","sendgrid_key","huggingface_token","jwt","url_credentials","password","credential_pair")
3
3
  | table _time, host, ai_tool, detection_type, masked_value, session_id_prefix
4
4
  | sort -_time