agentacta 1.3.4 → 2026.3.5

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
@@ -4,9 +4,11 @@
4
4
  [![npm](https://img.shields.io/npm/v/agentacta)](https://www.npmjs.com/package/agentacta)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
6
 
7
- **Your AI agent does hundreds of things. Can you find them?**
7
+ **Your agent did 1000s of things today. Can you find the 1 that broke prod?**
8
8
 
9
- AgentActa is an audit trail and search engine for AI agent sessions. It indexes everything your agent did — every message, tool call, file edit, web search, and decision — into a fast, searchable local interface.
9
+ AgentActa is a local audit trail and search engine for AI agent sessions.
10
+
11
+ It indexes messages, tool calls, file edits, searches, and decisions into a fast UI you can query in seconds.
10
12
 
11
13
  One command. Zero config. Full visibility.
12
14
 
@@ -18,24 +20,25 @@ npx agentacta
18
20
  <img src="screenshots/demo.gif" alt="AgentActa demo" width="800">
19
21
  </p>
20
22
 
21
- ---
23
+ ## Why this exists
22
24
 
23
- ## Why
25
+ Agents move fast. Your memory of what happened doesn’t.
24
26
 
25
- AI agents are powerful. They write code, send emails, manage infrastructure, make decisions on your behalf. But when you need to know *what happened* — what was changed, when, and why you're digging through scattered logs or asking the agent to remember (it won't).
27
+ When you need to answer what changed, when, and why,” youre usually scraping logs, scrolling transcripts, or asking the same assistant that forgot 20 minutes ago.
26
28
 
27
- AgentActa gives you a single, searchable view of everything.
29
+ AgentActa gives you one place to inspect the full trail.
28
30
 
29
- ## What You Get
31
+ ## What you get
30
32
 
31
- 🔍 **Full-text search** across all messages, tool calls, and results
32
- 📋 **Session browser** with summaries, token breakdowns (input/output), and model info
33
- 📅 **Timeline view** everything that happened on any given day
34
- 📁 **File activity** — every file your agent touched, across all sessions
35
- 📊 **Stats** sessions, messages, tool usage, token counts
36
- **Live indexing** new sessions appear automatically via file watching
37
- 📱 **Mobile-friendly** responsive UI with bottom tab navigation
38
- 💡 **Smart suggestions** — quick search chips derived from your actual session data
33
+ - 🔍 Full-text search across messages, tool calls, and results
34
+ - 📋 Session browser with summaries, token breakdowns, and model info
35
+ - 📅 Timeline view with live updates for today
36
+ - 📁 File activity across all indexed sessions
37
+ - 🌗 Light and dark themes
38
+ - 📊 Stats for sessions, messages, tools, and tokens
39
+ - Live indexing via file watching
40
+ - 📱 Mobile-friendly UI
41
+ - 💡 Search suggestions based on real data
39
42
 
40
43
  ## Demo
41
44
 
@@ -51,62 +54,81 @@ https://github.com/mirajchokshi/agentacta/raw/main/screenshots/demo-final.mp4
51
54
  ![Stats](screenshots/stats.png)
52
55
  ![Search Results](screenshots/search-results.png)
53
56
 
54
- ## Quick Start
57
+ ## Quick start
55
58
 
56
59
  ```bash
57
- # Run directly (no install needed)
60
+ # run directly
58
61
  npx agentacta
59
62
 
60
- # Or install globally
63
+ # or install globally
61
64
  npm install -g agentacta
62
65
  agentacta
63
66
  ```
64
67
 
65
- Open `http://localhost:4003` in your browser.
68
+ Open: `http://localhost:4003`
66
69
 
67
- AgentActa automatically finds your sessions in:
70
+ Auto-detected session paths:
68
71
  - `~/.openclaw/agents/*/sessions/` (OpenClaw)
69
72
  - `~/.claude/projects/*/` (Claude Code)
70
73
  - `~/.codex/sessions/` (Codex CLI)
71
74
 
72
- Or point it at a custom path:
75
+ Custom path:
73
76
 
74
77
  ```bash
75
78
  AGENTACTA_SESSIONS_PATH=/path/to/sessions agentacta
76
79
  ```
77
80
 
78
- ## Features
81
+ ## Core features
79
82
 
80
83
  ### Search
81
- Full-text search powered by SQLite FTS5. Filter by message type (messages, tool calls, results) and role (user, assistant). Quick search suggestions are generated from your actual data — most-used tools, common topics, frequently touched files.
84
+
85
+ SQLite FTS5 full-text search with filters for message type (messages, tool calls, results) and role (user, assistant).
86
+
87
+ Suggestions come from your own dataset: top tools, common topics, frequently touched files.
82
88
 
83
89
  ### Sessions
84
- Browse all indexed sessions with auto-generated summaries, token breakdowns (output vs input), and model info. Sessions are automatically tagged by type — cron jobs, sub-agent tasks, and heartbeat sessions get distinct badges. Click into any session to see the full event history, most recent first.
90
+
91
+ Browse indexed sessions with auto-generated summaries, token splits (input/output), and model details. Click into any session to see the full event history.
92
+
93
+ Session types get tagged so noisy categories are easier to spot (cron, sub-agent, heartbeat).
85
94
 
86
95
  ### Timeline
87
- Pick a date, see everything that happened. Messages, tool invocations, file changes — most recent first.
96
+
97
+ Pick a date, see everything that happened, newest first. Today's view updates live as new events come in.
88
98
 
89
99
  ### File Activity
90
- See every file your agent read, wrote, or edited. Sort by most touched, most recent, or most sessions. Filter by extension, group by directory. Click any file to see which sessions touched it and what was done.
100
+
101
+ See what files were touched, how often, and by which sessions.
102
+
103
+ Sort by recency, frequency, or session count. Filter by extension. Group by directory. Click any file to see which sessions touched it.
91
104
 
92
105
  ### Export
93
- Download any session or search results as Markdown or JSON. Great for sharing, auditing, or archiving.
94
106
 
95
- ## How It Works
107
+ Export sessions or search results as Markdown or JSON.
96
108
 
97
- AgentActa reads JSONL session files (including OpenClaw, Claude Code, and Codex CLI formats), parses every message and tool call, and indexes them into a local SQLite database with FTS5 full-text search.
109
+ Useful for handoffs, incident writeups, and audit archives.
98
110
 
99
- The web UI is a single-page app served by a lightweight Node.js HTTP server. No frameworks, no build step, no external dependencies beyond `better-sqlite3`.
111
+ ## How it works
100
112
 
101
- ```
102
- Session JSONL files → SQLite + FTS5 index → HTTP API → Web UI
113
+ AgentActa parses JSONL session files (OpenClaw, Claude Code, Codex CLI), then indexes events into local SQLite with FTS5.
114
+
115
+ The UI is a single-page app served by a lightweight Node HTTP server.
116
+
117
+ No framework build pipeline. Minimal moving parts.
118
+
119
+ ```text
120
+ Session JSONL files -> SQLite + FTS5 index -> HTTP API -> Web UI
103
121
  ```
104
122
 
105
- Data never leaves your machine.
123
+ Everything stays on your machine.
106
124
 
107
125
  ## Configuration
108
126
 
109
- On first run, AgentActa creates a config file with sensible defaults at `~/.config/agentacta/config.json` (or `agentacta.config.json` in the current directory if it exists):
127
+ On first run, AgentActa creates:
128
+ - `~/.config/agentacta/config.json`
129
+ - or `agentacta.config.json` in current directory (if present)
130
+
131
+ Default config:
110
132
 
111
133
  ```json
112
134
  {
@@ -118,85 +140,82 @@ On first run, AgentActa creates a config file with sensible defaults at `~/.conf
118
140
  }
119
141
  ```
120
142
 
121
- ### Storage Modes
143
+ ### Storage modes
122
144
 
123
- - **`reference`** (default) — Lightweight index. Stores parsed events in SQLite but not the raw JSONL. Source files must remain on disk.
124
- - **`archive`** Full JSONL stored in SQLite. Sessions survive even if the original files are deleted. Uses more disk space.
145
+ - `reference` (default): index parsed events in SQLite, keep source JSONL on disk. Lightweight.
146
+ - `archive`: store full JSONL in SQLite. Sessions survive even if original files are deleted. Uses more disk.
125
147
 
126
- ### Environment Variables
148
+ ### Environment variables
127
149
 
128
150
  | Variable | Default | Description |
129
151
  |---|---|---|
130
152
  | `PORT` | `4003` | Server port |
131
- | `AGENTACTA_HOST` | `127.0.0.1` | Bind address (see [Security](#security)) |
132
- | `AGENTACTA_SESSIONS_PATH` | Auto-detected | Custom sessions directory |
133
- | `AGENTACTA_DB_PATH` | `./agentacta.db` | Database file location |
134
- | `AGENTACTA_STORAGE` | `reference` | Storage mode (`reference` or `archive`) |
135
- | `AGENTACTA_PROJECT_ALIASES_JSON` | unset | JSON object mapping inferred project names (e.g. `{"old-name":"new-name"}`) |
153
+ | `AGENTACTA_HOST` | `127.0.0.1` | Bind address |
154
+ | `AGENTACTA_SESSIONS_PATH` | auto-detected | Custom sessions directory |
155
+ | `AGENTACTA_DB_PATH` | `./agentacta.db` | Database path |
156
+ | `AGENTACTA_STORAGE` | `reference` | `reference` or `archive` |
157
+ | `AGENTACTA_PROJECT_ALIASES_JSON` | unset | Rename inferred project labels |
136
158
 
137
159
  ## API
138
160
 
139
- AgentActa exposes a JSON API for programmatic access — useful for integrating search into your agent's workflow.
140
-
141
161
  | Endpoint | Description |
142
162
  |---|---|
143
- | `GET /api/stats` | Overview: session count, messages, tools, tokens |
144
- | `GET /api/sessions` | List sessions with metadata and token breakdowns |
145
- | `GET /api/sessions/:id` | Full session with all events |
146
- | `GET /api/search?q=<query>` | Full-text search with type/role/date filters |
147
- | `GET /api/suggestions` | Data-driven search suggestions |
148
- | `GET /api/timeline?date=YYYY-MM-DD` | All events for a given day |
149
- | `GET /api/files` | All files touched across sessions |
150
- | `GET /api/export/session/:id?format=md` | Export session as Markdown or JSON |
163
+ | `GET /api/stats` | Session/message/tool/token totals |
164
+ | `GET /api/sessions` | Session list with metadata |
165
+ | `GET /api/sessions/:id` | Full session events |
166
+ | `GET /api/search?q=<query>` | Full-text search + filters |
167
+ | `GET /api/suggestions` | Search suggestions |
168
+ | `GET /api/timeline?date=YYYY-MM-DD` | Events for one day |
169
+ | `GET /api/files` | Touched-file inventory |
170
+ | `GET /api/export/session/:id?format=md` | Export one session |
171
+ | `GET /api/timeline/stream?after=<ts>` | SSE stream for live timeline updates |
172
+ | `POST /api/maintenance` | VACUUM + WAL checkpoint (returns size before/after) |
151
173
  | `GET /api/export/search?q=<query>&format=md` | Export search results |
152
174
 
153
- ### Agent Integration
154
-
155
- Your AI agent can query AgentActa for better recall:
175
+ Agent integration example:
156
176
 
157
177
  ```javascript
158
- const results = await fetch('http://localhost:4003/api/search?q=deployment+issue&limit=5');
159
- const data = await results.json();
160
- // Agent now has context from past sessions
178
+ const res = await fetch('http://localhost:4003/api/search?q=deployment+issue&limit=5');
179
+ const data = await res.json();
161
180
  ```
162
181
 
163
- ### Demo Mode
164
-
165
- Want to see what AgentActa looks like with data? Run with demo sessions:
182
+ ## Demo mode
166
183
 
167
184
  ```bash
168
- # Generate demo data and start in demo mode
185
+ # seed demo data + run
169
186
  npm run demo
170
187
 
171
- # Or separately:
188
+ # or split steps
172
189
  node scripts/seed-demo.js
173
190
  node index.js --demo
174
191
  ```
175
192
 
176
- This creates 7 realistic sessions simulating a developer building a weather app scaffolding, API integration, frontend, debugging, deployment, tests, and a sub-agent task.
193
+ Demo mode creates 7 realistic sessions (weather app build path: scaffolding, API, frontend, debugging, deployment, tests, sub-agent task).
177
194
 
178
195
  ## Security
179
196
 
180
- **AgentActa is a local tool.** It binds to `127.0.0.1` by default — only accessible from your machine.
197
+ AgentActa binds to `127.0.0.1` by default.
181
198
 
182
- To expose on your network (e.g., for Tailscale access):
199
+ If you expose it on a network, do it intentionally:
183
200
 
184
201
  ```bash
185
202
  AGENTACTA_HOST=0.0.0.0 agentacta
186
203
  ```
187
204
 
188
- ⚠️ **Important:** Agent session data can contain sensitive information file contents, API responses, personal messages, tool call arguments. If you expose AgentActa on a network, ensure it's a trusted one. There is no built-in authentication.
205
+ **Important:** Session data can contain sensitive content (file snippets, API payloads, personal messages, tool args). There is no built-in auth yet, so only expose on trusted networks.
189
206
 
190
- ## Tech Stack
207
+ ## Tech stack
191
208
 
192
- - **Node.js** — HTTP server (built-in `http`, no Express)
193
- - **better-sqlite3** Fast SQLite with FTS5 full-text search
194
- - **Vanilla HTML/CSS/JS** — No framework, no build step
195
- - **PWA** — Installable as a home screen app
209
+ - Node.js (built-in `http`)
210
+ - `better-sqlite3` + SQLite FTS5
211
+ - Vanilla HTML/CSS/JS
212
+ - PWA support
196
213
 
197
214
  ## Privacy
198
215
 
199
- All data stays local. AgentActa runs entirely on your machine — no cloud services, no telemetry, no external requests. Your agent history is yours.
216
+ No telemetry. No cloud sync. No external indexing service.
217
+
218
+ Your session history stays local.
200
219
 
201
220
  ## Compatibility
202
221
 
@@ -207,13 +226,15 @@ All data stays local. AgentActa runs entirely on your machine — no cloud servi
207
226
 
208
227
  ## Contributing
209
228
 
210
- PRs welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup and guidelines. If you're adding support for a new agent format, add a parser in `indexer.js` and open a PR.
229
+ PRs welcome.
230
+
231
+ See [CONTRIBUTING.md](CONTRIBUTING.md). If you’re adding a new agent format, start in `indexer.js`.
211
232
 
212
- ## Etymology
233
+ ## Name
213
234
 
214
- *Acta* (Latin) "things done." In ancient Rome, the *acta diurna* were daily public records of official proceedings — senate decisions, military victories, births and deaths — posted in public spaces for all citizens to read.
235
+ *Acta* is Latin for things done.”
215
236
 
216
- AgentActa is the same idea: a complete, searchable record of everything your AI agent did.
237
+ That’s the job here: keep a readable record of what your agents actually did.
217
238
 
218
239
  ## License
219
240
 
@@ -221,4 +242,4 @@ MIT
221
242
 
222
243
  ---
223
244
 
224
- Built in Chicago by humans and agents working together.
245
+ Built in Chicago by humans and agents.
package/db.js CHANGED
@@ -54,6 +54,7 @@ function init(dbPath) {
54
54
  FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
55
55
  );
56
56
 
57
+ CREATE INDEX IF NOT EXISTS idx_sessions_start_time ON sessions(start_time DESC);
57
58
  CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);
58
59
  CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
59
60
  CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
package/index.js CHANGED
@@ -428,13 +428,70 @@ const server = http.createServer((req, res) => {
428
428
  const date = query.date || (() => { const n = new Date(); return `${n.getFullYear()}-${String(n.getMonth()+1).padStart(2,'0')}-${String(n.getDate()).padStart(2,'0')}`; })();
429
429
  const from = new Date(date + 'T00:00:00').toISOString();
430
430
  const to = new Date(date + 'T23:59:59.999').toISOString();
431
+ const limit = Math.min(parseInt(query.limit || '100', 10) || 100, 500);
432
+ const offset = Math.max(parseInt(query.offset || '0', 10) || 0, 0);
431
433
  const events = db.prepare(
432
434
  `SELECT e.*, s.summary as session_summary FROM events e
433
435
  JOIN sessions s ON s.id = e.session_id
434
436
  WHERE e.timestamp >= ? AND e.timestamp <= ?
435
- ORDER BY e.timestamp DESC`
436
- ).all(from, to);
437
- json(res, { date, events, total: events.length });
437
+ ORDER BY e.timestamp DESC
438
+ LIMIT ? OFFSET ?`
439
+ ).all(from, to, limit, offset);
440
+ const total = db.prepare(
441
+ `SELECT COUNT(*) as c FROM events e
442
+ WHERE e.timestamp >= ? AND e.timestamp <= ?`
443
+ ).get(from, to).c;
444
+ json(res, { date, events, total, limit, offset, hasMore: offset + events.length < total });
445
+ }
446
+ else if (pathname === '/api/timeline/stream') {
447
+ res.writeHead(200, {
448
+ 'Content-Type': 'text/event-stream',
449
+ 'Cache-Control': 'no-cache',
450
+ 'Connection': 'keep-alive',
451
+ 'X-Accel-Buffering': 'no'
452
+ });
453
+ res.write(': connected\n\n');
454
+
455
+ let lastTs = query.after || new Date().toISOString();
456
+ let lastId = query.afterId || '';
457
+
458
+ const onUpdate = () => {
459
+ try {
460
+ const rows = db.prepare(
461
+ `SELECT e.*, s.summary as session_summary FROM events e
462
+ JOIN sessions s ON s.id = e.session_id
463
+ WHERE (e.timestamp > ?) OR (e.timestamp = ? AND e.id > ?)
464
+ ORDER BY e.timestamp ASC, e.id ASC`
465
+ ).all(lastTs, lastTs, lastId);
466
+ if (rows.length) {
467
+ const tail = rows[rows.length - 1];
468
+ lastTs = tail.timestamp || lastTs;
469
+ lastId = tail.id || lastId;
470
+ res.write(`id: ${lastTs}:${lastId}\ndata: ${JSON.stringify(rows)}\n\n`);
471
+ }
472
+ } catch (err) {
473
+ console.error('Timeline SSE error:', err.message);
474
+ }
475
+ };
476
+
477
+ sseEmitter.on('session-update', onUpdate);
478
+
479
+ const ping = setInterval(() => {
480
+ try { res.write(': ping\n\n'); } catch {}
481
+ }, 30000);
482
+
483
+ req.on('close', () => {
484
+ sseEmitter.off('session-update', onUpdate);
485
+ clearInterval(ping);
486
+ });
487
+ }
488
+ else if (pathname === '/api/maintenance') {
489
+ if (req.method !== 'POST') return json(res, { error: 'Method not allowed' }, 405);
490
+ const sizeBefore = getDbSize();
491
+ db.pragma('wal_checkpoint(TRUNCATE)');
492
+ db.exec('VACUUM');
493
+ const sizeAfter = getDbSize();
494
+ json(res, { ok: true, sizeBefore, sizeAfter });
438
495
  }
439
496
  else if (pathname === '/api/files') {
440
497
  const limit = parseInt(query.limit) || 100;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentacta",
3
- "version": "1.3.4",
3
+ "version": "2026.3.5",
4
4
  "description": "Audit trail and search engine for AI agent sessions",
5
5
  "main": "index.js",
6
6
  "bin": {