tradeit.gg internal · engineering onboarding
Get the LLM Wiki running locally + import the tradeit.gg org synthesis.
Two halves travel together: the data (wiki pages, MEMORY.md, hooks, scripts) and
the reader contract (a prompt block in your ~/.claude/CLAUDE.md that
teaches your Claude to use it). Ship one without the other and the files become inert clutter.
Step 5 is load-bearing.
Walkthrough
A persistent, interlinked knowledge base maintained by Claude across sessions
Think of it as an LLM-readable wiki: every page has frontmatter
(confidence, scope, last_verified), wikilinks cross-reference
related pages, and a SessionStart hook injects the entrypoint into Claude's context
automatically on every new session.
The tradeit.gg org export contains scope: org and scope: both pages from
Ehud's master vault — repo synthesis, infra patterns, MySQL hard rules, business domain vocabulary.
Personal preferences and per-tool quirks are stripped before export.
| Tool | Version | Why |
|---|---|---|
| macOS | 14+ (Sonoma) | Scripts use BSD stat -f / date -j -f |
| Node | 22+ | export-org.sh runs node --input-type=module |
| Claude Code | latest | Fires the SessionStart + Stop hooks, reads MEMORY.md |
| Git | any modern | Auto-commits from the Stop hook |
| Obsidian | 1.5+ (cask) | Visual exploration, Dataview live views |
jq | any | Verify settings.json edits |
Install the missing pieces:
brew install node git jq
brew install --cask obsidian claude-code
You also need the latest org export tarball: tradeit-org-export-YYYY-MM-DD.tar.gz.
Ask Ehud, or build it yourself — see Maintainer notes.
Lay down the directory shape and the schema-disciplining files. The export tarball provides
wiki/, MEMORY.md, index.md and a filtered log.md —
but you create the surrounding skeleton (scripts, hooks, archive) first.
# Pick a stable home. Default below; substitute if you prefer elsewhere.
export VAULT_DIR="$HOME/MemoryVault"
mkdir -p "$VAULT_DIR"/{wiki/entities,wiki/concepts,wiki/sources,wiki/topics,raw,scripts,archive/inbox,.inbox,.export,assets}
cd "$VAULT_DIR"
git init -q
echo ".export/" > .gitignore
Copy the four hook + lint scripts from the skeleton source (Ehud's vault or a published skeleton repo).
Scripts are path-aware — they expect the vault at $HOME/MemoryVault;
edit the VAULT="..." line at the top of each if you chose a different location.
# Replace SRC with the path you received the skeleton from
SRC="/path/to/memoryvault-skeleton"
cp "$SRC/scripts/session-start-hook.sh" "$VAULT_DIR/scripts/"
cp "$SRC/scripts/session-stop-hook.sh" "$VAULT_DIR/scripts/"
cp "$SRC/scripts/export-org.sh" "$VAULT_DIR/scripts/"
cp "$SRC/scripts/lint.sh" "$VAULT_DIR/scripts/"
cp "$SRC/scripts/lint-repo-entities.sh" "$VAULT_DIR/scripts/"
cp "$SRC/CLAUDE.md" "$VAULT_DIR/"
chmod +x "$VAULT_DIR/scripts/"*.sh
CLAUDE.md at vault root is the schema spec — the LLM reads it on demand
when ingesting, querying, or maintaining the wiki. You won't typically edit it.
The tarball contains: wiki/ (org-scoped pages only), MEMORY.md
(entrypoint, personal links de-linked), index.md (filtered catalog), and
log.md (full history — read-only for you).
cd "$VAULT_DIR"
tar -xzf ~/Downloads/tradeit-org-export-2026-05-13.tar.gz --strip-components=1
# Verify the import
ls wiki/entities | head -5 # repo-tradeit-backend.md, repo-pricing-manager.md, ...
ls wiki/concepts | head -5 # mysql-hard-rules.md, pricing-domain.md, ...
cat MEMORY.md | head -10 # session entrypoint
Run the lint to confirm no broken links or frontmatter errors after import:
bash scripts/lint.sh
Expected: a list of OK lines, possibly a few STALE (90+ days unverified) or
NOSRC (entity pages missing a per-repo CLAUDE.md path) — both warnings, not failures.
Note on de-linked pages:
the export rewrites personal-scoped wikilinks (e.g., [[communication-style]]) as plain
text. You'll see them as non-clickable in Obsidian. That's intentional — those pages stay in Ehud's
private vault.
Two hooks make the vault feel native instead of inert:
| Hook | Fires when | What it does |
|---|---|---|
SessionStart | Every new Claude Code session | Injects MEMORY.md into Claude's context; surfaces pending .inbox/ items |
Stop | After every Claude turn completes | Auto-commits any uncommitted vault changes (idempotent) |
Edit ~/.claude/settings.json to add the hook entries. If you already have other hooks,
append these to the existing SessionStart and Stop
arrays — don't replace.
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "bash $HOME/MemoryVault/scripts/session-start-hook.sh",
"statusMessage": "📚 MemoryVault loaded — vault is live"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "bash $HOME/MemoryVault/scripts/session-stop-hook.sh",
"statusMessage": "Auto-committing MemoryVault..."
}
]
}
]
}
}
Verify the JSON parses:
jq '.hooks.SessionStart, .hooks.Stop' ~/.claude/settings.json
The SessionStart hook also writes an audit log. Tail it to see every fire:
tail -f ~/.claude/session-start.log
# [2026-05-13 09:12:04] vault loaded | MEMORY.md=103 lines | inbox=0 | cwd=/Users/you/...
Obsidian is the human-side interface. Claude reads the markdown directly via its hooks; you use Obsidian to browse, search, and explore the graph.
In Obsidian: File → Open Vault → Open folder as vault → choose
$HOME/MemoryVault.
MEMORY.md
Once Dataview is enabled, open MEMORY.md in Reading view to see the live
"high-confidence org pages" and "low-confidence pages" tables populated from frontmatter.
Without this, the SessionStart hook still injects MEMORY.md, but your Claude has no rules about what to do with it — no routing doctrine, no scope discipline, no inbox surfacing.
Append the block below to your ~/.claude/CLAUDE.md (create the file if it doesn't exist):
# MemoryVault — Reader Contract
You have access to a persistent, interlinked LLM Wiki at `$HOME/MemoryVault`.
It is the source of truth for tradeit.gg organizational knowledge — repo
synthesis, infra patterns, MySQL/Redis hard rules, business domain vocabulary.
The SessionStart hook auto-injects `MEMORY.md` (entrypoint) into your context
every new session. Follow these rules whenever you operate.
## Read order
1. `MEMORY.md` — already in context; orientation + high-signal entry pages.
2. `index.md` — full catalog by category. Load when answering navigational
questions or when MEMORY.md's entry list doesn't cover the topic.
3. `CLAUDE.md` (the schema) — read on demand when ingesting, querying, or
maintaining wiki pages. Authoritative on frontmatter, scope, supersession.
4. Specific `wiki/**/*.md` pages — drilled into via wikilinks `[[slug]]`.
## Frontmatter is authoritative
Every wiki page has `confidence` (0.0–1.0), `scope` (org | both — personal is
stripped from your export), `last_verified` (YYYY-MM-DD), `supersedes`,
`superseded_by`. Treat these as load-bearing:
- `confidence < 0.6` — speculative, verify before relying on
- `last_verified` > 90 days old — stale, mention staleness in your answer
- `superseded_by: <slug>` — read the successor page, not this one
## Repo-fact routing (LOAD-BEARING)
The vault contains `wiki/entities/repo-*.md` pages AND each repo has its own
team-owned `~/Projects/<repo>/CLAUDE.md`. They are complementary, not
competing:
- **How to work IN repo X** (build, test, in-repo conventions, debug recipes)
→ `~/Projects/X/CLAUDE.md` ONLY. Never the vault.
- **What X IS / how it fits the system / cross-repo synthesis**
→ `wiki/entities/repo-X.md` ONLY. Never the per-repo CLAUDE.md.
- **Cross-repo conventions** (MySQL, git, infra) → `wiki/concepts/*.md`.
**On conflict between vault and per-repo CLAUDE.md, per-repo wins.** Update
the vault page to match, bump `last_verified`, and never the reverse.
## What to write to the vault
When you learn a new durable fact about tradeit.gg in any session (regardless
of cwd):
- DO write a new/updated page under `$HOME/MemoryVault/wiki/{entities,
concepts,sources,topics}/` with proper frontmatter.
- DO update `$HOME/MemoryVault/index.md` and append to `log.md`.
- DO NOT write to `~/.claude/projects/<project>/memory/` for durable facts
about tradeit.gg — that's project-scoped, won't be loaded in other sessions.
- DO use project-scoped memory for ephemeral in-progress work that won't
outlive the current task.
## What to NEVER ingest
- `~/.local/secrets/` — live secrets, never read or grep
- `.env*` files (any variant) — live credentials
- Files containing API keys, JWT secrets, OAuth tokens
If a candidate source contains any of these inline, refuse the ingest and
surface to the user.
## Inbox-surfacing protocol (LOAD-BEARING)
When the SessionStart hook output contains a `=== Pending session-end notes
===` block, your VERY FIRST response in the session MUST surface those items
before addressing the user's actual request. Use this format:
> Pending inbox from previous session: <filename>
> Summary: <one-line synopsis>
> Process now, defer, or discard?
This OVERRIDES the no-filler / no-preamble preference — inbox surfacing is a
protocol step, not chatter. After the user decides, continue normally.
When processing: translate each suggestion into wiki pages per `CLAUDE.md`
§16, then `mv` the inbox file to `archive/inbox/`.
## Maintenance protocol
- Don't create a page for something mentioned once in passing. Wait for the
second mention. A wiki page needs at least 2 sentences of substance.
- Prefer updating in place over creating new pages with `supersedes`.
Reserve supersession for genuine reversals.
- When a session has produced durable learnings, proactively suggest running
`/revise-claude-md` near session end. Save its output to
`$HOME/MemoryVault/.inbox/session-end-YYYY-MM-DD-HHMM.md` so the next
session's hook surfaces it.
## Scope guardrail
All pages in your vault are `scope: org` or `scope: both`. Anything you write
back to the vault must respect that — no personal opinions, no unconfirmed
claims about teammates, nothing that wouldn't be safe to publish to the team.
Save the file. The next time you open a Claude Code session in any directory, the SessionStart hook will inject MEMORY.md and your Claude will know what to do with it.
Open a fresh Claude Code session in any project directory
(e.g., cd ~/Projects/tradeit-backend && claude). Run these four checks:
Ask Claude:
Without reading any files, quote me the first line of MEMORY.md.If it returns # MemoryVault — Session Entrypoint without using any tools, the hook is
working. The content is in its context from the injection.
Ask Claude:
What's the difference between scope:org and scope:both in this vault?Claude should answer from the schema (org = tradeit-only, both = applies
to both you and the team) without reading CLAUDE.md, because the rule is in your
~/.claude/CLAUDE.md reader contract.
tail -1 ~/.claude/session-start.log
# Expected: [<today>] vault loaded | MEMORY.md=NNN lines | inbox=0 | cwd=...
After any wiki edit (manual or via Claude), the Stop hook should auto-commit:
git -C "$VAULT_DIR" log --oneline -3
# Expected: latest entries prefixed with "auto: session-end <ts> — <category> (N files)"
If any check fails, see Troubleshooting.
| Situation | What happens |
|---|---|
| You learn a new MySQL gotcha for the team | Claude proposes a new/updated wiki/concepts/mysql-*.md; Stop hook auto-commits |
| You ask "what does the pricing-manager do?" | Claude reads wiki/entities/repo-pricing-manager.md first, then drills into the per-repo CLAUDE.md if needed |
| Per-repo CLAUDE.md disagrees with vault | Per-repo wins; Claude updates vault to match and bumps last_verified |
| You want to capture session learnings | Run /revise-claude-md near session end; output lands in .inbox/; next session's hook surfaces it |
| Visual graph exploration | Open Obsidian → graph view (Cmd+G) |
| Check for drift | bash $HOME/MemoryVault/scripts/lint-repo-entities.sh (weekly is plenty) |
jq '.hooks.SessionStart' ~/.claude/settings.json — confirm the entry exists and JSON is validls -l $HOME/MemoryVault/scripts/session-start-hook.sh — confirm executable (chmod +x if not)bash $HOME/MemoryVault/scripts/session-start-hook.sh — run manually; should print MEMORY.md contenttail ~/.claude/session-start.log — if empty after starting a session, hook isn't being called~/.claude/CLAUDE.md exists and contains the reader contract blockcat $HOME/MemoryVault/.gitignore — should exclude .export/ and local-only pathsgit add -A then commits. If you put secrets in the vault, they will be committed. Never put secrets in the vault. The privacy filter in the reader contract is your safety net.[[slug]] references point to personal-scoped pages not in your export. They render as plain text. Intentional.Expected. The vault page is Ehud's synthesis and may have aged. Re-pull the latest export from Ehud,
or update the vault page yourself: bump last_verified to today.
For whoever maintains the org export (currently Ehud).
bash /Users/ehudshahak/MemoryVault/scripts/export-org.sh
# exported NNN pages to /Users/ehudshahak/MemoryVault/.export
# personal-scoped links de-linked in M pages
# skipped K personal-scoped pages
cd /Users/ehudshahak/MemoryVault/.export
DATE=$(date +%Y-%m-%d)
tar -czf "$HOME/Downloads/tradeit-org-export-$DATE.tar.gz" .
echo "Built: $HOME/Downloads/tradeit-org-export-$DATE.tar.gz"
Distribute via 1Password Document, secure file share, or attach to the internal-docs PR.
Re-export cadence: weekly is plenty unless you've added major new pages.
Devs can pull the latest tarball and re-extract over their existing import —
tar -xzf overwrites in place.
| Resource | Location |
|---|---|
| Schema spec (authoritative) | $HOME/MemoryVault/CLAUDE.md |
| Session entrypoint | $HOME/MemoryVault/MEMORY.md |
| Wiki page index | $HOME/MemoryVault/index.md |
| Ehud's master vault | /Users/ehudshahak/MemoryVault |
| Export script | scripts/export-org.sh |
| Lint scripts | scripts/lint.sh, scripts/lint-repo-entities.sh |
| Hook scripts | scripts/session-start-hook.sh, scripts/session-stop-hook.sh |
| Audit log | ~/.claude/session-start.log |
Last verified 2026-05-13 · ping Ehud if any step diverges from what you actually see · tradeit.gg