I Built ContextFabric: One Private Memory Layer Across Claude, ChatGPT, Cursor, and More with Local Gemma 4 Based solely on the provided text, the article describes the creation of **ContextFabric**, a local AI memory layer powered by Gemma 4 that allows users to share portable, permissioned context across different AI tools like Claude and ChatGPT. The system uses a desktop app, local daemon, and browser extension to extract and store durable memory nodes (such as projects and decisions) in a local SQLite graph, ensuring user data remains private and is not sent to a cloud server. The project is built with technologies including Electron, React, and Ollama, and is submitted for the Gemma 4 Challenge. This is a submission for the Gemma 4 Challenge: Build with Gemma 4 AI tools remember now, but they remember in separate silos. Claude has projects, ChatGPT has personalization, Cursor indexes your codebase, and somehow you still end up re-explaining the same decisions, constraints, preferences, and project state every time you move between tools. That felt backwards to me. If memory is becoming part of the AI operating system, then personal context should not be trapped inside one vendor's product. It should be portable, permissioned, local-first, and owned by the user. So I built ContextFabric : a local AI memory layer powered by Gemma 4 . What I Built ContextFabric is a desktop app, local daemon, memory graph, and browser extension bridge that lets AI tools share approved context without sending your personal memory to a cloud memory server. The idea is simple: - Import your real project context: repos, folders, markdown, PDFs, ChatGPT exports, Claude exports, notes, and documents. - Gemma 4 runs locally through Ollama and extracts structured memory nodes. - ContextFabric stores those nodes in a local SQLite graph. - External tools request access. - You approve the request. - The browser extension injects the right context into Claude, ChatGPT, Cursor, Gemini, Perplexity, and other AI tools. The five core memory node types are: - project : what you are building - decision : choices already made and why - preference : stable working preferences - style : how you communicate, design, or code - person : collaborators and relevant human context This is not meant to replace Claude projects, ChatGPT memory, or Cursor indexing. It solves a different problem: your context should be portable across them . Demo Browser extension injection: The demo shows the full loop: - paste messy project context - Gemma 4 extracts structured memory nodes - nodes are saved locally with confidence scores - AI Query answers with sources - a permission request controls external access - the browser extension injects approved context into an AI chat tool Code GitHub: https://github.com/Boweii22/ContextFabric https://github.com/Boweii22/ContextFabric Live Site: https://boweii22.github.io/ContextFabric/ https://boweii22.github.io/ContextFabric/ The project is built with Electron, React, TypeScript, SQLite, Express, Ollama, and a Manifest V3 browser extension. The local app exposes two loopback APIs: - 127.0.0.1:47821 for the desktop app permission/token API - 127.0.0.1:7749 for the simple demo daemon UI and compatibility endpoints Both are bound to loopback, not 0.0.0.0 . That matters because the privacy claim is not just a paragraph in a README. The architecture does not expose a public server for your memory graph. How I Built It The architecture has six parts: User-owned sources repos, exports, docs, notes, PDFs | v Local ingestion chunking + metadata | v Gemma 4 via Ollama extract + reason | v SQLite memory graph nodes + embeddings | v Permissioned daemon localhost only | v Browser extension injects context The first hard problem was extraction. I did not want a generic summary. I wanted durable memory. That means the model has to decide whether a piece of text contains a project fact, a decision, a preference, a style signal, or a person. Here is the actual extraction schema prompt from the project: js export const CONTEXT NODE TYPES = 'project', 'style', 'decision', 'preference', 'person' as const export const CONTEXT EXTRACTION SYSTEM PROMPT = You are ContextFabric's local Gemma 4 context extractor. Your job is to read one piece of user-owned context and output ONLY valid JSON. No markdown. No prose. No comments. No trailing commas. Extract durable context nodes that another AI assistant should remember later. Use only facts supported by the input. Do not invent people, projects, tools, or decisions. Allowed node types: - project: what the user is building, maintaining, researching, or planning. - style: how the user writes, communicates, designs, codes, or prefers answers to be shaped. - decision: a choice already made, including why, tradeoffs, rejected alternatives, or reversibility. - preference: a stable working preference, constraint, tool choice, privacy preference, format preference, or habit. - person: a collaborator, stakeholder, user, client, author, or named human with relevant relationship/role context. Return this exact JSON shape: { "nodes": { "type": "project" | "style" | "decision" | "preference" | "person", "title": "short human-readable title", "summary": "one factual sentence, max 220 characters", "confidence": 0.0, "evidence": "short direct evidence phrase from the input, max 180 characters", "entities": "important names, tools, projects, people" , "tags": "lowercase-keywords" } } The parser is intentionally defensive. Gemma 4 is good at structured output, but production code still needs repair paths. export function parseContextExtraction raw: string : ContextExtractionParseResult { const errors: string = const parsed = parseJsonObject raw if parsed || typeof parsed == 'object' || Array.isArray parsed { return { ok: false, result: { nodes: }, errors: 'Output is not a JSON object.' } } const root = parsed as Record