Team Sync via .engrams/

In v1.4, Engrams uses a filesystem-first architecture for team knowledge. Decisions, patterns, and shared data are written as human-readable markdown files in .engrams/ — committed to Git and shared automatically. The SQLite database is a derived cache that can always be rebuilt.

New in v1.4: The .engrams/ directory replaces the older engrams-export/ hook-based workflow. Team items are now written to disk immediately when created — no export step needed.

How it works

When your AI logs a decision, pattern, or custom data item with visibility=team, Engrams performs a guaranteed write-through:

  1. SQLite first — the item is written to the local database to acquire a numeric ID.
  2. Filesystem write — a markdown file is written to .engrams/ using the pattern {nnn}-{slug}.md. This write is guaranteed — if it fails, the entire operation fails.
  3. Embedding (best-effort) — a vector embedding is created for semantic search. This step is non-blocking; if it fails, the item is still saved.

Directory structure

your-project/
├── .engrams/                    # ← Committed to Git
│   ├── config_seed.json         # Team/solo visibility default
│   ├── decisions/
│   │   ├── 001-use-postgresql.md
│   │   ├── 002-jwt-authentication.md
│   │   └── 003-react-query-for-server-state.md
│   ├── patterns/
│   │   ├── 001-repository-pattern.md
│   │   └── 002-error-handling-middleware.md
│   └── shared-data/
│       └── ProjectGlossary/
│           └── notification_channel.md
├── engrams/
│   └── context.db               # ← In .gitignore (local cache)
└── ...
What gets committed vs. what stays local:
  • .engrams/committed to Git — team decisions, patterns, shared data
  • engrams/context.dbin .gitignore — local cache (progress, active context, individual notes)

Setting up team sync

Step 1 — Initialize as a team project

When you run engrams init, choose Team when prompted (or pass --team):

engrams init --tool roo --team

# Or interactively:
engrams init --tool roo
# → "Project classification:"
# → [1] Team project — decisions shared via .engrams/ for git sync
# → [2] Solo project — decisions stay in local database only
# → Choose [1/2] (default: 1 for team): 1

This creates the .engrams/ directory structure and writes a config_seed.json that sets the default visibility to team.

Step 2 — Commit .engrams/ to Git

git add .engrams/
git commit -m "chore: initialize Engrams team sync"

Step 3 — Teammates clone and init

When a teammate clones the repo, they already get the .engrams/ directory with all team decisions. They just need to run:

pip install engrams-mcp
engrams init --tool roo --team

On first MCP tool call, Engrams reads the .engrams/ markdown files and populates the local SQLite cache automatically via TeamContentIndexer.scan_and_sync().

The filesystem-first invariant

This is the core architectural guarantee of Engrams v1.4:

Invariant: .engrams/ markdown files are the authoritative source of truth for team items. SQLite is always a derived, rebuildable cache. If the database is deleted, all team knowledge can be reconstructed from the filesystem.

This means:

  • Human-readable — open any file in .engrams/decisions/ with a text editor
  • Git-mergeable — markdown files support standard 3-way merge (unlike binary SQLite)
  • Auditable — use git log .engrams/ to see who changed what and when
  • Portable — copy the directory to any machine and Engrams rebuilds its index

How decisions are shared

The team sync workflow is fully automatic once .engrams/ is in your repo:

📝
Alice logs a decision

Her AI calls log_decision. Engrams writes to SQLite and creates .engrams/decisions/004-use-redis-caching.md

📤
Alice commits and pushes

git add .engrams/ && git commit && git push

📥
Bob pulls

git pull — Bob now has the new markdown file in .engrams/decisions/

🔄
Bob's Engrams auto-syncs

On the next MCP tool call, TeamContentIndexer detects the new file and imports it into Bob's local SQLite cache.

Content-addressed deduplication

Decisions are identified across machines by a content-addressed slug — a 12-character SHA-256 hash of the summary text. This means:

  • The same decision created on two machines produces the same slug
  • Import/sync recognizes identical decisions and skips them (no duplicates)
  • Patterns are matched by name, custom data by category + key

Rebuilding the database from .engrams/

If the SQLite database is lost or corrupted, Engrams automatically rebuilds it from the filesystem. You can also force a full re-index:

# Delete the local cache
rm engrams/context.db

# The MCP server rebuilds on next tool call automatically.
# Or trigger it manually:
engrams migrate

Visibility levels

VisibilityStored in .engrams/?Committed to Git?
team✅ Yes — write-through guaranteed✅ Yes
individual❌ No — SQLite only❌ No
proposed❌ No — SQLite only until accepted❌ No
workspace✅ Yes✅ Yes

Recommended .gitignore

# Engrams local database (rebuildable from .engrams/)
engrams/

# Do NOT ignore .engrams/ — it contains team knowledge
# .engrams/   ← WRONG — never ignore this

Legacy: engrams-export/ hook-based sync

Prior to v1.4, team sync used Git hooks that exported to engrams-export/ on commit and imported on pull. This approach still works via engrams install-hooks and is useful as a backup/snapshot mechanism, but the .engrams/ write-through is now the primary team sync method.

See Batch & Export for details on the hook-based approach.

MCP tools

  • log_decision — with visibility=team, writes through to .engrams/decisions/
  • log_system_pattern — with visibility=team, writes through to .engrams/patterns/
  • log_custom_data — with visibility=team, writes through to .engrams/shared-data/
  • export_engrams_to_markdown — full export for backup (separate from write-through)
  • import_markdown_to_engrams — import with merge=True for safe additive sync