Skip to content

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 Zoo Code Memory β€” Persistent memory for Zoo Code (and any code agent)

A simple, file-based system that gives persistent inter-session memory to Zoo Code, Claude Code, Cursor, or any code agent that can read files. No dependencies, no third-party tools, nothing to install β€” just conventions + a "rules" file that Zoo Code automatically injects into the system prompt at the start of every session.

Tested with Zoo Code + GLM License: MIT


πŸͺ„ Install it (the only instruction you need)

Open a new Zoo Code conversation in your workspace and paste this single sentence:

Read https://github.com/pguedon-ai/zoo-code-memory and install the Zoo memory
system in this workspace. Detect the projects present, fill in the global
memory and one ZOO.md per project with my real environment, create .clinerules,
add the git-exclusion block to each existing .gitignore, and tell me when
you're done and how to verify it works.

That's it β€” the agent does the rest. It will:

  1. Read this repo (README + templates/).
  2. Inspect your workspace, OS, tool versions, and existing .gitignores.
  3. Create .zoo/ZOO.md (global memory) and <project>/ZOO.md (one per project) filled with your real environment β€” not template placeholders.
  4. Create .clinerules at the workspace root β€” the trigger Zoo Code auto-injects at every session.
  5. Append the git-exclusion block to each repo's .gitignore so the memory is never committed.
  6. Tell you when it's done and how to verify it (see How to verify it works).

Why this works: Zoo Code can read a GitHub repo, write files, run shell commands, and edit your .gitignores β€” so a single sentence is enough to bootstrap the whole system. You don't need to copy templates by hand or read the rest of this README.

Prefer to do it by hand, or want to audit what the agent did? See Manual setup (optional) at the bottom β€” every step is verifiable.


What the system does, in 3 lines

  1. A global memory file (.zoo/ZOO.md) + a per-project memory file (<project>/ZOO.md).
  2. A rules file (.clinerules) that Zoo Code automatically injects into the system prompt at every session, instructing the agent: "read the memory before answering, update it when you're done".
  3. The memory is local and never version-controlled (added to .gitignore) β€” it lives on the volume, not on GitHub.

Result: from one session to the next, the agent no longer forgets the project's architecture, the pitfalls it hit, the decisions you made. It reads the relevant ZOO.md before answering β€” without you having to ask.


How the system is structured

Layer Location Content
Global .zoo/ZOO.md (at the workspace root) User preferences, server environment (OS, tools, versions), cross-project conventions, project inventory, session history
Per-project <project>/ZOO.md (at each project's root) Project architecture, decisions made, known pitfalls, code locations, DB schema, project-specific history
Trigger .clinerules (at the workspace root) Automatically injected by Zoo Code into the system prompt at every session (setting zoo-code.useAgentRules, enabled by default). This is what makes reading the memory automatic.

Layout in a workspace where projects live directly at the root:

.zoo/ZOO.md          # global memory
.clinerules          # trigger (injected at every session)
projectA/ZOO.md      # project A memory
projectB/ZOO.md      # project B memory

Adapting to other agents

If the agent is not Zoo Code, use the equivalent rules file:

Agent Rules file
Zoo Code .clinerules
Claude Code CLAUDE.md
Cursor .cursorrules
Generic agents AGENTS.md
Fallback paste the rules into the tool's custom system instructions

How to verify it actually works

Don't trust the setup until you've run this end-to-end test. It's the only way to know the agent actually reads the memory before answering.

Static checks (do these first)

# 1. Files exist where they should
ls .zoo/ZOO.md .clinerules <project>/ZOO.md    # all should exist

# 2. Memory is not tracked by git (in each repo)
git check-ignore -v ZOO.md .clinerules .zoo/ZOO.md   # should match .gitignore
git ls-files | grep -E 'ZOO\.md$|\.clinerules$|\.zoo/'  # should be empty

# 3. The memory contains real info, not template placeholders
head -20 .zoo/ZOO.md
head -20 <project>/ZOO.md

End-to-end test (the one that matters)

  1. Open a brand-new Zoo Code session (close the current one and start fresh β€” the injection happens at session start).
  2. Ask a question about a project, without telling the agent where to look:
    • "What's the stack of <project>?"
    • "What do you know about my environment?"
  3. The agent should answer using facts that only exist in the ZOO.md files β€” and you should see in the UI trace that it read ZOO.md before answering (e.g. "Zoo wants to read this file").
  4. If the answer is correct and cites info from the memory β†’ the system works.

If the agent doesn't read the memory spontaneously

  • Check that .clinerules (or your agent's equivalent) exists at the workspace root β€” not inside a project folder.
  • Check that zoo-code.useAgentRules is on (VSCode Settings β†’ search zoo-code.useAgentRules).
  • As a last resort, paste the .clinerules content into the tool's custom system instructions.

What a passing test looked like for us

On a Linux server with Zoo Code + GLM 5.2, after install:

  • git check-ignore -v ZOO.md matched .gitignore in all 3 repos in the workspace βœ“
  • git ls-files | grep ZOO.md was empty (no memory file tracked) βœ“
  • New session, question about a project's stack β†’ the agent read that project's ZOO.md spontaneously (visible in the trace: "Zoo wants to read this file" + recursive folder read) and answered correctly without being told where to look βœ“

The agent protocol (what .clinerules instructs it to do)

Reading (every session / every task)

  1. Read .zoo/ZOO.md before any action β€” even for a simple question.
  2. If the task mentions a project β†’ also read its ZOO.md.
  3. Never re-ask the user for info that's already in the memory.

Writing (the "automatic" save)

Write to the memory as soon as a piece of info is important and durable:

  • an architecture or design decision
  • a discovered pitfall (bug, undocumented behavior, tool limitation)
  • a clarification from the user (e.g. "this DB is shared between X and Y")
  • environment facts (installed version, unavailable tool, blocked network)
  • a working rule agreed with the user (e.g. "commits OK, pushes forbidden")

Do NOT write: ephemeral details, raw file contents, anything that can be derived from the code itself.

History entry format

  • Dated entry [YYYY-MM-DD] at the top of the "Session history" section (most recent first).
  • Dense summary: what, where (relative links to files), why.
  • Pitfalls ALSO go into a dedicated "Known pitfalls" section of the project.

Why plain Markdown files and not a database?

  • Human-readable and editable directly in your editor (VSCode, vim, etc.).
  • Optionally versionable (decision here: NOT version-controlled β€” see Limitations).
  • Zero dependencies, no third-party tool, nothing to install.
  • The agent reads it with its usual file-reading tool (read_file / cat / etc.).

Unlike Claude's native "memory" (which persists on Anthropic's servers), this system lives on disk, on your volume. You stay the owner β€” but it relies on the agent's discipline to read and maintain the files.


Limitations & design trade-offs

  • Reading discipline is still manual: .clinerules is injected, but nothing forces the agent to obey. In practice, recent models (GLM 5.2, Claude) follow the rule; a weaker model might ignore it.
  • The memory is not version-controlled: it survives a container rebuild only if the local volume persists. This is a deliberate choice (no secrets in git).
  • No Zoo-side memory backend: unlike Claude (which persists memory on Anthropic's servers), here everything is files on your disk β€” you stay the owner, but there's no automatic sync between machines.
  • Sanitize before sharing: if you ever want to share a ZOO.md (like this repo does for the system), strip every hostname, path, secret, or personal info before committing.

Known pitfalls (from real-world use)

  • 🚫 apply_diff corrupts emojis in SEARCH/REPLACE blocks (the character becomes U+FFFD). Never put an emoji inside a Zoo Code diff; if an emoji must be inserted near a change, use sed by line number (grep -n to locate, then sed "Ns|.*|...").
  • 🚫 git rejects spaces in branch names (git check-ref-format --branch exits 1). Convention: hyphens, no spaces, no accents.
  • ⚠️ If several git repos coexist (one at the root + one per project), project commits happen inside the project folder, not from the workspace root.
  • ⚠️ A .env referenced in a ZOO.md is just a hint β€” the real file stays gitignored and lives elsewhere (e.g. a secrets/ folder).

What's in this repo

README.md                    # This guide (generic, sanitized)
LICENSE                      # MIT
.gitignore                   # Ignores memory files (repo contains only the guide)
templates/
  .clinerules                # Trigger to copy at the workspace root
  ZOO-global.md              # Global memory template to fill in
  ZOO-project.md             # Per-project memory template to fill in
  gitignore-block.txt        # Block to append to each repo's .gitignore

Manual setup (optional)

Prefer to do it by hand, or want to audit what the agent did after the one-sentence install? Here's every step, each verifiable.

  1. Global memory β€” mkdir -p .zoo, copy templates/ZOO-global.md to .zoo/ZOO.md, fill in your real OS/tools/projects. Verify: cat .zoo/ZOO.md shows your real env, not placeholders.
  2. Per-project memory β€” for each project, copy templates/ZOO-project.md to <project>/ZOO.md, fill in architecture/DB/pitfalls/history. Verify: ls <project>/ZOO.md exists and describes the real architecture.
  3. Trigger β€” copy templates/.clinerules to the workspace root; edit the "User preferences" block. Verify: a new session's system prompt should mention the rules (ask the agent "what rules are in your system prompt?").
  4. Git exclusion β€” append the block from templates/gitignore-block.txt to every repo's .gitignore. Verify: git check-ignore -v ZOO.md matches, git ls-files | grep ZOO.md is empty.
  5. Enable injection β€” VSCode Settings β†’ zoo-code.useAgentRules β†’ on (default). Verify: see step 3.

Then jump to How to verify it actually works for the end-to-end test.


License

MIT β€” do whatever you want, including commercial use. Credit is appreciated but not required.

If this system is useful to you, consider starring the repo or opening an issue to suggest improvements.

About

Give Zoo Code persistent inter-session memory with plain Markdown files. A .clinerules trigger is auto-injected into every session so the agent reads its memory before answering.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors