CS357: Foundations of Artificial Intelligence - The Second Brain
Purpose
To build one Markdown vault that you own, that GitHub hosts, that Obsidian edits, and that every agent you run can read and write safely.
About This Tutorial
Every AI tool you use maintains its own little memory of you, in its own format, in its own silo, and none of them agree. The cure is architectural: one Markdown vault, hosted on GitHub, edited by you in Obsidian, and readable and writable by every agent you run, so that your context becomes a single, versioned, portable artifact instead of five inconsistent copies. This tutorial builds that system from zero: the vault, the gitless sync, the personal access token, the agent contract, and the wiring to an agent like hermes from our stack. Here is the path for today: why a vault → the LLM wiki pattern it implements → Obsidian and the repository → gitless sync with a PAT → the three-zone structure and AGENTS.md → the metadata protocol agents must honor → wiring hermes by prompting.
Key Concepts
| Term | Plain-English Definition | Where You’ll Meet It |
|---|---|---|
| Obsidian vault | A folder of plain Markdown files that Obsidian treats as a unified knowledge base. Because the files are just text files, they work with any other tool; no proprietary format lock-in. | Your vault might contain notes from class, links between ideas, summaries of papers, and context files that agents read before working with your data. |
| Personal Access Token (PAT) | A secret string that acts as a password for GitHub API calls. It grants specific permissions (like reading and writing a single repository) without sharing your full GitHub account credentials. | Your sync plugin uses the PAT to push note changes to GitHub; your agent uses it to pull the vault and write new wiki pages. |
| Gitless sync | A sync mechanism that uses the GitHub REST API directly to push and pull files, rather than running git commands locally. No .git folder, no merge conflicts, one consistent state machine. |
The GitHub Gitless Sync Obsidian plugin translates every file save into an API call; your phone and your laptop sync the same vault without ever needing git installed. |
| AGENTS.md contract | A file at the root of the vault that tells any agent exactly how to behave: which folders it can read, which it can write, how to handle sources, and what metadata to update. Because the file travels inside the repo, every agent reads it automatically. | An agent that reads AGENTS.md learns that raw/ is read-only, that wiki/ is where it should write, and that it must update github-sync-metadata.json in the same commit as any file it creates. |
| LLM wiki | The pattern this tutorial implements: a folder of Markdown pages that a model builds and maintains from your raw sources, so knowledge compounds across sessions instead of being re-derived on every query. Named in Andrej Karpathy’s April 2026 llm-wiki.md gist. |
Your wiki/ zone, its index.md catalog and log.md history, and the ingest/query/lint prompts that keep them current. |
| Blob SHA | The specific hash value Git uses to uniquely identify file contents. It is computed differently from a plain SHA-1 hash; Git prefixes the content with blob {bytecount}\0 before hashing. |
When an agent writes a file to the vault, it may need to compute the blob SHA to correctly update the sync metadata file. |
| Zone boundary | A deliberate structural rule about which areas of the vault serve which purpose and who is allowed to write to them. Zone boundaries are what make the vault safe to open to agents. | The raw/ zone is read-only for everyone including agents; the wiki/ zone is write-enabled for agents; the .obsidian/ zone is off-limits except for the specific metadata file. |
| Memory scope | Whether a remembered fact applies everywhere (global) or only inside one project. Zone boundaries govern where an agent may write; memory scope governs how widely what it writes should apply. | A global memory lives in LLMMEMORIES.md; a project memory lives in wiki/projects/<project>/MEMORIES.md, and your AGENTS.md states which is the default. |
Part I: The Architecture
In this part, you will understand why a single versioned vault (rather than five disconnected tool silos) is the right architectural choice for persistent AI context, and what each component of the system contributes to that goal.
Why This Architecture, and What Each Piece Does
Every AI tool you use today maintains its own context about you. Your coding assistant knows your recent files. Your chat AI knows this conversation. Your email AI knows your last few messages. None of them know what the others know, and none of them persist that knowledge reliably across sessions. The result is that you re-explain yourself constantly, to tools that could, in principle, already know.
The second-brain architecture solves this by making your accumulated context a first-class, versioned artifact that any agent can read and write. Think of it the way a new doctor reviews your full medical history before your appointment; you don’t have to explain everything from scratch because your record travels with you and is maintained by every provider who sees you.
The design has four pieces, each independently replaceable:
- Obsidian is a free note application that edits a folder of plain Markdown files (a vault) with wikilinks, graph view, and mobile apps. Crucially, it imposes no proprietary format; the vault is just files, so any other tool can read and write them too.
- GitHub hosts the vault as a private repository, providing versioning (you can see what changed and when), an API surface agents can reach from anywhere, and a webhook surface for automation.
- The GitHub Gitless Sync plugin (a community Obsidian plugin) bridges the two without git: it translates every file operation into GitHub REST API calls, so there is no
.gitdirectory, no merge conflicts from stray command-line operations, and identical behavior on desktop and phone. - Your agents complete the loop: they read the vault for context and, following a contract you will write, push changes that appear in Obsidian on the next sync.
| System Component | What It Replaces | Why This Choice | What You Lose If You Skip It |
|---|---|---|---|
| Obsidian as editor | Five different note apps, each in a different format that agents can’t read. | Plain Markdown is universal: any agent, any language, any tool can read and write it without a special library. | Interoperability: your notes are locked in a proprietary format that agents cannot access. |
| GitHub as host | Local storage that agents can only reach if they’re on the same machine. | GitHub provides a versioned REST API that agents on any machine, in any container, can reach with a token. | Portability and versioning: no history, no access from remote agents, no audit trail of changes. |
| Gitless sync plugin | Running git commands on every device and handling merge conflicts manually. |
One sync mechanism, owned by one plugin, means one consistent state machine instead of three fighting ones. | Simplicity: without the plugin, every device needs git installed and you’ll deal with merge conflicts between your phone and laptop. |
| AGENTS.md contract | Per-tool configuration of what each agent is allowed to do. | The contract travels inside the repository; every agent reads it automatically, requiring zero per-tool configuration. | Safety and consistency: without a contract, agents may write anywhere in the vault, including overwriting your source files. |
The Pattern Has a Name: Karpathy’s LLM Wiki
What you are about to build is a specific, widely adopted pattern rather than a local invention, and it is worth knowing the name and reading the source. In April 2026, Andrej Karpathy published a gist titled llm-wiki.md describing what he called an LLM wiki: a folder of Markdown files that a model incrementally builds and maintains for you, so that what you learn accumulates instead of evaporating at the end of each session. The gist is prose, not code (it is written to be handed to an agent), and it is short enough to read in ten minutes. Read it before you build, because everything below is an implementation of it.
The pattern has three layers, and our vault is one arrangement of them:
| Layer in the gist | Who owns it | Where it lives in this tutorial’s vault |
|---|---|---|
| Raw sources | You. Articles, papers, PDFs, transcripts, dropped in and never edited again | raw/ |
| The wiki | The model. Source summaries, entity pages, concept pages, and the cross-links between them | wiki/ |
| The schema | You. The conventions, zone rules, and workflows the model must follow | AGENTS.md (plus LLMMEMORIES.md and SYSTEMPROMPT.md) |
Two files inside wiki/ do the navigating, and an LLM wiki that lacks them degrades into a folder of disconnected notes:
wiki/index.mdis a content catalog: every page listed under a topic heading with a one-line summary of what it says. The agent reads it first on any question and then opens only the three or four pages that matter. This is why a wiki of several hundred pages stays searchable with no embeddings and no vector database; the index is the retrieval layer, and it is human-readable.wiki/log.mdis an append-only, chronological record of what happened to the wiki and when: sources ingested, questions asked, maintenance passes run. It costs an agent one line per operation and it is the only thing that lets you (or the next agent, in a fresh context) reconstruct how the wiki came to say what it says.
And three operations, each of which is a standing prompt rather than a piece of software:
- Ingest. You add a source to
raw/. The agent reads it, discusses the takeaways with you, writes a summary page, and then updates every existing page that source touches, which is typically ten to fifteen of them in a single pass. The cross-reference bookkeeping is the part that would make you quit, and it is exactly the part a model does without complaint. - Query. You ask a question. The agent reads
index.md, opens the relevant pages, and answers with citations to the pages it used. An answer worth keeping becomes a page of its own, which is how questions compound into content. - Lint. Periodically, you ask the agent to audit its own wiki: pages that contradict each other, claims that have gone stale, orphan pages nothing links to, topics named everywhere but written nowhere. What the lint finds becomes the next ingest queue.
Why this is not RAG. We build a retrieval-augmented generation pipeline later in the course, and the contrast is the sharpest way to understand what the wiki buys you. RAG searches your raw documents on every query and throws the result away; ask the same question twice and the model does the same work twice, and nothing about your corpus is any better than it was yesterday. The LLM wiki pays the synthesis cost once, when a source arrives, and keeps the result as a durable artifact. Karpathy’s argument for why this is newly practical is a labor argument rather than a technical one: good wikis have always been valuable and have always died of maintenance, and maintenance is precisely the work that has just become free. Neither replaces the other; RAG is what you reach for over a corpus too large or too fast-moving to curate, and the wiki is what you build over the corpus you actually care about.
Your job changes shape. You stop being the author and become the curator: you choose what enters raw/, you ask the questions, and you review what the agent wrote before you trust it. That last clause is not optional. Nothing in the wiki is durable knowledge until you have read it, which is the same review gate you apply to a coding agent’s diff.
Questions to Work Through
- Compare the classic
repo-scope Personal Access Token against a fine-grained token limited to a single repository’s Contents permission. What does an attacker gain with each token if it leaks? Which does our data-minimization principle select, and why?
Hint: A classic repo-scope token gives read/write access to all repositories in your account, including private ones. A fine-grained token scoped to one repository gives access only to that repository’s file contents. What is the worst-case scenario for each if the token appears in a public log?
- The expired-token failure is silent: local editing in Obsidian continues working, and only cross-device staleness or agent failures reveal the problem, sometimes days later. Design the cheapest detection habit you can (a calendar reminder, a canary note an agent updates daily) and justify why your choice is the right tradeoff between effort and reliability.
Hint: A calendar reminder set for one day before the token’s expiration date costs almost nothing to set up. A canary note that an agent updates daily would reveal staleness within 24 hours but requires an agent running on a schedule. Which failure mode do you actually care more about catching early?
- Your vault will hold personal context by design. List three categories of information you would deliberately keep out of even a private synced vault, and state the specific principle behind each exclusion. Consider both the risk of token theft and the risk of the GitHub account itself being compromised.
Hint: Consider categories like: credentials and passwords (should never be in plaintext anywhere), health or financial information with legal protection (subject to breach notification requirements even in private repos), and information that belongs to others (contacts, private conversations) rather than only to you.
Now that you understand what each architectural piece does and why it was chosen, you are ready to design the internal structure and rules that make it safe for agents to operate inside the vault.
Part II: Structure and the Agent Contract
In this part, you will design the zone structure and contract file that make it safe to give agents write access to your vault, which is the difference between a helpful automated collaborator and one that silently corrupts your source files.
The Three-Zone Vault and the AGENTS.md Contract
Structure is what turns a pile of notes into a system agents can be trusted inside. Without explicit zone boundaries, an agent asked to “help with your notes” has no way to know which files are pristine sources it must not touch, which are the curated knowledge base it should maintain, and which are internal plugin state it must never modify. The zone structure encodes those distinctions in the vault’s own layout.
vault/
|-- AGENTS.md # The agent contract: read completely before acting
|-- LLMMEMORIES.md # Persistent user context every AI session should know
|-- SYSTEMPROMPT.md # Standing behavioral and style instructions
|-- raw/ # READ-ONLY inbox: PDFs, transcripts, exports; never modified
|-- wiki/ # The curated, cross-linked knowledge base agents WRITE
| |-- index.md # The hub page: every page, by topic, one line each
| `-- log.md # Append-only: what was ingested, asked, or linted, and when
`-- .obsidian/
`-- github-sync-metadata.json # Sync state: plugin-managed, agent-updated
The boundaries are the design. raw/ is a one-way inbox: humans and automations drop source material there and nobody ever modifies it, so sources stay pristine and reprocessable. wiki/ is where all authored knowledge lives, organized into topical subdirectories with wikilinks, and agents are its primary authors: their job is synthesis from raw/ into wiki/, not transcription. Its two bookkeeping files are the ones from the LLM wiki pattern above: index.md is the catalog an agent reads before it opens anything else, and log.md is the append-only history of every ingest, query, and lint pass. The three root files are the only files at the root:
- LLMMEMORIES.md is your externalized, version-controlled memory: who you are, what you are working on, context that every new AI session should know before it does anything else.
- SYSTEMPROMPT.md holds the standing instructions you would otherwise paste into every tool’s custom-instructions box.
- AGENTS.md is the contract that specifies every rule an agent must follow when working inside the vault.
AGENTS.md opens with a non-negotiable instruction (read this file completely before taking any action) and then specifies: zone boundaries (raw/ strictly read-only; .obsidian/ untouchable except for the sync metadata file; .trash/ ignored entirely); the quick-start workflow (read the contract, inspect wiki/, inspect relevant raw/ material, change only wiki/, update the metadata, commit atomically); synthesis rules (summarize and deduplicate rather than mirror; preserve uncertainty and conflicts between sources rather than smoothing them; prefer enriching existing canonical pages over spawning duplicates); organization rules (topical directories, hub pages, extensive wikilinks, no flat dumps); and the question-answering rule (answer from wiki/ first, consulting raw/ only to fill gaps, updating the wiki before answering when it is stale).
An agent processing a new PDF in raw/ notices a typo in the PDF and also that wiki/index.md lacks a link to the page it just created. Under the AGENTS.md contract, the correct actions are:
- Fix the typo in the PDF and add the index link
- Leave the PDF untouched (raw/ is read-only), add the index link, and note the source’s typo in the wiki page if it matters
- Fix the typo and skip the index, since navigation is the human’s job
- Move the PDF into wiki/ so it can be edited
Answer
Leave the PDF untouched (raw/ is read-only), add the index link, and note the source’s typo in the wiki page if it matters
Common Misconception: “Since it’s my private repository, agents can write anywhere they want; I can always fix mistakes.”
This reasoning underestimates two risks. First, agents that overwrite source files in
raw/destroy the pristine record of what your original sources actually said, and if the agent’s interpretation was wrong, you’ve lost the ability to reprocess from scratch. Second, agents that write to.obsidian/can corrupt the plugin’s sync state in ways that cause silent data loss (your edits in Obsidian stop syncing to GitHub without any error message). The zone boundaries exist precisely because “I can fix it later” is not a recovery strategy when the failure is silent.
Project Scope: Keeping One Project’s Context Out of Another
Write every memory at the narrowest scope that makes it true. A fact that holds for one project belongs to that project, not to every session you will ever run.
The three root files above are global. Every agent reads them, in every project, before it does anything else. That is the right home for durable facts about you. It is the wrong home for the decision your project team made last Tuesday.
An agent that writes every fact globally creates three problems:
- Context bleed. A convention you adopted for one project starts steering an agent working on an unrelated one.
- Context cost. Every session pays to read every memory, including the ones that cannot apply to it.
- Silent staleness. A project ends, its decisions stop being true, and nothing prompts the global file to forget them.
Deciding where a memory goes
Ask one question: is this still true after the project ends?
| The memory | Scope | Where it goes |
|---|---|---|
| Your name, your program, how you want answers formatted | Global | LLMMEMORIES.md |
| A standing style rule you want in every tool | Global | SYSTEMPROMPT.md |
| A rule every agent must obey inside this vault | Global | AGENTS.md |
| “This team chose SQLite over Postgres, and why” | Project | wiki/projects/<project>/MEMORIES.md |
“The grader runs pytest -q and treats warnings as failures” |
Project | wiki/projects/<project>/MEMORIES.md |
“This repository protects main; open a pull request” |
Project | that repository’s own AGENTS.md |
The last row is easy to miss. A rule about a code repository belongs in that repository’s AGENTS.md, where it travels with the code. A rule about your vault belongs in the vault’s AGENTS.md. Two contracts, two homes, and an agent reads whichever one it is standing in.
Writing the rule down
Scope discipline fails unless the contract states it. Agents default to whatever is easiest to find, and the global file is always easiest to find. Add a section like this to your vault’s AGENTS.md:
## Memory Scope
Default to project scope. Write to `wiki/projects/<project>/MEMORIES.md`.
Write to `LLMMEMORIES.md` only when the fact stays true independent of any
single project. State in the entry why it is global.
Never copy a project memory into the global file to make it easier to find.
Link to it from the project's hub page instead.
When you cannot tell which scope applies, write the project-scoped entry
and ask.
That last instruction carries the most weight. Ambiguity must resolve downward, toward the narrower scope. A memory filed too narrowly is merely inconvenient to find. A memory filed too broadly contaminates every future session, and it does so silently.
Your agent finishes a lab and learns that your course’s grader rejects any commit message longer than 72 characters. Under a scope-disciplined contract, where does that memory belong?
LLMMEMORIES.md, because commit hygiene is a habit worth applying everywherewiki/projects/cs357/MEMORIES.md, because the rule belongs to one course’s graderSYSTEMPROMPT.md, because it constrains how output is formatted- Nowhere; the agent should rediscover it each session
Answer
wiki/projects/cs357/MEMORIES.md, because the rule belongs to one course’s grader
Common Misconception: “More memory is always better, so write everything to the global file where no agent can miss it.”
This confuses recall with relevance. A global file that accumulates every project’s decisions becomes long, internally contradictory, and expensive to read, and the agent cannot tell which entries still apply. Worse, the failure is silent: an agent confidently applies your last project’s database choice, or your last team’s review rule, to work that never agreed to either. Scope is not a filing preference. It is what keeps a memory’s authority attached to the context that earned it.
With the zone structure and contract defined, you are ready to learn the metadata protocol, the low-level bookkeeping detail that is invisible when it works and catastrophic when it doesn’t.
Part III: The Metadata Protocol (the Part Everyone Gets Wrong)
In this part, you will learn the specific metadata bookkeeping step that every agent commit must include to keep the bidirectional sync working, the single most common failure point when wiring agents to a gitless-synced vault.
Why Agent Writes Need One Extra Step
Here is the subtle mechanic that makes bidirectional sync work, and the single most common failure point when wiring agents to a gitless-synced vault. The plugin tracks every file’s sync state in .obsidian/github-sync-metadata.json. When you edit in Obsidian, the plugin maintains this file automatically. But when an agent creates or modifies vault files directly through the GitHub API, the plugin has no record of the change, and on the next sync, it may simply not pull the agent’s work, or may overwrite it.
The rule: any process that writes vault files outside Obsidian must update the metadata file in the same atomic commit.
Each metadata entry follows this schema:
{
"path": "wiki/projects/cs357.md",
"sha": null,
"dirty": true,
"justDownloaded": false,
"lastModified": 1718100000000
}
The easy, correct path for agents: after creating or modifying a file, write its metadata entry with sha set to null and dirty set to true, with lastModified as the current Unix time in milliseconds. The plugin uploads the file on the next sync and fills in the real SHA itself. Deletions add deleted: true and a deletedAt timestamp.
The two invariants that must never break:
- The file change and its metadata entry land in one commit; splitting them into two commits desynchronizes the state machine between the split.
- Nothing else inside
.obsidian/is ever touched by an agent exceptgithub-sync-metadata.json.
For completeness, because a thorough agent may pre-compute it: the sha field, when not null, is a git blob SHA, computed differently from a plain SHA-1 of the file. Git hashes the byte string blob {N}\0 (where {N} is the content’s byte length and \0 is a literal null byte) concatenated with the raw content.
Code Cell
The following code demonstrates how to compute a git blob SHA, the exact hash format that git uses internally and that the sync metadata file requires. Run it and observe that the plain SHA-1 of the same content (shown in the second output line) produces a different value, which is the mistake that causes silent sync failures.
# The git blob SHA, demystified: this reproduces `git hash-object` exactly.
import hashlib, traceback
def git_blob_sha(content: str) -> str:
try:
raw = content.encode("utf-8") # BYTES, not characters
header = f"blob {len(raw)}\0".encode("utf-8")
return hashlib.sha1(header + raw).hexdigest()
except Exception as e:
print(f"[secondbrain:git_blob_sha] {e}")
traceback.print_exc()
return ""
note = "# CS357\nAgentic AI, Fall 2026.\n"
print("blob sha:", git_blob_sha(note))
print("plain sha1 (WRONG for git):", hashlib.sha1(note.encode()).hexdigest())
# Multi-byte check: byte length vs character count matters
emoji_note = "café ☕\n"
print("bytes:", len(emoji_note.encode("utf-8")), "chars:", len(emoji_note))
Notice the last line: for content containing multi-byte characters (accented letters, emoji, non-ASCII), the byte length and the character count differ. Git uses byte length in the header; using character count instead will produce a wrong SHA that causes the sync to fail silently.
Questions to Work Through
- An agent’s commit contains: a new file
wiki/people/silverman.md, an edit towiki/index.md, and a metadata file updated with only one entry (forsilverman.md) whoseshafield holds the plain SHA-1 of the file’s text (not the git blob SHA). Find both protocol violations and predict the concrete symptom each one produces on the next Obsidian sync.
Hint: Violation 1: the metadata is missing an entry for wiki/index.md. What does the plugin do with a file it has no metadata record for: does it ignore it, overwrite it, or treat it as a conflict? Violation 2: the SHA is wrong (plain SHA-1 instead of blob SHA). What does the plugin do when it computes the correct SHA for the file and finds it doesn’t match the stored one: does it consider the file dirty, clean, or in conflict?
- Write the corrected metadata entries for both
wiki/people/silverman.mdandwiki/index.md, using the safe null-and-dirty pattern. Explain why settingsha: nullanddirty: trueis safer than trying to pre-compute the correct blob SHA.
Hint: The null-and-dirty pattern tells the plugin “I made a change and I want you to be the authority on the final SHA after upload.” Pre-computing the SHA requires getting the byte length exactly right, handling encoding correctly, and matching the exact content that was committed; any discrepancy causes a mismatch. Null-and-dirty eliminates all of those failure modes.
- Why does the AGENTS.md contract make the agent responsible for the metadata bookkeeping rather than asking the human to “just resync manually after the agent commits”? Connect your answer to the architecture’s goal of spending whose time.
Hint: The entire system is designed so that the human’s interaction with agent output is “open Obsidian and sync once.” If the agent’s commits require human follow-up (diagnose what didn’t sync, fix metadata, trigger a second sync), the system is not actually reducing the human’s cognitive load; it’s just moving the manual work to a different moment.
Having mastered the metadata protocol, you have everything you need to wire an actual agent to the vault and observe the full read-synthesize-write loop in action.
Part IV: Wiring an Agent (hermes) by Prompting
In this final part, you will see that connecting an agent to your vault requires only a well-formed prompt (not integration code) and you will trace the session rhythm that results when the full system is running.
The Wiring Is Just a Prompt
Because the contract lives in the repository, connecting an agent requires no plugin and no integration code; it requires telling the agent where the contract is. For hermes from our stack (or Claude Code, or any capable agent CLI), the entire wiring is:
Clone https://github.com/YOURUSERNAME/Obsidian-Vault using the token in the
GITHUB_TOKEN environment variable, read AGENTS.md completely, and follow it to
process any unprocessed documents in raw/. Commit and push your changes
atomically, including the sync metadata updates AGENTS.md specifies.
Provide the PAT as an environment variable when launching the container (never inline in the prompt, which lands in logs):
docker run --rm -it --name hermes \
--add-host=host.docker.internal:host-gateway \
-e GITHUB_TOKEN="$VAULT_PAT" \
-v "$HOME/agents/hermes/home:/home/hermes/.hermes" \
-v "$HOME/agents/workspace:/workspace" \
nousresearch/hermes-agent:latest
For agents on the same machine, a simpler read path exists: bind-mount the vault directory itself (-v "$HOME/obsidian-vault:/vault:ro" for context-consuming agents; read-write only for designated wiki authors). Standing instructions then go in each project’s context file:
## Context
Before any task, fetch and read from the knowledge repository:
- AGENTS.md, LLMMEMORIES.md, SYSTEMPROMPT.md (repository root)
Treat them as authoritative for all decisions this session.
The session rhythm that results: you drop a PDF into raw/ from your phone and sync; hermes runs (manually or on an n8n schedule from the stack module), reads the contract, synthesizes wiki pages, updates the metadata, and commits; you open Obsidian, sync, and the new cross-linked pages are simply there. The question-answering direction is one more prompt: “Using the vault per AGENTS.md, what do my notes say about X? Update the wiki first if raw/ has newer material.”
Obsidian becomes the comfortable viewer onto a knowledge base your agents largely maintain. What becomes possible once that loop is running, a living wiki that grows more useful each session rather than a folder that grows larger, is the argument the How I AI session makes; this page is the deeper build behind it.
Questions to Work Through
- The wiring prompt above passes the PAT via an environment variable rather than including it in the prompt string. Explain specifically why this matters: what are the two specific places where an inline PAT in a prompt could be exposed to unintended readers?
Hint: Consider: (1) where the prompt string goes when you run an agent CLI: does it appear in logs, in process listings (ps aux), in the shell history? (2) What happens if the agent itself is asked to repeat or summarize the instructions it was given?
- The AGENTS.md contract says agents should “answer from wiki/ first, consulting raw/ only to fill gaps, and update the wiki before answering when it is stale.” Explain the compounding benefit of this ordering rule for the vault’s long-term value. What happens to the wiki over dozens of agent sessions if this rule is followed consistently?
Hint: Each time an agent updates the wiki before answering, the wiki becomes more complete. The next agent session has a richer starting point and needs to consult raw/ less. Over time, what does the wiki become? What does this mean for the quality and speed of future agent sessions?
- An agent is given read-write access to the whole vault but no AGENTS.md contract exists yet. Describe three specific ways this could go wrong during the agent’s first session processing a document in raw/, and explain how each would have been prevented by an explicit zone contract.
Hint: Consider: What does the agent do if it finds a typo in a raw/ source file? What does it do if it wants to “organize” the vault and moves files around? What does it do if it creates a new note but doesn’t update the metadata file? For each, how would an explicit AGENTS.md rule have prevented the failure?
Exercises
- Stand it up.
What to do: Complete the five-step setup (install Obsidian, create a private GitHub repository, generate a fine-grained PAT with Contents read/write on that one repo, install and configure the GitHub Gitless Sync plugin, trigger the first sync). Demonstrate a round trip: edit a note on one device, sync, observe the change on a second device (or a second Obsidian instance pointing at the same vault). Submit your token-redacted plugin settings and the repository’s commit history showing at least two sync commits.
Starter hint: If you don’t have two devices available, you can demonstrate the round trip by: (1) editing a file in Obsidian and syncing (commit appears in GitHub), (2) then editing the same file directly in the GitHub web editor, (3) then syncing in Obsidian and confirming the web edit appears locally. This proves both directions of the sync work.
You’ve succeeded when: You can show a GitHub commit history with at least two commits from the Obsidian plugin (not manual git pushes), and demonstrate that a change made on one side appears on the other side after a sync.
- Author the contract.
What to do: Write your own AGENTS.md, LLMMEMORIES.md, and SYSTEMPROMPT.md; one page each is a good starting point. AGENTS.md must explicitly state: the zone boundaries (which directories agents can write, which are read-only), the metadata protocol (file changes and metadata entries in one atomic commit), the synthesis rules (summarize don’t transcribe; enrich existing pages before creating new ones), and the memory-scope rule (project scope is the default; what qualifies a fact as global; ambiguity resolves to project scope). LLMMEMORIES.md should contain context about you that any agent should know before starting work. SYSTEMPROMPT.md should contain standing behavioral instructions you’d otherwise paste into every tool.
Starter hint: Start AGENTS.md with: “Read this file completely before taking any action in this vault.” Then add a section for each major rule. For LLMMEMORIES.md, start with: who you are, what you’re currently working on, and three facts about your context that agents frequently get wrong when they don’t know them. For SYSTEMPROMPT.md, start with your preferred response style (concise vs. detailed), citation requirements, and any topics where you have strong preferences.
You’ve succeeded when: All three files are in the root of your vault and synced to GitHub, AGENTS.md explicitly states zone boundaries, the metadata protocol, and the memory-scope default, and LLMMEMORIES.md contains at least five facts about your context that are not publicly findable and that stay true after any one project ends.
- First agent write.
What to do: Drop one real document (a class reading, a paper, a saved article) into raw/ and sync it to GitHub. Run the ingestion prompt against hermes or your preferred agent CLI. Verify the result: (a) the agent did not modify the file in raw/, (b) a new wiki page was created in wiki/, (c) the metadata file was updated in the same commit as the wiki page. Submit the agent’s commit (showing the atomic file-plus-metadata change) and a screenshot of the synced wiki page in Obsidian after the next sync.
Starter hint: Before running the agent, check wiki/ and the metadata file to establish a baseline. After the agent commits, check: does the commit touch any file in raw/? Does the commit contain exactly one new/modified wiki file and one metadata file update? Are they in the same commit (not two separate commits)? Open the GitHub commit view to verify all of this before syncing to Obsidian.
You’ve succeeded when: You can show a GitHub commit that contains a new wiki/ file and a metadata update in one commit, with no changes to any raw/ file, and a screenshot of the resulting wiki page visible in Obsidian.
- Protocol forensics.
What to do: Deliberately commit a vault change without the metadata update: use the GitHub web editor to create or modify a file in wiki/ without touching the metadata file. Observe and document the sync behavior in Obsidian: does the change appear? does it appear correctly? does any error occur? Then repair the situation by adding the correct metadata entry and committing it. Write a three-sentence postmortem explaining what went wrong, why it went wrong, and what the fix was.
Starter hint: In the GitHub web editor, navigate to wiki/ and create a file like wiki/test-forensics.md with some content. Commit it. Then open Obsidian and sync. Observe carefully: does the file appear? Is the content correct? Does the plugin show any warning? Then add the metadata entry manually (following the null-and-dirty pattern) and sync again.
You’ve succeeded when: You have documented observations of the sync behavior before and after the fix, and your postmortem correctly identifies the mechanism of the failure (plugin had no record of the file) and confirms the fix worked.
- The memory loop.
What to do: After a substantive working session with any AI tool (a tutoring session, a coding session, a research conversation), identify one refined fact about your context that emerged from that session, something the AI helped you clarify about your own project or thinking. Write that fact into LLMMEMORIES.md and sync it to GitHub. Then start a fresh agent session, tell the agent to read the vault per AGENTS.md, and give it a task that would benefit from knowing that fact. Report whether the new session behaved differently because of the updated memory.
Starter hint: The fact you add should be specific enough to change agent behavior: not “I am interested in AI” but “I am building a RAG pipeline for course syllabi and I have decided to use Chroma as the vector store because the team already has Python skills.” After adding this, ask the agent: “What vector store should I use for my project, and why?” Compare the answer before and after the memory update.
You’ve succeeded when: You have a before/after comparison of agent responses to the same question (one without the memory fact, one with it), and you can describe in two sentences how the agent’s response changed and why that change was useful.
Where This Goes Next
This page is the deep version of Part I of the How I AI session; if you arrived here from that session, its Part II is where the same instinct gets applied to a project repository rather than to your notes. Later in the course, the case study From Second Brain to Chief of Staff: A Personal Agent in Production shows what this exact architecture grows into after a year of daily use: confirmation gates, scheduled routines, a robustness harness, and an assistant that maintains its own runbook inside the vault you just built.
Reflection Prompt
Personal level: In exercise 2, you decided what to put in LLMMEMORIES.md and what to leave out. Where did you personally draw the inclusion line, and what does your line reveal about which you currently fear more: forgetting (losing context that would make your tools more helpful) or being legible (having your context in a form that could be read by others if the repository were compromised)?
Technical level: This system makes your accumulated context durable, portable, and agent-readable, which is power; it also concentrates an intimate record of your work and thinking into one token-protected repository, which is risk. List the three most significant security properties the system relies on to protect your vault, explain what happens if any one of them fails, and identify which failure would be the hardest to recover from.
Societal level: Personal knowledge management tools like this vault externalize and make searchable the kind of context that, for most people, lives only in memory or scattered across email and notes. As AI agents become better at reading and synthesizing this kind of personal context, what new categories of privacy risk emerge, and what policies or personal practices would you want to see adopted before personal knowledge vaults become mainstream?
Further Reading
- Andrej Karpathy,
llm-wiki.md(gist, April 2026): the LLM wiki pattern in the author’s own words, and the source for the three-layer split, theindex.md/log.mdconvention, and the ingest/query/lint loop. Read it first; everything in this tutorial is one implementation of it. - W. Mongan, “A Private AI Knowledge Base: Obsidian, GitHub Sync, and Cross-Platform AI Context” (billmongan.com, May 2026): the full architecture this module teaches, including the complete AGENTS.md specification and SHA protocol.
- The GitHub Gitless Sync plugin repository and README: settings, conflict resolution, and the config-sync caution.
- GitHub Docs, “Managing your personal access tokens”: fine-grained tokens and scoping.
- This course: From Second Brain to Chief of Staff: A Personal Agent in Production, the production case study of the vault contract you built here.