artikeep 0.2.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.
Files changed (40) hide show
  1. artikeep-0.2.0/LICENSE +21 -0
  2. artikeep-0.2.0/PKG-INFO +257 -0
  3. artikeep-0.2.0/README.md +234 -0
  4. artikeep-0.2.0/artikeep/__init__.py +8 -0
  5. artikeep-0.2.0/artikeep/__main__.py +5 -0
  6. artikeep-0.2.0/artikeep/adapters/__init__.py +1 -0
  7. artikeep-0.2.0/artikeep/adapters/claude_code.py +478 -0
  8. artikeep-0.2.0/artikeep/adapters/codex.py +200 -0
  9. artikeep-0.2.0/artikeep/cli.py +201 -0
  10. artikeep-0.2.0/artikeep/config.py +73 -0
  11. artikeep-0.2.0/artikeep/gallery.py +242 -0
  12. artikeep-0.2.0/artikeep/gallery.template.html +958 -0
  13. artikeep-0.2.0/artikeep/importers/__init__.py +23 -0
  14. artikeep-0.2.0/artikeep/importers/chatgpt.py +92 -0
  15. artikeep-0.2.0/artikeep/importers/claude_ai.py +84 -0
  16. artikeep-0.2.0/artikeep/importers/files.py +40 -0
  17. artikeep-0.2.0/artikeep/install.py +424 -0
  18. artikeep-0.2.0/artikeep/issues.py +61 -0
  19. artikeep-0.2.0/artikeep/mcp_server.py +248 -0
  20. artikeep-0.2.0/artikeep/notify.py +39 -0
  21. artikeep-0.2.0/artikeep/search.py +151 -0
  22. artikeep-0.2.0/artikeep/server.py +320 -0
  23. artikeep-0.2.0/artikeep/store.py +294 -0
  24. artikeep-0.2.0/artikeep/util.py +197 -0
  25. artikeep-0.2.0/artikeep/viewers.py +406 -0
  26. artikeep-0.2.0/artikeep/worker.py +111 -0
  27. artikeep-0.2.0/artikeep.egg-info/PKG-INFO +257 -0
  28. artikeep-0.2.0/artikeep.egg-info/SOURCES.txt +38 -0
  29. artikeep-0.2.0/artikeep.egg-info/dependency_links.txt +1 -0
  30. artikeep-0.2.0/artikeep.egg-info/entry_points.txt +2 -0
  31. artikeep-0.2.0/artikeep.egg-info/top_level.txt +1 -0
  32. artikeep-0.2.0/pyproject.toml +38 -0
  33. artikeep-0.2.0/setup.cfg +4 -0
  34. artikeep-0.2.0/tests/test_claude_code.py +53 -0
  35. artikeep-0.2.0/tests/test_codex.py +65 -0
  36. artikeep-0.2.0/tests/test_importers.py +71 -0
  37. artikeep-0.2.0/tests/test_install.py +132 -0
  38. artikeep-0.2.0/tests/test_mcp.py +85 -0
  39. artikeep-0.2.0/tests/test_server.py +138 -0
  40. artikeep-0.2.0/tests/test_store.py +39 -0
artikeep-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 artikeep contributors
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,257 @@
1
+ Metadata-Version: 2.4
2
+ Name: artikeep
3
+ Version: 0.2.0
4
+ Summary: Never lose what your AI agents make: a local, versioned archive of Claude Code, Codex and chat artifacts, with a gallery and an MCP server.
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/aquahitt/artikeep
7
+ Project-URL: Changelog, https://github.com/aquahitt/artikeep/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/aquahitt/artikeep/issues
9
+ Keywords: claude,claude-code,codex,chatgpt,mcp,artifacts,ai-agents,archive,versioning,local-first
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Topic :: System :: Archiving :: Backup
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Dynamic: license-file
23
+
24
+ # artikeep
25
+
26
+ **Never lose what your AI agents make.**
27
+
28
+ English · [Русский](https://github.com/aquahitt/artikeep/blob/main/README.ru.md)
29
+
30
+ [![test](https://github.com/aquahitt/artikeep/actions/workflows/test.yml/badge.svg)](https://github.com/aquahitt/artikeep/actions/workflows/test.yml)
31
+ ![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-2E5E4E)
32
+ ![dependencies: none](https://img.shields.io/badge/dependencies-none-2E5E4E)
33
+ ![macOS | Linux](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-2E5E4E)
34
+ [![MIT](https://img.shields.io/badge/license-MIT-2E5E4E)](https://github.com/aquahitt/artikeep/blob/main/LICENSE)
35
+
36
+ Agents publish pages, canvases and documents to places you don't control: a hosted
37
+ artifact link, a chat you can lose access to, a temp folder that gets cleaned. artikeep
38
+ keeps a copy of each one on your disk the moment it is made. Every change becomes a
39
+ version, a gallery lets you browse and compare versions, and an MCP server lets any
40
+ agent search what you already have.
41
+
42
+ ![Search the archive, open an item, compare its first and current versions](https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/demo.gif)
43
+
44
+ - **Automatic where it can be.** Hooks in Claude Code and Codex capture without the
45
+ model having to remember anything.
46
+ - **Every change is a version.** Compare any two side by side, with the changed text lines.
47
+ - **Plain files, in git.** The archive is a folder of HTML, Markdown and JSON. It opens
48
+ without artikeep, and syncs between machines through a private git remote.
49
+ - **Agents can look it up.** Before rebuilding a report from scratch, an agent searches
50
+ the archive through MCP.
51
+ - **No dependencies.** Python 3.9+ standard library. Nothing to `pip install` for capture.
52
+
53
+ ## Quick start
54
+
55
+ ```bash
56
+ uv tool install git+https://github.com/aquahitt/artikeep # or: pipx install git+https://github.com/aquahitt/artikeep
57
+ artikeep init ~/artikeep # the archive folder (a git repo)
58
+ artikeep install # hooks + MCP for the agents found
59
+ artikeep doctor # check
60
+ ```
61
+
62
+ From now on, whatever Claude Code or Codex makes lands in `~/artikeep`. Open the
63
+ gallery with `artikeep open`, or `artikeep serve --open` for the local app.
64
+
65
+ No package manager? A clone works as is, with no install step:
66
+ `git clone https://github.com/aquahitt/artikeep ~/artikeep-src`, then
67
+ `python3 ~/artikeep-src/bin/artikeep init ~/artikeep` and so on.
68
+
69
+ Claude Code only? Use the plugin instead of `install`:
70
+ `/plugin marketplace add aquahitt/artikeep`, then `/plugin install artikeep@artikeep`
71
+ (details [below](#claude-code-plugin)).
72
+
73
+ ## What gets captured
74
+
75
+ | Source | How | What |
76
+ |---|---|---|
77
+ | Claude Code | hooks, automatic | pages published with the `Artifact` tool (with all their files), Claude Design canvases, Claude Docs documents (exported tab by tab), unpublished pages in the session scratchpad |
78
+ | Codex | hooks, automatic | documents a session writes that git does not keep — reports, pages, tables in temp folders, untracked or ignored files — plus the session's visualizations |
79
+ | Claude Desktop chat | MCP, on request | ask Claude to save what it made; the chat has no hooks, so this is the only live way in (the Code tab of Desktop is Claude Code and is captured automatically) |
80
+ | ChatGPT | `artikeep import chatgpt <export.zip>` | canvas documents, with every edit replayed as a version |
81
+ | claude.ai | `artikeep import claude-ai <export.zip>` | artifacts from chats, with every update as a version; React components open as live pages, offline too |
82
+ | Anything else | `artikeep add <file or folder>`, or the MCP `save_artifact` tool | whatever you point it at |
83
+
84
+ Files git already tracks are skipped: they are safe where they are.
85
+
86
+ ## The gallery
87
+
88
+ <picture>
89
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/gallery-dark.png">
90
+ <img alt="The gallery: items from Claude Code, Codex, Claude Desktop, ChatGPT and claude.ai with filters by project, source and type" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/gallery-light.png">
91
+ </picture>
92
+
93
+ `index.html` at the archive root: a static page that works from disk. Grid or list,
94
+ filters (project, source, type, how the copy was made), groups, full-text search,
95
+ a panel per item with its version history, side-by-side comparison of any two versions
96
+ with the changed text lines. Light and dark, English and Russian, usable on a phone.
97
+
98
+ <table>
99
+ <tr>
100
+ <td width="50%"><picture>
101
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/versions-dark.png">
102
+ <img alt="An item's panel: preview, where it came from, and its version history" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/versions-light.png">
103
+ </picture></td>
104
+ <td width="50%"><picture>
105
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/compare-dark.png">
106
+ <img alt="Two versions side by side, with the text lines that changed" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/compare-light.png">
107
+ </picture></td>
108
+ </tr>
109
+ <tr>
110
+ <td>Every save that changes something is a version, with its time, label and size of change.</td>
111
+ <td>Compare any two versions: both pages live, plus what changed in the text.</td>
112
+ </tr>
113
+ <tr>
114
+ <td><img alt="Full-text search across every item, with matches highlighted" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/search-light.png"></td>
115
+ <td align="center"><img alt="The gallery on a phone" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/mobile-light.png" width="210"></td>
116
+ </tr>
117
+ <tr>
118
+ <td>Full-text search across every item and source, in any language.</td>
119
+ <td>Works on a phone too.</td>
120
+ </tr>
121
+ </table>
122
+
123
+ Keyboard: `/` search, `G` / `L` grid or list, `←` `→` previous and next item, `C` compare
124
+ first and current versions, `Esc` close, `?` all shortcuts.
125
+
126
+ ### As a local app
127
+
128
+ `artikeep serve` runs the gallery on `http://127.0.0.1:8765` (archived files on the next
129
+ port; `--port` changes both). On top of the file version it searches the full text of every
130
+ item and highlights the match, updates by itself when an agent saves something, lets you
131
+ rename and describe an item, make an old version current (as a new version: nothing is
132
+ overwritten), delete an item (it stays in the archive's git history), show it in Finder, and
133
+ add files or chat exports by dropping them on the page. Pages that load their own files with
134
+ `fetch()` or ES modules, which browsers refuse over `file://`, work here. In Chrome, "Install
135
+ as app" gives it its own window and dock icon.
136
+
137
+ When capturing fails, artikeep also says so on the desktop (macOS notification, or
138
+ `notify-send` on Linux), at most once an hour per kind of failure; `"notify": false` turns it off.
139
+
140
+ ## Install, in detail
141
+
142
+ `install` finds Claude Code (`~/.claude`), Codex (`~/.codex`) and Claude Desktop, adds its
143
+ hooks next to yours (nothing else is touched; every edited file is backed up first),
144
+ registers the MCP server with each agent's own `mcp add` (for Desktop, in
145
+ `claude_desktop_config.json`; reopen Desktop after), and puts a short rules block into
146
+ `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`. If `~/.local/bin` is on your `PATH`, it also
147
+ links the `artikeep` command there. `--agents claude-code,codex,claude-desktop` limits it,
148
+ `--dry-run` shows the changes, `--uninstall` removes them.
149
+
150
+ To sync across machines, give the archive a **private** remote:
151
+ `artikeep init ~/artikeep --remote git@github.com:you/my-artifacts.git`. The background
152
+ pass commits after each capture and pushes.
153
+
154
+ Claude Code deletes session transcripts after 30 days by default. `install` raises
155
+ `cleanupPeriodDays` to ten years: transcripts are the last place a lost artifact can be
156
+ recovered from.
157
+
158
+ ### Claude Code plugin
159
+
160
+ Instead of `install`, Claude Code users can add the plugin:
161
+ `/plugin marketplace add aquahitt/artikeep`, then `/plugin install artikeep@artikeep`.
162
+ It brings the same hooks and MCP server; Codex still needs `artikeep install --agents codex`.
163
+ Use one or the other for Claude Code, not both (`artikeep doctor` flags it). The plugin
164
+ keeps copies in `~/artikeep` from the first artifact on; run `artikeep init` (with
165
+ `--remote` if you want sync) to give that folder git history, and set
166
+ `"cleanupPeriodDays": 3650` in `~/.claude/settings.json` yourself — a plugin cannot change
167
+ it, and `doctor` reminds you.
168
+
169
+ ## Use
170
+
171
+ ```bash
172
+ artikeep open # the gallery as a file: filters, versions, compare
173
+ artikeep serve --open # the same gallery as a local app
174
+ artikeep search kitchen layout # full-text, any language; --agent, --type, --project, --json
175
+ artikeep add ~/Downloads/report.pdf --title "Q3 report"
176
+ artikeep import chatgpt ~/Downloads/chatgpt-export.zip
177
+ artikeep scan codex --all # archive deliverables from past Codex sessions
178
+ artikeep scan claude-code # recover publishes missed in the last 30 days (--days N, --all)
179
+ artikeep rebuild # rebuild gallery and search index, commit and push
180
+ ```
181
+
182
+ (`artikeep` here is the command `uv tool` or `pipx` installed, the one `install` linked into
183
+ `~/.local/bin` for a clone, or `python3 <clone>/bin/artikeep`.)
184
+
185
+ **From any agent**, through MCP:
186
+
187
+ | Tool | Does |
188
+ |---|---|
189
+ | `search_artifacts` | find items by words, source, type |
190
+ | `read_artifact` | metadata, file list and text of an item or one of its versions |
191
+ | `list_versions` | versions with time, label and size of change |
192
+ | `diff_versions` | changed text lines between two versions |
193
+ | `save_artifact` | keep a page or document (off unless `--mcp-save`) |
194
+
195
+ By default an agent sees only items made in the repository it works in. See
196
+ [SECURITY.md](https://github.com/aquahitt/artikeep/blob/main/SECURITY.md) for why, and how to widen it.
197
+
198
+ ## Settings
199
+
200
+ The archive is `~/artikeep` unless `artikeep init <path>` chose another folder (remembered in
201
+ `~/.config/artikeep/config.json`) or `$ARTIKEEP_HOME` is set. Behaviour lives in
202
+ `artikeep.json` at the archive root, so it travels with the archive:
203
+
204
+ | Key | Default | Does |
205
+ |---|---|---|
206
+ | `git_push` | `true` | push to the archive's remote after each commit |
207
+ | `thumbnails` | `"auto"` | gallery thumbnails, if Playwright is importable by `python3`; `"off"` disables |
208
+ | `issue_links` | `true` | link items to GitHub issues that mention them (needs `gh`), once a day |
209
+ | `lang` | `"auto"` | gallery and hook messages: `"en"`, `"ru"`, or follow the browser / locale |
210
+ | `notify` | `true` | desktop notification when capturing fails |
211
+ | `mcp_scope` | `"project"` | `"all"` lets agents see every project's items |
212
+ | `mcp_save` | `false` | let agents save through MCP |
213
+ | `codex_extensions` | `.html .htm .svg .md .pdf .docx .pptx .xlsx .csv` | which files a Codex session made count as deliverables |
214
+
215
+ ## How it works
216
+
217
+ <img alt="Claude Code, Codex, Claude Desktop, chat exports and any file flow into ~/artikeep, a git repository; the gallery, the MCP server and a private remote read from it" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/how-it-works.svg" width="100%">
218
+
219
+ Hooks only copy files and start a detached background pass, so an agent never waits on
220
+ disk or network. The background pass renders viewers (Design canvases, Markdown
221
+ documents, React components with the libraries claude.ai artifacts may import: React,
222
+ Tailwind, recharts, lucide-react, lodash, d3, mathjs, PapaParse, SheetJS, three, Tone,
223
+ Chart.js, and stand-ins for shadcn/ui), makes offline copies with CDN scripts and fonts
224
+ vendored, updates the search index (SQLite FTS5) and the gallery, then commits and pushes.
225
+ The on-disk layout is specified in [FORMAT.md](https://github.com/aquahitt/artikeep/blob/main/FORMAT.md); any tool can write into it.
226
+
227
+ ## Limits, honestly
228
+
229
+ - **macOS and Linux.** Windows is not supported (file locking uses `fcntl`).
230
+ - **Host formats are undocumented.** The hook inputs of Claude Code's `Artifact` tool,
231
+ Codex rollouts and the Claude Docs export can change with any release. artikeep logs
232
+ every raw hook input to `.hooklog/payloads.jsonl`, and on session start checks recent
233
+ transcripts for publishes it missed and archives them late. `artikeep doctor` shows
234
+ when each source last saved something.
235
+ - **Importers are checked against documented shapes and synthetic exports**, not yet
236
+ against many real ones. Anything they do not recognise is counted and reported, not
237
+ guessed. Please open an issue with an anonymised sample if an import comes out wrong.
238
+ - **Codex has no artifact tool.** artikeep recognises deliverables by extension, by being
239
+ outside git, and by being named in the final answer. A file a script wrote and the
240
+ answer never mentioned is missed.
241
+ - **Web chats are not captured live.** ChatGPT and claude.ai come in through their data
242
+ exports, which you request by hand.
243
+
244
+ ## Development
245
+
246
+ ```bash
247
+ python3 -m unittest discover -s tests -t . # the test suite, no dependencies
248
+ scripts/e2e-codex.sh # live check of the Codex adapter: one real Codex request
249
+ scripts/readme-media/make.sh # rebuild the README screenshots and GIF
250
+ ```
251
+
252
+ The screenshots come from a synthetic archive (`scripts/readme-media/seed.py`), not from
253
+ anyone's real one; rebuilding them needs Playwright with Chromium and Pillow.
254
+
255
+ ## License
256
+
257
+ MIT. Changes are listed in [CHANGELOG.md](https://github.com/aquahitt/artikeep/blob/main/CHANGELOG.md).
@@ -0,0 +1,234 @@
1
+ # artikeep
2
+
3
+ **Never lose what your AI agents make.**
4
+
5
+ English · [Русский](https://github.com/aquahitt/artikeep/blob/main/README.ru.md)
6
+
7
+ [![test](https://github.com/aquahitt/artikeep/actions/workflows/test.yml/badge.svg)](https://github.com/aquahitt/artikeep/actions/workflows/test.yml)
8
+ ![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-2E5E4E)
9
+ ![dependencies: none](https://img.shields.io/badge/dependencies-none-2E5E4E)
10
+ ![macOS | Linux](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-2E5E4E)
11
+ [![MIT](https://img.shields.io/badge/license-MIT-2E5E4E)](https://github.com/aquahitt/artikeep/blob/main/LICENSE)
12
+
13
+ Agents publish pages, canvases and documents to places you don't control: a hosted
14
+ artifact link, a chat you can lose access to, a temp folder that gets cleaned. artikeep
15
+ keeps a copy of each one on your disk the moment it is made. Every change becomes a
16
+ version, a gallery lets you browse and compare versions, and an MCP server lets any
17
+ agent search what you already have.
18
+
19
+ ![Search the archive, open an item, compare its first and current versions](https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/demo.gif)
20
+
21
+ - **Automatic where it can be.** Hooks in Claude Code and Codex capture without the
22
+ model having to remember anything.
23
+ - **Every change is a version.** Compare any two side by side, with the changed text lines.
24
+ - **Plain files, in git.** The archive is a folder of HTML, Markdown and JSON. It opens
25
+ without artikeep, and syncs between machines through a private git remote.
26
+ - **Agents can look it up.** Before rebuilding a report from scratch, an agent searches
27
+ the archive through MCP.
28
+ - **No dependencies.** Python 3.9+ standard library. Nothing to `pip install` for capture.
29
+
30
+ ## Quick start
31
+
32
+ ```bash
33
+ uv tool install git+https://github.com/aquahitt/artikeep # or: pipx install git+https://github.com/aquahitt/artikeep
34
+ artikeep init ~/artikeep # the archive folder (a git repo)
35
+ artikeep install # hooks + MCP for the agents found
36
+ artikeep doctor # check
37
+ ```
38
+
39
+ From now on, whatever Claude Code or Codex makes lands in `~/artikeep`. Open the
40
+ gallery with `artikeep open`, or `artikeep serve --open` for the local app.
41
+
42
+ No package manager? A clone works as is, with no install step:
43
+ `git clone https://github.com/aquahitt/artikeep ~/artikeep-src`, then
44
+ `python3 ~/artikeep-src/bin/artikeep init ~/artikeep` and so on.
45
+
46
+ Claude Code only? Use the plugin instead of `install`:
47
+ `/plugin marketplace add aquahitt/artikeep`, then `/plugin install artikeep@artikeep`
48
+ (details [below](#claude-code-plugin)).
49
+
50
+ ## What gets captured
51
+
52
+ | Source | How | What |
53
+ |---|---|---|
54
+ | Claude Code | hooks, automatic | pages published with the `Artifact` tool (with all their files), Claude Design canvases, Claude Docs documents (exported tab by tab), unpublished pages in the session scratchpad |
55
+ | Codex | hooks, automatic | documents a session writes that git does not keep — reports, pages, tables in temp folders, untracked or ignored files — plus the session's visualizations |
56
+ | Claude Desktop chat | MCP, on request | ask Claude to save what it made; the chat has no hooks, so this is the only live way in (the Code tab of Desktop is Claude Code and is captured automatically) |
57
+ | ChatGPT | `artikeep import chatgpt <export.zip>` | canvas documents, with every edit replayed as a version |
58
+ | claude.ai | `artikeep import claude-ai <export.zip>` | artifacts from chats, with every update as a version; React components open as live pages, offline too |
59
+ | Anything else | `artikeep add <file or folder>`, or the MCP `save_artifact` tool | whatever you point it at |
60
+
61
+ Files git already tracks are skipped: they are safe where they are.
62
+
63
+ ## The gallery
64
+
65
+ <picture>
66
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/gallery-dark.png">
67
+ <img alt="The gallery: items from Claude Code, Codex, Claude Desktop, ChatGPT and claude.ai with filters by project, source and type" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/gallery-light.png">
68
+ </picture>
69
+
70
+ `index.html` at the archive root: a static page that works from disk. Grid or list,
71
+ filters (project, source, type, how the copy was made), groups, full-text search,
72
+ a panel per item with its version history, side-by-side comparison of any two versions
73
+ with the changed text lines. Light and dark, English and Russian, usable on a phone.
74
+
75
+ <table>
76
+ <tr>
77
+ <td width="50%"><picture>
78
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/versions-dark.png">
79
+ <img alt="An item's panel: preview, where it came from, and its version history" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/versions-light.png">
80
+ </picture></td>
81
+ <td width="50%"><picture>
82
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/compare-dark.png">
83
+ <img alt="Two versions side by side, with the text lines that changed" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/compare-light.png">
84
+ </picture></td>
85
+ </tr>
86
+ <tr>
87
+ <td>Every save that changes something is a version, with its time, label and size of change.</td>
88
+ <td>Compare any two versions: both pages live, plus what changed in the text.</td>
89
+ </tr>
90
+ <tr>
91
+ <td><img alt="Full-text search across every item, with matches highlighted" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/search-light.png"></td>
92
+ <td align="center"><img alt="The gallery on a phone" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/mobile-light.png" width="210"></td>
93
+ </tr>
94
+ <tr>
95
+ <td>Full-text search across every item and source, in any language.</td>
96
+ <td>Works on a phone too.</td>
97
+ </tr>
98
+ </table>
99
+
100
+ Keyboard: `/` search, `G` / `L` grid or list, `←` `→` previous and next item, `C` compare
101
+ first and current versions, `Esc` close, `?` all shortcuts.
102
+
103
+ ### As a local app
104
+
105
+ `artikeep serve` runs the gallery on `http://127.0.0.1:8765` (archived files on the next
106
+ port; `--port` changes both). On top of the file version it searches the full text of every
107
+ item and highlights the match, updates by itself when an agent saves something, lets you
108
+ rename and describe an item, make an old version current (as a new version: nothing is
109
+ overwritten), delete an item (it stays in the archive's git history), show it in Finder, and
110
+ add files or chat exports by dropping them on the page. Pages that load their own files with
111
+ `fetch()` or ES modules, which browsers refuse over `file://`, work here. In Chrome, "Install
112
+ as app" gives it its own window and dock icon.
113
+
114
+ When capturing fails, artikeep also says so on the desktop (macOS notification, or
115
+ `notify-send` on Linux), at most once an hour per kind of failure; `"notify": false` turns it off.
116
+
117
+ ## Install, in detail
118
+
119
+ `install` finds Claude Code (`~/.claude`), Codex (`~/.codex`) and Claude Desktop, adds its
120
+ hooks next to yours (nothing else is touched; every edited file is backed up first),
121
+ registers the MCP server with each agent's own `mcp add` (for Desktop, in
122
+ `claude_desktop_config.json`; reopen Desktop after), and puts a short rules block into
123
+ `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`. If `~/.local/bin` is on your `PATH`, it also
124
+ links the `artikeep` command there. `--agents claude-code,codex,claude-desktop` limits it,
125
+ `--dry-run` shows the changes, `--uninstall` removes them.
126
+
127
+ To sync across machines, give the archive a **private** remote:
128
+ `artikeep init ~/artikeep --remote git@github.com:you/my-artifacts.git`. The background
129
+ pass commits after each capture and pushes.
130
+
131
+ Claude Code deletes session transcripts after 30 days by default. `install` raises
132
+ `cleanupPeriodDays` to ten years: transcripts are the last place a lost artifact can be
133
+ recovered from.
134
+
135
+ ### Claude Code plugin
136
+
137
+ Instead of `install`, Claude Code users can add the plugin:
138
+ `/plugin marketplace add aquahitt/artikeep`, then `/plugin install artikeep@artikeep`.
139
+ It brings the same hooks and MCP server; Codex still needs `artikeep install --agents codex`.
140
+ Use one or the other for Claude Code, not both (`artikeep doctor` flags it). The plugin
141
+ keeps copies in `~/artikeep` from the first artifact on; run `artikeep init` (with
142
+ `--remote` if you want sync) to give that folder git history, and set
143
+ `"cleanupPeriodDays": 3650` in `~/.claude/settings.json` yourself — a plugin cannot change
144
+ it, and `doctor` reminds you.
145
+
146
+ ## Use
147
+
148
+ ```bash
149
+ artikeep open # the gallery as a file: filters, versions, compare
150
+ artikeep serve --open # the same gallery as a local app
151
+ artikeep search kitchen layout # full-text, any language; --agent, --type, --project, --json
152
+ artikeep add ~/Downloads/report.pdf --title "Q3 report"
153
+ artikeep import chatgpt ~/Downloads/chatgpt-export.zip
154
+ artikeep scan codex --all # archive deliverables from past Codex sessions
155
+ artikeep scan claude-code # recover publishes missed in the last 30 days (--days N, --all)
156
+ artikeep rebuild # rebuild gallery and search index, commit and push
157
+ ```
158
+
159
+ (`artikeep` here is the command `uv tool` or `pipx` installed, the one `install` linked into
160
+ `~/.local/bin` for a clone, or `python3 <clone>/bin/artikeep`.)
161
+
162
+ **From any agent**, through MCP:
163
+
164
+ | Tool | Does |
165
+ |---|---|
166
+ | `search_artifacts` | find items by words, source, type |
167
+ | `read_artifact` | metadata, file list and text of an item or one of its versions |
168
+ | `list_versions` | versions with time, label and size of change |
169
+ | `diff_versions` | changed text lines between two versions |
170
+ | `save_artifact` | keep a page or document (off unless `--mcp-save`) |
171
+
172
+ By default an agent sees only items made in the repository it works in. See
173
+ [SECURITY.md](https://github.com/aquahitt/artikeep/blob/main/SECURITY.md) for why, and how to widen it.
174
+
175
+ ## Settings
176
+
177
+ The archive is `~/artikeep` unless `artikeep init <path>` chose another folder (remembered in
178
+ `~/.config/artikeep/config.json`) or `$ARTIKEEP_HOME` is set. Behaviour lives in
179
+ `artikeep.json` at the archive root, so it travels with the archive:
180
+
181
+ | Key | Default | Does |
182
+ |---|---|---|
183
+ | `git_push` | `true` | push to the archive's remote after each commit |
184
+ | `thumbnails` | `"auto"` | gallery thumbnails, if Playwright is importable by `python3`; `"off"` disables |
185
+ | `issue_links` | `true` | link items to GitHub issues that mention them (needs `gh`), once a day |
186
+ | `lang` | `"auto"` | gallery and hook messages: `"en"`, `"ru"`, or follow the browser / locale |
187
+ | `notify` | `true` | desktop notification when capturing fails |
188
+ | `mcp_scope` | `"project"` | `"all"` lets agents see every project's items |
189
+ | `mcp_save` | `false` | let agents save through MCP |
190
+ | `codex_extensions` | `.html .htm .svg .md .pdf .docx .pptx .xlsx .csv` | which files a Codex session made count as deliverables |
191
+
192
+ ## How it works
193
+
194
+ <img alt="Claude Code, Codex, Claude Desktop, chat exports and any file flow into ~/artikeep, a git repository; the gallery, the MCP server and a private remote read from it" src="https://raw.githubusercontent.com/aquahitt/artikeep/main/docs/media/how-it-works.svg" width="100%">
195
+
196
+ Hooks only copy files and start a detached background pass, so an agent never waits on
197
+ disk or network. The background pass renders viewers (Design canvases, Markdown
198
+ documents, React components with the libraries claude.ai artifacts may import: React,
199
+ Tailwind, recharts, lucide-react, lodash, d3, mathjs, PapaParse, SheetJS, three, Tone,
200
+ Chart.js, and stand-ins for shadcn/ui), makes offline copies with CDN scripts and fonts
201
+ vendored, updates the search index (SQLite FTS5) and the gallery, then commits and pushes.
202
+ The on-disk layout is specified in [FORMAT.md](https://github.com/aquahitt/artikeep/blob/main/FORMAT.md); any tool can write into it.
203
+
204
+ ## Limits, honestly
205
+
206
+ - **macOS and Linux.** Windows is not supported (file locking uses `fcntl`).
207
+ - **Host formats are undocumented.** The hook inputs of Claude Code's `Artifact` tool,
208
+ Codex rollouts and the Claude Docs export can change with any release. artikeep logs
209
+ every raw hook input to `.hooklog/payloads.jsonl`, and on session start checks recent
210
+ transcripts for publishes it missed and archives them late. `artikeep doctor` shows
211
+ when each source last saved something.
212
+ - **Importers are checked against documented shapes and synthetic exports**, not yet
213
+ against many real ones. Anything they do not recognise is counted and reported, not
214
+ guessed. Please open an issue with an anonymised sample if an import comes out wrong.
215
+ - **Codex has no artifact tool.** artikeep recognises deliverables by extension, by being
216
+ outside git, and by being named in the final answer. A file a script wrote and the
217
+ answer never mentioned is missed.
218
+ - **Web chats are not captured live.** ChatGPT and claude.ai come in through their data
219
+ exports, which you request by hand.
220
+
221
+ ## Development
222
+
223
+ ```bash
224
+ python3 -m unittest discover -s tests -t . # the test suite, no dependencies
225
+ scripts/e2e-codex.sh # live check of the Codex adapter: one real Codex request
226
+ scripts/readme-media/make.sh # rebuild the README screenshots and GIF
227
+ ```
228
+
229
+ The screenshots come from a synthetic archive (`scripts/readme-media/seed.py`), not from
230
+ anyone's real one; rebuilding them needs Playwright with Chromium and Pillow.
231
+
232
+ ## License
233
+
234
+ MIT. Changes are listed in [CHANGELOG.md](https://github.com/aquahitt/artikeep/blob/main/CHANGELOG.md).
@@ -0,0 +1,8 @@
1
+ """artikeep: a local, versioned archive of what AI agents make for you.
2
+
3
+ Hooks of Claude Code and Codex copy every artifact into a git-backed folder the
4
+ moment it is made; importers take official chat exports; a stdio MCP server lets
5
+ any agent search and read the archive. Standard library only, Python >= 3.9.
6
+ """
7
+
8
+ __version__ = "0.2.0"
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from artikeep.cli import main
4
+
5
+ sys.exit(main())
@@ -0,0 +1 @@
1
+ """Capture adapters: one module per agent host. Each reads hook JSON from stdin."""