chat-logbook 0.12.0 → 0.14.0
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 +6 -7
- package/api/dist/drizzle/0004_add_tags.sql +16 -0
- package/api/dist/drizzle/0005_add_deleted_at_index.sql +1 -0
- package/api/dist/drizzle/0006_add_chat_sort_keys.sql +7 -0
- package/api/dist/drizzle/archive/0008_add_chats_project_idx.sql +1 -0
- package/api/dist/drizzle/archive/0009_add_chats_updated_at.sql +21 -0
- package/api/dist/drizzle/archive/0010_add_chats_created_at.sql +26 -0
- package/api/dist/drizzle/archive/meta/_journal.json +21 -0
- package/api/dist/drizzle/meta/_journal.json +21 -0
- package/api/dist/index.js +1363 -376
- package/package.json +1 -1
- package/web/dist/assets/index-BQlthoCZ.css +2 -0
- package/web/dist/assets/index-zW6L5xEX.js +57 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-BJlGZyK5.js +0 -57
- package/web/dist/assets/index-DSNHfjXl.css +0 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
A local-first library for the conversations you've had with your AI tools. Read by chat-logbook, kept on your machine, browsable and searchable in one place — even after your AI tool has deleted the original.
|
|
6
6
|
|
|
7
|
-
> **Status.** A personal side project, moving at side-project pace — development and responses happen as time allows. Early release: browsing, rendering, soft-delete, and a local archive that survives vendor cleanup all work today. Search
|
|
7
|
+
> **Status.** A personal side project, moving at side-project pace — development and responses happen as time allows. Early release: browsing, rendering, tags, soft-delete, and a local archive that survives vendor cleanup all work today. Search is next. See [Roadmap](#roadmap).
|
|
8
8
|
|
|
9
9
|
## What chat-logbook is
|
|
10
10
|
|
|
@@ -33,6 +33,7 @@ The full problem statement, user stories, and direction live in the [PRD](docs/P
|
|
|
33
33
|
and conversation content.
|
|
34
34
|
- **Rich conversation rendering.** Markdown, syntax-highlighted code blocks, collapsible tool calls with one-line summaries, and collapsible thinking blocks.
|
|
35
35
|
- **Virtual scrolling.** Long conversations scroll smoothly.
|
|
36
|
+
- **A chat list that scales.** The list loads on demand as you scroll and stays fast even with tens of thousands of chats.
|
|
36
37
|
- **Solarized Dark theme.** Easy on the eyes, consistent with Claude
|
|
37
38
|
Code's terminal look.
|
|
38
39
|
- **Soft delete with Trash.** Hide chats you don't want to see; restore
|
|
@@ -40,8 +41,10 @@ The full problem statement, user stories, and direction live in the [PRD](docs/P
|
|
|
40
41
|
- **Sortable lists.** Sort your chats by title, created time, or updated time, and the choice sticks between visits. Trash sorts independently — by deleted time by default.
|
|
41
42
|
- **Custom chat titles.** Rename any chat — click its title in the list or conversation header, or select it and press `F2` / `↵`. Clear the title to fall back to the first message.
|
|
42
43
|
- **Local archive.** Every conversation chat-logbook reads is copied into `~/.chat-logbook/archive.db`. The UI reads from the archive, so a chat stays visible even after the source JSONL is gone.
|
|
43
|
-
- **Live updates.** While Claude Code is actively writing to a chat, new messages appear in chat-logbook within seconds — no restart needed.
|
|
44
|
+
- **Live updates.** While Claude Code is actively writing to a chat, new messages appear in chat-logbook within seconds — no restart needed. New and changed chats surface in the list on their own, without a manual refresh.
|
|
44
45
|
- **Chat metadata at a glance.** A ⓘ button on the conversation header opens a popover showing when the chat started, when it was last updated, the agent, the project working directory, and the chat's IDs — with one-click copy.
|
|
46
|
+
- **Tags.** Create tags, give them colors, and assign them to chats. They show as colored chips on the chat and in the list. Rename or delete them anytime.
|
|
47
|
+
- **Filter by tag or project.** Narrow the chat list to a project, or to chats that carry all of several selected tags.
|
|
45
48
|
|
|
46
49
|
## Quick start
|
|
47
50
|
|
|
@@ -109,13 +112,9 @@ No. chat-logbook reads files those tools write on your machine. It doesn't talk
|
|
|
109
112
|
|
|
110
113
|
## Roadmap
|
|
111
114
|
|
|
112
|
-
Two phases of work are in flight, in this order.
|
|
113
|
-
|
|
114
|
-
**Custom titles and tags.** Rename a chat to something you'll recognize, attach tags with custom colors, and filter the list by tag or by project. This is the path from "I have a lot of conversations" to "I can find the one I need."
|
|
115
|
-
|
|
116
115
|
**Spotlight search.** A keyboard-driven overlay (`⌘K` or `/`) that searches across chats, messages, tags, and projects from one input. A match lands you on the exact message with the term highlighted, and you can jump between every match without leaving the overlay.
|
|
117
116
|
|
|
118
|
-
Beyond
|
|
117
|
+
Beyond this, several smaller things are on the list without firm timing — live updates while an AI tool is writing, annotations and highlights for marking what matters, editing your own past messages, CLI commands for working with conversations from a terminal. Some will ship; some are still being weighed.
|
|
119
118
|
|
|
120
119
|
Explicit non-goals: semantic / vector search, cloud sync inside the OSS core, modification of source directories like `~/.claude/`, and bulk export to bespoke formats (the archive itself is the export). See the [PRD](docs/PRD.md) for the full out-of-scope list.
|
|
121
120
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
CREATE TABLE `tags` (
|
|
2
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
3
|
+
`name` text NOT NULL,
|
|
4
|
+
`color` text NOT NULL,
|
|
5
|
+
`created_at` integer NOT NULL,
|
|
6
|
+
`updated_at` integer NOT NULL
|
|
7
|
+
);
|
|
8
|
+
--> statement-breakpoint
|
|
9
|
+
CREATE TABLE `chat_tags` (
|
|
10
|
+
`chat_id` text NOT NULL,
|
|
11
|
+
`tag_id` text NOT NULL,
|
|
12
|
+
PRIMARY KEY(`chat_id`, `tag_id`),
|
|
13
|
+
FOREIGN KEY (`tag_id`) REFERENCES `tags`(`id`) ON UPDATE no action ON DELETE cascade
|
|
14
|
+
);
|
|
15
|
+
--> statement-breakpoint
|
|
16
|
+
CREATE INDEX `chat_tags_tag_id_idx` ON `chat_tags` (`tag_id`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CREATE INDEX `chats_meta_deleted_at_idx` ON `chats_meta` (`deleted_at`,`id`) WHERE `deleted_at` IS NOT NULL;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CREATE INDEX `chats_project_idx` ON `chats` (`project`);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
-- Denormalized "most recent activity" column for the server-side activity sort
|
|
2
|
+
-- (ADR-0017, issue #129). Nullable on ADD COLUMN, then backfilled below so every
|
|
3
|
+
-- existing row gets a value; new rows are initialized by the ingest write seam.
|
|
4
|
+
ALTER TABLE `chats` ADD COLUMN `updated_at` integer;
|
|
5
|
+
--> statement-breakpoint
|
|
6
|
+
-- Backfill: most recent message ts per chat, falling back to first_seen_at for a
|
|
7
|
+
-- chat that has no messages yet, so updated_at is never NULL.
|
|
8
|
+
UPDATE `chats`
|
|
9
|
+
SET `updated_at` = coalesce(
|
|
10
|
+
(SELECT max(`m`.`ts`)
|
|
11
|
+
FROM `messages` `m`
|
|
12
|
+
WHERE `m`.`agent` = `chats`.`agent`
|
|
13
|
+
AND `m`.`source_id` = `chats`.`source_id`),
|
|
14
|
+
`chats`.`first_seen_at`
|
|
15
|
+
);
|
|
16
|
+
--> statement-breakpoint
|
|
17
|
+
-- Covering keyset indexes: (sortKey, id) so each list sort's ORDER BY + LIMIT is
|
|
18
|
+
-- an index range scan that stops after one page.
|
|
19
|
+
CREATE INDEX `chats_created_keyset_idx` ON `chats` (`first_seen_at`,`id`);
|
|
20
|
+
--> statement-breakpoint
|
|
21
|
+
CREATE INDEX `chats_updated_keyset_idx` ON `chats` (`updated_at`,`id`);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- Denormalized "conversation start" column for the createdAt list sort (issue
|
|
2
|
+
-- #143, reconciling ADR-0017). The createdAt axis must page by what the reader
|
|
3
|
+
-- displays — min(messages.ts) — not first_seen_at (the ingest time), so the
|
|
4
|
+
-- paged order and the shown createdAt agree. Nullable on ADD COLUMN, then
|
|
5
|
+
-- backfilled below so every existing row gets a value; new rows are initialized
|
|
6
|
+
-- by the ingest write seam.
|
|
7
|
+
ALTER TABLE `chats` ADD COLUMN `created_at` integer;
|
|
8
|
+
--> statement-breakpoint
|
|
9
|
+
-- Backfill: earliest message ts per chat, falling back to first_seen_at for a
|
|
10
|
+
-- chat that has no messages yet, so created_at is never NULL and matches the
|
|
11
|
+
-- reader's displayed createdAt (min(messages.ts) ?? first_seen_at).
|
|
12
|
+
UPDATE `chats`
|
|
13
|
+
SET `created_at` = coalesce(
|
|
14
|
+
(SELECT min(`m`.`ts`)
|
|
15
|
+
FROM `messages` `m`
|
|
16
|
+
WHERE `m`.`agent` = `chats`.`agent`
|
|
17
|
+
AND `m`.`source_id` = `chats`.`source_id`),
|
|
18
|
+
`chats`.`first_seen_at`
|
|
19
|
+
);
|
|
20
|
+
--> statement-breakpoint
|
|
21
|
+
-- Repoint the createdAt keyset index from first_seen_at to created_at: the
|
|
22
|
+
-- covering (sortKey, id) so the createdAt ORDER BY + LIMIT stays an index range
|
|
23
|
+
-- scan that stops after one page, in either direction.
|
|
24
|
+
DROP INDEX `chats_created_keyset_idx`;
|
|
25
|
+
--> statement-breakpoint
|
|
26
|
+
CREATE INDEX `chats_created_keyset_idx` ON `chats` (`created_at`,`id`);
|
|
@@ -57,6 +57,27 @@
|
|
|
57
57
|
"when": 1779200000000,
|
|
58
58
|
"tag": "0007_drop_session_scan_state",
|
|
59
59
|
"breakpoints": true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"idx": 8,
|
|
63
|
+
"version": "6",
|
|
64
|
+
"when": 1779300000000,
|
|
65
|
+
"tag": "0008_add_chats_project_idx",
|
|
66
|
+
"breakpoints": true
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"idx": 9,
|
|
70
|
+
"version": "6",
|
|
71
|
+
"when": 1779400000000,
|
|
72
|
+
"tag": "0009_add_chats_updated_at",
|
|
73
|
+
"breakpoints": true
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"idx": 10,
|
|
77
|
+
"version": "6",
|
|
78
|
+
"when": 1779500000000,
|
|
79
|
+
"tag": "0010_add_chats_created_at",
|
|
80
|
+
"breakpoints": true
|
|
60
81
|
}
|
|
61
82
|
]
|
|
62
83
|
}
|
|
@@ -29,6 +29,27 @@
|
|
|
29
29
|
"when": 1779500000000,
|
|
30
30
|
"tag": "0003_add_deleted_at",
|
|
31
31
|
"breakpoints": true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"idx": 4,
|
|
35
|
+
"version": "6",
|
|
36
|
+
"when": 1780000000000,
|
|
37
|
+
"tag": "0004_add_tags",
|
|
38
|
+
"breakpoints": true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"idx": 5,
|
|
42
|
+
"version": "6",
|
|
43
|
+
"when": 1780500000000,
|
|
44
|
+
"tag": "0005_add_deleted_at_index",
|
|
45
|
+
"breakpoints": true
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"idx": 6,
|
|
49
|
+
"version": "6",
|
|
50
|
+
"when": 1781000000000,
|
|
51
|
+
"tag": "0006_add_chat_sort_keys",
|
|
52
|
+
"breakpoints": true
|
|
32
53
|
}
|
|
33
54
|
]
|
|
34
55
|
}
|