Cecil works from the first message. No onboarding ceremony required. It learns your name, role, preferences, and context through natural conversation. If you want to bootstrap faster, optional onboarding creates a seed identity file.
Every conversation is analyzed for structured knowledge:
- Entities — People, projects, organizations, places, recurring topics. Tracked with mention counts and first/last seen timestamps.
- Beliefs — Opinions, values, preferences, principles. Tracked as active, revised, or contradicted, with temporal validity windows (
valid_from/valid_to). You can query what was believed at any point in time viabeliefsAsOf(date). - Open Loops — Things you said you'd do. Tracked as open, resolved, or stale (>30 days).
- Contradictions — When you say something that conflicts with an earlier statement, both are recorded with source references.
Access via CLI (npm run world-model), API (GET /api/entities), or programmatically (cecil.worldModel.entities()).
On-demand analysis that synthesizes the world model:
- Contradiction report — What changed, growth vs. inconsistency, which statement is current
- Open loop report — Grouped by age, which still matter, which were silently resolved
- Focus analysis — Entity mention frequency vs. stated priorities, hidden priorities, misalignment
- Pattern summary — Recurring themes, emotional patterns, strategic direction, blind spots
Run via CLI (npm run reflect), API (POST /api/reflect), or programmatically (cecil.reflect()).
Automated pipeline for memory hygiene:
- Exact dedup — Normalize text, keep higher quality, retire duplicates
- Semantic dedup — Cosine similarity >0.95 via Qdrant, merge near-duplicates. Processes all memories in batches of 50 (no longer capped at 100). Reports how many memories were checked.
- Quality sweep — Retire memories with quality score <0.4
- Stale loop detection — Open loops >30 days marked stale
- Contradiction refresh — Extract new contradictions from recent conversations
- Entity refresh — Rebuild entity mentions from recent memories
- Belief refresh — Check if active beliefs have been revised. Detects overlapping beliefs for the same entity and uses
reviseBelief()to properly close the old validity window instead of creating duplicates.
Steps 1-4 require no LLM calls. Steps 5-7 use batched LLM extraction. Supports --dry-run to preview changes. Individual steps can be run with --semantic-dedup, --beliefs, etc.
Every recalled memory carries an evidence tier:
| Tier | Source | Confidence |
|---|---|---|
| DIRECT_STATEMENT | User said it directly | Highest |
| OBSERVED_PATTERN | Detected from repeated behavior | Good |
| PUBLIC_CORPUS | Extracted from podcasts/transcripts | Useful, not private truth |
| INFERRED | Synthesized from multiple signals | Transparent inference |
Cecil's prompts enforce this discipline — it won't upgrade inference into certainty.
When Cecil doesn't have enough context to answer confidently, it triggers a [SEARCH: ...] marker. The system then:
- Searches across facts, podcasts, and observations in Qdrant
- Merges and deduplicates results
- Re-prompts the LLM with the search results
- Returns an evidence-backed answer
Every memory is automatically tagged with a domain: technology, business, personal, creative, health, education, finance, entertainment, or general. Detection uses keyword heuristics (no LLM call).
Domain-matched results get a scoring boost during retrieval (+0.5 in ranked recall, +0.3 in recall window). This is a boost only — non-matching memories are never excluded.
Conversations are embedded at three granularities:
- Full session (quality 0.65) — broad context
- Individual user messages (quality 0.55) — granular user intent
- Q+A exchange pairs (quality 0.60) — atomic user question + assistant answer
Exchange pairs get a scoring boost when the query looks like a question, ensuring "what did Cecil say about X?" queries find the relevant answer context.
After every chat session:
- Light pass (1 LLM call): Log conversation, detect domain, embed at 3 granularities (session + user messages + exchange pairs), record to SQLite, extract world model data
- Full synthesis (every N sessions, 3 LLM calls): Detect patterns, update narrative, compute drift, write observations
The synthesis interval is configurable via SYNTHESIS_INTERVAL in .env.
When you correct a fact ("Actually, I moved to Denver, not LA"), Cecil:
- Detects the correction
- Embeds the corrected information
- Soft-retires the conflicting old fact
- Web UI — Next.js app at
localhost:3000 - Discord bot — Full personality system with meeting facilitation
- REST API — 11 endpoints covering all functionality
- MCP server — 7 tools for Claude Code / Claude Desktop
- Client module — One import for any Node.js application
Beyond conversation, Cecil can ingest:
- Podcast transcripts (transcribe → ingest → extract facts)
- Interview transcripts
- Any long-form text content
These feed into the same memory system with appropriate evidence tiers.
Multiple ways to inspect what Cecil knows:
npm run memory:inspect # Browse memory
npm run memory:inspect -- --query="AI" --window # See ranked recall
npm run memory:audit # Health check
npm run world-model # World model summary
npm run world-model -- --entities # List all entitiesOr via API:
GET /api/memory?query=what+matters&includeWindow=true
GET /api/entities?kind=person
GET /api/contradictions
GET /api/open-loops?status=open