The Operating System

Session Lifecycle · Repo Map · Primitives · Connections · Maintenance
Tide Cash Flow App
🌱 LIVING DOCUMENT — ALWAYS LATEST & GREATEST  This page describes how the Tide repo runs as a Claude Code workspace — the anchors, hooks, slash-command skills, MCP servers and self-maintenance loops the agent operates inside. It continues to be updated as new skills, policies, and hooks get added. The diagram below evolves as the system does. 💡 Hover any item (cursor turns to ?) for a plain-English "what it's for → what you get".
1

Session lifecycle

When each Claude Code primitive activates over a session. The harness fires hooks deterministically; Claude reads anchors (CLAUDE.md) and applies its conventions/guardrails as situations arise; slash-command skills run only when invoked. MCP servers are available the whole session once configured; subagents get isolated context for delegated work. Routines sit outside the session entirely — scheduled cloud agents that fire on a cron clock with your laptop closed.

SESSION TIME
STARTEND
CLAUDE.mdFoundation — auto-loaded
Reference docsARCHITECTURE / LEARNINGS / specs
HooksSessionStart + Pre/PostToolUse (per tool call)
ConventionsRead on situational trigger
SkillsUser-invoked (/command) or model-invoked
MCP serversAvailable once configured
SubagentsIsolated context for delegation
RoutinesOff-session — cloud cron (laptop closed)
Anchors (CLAUDE.md, docs) — loaded all session
Hooks — harness-fired, deterministic
Conventions — Claude reads on situational trigger
Skills — run on user or model invocation
MCPs — external tool servers
Subagents — isolated context for delegation
Routines — scheduled cloud agent, off-session
2

Repo map — the Tide monorepo

An npm-workspaces monorepo. Every top-level folder performs one of six roles. Color-coded to match the primitives in §3 and the lifecycle bars in §1.

Anchors

Always-on context loaded every session.
CLAUDE.mdroot — conventions, gotchas, workflow
README.mdproject overview + stack
docs/*.mdARCHITECTURE, DATABASE, LEARNINGS, specs
docs/*.htmlvisual maps (GitHub Pages site)

Hooks

Harness-fired / manual shell scripts. Deterministic.
scripts/session-role.shSessionStart — OWNER vs CONSUMER detection
scripts/session-context.sh newSessionStart — injects latest LEARNINGS + memory index
scripts/precompact-context.sh newSessionStart(compact) — re-grounds after compaction
scripts/budget-guard.sh newPreToolUse(Bash) — DENIES banned AWS cost commands
scripts/consumer-guard.sh newPreToolUse(Bash) — DENIES duplicate service starts on a CONSUMER session
scripts/git-guard.sh newPreToolUse(Bash) — DENIES commits/pushes to main (PR-only)
scripts/doc-sync-guard.sh newPostToolUse(Edit/Write) — reminds to update matching docs
scripts/security-guard.sh newPostToolUse(Edit/Write) — flags PII/encryption/Plaid/AI-write violations
scripts/changelog-guard.sh newPostToolUse(Edit/Write) — flags a stale Operating System changelog
scripts/dev-stack.shmanual — become OWNER (docker + API + worker)
scripts/check-api-key-security.shmanual — guards leaked API keys / .env
scripts/sync-portfolio.sh new/ship 6.6 — docs → portfolio mirror (origin/main only)
scripts/sync-changelog.py/ship 6.5 — regenerates this page's changelog from git log
scripts/sync-memory.shmanual — snapshots ~/.claude memory into memory/
.claude/settings.jsonwires SessionStart + Pre/PostToolUse hooks + permissions

Conventions (policy layer)

CLAUDE.md is the canonical statement of these rules; this card mirrors it.
Doc-syncschema/arch/flow change → update .md + .html same PR
DATA FLOW = SPECdata-flow-map.html is the primary spec
LEARNINGS loopauto-append bugs/lessons to LEARNINGS.md
$46/mo budgetno EKS / NAT / ALB / ElastiCache / Secrets Mgr
SecurityAES-256 PII, Bouncer per resource, redactForLogging
BankDataProvidernever call Plaid directly
OWNER / CONSUMERone session owns the stack + migrations

Skills, commands & agents

Three distinct .claude/ extensions — commands are user-invoked; skills can be model-invoked; agents are isolated subagents.
/ux-critiquecommand — principal-designer mobile UI/UX audit
/shipcommand — branch → PR → merge → notify (+ changelog, mirror sync)
/setup-evalscommand — scaffold / run an eval pipeline
update-learnings newSKILL — model-invoked on any bug fix → LEARNINGS.md
update-docs newSKILL — model-invoked on spec-bearing changes → matching docs, same PR
/new-ai-tool newSKILL — scaffolds the 4 Bedrock-tool files in lockstep + ai-pipeline-map
/new-model newSKILL — model+migration with encryption / serializeAs / HMAC / Bouncer baked in
/doc-drift newSKILL — on-demand all-docs drift sweep → docs: PR (twin of the §5 nightly routine)
spec-auditor newAGENT — read-only data-flow=spec drift audit
commands = .claude/commands/ (no SKILL.md, user-invoked only) · skills = .claude/skills/ · agents = .claude/agents/

App & packages — the substance

The shipping code: mobile, backend, shared libs.
apps/mobile/React Native + Expo (iOS dev build)
apps/backend/AdonisJS 6 API + BullMQ worker
packages/bank-data-provider/BankDataProvider + PlaidAdapter
packages/shared/types, encryption utils, constants
evals/92 tests, rule checks + AI judge, pre-flight, runner

Operations

Infra, CI, meta- and contributor docs.
infra/Dockerfiles, k3s manifests, Terraform
.github/workflows/ci.yaml, evals.yml, deploy.yaml, judge-experiment.yml, drift-supersede.yml
docker-compose.ymllocal Postgres + Redis
GitHub Pagesserves docs/ as the visual-docs site (Settings → Pages, main /docs)
.worktreeincludeparallel-session worktree isolation
3

Hooks vs. Conventions vs. Skills vs. Agents vs. Routines

The five layers people most commonly confuse — different in who runs them, when, what they're best for, and crucially whether they get their own context and a restricted toolset. In Tide, the "policy" layer lives as conventions inside CLAUDE.md rather than a dedicated policies/ folder. Agents are isolated helper Claudes under .claude/agents/; Routines are the newest layer and the only one that runs with no session at all — a scheduled agent firing on a cron clock in the cloud, laptop closed.

Dimension Hooks Conventions Skills Agents Routines
Tripwire Checklist Playbook Specialist Clockwork
What it is Shell scripts run by the harness at lifecycle events Markdown rules in CLAUDE.md Claude reads when a trigger fires Bundled workflows (command prompt + instructions) A separate Claude defined by a frontmatter file (system prompt + declared tools) A cloud agent + a cron schedule (a claude.ai routine), with its own repo checkout
Who runs it The harness (deterministic) Claude (judgment) Claude — a true skill can self-invoke from its description; a command only when the user types /name A fresh Claude instance the main one delegates to — runs independently, then returns Anthropic's cloud scheduler — fires the agent unattended, no one online
When it fires Lifecycle events (SessionStart, …) When the matching situation arises When invoked via slash command When a bounded task is delegated to it (by Claude or you) On a cron schedule (e.g. nightly 07:00 UTC) — even with your laptop closed
Best for Non-negotiables; observability; deterministic side effects Situational judgment Reusable multi-step workflows Noisy fan-out work whose result you want without the file-dump; tasks that must be sandboxed (e.g. read-only) Recurring unattended upkeep — nightly audits, drift sweeps, scheduled reports that open a PR
Own context? No — it's a shell process, not Claude No — it lives inside Claude's context No — runs in the main conversation Yes — isolated window; returns only its result Yes — a fresh cloud session per run; result lands as a PR/commit, not in your chat
Tool access Whatever the script itself does Claude's full toolset Claude's full toolset Restricted set declared in frontmatter (sandboxed) Declared per routine — repo checkout + chosen tools; runs off your machine
In this repo scripts/session-role.shscripts/session-context.sh (SessionStart)scripts/precompact-context.sh (SessionStart:compact)scripts/budget-guard.sh (PreToolUse)scripts/consumer-guard.sh (PreToolUse)scripts/git-guard.sh (PreToolUse)scripts/doc-sync-guard.sh (PostToolUse)scripts/security-guard.sh (PostToolUse)scripts/changelog-guard.sh (PostToolUse) DATA FLOW = SPEC — judgment only (spec-auditor + nightly sweep)OWNER / CONSUMER — partly hook-backed (consumer-guard.sh)BankDataProvider only — partly hook-backed (security-guard.sh) commands: /ship /setup-evals /ux-critiqueskills: update-learnings, update-docs, /doc-drift (model-invoked) spec-auditor (read-only: Read, Grep, Glob, Bash)Riu persona — drift auditor for DATA FLOW = SPEC Nightly Doc-Drift Sweep (Opus 4.8, 07:00 UTC)→ opens a docs: PR; lives in claude.ai, not the repo
4

External connections

What the workspace talks to outside its own repo: runtime services, MCP tool servers, and the Claude Code host.

Runtime services

What the app itself depends on.
Plaidbank data — via BankDataProvider only
AWS BedrockClaude Sonnet/Haiku — AI coach + classifiers
AWS CognitoJWT auth (1h access / 30d refresh)
PostgreSQLlocal docker / RDS-ready
Redis + BullMQqueue / background jobs

MCP servers

Tool servers reachable from the session.
Figma integrateddesign context for UI work
GitHub integratedPRs, issues, CI, reviews
Google Drive / Box available
Gmail / Calendar available
Vercel / DocuSign available

Host & sites

The Claude Code host and published surfaces.
Claude CodeOpus 4.8 (1M ctx) — web / remote container
.claude/settings.jsonrepo-level hooks + permissions
.claude/commands/repo slash-command skills
Routines liveclaude.ai — scheduled cloud agents (nightly doc-drift sweep)
GitHub Pages livepublishes docs/ on merge to main
5

How the system maintains itself

The cadences and automations that keep the workspace current and the docs honest — Tide's "self-improvement layer." The throughline of the latest iteration: migrate the highest-risk rules out of the §3 "Conventions judge" column (which depends on Claude remembering) and into the "Hooks fire" column — deterministic tripwires that cannot be silently skipped. The cards below are tagged tripwire (harness-enforced), convention (Claude judgment), CI (GitHub Actions), or routine (scheduled cloud agent).

Per session start · SessionStart hook

Role detection tripwire

scripts/session-role.sh probes ports 3333 / 8081 / 5432 / 6379 and prints whether this session is the dev-stack OWNER or a CONSUMER, so parallel sessions don't collide on the shared DB or port.

Per session start · SessionStart hook

Context injection tripwire

scripts/session-context.sh injects the latest docs/LEARNINGS.md entries (newest N=8) + the MEMORY.md index into every session's context at start. A SessionStart hook's stdout is added to the model's context, so a fresh session boots already aware of recent lessons + project memory — the just-in-time / progressive-disclosure pattern (surface a digest, not the whole file).

After compaction · SessionStart(compact) hook

Post-compaction re-grounding tripwire

scripts/precompact-context.sh fires on SessionStart with source=compact — the only hook that can inject context into the freshly compacted window (PreCompact can't). It re-asserts the compaction-specific delta: the in-flight branch + uncommitted work, any spec-bearing edits that still owe a doc sync in this PR, the ./NOTES.md working-memory scratchpad, and a "recall may be degraded — re-verify paths/flags" checklist. Directly implements Anthropic's guidance to preserve architectural decisions + unresolved work across compaction.

Per edit · PostToolUse(Edit/Write) hook

Doc-sync tripwire tripwire

scripts/doc-sync-guard.sh fires the moment an edit lands on a spec-bearing path (a migration, a route/controller, services/ai/**, a mobile screen) and injects an explicit reminder of exactly which .md + .html maps now owe an update in the same PR. The old "code + docs move together" mandate was convention-only — now the harness raises it on every relevant edit. data-flow-map.html is the product spec; code and flow must never drift.

Every /ship that touches docs/*.html · ship step 6.6

Portfolio-mirror sync new

The portfolio site (vikkybharadwaj.github.io/projects/tide/) republishes most of docs/*.html — and for two weeks nothing synced it, so it kept showing features the app had removed. scripts/sync-portfolio.sh makes the mirror a build artifact: manifest-driven from .claude/doc-map.json (portfolio_mirror), it copies every published page, re-applies the mirror's nav transform, deletes orphans, and warns when the hand-owned portfolio landing's stat numbers fall behind. /ship step 6.6 runs it in the same ship cycle as any docs change; /doc-drift runs --check as its 8th sweep area. Mirror pages are never hand-edited again. Because it publishes whatever the working tree holds, the apply mode refuses (exit 3) unless the checkout is exactly origin/main with a clean docs/: a stale local branch can no longer overwrite the live mirror with old docs. --check stays read-only and runs anywhere.

Per edit + every /ship · PostToolUse hook + ship step

Changelog freshness tripwire tripwire

This page's Changelog (top-right button) bills itself as sourced from the commit history — but it was a hand-maintained array, so it silently froze at #11 while five more PRs shipped without a row. Now scripts/sync-changelog.py regenerates it from the file's real git log (date, ET time, author, PR#), only ever appending so hand-curated highlight prose survives. /ship records each PR's own row in the same PR (no one-ship lag), and scripts/changelog-guard.sh is the PostToolUse backstop that re-flags the list the instant it falls behind committed history. The textbook convention→tripwire migration, turned on the page that describes it.

On any bug fix · model-invoked skill

LEARNINGS loop tripwire

The update-learnings skill (.claude/skills/) carries a description that lets Claude self-invoke it whenever a bug is fixed, a crash resolved, or a non-obvious stack fact discovered — appending a dated, root-caused entry to docs/LEARNINGS.md in the same PR. Upgrades the old "remember to append" convention into a model-invoked routine, reviewed before mobile work to avoid repeating known pitfalls.

Per command · PreToolUse(Bash) hook

PR-only deny-wall tripwire

scripts/git-guard.sh hard-denies git commit while on main and any git push that targets main. "Everything ships via PR" was convention-only and failed three days running — small fixes kept landing straight on main because the agent judged them "too small for a PR". Now there is no judgment call to get wrong: /ship is the only path.

Per command · PreToolUse(Bash) hook

Budget + security deny-wall tripwire

scripts/budget-guard.sh hard-denies any Bash command that would create a budget-busting AWS resource — eks, nat-gateway, elbv2/ALB, elasticache, secretsmanager — with a reason pointing to STACK_DECISIONS.md. The $46/mo budget Gotcha was convention-only; now a careless or prompt-injected agent physically cannot run the forbidden command.

Per command · PreToolUse(Bash) hook

CONSUMER collision guard tripwire

scripts/consumer-guard.sh re-probes :3333 on every Bash call: if a stack is already up (this session is a CONSUMER), it denies duplicate service starts — node ace serve / queue:listen / npx expo start / docker compose up — and asks for confirmation before a shared-DB migration. session-role.sh only warned; this enforces it, killing the port-conflict / zombie-process / shared-DB-corruption class for parallel sessions.

Per edit · PostToolUse(Edit/Write) hook

Security invariant tripwires tripwire

scripts/security-guard.sh inspects the file just edited and flags likely breaches of the fintech non-negotiables: an encrypted column missing serializeAs: null, PII in a console.* call without redactForLogging(), a direct Plaid SDK call outside PlaidAdapter, or a DB write from the read-only services/ai/** layer. The ORM-level encryption + Bouncer discipline was convention-only; now a violation surfaces the moment it's typed.

Pre-PR / on demand · subagent

Spec-drift auditor tripwire

The spec-auditor agent (.claude/agents/, read-only) checks that data-flow-map.html still matches the code — parsing each flow's spec block (windows, thresholds, formulas, tool shapes) and diffing it against the implementation, then adversarially confirming before reporting drift. Makes DATA FLOW = SPEC a checkable invariant and materializes the long-referenced "Riu" reviewer persona as a real project agent.

Nightly · 07:00 UTC · cloud routine

Nightly doc-drift sweep routine

A claude.ai routine (Opus 4.8) fires nightly at 07:00 UTC (3am ET) on a fresh cloud checkout — no machine of yours involved. It diffs every tracked doc against the code — data-flow-map.html, DATABASE.md, ARCHITECTURE.md, the security / ai-pipeline / cost maps, and the landing-page counts — and, when it finds drift, opens ONE review-only docs: PR citing each mismatch as doc:line → code:line; finds nothing, opens nothing. The cloud cousin of the spec-auditor agent — same DATA FLOW = SPEC discipline, but unattended, on a clock, and across the whole doc set. Managed at claude.ai/code/routines.

Whenever a new sweep PR opens · GitHub Actions

Superseded-sweep cleanup CI

.github/workflows/drift-supersede.yml closes older doc-drift sweep PRs the moment a new one opens. Each sweep is a fresh audit of main, so an older one is never worth merging, and left alone they piled up (fifteen open at once, all editing the same lines, so none could merge). Now exactly one is ever waiting on a person.

Every push / PR to main · GitHub Actions

CI: lint, typecheck, test CI

.github/workflows/ci.yaml runs lint + typecheck + tests against an ephemeral Postgres. Reused by deploy.yaml as a pre-deploy gate.

Nightly + opt-in per PR · GitHub Actions

AI eval suite CI

.github/workflows/evals.yml runs the full 92-test suite nightly (06:00 UTC). A PR touching apps/backend/app/services/ai/** or evals/** always gets the free structural checks, but the paid suite runs only when the PR carries the run-evals label. Each answer is scored by two graders (rule checks + an AI judge); a pre-flight check stops a run whose setup is broken, so it's reported as a harness failure rather than a 0% score. judge-experiment.yml (manual) measures the AI judge itself against human grades.

On merge to main

Docs auto-publish

GitHub Pages publishes the docs/ folder, so this page and every visual map go live at vikkybharadwaj.github.io/tide without a build step.