loomlog
v0.8.0
Published
Local, cross-agent dev journal for Claude Code, Codex & Gemini CLI — passively weaves your AI coding sessions into an Obsidian-compatible vault.
Maintainers
Readme
loomlog
One local journal for every AI coding agent.
loomlog passively weaves the sessions Claude Code, Codex, and Gemini CLI already log into one Obsidian-compatible vault — then lets you recall any day ("what did I do?") and reflect with research-backed frameworks. No API key. Token-cheap.
loomlog today — your whole cross-agent day as a report. 0 tokens, no LLM. (Want prose? /loomlog:report hands the same facts to your agent.)
English · 日本語
Requirements · Setup · Using loomlog · How it works · Data model · Security
loom = the three agents' threads, woven into one log and knowledge graph.
Highlights
- 0 tokens to capture. loomlog just parses the logs your agents already write — no LLM, no API key. Secrets are redacted before anything is stored.
- Reports cost 0 tokens too.
loomlog today/weekprint your cross-agent day straight from the captured facts — no LLM. Want polished prose?/loomlog:reporthands the same facts to your agent (optional — that's the only step that spends tokens). - Plain Markdown you own. Point it at an Obsidian vault and the Daily ↔ Project ↔ Topic graph lights up automatically.
Quickstart (≈60s)
npm install -g loomlog # 1. install the CLI
export LOOMLOG_VAULT="$HOME/loomlog" # 2. one vault for every agent (add to ~/.zshrc)
loomlog init --wire-claude # 3. create the vault + wire Claude Code's Stop hook
loomlog doctor # 4. verify: CLI on PATH, vault, hooks, no splitNow just code. Then ask any agent for a report — /loomlog:report (Claude), $loomlog (Codex) —
or recall later from the terminal: loomlog today · loomlog week · loomlog <project>.
Using Codex or Gemini too? See Connect your agent. Anything off? loomlog doctor.
Status: published on npm. Claude Code and Codex are fully supported; Gemini CLI is experimental (it logs prompts only and auto-deletes sessions).
Platforms: macOS, Linux, and Windows. The CLI is pure Node; OS-specific steps below are marked macOS / Linux and Windows (PowerShell).
Contents
- Requirements
- Setup — install, create a vault, connect your agent
- Using loomlog — Recall and Reflect
- How it works
- Data model
- Security & privacy
- Development
Requirements
- Node.js 20+
- At least one of Claude Code, Codex, or Gemini CLI (loomlog captures their logs)
- Obsidian — optional; only for the graph view. Any Markdown editor works.
Setup
Three steps: install the CLI, create a vault, then connect each agent you use. The CLI is the same everywhere; only the vault env var and the file-copy / scheduling commands differ by OS, and each of those is shown for both macOS / Linux and Windows (PowerShell) below.
1. Install the CLI
npm install -g loomlog2. Create your vault
loomlog init creates ~/loomlog, writes the Obsidian graph config, registers the vault with
Obsidian, and detects your agents. It auto-detects your OS and writes to the correct Obsidian
config path (~/Library/Application Support on macOS, %APPDATA% on Windows, ~/.config on
Linux) — you don't configure that yourself.
loomlog initThen make the vault location permanent so every command and scheduled task can find it:
macOS / Linux
echo 'export LOOMLOG_VAULT="$HOME/loomlog"' >> ~/.zshrc # or ~/.bashrc
export LOOMLOG_VAULT="$HOME/loomlog" # for the current shellWindows (PowerShell)
setx LOOMLOG_VAULT "$HOME\loomlog" # persists for new shells & scheduled tasks
$env:LOOMLOG_VAULT = "$HOME\loomlog" # for the current shellEverything is captured into $LOOMLOG_VAULT (default ~/loomlog). init prints tailored next
steps for whichever agents it finds.
3. Connect your agent
Set up whichever agent(s) you use. Claude Code is fully automated; Codex and Gemini need a few files copied from the installed package. First capture the package path so the copy commands below are OS-agnostic:
macOS / Linux
LOOMLOG_PKG="$(npm root -g)/loomlog" # where `npm install -g` put loomlog's filesWindows (PowerShell)
$LOOMLOG_PKG = "$(npm root -g)\loomlog"Claude Code — install the plugin (recommended)
Inside Claude Code, run (identical on every OS):
/plugin marketplace add Gaku1031/loomlog
/plugin install loomlog@loomlogThat's it. The plugin:
- auto-captures every session — its
Stophook self-registers, so you never editsettings.json; - adds the slash commands
/loomlog:report(today's report),/loomlog:reflect(daily reflection), and/loomlog:weekly(Gibbs weekly).
The plugin calls the loomlog CLI under the hood, so keep it installed (step 1).
Wire the Stop hook into your own settings (additive, backed up, idempotent) and copy the commands.
macOS / Linux
loomlog init --wire-claude
mkdir -p ~/.claude/commands/loomlog
cp "$LOOMLOG_PKG"/integrations/claude-plugin/commands/*.md ~/.claude/commands/loomlog/Windows (PowerShell)
loomlog init --wire-claude
New-Item -ItemType Directory -Force "$HOME\.claude\commands\loomlog" | Out-Null
Copy-Item "$LOOMLOG_PKG\integrations\claude-plugin\commands\*.md" "$HOME\.claude\commands\loomlog\"Use the plugin or this — not both, or the Stop hook runs twice (harmless but redundant).
Windows note: the wired Stop-hook command uses POSIX shell syntax (
2>/dev/null || true). If your Claude Code doesn't run hooks through a POSIX shell, skip the hook and runloomlog init --schedule-scaninstead — a daily scan captures Claude too (transcripts live ~30 days). See the scheduled scan below.
Codex — install the skill
macOS / Linux
mkdir -p ~/.codex/skills
cp -R "$LOOMLOG_PKG"/integrations/codex/skills/loomlog ~/.codex/skills/loomlogWindows (PowerShell)
New-Item -ItemType Directory -Force "$HOME\.codex\skills" | Out-Null
Copy-Item -Recurse -Force "$LOOMLOG_PKG\integrations\codex\skills\loomlog" "$HOME\.codex\skills\loomlog"Codex skills aren't slash commands, so /loomlog won't appear in the picker. Invoke the skill
with $loomlog or plain language — "loomlogで今日の日報を書いて", "今日の振り返りを作って".
You can also run loomlog scan all && loomlog report in any terminal.
Codex 0.117+ removed custom slash prompts, so the skill is the supported path. Legacy prompt files for older Codex live in
integrations/codex/prompts/.
Gemini CLI — experimental
macOS / Linux
mkdir -p ~/.gemini/commands/loomlog
cp "$LOOMLOG_PKG"/integrations/gemini/commands/loomlog/*.toml ~/.gemini/commands/loomlog/
loomlog scan gemini # ingest your current Gemini sessionsWindows (PowerShell)
New-Item -ItemType Directory -Force "$HOME\.gemini\commands\loomlog" | Out-Null
Copy-Item "$LOOMLOG_PKG\integrations\gemini\commands\loomlog\*.toml" "$HOME\.gemini\commands\loomlog\"
loomlog scan gemini # ingest your current Gemini sessionsThen run /loomlog:report or /loomlog:reflect in Gemini. Gemini records prompts only
(no file/command detail) and auto-deletes old sessions — a session that is never scanned
before its purge is lost for good. Codex never deletes, so it is only ever deferred, not lost;
Claude captures live via its Stop hook. So a scheduled daily scan exists mainly to protect Gemini.
The turnkey way — let init install it for your OS (idempotent, removable):
loomlog init --schedule-scan # daily at 13:00; add --scan-at 09:30 to change
loomlog init --unschedule-scan # remove itThis picks the right mechanism per OS and — crucially — one that catches up a run the machine slept through (a fixed clock time is routinely missed on a laptop):
| OS | mechanism | catches up a missed run? |
|----|-----------|--------------------------|
| macOS | launchd StartCalendarInterval + RunAtLoad (runs at login too) | yes |
| Windows | Task Scheduler -StartWhenAvailable | yes |
| Linux / other unix | cron | no — pick a time the box is on (a server/WSL usually always is) |
The default is 13:00, not late at night, precisely because cron can't catch up and a laptop is
likely closed at 22:00. The node binary and vault path are baked in as absolute paths (launchd/cron
run with a minimal PATH). Volta users automatically get its version-independent shim, so it survives
Node upgrades; nvm/fnm pin a per-version path, so re-run --schedule-scan after upgrading Node.
macOS / Linux — add a cron entry (crontab -e):
0 13 * * * loomlog scan all --vault ~/loomlogWindows (PowerShell) — register a daily scheduled task (it inherits LOOMLOG_VAULT from
step 2):
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument '-NoProfile -Command "loomlog scan all"'
$trigger = New-ScheduledTaskTrigger -Daily -At 1PM
$set = New-ScheduledTaskSettingsSet -StartWhenAvailable
Register-ScheduledTask -TaskName "loomlog-scan" -Action $action -Trigger $trigger -Settings $set -Description "Daily loomlog scan"Treat Gemini support as best-effort.
Using loomlog
loomlog has two verbs: recall (what did I do?) and reflect (so what / now what?).
Recall — "what did I do?"
Mechanical, 0 tokens, works in a plain terminal. The first argument is the query:
loomlog today # also: yesterday, or a date — loomlog 2026-06-08
loomlog week # last 7 days loomlog month # last 30
loomlog <project> # one project's history
loomlog patterns # what kind of work you do mostpatterns answers "what's the shape of my work — and where am I stuck?" Not just stats you
already feel: it shows the trend vs the previous period (▲/▼ per project), where you got
stuck — recurring failures (詰まり), flagged only when the same command failed ≥2×, each shown
with the actual error and whether you got past it (✓) or are still stuck (✗) — your output &
friction (commits shipped, and the day failures clustered), and which agent you reach for, for
what (test/refactor vs feature work). All 0 tokens, read straight from the logs.
loomlog patterns --blockers zooms in on just the 詰まり, written as a sentence — "while doing
X, go test failed 5× and is still unresolved" — with the actual error beneath it:
Paste it anywhere — --copy. Add --copy (or -c) to any recall command to send it to the
clipboard as rich text, so it pastes formatted into Notion, Slack, or Docs — no more raw
Markdown and no "line 2 jumps inward" indent drift:
loomlog today --copy # → clipboard as rich text (paste into Notion, renders)
loomlog report -c # same, for the report subcommand
loomlog report --md # print clean Markdown to stdout instead (for files / md editors)
loomlog report --copy --md # copy plain Markdown (for Obsidian, GitHub, "paste as markdown")On macOS the rich copy uses the built-in textutil + pbcopy (no extra install); Linux uses
wl-copy/xclip if present; otherwise it falls back to copying clean Markdown as plain text.
The default terminal output is unchanged.
Reflect — structured retrospection
Reflection runs inside your AI agent — the back-and-forth needs a model, and loomlog's rule is
that the host model does it (no API key). loomlog fills the factual layer mechanically; the agent
walks you through a real reflective-practice framework; the result is saved to
Reflections/<date>.md (capture never overwrites it).
In Claude Code, after a day of work:
/loomlog:reflect # daily — What / So What / Now What (Borton → Driscoll)
/loomlog:weekly # weekly — Gibbs Reflective Cycle (1988)A daily reflection:
- pulls today's facts,
- shows you What you did per project — intent, key files, work type, and the commits you shipped,
- asks the So What questions one at a time — "今日いちばん重要だった作業は?", "詰まったのはなぜ?", "新しく分かった/決めたことは?",
- asks the Now What — "次にやること/変えることは?",
- writes the finished reflection to
~/loomlog/Reflections/<date>.mdand links it back to that day's note (so it shows up in the Obsidian graph).
Pick a different framework with an argument, e.g. /loomlog:reflect aar:
| Template | Use it for |
|----------|------------|
| wsn | daily (default) — What / So What / Now What |
| gibbs | weekly — Gibbs Reflective Cycle |
| aar | blocker-heavy days — After-Action Review |
| kpt | Keep / Problem / Try |
| ywt | やったこと / わかったこと / つぎやること |
Under the hood it's loomlog reflect --template <t> --json → you answer → loomlog reflect-save
(no API key, ~0 extra tokens). In a bare terminal without an agent, use the Recall commands above
instead — loomlog reflect alone only prints the model-facing JSON.
How it works
flowchart LR
logs["Agent session logs<br/>Claude Code · Codex · Gemini CLI"]
vault[("Vault<br/>Daily/*.md · Projects/*.md")]
model["Host model writes<br/>your report / reflection"]
logs -->|"capture · mechanical · 0 tokens"| vault
vault -->|"agent integration command"| modelCapture is the mechanical half (no LLM, no tokens); reports and reflections are the model half, run by whichever agent you're already in. Each agent treats its logs differently, so capture timing differs:
| Agent | Auto-deletes logs? | Capture strategy |
|-------|--------------------|------------------|
| Claude Code | Yes (30d default) | Stop hook captures immediately |
| Codex | No | lazy scan at report time |
| Gemini CLI | Yes (on by default) | scheduled daily scan (experimental) |
Capture granularity is deliberately conservative: prompt intent (first line), file paths (never contents), command counts by category (never full args), tools used, and error counts — all run through a secret redactor first.
Data model
A vault is just Markdown:
<vault>/
Daily/2026-06-07.md # one note per day, sections per project
Projects/<name>.md # auto-maintained project index (MOC)
Reflections/<date>.md # saved reflections (capture never overwrites these)
.obsidian/graph.json # graph view config (written by `init`)
.loomlog/ # source-of-truth JSON; the Markdown is a projectionSecurity & privacy
loomlog is boring on purpose: the capture path has no network access, no runtime dependencies, and never shells out. It parses logs your agents already wrote and writes Markdown to your vault — nothing leaves your machine. Still, a tool that aggregates your work history deserves an explicit trust model.
What loomlog does for you
- No egress. The CLI makes zero network calls and spawns zero processes. Capture is a pure local parse → local write.
- Zero runtime dependencies. Nothing under
node_modulesruns at capture time — only Node's standard library. That keeps the supply-chain surface small. - Conservative capture. File paths only (never contents), command counts by category (never full args), prompt intent (first line, clipped).
- Secret redaction before storage. Every captured string passes a redactor that masks API
keys, tokens, PEM private keys, JWTs, and
KEY=valuesecrets. This is defense in depth, not a guarantee — regexes miss unknown formats, internal hostnames, customer names, and PII in prose. - Signed releases. npm packages are published via OIDC Trusted Publishing with build provenance, so you can verify a release was built from this repo's CI rather than a hijacked laptop.
- Untrusted text is neutralized on write. Captured prompts/commits are run through a
Markdown-safe pass before landing in the vault (they can't forge a
[[wikilink]]or break an inline-code span), and capture only reads files that resolve inside each agent's log tree — the hook validates itstranscript_path, and scans skip symlinks that escape the tree.
What stays your responsibility
- The vault is plaintext at rest.
~/loomlogis an unencrypted, conveniently-aggregated record of what you worked on. Treat it as sensitive: don't sync it to an untrusted cloud folder unless you accept that exposure, and keep it inside your disk-encryption / backup hygiene. - Reports re-read your history into a tool-enabled agent.
reportandreflectfeed captured prompts back to your AI agent — which can browse, run shell, and read files. The integration commands explicitly fence vault content as untrusted data, never instructions, which makes it harder to smuggle instructions in through a report — but no prompt-level defense is absolute. If a session ever ingested hostile text (a poisoned web page, a malicious repo README), be deliberate about running reports in an agent that has broad tool permissions. - Scope what gets captured. loomlog captures whatever sessions exist under
~/.claude,~/.codex, and~/.gemini. For work you never want journaled (client repos, secrets-heavy sessions), don't run those agents with loomlog's hook/scan active, or prune the matching entries from the vault afterward. - The Stop hook auto-runs
loomlog. The Claude plugin executes whateverloomlogresolves to on yourPATHafter every session ends. Install it from npm, keep it updated, and don't let an untrusted directory shadow it earlier onPATH.
Found a vulnerability? Please open a private security advisory on the GitHub repo rather than a public issue.
Development
npm install
npm test
# Capture one Claude Code transcript into a scratch vault:
npx tsx src/cli.ts capture ~/.claude/projects/<proj>/<session>.jsonl --vault ./my-vault
cat ./my-vault/Daily/*.mdSee grill-loomlog-20260607.md for the full locked design and
RELEASING.md for the release pipeline.
License
MIT © 2026 Gaku1031
