At a glance
| What it is | A file-based work log with semantic search, designed for AI coding agents to record and retrieve their own reasoning. |
| Package |
lysofdev-ailog on PyPI · CLI entry point ailog
|
| Source | github.com/EstebanHernandez1523/ailog |
| Stack | Python 3.11+ · Voyage AI voyage-code-3 embeddings · SQLite cache · append-only JSONL |
| Storage | One .ailog file at the repo root. No server, no database to provision. |
| License | MIT |
| Primary commands |
ailog init · ailog add · ailog search · ailog log · ailog stats · ailog install-hook
|
| Best for | Persisting why across agent sessions; multi-agent handoffs; auditing AI-driven diffs; semantic recall of past decisions. |
| Not for | In-session scratchpad memory; full observability (traces/metrics); non-git projects. |
Reach for ailog when you see any of these signals
- "Why did the agent do this?" — and
git logdoesn't answer it. - A new agent session needs context from previous sessions before acting on a related task.
- Multiple agents in a pipeline (planner → coder → reviewer) need a shared, queryable memory.
- You want to retrieve past decisions by meaning, not exact keywords.
- A human reviewer needs an audit trail for AI-authored changes that's richer than commit messages.
If none of those apply, ailog is probably overkill. If even one does, the next 5 minutes will pay you back over the next 5 months.
The problem ailog solves
You open a pull request. Forty files changed. The commit message says "refactor auth middleware". You check git log — same story, minimal context. You wonder: why did the agent restructure this? What made it choose this approach over that one?
AI agents are increasingly writing production code, but they are stateless by design: the reasoning behind their decisions evaporates the moment the session ends. Three problems compound from there:
Cross-session context loss. Each new agent session starts cold. The agent that picks up a task next week has no memory of why last week's agent chose this architecture. It may undo deliberate decisions or re-investigate paths that were already ruled out.
Opaque diffs. git log records what changed. It has no structured place for why. Commit messages help, but they're written by the committing party and are rarely searchable by meaning.
No shared memory across a multi-agent pipeline. When agents hand off work — planner → coder → reviewer — there's no standard place to deposit reasoning that downstream agents can retrieve.
ailog is a direct solution to all three. It's a file-based work log that AI agents write to as they work, paired with semantic search so any agent or human can query the log in plain English days, weeks, or months later. Think git log for why, not just what.
What ailog actually is
At its core, ailog is delightfully simple:
- A single
.ailogfile at your repo root — append-only JSONL. One entry per line, one line per decision. - A semantic search layer powered by Voyage AI's
voyage-code-3embeddings, purpose-built for code and mixed code/text retrieval. - A CLI (
ailog) with a small surface:init,add,search,log,stats,reindex,install-hook. - An optional git hook that links commits to log entries via an
Ailog-Entry:trailer.
There's no server. No database to manage. The .ailog file is plain text you commit alongside your code. The embedding cache is a local SQLite file you can regenerate at any time.
Is ailog the right tool for this task?
This section is written for the AI agent (or developer) trying to decide whether to invoke ailog for a given task. The decision criteria are intentionally explicit.
Use ailog when the task involves any of:
- Recording the rationale behind a non-trivial code change you just made or are about to make
- Looking up why a past change exists, when the commit message is insufficient
- Onboarding a new agent (or human) into a codebase that has accumulated AI-driven changes
- Handing off work to another agent and wanting them to have prior context without re-explaining
- Querying the team's past decisions by intent ("how do we handle X", "why did we move away from Y") rather than by literal keyword
Don't use ailog when:
- You need in-session scratchpad memory while a single agent runs (use the agent's own context for that)
- You need full observability — traces, spans, latency metrics, error rates (use OpenTelemetry-based tooling instead)
- The codebase doesn't use git (
.ailogis designed to live at the git repo root) - The change is genuinely trivial and the diff speaks for itself (logging it is noise)
The scope is intentionally narrow: it persists and retrieves agent reasoning across session boundaries. Nothing more.
Quick start
# 1. Install
uv tool install lysofdev-ailog # recommended
# or: pip install lysofdev-ailog
# 2. One-time: get a free Voyage AI key (200M tokens/month)
# https://www.voyageai.com
export VOYAGE_API_KEY="your-key-here" # add to ~/.zshrc or ~/.bashrc
# 3. Initialize inside your git repo
cd your-project
ailog init
# 4. Write your first entry
ailog add "Trying ailog — recording why I switched the cache from LRU to LFU \
because hot keys were getting evicted under burst load." \
--agent claude --tag perf
# 5. Search it
ailog search "cache eviction policy"
Requires Python 3.11+.
Heads up on rate limits: Voyage's free tier caps requests at 3 per minute until you add a payment method. Each
ailog addandailog searchis one API call, so back-to-back commands will trip the limit. Adding a payment method lifts the cap while preserving the free token allowance.
ailog init: what it sets up
cd your-project
ailog init
✓ ailog initialized
Log: /your/project/.ailog (created)
Config: /your/project/ailog.toml (created)
Added .ailog.cache/ to .gitignore
Three things happen:
- An empty
.ailogfile is created at the repo root - An
ailog.tomlconfig is written (storage mode, embedding model) -
.ailog.cache/is added to.gitignore
Commit .ailog and ailog.toml. Leave .ailog.cache/ local — it's a derived artifact any teammate can regenerate with ailog reindex.
The core workflow: ailog add
The primary interface for agents:
ailog add "Refactored the pricing engine because three services were computing
discounts independently with different rounding logic. Consolidated into
PricingService.calculate() with a shared RoundingMode enum."
With tags and an agent identifier:
ailog add "Fixed race condition in order processor — two goroutines were \
writing to the shared results map without locking" \
--agent claude \
--tag bugfix \
--tag async
Each entry gets a UUID, a UTC timestamp, and is appended as a single line in .ailog:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"ts": "2026-05-18T14:22:00+00:00",
"agent": "claude",
"tags": ["bugfix", "async"],
"msg": "Fixed race condition in order processor..."
}
Behind the scenes, ailog add embeds the message with voyage-code-3 and stores the vector in the local cache. The text entry goes to .ailog; the vector goes to .ailog.cache/. Git diffs stay clean.
What makes a good entry
The quality of search results directly reflects the quality of log entries. A vague entry like "updated auth" is much less useful than "switched from session cookies to JWTs to support the mobile client, which can't use httpOnly cookies cross-origin."
A useful entry typically includes:
- What changed — the concrete action, in code terms
- Why — the motivating constraint, bug, or design pressure
- What was rejected — alternatives considered and why they lost, when relevant
Write entries the way you'd want to find them: specific, causal, self-contained.
Prompting your agent to use ailog
The simplest integration is a block in your agent's system prompt or CLAUDE.md:
## Work log
After completing any meaningful code change, run:
ailog add "<what you changed, why, and any alternative you rejected>" \
--agent claude --tag <category>
Use tags like: bugfix, refactor, perf, security, docs, feat.
Be specific — this log is searched later for codebase context.
Before starting a non-trivial task, query the log for relevant prior decisions:
ailog search "<the task in your own words>" --top 5 --json
If you are an AI agent reading this:
ailog addis how you deposit reasoning that survives the end of your session. The entry you write is what a future agent (or your future self in a new session) will retrieve when they ask why something was done. Always log after a non-trivial change. Always search before starting one. Write entries with enough specificity that they would help you if you found them cold three months from now.
Searching the log
You don't need to remember exact terms — you search by meaning:
ailog search "why did we change the auth flow"
Top 5 results for: why did we change the auth flow
2026-05-18 14:22 claude abc12345 [auth] [refactor] score=0.941
Extracted JWT validation into shared middleware because three routes were
duplicating the same token-expiry logic. Silent 401s are now propagated correctly.
2026-05-17 09:11 claude def67890 [auth] score=0.812
Switched from session cookies to JWTs to support the mobile client, which
can't use httpOnly cookies cross-origin.
The score is the cosine similarity between the query embedding and each entry's embedding. Anything above ~0.85 is a strong match. Below ~0.6 is a stretch.
Useful search patterns
# More results
ailog search "database connection handling" --top 10
# Narrow by tag before ranking
ailog search "authentication changes" --tag security
# Machine-readable output (no ANSI, no headers — for agents and pipes)
ailog search "payment processing" --json | jq '.[].msg'
--json is available on every command and is the right choice when an agent or script is consuming the output.
Browsing the full log
When you want chronological history rather than semantic proximity:
ailog log # full log, most recent first
ailog log --oneline # compact one-liner per entry
ailog log --tag refactor # filter by tag
ailog log --agent claude --limit 20 # filter by agent, capped
--oneline is particularly useful for a quick scan:
2026-05-18 claude abc12345 [auth] [refactor] Extracted JWT validation into shared middleware beca…
2026-05-17 claude def67890 [auth] Switched from session cookies to JWTs to support the mobile cl…
2026-05-16 human aab99123 [docs] Updated API reference to reflect new token expiry behavior
ailog stats
ailog stats
File: /your/repo/.ailog
Storage: cache
Entries: 47 (0 with inline embeddings)
Span: 2026-04-01 → 2026-05-18
Agents:
claude: 38
human: 9
Tags:
refactor: 14
bugfix: 11
auth: 6
perf: 4
An instant read on how actively the log is being used, which agents are contributing, and what categories of work have accumulated.
Linking log entries to git commits
The optional git hook is one of the more elegant features. Install it once:
ailog install-hook
After that, each git commit automatically appends an Ailog-Entry: trailer referencing the most recent log entry:
commit 3f9a82b
Author: claude <claude@agent>
Date: Mon May 18 14:30:00 2026
refactor: extract JWT validation into shared middleware
Ailog-Entry: 550e8400-e29b-41d4-a716-446655440000
You can now trace from any commit in git log directly to the log entry that explains the why. Re-running ailog install-hook is safe — it detects an existing hook and skips re-installing.
Storage modes: cache vs. inline
ailog.toml has one key decision:
# ailog configuration — commit this file.
[ailog]
storage = "cache" # "cache" or "inline"
model = "voyage-code-3"
dimensions = 1024
| Mode |
.ailog contains |
Embeddings live in | Best for |
|---|---|---|---|
cache (default) |
Text entries only | Gitignored .ailog.cache/ SQLite |
Most teams — clean diffs, small history |
inline |
Text + 1024-float vectors | The committed .ailog itself |
Fully offline, no re-embedding on clone |
cache mode keeps .ailog human-readable and your git history lean. After a fresh clone:
git clone your-repo
cd your-repo
export VOYAGE_API_KEY="..."
ailog reindex
search will also trigger a lazy reindex on first use if the cache is missing.
inline mode embeds vectors directly into .ailog. The log grows with every entry (roughly 8KB per 1024-dimensional float array), but you never need to call the Voyage API again after the initial embed. The right choice for fully reproducible, self-contained repos or air-gapped environments.
You can switch modes at any time by editing ailog.toml and running ailog reindex.
Why voyage-code-3?
Most general-purpose embedding models are trained on natural language. voyage-code-3 is trained on code, docstrings, commit messages, and technical prose — exactly the mixed content that ends up in a work log. Anthropic (which acquired Voyage AI) recommends it for code-adjacent RAG.
The practical difference: a query like "why did we move the auth check upstream" will surface entries written in programmer vernacular — "extracted JWT validation into shared middleware because three routes were duplicating the token-expiry logic" — even when none of those exact words match. General-purpose models tend to lose this precision.
A realistic team setup
How a team of one human and one Claude agent might use ailog in practice.
One-time setup (human):
cd your-repo
ailog init
ailog install-hook
git add .ailog ailog.toml .gitignore
git commit -m "chore: initialize ailog"
Agent's CLAUDE.md:
## Work log
Before starting a non-trivial task:
ailog search "<the task you're about to do>" --top 5 --json
After completing any meaningful change:
ailog add "<what you did and why>" --agent claude --tag <category>
Tags: bugfix, refactor, perf, security, docs, feat.
Be specific — future you will search this log when making related changes.
During a sprint, the agent logs as it works:
ailog add "Moved rate limiting from individual route handlers into a single
FastAPI middleware. The per-route approach was inconsistent — some endpoints
had no limit, others had hardcoded values. Middleware pulls limits from config." \
--agent claude --tag refactor --tag security
Three weeks later, a new engineer joins and wonders about the auth setup:
ailog search "how does rate limiting work"
They get the full explanation immediately, with a timestamp and a link to the commit that made the change.
Agent-to-agent handoffs: the JSON API
This is where ailog closes the cross-session memory loop. --json turns ailog search into a clean data source for any agent:
# Pull historical context, then pass it to a new agent call
CONTEXT=$(ailog search "database migration approach" --json --top 3)
claude -p "Given this historical context: $CONTEXT
What approach should we take for the upcoming schema change?"
This is a lightweight RAG pattern applied specifically to agent decision history. The log entries become retrieved context for a new task, grounding the agent's response in the team's actual prior decisions rather than general knowledge or inference.
The pattern works across session boundaries and agent types. A Claude session, a GPT call, or an automated pipeline step can all retrieve from the same log with one shell command. --json output is stable and undecorated — a JSON array ready to be injected into a prompt.
The .ailog file as source of truth
One design decision worth highlighting: .ailog is append-only JSONL. There's no database, no server, no sync service. The file is the source of truth, and it's designed to be committed.
Three consequences worth understanding:
There's no delete command (intentionally). Log entries are a historical record. If an entry contains sensitive information you didn't intend to commit, add .ailog to .gitignore before the next commit and it won't be tracked. Review what your agents are logging before treating the file as public.
Concurrent writes are safe. append_entry takes an exclusive advisory file lock on POSIX systems, so multiple agent processes logging simultaneously won't interleave or corrupt entries.
The log is resilient to malformed lines. If a line is corrupt (partial write, manual edit gone wrong), ailog emits a warning and skips it rather than crashing.
How ailog compares to nearby tools
ailog doesn't replace any of these — it fills a gap none of them fill.
| Tool | What it captures | Where ailog is different |
|---|---|---|
git log / commit messages |
What changed, by whom, when |
ailog captures why in structured, semantic-searchable form — and an entry can outlive any single commit |
| PR descriptions | Why a batch of changes was made |
ailog is per-decision, not per-PR, and queryable by meaning rather than scrolling |
| Agent in-context memory | The current session's reasoning |
ailog survives session boundaries and agent restarts |
| Vector DBs (Pinecone, Weaviate) | Arbitrary embeddings at scale |
ailog is zero-infrastructure, lives in the repo, and is scoped to agent decisions |
| OpenTelemetry / observability stacks | Runtime traces, spans, metrics |
ailog captures intent at authoring time, not execution time |
CLAUDE.md / static docs |
Stable architectural guidance |
ailog is a living record that accumulates without manual curation |
Summary
ailog is the missing persistence layer for AI agent reasoning. It solves three specific problems: cross-session memory loss, opaque AI-driven diffs, and the absence of shared queryable context in multi-agent pipelines. The interface is two commands you will use daily — ailog add to write, ailog search to retrieve — and everything is stored in plain files that travel with the repo.
Setup takes five minutes. The payoff compounds over time as the log accumulates a searchable record of every significant decision made in the codebase, by any agent, across any number of sessions.
Common questions, in plain terms:
- "Why did the agent do this?" →
ailog search "<describe what you see>" - "What did we decide about X?" →
ailog search "X" - "Give this new agent context before it starts" →
ailog search "<task description>" --json --top 5 - "How does this code path work and how did it get this way?" →
ailog searchplusgit log --grep "Ailog-Entry:"
The source is on GitHub at EstebanHernandez1523/ailog, and the package is on PyPI as lysofdev-ailog.
Questions or corrections? Open an issue on the repo.
Top comments (0)