Learn Zharwing Memory without digging through repository files.
Start the local interface, connect an AI coding agent, or understand the system design. Every project guide is organized here and remains available in the open-source repository.
Zharwing Memory is a local-first project context manager for AI-assisted coding workflows. It is not the coding agent. External agents such as Codex, Claude Code, Gemini CLI, Ollama-based tools, LM Studio workflows, and future MCP-capable clients do the engineering work. Zharwing Memory provides their durable, project-scoped memory layer.
The product keeps project knowledge, AI session history, context bundles, diagrams, decisions, commands, gotchas, and optional review proposals organized per project. A human can open the local browser UI or native desktop app to understand current work, inspect AI context, inspect the graph, search previous work, and enable review workflows only when wanted.
Status: standalone personal developer preview. The current product is intended for a trusted developer using a local, single-user environment. It is not presented as a production, multi-tenant, or hardened harness release. See the developer preview boundary for the exact profile, limitations, compatibility policy, and validation gates.
This repository is the generic, project-neutral Zharwing Memory application source. Private user memory, project data, and personal workflows belong outside this repo in each user's chosen memory store.
Implemented:
TypeScript monorepo layout.
Local daemon API.
CLI helper.
MCP HTTP endpoint and stdio adapter.
Tauri + React desktop shell.
Markdown-first storage model.
Project registry and .zharwing/memory.json pointer support.
Project-scoped sessions and workstreams.
Context bundle generation with inclusion/exclusion reasons.
AI-visible project memory with explicit visibility exclusions, never-send rules, secret redaction, and high-risk blocking.
Optional Memory Inbox proposals for review-mode or risky updates.
Docs, diagrams, graph, search, backup snapshot, and rebuildable index boundaries.
Optional local Memory Assistant boundary with deterministic jobs and reviewable proposal support.
Generic Markdown folder importer with preview/commit flow for existing memory and session corpora.
Flexible named repository links with custom role/category metadata.
Desktop/web first-run flow for project-only and single-repo setup.
Recoverable delete flow with global Trash, restore, and permanent purge actions.
Lightweight desktop navigation with project switcher, primary sections, and section tabs.
Configurable project graph rules for mapping imported folder layouts to topics, services, packages, diagram groups, and code areas without hardcoded project names.
Optional semantic graph analysis for LLM-assisted relationship proposals, review/approval, accepted AI-reviewed graph overlays, and local OpenAI-compatible providers.
The Codex/MCP daily-memory loop is complete. The supported capabilities map to the focused MCP surface as follows:
Context preview/load and health checks complete the eleven-tool surface. Project creation, repository linking, imports, graph settings, backups, and destructive operations remain administrative UI/CLI actions by design; they are not missing daily-memory features.
The root test command passes a deterministic spine covering privacy gates, Markdown session/document round-trips, context privacy integration, daemon lifecycle, graph overlays, semantic graph policy, and a fake OpenAI-compatible semantic graph provider flow.
The daemon, CLI, MCP adapter, browser UI, and desktop UI are implemented.
Optional semantic graph analysis is implemented for local OpenAI-compatible providers and can be smoke-tested manually.
Graph context map, context, session, docs, import, inbox, backup, and trash workflows do not require an AI provider.
Validation still outstanding (separate from the completed Codex daily-memory surface):
Broad end-to-end test coverage across all desktop workflows.
Running the opt-in live-provider smoke against each provider configuration the project intends to support.
Installer generation and installer-level smoke testing; the packaged Windows .exe build itself has passed.
Current Windows-checkout validation includes TypeScript typecheck, the complete test suite and coverage thresholds, desktop contract tests, the Vite production build with bundle budgets, a real Edge app-shell smoke, Rust tests, a packaged Windows executable, source-artifact checks, and a live eleven-tool MCP doctor check.
Project-scoped by default. Sessions, docs, graph, search, context, and startup state all resolve to the current project unless the user explicitly asks for all-project behavior.
Markdown is the source of truth. The supported index is a versioned, dependency-free JSON projection rebuilt from Markdown. SQLite/FTS5 remains an optional future optimization for very large stores, not unfinished core functionality.
UI, CLI, and MCP share daemon behavior. The daemon owns project/session/context logic. Each adapter exposes its intended surface without reimplementing the underlying rules; MCP stays focused on the daily agent-memory loop.
AI-visible by default. Memory in the selected project is available to the coding agent by default, including sessions, paths, and routine metadata. Explicit visibility exclusions, never-send patterns, and secret scanning remain safety rails.
Memory writes are direct by default. External AI agents can write routine session progress and durable project memory directly. Memory Inbox review is an optional project setting for teams that want approval gates or for risky/uncertain updates.
Session graph visibility is opt-in. Every session remains available in Session History, search, and eligible AI context. Routine sessions do not create graph nodes. A user can enable Include in graph from Work -> Sessions when a session is important enough to belong in the durable project map; its derived relationships are included with it.
The browser UI is a complete local interface for normal daily use, not a demo or a reduced documentation view. It exposes the same React pages and workflows as the native desktop window.
Start the daemon in the first terminal:
bash
corepack pnpm dev:daemon
Start the browser UI in a second terminal:
bash
corepack pnpm dev:web
Open http://localhost:5174/. Keep both processes running. The browser UI calls the daemon at http://127.0.0.1:37841; dev:web does not start it.
The values of ZHARWING_MEMORY_AUTH_TOKEN and VITE_ZHARWING_MEMORY_AUTH_TOKEN must match. Restart dev:web after changing Vite environment variables. Browser path fields accept typed or pasted absolute paths because browsers cannot expose arbitrary local folders.
See the dedicated Browser UI guide for the full setup, browser-versus-desktop comparison, local authentication, and troubleshooting.
In a source checkout, the desktop shell starts or reuses the local daemon automatically. A copied release executable reuses an already-running daemon or uses ZHARWING_MEMORY_DESKTOP_DAEMON_COMMAND when configured. The native shell adds OS folder pickers; the core project, session, library, graph, and settings workflows are shared with the browser UI.
In either UI, create a project, then link repos from Repositories. For multi-repo products, create the project first and add each Git repo root afterward.
A pointer file is a small .zharwing/memory.json file that Zharwing Memory can write into a linked Git repo. It lets tools opened from that repo detect the matching memory project automatically.
When creating a project with Project only, the preview shows Pointer file: disabled because no repo is linked yet. Create the project first, then open Repositories, link each repo root, and leave pointer files enabled if you want agents and CLI tools to auto-detect the project from those repos.
To migrate existing Markdown memory, open Import after selecting the project. Use Memory Docs for old MEMORY folders, Session History for old SESSIONS folders, and Mixed Workspace when one folder contains both. Preview first; commit only after the counts and sample rows look right.
After importing, use Graph Rules when the imported folder layout should create context hubs in the Graph page. Open Settings -> Project -> Graph Rules and save a JSON array such as:
This is project configuration, not application hardcoding. Zharwing Memory matches rules against imported relative paths and derives context graph nodes from them. Imported documents participate normally. Imported sessions remain searchable history and default to Include in graph off; enable it per session before session metadata or its imported path contributes to the graph. Use Graph for memory relationships; use Diagrams for runtime architecture and service dependencies. See Graph Rules for the full manual and AI-assisted administration workflow.
For AI-assisted relationship cleanup, use the optional semantic graph workflow. Graph works without a model and shows trusted saved relationships. AI review creates Inbox proposals; accepted relationships then appear in Graph. See Semantic Graph Analysis.
LM Studio or another local OpenAI-compatible provider is needed only for provider checks, model-backed session TLDR generation, and model-backed semantic graph analysis. It is not required for normal validation, daemon startup, context preview, or Graph viewing. See Testing With AI Providers.
Never commit the memory store. It contains project sessions, docs, imports, context bundles, Memory Inbox proposals, and backups.
Deletion is recoverable by default. Projects, linked repo entries, workstreams, sessions, docs, inbox proposals, and backups move to Trash first. Trash supports restore, single-item permanent delete, selected permanent delete, and full empty.
That pointer file contains project identity, the machine-local memory location, and compact context-selection limits used during project detection. Because the memory location is machine-local, .zharwing/memory.json is ignored by this app repo by default. Teams can decide separately whether pointer files in their own linked repos should be committed or kept local.
For automatic session behavior in Codex, Claude, or local agents:
Start the daemon.
Register the MCP adapter with zharwing-memory mcp install auto.
Link source repos from the UI or CLI. For multi-repo projects, keep Write pointer file enabled for every repo and open a separate Codex workspace for each repo being actively changed.
Generate repo bootstrap files from templates/bootstrap/.
Optionally install templates/skills/ai-memory-session as a generic Codex skill or translate it into another agent's custom instruction format.
Agents should call memory.get_startup_state once per work round, use its compact carry-forward summaries, start a fresh daily/work-round session, search memory, request selected session detail or context only when needed, save checkpoints during work, and close or checkpoint at the end. See Agent Automation. See Repository Links for the shared-memory, separate-workspace multi-repo pattern.
For localhost-only personal setups, ZHARWING_MEMORY_AUTH_MODE=none lets MCP clients use http://127.0.0.1:37841/mcp without a bearer token. The daemon refuses no-auth mode on non-loopback hosts.
For MCP setup details, including Codex and Claude config, HTTP vs stdio, Windows/WSL reachability, desktop installer buttons, and troubleshooting, see MCP Setup.
The MCP adapter exposes exactly eleven project-scoped tools for the daily coding-memory loop:
memory.health
memory.get_startup_state
memory.get_latest_session
memory.get_recent_sessions
memory.get_session_detail
memory.start_session
memory.search
memory.preview_context_bundle
memory.get_context_bundle
memory.save_checkpoint
memory.close_session
The full daemon API is intentionally broader. Use the desktop UI or CLI for project administration, repository links, workstreams, document editing, imports, graph settings, backups, Trash, and other administrative operations. See API Reference for both surfaces.
The local browser UI and native desktop app share the same React human interface. The browser UI is often the fastest way to use Memory from a source checkout: run the daemon, run dev:web, and open http://localhost:5174/. The sidebar stays intentionally small:
project switcher for selecting, creating, and deleting projects
Dashboard
Repos
Work
Library
Import
Search
Trash
Settings
Secondary pages live inside section tabs:
Work: Current Work, Sessions, Workstreams
Library: Docs, Diagrams, Inbox, Graph, Context
Settings: Project, Setup, Assistant, Backups
In the native Tauri desktop window, Setup, Repositories, and Import provide Browse buttons for selecting folders with the OS file picker. The browser UI provides the same underlying workflows but uses typed or pasted absolute paths because browsers do not expose arbitrary local folder paths to web apps.
Install dependencies in the same operating system that will run Vite/build commands; shared Windows/WSL checkouts can otherwise keep the wrong native Vite/Rollup/esbuild optional package.
Mermaid diagrams are stored as Markdown and are intended to render in Mermaid-capable viewers.
The assistant runtime can generate searchable session TLDR metadata through a configured local OpenAI-compatible endpoint, with deterministic fallback. It does not download or run a model.
The versioned JSON index is a supported rebuildable project manifest. Search continues to read Markdown-backed project records; SQLite/FTS5 is optional future scaling work.
Zharwing Memory is being prepared as a standalone personal developer preview. This preview is useful for developers who want a local, inspectable memory layer for AI-assisted coding, but it is not a production, multi-user, or hardened agent-management release.
Preparing this preview does not publish the repository, create a release, or change any private memory store. Those are separate owner-approved actions.
The source candidate starts from a clean baseline. Generated output, dependencies, private stores, credentials, and machine-specific evidence are not release source.
The standalone personal preview and the future hardened harness integration are separate profiles.
The preview preserves the current personal workflow:
Authentication: token authentication remains the default. Explicit no-auth mode is limited to a loopback-bound personal daemon.
Visibility: selected-project memory is AI-eligible by default. Explicit visibility exclusions, never-send patterns, secret detection, redaction, and high-risk blocking remain enforced.
Durable writes: routine agent writes are allowed when project review mode is off. Review mode and Memory Inbox proposals remain available when the user wants approval or when a change is risky or uncertain.
Browser authority: the browser and desktop UI are the human interface. The browser uses the authenticated daemon and does not gain arbitrary local filesystem access. Destructive and administrative operations are not part of the eleven-tool MCP daily-memory surface.
Compatibility: the current CLI, daemon, browser/desktop UI, pointer-file format, Markdown store, and eleven MCP tools remain compatible for this preview. Existing stores are not silently migrated to a different policy.
Migration and rollback: the preview performs no profile-policy migration. A future hardened profile must be opt-in, versioned, preceded by a verified backup, and reversible to the standalone profile without rewriting canonical memory content.
The future hardened harness profile must add project-scoped least-privilege credentials, import-safe visibility, proposal-only durable knowledge changes, browser session credentials, and explicit migration and rollback behavior. It must not silently change the standalone preview's behavior.
Intended for a trusted developer operating a local, single-user environment.
Not qualified for multi-tenant, shared-host, or untrusted-network use.
Broad end-to-end coverage across every desktop workflow is still incomplete.
Optional live-provider compatibility requires opt-in testing with each provider; normal memory, search, graph, and context workflows do not require a model.
Installer generation and installer-level smoke testing remain outstanding. A packaged Windows executable has been built, but it is not being published as part of this source preview.
The hardened harness profile and its security/data-integrity qualification remain future work and are not implied by this preview.
The release evidence must record the candidate commit, branch, upstream, OS, Node and pnpm versions, command, exit code, timestamp, and any intentional skip. It must also include:
git status --short --branch before and after validation.
A clean-clone or fresh-checkout result using only tracked source and the frozen lockfile.
A screenshot made only from disposable demonstration data.
An independently reviewed diff with no secrets, private memory, generated source artifacts, or machine-specific paths.
Installer generation and installer-level smoke testing are explicitly outside this developer-preview source release and must not be reported as passed.
Remote CI and repository visibility changes happen only after a separate owner approval. If preview validation fails, keep the repository private, retain the current installation, and revert only the preview-specific source and documentation changes.
The token is ZHARWING_MEMORY_AUTH_TOKEN when set; otherwise the daemon generates a per-user token on first start and stores it in the OS user state directory. See API Reference for details.
Run this in a second terminal while pnpm dev:daemon remains active, then open http://localhost:5174/. The local browser UI contains the complete React interface. See Browser UI for environment setup and troubleshooting.
Native Tauri window:
text
pnpm dev:desktop
Use dev:web for daily browser-based use or development. Use dev:desktop when you want the same UI in a Tauri window with OS folder picker support.
pnpm dev:cli close --project my-app --session session-id "Save bug fixed; next step is regression coverage"
Closed sessions remain searchable history. In the UI, Include in graph is off by default; enable it from Work -> Sessions only for sessions that should create graph nodes and derived relationships.
The UI moves deletions to Trash first for projects, linked repo entries, workstreams, sessions, docs, inbox proposals, and backup snapshots. Open Trash to restore an item or permanently delete it.
If startup reports an unregistered repo, create or link it through the UI or CLI, then retry. Project creation and durable-memory administration are not MCP tools.
Normal session and context calls are project-scoped by default. Project memory is AI-visible by default; explicit exclusions and secret checks still apply.
Zharwing Memory includes a full local browser interface. It is the same React interface used inside the Tauri desktop window, not a reduced demo and not the public documentation website.
Use it for day-to-day project administration, sessions, workstreams, documents, diagrams, graph inspection, context preview, imports, search, backups, Trash, and settings.
Browser UI, Desktop App, And Documentation Website#
These are three different surfaces:
Surface
Where it runs
What it does
Local browser UI
http://localhost:5174/
Full Memory UI connected to your local daemon and private store
Native desktop app
Tauri window
The same React UI with native folder pickers and daemon lifecycle help
Public website
https://zharwing.barbutsa.com/memory/
Product documentation only; it cannot read or host your memory
For a multi-repository product, choose Project only, then add repository roots from Repos.
For a single repository, choose Project plus one repo.
In browser mode, paste or type absolute local paths into path fields.
Optionally use Import to preview existing Markdown docs or session history before committing the import.
The main navigation includes Dashboard, Repos, Work, Library, Import, Search, Trash, and Settings. See Browser And Desktop UI for the full navigation and workflow reference.
Both modes render the same React application and call the same daemon API.
Behavior
Browser UI
Native Tauri app
Human-facing features
Same core pages and workflows
Same core pages and workflows
Daemon startup
Start dev:daemon separately
Source checkout starts or reuses it automatically
Folder selection
Type or paste absolute paths
OS Browse buttons are available
App location
Browser tab at port 5174
Native window
Best fit
Daily local use, development, and debugging
Native folder selection and desktop workflow
Browsers cannot reveal arbitrary absolute folder paths to a web application. That platform restriction is why Browse buttons are unavailable in browser mode; it does not remove the underlying project, repo, or import features.
The recommended source setup uses token authentication. Keep ZHARWING_MEMORY_AUTH_TOKEN and VITE_ZHARWING_MEMORY_AUTH_TOKEN identical. The token is a local credential and should never be committed.
For a strictly localhost-only personal setup, the daemon also supports:
text
ZHARWING_MEMORY_AUTH_MODE=none
No-auth mode is refused on non-loopback hosts. Do not expose the Vite UI or daemon to a public network.
This is expected. The public website is documentation only. Your projects are available only through your local browser UI, desktop app, CLI, and connected agent tools.
The local browser UI and native desktop app are two runtime modes for the same React human interface. Neither is an agent. Both let a user create memory projects, link repos, import old notes, review context, inspect sessions, manage durable memory, and recover deleted items.
Browser mode uses two processes. Start them in separate terminals:
text
pnpm dev:daemon
pnpm dev:web
Open:
text
http://localhost:5174/
Native Tauri development mode:
text
pnpm dev:desktop
dev:web starts only the browser UI and expects a separately running daemon. dev:desktop starts the Tauri desktop window, runs the same React app inside it, and starts or reuses the local daemon automatically from the source checkout. A copied release executable needs an already-running daemon or an explicit ZHARWING_MEMORY_DESKTOP_DAEMON_COMMAND. Set ZHARWING_MEMORY_DESKTOP_AUTOSTART_DAEMON=false to disable desktop daemon autostart for debugging.
The browser UI cannot browse arbitrary local folders. In browser mode, path fields accept typed or pasted absolute paths. In the Tauri window, Setup, Repos, and Import can use OS folder picker buttons.
Behavior
Browser UI
Native Tauri app
Pages and workflows
Full shared React UI
Full shared React UI
Daemon
Start separately
Starts or reuses it in a source checkout
Folder selection
Type or paste absolute paths
OS folder picker buttons
Window
http://localhost:5174/
Native application window
For browser environment variables, token matching, first startup, and common errors, see the dedicated Browser UI guide.
Setup also includes Agent MCP actions for automatic install, installing Codex, Claude Code, or Claude Desktop config, and checking the current MCP setup. These actions call the same installer as zharwing-memory mcp install and require restarting the target AI client after config changes. See MCP Setup.
A repo path should be a Git repo root or a folder inside that repo. Zharwing Memory normalizes it to the repo root when possible.
Do not use the private memory store as a repo path. The memory store is where AI Memory writes project memory. Repo paths point to source-code checkouts.
Sessions is table-first, like Docs. Clicking a row (or its Open action) opens that session's detail panel and records the selection in the URL as ?session=<id>, so a session view is linkable and survives a reload. Close dismisses the panel. Project-wide summary actions (Summarize missing and, under Advanced, Regenerate all summaries) sit in the toolbar above the table so they do not require opening a session first.
Timestamps are shown in the viewer's locale (for example Tue, Jul 28, 2026, 03:44 AM). ISO strings are storage format only and are not displayed in tables or detail panels.
A session closed automatically at day rollover shows its close reason in the detail panel. See Agent Protocol.
Every session stays in Session History, search, and eligible context whether or not it appears in the graph. On the Sessions screen, Include in graph is off by default. Enable it only for an important session that should become a visible graph node. The session's derived task, touched-file, repo, workstream, and document relationships are included or excluded with it.
Docs is table-first. The table is the document navigation surface, with filters and pagination for imported projects that contain many Markdown files. Diagrams are stored as document records internally, but the Docs tab hides diagram docs because the Library has a dedicated Diagrams tab.
New projects include draft starter docs: overview, architecture, decisions, tasks, gotchas, commands, glossary, and privacy rules. These are reusable project-memory slots that agents can read and update across sessions. They are different from session files: sessions are chronological logs for one work run, while docs are longer-lived project knowledge that future sessions can reuse. The Docs table shows this explanation automatically on the Draft filter and behind a compact help button elsewhere.
Opening a row or using its Edit action opens a large editor modal. The modal edits the Markdown body directly, keeps document metadata compact in the header, and provides a Preview mode for human-readable rendered Markdown. Markdown remains the canonical storage format.
For documents with Mermaid blocks, Preview renders the diagram through Mermaid itself so users can review the diagram visually while keeping the source editable in Markdown mode. Each rendered diagram can be opened in a larger viewer with zoom controls for dense architecture diagrams. In the larger viewer, Ctrl/Cmd + mouse wheel zooms and Shift + mouse wheel pans the diagram horizontally when horizontal overflow exists.
Critical delete actions show a confirmation dialog. The dialog includes a Do not ask again for this type of item option. That preference is local to the browser/desktop UI storage.
Graph, Search, and Context are derived from active project data. They are not deleted directly. Delete or edit the underlying projects, sessions, docs, workstreams, inbox proposals, or backups instead.
Graph renders the derived project knowledge map as an interactive node canvas. It is not a service architecture diagram. Nodes are project metadata records such as repos, workstreams, sessions, docs, diagrams, and files. Edges are metadata relationships such as works-on, touched, referenced, supports, explains, or uses.
Graph shows saved relationships only. Deterministic metadata links and accepted semantic links are both durable project knowledge. Pending semantic suggestions stay in Inbox, where users can review the proposed relationships and accept or reject them before they affect the graph.
When imported docs need clearer hubs, edit graph rules in Settings -> Project -> Graph Rules. Rules map imported paths such as apps/* or services/* to context nodes such as packages, services, topics, code areas, or diagram groups. See Graph Rules.
Graph Details shows saved relationship metadata for the selected node or edge. Use Inbox for pending AI relationship proposals, including model reasoning and evidence. See Semantic Graph Analysis.
Repo links are created in two ways:
explicit metadata, such as a session repoPath, workingDirectory, or touched file path
inferred document metadata, such as document topics or import paths that match linked repo names, repo descriptions, or repo roles
The default Knowledge map mode shows repo/workstream anchors plus useful relationships. It intentionally hides plain document-to-project belongs-to membership links because those only mean an item is stored under the project.
Raw storage audit mode shows those membership links for import debugging. It is expected to be noisy: every imported doc and diagram belongs to the project, so raw mode can produce a large project-to-document fanout. Service architecture belongs in the Diagrams tab, where imported Mermaid diagrams are rendered visually.
Agent calls memory.get_startup_state once for the work round.
If project is resolved, server returns bounded active/latest/recent summaries and a startup revision.
If project is unregistered, server recommends project creation.
Agent asks the user to create or link the project through the UI or CLI.
User completes project setup and restarts/retries from the linked repo.
Agent extracts carry-forward work from compact summaries, searches when needed, and requests explicit session detail only when summaries are insufficient.
Agent calls memory.start_session for today's work round by default.
Agent previews a context bundle only when compact state and targeted search are insufficient.
A Zharwing Memory project can be linked to multiple repositories, services, packages, tools, or worktrees. The links are stored in the project model as repos: RepoLink[].
For multi-repo products, create the memory project first, then link each Git repo root from Repos. Do not point a repo link at the private memory store. Repo links describe source-code checkouts; the memory store is where Zharwing Memory writes sessions, docs, imports, context bundles, and Trash.
Project only: use this for multi-repo products, programs, clients, or any product that owns several services and frontends.
Project plus one repo: use this as a shortcut for simple single-repo projects.
After project creation, the UI redirects to Repos. Add every repo that belongs to the memory project. For a monorepo, link the monorepo root once instead of linking every package folder.
Leave Write pointer file enabled for each linked repo. Linking writes .zharwing/memory.json at that repo root. If a repo is already linked but its pointer is missing, submit the same repo path again with Write pointer file enabled; the existing link is updated and the pointer is created.
In browser mode, paste or type absolute paths. In the Tauri desktop window, use the Browse button to choose folders with the OS picker.
name: human-friendly label, such as Product runtime
description: what this source root owns
role: free-form category, such as service, worker, docs, product-runtime, codex-wrapper, or worktree
defaultBranch: optional branch hint
Roles are descriptive metadata, not a fixed taxonomy. Multiple repos can share the same role, and a project does not need to force every repo into one layout.
The UI and authenticated daemon JSON-RPC surface support:
memory.list_project_repos
memory.link_repo
memory.unlink_repo
memory.link_repo resolves a nested path to its repo root when possible, stores the normalized repo path, updates the project registry, and writes a .zharwing/memory.json pointer file by default.
memory.unlink_repo removes the repo from the project model and removes that repo's .zharwing/memory.json pointer file by default.
memory.delete_repo removes the repo link from the active project and stores the repo-link payload in Trash. It does not delete the source-code checkout.
Repository administration is intentionally not advertised through the focused MCP daily-memory surface. Use the UI or CLI to create, link, unlink, or delete repository entries.
Pointer creation is on by default. Use --no-pointer only when deliberately opting out. Verify any repo or nested folder with:
text
zharwing-memory detect <repo-root-or-subfolder>
The result should report the same <project-id> for every linked repo.
The pointer contains a machine-local memory path. Add .zharwing/memory.json to each linked repo's .gitignore unless that repo has an explicit team policy for sharing machine-specific pointers.
Using One Memory Project From Several Codex Workspaces#
A Zharwing Memory project can span many repositories even when one Codex window opens only one folder. These scopes are intentionally separate:
Zharwing project scope supplies shared sessions, search, docs, context, and graph knowledge across every linked repo.
Codex workspace scope controls which source folder is currently open and normally editable.
Linking a repo to Zharwing does not mount that repo into an existing Codex workspace or expand Codex filesystem permissions.
Recommended workflow:
Link every repo to the same memory project and write a pointer in each repo.
Open Codex in the repo being changed. Opening a nested folder also works because project detection walks upward to the repo pointer.
For simultaneous work in another repo, open a separate Codex window or thread rooted in that repo.
Let each work round create its own session. All those sessions share the same Zharwing project, while session metadata records the active repo and working directory.
For example:
text
Codex: backend repo ─┐
Codex: frontend repo ├─> one shared Zharwing Memory project
Codex: local tools ─┘
Project-wide memory can tell a backend Codex session about a frontend decision, but editing the frontend still requires a Codex workspace or explicit filesystem permission that includes the frontend repo. For cross-repo tasks, separate repo-rooted Codex sessions are the safest default; coordinate them through the shared memory project.
A workstream is a project-scoped container for multi-day work. It is the right place for things people may also call an epic, initiative, topic, lane, or focus area.
Use one Zharwing Memory project for a long-lived product area, then create workstreams inside it.
Example:
text
Project: Acme Product
Workstreams:
Search
Permissions and Roles
Post-auth Onboarding
Design System
Epic often implies a specific product-management hierarchy. Workstream is looser: it can group sessions, docs, repositories, imported memory, and decisions across several days without forcing an agile structure.
Sessions and documents can attach explicitly with workstream_ids. The workstream detail view also finds related sessions and documents by matching topics, related task labels, names, summaries, and body text.
The UI and authenticated daemon JSON-RPC surface support:
memory.list_workstreams
memory.create_workstream
memory.get_workstream_detail
memory.update_workstream_status
memory.delete_workstream
The focused MCP daily-memory surface can attach known workstream ids when starting a session, but workstream administration remains a UI/CLI operation.
Zharwing Memory includes a generic Markdown importer for bringing existing notes, session logs, and project memory folders into a project workspace. It is not tied to any one repository or folder layout.
The original Markdown body is preserved. Existing source frontmatter is used as input metadata, then Zharwing Memory writes its own normalized frontmatter around the body.
An import profile is a set of rules that tells Zharwing Memory how to interpret files in the selected source folder. The profile decides:
which files are included or ignored
whether matching files become long-lived project documents or historical session records
the default document type, status, visibility, and format
whether topics are inferred from folder names
which special path patterns should override the defaults
where the imported files will be written inside the project memory workspace
Profiles do not change the source folder. Previewing an import only scans files and shows what would happen. Committing the import writes normalized Zharwing Memory Markdown files into the selected project.
Use a profile based on what the source folder represents:
Source folder contains
Choose
Result
General Markdown notes, loose docs, or text files
generic-markdown
Every included file becomes a project document.
An old MEMORY-style folder with durable project knowledge
markdown-memory
Every included file becomes a project document, with memory-oriented type inference.
Old session logs, work logs, or dated AI run notes
markdown-sessions
Every included file becomes a closed historical session.
A mixed folder that contains both docs and session-like paths
workspace-markdown
Session-looking paths become sessions; the rest become documents.
Best neutral fallback. Infers topics from folders and document type from names like README, architecture, decision, plan, spec, command, gotcha, or diagram.
markdown-memory
Document
*.md, *.txt
docs/imported/markdown-memory/...
Same core behavior as generic Markdown, but intended for existing durable memory folders. Use this for old project knowledge, decisions, commands, gotchas, architecture notes, and reference docs.
markdown-sessions
Session
*.md, *.txt
sessions/imported/markdown-sessions/...
Imports files as closed session history. It preserves the body, infers dates from paths when possible, and marks the agent/client as import metadata when the source does not specify them.
workspace-markdown
Document unless path looks session-like
*.md, *.txt
docs/imported/workspace-markdown/... or sessions/imported/workspace-markdown/...
Files under paths like sessions/, session/, or names containing session become sessions; other files become documents.
All built-in profiles skip common non-memory folders and binaries, including .git, node_modules, archives, image files, PDFs, and local .codex files.
The Profile dropdown also exposes generic-markdown for loose folders that are not specifically memory folders or session-history folders.
Profiles are data, not code. Authenticated daemon JSON-RPC clients can pass a custom profile object with include/exclude globs, default kind, visibility, status, and path rules.
Imports preserve original relative paths under docs/imported/<profile>/... or sessions/imported/<profile>/.... The graph projection can use document paths to create useful context hubs such as packages, services, domains, teams, or diagram groups. Imported sessions default to Include in graph off, so their paths and other session-derived relationships contribute only after a user explicitly enables the session from Work -> Sessions.
If the Graph page is too flat after an import, add project graph rules manually in Settings -> Project -> Graph Rules. See Graph Rules.
The Graph page is a context map, not a storage inventory and not a service architecture diagram. Its job is to show which repos, workstreams, topics, services, packages, diagram groups, important sessions, docs, and files are connected by usable project memory.
Storage ownership links such as doc -> project are kept for audit/debugging, but they are intentionally hidden from the normal context view because they only mean "this record is stored in this project."
Zharwing Memory builds the graph from deterministic project data:
linked repo metadata
workstream metadata
session metadata only when the session has include_in_graph: true
document metadata
document topics
imported file paths
package names mentioned in document titles or early body text
optional project graph rules
No AI processing is required for the default graph. AI can help propose better rules, but those suggestions should go through the Memory Inbox unless a human explicitly applies them.
Routine sessions stay in searchable Session History and do not create graph nodes. On the Sessions screen, enable Include in graph for a session that is important enough to belong in the durable project map. The setting also controls all task, touched-file, repo, workstream, and document relationships derived from that session.
After saving, refresh Graph. The normal Context map should show the new context nodes and relationships. Use Import audit only to debug indexed storage records and ownership links.
AI clients should not silently rewrite graph rules unless the user asked for a direct settings change. The safer workflow is:
Read project data through the UI, CLI, or authenticated daemon methods such as memory.get_project, memory.list_docs, and memory.get_graph.
Inspect imported paths, topics, repo names, and noisy/missing graph areas.
Propose a JSON rules array with memory.propose_graph_update.
Human reviews the Memory Inbox item.
Human applies the graph rules from the Inbox or edits them in Settings.
Authenticated daemon proposal example:
json
{
"projectId": "my-app",
"proposedPatch": "[{\"match\":\"apps/*\",\"nodeType\":\"package\",\"topic\":\"frontend\"},{\"match\":\"services/*\",\"nodeType\":\"service\",\"topic\":\"backend\"}]",
"reason": "Imported docs are organized by apps and services folders, but the context graph has no package/service hubs.",
"confidence": "medium",
"sourceAgent": "codex"
}
Direct daemon JSON-RPC settings update, only when the user explicitly approves it:
Do not use graph rules to model runtime service dependencies. Put architecture, sequence, data-flow, and service-dependency diagrams in Diagrams. The Graph page should answer "what memory is connected to this area of the project?", not "what calls what at runtime?"
Do not encode project-specific constants into application code. If a project has unusual folders, keep that mapping in the project's graphRules instead.
Semantic graph analysis is the optional AI-assisted relationship layer for the Graph page. It does not replace the normal graph. The normal graph remains available without any model.
The Graph page is the trusted project map. It shows saved relationships only:
deterministic relationships from project metadata, imported paths, graph rules, docs, topics, related files, and repo links
accepted or auto-accepted semantic relationships
Pending AI relationship suggestions are not drawn on the main graph. They live in Memory Inbox until accepted. After acceptance, those relationships become trusted graph links and appear in Graph.
Each project has only one current pending AI relationship proposal. Running the relationship review again replaces older pending AI relationship batches instead of stacking duplicate approvals in Inbox.
Sessions are not shown as normal graph nodes by default. A session is activity history and provenance, not durable project structure. Closed sessions should receive searchable TLDR metadata, and durable docs/relationships should carry the long-lived project knowledge. A user can explicitly enable Include in graph for an important session; only then are its node and derived relationships added to the normal graph.
The URL keeps the active project, library section, and focus, for example:
Add Graph Rules if imported paths should become service, package, topic, or diagram-group hubs.
Open Graph and confirm the saved map is useful.
Open Assistant and configure an OpenAI-compatible provider, such as llama.cpp, Ollama, LM Studio, or another local endpoint.
Open Graph Details.
In AI relationship review, choose the scope and click Run review.
Review the generated proposal in Inbox.
Accept the useful relationships.
Return to Graph to see accepted relationships as trusted links.
Provider overrides, dry-run mode, auto mode, document/candidate limits, timeouts, output-token limits, and provider JSON mode are available under Advanced.
Only start LM Studio, Ollama, llama.cpp, or another OpenAI-compatible provider when you are testing model-backed behavior:
provider checks
dry-run semantic analysis
review-mode semantic analysis
auto semantic analysis
Do not start a model for Graph or semantic graph preview. Preview builds the document extraction and candidate plan without calling a model.
If using LM Studio, load a model, start its local OpenAI-compatible server, and copy the endpoint and model name into Settings -> Assistant or pass them to the semantic graph CLI/RPC calls. See Testing With AI Providers for the full smoke test.
Small local models should not receive hundreds of full documents in one prompt. Zharwing Memory breaks the task into smaller steps:
select eligible documents by scope
apply privacy and secret gates first
split large documents into bounded Markdown/line-aware chunks
extract compact facts per chunk
merge chunk facts into one document-level extraction
cache merged extractions by content hash
build a deterministic candidate list
ask the model to judge one candidate relationship at a time
require confidence, reason, and evidence
route reviewable edges through Inbox instead of silently mutating the graph
Chunk metadata keeps the chunk id, heading path, and line range so evidence can point back to the source area. Use a focused node, changed-docs scope, and low document/candidate limits when testing a 12 GB VRAM local model. Increase limits only after the model returns stable JSON and useful evidence.
Semantic graph quality depends on the candidate list as much as the model. The candidate builder prioritizes richer relationship targets, such as docs, services, packages, and code areas, before metadata-only targets such as files and topics. When richer candidates exist, file/topic candidates are capped so they do not crowd out actual conceptual relationships.
Review-mode proposals should usually contain:
direct document-to-document or document-to-service/package/code relationships
file/topic edges only when they add useful evidence
no duplicate inverse related pairs for the same two documents
relationship types and directions that match the evidence
Do not accept noisy proposals just because they are high confidence. If the proposal is mostly metadata links, narrow the scope, improve document titles, topics, and related files, then rerun dry-run or review mode.
llm-memory owns a built-in chunked extraction pipeline so semantic graph remains usable as a standalone open-source project:
text
large document
-> privacy gate and redaction
-> Markdown/line-aware chunks
-> model extracts compact facts per chunk
-> llm-memory merges chunk facts into one document extraction
-> deterministic candidate builder
-> model judges candidate relationships
-> Inbox proposal or durable semantic edge
The chunking path does not require a vector database or another companion service. It is intentionally simple: split by Markdown structure and line budget, keep source locations, merge duplicate entities/hints, and cache the document-level result.
small-contwxt-manager can be integrated later as an optional evidence provider, but it should not be required for semantic graph. The clean boundary is:
An adapter can ask small-contwxt-manager for evidence around a document, candidate target, or relationship query. llm-memory would still judge the relationship, write Inbox proposals, and store accepted/rejected edges. This proves the companion services work together without making standalone llm-memory depend on another local service.
Zharwing Memory does not require a vector store for semantic graph relationships. The default candidate builder intentionally uses deterministic project signals first:
document topics
workstreams
related files
imported paths
graph rules
repo/package/service names
extracted mentions and entities
existing deterministic graph links
This keeps relationship analysis explainable, cheap to run locally, and easier to review. The LLM judges likely relationships; it is not asked to compare the entire document corpus at once.
A vector store can be added later as an optional candidate source, but it should not be part of the default workflow. It is useful only when deterministic signals are not enough, for example:
imported docs have poor or missing metadata
related docs use different names for the same concept
users have very large, messy corpora
the graph misses obvious conceptual relationships after graph rules and extraction are tuned
the product needs a separate "find similar docs" feature
For normal project memory, deterministic candidates plus LLM judging are the preferred approach. Vector search would add storage, dependency, privacy, and rebuild complexity without clear value for small and medium project-memory sets.
Start an OpenAI-compatible server separately. This can be LM Studio, Ollama, llama.cpp, or another local endpoint. The exact model and command depend on your local install. Zharwing Memory only needs the HTTP endpoint and model name.
Then use Test provider. If the provider responds with valid JSON, Graph can use it for semantic analysis. In Graph Details, Run review creates an Inbox proposal instead of immediately trusting every relationship. Dry-run and tuning controls are under Advanced.
Semantic edges are not trusted just because a model produced them.
Each edge must include:
source node
target node
relationship type
confidence
reason
evidence quote
In Inbox:
Accept All Edges accepts the whole semantic proposal.
Accept High Confidence accepts only high-confidence edges.
Accept Review+ accepts high and review-confidence edges.
Accept link accepts one suggested relationship.
Remove link drops one suggested relationship from the current approval.
Regenerate review reruns the AI relationship review and replaces the current pending approval.
Reject all rejects the proposal.
New review-mode proposals include a provider-generated reviewer summary stored with the proposal. The UI displays that summary directly. It does not synthesize AI reasoning in the browser. Proposals created before this summary field existed show that no AI summary is available and should be rerun if a real summary is needed.
When only some edges are accepted, the proposal remains edited with the remaining edges.
Sessions are summarized separately from graph relationships. On close, Zharwing Memory generates a compact searchable TLDR for the session when a local assistant provider is configured. If no safe local provider is available, it writes a deterministic metadata summary instead. The summary is stored on the session frontmatter/body, not as a graph node. Generating a TLDR does not opt the session into Graph; the separate Include in graph setting controls that projection.
Session TLDR metadata includes:
summary
topics
summary_generated_at
summary_source
summary_model
The Sessions UI can:
generate or refresh one selected session TLDR
summarize only sessions missing generated TLDR metadata
regenerate all session TLDRs from the Advanced control
Zharwing Memory keeps Markdown documents as the source of truth for human-authored knowledge. Semantic graph data is stored as project metadata beside that Markdown because it is structured relationship data.
Generated extraction and candidate files can be rebuilt. Accepted semantic edges should be treated as durable project metadata because they represent reviewed user decisions.
Use the Graph context map without a provider for saved metadata relationships. Semantic analysis is an advanced layer for users who want model-assisted relationship cleanup; suggestions stay in Inbox until accepted.
Zharwing Memory exposes memory.* tools to external agents through two MCP transports:
HTTP MCP on the daemon:
``text POST http://127.0.0.1:37841/mcp ``
Stdio MCP from the CLI:
``text zharwing-memory mcp serve ``
Use HTTP when the AI client and daemon run in the same OS or network namespace. Use stdio when a client needs to launch a child process, when HTTP MCP is not supported, or when a bridge is easier than exposing a daemon URL.
Start or make sure the daemon is available, then run:
text
zharwing-memory mcp install auto
zharwing-memory mcp doctor
auto installs the supported MCP configs for the environment where it is run:
Codex user config.
Claude Code .mcp.json in the current working directory.
Claude Desktop user config.
Windows Codex and Claude Desktop configs as an extra scope when running inside WSL and Windows interop exposes the real Windows profile paths.
The installer updates client MCP config and creates a timestamped backup when replacing an existing file. Stdio configs use the running CLI entrypoint instead of a hardcoded checkout path.
Generated token-auth configuration uses the canonical ZHARWING_MEMORY_AUTH_TOKEN and ZHARWING_MEMORY_DAEMON_URL names. Existing configs that reference legacy AIMEM_* names continue to work during the compatibility window, but rerunning the installer migrates generated entries.
Tokens are not required by MCP itself. Zharwing Memory uses token auth by default because the MCP surface can create sessions and write checkpoints/closeouts, and because the same daemon also hosts the broader authenticated administration API.
No-auth mode is accepted only when the daemon binds to a loopback host such as 127.0.0.1, localhost, or ::1. The daemon refuses to start with ZHARWING_MEMORY_AUTH_MODE=none on non-loopback hosts.
For token mode, make the AI client process inherit ZHARWING_MEMORY_AUTH_TOKEN or use the installer's generated environment-variable reference. Do not write real tokens into repo files.
Project creation, repo linking, imports, graph settings, backups, Trash, and other administration are intentionally UI/CLI operations. Their absence from tools/list is expected and does not mean the Codex memory workflow is incomplete.
Zharwing Memory is AI-visible by default inside the selected project. Sessions, file paths, and routine memory metadata are available to Codex without a per-request approval prompt. Explicit exclusions and secret scanning still apply to search and generated context.
For a multi-repo project, write .zharwing/memory.json in every linked repo by leaving Write pointer file enabled when linking it. Codex can then open any one of those repos and resolve the same shared memory project. The memory scope can span all linked repos, but the Codex workspace and filesystem permissions still belong to the folder opened in that Codex window. See Repository Links.
The MCP URL must be reachable from the process that launches the AI client. 127.0.0.1 is not a portable machine-wide address; it means "this OS/network namespace."
Common layouts:
Windows AI client + Windows daemon: use HTTP MCP at http://127.0.0.1:37841/mcp.
WSL AI client + WSL daemon: use HTTP MCP at http://127.0.0.1:37841/mcp.
WSL installer + Windows clients: zharwing-memory mcp install auto also tries to write Windows Codex and Claude Desktop config files by asking Windows for profile paths through interop.
WSL AI client + Windows daemon: first run zharwing-memory mcp doctor from WSL. If the daemon is not reachable at 127.0.0.1, run the daemon in WSL or launch a stdio bridge from Windows. Startup accepts WSL /mnt/<drive>/... working directories and normalizes them before Windows pointer/repository detection.
Windows installer + WSL clients: run zharwing-memory mcp install auto inside WSL separately. A Windows process should not guess a WSL distro, user, or tool path.
Do not bind the daemon to 0.0.0.0 with ZHARWING_MEMORY_AUTH_MODE=none. No-auth mode is intended only for same-machine loopback use.
Daemon unreachable: start the daemon, fix --daemon-url, run the daemon in the same OS/network namespace, or use a stdio bridge that can reach it.
Tools: (none) in an AI client: the client started but MCP initialization or tools/list failed. Check the client config and run the doctor command from the same shell or OS environment.
Auth failure: use ZHARWING_MEMORY_AUTH_MODE=none for loopback-only local personal use, or make the client inherit ZHARWING_MEMORY_AUTH_TOKEN.
Windows/WSL native dependency errors: reinstall dependencies in the OS where the command is being run.
An agent should be able to start inside a linked repo and automatically:
Detect the active Zharwing Memory project.
Read the latest relevant previous session, including the last weekday session after weekends or gaps.
Create a fresh session for the current day or work round by default.
Search prior project memory.
Load relevant context when needed.
Save checkpoints during work.
At end-of-day or work-round closeout, save final progress and close the session or leave next steps.
This daily-memory workflow is implemented. The focused MCP adapter exposes all of these capabilities; broader project administration stays in the UI and CLI.
Start the daemon first or use the desktop app to start or reuse it:
text
corepack pnpm dev:daemon
Recommended local setup uses the daemon's Streamable HTTP MCP endpoint:
text
zharwing-memory mcp install auto
zharwing-memory mcp doctor
The installer writes or updates detected client MCP configs, creates a timestamped backup when replacing an existing file, and uses the running CLI entrypoint for stdio configs instead of hardcoded checkout paths.
For localhost-only personal use, set:
text
ZHARWING_MEMORY_AUTH_MODE=none
No-auth mode is refused when the daemon is not bound to a loopback host.
Manual templates remain available in templates/mcp/:
codex.toml for Codex MCP configuration.
claude-desktop.json for Claude Desktop-style MCP configuration.
The MCP endpoint exposes memory.* tools and calls the local daemon. It does not store project data by itself.
The selected project is AI-visible by default. MCP returns normal sessions, paths, search results, and context without per-request approval. Only explicit visibility exclusions, never-send rules, and secret detection limit results.
For full setup details, including --transport stdio, token-auth config, desktop installer buttons, and Windows/WSL reachability, see MCP Setup.
Codex users can install the generic skill template from:
text
templates/skills/ai-memory-session
The skill tells an agent to use Zharwing Memory at session start, during progress checkpoints, and at closeout. It should not contain private project names or paths.
For users who prefer daily Markdown session files, use the compact carry-forward state returned by startup and then call memory.start_session for today's work. Use resume only when the user explicitly asks to continue the existing session.
Zharwing Memory should not prescribe a universal source-control, release, deployment, or task-tracker workflow. Those workflows are project-specific and belong in a private project profile, repo bootstrap file, or personal agent skill.
When such a project-specific closeout exists, Zharwing Memory can help by listing today's sessions/checkpoints, identifying touched repos, and recording final artifacts such as commit hashes, PR links, deploy targets, external task ids, blockers, and next steps.
Do not send or store secrets, .env files, private keys, credential caches, or unrelated private logs. Keep context project-scoped unless the user explicitly requests cross-project context and policy allows it.
This protocol defines how any AI agent should use Zharwing Memory. It is project-neutral and agent-neutral. Do not put project names, machine-local paths, or vendor-specific task systems in this file.
Zharwing Memory is the durable context layer for AI-assisted work. Agents use it to find relevant project knowledge, preserve session history, write durable memory updates, and build context bundles before doing work.
Zharwing Memory is not automatically the project task tracker, issue tracker, CI system, source control system, or deployment system. When a project has an external task system, store only stable references to external task ids in related_tasks metadata unless that project explicitly adopts Zharwing Memory for task tracking.
Resolve the active project from the current working directory or explicit project id.
Read startup state before assuming whether to resume or start a session.
Read the latest relevant previous session when the user or project prefers daily/session-per-work-round logs. Carry forward unfinished tasks, next steps, blockers, touched files, and decisions.
Search project memory for the task, feature, error, or file names involved.
Start a new project-scoped session for meaningful work by default. Resume only when the user explicitly asks to continue an existing session or the project policy says to reuse active sessions.
Preview or generate a context bundle when prior context matters.
If memory tooling is unavailable, continue with the user's task using local project files and report that Zharwing Memory was unavailable.
Agents frequently exit without closing their session. memory.start_session and memory.start_or_resume_session therefore close any session still marked active from an earlier local day before they create or resume anything, so start_or_resume never hands back yesterday's log as today's session. The auto-close records closed_reason, keeps updated at the last real activity, and fills a missing TLDR deterministically. Closing a session explicitly is still preferred: only an explicit close records the real summary, next steps, and blockers.
Save checkpoints after meaningful progress, decision points, or interruptions.
Add touched files, blockers, and next steps when saving progress.
Keep durable facts as docs, not only in the session body. Write routine memory directly when review mode is off.
Use Memory Inbox proposals when review mode is enabled, or when an update is risky, uncertain, private-sensitive, or should not become canonical without a human pass.
Link sessions and docs to workstreams when the task belongs to a known multi-day topic.
Link external task ids in related_tasks only when the project provides them.
Search before creating new durable docs to avoid duplicates.
When graph context looks noisy or missing useful hubs, inspect imported paths and propose graph rules with memory.propose_graph_update. Do not silently rewrite project graph rules unless the user explicitly asks for direct settings changes.
Treat end-of-day, "work is over", and explicit close-session requests as memory closeout triggers.
Follow project-specific source-control, release, deployment, or task-tracker closeout policy only when that policy is provided outside this universal protocol.
Close the session with a concrete summary.
Include next steps, blockers, touched files, and external closeout artifacts when known.
Write durable memory updates when the session established reusable facts, commands, decisions, gotchas, or architecture notes and review mode is off.
Route updates to Memory Inbox only when review mode or update risk calls for it.
An MCP adapter is complete enough for routine coding work when it can resolve startup state, read latest/recent sessions, start sessions, search project memory, preview/load context, save checkpoints, and close sessions. Project administration, imports, backups, graph settings, and Trash are administrative operations handled by the UI or CLI.
Project-specific setup belongs in the project profile and project workspace, not in this protocol. A project profile may define linked repos, workstreams, import roots, graph rules, privacy policy, context policy, assistant policy, and optional external task-system references.
Use this adapter when an agent has Zharwing Memory MCP tools.
The daily-memory surface is complete and intentionally limited to eleven tools. Administrative daemon methods are not missing MCP capabilities; they belong to the UI and CLI administration interfaces.
The JSON-RPC adapter should call the same memory.* methods listed in the API reference. Keep requests project-scoped unless the user explicitly asks for cross-project context and policy allows it.
Startup returns compact summaries and a stable revision. A justified refresh may pass that value as knownRevision; unchanged state returns a minimal notModified response. Use memory.get_session_detail for explicitly selected body or paginated checkpoint history.
Zharwing Memory is a local-first project context manager for AI-assisted coding tools. The architecture has one important rule:
text
UI, CLI, and MCP adapters do not own memory behavior.
They call the daemon.
The daemon calls shared packages.
Shared packages read and write Markdown source files.
storing sessions, docs, diagrams, commands, gotchas, decisions, and proposed updates
generating context bundles
previewing exactly what will be sent to AI clients
enforcing privacy, redaction, visibility, and never-send rules
exposing MCP and CLI integrations
maintaining rebuildable indexes and graph projections
providing a desktop interface
running optional local assistant jobs
External AI agents are responsible for:
understanding coding tasks
reading and editing code
debugging
running tests
implementing changes
proposing memory updates
The local Memory Assistant is responsible only for memory maintenance jobs such as summaries, classification, return-to-project summaries, and proposal drafting.
shares MCP request handling with the daemon HTTP /mcp endpoint
maps MCP tool calls to daemon behavior
exposes prompt/resource text for startup and checkpoint behavior
advertises only health, startup state, latest/recent sessions, session start, search, context preview/load, checkpoints, and closeout
The adapter is intentionally thin and focused. Project administration, document editing, imports, graph settings, backups, and Trash remain in the UI, CLI, and authenticated daemon administration API.
Memory is AI-visible by default inside the selected project. Sessions, file paths, and routine metadata are normal agent context; the privacy layer is an explicit-exclusion and accidental-secret safety rail, not an approval gate for ordinary memory access.
Visibility values:
ai-eligible: can be included if relevant
ai-pinned: intentionally included unless blocked
human-only: visible in app, not sent to AI by default
private: visible only to user, not sent to model contexts
never-send: blocked from all AI/local-assistant prompts
Default blocked patterns include:
.env
.env.*
private keys
credentials
secrets
.git/
node_modules/
build outputs
coverage
caches
High-risk secrets block context. Lower-risk findings can be redacted.
All-project search should remain an explicit advanced mode.
Session history and graph projection are intentionally separate concerns. All sessions remain stored and searchable, while the deterministic graph builder projects only sessions with include_in_graph: true. The desktop UI owns that opt-in; the focused MCP tool surface does not expose it.
The TypeScript workspace typechecks and the root test command runs a deterministic spine covering privacy gates, Markdown storage round-trips, context privacy integration, daemon lifecycle, graph overlays, semantic graph policy, and fake-provider semantic graph analysis. Desktop contracts, bundle budgets, a real Edge app-shell smoke, Rust tests, and a packaged Windows executable have also passed. Runtime validation remains narrower than the full product surface: broad desktop end-to-end coverage and configured live-provider smokes are still opt-in work.
Vite build validation depends on native Rollup/esbuild optional packages being installed for the operating system running the command. Shared Windows/WSL checkouts should reinstall dependencies in the active environment before treating build failures as product regressions.
The dependency install, typecheck, test, production web build, daemon/CLI smoke workflow, Rust check, and MCP doctor flow have been completed in the shared Windows checkout. Remaining productization work is narrower:
Extend browser-level desktop UI coverage from the app-shell smoke to critical workflows.
Run the opt-in live-provider smoke for each supported deployment profile.
Add and smoke-test a Windows installer if distribution requires one; the release executable build already passes.
Decide whether the rebuildable JSON index remains sufficient or should be supplemented by SQLite/FTS5.
Treat app-managed llama.cpp download/launch as an optional future runtime, not a prerequisite for normal Zharwing Memory or MCP operation.
Repo role is free-form category metadata. Examples include service, worker, docs, product-runtime, codex-wrapper, and worktree, but the app does not restrict the value.
memoryWritePolicy.reviewMode controls whether durable memory updates are written directly or routed to Memory Inbox. The default is off, which allows direct agent writes. risky-only keeps routine updates direct and reserves the inbox for risky or uncertain updates. all disables direct document writes and routes durable memory changes through proposals.
The default privacy policy makes memory inside the selected project AI-visible (ai-eligible) and does not require approval before serving context. The remaining fields are scope and secret-safety controls: they keep context inside the selected project, honor explicit exclusions, and avoid passing credential-shaped content to an agent.
graphRules is optional project configuration for deriving useful context graph nodes from imported folder layouts. It belongs in project.json, not in application code. See Graph Rules.
id: workstream-uuid
project_id: my-app
name: Huddle
slug: huddle
status: active
summary: Multi-day Huddle runtime and service work
goal: Ship the Huddle feature across repos
topics:
- huddle
- realtime
repo_roles:
- product-runtime
- service
related_tasks: []
related_files: []
pinned_doc_ids: []
created: 2026-06-08T00:00:00.000Z
updated: 2026-06-08T00:00:00.000Z
closed:
body: Full Markdown body after frontmatter.
Workstreams live under workstreams/<slug>.md. Sessions and documents can link explicitly through workstream_ids; the workstream detail view also finds related items from matching topics, tasks, names, summaries, and body text.
id: session-uuid
project_id: my-app
repo_path: <repo-root>
working_directory: <repo-root>
branch: main
agent: codex
client: zharwing-memory-cli
status: active
started: 2026-06-08T00:00:00.000Z
updated: 2026-06-08T00:00:00.000Z
closed:
closed_reason:
task_title: Fix settings page save bug
include_in_graph: false
goal: Make settings save reliably
summary:
next_steps: []
blockers: []
touched_files: []
workstream_ids: []
related_docs: []
related_tasks: []
context_bundle_id:
body: Full Markdown body after frontmatter; preserved and used for raw session context.
import_source_path:
import_source_hash:
imported_at:
import_profile:
closed_reason is set only when the daemon closed the session on its own. A session left active on an earlier local day is auto-closed the next time a session is started for that project, because agents routinely exit without an explicit close. The auto-close keeps updated at the last real activity, fills a missing TLDR deterministically (never through an AI provider), and appends a Close reason line to the session body. See Agent Protocol.
include_in_graph defaults to false, including for older session files where the field is absent. Every session remains available in Session History, project search, and context selection. Only sessions explicitly marked true appear as graph nodes; task, file, repo, workstream, and document relationships derived from those sessions follow the same opt-in rule.
Imported documents are written below docs/imported/<profile>/.... Imported sessions are written below sessions/imported/<profile>/.... Both preserve the source Markdown body and add import provenance metadata.
Delete operations move recoverable items to global Trash before permanent purge. Trash is global to the memory root so deleted projects can still be listed and restored after they are removed from the active project registry.
Path-backed items, such as projects, workstreams, sessions, documents, inbox proposals, and backups, move their original file or directory into the trash item directory. JSON-backed items, such as linked repo entries, store their payload in payload.json.
Restore moves recoverable items back to their original active location and removes the trash metadata. Purge permanently deletes the trash item directory.
The graph is derived from project/document metadata and opted-in session metadata. It is not the source of truth. Graph rules contribute extra context nodes and relationships during projection.
Semantic graph analysis is optional. It stores reviewed AI-assisted relationships as structured project metadata while Markdown docs remain the human-readable source of truth.
status: proposed, accepted, rejected, or auto-accepted
confidence
reason
evidence
source
Semantic document extractions may include chunk metadata:
chunkId
index
headingPath
startLine
endLine
per-chunk summary, entities, concepts, mentions, and candidate hints
Large documents are split into bounded Markdown/line-aware chunks. The model extracts facts per chunk, then llm-memory merges those chunk facts into a single document-level SemanticDocumentExtraction cached by document content hash. This keeps semantic graph standalone and avoids sending full huge documents to a small local model.
Pending review edges are stored as Memory Inbox graph-update proposals until the user accepts them. Accepted and auto-accepted semantic edges become saved relationships in the Graph context map. Rejected edges stay in durable metadata so a user decision is not lost on rebuild.
The semantic candidate index is deterministic by default. It is built from project metadata, graph rules, imported paths, extracted mentions, and existing graph links. A vector store is not required for semantic relationships and is not part of the default data model. Vector candidates can be added later as a rebuildable optional source if users need similarity discovery for weakly structured or very large document sets.
The current implementation writes a versioned, dependency-free JSON project manifest:
text
generated/index.json
It contains compact projections of:
schema version, generation timestamp, and collection counts
sessions
documents
workstreams
proposals
This is the supported rebuildable index for normal project sizes. Search still operates over Markdown-backed records, so deleting the index never loses source data. SQLite/FTS5 can be added later as an optional acceleration layer for very large stores without changing the source-of-truth model.
Zharwing Memory keeps behavior in the daemon. The CLI exposes broad operator workflows, while MCP intentionally exposes only the eleven tools needed for an AI agent's daily memory loop. A daemon method appearing below does not automatically make it an MCP tool.
POST http://127.0.0.1:37841/rpc
Authorization: Bearer <auth-token>
Content-Type: application/json
The daemon uses token auth by default. The token comes from ZHARWING_MEMORY_AUTH_TOKEN when set; otherwise the daemon generates a random per-user token on first start and stores it in the OS user state directory (%APPDATA%\zharwing-memory\daemon-token on Windows, $XDG_STATE_HOME or ~/.local/state/zharwing-memory/daemon-token on POSIX). Delete the file to rotate the token. Placeholder tokens copied from example configuration are for local development only and must never be exposed beyond the local machine or committed to a repo.
Streamable HTTP MCP endpoint:
text
POST http://127.0.0.1:37841/mcp
Content-Type: application/json
The HTTP /mcp endpoint and the stdio MCP adapter stay disabled until ZHARWING_MEMORY_AGENT_SURFACE=enabled is set in the daemon/adapter environment.
For localhost-only personal use, set ZHARWING_MEMORY_AUTH_MODE=none to allow MCP clients to connect without a bearer token. The daemon refuses no-auth mode when bound to a non-loopback host.
The stdio MCP entrypoint is:
text
zharwing-memory mcp serve
Client config can be generated with zharwing-memory mcp install auto or zharwing-memory mcp install <client>. See MCP Setup for supported clients, auth modes, and transport choices.
memory.update_session_graph_visibility is an administrative UI operation with projectId, sessionId, and boolean includeInGraph parameters. New and legacy sessions default to false. This method is intentionally not part of the MCP tool list, so an agent cannot opt its own routine sessions into the graph.
memory.get_startup_state, memory.get_latest_session, memory.get_recent_sessions, and memory.list_project_sessions return compact session summaries. Summaries never contain the Markdown body or the checkpoints array. Startup returns at most three non-duplicated recent summaries and does not duplicate the active session as latestSession; when the active session is latest, activeSession is authoritative. Startup also returns a revision; pass that revision as knownRevision only for a justified refresh. An unchanged refresh returns only:
Use memory.get_session_detail with projectId, sessionId, and explicitly requested sections (body, checkpoints) for progressive detail. checkpointLimit defaults to 20 and is capped at 100. Checkpoints are returned newest first; pass the opaque nextCursor to continue.
For checkpoint and closeout state, omitted nextSteps or blockers preserve current state, an explicit empty array clears it, and a supplied non-empty array replaces it. Touched files remain checkpoint-local in history while the session keeps aggregate file metadata for search and graph consumers.
Workstreams group related sessions and documents for multi-day topics or epics. Repo roles/categories used by workstreams are free-form metadata.
Workstream creation and administration stay in the UI and CLI, but agents can still attach sessions to existing lanes: memory.get_startup_state returns the project's open (active or paused) workstreams, and memory.start_session, memory.save_checkpoint, and memory.close_session all accept a workstreamIds array. Checkpoint and close merge the ids into the session, so a session can be attached mid-work when the topic becomes clear, not only at start.
memory.import_doc currently routes to document creation in the daemon dispatch. memory.create_doc writes directly when project memory write policy allows direct agent writes. If review mode is set to review every memory update, UI, CLI, or authenticated daemon clients should use memory.propose_memory_update instead. memory.update_doc rewrites the existing Markdown document body/title in place and preserves its file path and existing metadata.
memory.prepare_import scans a folder and returns an import plan without writing files. memory.commit_import commits either a reviewed plan or a source folder/profile pair. Conflict strategy is skip, overwrite, or duplicate.
Search is project-scoped by default. memory.get_graph returns the derived project context graph. The graph is rebuilt from project/document metadata, explicitly opted-in session metadata, and project.graphRules; it is not the source of truth.
memory.update_graph_rules replaces the project's deterministic graph extraction rules. Use it for manual settings saves or explicitly approved changes. For AI-suggested changes, prefer memory.propose_graph_update so the proposal lands in Memory Inbox first.
Semantic graph methods are optional. They add LLM-assisted relationship analysis on top of the deterministic graph. preview builds the scoped document/candidate plan without calling a model. analyze supports dry-run, review, and auto modes. Review mode writes Memory Inbox proposals; accepted edges are stored under semantic-graph/edges.json and can be overlaid with memory.get_graph by passing semantic include options.
The inbox is optional. Default project policy allows routine agent memory writes directly through session and document APIs. Use inbox proposals when review mode is enabled or the update is risky, uncertain, or needs human judgment.
memory.propose_graph_update creates a graph-update proposal for reviewed AI suggestions. The proposedPatch should be a JSON array of graph rules or an object containing graphRules.
Delete methods move items to Trash first. Restore moves recoverable items back to their active location. Purge permanently deletes one trash item. Empty Trash permanently deletes selected trash item ids, or all trash items when no ids are provided.
The MCP adapter intentionally exposes only the daily AI-memory workflow over the daemon HTTP endpoint or stdio adapter. Daemon administration, project creation, deletion, imports, backups, graph settings, and Trash remain UI/CLI administrative operations.
Supported MCP tools:
memory.health
memory.get_startup_state
memory.get_latest_session
memory.get_recent_sessions
memory.get_session_detail
memory.start_session
memory.search
memory.preview_context_bundle
memory.get_context_bundle
memory.save_checkpoint
memory.close_session
memory.get_startup_state includes bounded compact summaries and the open workstreams so an agent can attach its session to an existing lane; memory.start_session, memory.save_checkpoint, and memory.close_session accept workstreamIds. Workstream creation remains an administrative operation.
Memory in the selected project is AI-visible by default. Normal session data, file paths, and search metadata are returned to the coding agent. Explicit visibility exclusions, never-send patterns, and secret detection remain in the search/context pipeline.
RPC requests require a bearer token unless ZHARWING_MEMORY_AUTH_MODE=none is used on a loopback-only daemon.
HTTP MCP requests follow the same daemon auth mode.
There is no built-in default token. When ZHARWING_MEMORY_AUTH_TOKEN is unset, the daemon generates a random per-user token and stores it with restrictive permissions in the OS user state directory.
Placeholder tokens from example files are for local development only; never reuse them on a reachable interface or commit a real token to a repo.
Agent-facing surfaces (HTTP /mcp and stdio MCP) additionally require ZHARWING_MEMORY_AGENT_SURFACE=enabled.
Remote access should remain disabled unless explicitly configured.
sequenceDiagram
participant Agent as External AI agent
participant MCP as MCP adapter
participant Daemon as Daemon
participant Registry as Project registry
participant Storage as Memory workspace
Agent->>MCP: memory.get_startup_state(workingDirectory)
MCP->>Daemon: RPC memory.get_startup_state
Daemon->>Storage: find .zharwing/memory.json
Daemon->>Registry: find project by repo path
alt project resolved
Daemon->>Storage: load bounded session metadata
Daemon-->>MCP: compact summaries, revision, recommended action
MCP-->>Agent: startup state under response budget
else unregistered repo
Daemon-->>MCP: offer_create_project
MCP-->>Agent: ask user to create or link through UI / CLI
end
stateDiagram-v2
[*] --> Created
Created --> Active
Active --> Active: save checkpoint
Active --> Closed: close session
Closed --> Active: explicit reopen
Closed --> Archived: archive
Active --> Archived: archive
Archived --> [*]
The normal non-AI runtime should work without a model provider. Daemon startup, CLI commands, MCP startup, sessions, docs, context preview, import, inbox, backup, trash, search, and the saved Graph context map do not require LM Studio, Ollama, llama.cpp, or a remote provider.
Current automated validation covers workspace TypeScript build-mode validation, a deterministic test spine for privacy gates, Markdown storage round-trips, context privacy integration, daemon lifecycle, graph overlays, semantic graph policy, fake-provider semantic graph analysis, desktop route/workflow contracts, bundle budgets, and a real browser app-shell smoke. A live-provider smoke runner is opt-in because it requires an explicitly configured endpoint. Broad desktop end-to-end coverage is not yet present.
The Vite production build uses native Rollup/esbuild optional packages. A checkout shared between Windows and WSL must install dependencies in the same operating system that will run the build; otherwise Vite can fail with a missing or wrong-platform native package.
Native Tauri/Rust validation depends on a local Rust toolchain. Windows Rust tests and a release build have passed; the release executable is written to apps/desktop/src-tauri/target/release/zharwing-memory-desktop.exe.
ZHARWING_MEMORY_ROOT stores private project memory, sessions, docs, imports, context bundles, Memory Inbox proposals, and backups. Do not commit this folder.
When ZHARWING_MEMORY_AUTH_TOKEN is unset, the daemon generates a random per-user token on first start and stores it in the OS user state directory (%APPDATA%\zharwing-memory\daemon-token on Windows, $XDG_STATE_HOME or ~/.local/state/zharwing-memory/daemon-token on POSIX). Delete the file to rotate the token. Never commit a real token or use a placeholder token outside local development.
Optional desktop-shell overrides use ZHARWING_MEMORY_DESKTOP_PROJECT_ROOT, ZHARWING_MEMORY_DESKTOP_DAEMON_COMMAND, and ZHARWING_MEMORY_DESKTOP_AUTOSTART_DAEMON. Canonical ZHARWING_MEMORY_* variables always win. The previous AIMEM_* names remain fallback-only for one compatibility window.
New configuration, generated MCP files, logs, schemas, skill metadata, and runtime metadata use the Zharwing Memory name. A small set of legacy identifiers is retained deliberately so existing installations do not lose data or become separate applications:
AIMEM_* environment variables are read only as deprecated fallbacks.
aimem remains a CLI alias during the transition.
.ai-memory.json remains a readable legacy pointer filename.
AI Memory Root, local.aimem.desktop, and existing aimem.* browser storage keys remain stable compatibility identifiers.
Do not use those legacy identifiers in new examples or generated configuration.
The browser UI is a full local interface for daily use. It renders the same React application as the Tauri window, but it does not manage the daemon process. Start the daemon first and keep it running:
text
corepack pnpm dev:daemon
Then start the UI in a second terminal:
text
corepack pnpm dev:web
Open http://localhost:5174/. The React/Vite dev server is pinned to that port so it does not collide with other local product runtimes that commonly use Vite's default 5173.
In token mode, the daemon and browser bundle must use the same local token:
Vite loads .env when the process starts. Restart dev:web after changing a VITE_ value. See Browser UI for complete setup and troubleshooting.
Desktop/web UI workflows currently include setup, project selection, project delete, repo links, import preview/commit, workstreams, sessions, docs, search, context preview, inbox, graph, backup management, and Trash restore/purge. The browser UI calls the daemon API, so the daemon must be running first in browser mode. The native Tauri desktop app reuses a healthy local daemon. In a source checkout it also starts the repository daemon automatically. A copied release executable needs either an already-running daemon or ZHARWING_MEMORY_DESKTOP_DAEMON_COMMAND set to a command that starts one; the daemon is not embedded in the desktop executable.
When opened as a native Tauri window, the Setup, Repositories, and Import screens use OS folder pickers for path fields. Browser dev mode leaves those Browse buttons disabled and keeps typed paths as the fallback, because ordinary browsers cannot expose arbitrary absolute folder paths to web apps.
Use corepack pnpm dev:web for the browser app after corepack pnpm dev:daemon. Use corepack pnpm dev:desktop for the native Tauri window. The Tauri dev command starts or reuses the Vite app on port 5174, and the desktop shell starts or reuses the daemon on 127.0.0.1:37841.
Native Tauri dev window:
text
corepack pnpm dev:desktop
Packaged desktop build:
text
corepack pnpm build:desktop
On Windows this produces apps/desktop/src-tauri/target/release/zharwing-memory-desktop.exe. The current repository config does not build an installer.
MCP:
text
corepack pnpm dev:mcp
Installed client setup:
text
zharwing-memory mcp install auto
zharwing-memory mcp doctor
Use HTTP MCP when the client can reach the daemon at http://127.0.0.1:37841/mcp. Use stdio with --transport stdio when a client needs to launch a local subprocess or when Windows/WSL localhost routing makes the daemon URL unreachable. See MCP Setup.
The daemon and browser UI Vite commands have been run during validation. The native Tauri command requires the local Rust/Tauri toolchain.
generates a per-user local auth token when ZHARWING_MEMORY_AUTH_TOKEN is unset, stored with restrictive permissions in the OS user state directory
binds to localhost by default
Production packaging should additionally:
allow ZHARWING_MEMORY_AUTH_MODE=none only for loopback-only personal setups
keep remote access disabled by default
require confirmation for project creation, repo linking, and destructive administrative operations
serve selected-project memory to AI by default without per-request approval; keep explicit visibility exclusions, never-send patterns, and secret checks
route canonical memory writes through review only when the project enables review mode or the update is risky or uncertain
log sensitive operations without storing raw secrets
Path-backed items are moved below the same trash item directory. JSON-backed items, such as linked repo entries, store their payload in the trash item directory. Trash items can be restored until permanently purged.
Current index behavior writes a versioned project manifest:
text
generated/index.json
The index includes its schema version, generation time, collection counts, and compact record projections. It is rebuildable from Markdown/frontmatter and JSON proposal files and is the supported default for normal project sizes.
Optional scaling work:
add SQLite registry/index database
add SQLite FTS5 keyword search
extend the existing rebuild-index command with a richer validation report
The UI supports configured LM Studio, Ollama, llama.cpp server, OpenAI, Anthropic, and custom OpenAI-compatible endpoints. It does not advertise an app-managed download/runtime path. Persisted legacy app-managed-llamacpp settings remain readable and show a migration message.
Start LM Studio or another local OpenAI-compatible provider when testing model-backed session TLDR generation, semantic graph relationship review, or provider connectivity. It is not needed for normal validation or Graph context map viewing.
Zharwing Memory has real OpenAI-compatible provider integration for model-backed semantic graph analysis. That is the path that builds AI-suggested document relationships from project docs, routes reviewable edges through Memory Inbox, and stores accepted relationships as semantic graph metadata.
Default validation still does not start or require an AI model. Typecheck, build, unit tests, daemon startup, CLI commands, MCP startup, context preview, and the saved Graph context map should work without LM Studio, Ollama, llama.cpp, or any remote provider.
Use an AI provider when manually exercising the semantic graph relationship builder or checking provider connectivity. The provider is a real runtime dependency for those model-backed workflows, just not a dependency of the default automated test suite.
Start LM Studio only when you want to test model-backed behavior:
Assistant screen Test provider.
automatic or manual session TLDR generation.
memory.check_semantic_graph_provider.
Semantic graph dry-run, review, or auto analysis.
Do not start LM Studio for:
corepack pnpm typecheck
corepack pnpm test
corepack pnpm build
daemon health checks
project/doc/context workflows
Graph context map
semantic graph preview
If you use LM Studio, load a model that can follow JSON instructions, start its local OpenAI-compatible server, and copy the base URL shown by LM Studio. The examples below use placeholders; replace them with the endpoint and model name shown by your provider.
Local endpoints are preferred. Remote semantic graph providers are disabled by default and should be enabled only after the user explicitly accepts sending eligible project documents to that provider.
The build step runs Vite and uses native Rollup/esbuild optional packages. If a checkout is shared between Windows and WSL, install dependencies in the same operating system that will run the command. A missing or wrong-platform native optional package means the dependencies need to be reinstalled for that environment.
For a fast local loop after dependencies are already installed:
bash
pnpm typecheck
pnpm test
After corepack pnpm build, run the real browser smoke on a machine with Edge or Chrome:
text
corepack pnpm test:desktop-browser
The smoke launches the built Vite preview, opens the Projects route in a headless browser, and verifies that the React shell and Zharwing branding render. Set ZHARWING_MEMORY_BROWSER_PATH when the browser is not installed in a standard location.
The build also enforces a 450 KB raw startup-entry budget and a 1.2 MB raw maximum lazy-chunk budget. Override these only for deliberate investigation with ZHARWING_MEMORY_ENTRY_BUDGET_BYTES or ZHARWING_MEMORY_CHUNK_BUDGET_BYTES; CI uses the defaults.
The response includes the expected endpoint and model.
Latency is reasonable for the selected local model.
The repository also includes an opt-in automated live-provider smoke path. It is intentionally excluded from default CI because it requires a configured provider process and, for remote providers, credentials:
Set ZHARWING_MEMORY_LIVE_PROVIDER_API_KEY only in the local process environment when required. The smoke script never prints it.
If the provider rejects OpenAI response_format, add --no-json-mode to the CLI command or call the authenticated daemon RPC method with jsonMode: false.
Session TLDR generation is separate from semantic graph relationships. It keeps sessions searchable while graph visibility remains controlled by the session's Include in graph flag.
From the UI:
Configure a local assistant provider in Settings -> Assistant.
Start or select a session.
Close the session from Current Work.
Open Work -> Sessions.
Confirm the selected session has a TLDR source, generated timestamp, topics, and summary text.
Confirm Include in graph is off by default, then enable it and verify the session appears in Graph. Disable it again and verify its session-derived node and relationships disappear without removing it from Session History or search.
The UI path uses the provider saved in project settings. The CLI path also accepts advanced overrides such as --endpoint, --model, and --no-json-mode when testing provider compatibility directly.
Pass criteria:
The session Markdown frontmatter includes summary_generated_at.
Search finds the session by generated summary text or generated topics.
The main Graph excludes a session while Include in graph is off and shows it, together with its derived relationships, while the flag is on.
If no safe local provider is configured, the session still gets a deterministic TLDR instead of failing closeout.
For CLI/RPC smoke tests, first run semantic graph preview. Preview builds the scoped document and candidate plan without calling a model.
Then run a small model-backed dry run. Dry run calls the provider and writes run metadata/caches, but it does not create accepted durable edges or Inbox proposals.
When validating an AI client integration, start or reuse the daemon, install the target client config, and check setup:
text
zharwing-memory mcp install auto
zharwing-memory mcp doctor
Use codex, claude-code, or claude-desktop instead of auto to target one client. Use --transport stdio when the client needs a process-launched adapter. Manual templates remain available in templates/mcp/, and the full setup guide is MCP Setup.
Run semantic graph provider checks and analysis through the UI or CLI. Those administrative operations are intentionally outside the focused MCP surface; use preview and dry-run modes before review or auto mode.
ECONNREFUSED from Zharwing Memory: start corepack pnpm dev:daemon.
401 Unauthorized: the bearer token does not match .env, or the client did not inherit ZHARWING_MEMORY_AUTH_TOKEN.
Provider timeout: lower --max-docs, --max-candidates, and --per-doc, or increase --timeout-ms.
Invalid JSON: choose a model with stronger instruction following or lower the scope size. If the provider rejects OpenAI JSON mode, add --no-json-mode or pass jsonMode: false through the administrative RPC.
Remote endpoint rejected: local endpoints are allowed by default; remote endpoints require remoteProvidersEnabled.
Vite or build reports a missing or wrong-platform Rollup/esbuild optional package: reinstall dependencies in the operating system that is running the command.
Goal: protect the two places where a silent regression actually hurts — the privacy gate (data leaks into AI context) and Markdown storage round-trips (memory loss or corruption) — then grow outward to the daemon API surface.
semantic graph analysis through a fake OpenAI-compatible provider
corepack pnpm test compiles the workspace from a clean TypeScript build (tsc -b --clean && tsc -b --force) and then runs scripts/run-tests.mjs, which uses source files as the discovery authority: it finds every src/**/*.test.ts/.tsx, maps each to its expected dist output, and fails (non-zero) when
zero source tests are discovered,
an expected compiled test is missing,
a compiled test has no source counterpart (stale output), or
a noEmit workspace (the desktop) contains tests that the compiled Node runner cannot execute.
A fresh clone therefore cannot false-green with zero tests. The runner's own discovery/guard logic is covered by scripts/lib/*.test.mjs self-tests that run against temporary fixture repositories. Coverage is useful but still narrow compared with this plan. Import, backup, trash, HTTP RPC, broader search and graph cases, desktop pure logic, and desktop end-to-end workflows still need the broader test phases below.
AI-provider integration exists for model-backed semantic graph relationship building. The default automated suite covers that path with a deterministic fake OpenAI-compatible provider. Tests against real LM Studio, Ollama, llama.cpp, or remote provider processes remain manual smoke tests because they depend on a local model server, model quality, response latency, and JSON-following behavior. See Testing With AI Providers.
No new dependencies. Tests use node:test and node:assert/strict. The existing infrastructure already supports this end to end:
Write foo.test.ts next to foo.ts in each package's src/.
corepack pnpm test cleans, compiles, discovers every source test, and runs the compiled output with node --test. There is no separate build prerequisite to remember.
Generated .js/.d.ts/.map files must never be committed under src; corepack pnpm check:source-artifacts enforces this. This works identically on Windows and WSL because plain Node needs no platform-specific binaries, unlike Vite/Rollup/esbuild.
Test through public APIs. Storage tests call startSession, saveCheckpoint, commitImportPlan etc. against a real temp directory — no mocking of node:fs. Fixtures are built by the same creation APIs the app uses, so they cannot drift from reality.
Deterministic and isolated. Every filesystem test creates its own root via fs.mkdtemp(path.join(os.tmpdir(), "zharwing-daemon-test-")) and removes it in t.after(). No network, no shared state, no reliance on wall-clock values beyond "is a valid ISO timestamp".
Behavior, not implementation. Assert on parsed results and file contents, not on internal call order. No snapshot files.
makeTestProject(root, overrides?) — creates a real project via prepareProjectCreation + createProjectFromPreview. Exported from the package but tree-shaken from production paths (it is only imported by test files).
Decide and document: test files ship in dist/ (harmless for a private app; revisit if the packages are ever published).
Phase 1 — @zharwing/memory-privacy (highest risk, pure functions)#
secrets.test.ts
scanSecrets detects every built-in pattern class (API keys, tokens, private key blocks, connection strings, .env-style assignments) — one positive and one near-miss negative per pattern.
Severity classification: high-risk findings are marked high.
redactSecrets: replaces the secret, preserves surrounding text, returns one redaction record per finding, is a no-op on clean input, and is idempotent (redacting twice changes nothing).
purgeTrashItem removes payload + metadata; purging a missing id throws.
importer.test.ts
Fixture folder (built inline in the test) with nested Markdown docs and session-like files: prepareImportPlan counts match, plan is read-only (source untouched, nothing written to the project).
commitImportPlan writes docs/sessions with import provenance fields.
builder.test.ts — the privacy integration test that matters most
A project containing: an ai-pinned doc, an ai-eligible doc, a never-send doc, and a doc whose body contains a planted fake secret.
Assert: pinned + eligible content appears in bundle.markdown; the never-send doc appears in excludedItems with reason never-send and its content appears nowhere in the rendered markdown; the secret is redacted or the item blocked; safetyStatus reflects the worst finding; tokenEstimate > 0; every included item has an inclusion reason.
search/index.test.ts
Ranking: exact term beats single occurrence; multi-entity corpus returns sessions/docs/workstreams/proposals typed correctly.
snippet centers on the first match; tokenize drops 1-char noise; empty/whitespace query returns [].
graph/index.test.ts
buildProjectGraph from a fixture project: expected node types (project/repo/workstream/session/doc), belongs-to membership edges, and rule-derived context edges when graphRules are set.
Graph rules: match globs map imported paths to topic/service/ package nodes; invalid rules are ignored (ties into apps/daemon/src/services/graph-rules.ts normalization, tested in Phase 5).
Phase 5 — daemon (integration over the refactored services)#
The extracted apps/desktop/src/screens/graph/graph-display.ts and utils/*.ts are pure and worth testing, but the desktop app is bundled by Vite and does not emit dist/ JS, so the node:test runner cannot see them today. Two options, in preference order:
If graph display logic keeps growing, promote it into a small package (packages/graph-display) — it has no React dependency — and test it like Phase 4.
Otherwise adopt Vitest for the desktop workspace only (new dev dependency; run it in an environment whose native Vite/Rollup/esbuild dependencies were installed for that same operating system).
Component/UI tests (Testing Library) are explicitly out of scope until the pure-logic layers above are covered.
The per-OS pnpm install is what the current shared checkout cannot do, so CI also becomes the reliable place where the Vite production build is proven on Linux.
Please do not open public issues for security vulnerabilities.
Report them privately via GitHub Security Advisories (Report a vulnerability) or by email to sviatoslavbarbutsa@gmail.com. You should receive a response within a few days. Please include reproduction steps and the affected component (daemon, CLI, desktop, MCP server).
The daemon binds to 127.0.0.1 only and requires a bearer token (ZHARWING_MEMORY_AUTH_TOKEN); it is not designed to be exposed to a network. Reports that assume a remotely reachable daemon should state why the exposure is realistic.
Markdown files in the store are the source of truth. Anything that lets an agent or MCP client read or write outside the configured store root, bypass the privacy/redaction gates, or exfiltrate store content through tool responses is in scope and considered high severity.
Node 22.21.0 (pinned in .node-version) or Node 24 LTS. The engine range is >=22.21.0 <23 || >=24.0.0 <25; CI stays pinned to Node 22 for reproducibility.
pnpm 9.0.0 via corepack (packageManager field). Run commands as corepack pnpm <command> so the pinned version is used.
corepack pnpm install # install dependencies
corepack pnpm check:source-artifacts # fail if generated files sit under src/
corepack pnpm typecheck # tsc -b across the workspace
corepack pnpm test # clean-compile + run all tests
corepack pnpm test:coverage # same, with Node coverage thresholds
corepack pnpm test:desktop # desktop routing and workflow contracts
corepack pnpm test:desktop-browser # real headless Chrome/Edge route smoke after build
corepack pnpm test:live-provider # opt-in check against a configured provider
corepack pnpm build # TypeScript build + desktop web build
corepack pnpm check:bundle-size # enforce startup and lazy-chunk size budgets
corepack pnpm build:desktop # packaged native desktop executable
corepack pnpm test owns test compilation: it cleans TypeScript output, force-rebuilds, then runs scripts/run-tests.mjs. The runner discovers src/**/*.test.ts(x) as the source of truth and fails when zero tests are found, when an expected compiled test is missing, or when stale compiled tests have no source counterpart. Do not bypass it with ad-hoc node --test invocations for CI-relevant validation.
src directories contain authored TypeScript/TSX and reviewed assets only.
Compiler output (.js, .d.ts, .map and variants) is emitted only to ignored dist directories and is never committed or hand-edited.
A .js import specifier inside TypeScript source does not imply a committed .js file; it resolves at build time.
Never invoke tsc with positional file arguments such as tsc packages/core/src/index.ts — that bypasses project output settings and writes JavaScript next to the source. Use corepack pnpm typecheck, corepack pnpm build, or corepack pnpm --filter <pkg> build.
Run corepack pnpm check:source-artifacts before committing. CI runs it before and after builds.
A genuinely handwritten declaration file requires an exact-path allowlist entry in scripts/lib/artifact-scan.mjs with a rationale and owner; never allowlist an extension or directory wholesale.
A checkout shared between Windows and WSL must install dependencies in the same OS that runs Vite/Rollup/esbuild — optional native packages are platform-specific. If the repo lives on the Windows filesystem, run installs, typecheck, tests, and builds from Windows. Plain node:test suites work in either OS, but do not mix node_modules between them.
Backend tests use node:test + node:assert/strict, live next to the code as src/**/*.test.ts, and run compiled from dist.
The desktop workspace is noEmit. Pure routing and workflow contracts run through test:desktop; the built app shell runs through a real Chromium browser with test:desktop-browser.
Filesystem tests must create their own temp roots under os.tmpdir() and clean up after themselves.