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.
- artikeep-0.2.0/LICENSE +21 -0
- artikeep-0.2.0/PKG-INFO +257 -0
- artikeep-0.2.0/README.md +234 -0
- artikeep-0.2.0/artikeep/__init__.py +8 -0
- artikeep-0.2.0/artikeep/__main__.py +5 -0
- artikeep-0.2.0/artikeep/adapters/__init__.py +1 -0
- artikeep-0.2.0/artikeep/adapters/claude_code.py +478 -0
- artikeep-0.2.0/artikeep/adapters/codex.py +200 -0
- artikeep-0.2.0/artikeep/cli.py +201 -0
- artikeep-0.2.0/artikeep/config.py +73 -0
- artikeep-0.2.0/artikeep/gallery.py +242 -0
- artikeep-0.2.0/artikeep/gallery.template.html +958 -0
- artikeep-0.2.0/artikeep/importers/__init__.py +23 -0
- artikeep-0.2.0/artikeep/importers/chatgpt.py +92 -0
- artikeep-0.2.0/artikeep/importers/claude_ai.py +84 -0
- artikeep-0.2.0/artikeep/importers/files.py +40 -0
- artikeep-0.2.0/artikeep/install.py +424 -0
- artikeep-0.2.0/artikeep/issues.py +61 -0
- artikeep-0.2.0/artikeep/mcp_server.py +248 -0
- artikeep-0.2.0/artikeep/notify.py +39 -0
- artikeep-0.2.0/artikeep/search.py +151 -0
- artikeep-0.2.0/artikeep/server.py +320 -0
- artikeep-0.2.0/artikeep/store.py +294 -0
- artikeep-0.2.0/artikeep/util.py +197 -0
- artikeep-0.2.0/artikeep/viewers.py +406 -0
- artikeep-0.2.0/artikeep/worker.py +111 -0
- artikeep-0.2.0/artikeep.egg-info/PKG-INFO +257 -0
- artikeep-0.2.0/artikeep.egg-info/SOURCES.txt +38 -0
- artikeep-0.2.0/artikeep.egg-info/dependency_links.txt +1 -0
- artikeep-0.2.0/artikeep.egg-info/entry_points.txt +2 -0
- artikeep-0.2.0/artikeep.egg-info/top_level.txt +1 -0
- artikeep-0.2.0/pyproject.toml +38 -0
- artikeep-0.2.0/setup.cfg +4 -0
- artikeep-0.2.0/tests/test_claude_code.py +53 -0
- artikeep-0.2.0/tests/test_codex.py +65 -0
- artikeep-0.2.0/tests/test_importers.py +71 -0
- artikeep-0.2.0/tests/test_install.py +132 -0
- artikeep-0.2.0/tests/test_mcp.py +85 -0
- artikeep-0.2.0/tests/test_server.py +138 -0
- 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.
|
artikeep-0.2.0/PKG-INFO
ADDED
|
@@ -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
|
+
[](https://github.com/aquahitt/artikeep/actions/workflows/test.yml)
|
|
31
|
+

|
|
32
|
+

|
|
33
|
+

|
|
34
|
+
[](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
|
+

|
|
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).
|
artikeep-0.2.0/README.md
ADDED
|
@@ -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
|
+
[](https://github.com/aquahitt/artikeep/actions/workflows/test.yml)
|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
[](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
|
+

|
|
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 @@
|
|
|
1
|
+
"""Capture adapters: one module per agent host. Each reads hook JSON from stdin."""
|