Persistent storage for trading — trade journal (SQLite WAL at ${CLAUDE_PLUGIN_DATA}/journal.sqlite, survives plugin updates), historical OHLC + L1/L2 store (DuckDB columnar at ${CLAUDE_PLUGIN_DATA}/prices.duckdb), research embedding store (LanceDB vectors at ${CLAUDE_PLUGIN_DATA}/research.lancedb), and model-weight cache (${CLAUDE_PLUGIN_DATA}/models/). All paths use CLAUDE_PLUGIN_DATA so they persist across plugin updates; CLAUDE_PLUGIN_ROOT would be wiped on reinstall. Use when the user says "log this trade", "import historical prices", "store research findings", "cache this model", or any persistence task.
Context: Plugin binaries change on update. User DATA must not. This skill puts every durable artifact in ${CLAUDE_PLUGIN_DATA} (resolves to ~/.claude/plugins/data/{plugin-id}/) which SURVIVES updates. Never write journals/models/prices under ${CLAUDE_PLUGIN_ROOT} — that's wiped on every plugin upgrade.
| Store | Backend | Path | Purpose |
|---|---|---|---|
| Trade journal | SQLite WAL | ${CLAUDE_PLUGIN_DATA}/journal.sqlite | every placed order + fill + outcome |
| Price store | DuckDB columnar | ${CLAUDE_PLUGIN_DATA}/prices.duckdb | OHLCV + L1/L2 snapshots |
| Research vectors | LanceDB | ${CLAUDE_PLUGIN_DATA}/research.lancedb | embeddings of news / social / findings |
| Model cache | flat files | ${CLAUDE_PLUGIN_DATA}/models/{name}.pt |
| PyTorch state dicts + ONNX exports |
CREATE TABLE trades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts INTEGER NOT NULL, -- unix seconds
venue TEXT NOT NULL, -- 'polymarket' | 'coinbase-cdp' | custom
market TEXT, -- condition_id / token_id / symbol
side TEXT, -- BUY / SELL / long / short
size REAL,
entry REAL,
exit REAL,
stop REAL,
R_initial REAL,
pnl_usd REAL,
pnl_R REAL,
cluster TEXT, -- correlation-cluster tag
strategy TEXT, -- strategy name / id
notes TEXT,
order_id TEXT, -- venue's order id
signature TEXT -- tx hash / signed order signature
);
CREATE INDEX idx_trades_ts ON trades(ts);
CREATE INDEX idx_trades_strategy ON trades(strategy);
CREATE INDEX idx_trades_cluster ON trades(cluster);
# log a trade (called by PostToolUse hook automatically)
uv run ${CLAUDE_PLUGIN_ROOT}/skills/trading-storage/scripts/store.py log \
--venue polymarket --market 0xcond... --side BUY --size 100 --entry 0.42 --strategy thesis-fed-cut
# query
uv run ${CLAUDE_PLUGIN_ROOT}/skills/trading-storage/scripts/store.py query \
--venue polymarket --strategy thesis-fed-cut --since 2026-01-01 --format json
# import historical OHLCV from a CSV into DuckDB
uv run ${CLAUDE_PLUGIN_ROOT}/skills/trading-storage/scripts/store.py ingest-prices \
--symbol BTC-USD --file btc.csv
# embed a research note into LanceDB
uv run ${CLAUDE_PLUGIN_ROOT}/skills/trading-storage/scripts/store.py embed-research \
--market 0xcond... --text "Fed signaled dovish pivot..."
# vector search
uv run ${CLAUDE_PLUGIN_ROOT}/skills/trading-storage/scripts/store.py search-research \
--query "rate cut probability" --k 5
${CLAUDE_PLUGIN_ROOT}. It's the CACHE dir and gets wiped on plugin updates.${CLAUDE_PLUGIN_DATA} is created lazily. First write creates the dir. Don't assume it exists.PRAGMA journal_mode=WAL..pt files are 100 MB – 5 GB. Old models accumulate; add a cleanup policy.${CLAUDE_PLUGIN_DATA} to off-device storage.