The Problem
Developers building AI‑augmented applications need a persistent “brain” that can store conversational context, retrieve relevant episodes, and trigger actions across many tools. Without a unified store, each app maintains its own silo, forcing developers to duplicate memory logic and lose coherence when users switch between services.
What This Does
core implements a memory agent that persists “episodes” in Neo4j, indexes them in a vector store, and exposes a React‑based UI for exploration and management. The main server lives under apps/webapp/ and is bootstrapped by the Vite config apps/webapp/vite.config.ts. UI components such as apps/webapp/app/components/conversation/*.tsx render chat streams, while apps/webapp/app/components/graph/*.tsx visualise topic graphs. Integration adapters (e.g., integrations/github/, integrations/discord/) provide plug‑ins that push and pull episode data via the core services.
Key files:
apps/webapp/app/bullmq/queues/index.ts– registers background queues.apps/webapp/app/bullmq/workers/index.ts– starts workers that ingest new messages.apps/webapp/app/services/logger.service.ts– centralised logging used by most modules.packages/providers/src/graph/neo4j/index.ts– thin wrapper around Neo4j driver used by the ingestion pipeline.
How It Is Wired
Execution starts when Vite launches the server defined in apps/webapp/app/entry.server.tsx. The server imports apps/webapp/app/bullmq/start-workers.ts, which in turn loads the queue definitions from apps/webapp/app/bullmq/queues/index.ts. Each queue enqueues a job that eventually reaches a worker defined in apps/webapp/app/bullmq/workers/index.ts.
A typical ingestion flow:
- API endpoint (
apps/webapp/app/components/api/index.ts) receives a POST with a new message. - It calls
apps/webapp/app/trigger/ingest/ingest.ts(part of an import cycle; see health section). ingest.tscreates a BullMQ job viaapps/webapp/app/bullmq/connection.ts.- The worker (
apps/webapp/app/bullmq/workers/index.ts) processes the job, invokingapps/webapp/app/lib/utils.tsfor payload normalization and thenpackages/providers/src/graph/neo4j/core.tsto persist the episode. - After storage, the worker pushes the episode’s embedding to the vector store (code located in
packages/providers/src/vector-store/).
Blast‑radius hubs – modules with the highest inbound imports:
| Hub module | Ca (importers) | Ce (imports) | Instability |
|---|---|---|---|
apps/webapp/app/components/ui/index.ts | 25 | 6 | 0.19 |
apps/webapp/app/lib/utils.ts | 25 | 0 | 0 |
apps/webapp/app/components/icons/types.tsx | 22 | 0 | 0 |
These files are touched by many downstream components; any change here will affect dozens of UI paths.
Circular imports – 11 modules participate in cycles; e.g., packages/emails/src/transports/index.ts ↔ apps/webapp/app/trigger/utils/queue.ts. Such cycles increase cognitive load and risk of runtime errors when refactoring.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/core
cd core
# Install dependencies (pnpm is the declared package manager)
pnpm install
# Copy example env and fill secrets
cp .env.example .env
# Edit .env (or hosting/docker/.env) with:
# NEO4J_PASSWORD, POSTHOG_PROJECT_KEY, MAGIC_LINK_SECRET, etc.
# Run locally (Vite dev server)
pnpm dev # starts the webapp on http://localhost:5173
# Or build and run the Docker image
docker build -t core .
docker run -p 3000:3000 --env-file .env core
The UI is reachable at the server’s root. API calls are routed through apps/webapp/app/components/api/ and background processing is handled by the BullMQ workers started automatically on server start.
Real‑World Use
A SaaS product that offers AI‑assisted customer support can embed the Core SDK (found under packages/providers/) in its backend. When a support ticket arrives, the service posts the ticket text to Core’s /api/v1/ingest endpoint. Core stores the episode in Neo4j, creates an embedding, and makes it searchable for future tickets. The product’s UI then uses apps/webapp/app/components/graph/graph-client.tsx to display related past tickets, enabling agents to surface prior resolutions instantly.
Code Health & Issues
Measured findings (static analysis)
- HIGH/clarity – Hub modules (e.g.,
apps/webapp/app/components/ui/index.ts) have 25+ dependents; keep them stable. - HIGH/soundness – 11 import cycles (e.g.,
packages/emails/src/transports/index.ts). Break cycles by extracting shared types. - HIGH/cognitive_load – Deep nesting (max depth 6) in several components; refactor with early returns.
- HIGH/cognitive_load – Oversized files (> 1 k lines) such as
apps/webapp/app/components/onboarding/provider-config.tsx. Split by responsibility. - HIGH/clarity – Repeated 6‑line blocks across > 200 files; extract helpers.
- MEDIUM/resilience – Empty
catch {}blocks in two files; add logging or rethrow. - MEDIUM/cognitive_load – High branching density in three utility files; consider strategy tables.
Code‑health audit (severity‑ranked)
- CRITICAL – Committed credentials in
hosting/docker/.env(MAGIC_LINK_SECRET, NEO4J_PASSWORD, POSTHOG_PROJECT_KEY). Rotate and remove from repo. - HIGH –
.envis tracked despite.gitignore;git rm --cached hosting/docker/.envand rotate keys. - HIGH – GitHub Actions use tag references; pin each action to a SHA.
- HIGH – No test suite; add tests for each public entry point and run them in CI.
- HIGH – Wildcard CORS (
"*"inapps/webapp/server.ts); replace with explicit origins. - MEDIUM – GITHUB_TOKEN permissions not declared; add least‑privilege scopes.
- MEDIUM – Dependabot not configured; add
.github/dependabot.yml. - MEDIUM – No dependency‑vulnerability gate; add
dependency-review-actionorosv-scanner. - MEDIUM – No pre‑commit secret scan; install a hook (e.g.,
detect-secrets).
The Bottom Line
core provides a full‑stack memory‑agent with a React UI, Neo4j backing, and extensible integration points, making it a solid foundation for AI‑driven apps. However, the repository currently ships live credentials, lacks automated tests, and contains several high‑impact architectural smells (hub modules, import cycles). Addressing the health issues and adding a test suite should be priority steps before adopting it in production.