{"slug": "lysofdev-ailog-a-git-log-for-why-your-ai-agent-did-what-it-did", "title": "lysofdev-ailog: A git log for Why Your AI Agent Did What It Did", "summary": "Ailog**, a file-based work log tool designed to capture and preserve the reasoning behind AI agents' coding decisions. It addresses the problem of stateless AI agents losing context across sessions, resulting in opaque diffs and no shared memory in multi-agent pipelines. The tool stores append-only JSONL entries in a `.ailog` file at the repo root, paired with semantic search via Voyage AI embeddings, allowing agents or humans to query the \"why\" behind changes in plain English.", "body_md": "## At a glance\n\nWhat it is |\nA file-based work log with semantic search, designed for AI coding agents to record and retrieve their own reasoning. |\nPackage |\n`lysofdev-ailog` on PyPI · CLI entry point `ailog`\n|\nSource |\n|\n\n**Stack**`voyage-code-3`\n\nembeddings · SQLite cache · append-only JSONL**Storage**`.ailog`\n\nfile at the repo root. No server, no database to provision.**License****Primary commands**`ailog init`\n\n· `ailog add`\n\n· `ailog search`\n\n· `ailog log`\n\n· `ailog stats`\n\n· `ailog install-hook`\n\n**Best for*** why*across agent sessions; multi-agent handoffs; auditing AI-driven diffs; semantic recall of past decisions.**Not for**###\n\nReach for `ailog`\n\nwhen you see any of these signals\n\n- \"Why did the agent do this?\" — and\n`git log`\n\ndoesn't answer it. - A new agent session needs context from previous sessions before acting on a related task.\n- Multiple agents in a pipeline (planner → coder → reviewer) need a shared, queryable memory.\n- You want to retrieve past decisions by\n*meaning*, not exact keywords. - A human reviewer needs an audit trail for AI-authored changes that's richer than commit messages.\n\nIf none of those apply, `ailog`\n\nis probably overkill. If even one does, the next 5 minutes will pay you back over the next 5 months.\n\n## The problem `ailog`\n\nsolves\n\nYou open a pull request. Forty files changed. The commit message says `\"refactor auth middleware\"`\n\n. You check `git log`\n\n— same story, minimal context. You wonder: *why* did the agent restructure this? What made it choose this approach over that one?\n\nAI 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:\n\n**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.\n\n**Opaque diffs.** `git log`\n\nrecords *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.\n\n**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.\n\n`ailog`\n\nis 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`\n\nfor *why*, not just *what*.\n\n## What `ailog`\n\nactually is\n\nAt its core, `ailog`\n\nis delightfully simple:\n\n- A single\nat your repo root — append-only JSONL. One entry per line, one line per decision.`.ailog`\n\nfile - A\n**semantic search** layer powered by Voyage AI's`voyage-code-3`\n\nembeddings, purpose-built for code and mixed code/text retrieval. - A\n**CLI**(`ailog`\n\n) with a small surface:`init`\n\n,`add`\n\n,`search`\n\n,`log`\n\n,`stats`\n\n,`reindex`\n\n,`install-hook`\n\n. - An optional\n**git hook** that links commits to log entries via an`Ailog-Entry:`\n\ntrailer.\n\nThere's no server. No database to manage. The `.ailog`\n\nfile is plain text you commit alongside your code. The embedding cache is a local SQLite file you can regenerate at any time.\n\n## Is `ailog`\n\nthe right tool for this task?\n\nThis section is written for the AI agent (or developer) trying to decide whether to invoke `ailog`\n\nfor a given task. The decision criteria are intentionally explicit.\n\n**Use ailog when the task involves any of:**\n\n- Recording the rationale behind a non-trivial code change you just made or are about to make\n- Looking up\n*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\n- Handing off work to another agent and wanting them to have prior context without re-explaining\n- 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\n\n**Don't use ailog when:**\n\n- You need in-session scratchpad memory while a single agent runs (use the agent's own context for that)\n- You need full observability — traces, spans, latency metrics, error rates (use OpenTelemetry-based tooling instead)\n- The codebase doesn't use git (\n`.ailog`\n\nis designed to live at the git repo root) - The change is genuinely trivial and the diff speaks for itself (logging it is noise)\n\nThe scope is intentionally narrow: it persists and retrieves agent reasoning across session boundaries. Nothing more.\n\n## Quick start\n\n```\n# 1. Install\nuv tool install lysofdev-ailog            # recommended\n# or: pip install lysofdev-ailog\n\n# 2. One-time: get a free Voyage AI key (200M tokens/month)\n#    https://www.voyageai.com\nexport VOYAGE_API_KEY=\"your-key-here\"     # add to ~/.zshrc or ~/.bashrc\n\n# 3. Initialize inside your git repo\ncd your-project\nailog init\n\n# 4. Write your first entry\nailog add \"Trying ailog — recording why I switched the cache from LRU to LFU \\\nbecause hot keys were getting evicted under burst load.\" \\\n  --agent claude --tag perf\n\n# 5. Search it\nailog search \"cache eviction policy\"\n```\n\nRequires Python 3.11+.\n\nHeads up on rate limits:Voyage's free tier caps requests at 3 per minute until you add a payment method. Each`ailog add`\n\nand`ailog search`\n\nis 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.\n\n## `ailog init`\n\n: what it sets up\n\n```\ncd your-project\nailog init\n✓ ailog initialized\n  Log:     /your/project/.ailog  (created)\n  Config:  /your/project/ailog.toml  (created)\n  Added .ailog.cache/ to .gitignore\n```\n\nThree things happen:\n\n- An empty\n`.ailog`\n\nfile is created at the repo root - An\n`ailog.toml`\n\nconfig is written (storage mode, embedding model) -\n`.ailog.cache/`\n\nis added to`.gitignore`\n\n**Commit .ailog and ailog.toml. Leave .ailog.cache/ local** — it's a derived artifact any teammate can regenerate with\n\n`ailog reindex`\n\n.##\n\nThe core workflow: `ailog add`\n\nThe primary interface for agents:\n\n```\nailog add \"Refactored the pricing engine because three services were computing\ndiscounts independently with different rounding logic. Consolidated into\nPricingService.calculate() with a shared RoundingMode enum.\"\n```\n\nWith tags and an agent identifier:\n\n```\nailog add \"Fixed race condition in order processor — two goroutines were \\\n  writing to the shared results map without locking\" \\\n  --agent claude \\\n  --tag bugfix \\\n  --tag async\n```\n\nEach entry gets a UUID, a UTC timestamp, and is appended as a single line in `.ailog`\n\n:\n\n```\n{\n  \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"ts\": \"2026-05-18T14:22:00+00:00\",\n  \"agent\": \"claude\",\n  \"tags\": [\"bugfix\", \"async\"],\n  \"msg\": \"Fixed race condition in order processor...\"\n}\n```\n\nBehind the scenes, `ailog add`\n\nembeds the message with `voyage-code-3`\n\nand stores the vector in the local cache. The text entry goes to `.ailog`\n\n; the vector goes to `.ailog.cache/`\n\n. Git diffs stay clean.\n\n### What makes a good entry\n\nThe quality of search results directly reflects the quality of log entries. A vague entry like `\"updated auth\"`\n\nis much less useful than `\"switched from session cookies to JWTs to support the mobile client, which can't use httpOnly cookies cross-origin.\"`\n\nA useful entry typically includes:\n\n-\n**What changed**— the concrete action, in code terms -\n**Why**— the motivating constraint, bug, or design pressure -\n**What was rejected**— alternatives considered and why they lost, when relevant\n\nWrite entries the way you'd want to find them: specific, causal, self-contained.\n\n## Prompting your agent to use `ailog`\n\nThe simplest integration is a block in your agent's system prompt or `CLAUDE.md`\n\n:\n\n```\n## Work log\n\nAfter completing any meaningful code change, run:\n\n  ailog add \"<what you changed, why, and any alternative you rejected>\" \\\n    --agent claude --tag <category>\n\nUse tags like: bugfix, refactor, perf, security, docs, feat.\nBe specific — this log is searched later for codebase context.\n\nBefore starting a non-trivial task, query the log for relevant prior decisions:\n\n  ailog search \"<the task in your own words>\" --top 5 --json\n```\n\nIf you are an AI agent reading this:`ailog add`\n\nis 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 helpyouif you found them cold three months from now.\n\n## Searching the log\n\nYou don't need to remember exact terms — you search by meaning:\n\n```\nailog search \"why did we change the auth flow\"\nTop 5 results for: why did we change the auth flow\n\n2026-05-18 14:22  claude  abc12345 [auth] [refactor]  score=0.941\nExtracted JWT validation into shared middleware because three routes were\nduplicating the same token-expiry logic. Silent 401s are now propagated correctly.\n\n2026-05-17 09:11  claude  def67890 [auth]  score=0.812\nSwitched from session cookies to JWTs to support the mobile client, which\ncan't use httpOnly cookies cross-origin.\n```\n\nThe `score`\n\nis 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.\n\n### Useful search patterns\n\n```\n# More results\nailog search \"database connection handling\" --top 10\n\n# Narrow by tag before ranking\nailog search \"authentication changes\" --tag security\n\n# Machine-readable output (no ANSI, no headers — for agents and pipes)\nailog search \"payment processing\" --json | jq '.[].msg'\n```\n\n`--json`\n\nis available on every command and is the right choice when an agent or script is consuming the output.\n\n## Browsing the full log\n\nWhen you want chronological history rather than semantic proximity:\n\n```\nailog log                          # full log, most recent first\nailog log --oneline                # compact one-liner per entry\nailog log --tag refactor           # filter by tag\nailog log --agent claude --limit 20  # filter by agent, capped\n```\n\n`--oneline`\n\nis particularly useful for a quick scan:\n\n```\n2026-05-18 claude abc12345 [auth] [refactor]  Extracted JWT validation into shared middleware beca…\n2026-05-17 claude def67890 [auth]  Switched from session cookies to JWTs to support the mobile cl…\n2026-05-16 human  aab99123 [docs]  Updated API reference to reflect new token expiry behavior\n```\n\n## `ailog stats`\n\n```\nailog stats\nFile:     /your/repo/.ailog\n  Storage:  cache\n  Entries:  47  (0 with inline embeddings)\n  Span:     2026-04-01 → 2026-05-18\n\n  Agents:\n    claude: 38\n    human: 9\n\n  Tags:\n    refactor: 14\n    bugfix: 11\n    auth: 6\n    perf: 4\n```\n\nAn instant read on how actively the log is being used, which agents are contributing, and what categories of work have accumulated.\n\n## Linking log entries to git commits\n\nThe optional git hook is one of the more elegant features. Install it once:\n\n```\nailog install-hook\n```\n\nAfter that, each `git commit`\n\nautomatically appends an `Ailog-Entry:`\n\ntrailer referencing the most recent log entry:\n\n```\ncommit 3f9a82b\nAuthor: claude <claude@agent>\nDate:   Mon May 18 14:30:00 2026\n\n    refactor: extract JWT validation into shared middleware\n\n    Ailog-Entry: 550e8400-e29b-41d4-a716-446655440000\n```\n\nYou can now trace from any commit in `git log`\n\ndirectly to the log entry that explains the *why*. Re-running `ailog install-hook`\n\nis safe — it detects an existing hook and skips re-installing.\n\n## Storage modes: `cache`\n\nvs. `inline`\n\n`ailog.toml`\n\nhas one key decision:\n\n```\n# ailog configuration — commit this file.\n[ailog]\nstorage = \"cache\"      # \"cache\" or \"inline\"\nmodel = \"voyage-code-3\"\ndimensions = 1024\n```\n\n| Mode |\n`.ailog` contains |\nEmbeddings live in | Best for |\n|---|---|---|---|\n`cache` (default) |\nText entries only | Gitignored `.ailog.cache/` SQLite |\nMost teams — clean diffs, small history |\n`inline` |\nText + 1024-float vectors | The committed `.ailog` itself |\nFully offline, no re-embedding on clone |\n\n** cache mode** keeps\n\n`.ailog`\n\nhuman-readable and your git history lean. After a fresh clone:\n\n```\ngit clone your-repo\ncd your-repo\nexport VOYAGE_API_KEY=\"...\"\nailog reindex\n```\n\n`search`\n\nwill also trigger a lazy reindex on first use if the cache is missing.\n\n** inline mode** embeds vectors directly into\n\n`.ailog`\n\n. 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`\n\nand running `ailog reindex`\n\n.\n\n## Why `voyage-code-3`\n\n?\n\nMost general-purpose embedding models are trained on natural language. `voyage-code-3`\n\nis 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.\n\nThe 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.\n\n## A realistic team setup\n\nHow a team of one human and one Claude agent might use `ailog`\n\nin practice.\n\n**One-time setup (human):**\n\n```\ncd your-repo\nailog init\nailog install-hook\ngit add .ailog ailog.toml .gitignore\ngit commit -m \"chore: initialize ailog\"\n```\n\n**Agent's CLAUDE.md:**\n\n```\n## Work log\n\nBefore starting a non-trivial task:\n  ailog search \"<the task you're about to do>\" --top 5 --json\n\nAfter completing any meaningful change:\n  ailog add \"<what you did and why>\" --agent claude --tag <category>\n\nTags: bugfix, refactor, perf, security, docs, feat.\nBe specific — future you will search this log when making related changes.\n```\n\n**During a sprint, the agent logs as it works:**\n\n```\nailog add \"Moved rate limiting from individual route handlers into a single\nFastAPI middleware. The per-route approach was inconsistent — some endpoints\nhad no limit, others had hardcoded values. Middleware pulls limits from config.\" \\\n  --agent claude --tag refactor --tag security\n```\n\n**Three weeks later, a new engineer joins and wonders about the auth setup:**\n\n```\nailog search \"how does rate limiting work\"\n```\n\nThey get the full explanation immediately, with a timestamp and a link to the commit that made the change.\n\n## Agent-to-agent handoffs: the JSON API\n\nThis is where `ailog`\n\ncloses the cross-session memory loop. `--json`\n\nturns `ailog search`\n\ninto a clean data source for any agent:\n\n```\n# Pull historical context, then pass it to a new agent call\nCONTEXT=$(ailog search \"database migration approach\" --json --top 3)\n\nclaude -p \"Given this historical context: $CONTEXT\nWhat approach should we take for the upcoming schema change?\"\n```\n\nThis 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.\n\nThe 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`\n\noutput is stable and undecorated — a JSON array ready to be injected into a prompt.\n\n## The `.ailog`\n\nfile as source of truth\n\nOne design decision worth highlighting: `.ailog`\n\nis 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.\n\nThree consequences worth understanding:\n\nThere'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`\n\nto `.gitignore`\n\nbefore the next commit and it won't be tracked. Review what your agents are logging before treating the file as public.\n\n**Concurrent writes are safe.** `append_entry`\n\ntakes an exclusive advisory file lock on POSIX systems, so multiple agent processes logging simultaneously won't interleave or corrupt entries.\n\n**The log is resilient to malformed lines.** If a line is corrupt (partial write, manual edit gone wrong), `ailog`\n\nemits a warning and skips it rather than crashing.\n\n## How `ailog`\n\ncompares to nearby tools\n\n`ailog`\n\ndoesn't replace any of these — it fills a gap none of them fill.\n\n| Tool | What it captures | Where `ailog` is different |\n|---|---|---|\n`git log` / commit messages |\nWhat changed, by whom, when |\n`ailog` captures why in structured, semantic-searchable form — and an entry can outlive any single commit |\n| PR descriptions | Why a batch of changes was made |\n`ailog` is per-decision, not per-PR, and queryable by meaning rather than scrolling |\n| Agent in-context memory | The current session's reasoning |\n`ailog` survives session boundaries and agent restarts |\n| Vector DBs (Pinecone, Weaviate) | Arbitrary embeddings at scale |\n`ailog` is zero-infrastructure, lives in the repo, and is scoped to agent decisions |\n| OpenTelemetry / observability stacks | Runtime traces, spans, metrics |\n`ailog` captures intent at authoring time, not execution time |\n`CLAUDE.md` / static docs |\nStable architectural guidance |\n`ailog` is a living record that accumulates without manual curation |\n\n## Summary\n\n`ailog`\n\nis 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`\n\nto write, `ailog search`\n\nto retrieve — and everything is stored in plain files that travel with the repo.\n\nSetup 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.\n\n**Common questions, in plain terms:**\n\n- \"Why did the agent do this?\" →\n`ailog search \"<describe what you see>\"`\n\n- \"What did we decide about X?\" →\n`ailog search \"X\"`\n\n- \"Give this new agent context before it starts\" →\n`ailog search \"<task description>\" --json --top 5`\n\n- \"How does this code path work and how did it get this way?\" →\n`ailog search`\n\nplus`git log --grep \"Ailog-Entry:\"`\n\nThe source is on GitHub at [EstebanHernandez1523/ailog](https://github.com/EstebanHernandez1523/ailog), and the package is on PyPI as `lysofdev-ailog`\n\n.\n\n*Questions or corrections? Open an issue on the repo.*", "url": "https://wpnews.pro/news/lysofdev-ailog-a-git-log-for-why-your-ai-agent-did-what-it-did", "canonical_source": "https://dev.to/lysofdev/lysofdev-ailog-a-git-log-for-why-your-ai-agent-did-what-it-did-17ea", "published_at": "2026-05-19 01:19:01+00:00", "updated_at": "2026-05-19 01:30:59.631062+00:00", "lang": "en", "topics": ["artificial-intelligence", "developer-tools", "open-source", "products"], "entities": ["ailog"], "alternates": {"html": "https://wpnews.pro/news/lysofdev-ailog-a-git-log-for-why-your-ai-agent-did-what-it-did", "markdown": "https://wpnews.pro/news/lysofdev-ailog-a-git-log-for-why-your-ai-agent-did-what-it-did.md", "text": "https://wpnews.pro/news/lysofdev-ailog-a-git-log-for-why-your-ai-agent-did-what-it-did.txt", "jsonld": "https://wpnews.pro/news/lysofdev-ailog-a-git-log-for-why-your-ai-agent-did-what-it-did.jsonld"}}