@dungdq3/memex
v0.5.10
Published
CLI tool that aggregates AI chat history from multiple platforms into a searchable Markdown archive
Maintainers
Readme
memex
memex is a CLI tool that aggregates your AI chat history from multiple platforms into a single, searchable Markdown archive. It integrates with qmd for semantic search and LLM context injection.
AI Platforms memex sync workdir/ qmd
───────────── ──────────────────▶ ─────────────── ──────────────
Claude Code convert memory/ qmd search
ChatGPT (normalize to .md) wiki/ qmd query
Claude.ai
Gemini ~/.memex/
Grok state/sync.db
DeepSeek logs/
Codex config.json
OpenClawInstall
Requirement: Bun >= 1.3 must be available in PATH.
memex is distributed through the npm registry. You can install it with either npm or Bun.
Install from npm registry
Using npm:
npm install -g @dungdq3/memex
memex --helpUsing Bun:
bun add -g @dungdq3/memex
memex --helpBoth commands install the published package from the npm registry. The CLI itself still runs with Bun because bin/memex uses #!/usr/bin/env bun.
Local development install
Use bun link when you want the global memex command to run directly from your local checkout:
git clone https://github.com/dungdamquoc1993/memex.git
cd memex
bun install
bun link
memex --helpWith bun link, edits in the repo affect the global memex command immediately.
Check where memex is coming from
Use these commands whenever you are not sure whether memex is coming from npm, Bun, or a local link:
which -a memex
ls -l "$(which memex)"
realpath "$(which memex)"Common results:
/usr/local/bin/memexUsually means npm global from the system npm. Confirm with:
ls -l /usr/local/bin/memex
/usr/local/bin/npm list -g --depth=0 @dungdq3/memex/Users/<you>/.nvm/versions/node/<version>/bin/memexMeans npm global from the active nvm Node/npm. Confirm with:
which npm
npm prefix -g
npm list -g --depth=0 @dungdq3/memex/Users/<you>/.bun/bin/memexMeans Bun global or a Bun local link. Confirm with:
ls -l ~/.bun/bin/memex
ls -l ~/.bun/install/global/node_modulesIf ~/.bun/install/global/node_modules/memex or ~/.bun/install/global/node_modules/@dungdq3/memex points to your local checkout, you are using a local bun link.
Uninstall and clean old links
Remove npm global installs:
npm uninstall -g @dungdq3/memex
/usr/local/bin/npm uninstall -g @dungdq3/memexRemove Bun global installs:
bun remove --global @dungdq3/memexRemove a current local Bun link from inside the repo:
cd memex
bun unlinkIf you previously linked the package under an old package name, stale symlinks can remain. Remove only the memex symlinks:
rm -f ~/.bun/bin/memex
rm -f ~/.bun/install/global/node_modules/memex
rm -f ~/.bun/install/global/node_modules/@dungdq3/memexVerify that the command is gone:
which -a memexQuick Start
# 1. Initialize profile (default workdir = ~/.memex)
memex init
# Or choose a custom workdir (e.g. Dropbox, iCloud, a git repo)
memex init --workdir ~/Dropbox/memex-data
# 2. Sync Claude Code conversations (fully automatic — reads ~/.claude/projects/)
memex sync claude_code
# 3. For web platforms (ChatGPT, Claude.ai, Gemini, Grok, DeepSeek):
# Get the browser snippet pre-filled with your last sync date
memex sync-script chatgpt
# Open chatgpt.com → DevTools (F12) → Console → paste → Enter
# Move the downloaded file, then sync:
mv ~/Downloads/chatgpt_*.json "$(memex config get workdir)/memory/raw/chatgpt/"
memex sync chatgpt
# 4. Check status
memex statusCommands
memex init [--workdir <path>]
Initialize the memex profile. Run once after install.
- Internal state (
state/,logs/,config.json) always lives in~/.memex/. - User content (
memory/,wiki/,scripts/) goes into the workdir — defaults to~/.memex/but can be set to any path (Dropbox, iCloud Drive, a git repo, etc.).
memex init # workdir = ~/.memex (default)
memex init --workdir ~/Dropbox/memex # workdir = ~/Dropbox/memexThe chosen workdir is persisted to ~/.memex/config.json so subsequent commands pick it up automatically.
memex sync [source] [--dry-run]
Sync one or all sources. Sync is incremental and idempotent — unchanged conversations are skipped by content hash.
memex sync # sync all configured sources
memex sync claude_code # sync Claude Code only
memex sync chatgpt # sync ChatGPT only
memex sync deepseek # sync DeepSeek only
memex sync --dry-run # preview changes, no files writtenSupported sources: chatgpt, claude_web (alias: claude), gemini, grok, deepseek, claude_code, codex, openclaw
memex sync-script <source>
Print a browser console snippet pre-filled with your last sync date for a web platform. Paste the output into the browser's DevTools Console while logged in.
memex sync-script chatgpt
memex sync-script claude
memex sync-script gemini
memex sync-script grok
memex sync-script deepseekBrowser scripts use the browser's own runtime auth (cookies/tokens from the active session). No credentials are hardcoded or exported to disk.
memex status
Show sync statistics from sync.db.
Source | Conversations | Last Sync
----------------|---------------|--------------------
chatgpt | 2479 | 2026-04-14 04:23:32
claude_code | 17 | 2026-04-14 04:23:08
claude_web | 187 | 2026-04-14 04:23:40
gemini | 327 | 2026-04-14 04:23:47
grok | 12 | 2026-04-15 06:38:18
deepseek | 25 | 2026-04-15 06:57:29memex config <subcommand>
Read and write ~/.memex/config.json.
memex config list # print full config
memex config get workdir # print current workdir path
memex config set workdir ~/new/path # update workdir pointer (does not move data)
memex config path # print path to config.jsonmemex export [file]
Back up both the profile root (~/.memex/) and the workdir to a single .tar.gz archive.
memex export # creates ./memex-profile-YYYYMMDD-HHMMSS.tar.gz
memex export ~/backup/memex.tar.gz # write to specific pathmemex verify <file>
Validate a backup archive without restoring it. Checks that the tar is readable, the manifest is valid, and required directories are present.
memex verify ~/backup/memex.tar.gzmemex import <file> [--replace] [--workdir <path>]
Restore a backup. Fails if target paths already exist unless --replace is passed (moves existing data to *.backup-<timestamp> first, never deletes).
memex import ~/backup/memex.tar.gz
memex import ~/backup/memex.tar.gz --replace
# Restore to a different workdir (e.g. when moving to a new machine)
memex import ~/backup/memex.tar.gz --workdir ~/new/memex-dataIf the archive's original workdir path is not available on the current machine, memex will fail with a clear error and suggest the --workdir flag rather than silently restoring to the wrong location.
Platform Support
| Platform | Source key | Method | Incremental |
|---|---|---|---|
| Claude Code | claude_code | Automatic (reads ~/.claude/projects/) | Yes |
| ChatGPT | chatgpt | Browser script → JSON file | Yes |
| Claude.ai | claude_web / claude | Browser script → JSON file | Yes |
| Gemini | gemini | Browser script (batchexecute API) → JSON file | Yes |
| Grok | grok | Browser script (REST API) → JSON file | Yes |
| DeepSeek | deepseek | Browser script (runtime token) → JSON file | Yes |
| Codex | codex | Automatic (reads ~/.codex/) | Yes |
| OpenClaw | openclaw | Automatic (reads session files) | Yes |
Directory Structure
memex separates internal state from user content into two roots:
~/.memex/ # Profile root — always here, internal
├── state/
│ └── sync.db # SQLite dedup tracking
├── logs/
│ └── sync.log
└── config.json # workdir path + settings
<workdir>/ # Configurable — default is also ~/.memex
├── memory/ # Immutable — written by memex only
│ ├── chatgpt/
│ │ └── 2026/04/<id>.md # Normalized Markdown
│ ├── claude_web/
│ ├── claude_code/
│ ├── gemini/
│ ├── grok/
│ ├── deepseek/
│ ├── codex/
│ ├── openclaw/
│ ├── raw/ # Original JSON exports (not indexed)
│ │ ├── chatgpt/
│ │ ├── claude_web/
│ │ ├── gemini/
│ │ ├── grok/
│ │ └── deepseek/
│ └── attachments/ # Chat attachments (not indexed)
│
├── wiki/ # Mutable — agent and user editable
│ ├── domains/ # Knowledge domain notes
│ ├── references/ # Raw reference files (not indexed)
│ ├── profile.md # Personal context — LLM compiled
│ └── index.md # Content catalog
│
└── scripts/ # Generated browser export scriptsWorkdir resolution order (highest priority first):
--workdir <path>CLI flagMEMEX_WORKDIRenvironment variableworkdirfield in~/.memex/config.json- Default:
~/.memex
Rules:
memory/andwiki/contain only.mdfiles — these are what qmd indexes.memory/raw/is append-only; do not edit manually.attachments/andreferences/are not indexed.state/is internal; do not edit manually.
Each conversation is stored as one .md file with YAML frontmatter:
---
id: "chatgpt_abc123"
source: "chatgpt"
title: "My conversation title"
model: "gpt-4o"
created_at: "2026-04-10T03:15:00.000Z"
updated_at: "2026-04-13T09:22:00.000Z"
message_count: 24
original_url: "https://chatgpt.com/c/abc123"
---
## [2026-04-10 03:15:00] user
Message content...
## [2026-04-10 03:15:42] assistant (gpt-4o)
### Thinking
(reasoning block if present)
### Response
Response content...## headings at each message boundary allow qmd to chunk at the right granularity for search.
qmd Integration
# Register collections (once) — use your actual workdir path
qmd collection add "$(memex config get workdir)/memory" --name memex-memory
qmd collection add "$(memex config get workdir)/wiki" --name memex-wiki
# Add as LLM context
qmd context add qmd://memex-memory "Personal AI chat history: ChatGPT, Claude, Gemini, Grok, DeepSeek, Claude Code, Codex, OpenClaw"
qmd context add qmd://memex-wiki "Curated personal wiki, domain notes, profile"
# Index and embed
qmd update
qmd embed
# Search
qmd search "sourdough hydration"
qmd query "what have I discussed about sleep"
qmd get "#abc123"Adding an Adapter
Implement the Adapter interface and register it in src/cli/sync.ts:
// src/adapters/myplatform.ts
import type { Adapter } from './base.ts';
import type { Conversation } from '../normalize/schema.ts';
export class MyPlatformAdapter implements Adapter {
source = 'myplatform' as const;
async *sync(): AsyncIterable<Conversation> {
// Read data from the platform
// yield each Conversation
}
}Steps:
- Create
src/adapters/<platform>.tsimplementingAdapter - Place raw exports in
~/.memex/memory/raw/<platform>/ - Register in
src/cli/sync.tsin theADAPTERSobject - If browser-based, add
src/browser-scripts/<platform>.jsusingSINCE_DATEfor incremental sync - Add the source key to the
Sourceunion insrc/normalize/schema.ts
Roadmap
- [ ]
memex ingest <file>— manually ingest an arbitrary JSON file - [ ] Attachment handling — copy attachments to
memory/attachments/ - [ ]
memex watch— daemon that auto-syncs Claude Code on new sessions - [ ] MCP server — expose memex as a tool for LLM agents
License
MIT — see LICENSE
