# Background Intelligence (/docs/advanced-features) Background Intelligence is how Mem becomes more than a storage layer. You save memories, threads, and documents. Then the system keeps working on them: linking related ideas, surfacing contradictions, synthesizing clusters, and writing a daily briefing your connected tools can read. You save a decision about PostgreSQL in January. In July, you record that you're migrating to CockroachDB. Six months apart, different contexts. Nowledge Mem links them, tracks the evolution, and the next time you search for either, both appear with the full trail of how your thinking changed. This runs in the background. You open the app and the connections are there. Do not try to validate every background feature at once. The first useful proof is simpler: save enough real knowledge that Mem can show you one relevant briefing item, one non-obvious connection, or one contradiction you had not surfaced yourself.
Knowledge Graph Background Intelligence requires a configured Remote LLM and the appropriate license for your build. Enable it in **Settings > Knowledge Processing**. ## The First Useful Sign [#the-first-useful-sign] You know Background Intelligence is becoming useful when Mem shows you something you probably would not have found on your own: * a contradiction between old and new thinking * a cluster of related work across time * a morning briefing that is actually relevant ## Knowledge Graph [#knowledge-graph] Every memory becomes a node in a graph. The system extracts entities (people, technologies, concepts, projects) and maps how they relate to each other and to your existing knowledge. The result: search "distributed systems" and find your memory about "Node.js microservices." The words don't match. The meaning does. With Background Intelligence enabled, extraction runs automatically for new memories. You can also trigger it manually for older ones. ### What Gets Extracted [#what-gets-extracted] When a memory is processed, the LLM identifies: * **Entities**: people, technologies, concepts, organizations, projects * **Relationships**: how those entities connect * **Links to existing knowledge**: connections to memories already in the graph Trigger extraction for any memory by clicking **Knowledge Graph** on its card. Distill with Knowledge Graph ### Knowledge Evolution [#knowledge-evolution] When you save something new about a topic you've written about before, the system detects the relationship and creates a version link: | Link type | Meaning | Example | | -------------- | ---------------------- | ------------------------------------------------------------------- | | **Replaces** | You changed your mind | "Use CockroachDB" replaces "Use PostgreSQL" | | **Enriches** | You added depth | "React 19 adds a compiler" enriches "React 18 concurrent rendering" | | **Confirms** | Independent agreement | Two separate reviews recommend the same library | | **Challenges** | Contradiction detected | Your March assessment disagrees with your October conclusion | You can trace how your understanding of any topic changed over time. ### Community Detection [#community-detection] Graph algorithms find natural clusters in your knowledge: groups of tightly connected memories that form coherent topics. Your graph might reveal clusters for "React Patterns," "API Design," and "Database Optimization." A map of your expertise you never drew by hand. In **Graph View**, click **Compute** to run community detection. Graph Algorithm Compute ## Visual Exploration [#visual-exploration] Your knowledge as an interactive network. Click a memory to see its connections. Zoom into clusters. Follow links between topics you never thought to compare.
The timeline slider filters by date range. Watch how your knowledge in a domain grew over weeks or months. ## What the System Discovers [#what-the-system-discovers] The graph is the foundation. On top of it, Background Intelligence actively analyzes your knowledge and surfaces findings in the Timeline. ### Insights [#insights] Insights are connections you wouldn't have found on your own. * **Cross-domain links.** In March you noted that JWT refresh tokens were causing race conditions in the payment service. In September you chose the same token rotation pattern for a new auth service. The system catches it: same failure pattern, different project. * **Temporal patterns.** "You've revisited this database migration decision 3 times in 2 months." Maybe it's time to commit. * **Forgotten context.** "Your March assessment contradicts the approach you chose in October." The system remembers what you wrote, even when you don't. Every insight cites its sources so you can trace the reasoning. One insight that changes how you think beats ten that state the obvious. Strict quality gates keep the noise out. ### Crystals [#crystals] Five memories about React patterns saved over three months. Scattered across your timeline. Hard to piece together. A crystal synthesizes them into one reference article. Sources are cited. When you save new related information, the crystal updates. Crystals appear when the system has enough material to say something useful. You don't request them. ### Flags [#flags] Sometimes the system finds problems, not connections: | Flag | What it means | Example | | ---------------------- | -------------------------------- | ----------------------------------------------------------------- | | **Contradiction** | Two memories disagree | "Use JWT tokens" vs. "Session cookies are more secure" | | **Stale** | Newer knowledge supersedes older | A deployment guide from 6 months ago, overwritten by recent notes | | **Needs verification** | Strong claim, no corroboration | A single memory making an assertion with no supporting evidence | Each flag appears in the Timeline. You can dismiss it, acknowledge it, or link it to a resolution. ### Working Memory [#working-memory] Each morning, Mem writes a Working Memory briefing for the current space: * **Active topics** based on recent activity * **Unresolved flags** needing attention * **Recent changes** in your knowledge base * **Priority items** by frequency and recency Connected AI tools can load this briefing through their own connector path at session start. MCP is one path, but native connectors and other packaged setups can do the same. The **Default** space keeps the familiar compatibility file at `~/ai-now/memory.md`. If you turn on [Spaces](/docs/spaces), other spaces get their own Working Memory briefings behind the same Mem APIs and connectors. You can still edit Working Memory directly. Your changes are respected. Connected AI tools can load Working Memory through MCP, native connectors, or other packaged paths. When a tool knows the active space, it reads the right briefing automatically. ## Configuration [#configuration] Control background processing in **Settings > Knowledge Processing**: Memory Processing Settings | Setting | Default | What it controls | | --------------------------- | ----------------- | ----------------------------------------------------- | | **Background Intelligence** | Off | Master toggle for all background processing | | **Daily Briefing** | On (when enabled) | Morning Working Memory generation | | **Briefing Hour** | 8 | What hour the daily briefing runs (local time) | | **Auto Extraction** | On (when enabled) | Automatic knowledge graph enrichment for new memories | On Linux servers, configure via CLI: ```bash nmem config settings set backgroundIntelligence true nmem config settings set autoDailyBriefing true nmem config settings set briefingHour 8 ``` ## Next Steps [#next-steps] * **[Memories](/docs/memories)**: Create, search, organize, and connect your knowledge * **[Threads](/docs/threads)**: Capture, browse, and distill AI conversations * **[Getting Started](/docs/getting-started)**: The Timeline, document import, and all ways to add knowledge * **[Connectors](/docs/integrations)**: Connect your AI tools through native connectors, reusable packages, MCP, and browser capture * **[Troubleshooting](/docs/troubleshooting)**: Common issues and solutions # Context (/docs/ai-context) Context is where you check what a connected AI will see before it starts: who you are, which AI profile it is using, which memories it can use, standing rules, and Working Memory. Think of it as the start card Mem hands to your AI tools. ## How It Fits With The Rest Of Mem [#how-it-fits-with-the-rest-of-mem] Memories, Threads, Library, Skills, Spaces, and AI Now each do a different job. Context does not replace them. It shows how they come together for a specific AI run. | View | What it is for | | ----------------------------------- | ------------------------------------------------------------------------------------------------------ | | **Memories** | Durable facts, preferences, decisions, plans, procedures, learnings, events, and context worth keeping | | **Threads** | Saved conversations and exact discussion history | | **Library** | Files, documents, sources, and generated artifacts | | **[Skills](/docs/concepts/skills)** | Repeatable ways your AI should perform a task | | **Spaces** | The memory lane a project, tool, or long-running agent should use | | **AI Now** | The place where you work directly with Mem's built-in AI | | **Context** | The preview and editor for what connected AI tools receive before they start | ## The First Useful Move [#the-first-useful-move] Open **Context → Preview**. You should see a sentence like: > Default AI receives your profile, Working Memory, and no rules. It can use memories only from Default. If that sentence matches what you expect, you do not need to configure anything else. ## What You Can Change Here [#what-you-can-change-here] * **You**: your name, aliases, language, and personal context * **AI Profiles**: named long-running agents, each with an optional default space and profile-specific rules * **Rules**: standing behavior rules that apply to everyone, one AI profile, or one space * **Spaces**: memory scope, shared context, and space-level rules Every change should be visible back in **Preview**. AI identities in Context Standing rules in Context ## When To Create An AI Profile [#when-to-create-an-ai-profile] Do it when an AI has a stable role over time: * a reviewer that always checks code quality * an onboarding assistant that explains slowly * a research agent that should stay in one project space Do not create a profile for every temporary chat. The default AI profile is enough for normal use. ## How Connected Tools Use It [#how-connected-tools-use-it] Supported connectors read the Context Bundle at session start when they can. It includes Context plus the current Working Memory. Older or simpler integrations may read only Working Memory as a lightweight fallback. For multi-agent tools, the profile is selected only when the tool passes an explicit Mem agent ID or stable host agent ID. The tool name itself, such as `codex` or `claude-code`, is only provenance. ## What Not To Worry About Yet [#what-not-to-worry-about-yet] * Context is not a new memory type. * It is not indexed or embedded. * Changing it does not require search reindexing. * You do not need to understand Context Bundle, MCP, or KFS paths to use the page. ## Next Steps [#next-steps] * [Your Profile](/docs/profile) if the AI does not know enough about you yet * [AI Profiles](/docs/concepts/ai-profiles) if a long-running agent needs its own identity * [Rules](/docs/concepts/rules) if you want behavior that applies before search or Skills * [Spaces](/docs/spaces) if two projects or agents need different memory lanes * [Connectors](/docs/integrations) if you want another AI tool to use this context # AI Now (/docs/ai-now) AI Now is the place where you work directly with your saved knowledge. It runs with your Mem server, so the desktop app, web app, and mobile clients can see the same AI Now sessions when they connect to that server. Instead of starting from a blank prompt every time, AI Now starts from what you already know. That makes it useful for research, analysis, presentations, and longer multi-step tasks that should build on your own history rather than generic model output.
AI Now requires a configured **Remote LLM**. Go to **Settings** → **Remote LLM** to set up, refer to [Remote LLMs](/docs/usage#remote-llms) for details. If you're connected to another Nowledge Mem via [Access Anywhere](/docs/remote-access), AI Now uses that server's LLM configuration. You do not need to configure a separate provider on each client. ## The First Useful Task [#the-first-useful-task] If you are opening AI Now for the first time, start with something grounded in your own knowledge: > What architecture decisions have I made about caching? That is a better first task than a generic prompt because it lets you see the product model immediately: * AI Now reads from your saved knowledge * it can pull in files or enabled plugins when relevant * it can turn the result back into updated knowledge if needed You know AI Now is set up correctly when one grounded question about your own work gets a useful answer without you re-explaining everything from scratch. ## What AI Now Can Do [#what-ai-now-can-do] | Category | What it does | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | **Memory Search** | Finds relevant memories with semantic understanding | | **[Library Search](/docs/library)** | Searches, reads, and analyzes documents you imported into the Library: PDFs, spreadsheets, Word files, slides, code | | **Deep Research** | Multi-source research combining your memories and web search | | **File Analysis** | Analyzes Excel, CSV, Word, PDF files you provide | | **Data Visualization** | Generates charts from your data | | **Presentations** | Creates slides with live preview and PowerPoint export | | **Travel Planning** | Creates interactive day-by-day itineraries | | **Connectors** | Connects to Notion, Obsidian, Apple Notes, and custom MCP plugins | ## Getting Started [#getting-started]
### Configure Remote LLM [#configure-remote-llm-step] Go to **Settings** → **Remote LLM** and add your API key.
### Open AI Now [#open-ai-now-step] Click the **AI Now** tab in the sidebar, or press Cmd/Ctrl + 5.
### Start a Grounded Task [#start-a-grounded-task-step] Start with a task that matches the context you have already given Mem: > What architecture decisions have I made about caching? When relevant, it pulls from your memories, searches the web, and uses any connected notes or enabled plugins you have configured. You can also drop files or folders for analysis, request reports based on your recent work, or run a deep study on any topic. As it works, AI Now can also create or update memories when that is useful. If you use [Spaces](/docs/spaces), AI Now follows the space currently selected in the app. That lets one AI Now session stay focused on a project or agent context without changing how the rest of Mem works.
## Mention memories in your chat [#mention-memories-in-your-chat] Use @ to search and reference specific memories in your conversation. ## Deep Research [#deep-research] For comprehensive research, AI Now runs parallel sub-tasks across multiple sources and synthesizes the results. Deep Research Click the Research toggle in the AI Now chat interface. ### How It Works [#how-it-works] Ask a research question: > Research the current state of quantum error correction AI Now will: 1. Search your memories for existing knowledge on the topic 2. Search the web from multiple angles 3. Synthesize findings into a single answer 4. Cite sources with reliability indicators ## Optional Skills [#optional-skills] Skills are specialized capabilities you enable for specific tasks. | Skill | What it enables | | ------------------------ | ------------------------------------------------------------------- | | **Documents** | Excel/CSV analysis, chart generation, file operations | | **Presentation Creator** | Slide generation with live preview and export | | **Travel Planner** | Interactive itinerary creation | | **Browse Now** | Real-browser automation for authenticated and interactive web tasks | Enable skills in **AI Now** → **Plugins** → **Skills**. ### File Analysis [#file-analysis] Attach files or folders to your conversation for analysis. When you send the message, AI Now copies those attachments into the current task workspace under `inputs/`. The agent reads that workspace copy and writes new charts, scripts, reports, or slides back into the same task folder. If you are connected to your Mem server through Access Anywhere, the App or Web client securely uploads the selected files into that task before AI Now starts. The server works from its own copy, so the original path does not need to exist on the server. If file attachment is unavailable for a hosted workspace, add the file to your Library and reference it from there. Toggle the Documents SKILL in AI Now Plugins to enable. #### Supported Files [#supported-files] | Type | Extensions | What AI Now Does | | ---------------- | ------------------- | -------------------------------------------------- | | **Spreadsheets** | .xlsx, .xls, .csv | Analyzes data, finds patterns, generates charts | | **Documents** | .docx, .doc, .pdf | Summarizes, extracts key points, answers questions | | **Code** | .py, .js, .ts, etc. | Reviews, explains, suggests improvements | #### Example [#example] 1. Attach `sales_q4.xlsx` 2. Ask: "What are the top 3 trends in this data?" 3. AI Now analyzes and generates visualizations Whole folders work too. Data Analysis ### Presentations [#presentations] Toggle the Presentation SKILL in AI Now Plugins to enable. > Create a presentation based on our above study and research, include some charts or diagrams to support the insights AI Now generates slides with structure, charts, and insights from your conversation. Presentation Creation Refine with follow-up requests ("Make the third slide more visual", "Add a slide about customer segments"), or click Edit to edit directly. Export as PowerPoint with the PPTX button. ### Travel Planning [#travel-planning] Toggle the Travel Planner SKILL in AI Now Plugins to enable. > Plan a 5-day trip to Tokyo focusing on food and culture AI Now generates an interactive day-by-day itinerary using your recent memories and web research as context. Travel Planning ### Browse Now [#browse-now] Toggle the Browse Now skill in **AI Now** → **Plugins** → **Skills** to let AI Now use your real browser for authenticated or dynamic pages. Turn this on when a task needs your actual browser session, not a generic fetch. Typical cases: * logged-in websites * clicking, typing, scrolling, or multi-step flows * screenshots or rendered-page extraction * dynamic pages where ordinary fetches miss the real UI state This capability is local-only. The browser bridge runs on the same machine as AI Now and is not exposed through Access Anywhere. Read the full [Browse Now guide](/docs/browse-now) for setup, limits, and CLI examples. ## Plugins [#plugins] Extend AI Now with connections to your other apps. ### Custom MCP Servers [#custom-mcp-servers] Use **AI Now** → **Plugins** → **Add custom MCP** when a tool already exposes an HTTP MCP endpoint. Paste the server URL, add any required headers, enable the plugin, then ask AI Now to use that tool. For local providers such as Lemonade, use the provider page for chat and add the provider's MCP endpoint separately if you also want AI Now to call its tools. STDIO MCP servers are not yet available in the built-in Rust runtime. ### Built-in Plugins [#built-in-plugins] #### Obsidian [#obsidian] 1. Go to **AI Now** → **Plugins** 2. Enable **Obsidian** 3. Set your vault path AI Now can now search and read your Obsidian notes alongside your memories. #### Notion [#notion] 1. Go to **AI Now** → **Plugins** 2. Enable **Notion** 3. Click **Connect** and authorize in the browser AI Now can search your Notion pages and databases. #### Apple Notes (macOS) [#apple-notes-macos] 1. Go to **AI Now** → **Plugins** 2. Enable **Apple Notes** 3. Grant permission when prompted AI Now can search and read your Apple Notes. No vault path or sync setup needed: it reads directly from the system database. Read-only. ### Custom MCP Plugins [#custom-mcp-plugins] AI Now supports Model Context Protocol for custom integrations.
### Open Custom Plugins [#open-custom-plugins-step] Go to **AI Now** → **Plugins** → **Custom Plugins**
### Add MCP Server [#add-mcp-server-step] Click **Add MCP Server**
### Configure the server [#configure-the-server-step] Configure the server (stdio command or HTTP endpoint)
### Test the connection [#test-the-connection-step] Click **Test Connection** to verify
### Enable the plugin [#enable-the-plugin-step] Enable the plugin MCP plugins with OAuth (GitHub, Slack, etc.) are detected automatically and prompt for authorization.
## Session Management [#session-management] Conversations are saved automatically. Click a previous session to resume, or create new sessions for parallel workstreams. Each session maintains its own history. ## Auto-Approve Mode [#auto-approve-mode] Enable Auto to skip confirmation prompts for file operations and other actions. Auto-Approve grants AI Now permission to act without asking. Only enable for trusted workflows. ## Using AI Now from Another Device [#using-ai-now-from-another-device] If your main Nowledge Mem runs on an always-on machine (a Mac Mini, a server, your office desktop), you can use AI Now from any other device that connects via [Access Anywhere](/docs/remote-access). This is not a separate second knowledge base. You are using the same Mem from another client. If you want the broader model, read [Sync Across Devices](/docs/sync). How it works: * Connect from the desktop app, the web app at `/app`, or the mobile app through **Access Anywhere** * AI Now runs on the Mem server you connected to, using that server's LLM configuration * Your session list, message history, and pasted images stay with the server, so you can switch clients and continue the same work * Your memories, threads, and Library are read from the same knowledge base through the secure connection AI Now is available from connected clients because the agent runs on the Mem server. Keep that server running while you work from another device. Plugins that read local apps or files, such as Obsidian, Apple Notes, and Browse Now, run on the machine hosting the Mem server. If you connect from a phone or another laptop, those plugins still see the server machine's apps and files. ## Tips [#tips] * **Be specific**: "What did we decide about the database migration last month?" beats "database stuff" * **Attach context**: drop files or mention notes with `@` for better results * **Use sessions**: separate sessions for different projects or topics ## Next Steps [#next-steps] * **[Access Anywhere](/docs/remote-access)**: Use Mem from any device, the foundation for multi-device workflows * **[Sync Across Devices](/docs/sync)**: Understand the single-Mem, multi-client sync model * **[Remote LLM Setup](/docs/usage#remote-llms)**: Configure your AI provider * **[Connectors](/docs/integrations)**: Connect your AI tools and capture paths * **[Background Intelligence](/docs/advanced-features)**: How your knowledge grows on its own # Browse Now (/docs/browse-now)
Browse Now lets Mem use a connected local Chromium browser. When a page needs your login session, live JavaScript, clicks, forms, or a screenshot, ordinary web fetches are not enough. Browse Now gives AI Now and supported agents a safe local path into your real Chrome, Edge, Arc, or Chromium browser, with the context you already have there. The Nowledge Mem Exchange extension also supports Firefox for capturing and saving web AI chats. That is a different job. Firefox can use Exchange for capture, Manual Distill, and Thread Backup, but Browse Now browser control uses the Chrome DevTools Protocol and currently requires a Chromium browser. This is the browser side of Mem. It helps AI Now browse, helps Feed and Timeline agents inspect URLs, and helps the Library learn pages that need a rendered browser instead of a plain download. Browse Now only controls a browser connected to the same machine as the Mem app or server. Access Anywhere does not expose your browser bridge, and a remote client cannot make the server control the browser on your laptop or phone. ## The First Useful Task [#the-first-useful-task] If you use AI Now, start with one page that only works in your browser: 1. Open **AI Now**. 2. Go to **Plugins → Skills** and enable **Browse Now**. 3. Ask a task that needs the live page: > Open my logged-in project dashboard and summarize what changed this week. You know it is working when the browser opens locally, the agent reads the rendered page, and the answer reflects what is actually visible in that browser session. If the page is public and static, Mem may use normal web search or URL fetching instead. That is expected. Browse Now is for the cases where a real browser changes the result. ## Where You Will See It [#where-you-will-see-it] | Place | How Browse Now helps | | ------------------------- | ------------------------------------------------------------------------------------------- | | **AI Now** | Lets the agent browse logged-in or dynamic pages during a task. | | **Feed / Timeline agent** | Gives background agents a way to inspect a URL when page rendering matters. | | **Library URL learning** | Helps Mem learn pages that require a browser session instead of a plain file download. | | **External agents** | Provides a CLI and reusable skill so supported agents can operate the browser deliberately. | Browse Now is not a replacement for memory search. It is the capability Mem uses when the task needs the live web page in front of you. ## Requirements [#requirements] You need all of these: * the Nowledge Mem desktop app installed * the Nowledge Mem Exchange extension installed in Chrome, Edge, Arc, or another supported Chromium browser * at least one connected browser with the extension active * for AI Now usage, the **Browse Now** skill enabled in **AI Now → Plugins → Skills** Firefox is not a Browse Now control browser yet. Use Firefox for Exchange capture; use Chrome, Edge, Arc, or another Chromium browser for Browse Now automation. If you connect to Mem through Access Anywhere, Browse Now still runs only on the machine hosting the Mem server and its connected browser extension. It does not control the browser on the remote client device. For normal AI Now, Feed, Timeline, and Library usage, you do not need to run the CLI manually. ## The CLI [#the-cli] The desktop app also bundles a command-line tool named `browse-now`. Agents use this CLI under the hood, and power users can run it directly. If the app is installed, the CLI is usually auto-installed for you. Check it with: ```bash browse-now status browse-now --help ``` The core loop is: 1. open a page 2. inspect the interactive elements 3. click or fill by reference 4. verify where you landed 5. inspect again after the page changes Refs such as `@e5` come from `snapshot -i`. They are usually more reliable than guessing a selector or coordinate. ```bash browse-now open https://example.com browse-now snapshot -i browse-now click @e5 browse-now wait 2 browse-now get url browse-now snapshot -i ``` If the page has weak accessibility data, the CLI also supports text search, text clicks, screenshots, scrolling, key presses, and page-text extraction: * `browse-now find "query"` * `browse-now click -T "visible text"` * `browse-now screenshot /tmp/page.png` ## Useful Commands [#useful-commands] ```bash browse-now open https://example.com browse-now snapshot -i browse-now find "search button" browse-now click @e12 browse-now fill @e3 "Nowledge Mem" --submit browse-now get page-text --max-chars 4000 browse-now screenshot /tmp/page.png ``` ## What To Ignore At First [#what-to-ignore-at-first] * You do not need Browse Now for simple public webpages. Normal search or URL learning is faster. * You do not need the CLI for everyday AI Now usage. Enable the skill and let the agent call it when needed. * You should not expect it to bypass paywalls, permission prompts, anti-bot checks, or pages your browser itself cannot access. ## External Agent Skill [#external-agent-skill] There are two common ways to make an agent use `browse-now`: * in AI Now, enable the built-in **Browse Now** skill * in external agents, install the reusable `npx skills` package below If you want supported agents to learn when and how to use `browse-now`, install the reusable skill package from `community`: ```bash npx skills add nowledge-co/community/nowledge-mem-browse-now-npx-skills ``` That package teaches the agent to: * prefer `browse-now` for authenticated or interactive browser work * use refs from `snapshot -i` as the main interaction path * re-snapshot after navigation * verify results with `get url` and `get title` ## How It Fits With Mem [#how-it-fits-with-mem] A strong combined setup looks like this: * use `Nowledge Mem` skills or integrations to recall context * use `browse-now` when the task needs the user's real browser * save durable insights back into Mem when the browser task reveals something worth keeping ## PyPI And Remote Use [#pypi-and-remote-use] `browse-now` is also published on PyPI. That is for cases where you want the CLI or Python API outside the desktop bundle. It does **not** mean browser automation becomes a remote-access feature. Even with the PyPI package, the browser bridge still stays on the local machine for security reasons. ## Related Guides [#related-guides] * [AI Now](/docs/ai-now) * [Background Intelligence](/docs/advanced-features) * [Library](/docs/library) * [Browser Extension](/docs/integrations/browser-extension) * [Connectors](/docs/integrations) * [Nowledge Mem CLI](/docs/cli) # Nowledge Mem CLI (/docs/cli) The `nmem` CLI gives you terminal access to your Nowledge Mem knowledge base. Search memories, browse threads, read and edit Working Memory, explore the knowledge graph, and view your activity feed, all from the shell. If you also need browser automation, the desktop app bundles a second CLI called [`browse-now`](/docs/browse-now). It works with the Nowledge Mem Exchange extension to let agents control the user's real browser for authenticated and interactive web tasks. That browser bridge is local-only and is not exposed through Access Anywhere. ## Installation [#installation] ### Option 1: Standalone CLI Package [#option-1-standalone-cli-package] Install on any machine. Works with a local or remote Nowledge Mem server: ```bash pip install nmem-cli # or with uv uv pip install nmem-cli # on Arch Linux, use the community-maintained AUR package yay -S nmem-cli # or: paru -S nmem-cli # or run without installing uvx --from nmem-cli nmem --help ``` **Requirements:** Python 3.11+, Nowledge Mem running locally or reachable remotely. The standalone package lets you reach your Nowledge Mem from servers, CI/CD pipelines, or remote workstations. See [Access Mem Anywhere](/docs/remote-access). View on [PyPI](https://pypi.org/project/nmem-cli/). The AUR package is community-maintained by [czyt](https://github.com/czyt) and follows the PyPI `nmem-cli` release. As with any AUR package, review the PKGBUILD before installing. ### Option 2: Bundled with Desktop App [#option-2-bundled-with-desktop-app]
#### macOS [#macos-step] Go to **Settings → Preferences → Developer Tools** and click **Install CLI**. Installs to `/usr/local/bin/nmem`.
#### Windows [#windows-step] The CLI is automatically available after app installation. Open a **new terminal window** to use `nmem`.
#### Linux [#linux-step] Included with deb/rpm packages. The binary is placed in `/usr/local/bin/nmem`. ***
## Quick Start [#quick-start] ```bash nmem status # Check connection nmem ask "What did we decide about deployment?" nmem ask "What changed?" --space work --ephemeral nmem m search "project notes" # Search memories nmem m search "project notes" --space work nmem m add "Key insight" --title "Learning" nmem wm # Read today's Working Memory nmem wm --space work # Read Working Memory for one space nmem spaces # List known spaces nmem f --days 1 # Today's activity nmem g expand # Explore graph connections nmem tui # Interactive terminal UI ``` *** ## Global Options [#global-options] | Option | Description | | ----------------- | -------------------------------------------------------------------------- | | `-j, --json` | Machine-readable JSON output | | `--api-url ` | API URL (default: `http://127.0.0.1:14242`) | | `--space ` | Run the command inside one named space when you want a non-default context | | `-v, --version` | Show version | | `-h, --help` | Show help | **Aliases:** `m` = memories · `t` = threads · `wm` = working-memory · `g` = graph · `f` = feed · `c` = communities *** ## Ask your knowledge (`nmem ask`) [#ask-your-knowledge-nmem-ask] Ask across Memories, past conversations, Library documents, and graph connections from the terminal: ```bash nmem ask "What did we decide about the authentication migration?" nmem ask "Summarize the evidence" --space "Research" nmem ask "Is this documented anywhere?" --ephemeral nmem --json ask "Which sources support this decision?" ``` By default, the question and completed answer are saved to Timeline so you can reopen the evidence or continue the conversation later. Use `--ephemeral` for a one-off answer that should not create a Timeline entry. Progress is written to stderr and the answer to stdout, so ordinary shell piping stays clean; `--json` returns one terminal object with the answer, evidence references, retrieval coverage, and Timeline event ID. `--space` follows that Space's normal strict/shared/all retrieval policy. It does not bypass Space boundaries. *** ## Memory Commands (`nmem m`) [#memory-commands-nmem-m] If you do not use spaces, ignore `--space` and keep working in the default space. When you do need separate project or agent contexts, the same commands work with `--space ""`. ### List memories [#list-memories] ```bash nmem m # Recent 10 memories nmem m -n 50 # List 50 nmem m --importance 0.7 # Minimum importance filter ``` ### Search [#search] ```bash nmem m search "authentication patterns" nmem m search "authentication patterns" --space work nmem m search "API design" --importance 0.8 nmem m search "deploy" -l devops -l backend # Filter by labels (AND) nmem m search "renewal" --metadata customer=acme --metadata purpose=contract-review nmem m search "sprint" --mode deep # Graph + LLM-enhanced results nmem m search "old deployment notes" --include-history ``` Search shows where a memory came from and how old it is in the default table. By default, recall returns current memories only; memories that were superseded by a newer version stay in graph history but do not keep competing in normal search. Use `--include-history` when you are auditing how an answer changed over time. Use `--metadata key=value` for stable fields your workflow already knows, such as customer, project, material type, or purpose. Repeat `--metadata` to narrow the memory set before ranking. **Bi-temporal search.** Distinguish *when something happened* from *when you saved it*: ```bash nmem m search "database decision" --event-from 2025-01 --event-to 2025-06 nmem m search "meeting notes" --recorded-from 2026-01-01 ``` | Option | Description | | -------------------- | --------------------------------------------------------- | | `-n` | Max results | | `-l, --label` | Filter by label (repeatable) | | `--metadata, --meta` | Filter by memory metadata key/value (repeatable) | | `--importance` | Minimum importance (0–1) | | `--mode` | `normal` (default, fast) or `deep` (graph + LLM-enhanced) | | `--include-history` | Include superseded/deprecated memory versions | | `--event-from/to` | When the fact *happened* (YYYY, YYYY-MM, or YYYY-MM-DD) | | `--recorded-from/to` | When it was *saved* to Nowledge Mem (YYYY-MM-DD) | ### Add [#add] ```bash nmem m add "We chose PostgreSQL for task events" nmem m add "Prefer functional components in React" \ --title "Frontend conventions" \ --unit-type preference \ --importance 0.8 \ -l frontend -l react # Record when something actually happened (bi-temporal) nmem m add "Decided to sunset the legacy API" \ --unit-type decision \ --event-start 2025-11 \ --when past # Preserve provenance when an agent distills a thread nmem m add "The migration script must run after the schema check" \ --unit-type learning \ --source claude-code \ --source-thread thread_abc \ --source-msg msg_042 ``` | Option | Description | | ------------------ | ------------------------------------------------------------------------------ | | `-t, --title` | Memory title | | `-i, --importance` | Importance 0–1 | | `-l, --label` | Add label (repeatable) | | `--unit-type` | `fact` `preference` `decision` `plan` `procedure` `learning` `context` `event` | | `--event-start` | When it happened (YYYY, YYYY-MM, YYYY-MM-DD) | | `--event-end` | End of a time range | | `--when` | `past` `present` `future` `timeless` (default: timeless) | | `--source-thread` | Thread ID this memory was distilled from | | `--source-msg` | Message ID this memory was distilled from | | `--source-range` | Message index range, for example `12:18` | ### Review memory types [#review-memory-types] Use this when old or weakly typed memories should be reviewed against the current type system. The command defaults to a dry run. Applying changes updates only memory metadata and search-index filter metadata; it does not rewrite memory content, re-embed memories, or rebuild the search index. ```bash nmem m reclassify-types nmem m reclassify-types --target-type procedure nmem m reclassify-types --unit-type learning --unit-type decision --target-type procedure nmem --json m reclassify-types --target-type procedure --wait nmem m reclassify-types --apply --target-type procedure --limit 50 ``` Use `--target-type procedure` when you are repairing reusable how-tos that were previously saved as decisions or learnings. Use `--wait` when a script wants the Feed result for the exact review request before continuing. ### Show [#show] ```bash nmem m show nmem m show --content-limit 500 ``` ### Update [#update] ```bash nmem m update --title "New title" nmem m update --importance 0.9 nmem m update --content "Updated content" ``` ### Deprecate or supersede [#deprecate-or-supersede] Use lifecycle commands when a memory is no longer true. This keeps the old memory available for history while removing it from normal recall. ```bash nmem m deprecate mem_old --reason "The API changed" nmem m supersede mem_old mem_new --reason "The newer deployment decision replaced it" ``` `supersede` is not a delete. It records an EVOLVES `replaces` link from the old memory to the new memory, moves labels forward to the replacement, and leaves the older memory available through history views and `m search --include-history`. ### Move between spaces [#move-between-spaces] Use this when you already saved memories in one space and want to move them into another one. ```bash nmem m move --space "Research Agent" --to-space "Archive" nmem m move --space "Research Agent" --to-space "Archive" -f nmem m move --all-in-space "Research Agent" --to-space "Archive" --dry-run nmem m move --all-in-space "Research Agent" --to-space "Archive" -f ``` `--space` is the source space. `--to-space` is the destination. For whole-space moves, use `--dry-run` first if you want to preview the count before changing anything. ### Delete [#delete] ```bash nmem m delete nmem m delete -f # Skip confirmation nmem m delete # Multiple IDs ``` `nmem m delete` is interactive by default. For scripts, agents, CI, or any non-interactive shell, use `-f` so the command does not block waiting for confirmation. *** ## Thread Commands (`nmem t`) [#thread-commands-nmem-t] ### List and search [#list-and-search] ```bash nmem t # Recent threads nmem t list --source openclaw -n 20 # Recent OpenClaw threads only nmem t list --offset 20 -n 20 # Next page of recent threads nmem t search "architecture decisions" ``` Use `list` when you want the newest threads in order. Use `search` when you want full-text matches inside thread content. ### Show [#show-1] ```bash nmem t show nmem t show -n 50 # Show up to 50 messages nmem t show --content-limit 200 ``` ### Create [#create] ```bash # From text nmem t create -t "Quick note" -c "Remember to review the API changes" # From a file nmem t create -t "Meeting notes" -f notes.md # With structured messages nmem t create -t "Chat session" \ -m '[{"role":"user","content":"Hello"},{"role":"assistant","content":"Hi!"}]' # With a stable ID (idempotent, safe to re-run) nmem t create -t "OpenClaw session" --id "openclaw-abc123-session" ``` ### Append [#append] Add messages to an existing thread. Safely idempotent: duplicate messages are filtered by content hash or external ID. ```bash # Single message nmem t append -c "Follow-up note" # Structured messages nmem t append \ -m '[{"role":"user","content":"Question"},{"role":"assistant","content":"Answer"}]' # With idempotency key (safe for retries / repeated hook fires) nmem t append \ -m '[{"role":"user","content":"msg"}]' \ --idempotency-key "oc-batch-session-001" ``` ### Save Claude Code / Grok Build / Codex / Gemini CLI session [#save-claude-code--grok-build--codex--gemini-cli-session] ```bash nmem t save --from claude-code # Save Claude Code session nmem t save --from grok # Save Grok Build session nmem t save --from codex # Save Codex session nmem t save --from codex -s "Summary" # With session summary nmem t save --from gemini-cli # Save Gemini CLI session ``` By default, `nmem` reads Claude Code from `~/.claude`, Grok Build from `~/.grok`, and Codex from `~/.codex`. If you keep those tools in a custom location, `CLAUDE_CONFIG_DIR`, `GROK_HOME`, and `CODEX_HOME` are respected automatically. | Option | Description | | --------------- | ---------------------------------------------------------- | | `--from` | `claude-code`, `grok`, `codex`, or `gemini-cli` (required) | | `-p, --project` | Project directory path (default: current dir) | | `-m, --mode` | `current` (latest) or `all` sessions | | `--session-id` | Specific session ID (Codex and Grok Build) | | `-s, --summary` | Brief session summary | | `--truncate` | Truncate large tool results (>10KB) | ### Delete [#delete-1] ```bash nmem t delete nmem t delete -f # Force nmem t delete --cascade # Also delete associated memories ``` ### Move between spaces [#move-between-spaces-1] ```bash nmem t move --space "Research Agent" --to-space "Archive" nmem t move --space "Research Agent" --to-space "Archive" -f nmem t move --all-in-space "Research Agent" --to-space "Archive" --dry-run nmem t move --all-in-space "Research Agent" --to-space "Archive" -f ``` As with memories, `--space` is the source guard and `--to-space` is the destination. Mem resolves whole-space moves on the server, so scripts do not need to page through every result first. *** ## Nowledge FS (`nmem fs`) [#nowledge-fs-nmem-fs] `nmem fs` is the CLI for **Nowledge FS**, the preview path-first layer that powers [Knowledge Tree](/docs/nowledge-fs). Use it when a script or agent should navigate Mem as paths instead of juggling separate memory, thread, wiki, feed, and Library commands. This is a preview shape, not a local mount yet. The paths are stable Mem identifiers served by the Mem API, so they work from the desktop app, the web client, remote clients, scripts, and MCP-connected agents. ```bash nmem fs capabilities --json # Discover roots, verbs, and limits nmem fs ls / # Top-level branches nmem fs cat /wiki/entities/PostgreSQL.entity.md nmem fs cat /sources/research-report-abc123.pdf --line 120 --lines 80 nmem fs stat /memories/by-id/mem_abc.memory.md nmem fs find /memories --label decisions --since 2026-01-01 nmem fs grep "JWT rotation" /memories nmem fs grep "JWT rotation" /threads nmem fs grep "JWT rotation" /sources nmem fs grep -E "JWT|token" /threads --jsonl nmem fs grep "JWT rotation" /threads --jsonl nmem fs recall "session token strategy" --in /memories ``` Use `capabilities --json` when a script or adapter needs the current root list, supported verbs, limits, or feature flags. Use `recall` when wording is fuzzy and you are looking for memories, `find` when the constraint is structural, and `grep` when you need an exact phrase. `grep` is case-insensitive by default; add `--case-sensitive` for exact casing or `-E` for regex patterns such as `JWT|token`. Results are paths, so you can pipe or copy them into `cat`. `grep` also returns line numbers; use `cat --line` and `--lines` to inspect just the useful window of a long thread or parsed document. ```bash nmem fs recall "why did we change token refresh?" --in /memories -k 5 --paths \ | while IFS= read -r kfs_path; do nmem fs cat "$kfs_path"; done nmem fs grep "JWT rotation" /threads --jsonl \ | while IFS= read -r hit; do kfs_path=$(printf '%s' "$hit" | jq -r '.path') kfs_line=$(printf '%s' "$hit" | jq -r '.line') nmem fs cat "$kfs_path" --line "$kfs_line" --lines 12 done ``` Start broad, then narrow: `recall` or `find` returns paths, `ls` gives nearby context, `stat` checks metadata cheaply, and `cat` loads only the final object. This keeps context small while preserving the user's mental model of a tree. Canonical writable paths can be updated from the shell: ```bash cat note.md | nmem fs write /memories/by-id/mem_abc.memory.md --stdin nmem fs rm /memories/by-id/mem_abc.memory.md --force ``` Alias and derived paths stay read-only. For example, a memory shown under a label or date branch should be edited through its `/memories/by-id/...` path. ### Verbs [#verbs] | Verb | Use it for | | ----------------------------- | ------------------------------------------------------------------------------------------------------------------ | | `capabilities` | Discover supported roots, verbs, limits, and feature flags. Use `--json` for scripts. | | `ls PATH` | List a branch. Use `--cursor` with `-n` when a directory is paginated. | | `cat PATH` | Read a rendered object body plus frontmatter. Add `--line N --lines M` for a small window. | | `stat PATH` | Inspect metadata without loading the body. | | `find PATH ...` | Structural search, such as `--type memory`, `--label decisions`, `--since 2026-01-01`, or `--mentions PostgreSQL`. | | `grep QUERY PATH` | Exact-string search over memories, thread messages, and parsed Library documents. Add `-E` for regex. | | `recall QUERY --in /memories` | Semantic memory search that returns paths. | | `write PATH` | Update a canonical writable object. | | `rm PATH` | Delete a canonical writable object. | For shell pipelines, `find`, `grep`, and `recall` support `--paths`; `grep` also supports `--jsonl` when the next command needs both `path` and `line`. In `zsh`, avoid naming loop variables `path`; it shadows the shell's command search path. ### Current boundaries [#current-boundaries] * `nmem fs` is API-backed. It does not create a real folder on disk yet. * The preview release supports Tree, `/fs/*`, CLI, and MCP. Mounting is planned for a later phase. * `grep` is exact-string search. It can search memories, thread messages, and parsed Library documents. It is case-insensitive by default; use `--case-sensitive` for exact casing or `-E` for regex. Use `recall` for semantic memory search. * Source fragments such as PDF pages or spreadsheet sheets, plus SQL/Cypher/replay/tail, are planned after their schemas and safety limits are pinned. * Errors use familiar filesystem-style codes: `ENOENT` for missing paths, `EROFS` for derived read-only paths, `EXDEV` for alias write attempts, and `ENOTSUP` for verbs that are designed but not shipped yet. *** ## Library Sources (`nmem sources`) [#library-sources-nmem-sources] Your [Library](/docs/library) (PDFs, spreadsheets, Word files, presentations, Markdown, code, and URLs) is reachable from the terminal. Use `nmem sources` when a script needs to find a document, read a passage from it, or pull structured analysis out of a spreadsheet without opening the app. `nmem sources` aliases to `nmem s`. ### List, add, show, delete [#list-add-show-delete] ```bash nmem sources list # Sources in the current space nmem sources add notes.pdf # Import a file nmem sources add https://example.com/doc # Capture a URL nmem sources show src_abc123 # Metadata for one source nmem sources delete src_abc123 -f # Delete (non-interactive) ``` ### Search across the Library [#search-across-the-library] ```bash nmem sources search "meeting notes" nmem sources search roadmap -n 10 nmem sources search "renewal terms" --label customer-acme --metadata purpose=contract-review nmem sources list --metadata material_type=case-study ``` Full-text match against filenames and parsed summaries. Returns source IDs you can feed into the commands below. Use `--label` for broad source labels and `--metadata key=value` for fields your import flow already knows, such as customer, project, material type, or purpose. Repeat `--label` or `--metadata` to narrow the result set before ranking. ### Read parsed content [#read-parsed-content] ```bash nmem sources read src_abc123 # First 8000 characters nmem sources read src_abc123 --offset 8000 # Next page nmem sources read src_abc123 --limit 16000 # Larger window ``` Returns the parsed text of one document, paged by character offset. Useful for feeding a specific section into another tool. ### Search inside a single document [#search-inside-a-single-document] ```bash nmem sources search-chunks src_abc123 "risk factors" nmem sources search-chunks src_abc123 budget -n 3 ``` Runs a full-text search against the indexed chunks of one source. Each match comes back with the actual passage, chunk index, and score, so you and any downstream agent can see what was matched, not just how many chunks matched. ### Analyze tabular sources [#analyze-tabular-sources] ```bash nmem sources analyze src_abc123 # All columns nmem sources analyze src_abc123 --column price --column region # Specific columns ``` Runs structured analysis on CSV, TSV, XLSX, or XLS sources: column stats, distributions, and basic shape. For narrative documents, use `search-chunks` and `read` instead. `search`, `read`, `search-chunks`, and `analyze` are the same Library tools available to AI Now, the Feed Agent, the Graph Intelligence Agent, and MCP-connected clients. Anything you can do from the terminal, agents can do on your behalf, and vice versa. *** ## Working Memory (`nmem wm`) [#working-memory-nmem-wm] Working Memory is the AI-generated daily briefing: focus areas, open questions, and recent activity. Background Intelligence updates it each morning. The **Default** space keeps the familiar compatibility file at `~/ai-now/memory.md`. If spaces are enabled, `nmem wm` can read or edit the briefing for any space with `--space ""`. ### Read [#read] ```bash nmem wm # Today's Working Memory nmem wm --space work # Working Memory for one space nmem wm --date 2026-02-12 # Archived date nmem wm history # List available archived dates ``` ### Edit [#edit] ```bash nmem wm edit # Opens $EDITOR nmem wm edit --space work # Edit one space nmem wm edit -m "## Focus Areas\n- Ship v0.6" # Set directly ``` ### Patch a section (non-destructive) [#patch-a-section-non-destructive] Replace or append to one section without touching the rest of the document: ```bash # Replace a section nmem wm patch --heading "## Focus Areas" --content "- Finish OpenClaw plugin release" # Append to a section nmem wm patch --heading "## Notes" --append "Reminder: deploy to staging tonight" ``` The heading is matched case-insensitively and partially. `"Focus"` matches `"## Focus Areas"`. ## Spaces (`nmem spaces`) [#spaces-nmem-spaces] Use this only when you want more than the default space. ```bash nmem spaces nmem spaces create "Research Agent" nmem spaces update "Research Agent" --instructions "Prefer research notes and hypotheses" nmem spaces show "Research Agent" ``` If you need a stable storage key for automation, `--id` is still available as an advanced option. Most people should let Mem generate it. *** ## Graph Commands (`nmem g`) [#graph-commands-nmem-g] ### Expand graph neighborhood [#expand-graph-neighborhood] Explore connected memories, entities, crystals, and source documents around a given memory: ```bash nmem g expand nmem g expand --depth 2 # Two hops out nmem g expand -n 10 # Limit neighbors per hop ``` ### Show EVOLVES version chain [#show-evolves-version-chain] See how a memory has been refined or superseded over time: ```bash nmem g evolves ``` *** ## Feed (`nmem f`) [#feed-nmem-f] The activity feed shows what was saved, learned, synthesized, or ingested, in chronological order. ```bash nmem f # Last 7 days (high-signal events) nmem f --days 1 # Today only nmem f --days 30 # Last 30 days nmem f --type crystal_created # Only crystal synthesis events nmem f --from 2026-02-10 --to 2026-02-14 # Exact date range nmem f --all # Include low-signal background events nmem f -n 50 # Limit events (default: 100) ``` | Option | Description | | ---------------- | ------------------------------------------------ | | `--days` | How many days back (default: 7; use 1 for today) | | `--type` | Filter by event type | | `-n, --limit` | Max events to fetch (default: 100) | | `--all` | Include low-signal background events | | `--from`, `--to` | Exact date range (YYYY-MM-DD) | **Event types:** `memory_created` · `crystal_created` · `insight_generated` · `source_ingested` · `source_extracted` · `daily_briefing` · `url_captured` *** ## Knowledge Communities (`nmem c`) [#knowledge-communities-nmem-c] Browse topic clusters automatically detected in your knowledge graph: ```bash nmem c # List communities nmem c -n 20 nmem c show # Show community details (entities, memories) nmem c detect # Trigger community detection (background) ``` *** ## Configuration & Models [#configuration--models] ### Search Index Model [#search-index-model] ```bash nmem models status # Check current model status nmem models download # Download the Search Index Model nmem models reindex # Rebuild the search index ``` ### LLM provider [#llm-provider] ```bash nmem config provider list nmem config provider set openai --api-key sk-xxx --model gpt-4o nmem config provider test ``` ### Processing settings [#processing-settings] ```bash nmem config settings # Show all settings nmem config settings set briefingHour 8 # Change morning briefing time ``` ### Client connection settings [#client-connection-settings] Use this when the current machine needs to connect to a remote Mem server: ```bash nmem config client show nmem config client set url https://mem.example.com nmem config client set api-key nmem_... nmem config client clear api-key ``` `nmem config client ...` updates the local client config used by this machine's CLI and plugins. It is separate from `nmem config access ...`, which controls how a Mem server is exposed to other devices. ### MCP config snippets [#mcp-config-snippets] Use this when an AI host or orchestrator asks for an MCP config file instead of reading the Mem client config directly: ```bash nmem config mcp show --host claude-code nmem config mcp show --host codex nmem config mcp show --host cursor nmem config mcp show --host gemini-cli ``` The snippet includes the resolved Mem URL, API key headers when configured, and the right shape for that host. If another tool launches Claude Code for you, that launcher still needs to pass Claude Code the generated MCP config. ### License [#license] ```bash nmem license status nmem license activate [email] # Email is inferred from the license key when possible nmem license renew # Refresh or renew this device's authorization nmem license deactivate # Deactivate license on this device ``` *** ## Remote Access [#remote-access] ```bash # LAN / private network export NMEM_API_URL=http://192.168.1.100:14242 nmem status # Cloudflare tunnel (from desktop app: Settings → Access Mem Anywhere) export NMEM_API_URL=https:// export NMEM_API_KEY=nmem_... nmem m search "notes" # One-off without env vars nmem --api-url https:// status ``` | Variable | Description | Default | | -------------- | --------------------- | ------------------------ | | `NMEM_API_URL` | API server URL | `http://127.0.0.1:14242` | | `NMEM_API_KEY` | API key (Bearer auth) | *(unset)* | Full guide: [Access Mem Anywhere](/docs/remote-access). *** ## JSON Output [#json-output] Add `--json` (or `-j`) before the subcommand for machine-readable output: ```bash nmem --json m search "API design" | jq '.memories[0].id' nmem --json m add "Note" | jq -r '.id' nmem --json f --days 1 | jq '.events[].title' ``` ### Search response [#search-response] ```json { "query": "API design", "total": 3, "search_mode": "fast_bm25_vector", "memories": [ { "id": "abc123-def456-...", "title": "REST API versioning decision", "content": "We use /v1/ prefix for all public endpoints...", "score": 0.91, "relevance_reason": "Text Match (89%) + Semantic Match (73%) | decay[imp:high]", "importance": 0.8, "labels": ["architecture", "api"], "event_start": "2025-09", "temporal_context": "past", "source": "cli" } ] } ``` ### Feed response [#feed-response] ```json { "events": [ { "id": "evt-...", "event_type": "memory_created", "severity": "info", "title": "Memory or event title", "description": "Summary text...", "metadata": { "source": "claude", "unit_type": "fact" }, "related_memory_ids": ["..."], "created_at": "2026-02-20T02:35:28+00:00" } ] } ``` ### Error response [#error-response] ```json { "error": "api_error", "status_code": 404, "detail": "Memory not found" } ``` *** ## Status and Statistics [#status-and-statistics] ```bash nmem status # nmem v0.6.2 # status ok # api http://127.0.0.1:14242 # database connected # search ready nmem stats # Database Statistics # memories 83 # threads 27 # entities 248 # labels 177 # communities 32 ``` If search needs attention, `nmem status` tells you which case you are in: * `search rebuild needed`: run `nmem models reindex` * `search updating metadata`: Mem is filling new search metadata in the background. No rebuild is needed. *** ## AI Agent Integration [#ai-agent-integration] The `--json` flag and stable exit codes make `nmem` easy to drive from AI agents. ```bash # Search for context before responding nmem --json m search "authentication flow" | jq '.memories[:3]' # Save an insight nmem m add "Rate limiting is per-user, not per-IP" \ --unit-type learning --importance 0.8 -l backend # Save a decision with when it was made nmem m add "Chose Postgres over MySQL for task events" \ --unit-type decision --event-start 2026-02 -l architecture # Browse what was worked on last week nmem --json f --days 7 | jq '.events[].title' # Create a session thread backup nmem t create -t "Debug session $(date +%Y%m%d)" \ -m '[{"role":"user","content":"Investigate auth failures"},{"role":"assistant","content":"Found rate limit issue"}]' ``` *** ## TUI [#tui] An interactive terminal UI for browsing memories, threads, and the knowledge graph: ```bash nmem tui ``` If you launch the TUI with `NMEM_SPACE="Research Agent"`, the Memories and Threads tabs stay inside that space. This is useful for agent workstations or terminal-only servers where one shell session belongs to one project or agent lane. For moving many records between spaces, use the app or the `nmem m move` / `nmem t move` commands. The TUI keeps browsing and editing scoped, but it does not add a separate multi-select move workflow. In the `Settings` tab, you can also manage **Access Anywhere** (Quick link / stable Cloudflare account mode) from terminal-only environments. This is the same remote-access feature documented in [Access Mem Anywhere](/docs/remote-access). nmem tui main nmem tui memory nmem tui thread nmem tui graph *** ## Troubleshooting [#troubleshooting] **"command not found: nmem"** * PyPI install: `pip install nmem-cli` (Python 3.11+) * Arch Linux: `yay -S nmem-cli` or `paru -S nmem-cli` * Run without installing: `uvx --from nmem-cli nmem --help` * macOS desktop: Settings → Preferences → Developer Tools → Install CLI * Windows: open a new terminal after app installation **"Cannot connect to server"** 1. Ensure Nowledge Mem is running 2. Try: `nmem --api-url http://127.0.0.1:14242 status` 3. Check for proxy or VPN blocking localhost # Community & Support (/docs/community) ## Community Channels [#community-channels] ## Get Support [#get-support] Choose the fastest path for the kind of help you need: * **Discord** for setup questions, workflow advice, and quick product help * **GitHub Issues** for bugs, feature requests, and reproducible product problems * **Email / private channels** when you need account or sensitive support ### Documentation [#documentation] * **[Getting Started](/docs/getting-started)**: Your first five minutes with the Timeline and your first saved knowledge * **[Connectors](/docs/integrations)**: Choose the right connection path for each AI tool * **[Background Intelligence](/docs/advanced-features)**: Knowledge graph, insights, crystals, and working memory * **[Troubleshooting](/docs/troubleshooting)**: Common issues and solutions ### Report Issues & Request Features [#report-issues--request-features] ### Email Support [#email-support] For direct assistance, reach out to our team:
[hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai)
Licensed users may have access to higher-touch support channels depending on their purchase and rollout status. If you need help and are not sure which channel applies, start with email or Discord. # Back Up, Export, and Import (/docs/data-portability) Nowledge Mem is local-first. Data Transfer is how you keep that promise practical: you can export your knowledge, store it yourself, and import it into another Mem when you need to move. Use it when you want a backup before a major change, a one-time migration to another machine, or an offline copy you can inspect later. The Mem export itself is not an opaque binary database dump. It is a text-based bundle: JSON manifest files, JSONL records for memories, threads, sources, entities, skills, and graph edges, non-secret AI Profiles and Rules, plus Markdown for Working Memory. If you choose to include original Library files or managed skill bundles, those files keep their original format. The `.zip` is only packaging. ## When To Use Data Transfer [#when-to-use-data-transfer] Use **Settings -> Data Transfer** when you want to: * back up your knowledge before reinstalling or upgrading * move from one computer to another * move between desktop, Linux server, and headless deployments * keep a human-inspectable archive of your Mem data * keep reusable skills with the knowledge they were created from * import a previous export into a fresh Mem install This is different from [Sync Across Devices](/docs/sync). Sync means one always-on Mem with many clients connected to it. Data Transfer is for backup, export, import, and one-time migration. It is also different from the [Open Knowledge Format (OKF)](/docs/concepts/open-knowledge-format) export. Data Transfer is a complete, re-importable backup of your Mem; the OKF export is a portable, readable knowledge bundle for handing your knowledge to other tools. ## Data Transfer vs Search Maintenance [#data-transfer-vs-search-maintenance] Use **Data Transfer** when you need a copy of your knowledge or want to move it somewhere else. Use **Settings -> Memory Processing -> Search** for local maintenance: * **Optimize** compacts the rebuildable search index when it is using too much disk space. * **Rebuild Index** recreates search from your saved memories, library content, and message store when results look stale or incomplete. Neither action creates a backup. They also do not replace export/import. If you are preparing for a major upgrade or moving to another machine, export first. ## Export From The App [#export-from-the-app] 1. Open **Settings**. 2. Go to **Data Transfer**. 3. Choose what to include. 4. Keep **Compress as .zip** on if you want a single file. 5. Click **Export**. On desktop, you can export either a `.zip` file or an expanded folder. In web or remote client mode, the browser downloads a `.zip` because the client cannot write directly to the server's filesystem. A successful export gives you a `.zip` file or folder containing a `manifest.json` file. Keep that file somewhere you control: external drive, encrypted backup, NAS, or your normal backup system. ## Import Into Another Mem [#import-into-another-mem] 1. Open **Settings -> Data Transfer** on the destination Mem. 2. Pick an import mode. 3. Select the export `.zip` or folder. 4. Start the import and wait for it to finish. 5. Check Timeline, Library, Search, and the Knowledge Graph. Import runs as a background job. Large exports can take time because Mem needs to restore records and rebuild search projections. ## Import Modes [#import-modes] Choose the mode based on what should happen when the export contains an item that already exists on the destination. | Mode | Best For | What It Does | | ------------- | --------------------------------------- | ----------------------------------------------------------------------------------------- | | **Merge** | Normal restores and migrations | Keeps existing records and fills in missing related data where possible. | | **Skip** | Importing an archive into an active Mem | Leaves destination records untouched when the same item already exists. | | **Overwrite** | Replacing a test or stale destination | Replaces matching records with the export copy. Use this only when the export should win. | If you are not sure, start with **Merge**. ## What Is Inside The Export [#what-is-inside-the-export] The exact contents depend on the options you choose, but a Mem export can include: | Path | Purpose | | ------------------------- | ------------------------------------------------------------------------------------------------------------ | | `manifest.json` | Export format, version, counts, and included sections. | | `nodes/*.jsonl` | Memories, threads, sources, entities, labels, communities, and other graph nodes. | | `relationships/*.jsonl` | Graph relationships between those nodes. | | `content_store/*.jsonl` | Thread messages and larger content payloads when included. This is the portable form of Mem's message store. | | `working_memory.md` | Current Working Memory in Markdown. | | `working_memory_archive/` | Archived Working Memory snapshots, when included. | | `skills/` | Managed skill bundles, including `SKILL.md` and bundled files. | | `settings/*.json` | Non-secret AI Profiles and Rules, so named agents keep their identity and behavior after migration. | | original source files | Optional Library files, kept in their original format. | This format is meant to be recoverable and inspectable. You are not locked into a hidden desktop-only database file. ## What This Does Not Move [#what-this-does-not-move] Data Transfer is for your knowledge data. It is not a full clone of the whole app install. After moving to a new machine, you may still need to reconnect model providers, integrations, remote-access settings, licenses, or operating-system-level app preferences. AI Profiles and Rules are included, but API keys, provider credentials, and license tokens are not. Search indexes, embeddings, and active skill projection folders are not moved as source data. Mem rebuilds those projections from the restored memories, messages, Library files, and managed skill bundles. Background task queues, in-progress catch-up plans, and the local AI usage ledger are also not moved. After import, the new Mem recalculates maintenance backlog from the restored memories. If the old Mem was still catching up, start catch-up again on the new machine. For a self-hosted Docker or Linux server, also read [Server Deployment](/docs/server-deployment). Server operators can choose between a fast volume-level snapshot and an application-level export that uses the same portable Mem data format. If you are automating the same flow, the API reference includes [export](/docs/api/data/export/post), [download export](/docs/api/data/export/download/post), [import](/docs/api/data/import/post), and [upload import](/docs/api/data/import/upload/post) endpoints. For large browser/API downloads, Mem stages the temporary export files on its app storage volume instead of the container's small `/tmp` area. Keep enough free space on the Mem data/config volume for the export workspace and the final `.zip`; Mem will not overwrite an existing export file unless you explicitly enable overwrite. ## Good Backup Habits [#good-backup-habits] * Export before a major upgrade or machine migration. * Keep at least one recent export outside the computer that runs Mem. * Use `.zip` when you want a single portable file. * Use a folder export on desktop when you want to inspect the files directly. * Test an import into a spare Mem before deleting the original machine. Your knowledge should be yours. Data Transfer is the practical way to keep that true. # Docker Deployment (/docs/docker) **Not sure if you need this?** Most people use Nowledge Mem as a desktop app on macOS, Windows, or Linux. Install once, the data lives locally, no Linux or Docker knowledge required. See **[Installation](/docs/installation)**. This page is for the specific case where you want Mem to run as a **headless server** on a host you administer, such as a VPS, a home NAS, a cloud VM, or a homelab box, so the web app and `nmem` CLI on your other devices can reach it over your network. The official `nowledgelabs/mem` image runs the same backend as the desktop app, serves the web app at `/app`, and keeps all your data in three plain bind-mounted directories on the host (`./data`, `./config`, `./cache`). You back them up with whatever you already use: `rsync`, `restic`, `tar`, ZFS snapshots. It is in preview: shipping and verified end-to-end on real hosts, but the operator surface will keep evolving while we round it out. ## Is this path for you? [#is-this-path-for-you] Pick Docker when **all** of these are true: * You have a long-running host you administer, such as a VPS, a home NAS box, a cloud VM, or a homelab server, and you want Mem to live there as a service. * You already manage other long-running services with Docker on that host, or you're comfortable enough with a shell to run a few commands and edit a `compose.yaml`. * You want one centralized Mem server that the web app and the `nmem` CLI on your laptop / phone / other machines can connect to over your network. If none of those fit, install the **[desktop app](/docs/installation)** instead. That is the normal path for almost every user, and your data still lives entirely on your machine. ## Supported architectures [#supported-architectures] The image is published as a multi-arch manifest, so `docker pull nowledgelabs/mem:` resolves correctly on the two architectures you'll typically run a server on: | Architecture | Where it usually runs | | ------------- | ---------------------------------------------------------------------------------------------------- | | `linux/amd64` | Standard x86\_64 VPS, cloud VMs, x86 NAS boxes (Synology DSx+, QNAP TS-x73AU, etc.), homelab servers | | `linux/arm64` | Ampere / AWS Graviton VPS, arm64 NAS boxes, Raspberry Pi 5 class boards | You don't pick the arch; Docker pulls the right one for the host. If you happen to run Docker Desktop on an Apple Silicon Mac for development, it'll pull `arm64` and work, but that isn't the recommended path: on a personal Mac, the desktop app is simpler. ## GPU image (optional) [#gpu-image-optional] If your host has an NVIDIA GPU and you want faster local embeddings, run the opt-in `:-cuda` tag instead of the default: ```bash docker run --gpus all ... nowledgelabs/mem:-cuda ``` In the compose stack, point the `mem` service `image:` at the `:-cuda` tag and add `gpus: all` (Compose v2.30+) or the equivalent `deploy.resources` reservation. A few things worth knowing before you switch: * The GPU image is `linux/amd64` only. The default `:` tag stays multi-arch (`amd64` + `arm64`) and CPU-only, so keep using it unless you specifically want GPU acceleration. * The host needs the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) installed. Without it the container still starts, but it falls back to CPU, so you gain nothing. * The image bundles the GPU-accelerated embedding runtime, not a language model. You still supply your own GGUF model the same way you would on the CPU image. Everything else on this page (data layout, backups, upgrades, verification) is identical for both tags. ## GPU image for AMD and Intel (Vulkan) [#gpu-image-for-amd-and-intel-vulkan] If your host has an AMD or Intel GPU, run the `:-vulkan` tag. It uses Vulkan, so it also works on NVIDIA, though the `:-cuda` image is usually faster there. For AMD or Intel, pass the GPU's render node. No extra toolkit is needed: ```bash docker run --device /dev/dri -p 14242:14242 ... nowledgelabs/mem:-vulkan ``` For NVIDIA on this image, use the NVIDIA Container Toolkit with the graphics capability instead: ```bash docker run --gpus all -e NVIDIA_DRIVER_CAPABILITIES=graphics,compute,utility \ -p 14242:14242 ... nowledgelabs/mem:-vulkan ``` In the compose stack, point the `mem` service `image:` at the `:-vulkan` tag and add the matching device passthrough (`devices: ["/dev/dri:/dev/dri"]` for AMD or Intel). A few things worth knowing before you switch: * This image is `linux/amd64` only. The default `:` tag stays multi-arch (`amd64` + `arm64`) and CPU-only, so keep using it unless you specifically want GPU acceleration. * If no Vulkan device is visible, the container still starts and falls back to CPU, so it's safe to run without a GPU, just slower. * Like the CUDA image, it bundles the GPU-accelerated runtime, not a language model. You still supply your own GGUF model the same way you would on the CPU image. Everything else on this page (data layout, backups, upgrades, verification) is identical for all three tags. ## Quick start [#quick-start] The drop-in stack lives in the community repository: ```bash git clone https://github.com/nowledge-co/community.git cd community/docker ./nmemctl up ``` `nmemctl` is the lifecycle controller for this deploy. It starts the container, waits for `/livez`, prints your API key, and tells you the URL to open. If you already have a license code: ```bash ./nmemctl license activate ``` Other commands: `./nmemctl status` (health + key + URL), `./nmemctl logs -f`, `./nmemctl upgrade `, `./nmemctl wipe` (factory reset), `./nmemctl help` for the full list. By hand, the same thing in three lines: ```bash docker compose up -d docker compose exec -T mem nmem key # print API key docker compose exec -T mem nmem license activate # optional ``` Then open `http://:14242/app` and paste the API key when asked. Hand this URL to Claude / Codex / Cursor / any agent, and it will know how to install, monitor, and upgrade your Mem server on its own. Destructive operations (wipe, key rotation, license activation) always stay with you. ``` https://raw.githubusercontent.com/nowledge-co/community/main/skills/nowledge-mem-docker/SKILL.md ``` That's the raw file: `curl` it and you get the markdown directly. The rest of this page is the human-readable version of the same workflow. ## What you get [#what-you-get] * One container running the same Mem backend as the desktop app, with the web app available at `/app`. * A non-root user, a read-only image filesystem, all data in three local directories next to your `compose.yaml`. No docker-volume idioms to learn: back them up with `rsync`, `restic`, `tar`, or ZFS snapshots. * A small image (\~1.3 GB compressed) built straight from source. Same Python bundle as the desktop release. * Multi-arch: one tag works on both `amd64` and `arm64` hosts. ## Where is my API key? [#where-is-my-api-key] Mem generates an API key on first start. If you missed it, lost it, or want to rotate it, any of these works: ```bash ./nmemctl status # reprints key, license, URL, health ./nmemctl key # just the current key ./nmemctl key --rotate # rotate to a new value ./nmemctl logs | grep -A 1 "API Key" # peek at the first-run banner ``` The key lives in `./config/co.nowledge.mem.desktop/remote-access.json` on the host (mounted into the container at `/etc/nowledge-mem/...`), so it survives image upgrades. Backing up `./config` backs up the key. If you rotate, every existing client (the web UI, MCP clients, the `nmem` CLI on remote machines) needs the new value pasted back in. ### One-click installs (NAS app stores) [#one-click-installs-nas-app-stores] All of the above needs a shell. If you installed from a NAS app store (Synology, QNAP, Unraid, and the like) with one click, you may not have one. For that case set **`NOWLEDGE_NAS_BOOTSTRAP: "1"`** in the compose `environment` block (it ships commented out, default off). Then open the web UI from a browser on the same network, go to **Settings → Access Anywhere**, and a "Finish setup: copy your access key" card lets you copy the key right there, no terminal needed. It's deliberately narrow: opt-in only, it closes for good the first time the key is used, and the reveal is refused for anything arriving over the Access Anywhere tunnel. The server checks the visitor's address (including a reverse proxy's forwarded client header) and refuses public ones. On a standard Linux Docker host the real client IP is preserved, so this genuinely rejects outside visitors, but some networking setups present the bridge gateway instead, where a LAN client and an outside one look the same. Because you can't always be sure, only turn it on for a box on your trusted home network; if the port is exposed straight to the internet, retrieve the key with `nmemctl` instead. ## Where your data lives [#where-your-data-lives] Three local directories sit next to `compose.yaml`. You own them, and standard tools work directly: | Directory | Holds | Tier | | ---------- | --------------------------------------------------------------------- | ------------------------------- | | `./data` | Your graph, your conversations, your files | **Irreplaceable**, back this up | | `./config` | Settings, license, plugin choices, your API key, your device identity | **Valuable**, back this up | | `./cache` | Embedding models, search index projection | **Rebuildable**, safe to wipe | Files are owned by UID 10001 inside the container; `./nmemctl up` chowns the directories for you on first run via a one-shot helper container, so you never type `chown` or `sudo` yourself. When you upgrade with `./nmemctl upgrade ` (or `docker compose pull && docker compose up -d` by hand), all three directories stay in place. Your license stays activated, your data and conversations stay put, and the embedding model in cache means searches don't need to re-download anything. The only operation that resets you to a fresh install is `./nmemctl wipe`, which is the deliberate "wipe and start over" flow. SELinux operators (RHEL / Fedora / Rocky): append `:Z` to each bind mount in `compose.yaml` so SELinux relabels the host directories for container access. The label is opt-in because it's destructive on first apply. ## Reach your server from anywhere [#reach-your-server-from-anywhere] `cloudflared` is bundled inside the image, so Access Anywhere on Docker is turnkey. There is no sidecar to add and no `cloudflared service install` to run. The server starts and manages the tunnel for you. Configure it from the web UI in **Settings → Access Anywhere**, or from the `nmem` CLI inside the container: ```bash docker compose exec -T mem nmem config access ... ``` Once the tunnel is live, copy the URL and API key and connect any other device. The setup, key handling, and client connection steps are the same as the desktop app, so the full walkthrough lives on one page: [Remote Access](/docs/remote-access). The terminal UI ships in the image too. Run it inside the container to configure Access Anywhere, reveal the API key, and check status without leaving the shell: ```bash docker compose exec -it mem nmem tui ``` ## Memory and growing data [#memory-and-growing-data] The default `mem_limit: 4g` is sized for **passive** use of Mem: graph, web app, idle search. If you intend to use AI Now or Feed Agent actively on the server, raise it. As a rule of thumb: | Your graph size | Recommended `mem_limit` | | --------------- | -------------------------------------------------- | | Under 200 MB | 2 GB | | Under 1 GB | **4 GB** (compose default) | | 1 to 4 GB | 8 GB | | 4 to 16 GB | 16 GB | | Over 16 GB | Tune explicitly (see `community/docker/README.md`) | If a file upload or an agent query ever leaves the UI hanging on 500s, the safe recovery is `docker compose restart mem`. The image escalates its internal memory budget on the next start automatically, so the same workload should fit afterward. If it keeps happening, raise `mem_limit` per the table above. On arm64 SBCs (Raspberry Pi 5, Orange Pi 5, etc.), the same table applies, but be aware these boards usually share host RAM with the GPU and other accelerators. Leave headroom for the OS. ## Check that search is fully working [#check-that-search-is-fully-working] Search keeps working the whole time, so you never have to wait on it. `GET /health` tells you exactly which part is live: ```bash curl -s http://:14242/health | python3 -m json.tool ``` Two fields matter: * **`embedding.mode`** tells you how semantic search is running: * `remote`: a remote embedding provider (for example Nowledge AI or your own key). Full semantic search. * `local-gguf`: your bundled GGUF embedding model. Full semantic search. * `local-hash-fallback`: no real embedder is configured, so semantic ranking is degraded. Keyword search still works. This is the signal to configure an embedding provider or model. * **`reindex_needed`** is `true` when the search index is stale, usually because the embedding identity changed (you switched providers or models). The server does not block boot to rebuild the index. It starts right away and serves keyword (FTS) search while the index catches up, so a stale index quietly falls back to keyword results rather than erroring. When you are ready, trigger the rebuild from **Settings → Memory Processing → Search**, or by hand: ```bash curl -X POST -H "Authorization: Bearer $NMEM_API_KEY" http://:14242/search-index/reindex ``` If you would rather the server finish the rebuild before serving (the old behavior), set `NMEM_BOOT_AUTO_REINDEX=1` in the compose `environment` block. Most operators do not need this; the default fail-soft path keeps search available throughout. ## Verify the image came from us [#verify-the-image-came-from-us] Each release is published with a Sigstore attestation. If you want to confirm the image you're about to pull came from our build pipeline (and not from somewhere that happens to have the same tag), run: ```bash cosign verify docker.io/nowledgelabs/mem:0.9.4 \ --certificate-identity-regexp='https://github.com/nowledge-co/mem/.github/workflows/release-docker.yml@.*' \ --certificate-oidc-issuer='https://token.actions.githubusercontent.com' ``` A passing run shows the build's GitHub Actions identity. A failure means the image you pulled was not produced by our pipeline. Do not trust it. The attestation is attached to the manifest, so the same `cosign verify` works for both `amd64` and `arm64`. To confirm exactly which commit a running container was built from, read the build SHA: ```bash docker compose exec -T mem nmem-server --build-info ``` The same value is in `GET /health` under `.build_sha`, which is handy when you want to verify a deployment over the network or from a script. ## TLS on a public host [#tls-on-a-public-host] If the server is reachable from the internet and you want a real certificate, the same `community/docker/` directory ships a Caddy sidecar: ```bash export NOWLEDGE_DOMAIN=mem.example.com export NOWLEDGE_LE_EMAIL=you@example.com docker compose -f compose.yaml -f compose.tls.yaml up -d ``` You need a DNS record pointing at the host, ports 80 and 443 open for the Let's Encrypt challenge, and **Docker Compose v2.24.4 or newer** (the overlay uses a YAML merge tag that earlier versions silently ignore). Caddy renews the certificate automatically. ## Backups and migration [#backups-and-migration] Two layers, pick the one that matches your move: **Volume-level snapshot** (same image version on both ends, fastest restore): ```bash ./nmemctl export # stop, tar ./data ./config ./cache, restart ./nmemctl export --no-cache # smaller archive, skip rebuildable cache ./nmemctl import mem-export--.tar.gz # restore on the new host ``` **Application-level dump** (cross-version, or migrating from a `.deb` / desktop install, uses the same portable JSONL format the desktop app uses for "Export to file"): ```bash ./nmemctl backup-app # produces mem-app-export--.zip ./nmemctl restore-app mem-app-export--.zip ``` For the app-side guide to this portable export format, read [Back Up, Export, and Import](/docs/data-portability). Both flows leave the `machine_id` behind on purpose: the destination gets a fresh device identity and re-activates the license on first launch (consumes one seat). Retire the source server after a successful migration, since running both side-by-side diverges state. You can also use `rsync`, `restic`, `borg`, ZFS snapshots, or plain `tar` directly against `./data` and `./config`; they're just host directories. Stop the container first (`./nmemctl down`) for a guaranteed-consistent snapshot, then `./nmemctl up` afterward. Application-level dump is also how you migrate between architectures (e.g. moving from an amd64 VPS to an arm64 NAS). Volume-level snapshots are tied to the source architecture's data layout for some on-disk projections, so cross-arch moves should go through `backup-app` / `restore-app`. ## Upgrade from the web UI (optional) [#upgrade-from-the-web-ui-optional] By default, upgrading a self-hosted Mem server means SSH-ing in once per release and running `./nmemctl upgrade `. If you'd rather upgrade from the same web app you use Mem in, turn auto-update on once: ```bash ./nmemctl auto-update enable ``` This path is only for the official `community/docker` deployment. NAS app-store installs, NAS Container Manager templates, Portainer stacks, Unraid templates, and custom compose files should be updated through the system that created them. Mem can still show that a newer version exists, but it should not rewrite an unknown deployment layout. That generates a per-deploy token, adds a small companion container that handles the upgrade work, and allows Install to be triggered from the browser. After this: * **Title-bar badge** lights up when a newer Mem image is published, the same way the desktop app signals updates. * **Settings → Server card** shows the current version, the latest published version, a Download button (background pull, no downtime), and an Install button (about 30 seconds of downtime, with a snapshot taken before the container is recreated). * **Skipping versions works.** If you're on 0.9.2 and 0.9.4 is the latest, Install moves you directly to 0.9.4. Forward-only schema migrations run in order on the new image's first boot. Before turning it on: * The companion container mounts `/var/run/docker.sock`, which is why this stays opt-in. That container is root-equivalent on the host. The Mem container itself never gets socket access. * **Remote Install is a deliberate opt-in.** Checking for updates always works from the web UI, but Download and Install are loopback-only until `NOWLEDGE_ADMIN_REMOTE_OPS=1` is set. `auto-update enable` sets that flag for you, because clicking Install from a browser is a server-side state change. Only enable this on a trusted network. * Every Install takes a snapshot of `./data` and `./config` into `./cache/_pre-upgrade-.tar.gz` before recreating the container. The last three snapshots stay on disk. If the new image fails to come up, the web UI shows the snapshot path so you can SSH in and run `./nmemctl import --force` to restore the previous state. ```bash ./nmemctl auto-update status # current state, last pull, retained snapshots ./nmemctl auto-update rotate # rotate the updater token ./nmemctl auto-update upgrade # bump the companion container's image ./nmemctl auto-update disable # remove the companion container; keep the snapshots ``` ## Full operator notes [#full-operator-notes] For the complete operator contract (every environment variable, security hardening details, the device-identity invariant, troubleshooting recipes), see [`community/docker/README.md`](https://github.com/nowledge-co/community/tree/main/docker) in the community repository. ## Related [#related] * [Installation](/docs/installation): The desktop app path, which is what most users want. * [Linux Server Deployment](/docs/server-deployment): `.deb` install with a systemd unit, for Linux servers where you'd prefer apt-managed updates over containers. * [Back Up, Export, and Import](/docs/data-portability): Application-level export format and restore flow. * [Remote Access](/docs/remote-access): Access Anywhere keys, API access, multi-device sync. Applies identically to the Docker deployment. * [LLM Providers](/docs/llm-providers): Required for background intelligence (daily briefings, insights, graph enrichment). * [Troubleshooting](/docs/troubleshooting): Common operator issues, including the headless container path. # Use Nowledge Mem with fully local models (/docs/fully-local-models) Nowledge Mem can keep both your knowledge and the model calls that process it on your own machine. A local inference server such as LM Studio or Ollama exposes a loopback endpoint; Mem sends requests to that endpoint instead of a cloud model provider. This guide gives you a practical first setup, a way to verify it, and the boundaries you need to check before calling the whole workflow fully local. The content processing you enable, including memory organization, agent responses, embeddings, and optional vision or OCR, must call only built-in models or endpoints on the same machine. No content is sent to a cloud model, and a local failure must not silently fall back to one. Changing only the model used for memory processing does not, by itself, prove that every enabled workflow is local. ## Local AI beyond the Mac since version 0.10 [#local-ai-beyond-the-mac-since-version-010] Since version 0.10, Nowledge Mem's zero-Python local runtime has covered desktop and headless Linux deployments. Official Docker images include a CPU build plus opt-in CUDA and Vulkan builds. You can run Mem on personal hardware or on your own Linux server. The bundled Gemma 4 model is multimodal. Vision is the part integrated today: Library uses it for scanned PDFs, text in images, and other documents that need visual understanding. The underlying model also provides a foundation for audio, but production audio routing, PII filtering, and audio-meeting processing remain future directions rather than features delivered by this page today. Beyond the model bundled with the app, Nowledge Mem gives [Lemonade](https://lemonade-server.ai/), Ollama, and LM Studio first-class local-provider support. Special thanks to community contributor and power user [abn](https://github.com/abn), who did substantial work on the Lemonade integration. ## Before you start [#before-you-start] You need: * Nowledge Mem running in local desktop or local-server mode * A local inference server, such as [Lemonade](https://lemonade-server.ai/), [LM Studio](https://lmstudio.ai/), or [Ollama](https://ollama.com/) * A chat model loaded by that server * Enough memory for the model and the rest of your daily applications Lemonade's default OpenAI-compatible endpoint is `http://127.0.0.1:13305/v1`, LM Studio's is `http://127.0.0.1:1234/v1`, and Ollama's is `http://127.0.0.1:11434/v1`. If Mem and the model server run in different containers or on different machines, use an address that Mem can reach; inside a container, `127.0.0.1` refers to that container itself.
## Start the local model server [#1-start-the-local-model-server] Load a model in Lemonade, LM Studio, or Ollama, start the local server, and confirm that its OpenAI-compatible `/v1` endpoint is running. Verify that the server reports at least one model: ```bash # Lemonade curl http://127.0.0.1:13305/v1/models # LM Studio curl http://127.0.0.1:1234/v1/models # Ollama curl http://127.0.0.1:11434/v1/models ``` The model ID returned here is the value you should use in Mem. Do not guess it from the model's display name.
## Add the provider in Mem [#2-add-the-provider-in-mem] 1. Open **Settings → Providers**. 2. Add **Lemonade**, **LM Studio**, or **Ollama**. 3. Enter the loopback URL and the exact model ID reported by the server. 4. Leave the API key empty unless your local server requires one. 5. Test the connection, then save the provider. If you use another local runtime, add an **OpenAI-compatible custom endpoint**. It must implement Chat Completions or the Responses API format you select.
## Route every enabled model purpose [#3-route-every-enabled-model-purpose] Provider setup and workload routing are separate. In the Providers screen, check each purpose: | Purpose | Fully local choice | What it affects | | ---------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | | **Default** | Your local provider | The model inherited by any purpose set to "Same as default" | | **Agents** | Your local provider, or "Same as default" when Default is local | Background Intelligence, AI Now, Timeline, the browser-extension agent, and other agent workflows | | **Embedding** | **Built-in local** | Search indexing and vector retrieval | | **Vision / OCR** | Built-in local vision or a local vision-capable provider; otherwise leave those workflows unused | Image understanding and OCR requests used by Library | Keeping **Embedding** on **Built-in local** is the simplest local setup. If you switch to a different embedding model or dimension, follow the reindex prompt before judging search results. If an external local model cannot process images, do not assign it to Vision or OCR and assume those features are covered. Use the built-in local vision model, another local vision-capable model, or keep image workflows disabled. Check the route again whenever you enable a new enrichment feature.
## Verify the setup [#4-verify-the-setup] Use a small, observable test: 1. Disconnect or disable every cloud provider in **Settings → Providers**. 2. Keep the local inference server's request log visible. 3. Create a test memory with one durable preference and one piece of temporary noise. 4. Run the relevant Background Intelligence action, then ask AI Now to retrieve the durable preference. 5. Confirm that requests appear only in the local server log and that the result is saved or returned as expected. 6. Stop the local server and repeat once. The action should fail visibly; it should not succeed through a cloud fallback. Success means the local server handled the request, Mem produced the expected output, and no remote provider was used.
## Model sizing: one user's Apple Silicon benchmark [#model-sizing-one-users-apple-silicon-benchmark] Community member [Versun](https://x.com/VersunPan) tested three 4-bit models on a Mac mini with an M4 Pro and 64 GB of unified memory. All three passed the same controlled memory-organization task three times. The differences were mainly latency and memory use, not a broad measure of intelligence. | Model | Cold load | Resident memory task | Long-input TTFT | LM Studio total peak RSS | | ------------------- | --------: | -------------------: | --------------: | -----------------------: | | Gemma 4 12B GGUF | 3.82 s | 7.38 s | 36.79 s | 10.65 GiB | | Gemma 4 26B-A4B MLX | 8.17 s | 2.68 s | 13.83 s | 17.69 GiB | | Qwen3.6 35B-A3B MLX | 11.55 s | 2.64 s | 9.87 s | 17.72 GiB | His practical choices were: * **Under 32 GB:** the 12B GGUF model leaves more room for other applications. * **Between 32 and 64 GB:** the 26B-A4B MLX model is a safer balance. * **64 GB and a resident model:** the 35B-A3B MLX model gave the best overall latency in this test. * **Frequent load and unload:** the 26B-A4B model had the lower combined load-plus-task time. These results come from one machine, one runtime version, and one fixed prompt. Shared memory pages can also make summed RSS larger than the exact reduction in free system memory. Treat the table as a sizing reference, then test your own workload. Read [Versun's original Chinese benchmark](https://x.com/VersunPan/status/2077967423689707679) or the [formatted republication on the Nowledge Labs blog](https://nowledge-labs.ai/zh/blog/nowledge-mem-local-model-benchmark). ## Privacy boundaries to review [#privacy-boundaries-to-review] A local model endpoint keeps inference local, but other product features can still use the network: * Sync and remote access send the data required for those features to the service you configured. * Browser connectors and imports fetch content from their source services. * Updates, sign-in, and external links may contact their respective services. * A custom endpoint on another device is self-hosted, but it is no longer on the same machine. If your requirement is an offline machine rather than simply local inference, disable sync and remote providers, disconnect the network, and rerun the verification above. ## Troubleshooting [#troubleshooting] ### Mem cannot list models [#mem-cannot-list-models] Confirm that the model server is running and that the URL ends in `/v1`. Use `curl` against `/v1/models` before debugging Mem. ### The connection works, but agent tasks fail [#the-connection-works-but-agent-tasks-fail] The model may not support the chat or tool-calling behavior used by that workflow. Try a stronger instruction model and verify that **Agents** points to it. ### The first request is much slower [#the-first-request-is-much-slower] That is usually a cold load. Keep the model resident if your runtime and available memory allow it. Measure cold-load time separately from steady-state requests. ### Search changed after switching embeddings [#search-changed-after-switching-embeddings] Embedding vectors from different models or dimensions are not interchangeable. Complete the requested reindex and test search again. Next, see [LLM Providers](/docs/llm-providers) for provider-specific settings and context-window guidance. # Getting Started (/docs/getting-started) Save one real memory in the Timeline and confirm you can find it again. If you have not picked a path yet, read [Start Here](/docs/start-here) first. ## The Timeline [#the-timeline] Open Nowledge Mem. You see one input and a timeline below it. Nowledge Mem Timeline ### Save a thought [#save-a-thought] Type a decision, an insight, anything worth keeping. Hit enter. Nowledge Mem handles the rest: title, key concepts, graph connections. You just write. Open the Graph view later and you'll see it already linked to related memories. ### Ask a question [#ask-a-question] Type a question: *"What did I decide about authentication last month?"* The answer comes from **your own knowledge**: not the internet. Every question searches your full memory and synthesizes an answer from what you've written and saved. ### Drop a URL or file [#drop-a-url-or-file] Paste a URL. The page gets fetched, parsed, and stored as a searchable source. Drop a PDF, a Word doc, a presentation. Same treatment. Each input grows your knowledge base. Nowledge Mem Timeline ## Your First Win [#your-first-win] Before you connect any AI tool, prove the loop in the app itself: 1. Save one memory 2. Ask for it back 3. Confirm the answer reflects your own knowledge If you want a concrete verification checklist, use [How To Know Mem Is Working](/docs/verify-it-works). ## Bring in conversations you already have [#bring-in-conversations-you-already-have] If you are not starting from an empty slate (**coding assistant logs on disk**, **ChatGPT / DeepSeek / ChatWise / Alma exports**, or **one saved `.md` thread**), use **[Import existing conversations](/docs/import-existing-conversations)**. There you get Threads → Import spelled out: disk scans, **bulk** vendor files, **single** files, and the extension on the **tab you have open** (not your full web chat history in one shot). ## Connect Your First Tool [#connect-your-first-tool] Do not start by picking a tool from a long list. Give your AI tool one prompt and let it choose the best supported setup path: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for the AI tool I am using. ``` Paste this into Claude Code, Grok Build, Codex, Cursor, Gemini CLI, Copilot CLI, OpenClaw, Hermes, Droid, Alma, Bub, Pi, OpenCode, or Claude Desktop. The agent fetches the install contract, detects which host it is in, uses the matching setup path, verifies the connection with `nmem status`, and asks you to restart the host when needed. Command-line hosts can usually be installed directly. App-based hosts may still require a user-confirmed marketplace step. Pick the AI tool you actually use most. Run the prompt there. Restart that tool. Stop. Adding more tools later is the same one-prompt gesture each time. ### Remote or cross-device setup [#remote-or-cross-device-setup] If Mem runs on the same machine as the AI tool, the generic prompt above is enough. If the AI tool runs on another machine, or if you are using a managed or self-hosted remote Mem server, configure the shared client settings first: ```bash nmem config client set --url https://your-mem-server.example --api-key nmem_... ``` In the desktop app, remote URL and key controls live under **Settings → Access Anywhere**. ### When the prompt does not fit [#when-the-prompt-does-not-fit] A small set of surfaces install differently: * **Web chat (ChatGPT, Claude.ai, Gemini, NotebookLM, Poe)**: install the [Browser Extension](/docs/integrations/browser-extension) from the Chrome Web Store and open the side panel. * **Raycast**: install from the Raycast Store. See [Raycast](/docs/integrations/raycast). * **Trajectory extractors (Windsurf, Antigravity)**: external CLIs that export sessions for one-time import. See [Import existing conversations](/docs/import-existing-conversations). For per-tool behavior reference once the connect is done (skills, recall strategy, distillation), see the individual connector pages. The connect itself is one prompt. ## Other Ways Content Reaches Mem [#other-ways-content-reaches-mem] * **Existing chats (map first)**: [Import existing conversations](/docs/import-existing-conversations): coding agents on disk, vendor exports, single files, and the extension on the tab you are using * **Web chat (current tab)**: the [browser extension](/docs/integrations/browser-extension) saves the session you work with in the panel, not a full account export (use bulk import for that) * **Thread formats (reference)**: [Threads](/docs/threads) for Markdown rules and bulk file specifics * **Manual**: create memories in the Memories view with **+ Create**, or from any terminal with `nmem m add` ([CLI reference](/docs/cli)) ## What to Try [#what-to-try] Once you have a few memories saved, try these in the Timeline: **"Which of my ideas have evolved the most?"** Finds ideas that went through multiple revisions and tells the story chronologically. **"Summarize my recent coding conversations"** If your coding conversations are already flowing into Mem through auto-sync, native save paths, or imports, this lists and summarizes your latest sessions. **"Search my documents for \[topic]"** Full-text search across everything in your Library: PDFs, spreadsheets, code files, anything you dropped in. These get more powerful as your knowledge grows. After a month, the results will surprise you. ## Next Steps [#next-steps] * **[Start Here](/docs/start-here)**: Pick the first path that matches your real workflow * **[Using Nowledge Mem](/docs/usage)**: Daily workflow, search, and how your knowledge grows * **[How To Know Mem Is Working](/docs/verify-it-works)**: Verify the app loop and connected tools * **[Memories](/docs/memories)**: Atomic knowledge you can search, connect, and evolve * **[Import existing conversations](/docs/import-existing-conversations)**: Map every import path in one page * **[Threads](/docs/threads)**: Formats, import UI, and distillation * **[AI Now](/docs/ai-now)**: Personal AI with full access to your knowledge base * **[Connectors](/docs/integrations)**: Connector reference for each AI tool # Import existing conversations (/docs/import-existing-conversations) Mem can bring in prior chats in three ways: **coding agents we discover on disk**, **files you export from an app**, and **the browser extension on the tab you are looking at**. This page matches those options to the buttons in **Threads → Import** (and **Connectors → Thread Import**). Bulk filenames, Markdown headers, and odd edge cases live in **[Threads](/docs/threads)**. ## Pick what matches you [#pick-what-matches-you] | You have… | In Mem | Notes | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | | **Claude Code, Cursor, Codex, or OpenCode** logs on disk | **Threads** → **Import** → **Find AI Conversations** (same entry under **Connectors → Thread Import**) | Pick sessions after Mem scans | | Older local sessions from **Antigravity, Claude Code, Grok Build, Codex, Craft Agent, Gemini CLI, Kimi Code, Kimi Work, MiMo Code, OpenCode, OMP, or Pi**, especially when Mem runs on another machine | Run `nmem t sync --from ...` on the machine where that agent stores its sessions | Preview first; add `--apply` when the list looks right | | A **full export** from ChatGPT, **Google Gemini / AI Mode**, **Claude** (claude.ai / Claude Desktop), DeepSeek, ChatWise, Alma, or **Raycast AI** (via exporter JSON) | **Threads** → **Import** → **Bulk Import** | One file (see table below) | | **One** `.md` thread or similar | **Threads** → **Import** → **Single Thread** | See [Single thread](/docs/threads#single-thread) | | A chat **open in the browser right now** | [Browser extension](/docs/integrations/browser-extension) | Sends the **focused** session from the tab you use with the extension, not your full account history |
## Coding agents (disk) [#1-coding-agents-disk] **Find AI Conversations** looks for local session data from Claude Code, Cursor, Codex, and OpenCode. Nothing is saved until you choose what to import. Plugins can also keep threads in sync over time; this scan is mainly for **catching up** (new machine, or first setup). For connector history that is not listed in the desktop scanner, use the CLI backfill path. Supported sources today are `antigravity`, `claude-code`, `grok`, `codex`, `craft-agent`, `gemini-cli`, `kimi-code`, `kimi-work`, `mimo-code`, `opencode`, `omp`, and `pi`. ```bash # Project-scoped coding agents nmem t sync --from codex --all-projects --limit 20 nmem t sync --from craft-agent --all-projects --limit 20 nmem t sync --from grok --all-projects --limit 20 # Pi sessions nmem t sync --from pi --limit 20 # Other local coding-agent stores nmem t sync --from antigravity --limit 20 nmem t sync --from kimi-code --limit 20 nmem t sync --from kimi-work --limit 20 nmem t sync --from mimo-code --limit 20 nmem t sync --from omp --limit 20 ``` The first run is a preview. Replace `codex` with another supported source when needed. When the list looks right, run the same command with `--apply`. Current Antigravity CLI and Antigravity 2.0 sessions keep a documented local `transcript.jsonl`, which `nmem t sync --from antigravity` reads directly. The command imports only user and assistant turns and keeps the original conversation ID, so it converges with live capture instead of creating a second thread. Some older sessions exist only in Antigravity's private cache. For those, use the [Antigravity Trajectory Extractor](https://github.com/jijiamoer/antigravity-trajectory-extractor) while Antigravity is running, export JSON, then preview it with `nmem t sync --from antigravity --session-dir `. Mem does not guess at private protobuf or database formats. Run `nmem t sync` on the laptop or server where the AI tool keeps its session files. The command uses your normal `nmem` client config, so it can upload to local Mem or a remote Mem server. The remote server does not need direct access to your `~/.codex`, `~/.craft-agent`, `~/.grok`, `~/.claude`, `~/.gemini`, `~/.kimi-code`, Kimi Work runtime, `~/.pi`, `~/.omp`, OpenCode, or MiMo Code data.
## Export files (bulk) [#2-export-files-bulk] **Bulk Import** expects the real export each vendor hands you: | App | File | Export | | -------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ChatGPT** | `chat.html` (inside their ZIP) | Settings → Data controls → Export data | | **Google Gemini Apps / AI Mode** | The Takeout ZIP, or `MyActivity.html` after you extract it | [takeout.google.com](https://takeout.google.com) → **Deselect all** → **My Activity** → **All activity data included** → select **Gemini Apps** or **AI Mode** → export. Do **not** select the top-level **Gemini** checkbox; that is for Gems settings, not chat history. | | **Claude** | `data-…-batch-….zip` (contains `conversations.json` + `memories.json`) | Web or Desktop: initials → **Settings** → **Privacy** → **Export data**, then Anthropic emails a download link (see [their guide](https://support.claude.com/en/articles/9450526-how-can-i-export-my-claude-data)). Not available from Claude mobile apps. | | **DeepSeek** | `deepseek_conversations.json` | chat.deepseek.com → Settings → Data → Export data | | **ChatWise** | `.zip` of chats | Export all chats from ChatWise | | **Alma** | `alma-backup-…zip` with `threads.json` | Settings → Data → Export all threads | | **Raycast AI** | `raycast_ai_chats.json` (or any `.json` from the tool) | No built-in export, so use **[raycast-ai-exporter](https://github.com/daveonkels/raycast-ai-exporter)** (macOS; see its README) | Drop the file in as downloaded; Mem figures out the format. For Gemini and AI Mode, Google stores the chat text in **My Activity**, not in the top-level Gemini export. You can upload the full Takeout ZIP, or extract it and upload `Takeout/My Activity/Gemini Apps/MyActivity.html` or `Takeout/My Activity/AI Mode/MyActivity.html` directly. Imported conversations are searchable right away as Threads. Mem does not automatically turn every imported conversation into Memories, because a large archive can spend a lot of AI tokens and produce noisy results. Start by searching the imported threads; distill only the decisions, facts, procedures, or lessons you want to keep as long-term memory. When you do want to process a backlog, go to **Threads**, click **Select**, choose the current page or **Select all results**, then click **Plan distillation**. Mem plans a small safe wave instead of queuing hundreds of conversations at once; very large threads are deferred for a separate pass. Use the **ZIP** from the email (for example `data-2026-04-01-08-10-35-batch-0000.zip`). Mem imports **all chats** from `conversations.json` and saves Claude's **profile memory** from `memories.json` as a labeled memory card after the threads you selected finish importing. If you only extract `conversations.json`, you get threads only. The exporter is a third-party script: you keep Raycast’s **AI Chat** window open, grant **Accessibility** to your terminal, and it writes structured JSON (sessions with `role` / `content` messages). Dates in the file are **approximate** (sidebar groupings). Same JSON works in **Bulk Import** and `nmem t import --file`.
## Browser: focused tab only [#3-browser-focused-tab-only] The extension does **not** download your entire web chat history. It works with the **session in the active tab** when you capture, useful for what you are doing **now**. For **everything the provider ships in one archive**, use **Bulk Import** (or your coding-agent scan where that applies).
## One file [#4-one-file] **Single Thread** is for conversation Markdown, Cursor exports, and other single-file flows; details in **[Threads](/docs/threads#single-thread)**.
## Where to click [#where-to-click] * **Threads** → **Import**: Find AI, Bulk, Single. * **Connectors** → **Thread Import**: same story, plus shortcuts into **Threads**. ## Next [#next] * **[Threads](/docs/threads)**: formats and distillation * **[Getting Started](/docs/getting-started)**: first day in the app * **[Connectors](/docs/integrations)**: AI tools, MCP, extension # Nowledge Mem (/docs) Your AI tools do not remember your work for you. Nowledge Mem does. 0.10.0 rebuilds the core engine in native Rust: faster and lighter on every platform, now running natively on Windows and Linux, reading images on-device, and able to use your GPU. The download is roughly a quarter the size and uses about a third less memory. See the [changelog](/changelog) for what is live and what is rolling out. It is your memory layer for AI work. Save a decision, an insight, a useful source, or a conversation. Mem makes it searchable, connects it to what you already know, and lets the tools you connect start from the same context. You do not need to wire everything at once. Save one thing, find it again, then let one real tool use it. Once that loop works, Mem becomes much easier to understand. If you want to use Mem across multiple devices, that is now supported too: run one Mem on an always-on machine, then connect your desktop, web, mobile, and supported tools to that same knowledge base. See [Sync Across Devices](/docs/sync). If you're new here, the shortest path is: 1. [Install the app](/docs/installation) 2. [Save your first memory](/docs/getting-started) 3. Connect any AI tool with one copy-paste, see [Start Here](/docs/start-here) 4. [Confirm Mem is actually working](/docs/verify-it-works) The connect step starts with one prompt: *"Read [https://mem.nowledge.co/SKILL.md](https://mem.nowledge.co/SKILL.md) and follow the instructions to install or update Nowledge Mem for the AI tool I am using."* Paste it into Claude Code, Grok Build, Codex, Cursor, Gemini CLI, Copilot CLI, OpenClaw, or another supported host. Command-line hosts can usually install directly; app-based hosts may ask you to confirm a marketplace step.
Start Here
The shortest useful path for a new user: save one memory, choose one tool path, and verify it works.
Use Any Tool, Lose Nothing
Connect one real tool first. The same memories can then flow across Claude Code, Grok Build, Cursor, Codex, ChatGPT, Grok Web, and more.
It Learns While You Sleep
The system discovers connections you missed, flags contradictions in past decisions, and writes a morning briefing so your AI tools know what you're working on before you say a word.
Everything Connected
Your knowledge forms a graph. Search by meaning, browse visually, or discover connections you didn't know existed.
Knowledge Tree Preview
Browse memories, conversations, wiki pages, working memory, activities, sources, and artifacts in one tree. Agents and scripts use the same layer as Nowledge FS.
Own Your Data
Export a portable, text-based snapshot for backup or migration, then import it later without being locked to one machine.
## Connect Any AI Tool [#connect-any-ai-tool] Paste this into your AI tool. The agent reads it, detects the host, uses the right setup path, verifies Mem, and tells you what changed: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for the AI tool I am using. ``` This works in Claude Code, Grok Build, Codex, Cursor, Gemini CLI, Copilot CLI, OpenClaw, Hermes, Droid, Alma, Bub, Pi, OpenCode, and Claude Desktop. For remote or cross-device access, configure the shared client settings with `nmem config client set --url ... --api-key ...`; in the desktop app, remote URL and key controls live under **Settings → Access Anywhere**. For per-tool behavior reference (skills, recall strategy, distillation), the individual connector pages still apply once the connect is done: Native connector with automatic briefing, recall, and session capture Native connector for the coding agent, with startup context, hooks, and session capture Native connector with Working Memory, routed recall, and clear handoff behavior Native extension with commands, hooks, and real session save Native connector with bundled MCP, AGENTS guidance, and automatic Codex thread capture Native connector with startup context, recall guidance, and session capture Full plugin guide for lifecycle capture, recall, and distillation One-click extension for search, save, and memory updates Capture conversations from supported web AI chat platforms ## Import Your Documents [#import-your-documents] Drop a PDF, Word doc, or presentation into the Library. It gets parsed and indexed alongside your memories. When you ask a question in the Timeline, the answer draws from both. ## Local-First Privacy [#local-first-privacy] Nowledge Mem is local-first. Your knowledge lives on your device by default. You can connect a remote LLM when you want stronger processing, but your data never touches Nowledge servers. For backup or one-time migration, use [Back Up, Export, and Import](/docs/data-portability). Mem exports a portable, text-based bundle so your knowledge stays under your control. The first page to read after installation Get started in minutes Your first five minutes Fast checks for search, capture, and connected tools # Installation (/docs/installation) Nowledge Mem can be downloaded directly: * **Download**: open the [download page](/download) for macOS, Windows, and Linux builds * **Manage access**: sign in at [mem.nowledge.co/licenses](https://mem.nowledge.co/licenses) for Lifetime License devices and receipts Do not configure everything at once. After the app opens, go to [Start Here](/docs/start-here), save one memory in the Timeline, and choose only one connection path for the tool you actually use. ## System Requirements [#system-requirements] Minimum system requirements: | Requirement | Specification | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | **Operating System** | macOS 15 or later
Windows 10 or later
Linux x86\_64 (Ubuntu 22.04+, Debian 12+, or AppImage for other distros) | | **Memory (RAM)** | 16 GiB minimum | | **Disk Space** | 10 GiB available | | **Network** | If using a proxy, ensure it bypasses `127.0.0.1` and `localhost` | **Linux headless servers** are also supported. See the **[Linux Server Deployment](/docs/server-deployment)** guide to run Nowledge Mem on servers without a desktop environment. **GPU acceleration.** On a Mac with Apple Silicon, on-device work (local search and the built-in model) uses the GPU automatically through Metal, with nothing to set up. On Windows and Linux the desktop app runs on the CPU, which is the right choice for almost everyone. If you want GPU acceleration on a server or workstation, run Nowledge Mem with Docker: the CUDA image (NVIDIA) and the Vulkan image (AMD and Intel) are described in **[Docker Deployment](/docs/docker)**. ## Installation Steps [#installation-steps] ## Step 1: Install the Application [#step-1-place-app] Drag Nowledge Mem to your `/Applications` folder. Nowledge Mem requires the **Microsoft Visual C++ Redistributable** to run on Windows. If you haven't installed it yet, download and run the installer first: Download the Windows installer from [mem.nowledge.co/licenses](https://mem.nowledge.co/licenses) and run it. Future updates install automatically from within the app, so there is no need to download again. The Microsoft Store version has been discontinued. If you previously installed Nowledge Mem from the Store, uninstall it first via **Settings → Apps → Nowledge Mem → Uninstall**, then install the version linked above. Your data is preserved; only the app binary is replaced. Install via the APT repository for automatic updates, or download the `.deb` / `.AppImage` directly. For terminal downloads, use the commands below as written. They include a browser User-Agent because some download endpoints return `403` to plain `curl` / `wget` requests. If this machine is a headless Linux server, use the APT or `.deb` path and then follow [Linux Server Deployment](/docs/server-deployment). AppImage is a portable fallback, not the main server setup path. One-line setup that adds the GPG key and repository, then installs: ```bash curl -fsSL https://nowledge-co.github.io/community/apt/install.sh | sudo bash sudo apt-get install nowledge-mem ``` Future updates arrive automatically via `sudo apt-get upgrade`. ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # Download the latest .deb curl -A "$BROWSER_UA" -L -o nowledge-mem.deb https://nowled.ge/download-mem-deb # Install sudo dpkg -i nowledge-mem.deb sudo apt-get install -f # fix any missing dependencies ``` ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # Download the latest AppImage curl -A "$BROWSER_UA" -L -o nowledge-mem.AppImage https://nowled.ge/download-mem-appimage # Make it executable and run chmod +x nowledge-mem.AppImage ./nowledge-mem.AppImage ``` This does not install the `nmem` CLI into your PATH. For server use, prefer APT or `.deb`. ## Step 2: Launch the Application [#step-2-first-boot] Double-click the Nowledge Mem icon in your Applications folder to launch the app for the first time. If the app takes too long to start or shows errors: * **Service timeout**: If you see "It took too long to start the service", this usually means a global proxy is preventing access to `localhost`. Disable your proxy and try again. * **macOS version**: Ensure you're running macOS 15 or later. Older versions are not supported. * **Need more help?** Check the [Troubleshooting Guide](/docs/troubleshooting) to view logs and get detailed diagnostics. You can share logs with our community or email support for assistance. After installation, launch Nowledge Mem from the Start menu. Search for "Nowledge Mem". If the app takes too long to start or shows errors: * **Missing Visual C++ Runtime**: If you see `DLL load failed` or the app exits on startup, install the [Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe) and restart the app. See [Troubleshooting](/docs/troubleshooting#windows-missing-visual-c-runtime) for details. * **Service timeout**: If you see "It took too long to start the service", this usually means a global proxy is preventing access to `localhost`. Disable your proxy and try again. * **Need more help?** Check the [Troubleshooting Guide](/docs/troubleshooting) to view logs and get detailed diagnostics. You can share logs with our community or email support for assistance. Launch Nowledge Mem from your application menu, or run it from the terminal: ```bash nowledge-mem ``` If the app takes too long to start or shows errors: * **Service timeout**: If you see "It took too long to start the service", this usually means a global proxy is preventing access to `localhost`. Disable your proxy and try again. * **Missing libraries**: If you see `libwebkit2gtk` errors, install the dependencies: `sudo apt-get install libgtk-3-0 libwebkit2gtk-4.1-0 libayatana-appindicator3-1` * **Need more help?** Check the [Troubleshooting Guide](/docs/troubleshooting) to view logs and get detailed diagnostics. ## Step 3: Install The Required Models [#step-3-download-models] After launching Nowledge Mem, install the models the app asks for (approximately 2.4GB total): * **Apple Chip Mac**: On-device LLM is supported. * **Windows**: Remote LLM is required. * **Intel Mac**: Remote LLM is required. * **Linux**: Remote LLM is required.
### Check notifications [#check-notifications-step] You'll see download prompts in the top-right corner of the app
### Navigate to models [#navigate-to-models-step] Click the notification button, or go to **Settings** → **Models**
### Install models [#install-models-step] Click **Install** on the model card the app prompts you to download LLM Model Install The download will begin automatically, and you can monitor the progress: LLM Model Install Progress Depending on your internet connection, the download may take 5-15 minutes. The models only need to be downloaded once.
## Optional: Install The Browser Extension [#step-4-browser-extension] The **Nowledge Mem Exchange** browser extension is optional. Install it if you want to capture insights and thread backups from supported web AI chat platforms. After installing, click the extension icon to open the side panel or sidebar. Configure your LLM provider in **Settings** to enable auto-capture. ChatGPT, Claude, Gemini, NotebookLM, Microsoft Copilot, Perplexity, DeepSeek, Kimi, Qwen, POE, Manus, Grok, and more. The extension can capture valuable insights and full thread backups from supported sites. See the [Browser Extension guide](/docs/integrations/browser-extension) for details. ## After Installation [#after-installation] Installing the app gives you the memory system itself. The next step is not "configure everything." It is to prove one real workflow: 1. Save one memory in the Timeline 2. Choose one path that matches the tool you already use 3. Confirm it works before adding anything else For most people, the three main paths are: * Use a **dedicated connector** when your tool has one: Claude Code, Grok Build, Codex, Gemini CLI, OpenClaw, Hermes Agent, Alma, Cursor, Droid, OpenCode, Copilot CLI, Pi, or Bub * Use the **browser extension** if your work mostly happens in ChatGPT, Claude, Gemini, Microsoft Copilot, or other supported web chats * Use the app itself first if you want to learn Mem before wiring external tools Everything else, reusable packages, `nmem` CLI, and direct MCP, is secondary unless your tool actually needs it. If you already know you want one always-on Mem and several connected devices, read [Sync Across Devices](/docs/sync) first, then follow [Access Anywhere](/docs/remote-access) for setup. ## Mobile Apps (Preview) [#mobile-apps-preview] Native iOS and Android apps are available as preview clients. They connect to your desktop Mem through [Access Anywhere](/docs/remote-access): your data stays on your main machine, and the mobile app gives you search and capture on the go. * **iOS**: [Join the TestFlight](https://nowled.ge/mem-ios) * **Android**: [Download the APK](https://nowled.ge/mem-android) Both require a running desktop Mem with Access Anywhere enabled. ## Next Steps [#next-steps] * **[Start Here](/docs/start-here)**: The shortest path for new users * **[Getting Started](/docs/getting-started)**: Your first five minutes with the Timeline * **[How To Know Mem Is Working](/docs/verify-it-works)**: Verify search, capture, and tool connections * **[Connectors](/docs/integrations)**: Connect Claude Code, Grok Build, Codex, Cursor, and other AI tools * **[Sync Across Devices](/docs/sync)**: Understand the single-Mem, multi-client sync model * **[Linux Server Deployment](/docs/server-deployment)**: Run headless on a Linux server # Knowledge Graph (/docs/knowledge-graph) Everything you save in Mem lives on one [Super Knowledge Graph](https://nowledge-labs.ai/blog/building-memory-systems-for-ai-agents#heading-11): three knowledge forms (Trace, Unit, Crystal) on top of seven node types and eleven edge types, designed for *progressive disclosure*. Light queries first. Walk relationships when you need more context. Walk the version chain when you need history. Look at communities and Crystals when you want the big picture. The Knowledge Graph view is where that graph stops being a metaphor and becomes something you can pan, click, and ask questions of. **Graph Intelligence** is the agent that shares the canvas with you. You select; it reasons. You ask; the graph highlights. The conversation produces durable artifacts: Crystals, reports, persisted exploration sessions. The Library answers *what do I know?* The Knowledge Graph answers *how does it connect, and what should I do with it next?* ## First useful action [#first-useful-action] 1. Open the **Graph** view from the sidebar. The overview shows your most-connected memories, entities, and Crystals. 2. Click any node, or run **Compute** to detect topic communities and color the graph by cluster. 3. When two Memory nodes should be read together, use **Connect memories** to create a [Memory Link](/docs/concepts/memory-links): name the relation, add a reason, and keep that connection in the graph. 4. Open the **Chat** tab in the right panel and ask one real question about what you're looking at. *"What is this cluster about?"* *"Where does this contradict itself?"* *"Find the shortest path between these two."* The agent reads your selection, calls the right tools, and writes the answer on the same canvas. You should be able to answer a real question about your own knowledge without leaving the graph.
## Two ways to use the graph [#two-ways-to-use-the-graph] ### Visually, on your own [#visually-on-your-own] Your knowledge as an interactive network. Drag to pan, scroll to zoom, click a node to inspect its details and edges. The timeline slider filters by date so you can watch a domain grow over weeks or months. Hold Cmd/Ctrl to multi-select; switch to lasso mode to draw a region. **Compute** runs Louvain community detection and colors the graph by cluster, so the topic structure becomes visible instead of buried under 1,000 dots. When you spot a relationship the system should remember, connect two Memory nodes directly. That edge becomes part of the graph, not just a note in your head. The overview also renders in 3D — orbit the whole graph like a terrain, with communities as constellations and influence as elevation:
### With the Graph Intelligence Agent [#with-the-graph-intelligence-agent] The Chat tab opens a reasoning partner that shares your canvas. When you select something, the agent reads the same selection. Its tool calls light up the graph in real time, so you can audit its reasoning while it works. Useful question patterns: * Ask *"What is going on here?"* with a community selected. The agent summarises the cluster's central themes and hands you back a list of the strongest sources. * Ask *"Where does this contradict itself?"* with a topic, entity, or memory selected. The agent walks the EVOLVES chain and surfaces the disagreements. * Multi-select two nodes and ask *"Find the shortest path between these two."* The agent walks the graph and explains every hop, often via bridge entities you wouldn't have spotted. * Ask *"Draft a brief from this."* with a cluster selected. The agent produces a Crystal or a report. You decide whether to keep it. ## What makes this not "AI chat with a graph backend" [#what-makes-this-not-ai-chat-with-a-graph-backend] A few architectural decisions add up to a different kind of product. **Frozen context, single source of truth.** When you send a message, the agent sees the exact graph state you were looking at. No drift, no split-brain, no state mirror to keep in sync. You move the canvas while the agent thinks; that just means the next turn picks up the new view. The conversation thread itself is the source of truth. **Visual reasoning chain.** Every tool the agent calls can emit a canvas command: `highlight_nodes`, `highlight_path`, `select_community`. You see the agent's reasoning as it happens, not as a black-box answer. If the agent says "the path goes through these three bridges", those three bridges are already lit up on the canvas. **Artifacts that fit your existing surfaces.** When the agent produces a Crystal, that Crystal is a real Memory with `is_crystal=true`. When it produces a report, that report is a real Source in the Library. There are no new entity types to learn. Anything the agent saves is searchable, linkable, and editable from the same surfaces you already know. **Step-based history.** Every turn captures both the user's frozen graph context and the agent's emitted canvas commands as message metadata. You can replay an exploration, resume it later, or share it. The conversation is not just a chat log; it is a complete record of an investigation. ## What the agent can do [#what-the-agent-can-do] Twenty or so specialised tools, grouped by what they answer for you: * **Navigate the graph.** Shortest paths between concepts, walks across `RELATES_TO` edges with their temporal context, batch-lookup of selected node details, neighbor traversal, community membership. * **Find evidence.** Source memories behind a Crystal or entity, the EVOLVES chain showing how a piece of knowledge changed, the source documents that ground a claim, the past threads where you explored a topic. * **Analyze structure.** Subgraph PageRank for centrality, bridge entities that connect communities, community summaries with member counts and key entities. * **Synthesize and save.** A Crystal that distils 3+ source memories into a stable reference page (with `[[Entity Name]]` wikilinks already woven in), or a longer report or blog draft that lands in the Library and re-enters the search index. You don't pick the tool; you ask the question and the agent picks. What we expose to you is the discipline: every claim it makes is traceable to memories, sources, or threads you can open. Crystals require three or more independent sources. Reports cite their evidence. ## From the Library, with Investigate [#from-the-library-with-investigate] Most of the time you won't start in the Graph view. You'll be reading the [Library](/docs/library) when something raises a real question. Click **Investigate** on any wiki page (entity, crystal, or topic). The Graph view opens with that node already selected, or, for a topic, with every entity in the cluster highlighted at once. The Graph Intelligence chat shows an "Investigating topic: \" banner above the input, and any Crystal it creates from that session carries the cluster as its anchor. That handoff is the loop: read in Library, dig in Graph, save back to Library. ## Boundaries [#boundaries] A few things stay out of your way on purpose. * The agent only proposes. Crystals and reports it produces show up as artifacts in chat. You decide what to keep. * The agent reads the same canvas you do. There is no hidden context. If you cannot see it, neither can the agent. * Graph Intelligence runs through your configured Remote LLM. Set it in **Settings > LLM Providers**. * A heavy run produces tokens. Background and on-demand work share separate budgets and rate limits, configurable in **Settings > Knowledge Processing**. ## Where to go next [#where-to-go-next] * [LLM Wiki](/docs/concepts/llm-wiki): the model behind the Library wiki and the Library → Investigate → Graph Intelligence loop. * [Memory Links](/docs/concepts/memory-links): how to connect two memories inside a space when they should be read together. * [Library](/docs/library): the read-side surface where most Investigate sessions begin. * [Background Intelligence](/docs/concepts/background-intelligence): the work that builds and maintains the graph in the first place. * [Crystals](/docs/concepts/crystals): how stable reference pages are synthesised, and what the agent's `CreateCrystal` actually produces. * [Building memory systems for AI agents](https://nowledge-labs.ai/blog/building-memory-systems-for-ai-agents): the long-form essay on the Super Knowledge Graph and what makes it more than a regular knowledge graph. The post also embeds the original Chinese-language talk recording. # Library (/docs/library) The Library is where your files become usable knowledge. It is for source material that should stay whole: PDFs, reports, spreadsheets, slide decks, markdown notes, and code. Mem parses them, indexes them, and lets them work alongside your memories instead of living as isolated attachments. Use the Library for source material you want to preserve whole. Use memories for the durable takeaways. A strong workflow is: import the document, ask grounded questions against it, then extract memories only when you want its knowledge to join your long-term memory graph.
Drop a 40-page architecture review into the Library. Ask in the Timeline: *"What does the review say about API rate limits?"* The answer cites page 12 of the document and a Redis decision you saved three months ago. Your documents and your memories search together. The Library stores PDFs, spreadsheets, Word files, presentations, code, and other formats. Content is parsed, split into searchable segments, and indexed. Once a document is **Searchable**, it shows up everywhere you already think from: * **AI Now**: ask about a file by name, topic, or question. AI Now searches the Library, reads matching passages, and cites them alongside your memories. * **The Timeline Feed Agent**: the built-in background Agent that turns conversations into memories can now also reach into Library documents when a thread references one. * **Graph Intelligence Agent**: when exploring your graph, Source nodes can be searched and read directly, so you can move from a cluster of related memories into the underlying document without leaving the canvas. * **Connected AI tools via MCP**: Claude Code, Cursor, and any other MCP-aware client can call `query_sources`, `read_source_content`, `search_source_chunks`, and `analyze_source_data` to ground their answers in your actual files. * **The `nmem` CLI**: terminal and script workflows can search, read, and analyze the Library with `nmem sources search`, `read`, `search-chunks`, and `analyze`. See [the CLI reference](/docs/cli). ## Reading the Library as a wiki [#reading-the-library-as-a-wiki] In v0.8 the Library also reads as a wiki. The memories, sources, and Crystals you have been collecting now show up as topic pages, entity pages, and crystal pages, cross-linked so you can click your way through them.
Switch to the **Wiki** tab inside the Library to see your knowledge grouped by topic. Each card lists the concepts most-discussed in that cluster and a few Crystals that summarise them. Click a card to open its topic page, click an entity to open its wiki entry, click an `[[Entity]]` chip inside a Crystal to keep going. When reading raises a real question, click **Investigate** on any wiki page. The Knowledge Graph opens with the right thing already selected: a single node for an entity or crystal page, the whole cluster for a topic page. From there you can pan, expand neighbours, or hand the selection to the Graph Intelligence Agent and ask what is actually going on. For the underlying model (what the system maintains for you, what you stay in charge of), see the [LLM Wiki concept page](/docs/concepts/llm-wiki). ## Wiki Export [#wiki-export] The Wiki tab has a Download button on its tab row. Click it and pick a format: Both export your **whole knowledge graph**: topics, entities, crystals, your memories grouped by type (`memories/decision/`, `memories/procedure/`, and the rest), the reports and blog drafts the agent generated, your active skills, and a label index. They differ only in flavor: * **Markdown wiki** is the Obsidian-style folder, cross-linked with the same `[[wikilinks]]` you see inside Mem. It opens directly in Obsidian, Logseq, or any markdown reader. * **OKF bundle** is the vendor-neutral version in the [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf), an open spec for knowledge as markdown files. It links with standard markdown paths instead of wikilinks, follows the spec's frontmatter, and validates against the OKF reference tools. Pick it for an interoperable copy, or to hand your knowledge to another tool that reads OKF. Both are plain markdown either reader can open, so the choice is just the link style and frontmatter. Re-export whenever you want a fresh copy. The export is a snapshot, not a sync target: edits you make outside Mem do not flow back automatically. For more on the OKF format and how the export maps onto it, see [Open Knowledge Format (OKF)](/docs/concepts/open-knowledge-format). ## The First Useful Document [#the-first-useful-document] If you are new, import one document you actually care about. Then ask one concrete question about it in the Timeline. That is the core loop: * add one real source * ask one grounded question * see the answer use both the document and your existing knowledge That is enough for a first proof. Memory extraction can wait until this basic loop already feels useful. ## Supported Formats [#supported-formats] | Format | Extensions | What Happens | | ----------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | **PDF** | .pdf | Native text is extracted with layout awareness; scanned pages can be read with a configured Vision model | | **Word** | .docx | Parsed to text with image extraction, segmented, indexed | | **Presentations** | .pptx | Slide content extracted with images, indexed | | **Spreadsheets** | .xlsx, .csv | Parsed to markdown tables, indexed. Multi-sheet XLSX renders as tabs | | **Markdown** | .md | Parsed and indexed directly | | **Plain text** | .txt, .org | Indexed as-is | | **Code** | .py, .js, .ts, .rs, .go, .java, .c, .cpp, .rb, .swift | Indexed | | **URL** | .html, .pdf | Converted to markdown, indexed | ## Adding Documents [#adding-documents] Drag files into the Timeline input, or use the Library view to import. You can also drag entire folders: all supported files inside will be imported automatically. Documents go through a processing pipeline: 1. **Parsing**: content extracted from the file format 2. **Segmentation**: split into searchable chunks 3. **Indexing**: added to both vector and keyword search indexes Processing status is visible in the Library view. Once indexed, the document is **Searchable**, ready to use in conversations, global search, and connected AI tools. ### Adding web pages [#adding-web-pages] Paste a public URL into the Timeline or Library and Mem will try to read it locally first. For many articles, docs pages, PDFs, and blogs, that is all it needs. Some modern pages block basic fetching or only return an empty app shell. If you enable **Settings → Processing → Public web fallback**, Mem can ask Firecrawl to return clean public content for those pages. This is optional, and it only applies to safe public URLs. Mem does not send cookies, browser sessions, or signed-in pages to Firecrawl. Use the browser extension for supported web AI chats. Use Browse Now with Chrome, Edge, Arc, or another Chromium browser for pages that need browser control: logged-in workspaces, private docs, paywalled pages, dashboards, or anything that only you can see. For scanned PDFs, Mem first finishes the normal import so the app stays responsive. If a page has no text layer, Mem can read the scanned text in the background with the effective Vision model and add it back into the document. Vision uses your **Default** provider unless you choose a separate model in **Settings → Providers → Vision**. Make sure the effective Vision model supports image input. If it does not, or your background budget is reached, the Library pauses the work and shows what to do next. After setting the model, return to the source and click **Continue**. ## Searchable, Study, and Extract Memories [#searchable-study-and-extract-memories] Library has three different actions: | Mode | What it means | How it happens | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | | **Searchable** | Content is parsed, segmented, and indexed. AI can read and reference the document when you ask about it in the Timeline. A document can stay searchable-only; it is not waiting for extraction. | Automatic, happens when you import a file. | | **Study with AI** | A guided reading session. The AI reads the source, compares it with existing memories, and proposes what may be worth saving. Nothing is written unless you choose to save it. | Opt-in: click **Study with AI** on a source. | | **Memories extracted** | A full extraction pass creates structured memories, graph links, and cross-references. The document's durable takeaways join your memory graph. | Opt-in: click **Extract memories** on a source. | Asking about a file in the Timeline reads its content directly. Studying a file with AI helps you decide what matters. Extracting memories turns selected knowledge into persistent graph-backed memory. ### What memory extraction produces [#what-memory-extraction-produces] When you extract memories from a source, the AI analyzes the content (computing statistics for spreadsheets, reading text for documents) and creates: * **Memories**: 2-5+ atomic insights per document (decisions, facts, procedures), each searchable on its own * **Graph connections**: links to your existing related memories, surfacing relationships you might not have noticed * **Crystals**: synthesized crystals when 3+ memories cluster around a topic * **Contradiction detection**: flags conflicts with existing knowledge (e.g., a new policy that reverses a previous decision) Memory extraction uses AI processing time. The result count appears in the pipeline indicator after completion (for example, "Memories (5)"). ## Searching Documents [#searching-documents] Documents are searched alongside memories. A Timeline question like *"What does the Q4 report say about churn?"* searches both your saved memories and any imported documents that match. In the Library view, you can filter by status (**Searchable**, **With memories**, **Stale**, or **Error**) to find sources by processing state. Searchable-only documents are normal; choose extraction when you want durable memories from them. If you manage many documents for customers, projects, or internal workflows, add labels or source metadata when you import them. API, MCP, and CLI searches can then narrow the Library before ranking results. For example: ```bash nmem sources search "renewal terms" --label customer-acme --metadata purpose=contract-review nmem sources list --metadata material_type=case-study ``` Use labels for broad buckets people recognize. Use metadata for fields scripts and integrations already know, such as `customer`, `project`, `material_type`, or `purpose`. ## Chat with Your Documents [#chat-with-your-documents] Ask questions about any document directly in the Timeline. The answer draws from both the document and your memories, citing specific pages. *"What does the architecture review say about API rate limits?"* returns an answer referencing page 12 of the document and your Redis decision from three months ago. ## Batch Actions [#batch-actions] Select multiple documents in the Library view and: * **Send to AI Now** for cross-document analysis: compare reports, synthesize findings, or ask questions that span multiple documents * **Extract memories**: select sources that do not yet have memories and click "Extract memories (N)" to process them together. For sources that already have memories, the button shows "Re-analyze (N)" to refresh their extracted knowledge ## Documents, Memories, and Threads [#documents-memories-and-threads] Three types of content, each with its own purpose: | Type | What it is | Example | | ------------ | ------------------------------------ | ----------------------------------------- | | **Memory** | An atomic insight, decision, or fact | "We chose PostgreSQL for jsonb support" | | **Document** | Reference material imported whole | A 40-page architecture review PDF | | **Thread** | An AI conversation archive | Your ChatGPT session about async patterns | Documents and threads are sources. Memories are the distilled knowledge. When you extract memories from a document or thread, individual insights get saved as memories and connected to the knowledge graph. The original stays in the Library or Threads view as the source. ## Next Steps [#next-steps] * **[Getting Started](/docs/getting-started)**: The Timeline and all ways to add knowledge * **[Background Intelligence](/docs/advanced-features)**: How imported knowledge connects to your graph * **[Search & Relevance](/docs/search-relevance)**: How search ranks results across memories and documents # LLM Providers (/docs/llm-providers) Choose your setup in three layers: * **Plan or subscription**: what account or bundle you already pay for * **Provider or endpoint**: where requests actually go * **Model**: the concrete tool-capable default you run day to day Then configure it once in Settings (or `nmem` CLI/TUI). Follow [Use Nowledge Mem with fully local models](/docs/fully-local-models) for LM Studio and Ollama setup, purpose routing, verification, and privacy boundaries. Nowledge Mem recommends **subscription-based defaults** for the smoothest daily experience right now: * **OpenAI ChatGPT/Codex subscription** * **Kimi Code subscription** * **SuperGrok subscription** For day-to-day AI Now usage, prioritize **fast tool-capable models** over SOTA by default.\ For ChatGPT/Codex, fetch the current model list in Settings and choose a supported Codex or base GPT-5 model. Kimi Coding Plan models are also good daily defaults. If your current setup is spending too many tokens (for example always running `gpt-5.3-codex`), switch to a lighter tool-capable default first. ## What To Choose [#what-to-choose] Best default for coding-heavy AI Now workflows with strong tool use support. Great for coding workflows and tool-calling in AI Now. Use your Grok subscription through xAI sign-in, without pasting an API key. ## Provider Guides [#provider-guides]
OpenAI (ChatGPT/Codex)
Best for: coding + daily assistant workflows.
  • Stable tool-calling in AI Now and agents
  • Strong ecosystem compatibility
  • For ChatGPT Subscription, pick Codex models or base GPT-5 releases. Avoid chat aliases like gpt-5-chat-latest here.
Kimi / Moonshot
Best for: Kimi Code subscription users.
  • Great fit for coding-heavy AI Now sessions
  • Reliable tool workflows in day-to-day usage
Anthropic Claude
Best for: reliable autonomous workflows.
  • Strong planning and tool use quality
  • Good for long multi-step sessions
DeepSeek
Best for: cost/performance-sensitive workflows.
  • Start with deepseek-v4-flash for AI Now and agents
  • Use deepseek-v4-pro when quality matters more than speed
OpenRouter
Best for: one endpoint with many models.
  • Flexible multi-model routing
  • Pick tool-capable models for AI Now / agent workflows
Gemini
Best for: Google ecosystem users.
  • Supported in AI Now and agent flows
  • Smooth fit with Google AI Studio credentials
xAI
Best for: xAI API users.
  • Supported with tool workflows in AI Now
  • Use this path when you have an xAI API key
  • Use SuperGrok instead when you want to sign in with your Grok subscription
SuperGrok
Best for: Grok subscription users.
  • Sign in with xAI from Settings; no API key paste is needed
  • Works in AI Now and agent workflows after the local OAuth token is saved
  • Keep using the xAI provider if you prefer API-key billing
MiniMax
Best for: users already invested in MiniMax.
  • Supported in AI Now and extension workflows
  • Works with current MiniMax chat models
Z.AI
Best for: Zhipu ecosystem users.
  • Supported for AI Now and agents
  • Good regional/provider fit for existing usage
Ollama
Best for: local-first and self-hosted users.
  • No cloud dependency for model runtime
  • Use tool-capable models for AI Now agents
LM
LM Studio
Best for: local OpenAI-compatible models with a desktop model manager.
  • Default local URL: [http://127.0.0.1:1234/v1](http://127.0.0.1:1234/v1)
  • The API key is optional unless you enable authentication
  • In remote mode, LM Studio must run on the Nowledge Mem server machine
LM
Lemonade
Best for: local Windows GPU workflows and Lemonade users.
  • Use the Lemonade provider instead of a generic custom endpoint
  • Default local URL: [http://127.0.0.1:13305/v1](http://127.0.0.1:13305/v1)
  • AI Now can also use Lemonade's HTTP MCP endpoint when you add it as a custom MCP server
GitHub Copilot
Best for: Copilot subscription workflows.
  • Supported in AI Now
  • Low-friction if your team already uses Copilot
API
OpenAI-Compatible Custom Endpoint
Best for: private gateways and enterprise proxies.
  • Requires OpenAI-compatible chat completions
  • Tool support depends on your gateway/model
Use `deepseek-v4-flash` for the quickest DeepSeek setup in AI Now and agent tasks. Choose `deepseek-v4-pro` when you want the stronger V4 model. `deepseek-chat` still works, but `deepseek-reasoner` is not offered for agent workflows because it does not support tool calling. ## Context Window [#context-window] Every model has a maximum number of tokens it can process in a single request. Nowledge Mem auto-detects this limit from the model name. For example, `gpt-4o` defaults to 128k tokens, `gemini-2.0-flash` to 1M. You can override the context window in **Settings → Providers → Advanced** (or via `nmem config provider set --context-window `). **When to adjust:** * **Small or fine-tuned models** (8k–32k context): set the actual limit so that AI Now compacts the conversation before it overflows. * **Extended-context models** (500k–1M+): increase the window so AI Now uses the full capacity instead of compacting early. * **Custom or self-hosted models**: if the model name doesn't match a known pattern, the default is 128k. Set the real value to get accurate compaction behavior. When a conversation approaches the context limit, AI Now automatically summarizes older messages and keeps the most recent exchanges. This lets long sessions continue without losing important context. Setting the right context window ensures compaction fires at the right time, not too early, not too late. ## Custom Provider Guidance [#custom-provider-guidance] If you configure a custom OpenAI-compatible endpoint (`openai_compatible`) for DeepSeek V4, use `deepseek-v4-flash`, `deepseek-v4-pro`, or the exact DeepSeek V4 model id your gateway exposes. DeepSeek V4 uses a provider-specific thinking mode; Mem disables that mode during tool-loop agent calls so tool history remains compatible with strict DeepSeek validation. If you run DeepSeek V4 through OpenRouter, keep using the OpenRouter provider. Mem leaves OpenRouter-hosted models on OpenRouter's own request contract instead of adding DeepSeek-native `thinking` fields. Custom endpoints also support the newer **Responses API** (`/v1/responses`) alongside the legacy Chat Completions format. Select the API format when adding or editing the provider. For Linux headless deployment setup, see [Linux Server Deployment](/docs/server-deployment). # Mem Lifetime Pro (/docs/mem-pro) ## Free, Plus, Max, And Lifetime Pro [#free-plus-max-and-lifetime-pro] Nowledge Mem offers **Free**, **Plus**, **Max**, and **Lifetime Pro** options. **Free** is for trying Mem locally. You can sign in, save up to 50 memories, and use your own AI keys. **Plus** is the account service plan. It includes monthly Nowledge AI credit, one managed Nowledge Link host, and future account features such as encrypted backup and selective sync. Your Mem data still stays on your machine unless you choose an account feature that uploads encrypted data. **Max** is the upcoming higher-usage service tier for more included AI credit, larger backup capacity, premium model lanes, and team-oriented controls. **Lifetime Pro** is different from Plus. It is a one-time local unlock: unlimited local memories, BYOK AI, three local desktop activations, and local app features for life. It does not include Nowledge AI credit, managed Nowledge Link, encrypted cloud backup, or cross-device sync. Nowledge Mem plans in the app For detailed feature comparisons, visit the [Pricing Page](https://mem.nowledge.co/pricing). ## Activating Lifetime Pro [#activating-lifetime-pro]
### Start checkout from the pricing page [#start-checkout-from-the-pricing-page-step] Visit the pricing page and choose **Lifetime Pro** to proceed to checkout:
### Complete payment [#complete-payment-step] Complete the payment using your email address. Your email address will be used to receive the license key and is permanently associated with your Lifetime Pro activation. Payment Page
### Receive your license key [#receive-your-license-key-step] You'll receive an email with your license key. You can retrieve your license key anytime at mem.nowledge.co/licenses using your email address.
### Open Plans in the app [#open-plans-in-the-app-step] Open Nowledge Mem and navigate to **Settings** → **Plans**: Free Plan
### Activate with your license key [#activate-with-your-license-key-step] Paste your license key, then click **Activate License**: Activating License
### Confirm Lifetime Pro is active [#confirm-lifetime-pro-is-active-step] Once activated, your Lifetime Pro status will be displayed: Activated License Manage your activated devices anytime at mem.nowledge.co/licenses. Need help? Contact [hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai) for assistance with activation or licensing.
# Memories (/docs/memories) A memory is one durable thing worth keeping: a fact, preference, decision, plan, procedure, learning, event, or important context. Each memory should stand on its own, readable without the full conversation that produced it. Memories are the core unit of Nowledge Mem. Search, the knowledge graph, crystals, daily briefings, and connected tools all become more useful because memories exist underneath them. Use a memory for the durable takeaway. Use a thread when you need the original conversation history. A strong workflow is: save or import the thread, then distill the parts worth keeping into memories. ## The First Useful Memory [#the-first-useful-memory] If you are new, do not overthink structure first. Save one real thing such as: * a decision you made * a lesson you learned * a workflow you repeat Then ask for it back in the Timeline. Once that works, this whole page becomes much easier to understand. ## Anatomy of a Memory [#anatomy-of-a-memory] | Field | What it is | | -------------- | ----------------------------------------------------------------------------------- | | **Title** | A short summary. Auto-generated when you capture from the Timeline, or set manually | | **Content** | The knowledge itself. Markdown supported | | **Type** | What kind of durable knowledge this is | | **Labels** | Categories for filtering and organization | | **Importance** | A score from 0.1 to 1.0 that affects search ranking and briefing priority | | **Created** | Timestamp. Used for temporal search and knowledge evolution tracking | ### Importance Scale [#importance-scale] | Range | Meaning | Examples | | --------- | ---------- | ----------------------------------------------------------------------- | | 0.8 – 1.0 | Critical | Architectural decisions, breakthrough discoveries, production incidents | | 0.5 – 0.7 | Useful | Standard decisions, good insights, project learnings | | 0.1 – 0.4 | Background | Reference info, minor details, casual notes | The default is 0.5. AI tools and background intelligence use this score to prioritize what surfaces in search results and daily briefings. ### Memory Type [#memory-type] Each memory has one primary type. This helps agents decide how to use it: | Type | Use for | | ------------ | ------------------------------------------------ | | `fact` | Durable reference information | | `preference` | User taste, style choices, working constraints | | `decision` | Choices with rationale and trade-offs | | `plan` | Future intent, next steps, roadmap items | | `procedure` | How-to knowledge, workflows, step-by-step guides | | `learning` | Lessons, realizations, debugging conclusions | | `context` | Background information that frames future work | | `event` | Things that happened, outcomes, dated moments | If an agent does not pass a type explicitly, Mem classifies the memory during creation. Connected tools should still pass the type when they know it, because a clear `decision` or `procedure` is more useful than a generic note. ### Labels [#labels] New memories are labeled automatically when created. The system assigns 2–4 labels based on content and reuses your existing labels to keep the taxonomy consistent. You can always edit, add, or remove labels afterward. You can also create custom labels. Labels are lowercase and hyphenated (`api-design`, `team-standup`). Filter by label in the Memories view to focus on a specific domain. ## Creating Memories [#creating-memories] ### In the Timeline [#in-the-timeline] Type into the input at the top and press Enter. AI classifies your intent automatically: * A thought becomes a **memory** with auto-generated title and labels * A question gets **answered** from your existing knowledge * A URL gets **fetched**, parsed, and indexed * A file gets **parsed** and stored See [Getting Started](/docs/getting-started) for the full onboarding walkthrough. ### From AI Conversations [#from-ai-conversations] The [browser extension](/docs/integrations/browser-extension) captures memories from supported web AI chat platforms: * **Auto-Capture** monitors conversations and saves what matters autonomously * **Manual Distill** lets you trigger capture on a specific conversation ### From Threads [#from-threads] Import a conversation, then distill it into individual memories. Each extracted memory gets its own title, labels, and importance score. This is how hours of AI conversation become searchable, connected knowledge. See [Threads](/docs/threads) for the full workflow. ### From AI Tools [#from-ai-tools] Connected agents can read, search, and preserve durable knowledge while you work. The exact behavior depends on the connector path you chose: | Integration | How memories are saved | Setup | | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------- | | **Dedicated connectors** (Claude Code, Grok Build, Codex, Gemini CLI, OpenClaw, Hermes Agent, Alma, Cursor, Droid, OpenCode, Copilot CLI) | Dedicated package teaches the agent when to recall, distill, add, and sometimes update memories | [Connectors](/docs/integrations) | | **Reusable workflow packages** (`npx skills`, OpenCode, many agents) | Shared skills or prompts call `nmem` on your behalf | [Getting Started](/docs/getting-started) | | **Direct MCP** (any MCP client without a dedicated package) | Agent calls `memory_add` and `memory_update` directly | [Connectors](/docs/integrations) | The best-integrated setups do more than expose `memory_add`: they also teach the agent when to search first and when to update an existing memory instead of creating a duplicate. ### Via CLI [#via-cli] ```bash # Add a memory with auto-generated title nmem m add "We chose PostgreSQL for the new service because of jsonb support" # Add with explicit title and labels nmem m add "PostgreSQL chosen for jsonb support and team familiarity" \ --title "Database Decision: PostgreSQL" \ --unit-type decision \ --labels "decision,infrastructure" \ --importance 0.8 ``` ### Via API [#via-api] ```bash curl -X POST http://127.0.0.1:14242/memories \ -H "Content-Type: application/json" \ -d '{ "content": "We chose PostgreSQL for the new service", "title": "Database Decision", "unit_type": "decision", "labels": ["decision", "infrastructure"], "importance": 0.8 }' ``` See the [API Reference](/docs/api) for the full schema. ## Searching Memories [#searching-memories] ### In the App [#in-the-app] Open memory search with Cmd + K (macOS) or Ctrl + K (Windows/Linux). Three search modes work together: * **Semantic** finds memories by meaning, so searching "design patterns" finds memories about "architectural approaches" * **Keyword** does exact match for specific terms * **Graph** discovers memories through entity connections and topic clusters Press Cmd + Shift + K from any application to search without opening Nowledge Mem. ### From AI Tools [#from-ai-tools-1] Connected agents search through their native connector, shared workflow package, or MCP tools. When a topic might connect to prior work, the strongest paths search your knowledge base without waiting for an explicit prompt. ### Via CLI [#via-cli-1] ```bash # Semantic search nmem m search "authentication patterns" # Narrow by metadata your workflow already knows nmem m search "renewal decision" --metadata customer=acme --metadata purpose=contract-review # JSON output for scripting nmem --json m search "API design" | jq '.memories[0].content' ``` Use metadata filters when an integration or import flow already knows a stable field such as `customer`, `project`, `material_type`, or `purpose`. Mem narrows the memory set before ranking, so the agent searches the right slice instead of hoping broad ranking finds it. ## Editing and Organizing [#editing-and-organizing] ### Update a Memory [#update-a-memory] Click any memory in the Memories view to edit its content, title, labels, or importance. Changes take effect immediately. Via CLI: ```bash # Update importance nmem m update --importance 0.9 # Update labels nmem m update --labels "decision,infrastructure,critical" ``` ### Delete a Memory [#delete-a-memory] Delete from the memory detail view, or via CLI: ```bash nmem m delete nmem m delete -f # Use -f in scripts or non-interactive shells ``` `nmem m delete` asks for confirmation by default. In scripts, agents, or any non-interactive shell, add `-f` to avoid hanging while waiting for input. ## How Memories Connect [#how-memories-connect] When [Background Intelligence](/docs/advanced-features) is enabled, memories grow connections automatically: * **Knowledge Graph.** Every memory becomes a node. The system extracts entities (people, technologies, concepts) and maps relationships. Search "distributed systems" and find your memory about "Node.js microservices". The words don't match, the meaning does. * **Knowledge Evolution.** Save something new about a topic you've written about before, and the system creates a version link: *replaces*, *enriches*, *confirms*, or *challenges*. Trace how your understanding of any topic changed over time. * **Crystals.** When enough memories cover the same ground, they get synthesized into a reference article. Sources are cited. When you save related information later, the crystal updates. * **Working Memory.** Each morning, Mem writes a briefing from your recent and important memories. The Default space keeps `~/ai-now/memory.md`; if you use [Spaces](/docs/spaces), other spaces get their own briefings too. See [Background Intelligence](/docs/advanced-features) for the full guide on how these work. ## Where Memories Come From [#where-memories-come-from] | Source | How | Learn more | | ------------------- | ------------------------------------------------ | --------------------------------------------------------- | | Timeline | Type and press Enter | [Getting Started](/docs/getting-started) | | Browser extension | Auto-capture or manual distill from web AI chats | [Browser Extension](/docs/integrations/browser-extension) | | Thread distillation | Extract from imported AI conversations | [Threads](/docs/threads) | | AI tools | Skills, plugins, or MCP `memory_add` | [Connectors](/docs/integrations) | | CLI | `nmem m add` | [CLI Reference](/docs/cli) | | API | `POST /memories` | [API Reference](/docs/api) | ## MCP Tools [#mcp-tools] | Tool | What it does | | --------------------- | --------------------------------------------------------------------- | | `memory_search` | Search memories by meaning, keywords, or graph connections | | `memory_add` | Create a new memory with content, title, type, labels, and importance | | `memory_update` | Update content, title, importance, or labels | | `memory_delete` | Delete one or more memories | | `list_memory_labels` | List all labels with usage counts | | `read_working_memory` | Read today's daily briefing | ## Next Steps [#next-steps] * **[Threads](/docs/threads)**: Import and distill AI conversations into memories * **[Library](/docs/library)**: Import documents alongside your memories * **[AI Now](/docs/ai-now)**: Personal AI with full access to your knowledge base * **[Background Intelligence](/docs/advanced-features)**: How memories grow connections automatically * **[Browser Extension](/docs/integrations/browser-extension)**: Capture memories from web AI conversations * **[Connectors](/docs/integrations)**: Connect your AI tools through native connectors, reusable packages, or MCP # Nowledge FS (/docs/nowledge-fs) Nowledge FS is Mem's preview path-first layer for humans, agents, and scripts. In the app, people meet it as **Knowledge Tree**: everything you know appears in one familiar tree. Memories, conversations, wiki pages, Working Memory, activities, sources, and artifacts keep their native behavior. The tree is not a folder full of raw implementation files. It is a calm map over Mem itself, so you can open one thing, see the right preview, and keep moving. Agents see the same map as a virtual filesystem. That is the important shift: a human can browse in the app, while a script or agent can list, read, search, recall, and update canonical writable objects by path. This is the first public shape of Knowledge Tree and Nowledge FS. It is ready to try in the app, CLI, API, and MCP, but the mount, source-fragment, SQL/Cypher, replay, and tail phases are still being designed. ## When To Use It [#when-to-use-it] Use Knowledge Tree when you want a sense of place. * You remember that something exists, but not whether it was a memory, thread, wiki topic, or source. * You want to scan by type, date, label, or topic without opening several different views. * You want an agent to inspect nearby context before loading large objects. * You want paths you can copy into a command, script, prompt, or MCP call. If you are just asking one question, search is still fine. Knowledge Tree is for navigation, orientation, and controlled inspection. ## First Useful Loop [#first-useful-loop] 1. Open **Tree** in the app sidebar. 2. Open one branch such as **Memories**, **Threads**, **Wiki**, **Working Memory**, **Activities**, or **Artifacts**. 3. Click one item. The preview should feel like the rest of Mem: memories open as memory context, threads as readable conversations, wiki pages as wiki pages, and activities as Timeline-style events. 4. If you use the CLI, run: ```bash nmem fs ls / nmem fs recall "what did we decide about auth?" --in /memories -k 5 ``` A good result is not a long blob of text. It is a path you can inspect next: ```bash nmem fs stat /memories/by-id/.memory.md nmem fs cat /memories/by-id/.memory.md ``` ## How To Think About Paths [#how-to-think-about-paths] Paths are Mem addresses, not files on your disk. ```text /memories/by-id/.memory.md /threads///messages.jsonl /wiki/entities/.entity.md /working-memory/today.md /feed/2026-05-15/.feed.jsonl /artifacts/imports/.artifact.pdf ``` Some paths are canonical. Those can be updated when the object itself is writable. Other paths are aliases, like a memory shown under a label or date branch. Aliases are there for browsing and should be edited through the canonical path. ## What Agents Should Do [#what-agents-should-do] Agents should move through the tree in small steps: 1. Use `recall` for fuzzy memory questions. 2. Use `find` for structural constraints such as type, label, date, or mention. 3. Use `grep` for exact phrases, or `grep -E` for explicit regex. 4. Use `stat` before loading large objects. 5. Use `cat` only after a useful path has been found. This keeps context small and makes the agent's work inspectable. You can see the same path in the app, the CLI, the API, or the MCP tool. ```bash nmem fs recall "why did we change token refresh?" --in /memories -k 5 nmem fs ls /memories/by-label/auth nmem fs cat /memories/by-id/.memory.md ``` For long conversations and documents, agents should not load the whole file first. Search the branch, then read a small line window: ```bash nmem fs grep "JWT rotation" /threads nmem fs cat /threads///messages.jsonl --line 42 --lines 12 nmem fs grep "rate limit" /sources nmem fs cat /sources/.pdf --line 120 --lines 80 ``` Thread transcripts are JSONL: one line is one message. Parsed Library documents are rendered as markdown, so grep line numbers can be passed directly into `cat --line`. Grep is case-insensitive fixed-string search by default; use `--case-sensitive` for exact casing, and `-E` when you need regex alternation such as `JWT|token`. In this preview, `recall` is memory-backed. Use `grep` for exact search inside threads and parsed Library documents. MCP clients can use the same verbs through `mem_fs`. Codex, Claude, Cursor, Gemini, OpenClaw, and other agents are just consumers of this shared Mem shape; no single integration owns it. The concrete entry points keep short host-friendly names: `nmem fs` in the CLI, `/fs/*` in the API, and `mem_fs` in MCP. For tools and adapters, start by asking Mem what this server supports: ```bash nmem fs capabilities --json ``` The response includes the current roots, verbs, limits, and feature flags. That keeps integrations from guessing whether a future surface such as mounting, source fragments, SQL, Cypher, replay, or tail has shipped yet. ## What Not To Worry About Yet [#what-not-to-worry-about-yet] * You do not need to mount anything. * You do not need to understand the graph schema. * You do not need to choose between Tree and Library. Library remains the rich document and wiki reading surface; Tree gives you one map across all Mem objects. * You do not need SQL or Cypher for the preview release. Those query surfaces belong to later phases after the safety limits and result shapes are pinned. ## Success Check [#success-check] Knowledge Tree is working when: * the app shows the main branches without raw implementation files; * clicking an item opens a native Mem preview, not a generic text dump; * `nmem fs ls /` returns the same top-level idea as the app; * `nmem fs recall ...` returns paths; * web and remote clients can use the same `/fs/*` API shape as desktop. ## Next [#next] Run `nmem fs` from a terminal or script. Build against the `/fs/*` endpoints directly. Pick the native connector or MCP path for your tool. Use Library when you want the richest document and wiki reading experience. # Your Profile (/docs/profile) Your profile is how Mem's agents understand you. Without it, they work generically. With a few sentences, every briefing, label, and insight becomes more relevant to your actual work. ## What Your Profile Does [#what-your-profile-does] When you fill in your profile, every agent in the system reads it: * **Daily briefings** frame what matters around your role and current work * **Auto-labeling** picks categories that match how you think, not generic taxonomy * **Knowledge extraction** understands domain terms you use * **AI Now** starts each session knowing your context You fill it in once. Every agent reads it every time it runs. ## Setting Up Your Profile [#setting-up-your-profile]
### Open Profile [#open-profile-step] Go to **Context → You**.
### Name and Aliases [#name-and-aliases-step] Your name helps agents recognize you in imported conversations and threads. Aliases are handles you use on other platforms (GitHub username, Twitter handle, Slack display name). Agents use these to identify which messages are yours when processing threads from different sources.
### About You [#about-you-step] A few sentences about your role, current work, and interests. This is the most impactful field. Agents use it to decide what matters when they process your knowledge. Good examples: * *Product designer at a fintech startup, focused on mobile payments and onboarding flows* * *Currently building a knowledge base for our compliance team to reduce repeated legal reviews* * *Interested in AI-assisted writing, second brain methodology, and personal knowledge management* You don't need to write all three. Even one sentence changes how agents prioritize.
### Custom Instructions [#custom-instructions-step] Rules for how agents handle your knowledge. This is where you tell agents what to do differently from their defaults. Examples: * **Labels**: *"Always label memories about customer feedback with 'customer-voice'. Use project codenames, not full project names."* * **Language**: *"Write briefings in French. Use technical English terms for programming concepts."* * **Tone**: *"Keep briefings concise, no more than 5 bullet points. Skip obvious connections."* Custom instructions are applied to daily briefings, background knowledge processing, and AI Now sessions.
### Output Language [#output-language-step] Choose the language agents use when they write briefings, insights, labels, and other generated content. This is separate from the app interface language. The picker includes every official EU language, Norwegian Bokmål, Icelandic, and the existing global language set. The same choice follows you between local and Cloud workspaces.
## How It Reaches Your Agents [#how-it-reaches-your-agents] Your profile is injected into three agent paths: | Agent | What it reads | How it uses it | | --------------------------- | ---------------------------------- | ------------------------------------------------------- | | **Background Intelligence** | Full profile + custom instructions | Frames briefings, labels, and insights around your work | | **Knowledge Agent** | Full profile + custom instructions | Guides EVOLVES detection, labeling, and extraction | | **AI Now** | Full profile + custom instructions | Starts each session with your context already loaded | Supported connected tools receive your profile through **Context** when they load the Context Bundle at session start. Simpler or older integrations may still benefit indirectly through better search results, labels, and briefings. ## Tips [#tips] * **Be specific over comprehensive.** "Leading a MongoDB-to-PostgreSQL migration" is more useful than "senior software engineer with 10 years of experience." * **Update when your work changes.** The profile is not a resume. If you switch projects, update it. * **Custom instructions compound.** A rule like "always label with project codenames" saves you from manually relabeling hundreds of memories. * **You can leave fields empty.** Agents fall back to generic behavior for any field you skip. ## Next Steps [#next-steps] * **[Background Intelligence](/docs/advanced-features)**: See what agents do with your profile * **[Context](/docs/ai-context)**: Check what each connected AI receives before it starts * **[AI Now](/docs/ai-now)**: Your personal AI workspace, pre-loaded with your context * **[Connectors](/docs/integrations)**: Connect the tools that benefit from better context # Access Mem Anywhere (/docs/remote-access) Nowledge Mem runs on your machine, so your data never leaves your control. Access Anywhere lets you reach that same instance from any other device, agent, or browser through a secure tunnel. One Mem, many ways to connect: your laptop at a coffee shop, a browser tab on your phone, a coding agent on a CI runner, AI Now on a second desktop. The Mem on your always-on machine is the hub. Everything else connects to it. This is also how sync works in Mem today: one always-on Mem instance, many connected clients. If you want the short product explanation first, read [Sync Across Devices](/docs/sync). If you subscribe to Plus or Max, open **Settings → Access Anywhere** and turn on **Nowledge Link**. Mem creates the stable link for you; you do not need to own a domain or configure Cloudflare. The manual Quick link and Cloudflare account paths below remain useful for Lifetime Pro users, servers, and advanced BYO-domain setups. Nowledge Link in Plus Run Nowledge Mem on an always-on device, such as a Mac Mini, a Linux server, or a desktop that stays powered on. Then connect from everywhere else: a second laptop, a web browser, or the iOS mobile app. This gives you 24/7 access to your knowledge base, background intelligence that keeps running, and a single source of truth for all your tools and devices. Access Mem Anywhere ## Choose Your Connection Type [#choose-your-connection-type] | Type | Best for | What URL you get | | ---------------------- | ------------------------------------------- | --------------------------------------------------------------------- | | **Nowledge Link** | Plus and Max users who want one-click setup | Stable `*.nowledge-mem.com` URL | | **Quick link** | Fast setup in under a minute | Random `*.trycloudflare.com` URL | | **Cloudflare account** | Daily/long-term usage | Stable URL on your own domain (for example `https://mem.example.com`) | ## Before You Start [#before-you-start] Open this guide from **Settings → Access Mem Anywhere → Guide**. * Nowledge Link requires an active Plus or Max subscription and sign-in inside Nowledge Mem. * Quick link needs no Cloudflare account and no domain. * Cloudflare account mode requires a domain already managed in your Cloudflare account. * If you do not have a domain in Cloudflare yet, use **Quick link** first. * In Cloudflare account mode, the final public URL appears only after you create a hostname route. If you are on a server/terminal workflow, open nmem tuiSettings tab → Access Anywhere. You can configure stable link, start/stop tunnel, rotate/reveal key, and view terminal setup there. Access Anywhere management APIs are local-only.\ If your shell is pointed at a remote Mem (NMEM\_API\_URL=https\://...), temporarily switch back to local ([http://127.0.0.1:14242](http://127.0.0.1:14242)) before configuring tunnel settings. ## Path A: Quick Link (No Account) [#path-a-quick-link-no-account]
### Open remote access in Mem [#open-remote-access-in-mem-step] Open **Settings → Access Mem Anywhere**. Turn on **Allow devices on same Wi-Fi** if you also want LAN access. When you enable this, an API key is automatically generated. Other devices on your network will need this key to connect. It's the same key used for access anywhere. You can copy it from the **API Key** section that appears below.
### Choose Quick link and start [#choose-quick-link-and-start-step] In **Access from Anywhere**, choose **Quick link**, then click **Start**. Wait for status to become **Live**.
### Copy URL and API key [#copy-url-and-api-key-step] In **Ready to connect**, copy: * **URL** * **API key** Use **Rotate** if you want to issue a fresh key.
### Verify from another machine [#verify-from-another-machine-step] ```bash export NMEM_API_URL="https://" export NMEM_API_KEY="nmem_..." nmem status ``` Expected: `status ok`. Some VPS, office, campus, or ISP networks block UDP/QUIC. Mem now retries Cloudflare tunnel startup with HTTP/2 automatically if QUIC fails during startup. If you want to force TCP-only transport in a headless or systemd deployment, set: ```bash export TUNNEL_TRANSPORT_PROTOCOL=http2 ``` Then restart Mem and start Access Anywhere again.
## Path B: Cloudflare Account (Stable URL) [#path-b-cloudflare-account-stable-url] You need a domain already in Cloudflare DNS (for example `example.com`) before this path can produce a stable URL.
### Create a tunnel and copy the token [#create-a-tunnel-and-copy-the-token-step] In Cloudflare Zero Trust: 1. Open NetworksConnectorsCreate a tunnel. 2. Click Select Cloudflared. Cloudflare Connectors page 3. Name the tunnel and click Save tunnel. Name your tunnel 4. In **Install and run connectors**, Cloudflare shows a command like: ```bash sudo cloudflared service install ... ``` You do not run that command. Mem runs the tunnel for you; you only need the token from it. Copy the token, then in Mem paste either: * the raw token, or * the full command line (supported forms: `service install `, `--token `, `--token=`). Mem extracts the token automatically. On the desktop app and `.deb` / AppImage host installs, Mem bundles its own `cloudflared`, so you never install or run it yourself. This is unchanged. On the [Docker deployment](/docs/docker), `cloudflared` is now bundled in the image too (both the default and `:cuda` tags). Earlier guidance to install or run `cloudflared` as a separate sidecar in the container no longer applies: configure the tunnel from **Settings → Access Anywhere** or the in-container `nmem` CLI, and the server manages it. Copy token from command
### Create a public hostname route [#create-a-public-hostname-route-step] In tunnel routing / hostname routes: 1. Create a hostname (for example `mem.example.com`). 2. Bind it to the tunnel you created. This step creates your stable public URL. Hostname routes list Create hostname route
### Map the hostname to local Mem API [#map-the-hostname-to-local-mem-api-step] 1. Open NetworksConnectors → your tunnel. Open tunnel details 2. In Published application routes, click Add a published application route. Add app route 3. Map `mem.example.com` to your local Mem server: * Subdomain: `mem` * Domain: your Cloudflare-managed domain * Service Type: `HTTP` * Service URL: `http://127.0.0.1:14242` Do not append `/remote-api`. Map to local Mem API
### Save and start in Mem [#save-and-start-in-mem-step] Back in SettingsAccess Mem AnywhereCloudflare account: * Public URL: `https://mem.example.com` * Tunnel token: paste raw token or full `cloudflared` command Then: * Click Save * Click Start * Click Rotate if you want a fresh key * Click Copy to copy URL and API key
### Verify from another machine [#verify-from-another-machine-step-1] ```bash export NMEM_API_URL="https://mem.example.com" export NMEM_API_KEY="nmem_..." nmem status ``` Expected: `status ok`.
## Use It on Other Clients [#use-it-on-other-clients] Pick the connection path that matches your situation: * **Mobile app**: native iOS or Android access from your phone or tablet * **Desktop app**: full experience including AI Now from a second computer * **Web browser**: quick visual access from any device * **`~/.nowledge-mem/config.json`**: the shared local client config written by `nmem config client ...`, reused automatically by `nmem`, OpenClaw, Bub, Claude Code, and other integrations * **Browser extension**: paste your URL + key in SidePanel settings * **ChatGPT / OAuth MCP clients**: paste the public `/mcp` endpoint and approve Mem through OAuth * **Direct MCP**: for MCP clients without a better dedicated path, or as the companion MCP layer for hybrid hosts like Codex ### Mobile App (iOS & Android) [#mobile-app-ios--android] The mobile app is in alpha. iOS is available via TestFlight; Android is available as an unsigned APK. Reach out via [Discord](https://discord.gg/nowledge) for TestFlight access, or download the APK from the [community releases page](https://github.com/nowledge-co/community/releases/tag/v0.6.11). The mobile app is a native wrapper that connects to your Mem server: no local database, no local Python backend. It gives you the full mobile experience: search, memories, threads, library, graph, and feed. 1. Install the app (TestFlight for iOS, APK for Android) 2. Enter your **Mem URL** and **API key** 3. Tap **Connect** The app stores your credentials locally and reconnects automatically on subsequent launches. ### Desktop App (Client Mode) [#desktop-app-client-mode] Install Nowledge Mem on a second computer and connect to your main instance: 1. Open **Settings → Access Anywhere** 2. Enter the URL and API key from your main Mem 3. Click **Connect** You get the full desktop experience: search, memories, threads, library, graph, and **AI Now**. AI Now runs on the Mem server you connect to and uses that server's LLM configuration. No extra LLM setup is needed on the client. The title bar shows **Remote** to indicate you're connected to another Mem. AI Now sessions, message history, and pasted images stay with that server so you can move between clients. ### Web Browser [#web-browser] Open your Mem URL with `/app` appended (for example `https://mem.example.com/app`) in any modern browser. Enter your API key to log in. You get search, memories, threads, graph views, and AI Now from the same server-backed session list. This is the fastest way to check your knowledge base from a machine where you haven't installed the desktop or mobile app. On mobile, the native app (above) is recommended. If you prefer the browser, tap **Share → Add to Home Screen** (iOS) or the install banner (Android) to save it as a shortcut. It opens full-screen without browser chrome. ### nmem CLI [#nmem-cli] **Auto-configured on the same machine.** If you run `nmem` on the same computer as the desktop app, this file is created automatically when Access Anywhere generates an API key. You can skip straight to `nmem status`. Configure this machine once so every `nmem` command, and every plugin that uses `nmem`, connects automatically: ```bash nmem config client set url https:// nmem config client set api-key nmem_... ``` ```bash nmem status # reads from config.json nmem m search "project notes" ``` The command writes the same local client config file that OpenClaw, Bub, Claude Code, Claude Desktop, and other integrations read. It is separate from `nmem config access ...`, which controls how a Mem server is exposed to other devices. For CI or scripted setups, you can also use `NMEM_API_URL` and `NMEM_API_KEY` environment variables. Priority: CLI flags > env vars > config file > defaults. ### Browser Extension (Side Panel Or Sidebar) [#browser-extension-side-panel-or-sidebar] Open any supported AI chat page, then open **Nowledge Mem Exchange** in the browser side panel or sidebar: 1. Click **Settings** 2. In **Access Mem Anywhere**, paste the terminal setup copied from Mem Desktop: ```bash export NMEM_API_URL="https://" export NMEM_API_KEY="nmem_..." ``` 3. Click **Fill URL + key** 4. Click **Save** 5. Click **Test connection** (should show success) You can also type URL + key manually in the same section. ### ChatGPT / OAuth MCP Clients [#chatgpt--oauth-mcp-clients] Some cloud MCP clients, including ChatGPT Connectors, cannot use a private `nmem_` API-key header. For those clients, use **Remote MCP over OAuth**: 1. In Mem, open **Connectors → AI Tools → Remote MCP over OAuth**. 2. Click **Start setup**. 3. Let Mem open the pairing page in the browser profile you will use for the AI client's OAuth approval. 4. Copy the Access Anywhere MCP endpoint. It must end with `/mcp`. 5. Paste that URL into the AI client's MCP connector setup. 6. Approve Mem on the OAuth page in that same browser profile. For ChatGPT, create the connector from ChatGPT Web settings. After it is connected, the same connector is available in ChatGPT Web and the ChatGPT desktop app; mention `@Nowledge Mem` in a chat when you want ChatGPT to search Mem. For ChatGPT screenshots, see [ChatGPT Web and Desktop](/docs/integrations/chatgpt-web). ### OpenClaw Plugin [#openclaw-plugin] If you already ran `nmem config client ...` on this machine, you're done. The OpenClaw plugin reads the same shared client config automatically. You can also set credentials in the OpenClaw dashboard under **Automation → Plugins → Nowledge Mem**. The API key is passed to the `nmem` subprocess via environment variable only. It never appears in logs or process arguments. Behavioral skills bundled with the plugin (like the memory guide) work the same in remote mode; they're part of the plugin, not the server. ### Bub Plugin [#bub-plugin] Same shared client config. If you already ran `nmem config client ...` on this machine, the Bub plugin picks those credentials up automatically. ```json title="~/.nowledge-mem/config.json" { "apiUrl": "https://", "apiKey": "nmem_..." } ``` Or set `NMEM_API_URL` and `NMEM_API_KEY` environment variables before running Bub. ### Alma Plugin [#alma-plugin] Two options. Pick whichever fits your setup: **Option A: Plugin settings (recommended)** In Alma, open Settings and configure the Nowledge Mem plugin: * **`nowledgeMem.apiUrl`**: your remote URL (e.g. `https://mem.example.com`). Leave empty for local. * **`nowledgeMem.apiKey`**: your Mem API key (`nmem_...`). Passed via environment variable only, never logged or shown in process arguments. The plugin shows `mode=remote` or `mode=local` in its activation log so you can confirm which mode is active. **Option B: Environment variables** Set these in your shell before starting Alma: ```bash export NMEM_API_URL="https://" export NMEM_API_KEY="nmem_..." ``` Both options are equivalent. Use Option A for a self-contained setup. Use Option B to keep credentials out of config files. ### MCP / Agent Nodes [#mcp--agent-nodes] MCP clients connect via HTTP. The MCP host owns that connection, so it does **not** automatically read `~/.nowledge-mem/config.json`. If you already configured this machine with `nmem config client ...`, generate the exact host config from the same URL and API key: ```bash nmem config mcp show --host codex nmem config mcp show --host gemini-cli nmem config mcp show --host cursor nmem config mcp show --host claude-desktop ``` Paste the generated block into that host's MCP settings. It includes your API key when one is configured, so keep it in the host's private user config. If you are writing the block by hand, pass your API key in the `Authorization` header, or use the `X-NMEM-API-Key` header. Use the exact MCP endpoint with a trailing slash: `https:///mcp/`. **Cursor** (`~/.cursor/mcp.json` or workspace `.cursor/mcp.json`): ```json { "mcpServers": { "nowledge-mem": { "url": "https:///mcp/", "type": "streamableHttp", "headers": { "APP": "Cursor", "Authorization": "Bearer nmem_..." } } } } ``` or ```json { "mcpServers": { "nowledge-mem": { "url": "https:///mcp/", "type": "streamableHttp", "headers": { "APP": "Cursor", "X-NMEM-API-Key": "nmem_..." } } } } ``` **Claude Desktop.** If you use the [Nowledge Mem extension](/docs/integrations/claude-desktop), it reads the same shared client config as `nmem`: * macOS / Linux: `~/.nowledge-mem/config.json` * Windows: `%USERPROFILE%\.nowledge-mem\config.json` ```json { "apiUrl": "https://", "apiKey": "nmem_..." } ``` If you're running Nowledge Mem Desktop on the same machine, this file is usually written for you automatically when you start Access Anywhere. Alternatively, add an MCP server entry to `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json { "mcpServers": { "nowledge-mem": { "url": "https:///mcp/", "type": "streamableHttp", "headers": { "APP": "Claude", "Authorization": "Bearer nmem_..." } } } } ``` **Codex** (`~/.codex/config.toml`, shared by the desktop app and CLI): If you are following the dedicated [Codex guide](/docs/integrations/codex-cli), keep that plugin package in place. The package includes a local MCP endpoint by default. For remote Mem, run `nmem config mcp show --host codex` and paste the generated TOML into `~/.codex/config.toml`. **Gemini CLI** (`settings.json`, override for the Gemini extension): If you installed the [Gemini CLI extension](/docs/integrations/gemini-cli), the extension includes a local MCP endpoint by default. For remote Mem, run `nmem config mcp show --host gemini-cli` and paste the generated JSON into Gemini's user settings. **Claude Code.** Install the [Nowledge Mem plugin](/docs/integrations/claude-code) for automatic Working Memory, search, and session capture. For remote mode, run `nmem config client set url ...` and `nmem config client set api-key ...` once on the client machine. The plugin's `nmem` commands read that same shared local config. **CI / other shell-based agents.** Set `NMEM_API_URL` and `NMEM_API_KEY` environment variables. Same variables work in any shell context. For transcript-backed saves such as `nmem t save --from claude-code`, `grok`, `gemini-cli`, or `codex`, remote mode does **not** mean the Mem server reads those agent session files remotely. The client machine running the agent still performs local discovery and parsing, then uploads the normalized thread data to Mem. ## Quick Health Check [#quick-health-check] ```bash curl -H "Authorization: Bearer $NMEM_API_KEY" "$NMEM_API_URL/health" ``` Expected: health JSON response. If wrong key: ```bash curl -H "Authorization: Bearer wrong_key" "$NMEM_API_URL/health" ``` Expected: `401`. If your proxy strips auth headers: ```bash curl "$NMEM_API_URL/health?nmem_api_key=$NMEM_API_KEY" ``` ## Security and Operations [#security-and-operations] * API key is required for every remote request, both tunnel and LAN connections. * When LAN access is enabled, connections from other devices on your network require the API key. Connections from the same computer are always allowed without a key, unless you enable **Require API key on localhost** in Settings. * Rotate key anytime in Settings (old key becomes invalid immediately). * After your first successful **Start**, tunnel reconnects automatically on app restart until you click **Stop**. * Browse-Now / Browser Bridge automation endpoints are local-only and are not exposed through Access Anywhere. * Stop tunnel when remote access is not needed. ## Troubleshooting [#troubleshooting] * **Start timed out**: your network/proxy may block Cloudflare traffic. Retry, or switch to Cloudflare account mode. * **`401 Missing API key`**: proxy likely removed auth headers. Update `nmem`, or use query fallback for manual checks. * **`429 Too many invalid auth attempts`**: wrong key was retried repeatedly. Re-copy key or click **Rotate**. # Search & Relevance (/docs/search-relevance) How Nowledge Mem finds matching memories, ranks them by relevance, and learns from your usage patterns. ## The Scoring Pipeline [#the-scoring-pipeline] Search combines multiple signals to rank results beyond keyword matching. Nowledge Mem Scoring Pipeline ### Semantic Scoring [#semantic-scoring] This track finds memories that match what you're looking for: * **Meaning-based search**: Finds memories by semantic similarity, not just exact words. Search for "design patterns" and find memories about "architectural approaches." * **Keyword search**: Catches exact phrases and technical terms using BM25 ranking. * **Label matching**: Surfaces memories with matching tags. * **Graph traversal**: Discovers connected memories through entities and topic communities. ### Decay, Confidence & Temporal Scoring [#decay-confidence--temporal-scoring] This track adjusts results based on freshness, validation, and your usage: * **Recency**: Recently accessed memories score higher. We use exponential decay with about a 30-day half-life. * **Frequency**: Memories you access repeatedly become more durable (logarithmic scaling with diminishing returns). * **Importance floor**: High-importance memories maintain minimum accessibility even when unused. * **Confidence**: Memories that have been validated through usage and knowledge-graph connections get a subtle boost. Confidence grows with evidence and never decreases. * **Temporal matching**: Boosts memories whose event time matches your query (deep mode only). These tracks combine into a final score that determines result ranking. ## Memory Decay [#memory-decay] Memories fade over time unless reinforced by use. ### How It Works [#how-it-works] **Recency**: A memory accessed yesterday scores much higher than one from three months ago. The 30-day half-life means scores roughly halve each month without access. **Frequency**: Your 10th access to a memory matters more than your 100th. This mirrors how human memory works: early repetitions build durability, later ones have diminishing returns. **Importance Floor**: Memories marked as high importance never fully decay. Even untouched, they maintain minimum accessibility. This protects foundational knowledge from fading away. ### Search Reinforcement [#search-reinforcement] Starting from v0.6.6, every search appearance updates a memory's last-accessed time and access count, strengthening its freshness score automatically. Previously, only explicit clicks updated freshness. Now, appearing in search results counts as a light access, keeping actively relevant memories from fading. ### Confidence [#confidence] Confidence scoring is computed during the daily freshness refresh. Separate from decay, each memory builds a **confidence score** that reflects how well-validated it is. Confidence starts at a baseline and grows as evidence accumulates: * **Search usage**: Appearances, clicks, and reading time * **Knowledge graph**: Memories confirmed or enriched by other memories, or used as sources for crystallized knowledge Unlike decay which fades with time, confidence only increases. A memory that has been frequently accessed, clicked, and connected to other knowledge scores higher than a freshly created one with the same semantic match. The influence is subtle (confidence contributes about 5% of the final score), but it gives well-established knowledge a consistent edge. ### What This Means [#what-this-means] * Active knowledge stays fresh, including memories that appear in search results * Old memories don't disappear, they just rank lower when equally relevant * Important knowledge persists regardless of access patterns * Well-validated memories get a subtle ranking boost * The system learns from your behavior automatically ### Automatic Maintenance [#automatic-maintenance] These features are opt-in via Settings → Processing → Advanced. To keep decay scores accurate and memory quality high, Nowledge Mem can run background maintenance: * **Freshness refresh**: A daily task recomputes decay and confidence scores across all memories, so ranking stays current even for memories you haven't touched recently. This changes scores only; it does not archive, merge, delete, or rewrite memories. * **Memory Maintenance**: A review-first task looks for memory growth pressure. It can prepare a Timeline review for stale low-risk facts/events that could move out of everyday recall, and for protected knowledge that may need semantic organization. * **Compaction**: A weekly task identifies clusters of similar or redundant memories and can create links, summaries, or review items. It never silently deletes your saved memory text. ## Temporal Understanding [#temporal-understanding] Nowledge Mem understands two kinds of time. ### Event Time vs Record Time [#event-time-vs-record-time] **Event time** is when something actually happened: * "The 2020 product launch" * "Last quarter's decisions" * "Before we migrated" **Record time** is when you saved the memory. You might record a memory today about an event from 2020. This matters for queries like "recent memories about 2020 events": things you saved recently (record time) about events from 2020 (event time). ### Temporal Intent Detection [#temporal-intent-detection] Temporal intent detection requires deep mode search. In fast mode, temporal references are matched by keywords only. In deep mode, the system interprets temporal references: | Query | Understanding | | ---------------------------- | --------------------------- | | "Decisions from 2023" | Event time: 2023 | | "Recent memories" | Record time: recent | | "Recent memories about 2020" | Event: 2020, Record: recent | | "Before the migration" | Event: before that event | Fuzzy references like "last quarter," "around 2020," or "early this year" are translated into meaningful filters. ### Date Precision [#date-precision] When you save a memory about "early 2020," the system: 1. Normalizes to a searchable date (2020-01-01) 2. Tracks precision level (year, month, or day) 3. Preserves original meaning for accurate matching This lets "memories from 2020" (year precision) work differently from "memories from January 2020" (month precision). ## Feedback Loop [#feedback-loop] Your usage patterns continuously improve search relevance. ### What We Track [#what-we-track] | Signal | What It Captures | | --------------- | -------------------------------------- | | **Appearances** | How often a memory shows in results | | **Clicks** | When you open a memory to view details | | **Dwell time** | How long you spend reading | ### How It Improves Search [#how-it-improves-search] * High click-through rate indicates the memory is genuinely useful * Long dwell time suggests valuable content * Frequent appearances without clicks may indicate declining relevance No action required. Relevance improves with normal use. ### Automatic Labeling [#automatic-labeling] Labels are assigned automatically when new memories are created. When you create a memory, Background Intelligence reads its content and assigns 2–4 descriptive labels. It reuses existing labels when they fit, following a consistent lowercase-hyphenated convention (like `machine-learning` or `project-alpha`). This means your memories are organized from the start without manual tagging. ## Graph-Powered Discovery [#graph-powered-discovery] The knowledge graph enables discovery through entity and topic connections. ### How Memories Connect [#how-memories-connect] Each memory can link to: * **Entities**: People, concepts, technologies, places mentioned * **Other memories**: Through shared entities or relationships * **Communities**: Graph Analysis detected topic clusters ### Search Through Connections [#search-through-connections] **Entity-mediated**: Find memories about "database optimization" even when tagged differently, through shared entities like PostgreSQL or indexing. **Community-mediated**: A search about "authentication" might surface memories from your "Security Practices" community. **Graph expansion**: Start from one memory and explore connected knowledge. ## Search Modes [#search-modes] Two modes, available across all interfaces: ### Fast Mode [#fast-mode] * Under 100ms typical response * Direct semantic and keyword matching * Entity and community search without language model analysis * Best for quick lookups ### Deep Mode [#deep-mode] * Full language model analysis * **Temporal intent detection** (e.g., "recently working on; social events in last decade") * Query expansion for better recall * Context-aware strategy weighting * Better for exploratory searches Both modes work in main search, global launcher, and API. ## Result Transparency [#result-transparency] Every result shows why it ranked where it did. ### Search Query Details [#search-query-details] After each search, you can view detailed analysis of how your query was interpreted: * Which search strategies were used * Temporal intent detection results (in deep mode) * Query expansion and entity extraction ### Score Breakdown [#score-breakdown] Hover over any result's score to see a breakdown of how it was calculated: * **Semantic score**: How well the content matches your query * **Decay score**: Freshness based on recency and frequency * **Confidence**: How well-validated through usage and graph connections * **Temporal boost**: Event time relevance (when applicable) * **Graph signals**: Entity and community connections Search Query Details This makes it clear how usage patterns influence ranking and why certain memories appear for specific queries. # Linux Server Deployment (/docs/server-deployment) Nowledge Mem can run as a **headless server** on Linux machines without a GUI. For a real server setup, use the Linux package and manage it from the command line. You can then open the built-in web app from a browser on the same machine, or connect other clients with an API key. Background intelligence features such as daily briefings, insight detection, and knowledge graph enrichment require a configured Remote LLM and the appropriate license for your build. The server guide itself is about deployment, not packaging. Use `sudo` for package installation and system service installation. Run day-to-day commands like `nmem serve`, `nmem config ...`, `nmem license ...`, and `nmem tui` as your normal Linux user. Recent builds block these stateful commands when you reach `root` through `sudo` or another elevation step, so a fresh install does not silently create `root`-owned Mem state in the wrong user environment. If you intentionally log in as `root` on a root-only VPS, Mem will still use `/root` normally. ## System Requirements [#system-requirements] | Requirement | Specification | | -------------------- | ------------------------------------------------------------------------------- | | **Operating System** | Ubuntu 22.04+, Debian 12+, or compatible (via AppImage) | | **Architecture** | `x86_64` for `.deb` / AppImage; `x86_64` and `arm64` for Docker | | **Memory (RAM)** | 8 GiB minimum (16 GiB recommended) | | **Disk Space** | 10 GiB available | | **Dependencies** | `libgtk-3-0`, `libwebkit2gtk-4.1-0`, `zstd` (installed automatically by `.deb`) | ## Installation [#installation] Set up the APT repository for automatic updates via `apt upgrade`: ```bash curl -fsSL https://nowledge-co.github.io/community/apt/install.sh | sudo bash sudo apt-get install nowledge-mem ``` This adds the GPG signing key and repository source. To update only Mem later, run `sudo apt-get update && sudo apt-get install --only-upgrade nowledge-mem`. Normal system-wide upgrades still work through `sudo apt-get update && sudo apt-get upgrade`, or via `unattended-upgrades` if configured. For a headless server on a VPS, NAS, cloud VM, or homelab box, the Docker path is a separate guide: ```bash git clone https://github.com/nowledge-co/community.git cd community/docker ./nmemctl up ``` See **[Docker Deployment](/docs/docker)** for the full walkthrough: multi-arch (`amd64` + `arm64`), the "For your agent" skill, bind-mount layout, image verification, Caddy TLS, backup/migration, and the optional web-UI auto-update. ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # Download the package curl -A "$BROWSER_UA" -L -o nowledge-mem.deb https://nowled.ge/download-mem-deb # Install the package sudo dpkg -i nowledge-mem.deb # Fix any missing dependencies sudo apt-get install -f -y ``` ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # Download the AppImage curl -A "$BROWSER_UA" -L -o nowledge-mem.AppImage https://nowled.ge/download-mem-appimage # Portable use only chmod +x nowledge-mem.AppImage ./nowledge-mem.AppImage ``` For a headless-first Linux server, prefer the APT, Docker, or `.deb` install path. AppImage is best for portable/manual use, not unattended server setup. It does not install the `nmem` CLI into your PATH, so it is not the cleanest `nmem` + systemd workflow on a machine with no desktop session. If you download packages from a terminal, use the commands above as written. They include a browser User-Agent because some download endpoints return `403` to plain `curl` / `wget` requests. APT and `.deb` installs automatically: * Extracts the bundled Python runtime * Creates the `nmem` CLI at `/usr/local/bin/nmem` * Configures the APT repository for automatic updates (if installed via APT) * Sets up the desktop entry (ignored on headless servers) Verify the CLI is available: ```bash nmem --version ``` If you used the AppImage instead, run the AppImage file directly each time. It does not add `nmem` to your PATH. ## Docker (preview) [#docker-preview] This page covers the `.deb` / APT / systemd path on Linux servers. Docker is a separate deployment model with its own walkthrough. It uses the same Mem backend, same web app, and same data, but the lifecycle (compose, bind mounts, image upgrades, optional web-UI auto-update) is different enough to live on its own page. See **[Docker Deployment](/docs/docker)** for the full guide: when Docker is the right choice (VPS, NAS, cloud VM, homelab), supported architectures (`amd64` + `arm64`), quick start with `nmemctl`, the "For your agent" skill, where your data lives, memory tuning, image verification, Caddy TLS, backups and migration, and the optional web-UI auto-update. ## Quick Start [#quick-start] For a real Linux server, set up the background service first. That gives you one stable local Mem server so the next commands work cleanly from SSH, across new terminals, and after reboot.
### Install the background service [#install-the-background-service-step] Recommended on servers: ```bash sudo nmem service install --service-user ``` If you truly want a user-level service instead: ```bash nmem service install --user ``` On headless servers, prefer the system service. A user service only survives logout and reboot if lingering is enabled for that account: ```bash sudo loginctl enable-linger ```
### Verify the service [#verify-the-service-step] ```bash nmem service status nmem status ``` To confirm exactly which build is running, print the build SHA: ```bash nmem-server --build-info ``` The same value appears in `GET /health` under `.build_sha`, so you can verify a deployment over the network or from a script.
### Activate Your License [#activate-your-license-step] ```bash nmem license activate # Email is usually inferred from the key nmem license status # Verify activation nmem license renew # Refresh this device later if authorization expires ``` If email inference fails, run `nmem license activate ` explicitly.
### Open the Web App [#open-the-web-app-step] Print the browser login details: ```bash nmem key --show-login ``` If your current build does not support `--show-login` yet, use: ```bash nmem key ``` Then open the URL it prints. On the default setup, that is usually: ```text http://127.0.0.1:14242/app ``` On a headless server, your browser is usually on another computer. Use the exact URL and port that `nmem key --show-login` prints. If you need an SSH tunnel, forward that same port: ```bash ssh -L :127.0.0.1: ``` Then open the matching local URL in your browser and paste the API key.
### Download the Search Index Model [#download-the-search-index-model-step] ```bash nmem models download nmem models status # Verify installation ``` This downloads the Search Index Model for hybrid search (\~500 MB). Only needed once. When you run headless, use these two commands as your quick search-health check: * `nmem status`: shows whether search is ready, rebuilding is needed, or Mem is only filling metadata in the background * `nmem models status`: shows the model state plus the current search-index action, if any `GET /health` carries the same signal for scripts and remote checks. Two fields matter: * `embedding.mode` is `remote`, `local-gguf`, or `local-hash-fallback`. The hash-fallback value means no real embedder is configured, so semantic search is degraded while keyword search still works. That is the signal to set a remote provider or download the local model. * `reindex_needed` is `true` when the search index is stale, usually after the embedding identity changes (a new provider or model). The server never blocks boot to rebuild. It starts immediately and serves keyword (FTS) search while the index catches up, so a stale index fails soft to keyword results rather than erroring. Trigger the rebuild when you are ready, from **Settings → Memory Processing → Search** or with `POST /search-index/reindex`. If you would rather rebuild eagerly on boot, set `NMEM_BOOT_AUTO_REINDEX=1` before starting the server.
### Configure the LLM Provider [#configure-the-llm-provider-step] A remote LLM is required on Linux (no on-device LLM support): ```bash nmem config provider set anthropic \ --api-key sk-ant-xxx \ --model claude-sonnet-4-20250514 nmem config provider test # Verify connection ``` Supported providers include `anthropic`, `openai`, `gemini`, `xai`, `deepseek`, `minimax`, `zai`, `moonshot`, `ollama`, `openrouter`, and OpenAI-compatible endpoints.\ See the full provider matrix and caveats: [LLM Providers](/docs/llm-providers).
### Enable Background Intelligence [#enable-background-intelligence-step] ```bash nmem config settings set backgroundIntelligence true nmem config settings set autoDailyBriefing true ```
### Verify Everything [#verify-everything-step] ```bash nmem status ```
### Quick foreground test instead of systemd [#quick-foreground-test-instead-of-systemd-step] If you do not want to install a systemd service yet: ```bash nmem serve ``` Keep that terminal open. Then use a second terminal for `nmem license ...`, `nmem models ...`, and `nmem config ...`.
## Running as a systemd Service [#running-as-a-systemd-service] For production deployments, use `nmem service install` to set up a background systemd service that automatically starts on boot: ```bash # Install, enable, and start as your normal Linux user sudo nmem service install --service-user # If you are running sudo directly from that Linux user, Mem can usually infer it sudo nmem service install # Custom host/port sudo nmem service install --service-user --host 0.0.0.0 --port 8080 ``` ```bash # No root required nmem service install --user ``` For a system service, Mem should run as your normal Linux user, not as `root`. If `sudo` cannot infer the right account, pass `--service-user `. For a user service, run `nmem service install --user` directly as that user without `sudo`. If you want a user service to survive logout and reboot, also run `sudo loginctl enable-linger ` once. If your VPS is intentionally root-only and you log in as `root` directly, `nmem service install` can still use `/root` consistently. If you previously ran older builds as `root`, some files under `~/.config/co.nowledge.mem.desktop/` may still be owned by `root`. In that case, license actions, provider changes, or Access Anywhere settings can fail until you fix ownership for the Linux user that runs the service. Recent builds now show the exact path when this happens. A typical repair looks like: ```bash sudo chown -R : ~/.config/co.nowledge.mem.desktop sudo chown -R : ~/.local/share/NowledgeGraph ``` If you use custom `XDG_CONFIG_HOME` or `XDG_DATA_HOME`, repair those locations instead. ### Managing the Service [#managing-the-service] ```bash nmem service status # Show service status nmem service logs -f # Follow service logs nmem service stop # Stop the service nmem service start # Start the service nmem service uninstall # Stop, disable, and remove ``` Add `--user` to any `nmem service` command if you installed a user-level service. ### serve vs service [#serve-vs-service] | | `nmem serve` | `nmem service install` | | ------------------ | ----------------------------- | -------------------------------------- | | **Runs in** | Foreground (current terminal) | Background (systemd) | | **Stops when** | Ctrl+C or terminal closes | `nmem service stop` or system shutdown | | **Starts on boot** | No | Yes (auto-enabled) | | **Best for** | Testing, development | Production deployments | ## Data Location [#data-location] All data (graph database, search index, version metadata) is stored in a single directory: ``` ~/.local/share/NowledgeGraph/ ├── nowledge_graph_v2.db/ # KuzuDB graph database ├── search_index/ # LanceDB vector + BM25 index └── db_version.json # Schema version tracking ``` The server resolves this path automatically using `XDG_DATA_HOME` (defaults to `~/.local/share`). To use a custom location, set the `NOWLEDGE_DB_PATH` environment variable **before** starting the server: ```bash export NOWLEDGE_DB_PATH=/mnt/data/NowledgeGraph/nowledge_graph_v2.db nmem serve ``` Older versions stored data in `./data/` relative to the working directory. After upgrading, the server will auto-detect legacy data and print migration instructions. If your data seems missing, see [Troubleshooting: Missing data after upgrade](#missing-data-after-upgrade) below. ## Remote Access [#remote-access] By default, `nmem serve` listens on `127.0.0.1` only. That is enough for: * `nmem` commands on the server itself * the built-in web app on the same local URL (by default `http://127.0.0.1:14242/app`) If you bind to `0.0.0.0` or another non-loopback address, Mem requires an API key for other machines. The key is auto-generated when needed, and you can print it again at any time with: ```bash nmem key # or nmem key --show-login ``` Once the server is reachable, connect clients through the highest-level surface they support: native connectors first, then plugin settings or `nmem` config, and only then direct MCP when no better dedicated path exists. The main exception today is Codex, where the dedicated package already bundles local MCP and remote deployments should override that endpoint in Codex config. ```bash # On the server nmem serve nmem key ``` Install the standalone CLI on remote machines: ```bash pip install nmem-cli # or uv pip install nmem-cli ``` Then configure the connection. The recommended persistent setup is: ```bash nmem config client set url http://your-server:14242 nmem config client set api-key nmem_... ``` That writes `~/.nowledge-mem/config.json` for this machine. If you only need a temporary shell session, use environment variables instead: ```bash title="Temporary shell override" export NMEM_API_URL=http://your-server:14242 export NMEM_API_KEY="nmem_..." ``` ```bash nmem status nmem m search "query" ``` Priority: CLI flags > env vars > config file > defaults. Commands like `nmem t save --from claude-code`, `grok`, `gemini-cli`, or `codex` still read local agent session files on the client machine running that agent. Pointing `nmem` at a remote server changes where the normalized data is uploaded, not where session discovery happens. To disable authentication (not recommended for production): ```bash nmem serve --no-auth ``` API key authentication is enabled by default for connections from other machines. Localhost browser access can also require a key if you enable localhost auth. For additional security, restrict access via firewall rules or use [Access Mem Anywhere](/docs/remote-access) with a Cloudflare tunnel. ## Interactive TUI [#interactive-tui] For an interactive terminal experience, use the TUI: ```bash nmem tui ``` The TUI provides a full settings management interface including license activation, LLM configuration, and knowledge processing toggles. It is bundled in the Docker image too. On a container deployment, run it inside the container: ```bash docker compose exec -it mem nmem tui ``` It also includes **Access Anywhere** controls in `Settings`, and the same screen can reveal the current API key plus the local web login URL. That makes it practical to complete the `/app` login flow even on a headless server.\ Full guide: [Access Mem Anywhere](/docs/remote-access). If your server network blocks UDP/QUIC and Access Anywhere fails to come online, force Cloudflare transport to HTTP/2 before restarting Mem: ```bash export TUNNEL_TRANSPORT_PROTOCOL=http2 ``` ## Configuration Reference [#configuration-reference] ### Environment Variables [#environment-variables] | Variable | Default | Description | | ----------------------- | ------------------------ | -------------------------------------------------------------- | | `NMEM_API_URL` | `http://127.0.0.1:14242` | Server URL for CLI commands | | `NMEM_API_KEY` | `-` | API key for authenticated requests | | `NOWLEDGE_DB_PATH` | Auto-detected | Override database location | | `NOWLEDGE_BACKEND_HOST` | `127.0.0.1` | Server bind address | | `NMEM_LAN_AUTH` | `-` | Set to `disabled` to skip authentication (same as `--no-auth`) | ### CLI Commands Summary [#cli-commands-summary] | Command | Description | | -------------------------------------------- | ----------------------------------------------------- | | `nmem serve` | Start the server (default: same machine only) | | `nmem serve --no-auth` | Start without API key authentication | | `nmem service install` | Install and start as a systemd service | | `nmem service status` | Show systemd service status | | `nmem service logs -f` | Follow service logs | | `nmem service stop` / `start` | Stop or start the service | | `nmem service uninstall` | Remove the systemd service | | `nmem status` | Check server health | | `nmem license activate [email]` | Activate license (email is usually inferred) | | `nmem license renew` | Refresh or renew this device authorization | | `nmem models download` | Download Search Index Model | | `nmem config provider set

--api-key ` | Configure LLM provider | | `nmem config provider test` | Test LLM connection | | `nmem config settings` | Show processing settings | | `nmem config settings set ` | Update a setting | | `nmem update` | Check for available updates | | `nmem update apply` | Download and apply update | | `nmem tui` | Interactive terminal UI | | `nmem key` | Print the current API key | | `nmem key --show-login` | Print the local web app URL together with the API key | ## Troubleshooting [#troubleshooting] ### Missing data after upgrade [#missing-data-after-upgrade] Older versions (before 0.7) stored the database in `./data/` relative to the directory you ran `nmem serve` from. The current version stores data in the standard location (`~/.local/share/NowledgeGraph/`). If your memories disappeared after upgrading, your data is likely still on disk, just in the old location.

#### Find your old data [#find-your-old-data-step] Search common locations where the old database may be: ```bash find / -name "nowledge_graph*.db" -type d 2>/dev/null ``` Typical locations include: * `~/data/nowledge_graph.db`, if you ran `nmem serve` from your home directory * `/data/nowledge_graph.db`, if the systemd service ran from `/` (system service without `WorkingDirectory`) * `/path/where/you/ran/nmem/data/nowledge_graph.db`, any other working directory
#### Move to the standard location [#move-to-the-standard-location-step] ```bash # Stop the server first nmem service stop # if using systemd # or Ctrl+C # if running in foreground # Create the standard directory if needed mkdir -p ~/.local/share/NowledgeGraph # Move your database and related files mv /old/path/data/nowledge_graph*.db* ~/.local/share/NowledgeGraph/ mv /old/path/data/search_index ~/.local/share/NowledgeGraph/ 2>/dev/null mv /old/path/data/db_version.json ~/.local/share/NowledgeGraph/ 2>/dev/null # Restart the server nmem serve # or: nmem service start ```
#### Verify recovery [#verify-recovery-step] ```bash nmem m search "test" # Search for your memories nmem status # Check server health ``` Starting with the current version, `nmem serve` prints the database path at startup. This makes it easy to verify which location is being used. If legacy data is detected in `./data/`, the server prints migration instructions automatically.
## Next Steps [#next-steps] * **[CLI Reference](/docs/cli)**: Complete CLI documentation * **[API Reference](/docs/api)**: REST API endpoints * **[Connectors](/docs/integrations)**: Connect with AI tools # Spaces (/docs/spaces) Spaces are an optional way to keep different kinds of knowledge focused without splitting Mem into separate apps. Most people do not need them on day one. Staying in **Default** is the right choice until two contexts keep getting in each other's way. If you are not already feeling real overlap between projects, teams, or agents, leave spaces off and keep using the default space. ## The First Useful Move [#the-first-useful-move] Create one extra space only when you already know why you need it. Good first cases: * a long-running work project that should not mix with personal notes * an agent that should build up its own experience over time * a shared team space that several tools should search first Go to **Context → Spaces**, turn spaces on, and create one space with a clear name. Save one memory in the new space, switch back to **Default**, and confirm it no longer appears in the default Memories view. Then switch back and find it immediately. ## What Spaces Change [#what-spaces-change] When a space is active, these views follow it by default: * **Memories** * **Threads** * **Library** * **Working Memory** * **AI Now** The **Timeline** also starts from the active space, while still letting you expand back to all activity when you want the wider picture. The **entity graph stays global by design**. Mem still understands the whole shape of your knowledge. Spaces change what your day-to-day memory surfaces read and write by default. ## What The Settings Actually Mean [#what-the-settings-actually-mean] Inside a space profile you will see three settings that matter most: * **Automatic recall in this space** * **Stay in this space** keeps the first recall step inside the current lane. * **Stay here + shared spaces** starts here, then also reads the spaces you marked as shared context. * **Search every space** is for the rare lane that should search across your whole memory by default. * **Shared context for recall** * This is retrieval only. * It does **not** move memories into those spaces. * It does **not** merge spaces together. * **How agents should work here** * AI Now, Feed, and built-in background agents read this when they work in that space. * It changes how they search and explain. * It does **not** change where records are stored. ## Working Memory In Spaces [#working-memory-in-spaces] Working Memory is no longer just one global file. * The **Default** space keeps the familiar compatibility path at `~/ai-now/memory.md`. * Other spaces get their own Working Memory briefing behind the same Mem interfaces. * Connected tools read the briefing for the current space when they know which space they are in. That means a research agent can open with its own current priorities, while your default personal space stays quieter. If a space no longer has memories, threads, or Library items, but still has its own Working Memory notes, Mem will tell you that clearly when you delete the space and let you remove those generated notes in the same step. ## Moving Existing Records [#moving-existing-records] If you created a space after using Mem for a while, you do not have to recreate your history. In **Memories** or **Threads**, turn on selection mode, choose the items you want, then use **Move** to send them to another space. For a larger cleanup, select the current page first, then choose **All pages** to move or delete every primary item in the current space. Shared context does not move records. It only lets one space read another space when recall is configured that way. ## How AI Tools Use Spaces [#how-ai-tools-use-spaces] The best integrations treat space as background context, not as a new thing you have to explain every turn. * **AI Now** follows the current space in the app. * **Native integrations** should store the lane in their own profile or provider config when the host already knows it. * **CLI workflows** can opt into a space with `--space ""`. * The HTTP and MCP APIs still use the `space_id` field name for compatibility, but they accept the visible space name too. You can preview the result in **Context** before starting a new tool session. ```bash nmem --json wm read --space "Research Agent" nmem --json m search "token rotation" --space "Research Agent" nmem spaces ``` If a tool has no natural project or agent context, it should simply stay in **Default**. If an integration already has a real settings surface, use that to choose the lane. Environment variables are only the fallback for CLI-first tools that have no better profile-level config. ## Multi-Agent Hosts [#multi-agent-hosts] Not every integration can route spaces at the same level. * **Coding tools** like Claude Code, Grok Build, Codex, and Gemini CLI usually only need one optional lane for the whole session. * **Agent harnesses** like Hermes, Alma, Bub, and OpenClaw may need one lane per profile, process, or agent identity. The right pattern is: * **Fixed lane**: one profile or process always stays in one space * **Derived lane**: the host already knows a stable identity or workspace and derives the space from it * **Exact mapping**: the host exposes a small known set of identities and maps each one to a named space If a host does not expose a trustworthy identity or workspace signal, do not invent per-agent routing anyway. Use one fixed lane per profile or process, or stay on Default. ## When Spaces Help Most [#when-spaces-help-most] Spaces are strongest when you want focus, not isolation for its own sake. They work especially well for: * one owner with several long-running agents * separating work from personal context * a shared project space plus a quieter default space * teams that want one common context without mixing every private note into it ## What Not To Worry About Yet [#what-not-to-worry-about-yet] * You do not need a work space and a life space just because the feature exists. * You do not need to redesign your labels or graph usage to start using spaces. * You do not need to split the entity graph. Mem keeps that global on purpose. ## Next Steps [#next-steps] * [Memories](/docs/memories) if you want the capture and search workflow * [Context](/docs/ai-context) if you want to see what a connected AI receives * [AI Now](/docs/ai-now) if you want a space-aware agent workspace * [Nowledge Mem CLI](/docs/cli) if you want to script `--space` and `nmem spaces` * [Background Intelligence](/docs/advanced-features) if you want to understand how Working Memory and scheduled tasks behave over time # Start Here (/docs/start-here) Nowledge Mem is easiest to understand through one loop: * save something that matters * find it again * let one real tool use it This page is the shortest path to that loop. If you have not installed yet, go to [Installation](/docs/installation) first; everything below assumes the app is running. ## What Mem Is [#what-mem-is] At its simplest, Mem does three things: * it stores your decisions, insights, files, and conversations * it makes them searchable and reusable later * it lets the tools you connect work from the same memory instead of starting cold If you plan to use Mem across several devices, the model is straightforward: run one Mem on an always-on machine and let your other clients connect to it. See [Sync Across Devices](/docs/sync). You do not need to understand the whole product before it becomes useful. ## The First Loop [#the-first-loop]
### Save One Real Memory [#save-one-real-memory-step] In the Timeline, write one real thing you want to keep: a decision you made, an insight from work, a preference you repeat often. Press Enter.
### Confirm Search Can Find It [#confirm-search-can-find-it-step] Ask the Timeline a direct question such as: > What did I decide about authentication? If the answer reflects what you just saved, you already have a working loop.
### Connect One Real Tool [#connect-one-real-tool-step] Instead of choosing a tool from a long list first, start with one instruction. Your agent uses the best supported setup path for the host it is running in.
## Connect Any AI Tool [#connect-any-ai-tool] Open the AI tool you actually use (Claude Code, Grok Build, Codex, Cursor, Gemini CLI, Copilot CLI, OpenClaw, Hermes, Droid, Alma, Bub, Pi, OpenCode, OMP, Paseo, or Claude Desktop) and paste this prompt: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for the AI tool I am using. ``` That URL is a machine-readable install contract. The agent fetches it, detects which host it is running in, uses the right install or setup path, verifies the connection with `nmem status`, and asks you to restart the host when needed. Command-line hosts can usually be installed directly. App-based hosts may still ask you to confirm a marketplace step. The agent usually knows which host it lives in. It can read [SKILL.md](https://mem.nowledge.co/SKILL.md), run the matching plugin install or MCP config command when the host allows it, and tell you what changed. You confirm any manual app step and restart; the loop becomes visible. ### Remote or cross-device setup [#remote-or-cross-device-setup] If Mem runs on the same machine as the AI tool, the generic prompt above is enough. The agent will configure the local endpoint at `127.0.0.1:14242` and stop there. If the AI tool runs on another machine, or if you are using a managed or self-hosted remote Mem server, first point this machine's CLI at that server: ```bash nmem config client set --url https://your-mem-server.example --api-key nmem_... ``` In the desktop app, find remote URL and key controls under **Settings → Access Anywhere**. Use that path when: * you are on **Pro** and want the agent to use your managed Nowledge Link endpoint * you are on **Lifetime** with a self-hosted Mem and need cross-device access * you want the agent to talk to your Mem from a machine other than the one running it ## Definition of Done [#definition-of-done] You should be able to answer yes to all of these: * I saved one memory in the Timeline * I searched for it and got it back * I pasted the Connect prompt into my AI tool, it completed the install or told me the exact manual step, and I restarted that tool * In a fresh session of that tool, the agent could read my Working Memory (empty is fine on day one) If any answer is no, see [How To Know Mem Is Working](/docs/verify-it-works) for verification steps. ## When The Connect Prompt Does Not Fit [#when-the-connect-prompt-does-not-fit] A small set of surfaces install differently, because they are not driven by a chat-style agent: * **Browser Extension** for web chat (ChatGPT, Claude.ai, Gemini, Poe): install from the Chrome Web Store, open the side panel, connect it to Mem. Guide: [Browser Extension](/docs/integrations/browser-extension). * **Raycast**: install from the Raycast Store. Guide: [Raycast](/docs/integrations/raycast). * **Trajectory extractors** for Windsurf, Antigravity: external CLIs that export sessions to disk for one-time import. Guide: [Import existing conversations](/docs/import-existing-conversations). For everything else, use the Connect prompt. If your host is not yet in `SKILL.md`'s table, ask the agent to read the file anyway and report what it tried; we add hosts as they appear in the wild. ## Bring In Conversations You Already Have [#bring-in-conversations-you-already-have] If you are migrating from ZIP/JSON/HTML exports (ChatGPT, DeepSeek, ChatWise, Alma), local coding-agent sessions, or single `.md` threads, start from [Import existing conversations](/docs/import-existing-conversations). It maps each case to the exact Mem screen so you do not bounce between Threads and Connectors. Save one memory. Run the Connect prompt for one tool. Restart that tool. Stop. The point on day one is to prove the loop, not to wire every surface at once. ## Next Steps [#next-steps] * [Installation](/docs/installation): install and finish first boot * [Getting Started](/docs/getting-started): the Timeline and your first captures * [Connectors](/docs/integrations): connector reference (behavior, skills, distillation) * [How To Know Mem Is Working](/docs/verify-it-works): verify the full loop * [Access Anywhere](/docs/remote-access): run Mem on one machine and reach it from everywhere * [Sync Across Devices](/docs/sync): the single-Mem, multi-client sync model # Sync Across Devices (/docs/sync) Yes. Nowledge Mem supports sync today. But it works in a specific way: * one Nowledge Mem instance is the single source of truth * other clients connect to that same instance * your memories, threads, graph, and library stay consistent because everyone is using the same backend This is different from running several separate Mem databases and merging them later. If you want a backup or one-time migration instead of ongoing multi-device access, use [Back Up, Export, and Import](/docs/data-portability). ## What Sync Means In Mem [#what-sync-means-in-mem] The recommended setup is simple: 1. Run Nowledge Mem on an always-on machine. 2. Turn on [Access Anywhere](/docs/remote-access). 3. Connect your other clients to that same Mem. That can be: * the desktop app on another computer * the web app at `/app` * the mobile app * the browser extension * `nmem` CLI * supported agent integrations running on other machines If they all point to the same Mem URL and API key, they are working against the same knowledge base. ## What This Is Not [#what-this-is-not] Mem does **not** currently mean: * several independent local Mem apps automatically replicating and reconciling with each other * a centralized Nowledge-hosted account backend * offline-first multi-master sync between separate databases Today, sync means one Mem hub and many clients. ## When This Is The Right Setup [#when-this-is-the-right-setup] This model is ideal if you already have: * a Mac Mini that stays on * a Linux server * a desktop machine that acts as your main knowledge hub * a dedicated agent machine such as an OpenClaw or coding-agent box You keep one long-running Mem there, then access the same knowledge base from everywhere else. Historically, people mostly saw remote access through the browser extension and `nmem` CLI, so many assumed Mem did not really support sync. That is out of date. Web access, desktop client mode, and the mobile app now make the single-Mem multi-client model much more visible. ## What To Read Next [#what-to-read-next] * Read [Access Anywhere](/docs/remote-access) for setup, security, Cloudflare tunnel steps, and client-specific connection instructions. * Read [Back Up, Export, and Import](/docs/data-portability) if you want a portable backup or one-time migration. * Read [AI Now](/docs/ai-now) if you want to use the desktop client remotely with the same knowledge base. * Read [Verify It Works](/docs/verify-it-works) if you want to confirm that another device is really connected to the same Mem. # Threads (/docs/threads) Threads are your conversation layer. They keep the original flow of what happened in an AI session: what you asked, what the tool answered, and how the work evolved. Their real value is not just storage. Threads become useful when you can search past conversations, reopen exact context, and distill the durable parts into [memories](/docs/memories). If you need the original messages, save or import a thread. If you only need the durable takeaway, distill it into memories and work from there. If you are deciding **how** to bring existing conversations in (bulk file vs coding-agent scan vs browser vs one markdown file), read **[Import existing conversations](/docs/import-existing-conversations)** first. This page remains the **format and feature reference** for Threads. ## The First Useful Thread [#the-first-useful-thread] If you are new, do one of these first: * import one conversation you already care about * let one supported tool capture a full session * capture one web conversation through the browser extension Then open that thread and distill one useful memory from it. That is the core workflow. | I want to... | Jump to | | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | | See **every import path** in one overview | [Import existing conversations](/docs/import-existing-conversations) | | Browse and search threads | [Browsing Threads](#browsing-threads) | | Distill threads into memories | [Thread Distillation](#thread-distillation) | | Auto-import from **coding agents** | [Auto-Sync](#auto-sync) | | Capture from **web AI chats** | [Browser Extension](#browser-extension) | | Import my **ChatGPT**, **DeepSeek**, or **Raycast AI** (exporter JSON) conversations | [Bulk Import](#bulk-import) | | Import a **conversation file** (`.md` with `## User`/`## Assistant` headers) | [Single Thread](#single-thread) | | Learn the **.md** conversation format | [Conversation Markdown](#conversation-markdown-format) | | Import via **API** | [Import API](#import-api) | | Import via **CLI** | [CLI](#cli) | ## Browsing Threads [#browsing-threads] The Threads view shows all your imported conversations in one place. * **Search** threads by content or title * **Filter** by source (Claude Code, ChatGPT, Cursor, etc.) * **Pin** important threads to keep them accessible * **View** individual messages within any thread Open Threads from the sidebar or press Cmd + 3 (macOS). ## Thread Distillation [#thread-distillation] The key workflow that connects threads to memories. Open any thread and trigger distillation. The system extracts individual memories from the conversation, each with its own title, labels, and importance score. The extracted memories enter your knowledge graph and become searchable alongside everything else. This is how hours of AI conversation become connected knowledge you can find later. For normal-sized threads, distillation runs right away. For very large threads, Mem now offers **Smart Background Distillation** instead: it starts a few seconds later, lets the Knowledge Agent read the thread progressively, and then saves a smaller set of durable memories. This is slower than a short-thread distill, but much safer than forcing one foreground request to read everything at once. The [browser extension](/docs/integrations/browser-extension) supports Smart Distill directly from web conversations, so you can capture memories without importing the full thread first. ## How Threads Reach Mem [#how-threads-reach-mem] Threads can enter Nowledge Mem through several different paths. They are related, but they are not the same: * **Dedicated plugins and extensions**: tool-specific integrations like Claude Code, Grok Build, Codex, Gemini CLI, OpenClaw, Hermes Agent, Alma, Cursor, Droid, OpenCode, Craft Agent, and Copilot CLI * **Local discovery/backfill**: in-app import for supported coding-agent conversations on the machine running Mem * **Shared skills or prompt packs**: reusable setups like `npx skills` * **Browser capture**: the Exchange extension works with the **focused web session** you use in the panel (not your full chat account); see [Import existing conversations](/docs/import-existing-conversations) * **Manual import**: files, exports, API calls, and CLI imports The main thing to understand is this: * **Full session capture** means Mem receives the actual recorded conversation from that tool * **Handoff summary** means Mem stores a concise continuation note instead of the full session Shared skills matter here too. They are useful across many agents, but they cannot honestly promise full session capture unless that host runtime exposes readable session files or a stable transcript API. Most users only need one rule: * if your tool already has a real thread-save path, use it * if it only supports handoff summaries today, keep that mental model clear and use import or `nmem t sync` for full history ## Auto-Sync [#auto-sync] ### In-App Discovery [#in-app-discovery] Scan your machine for conversations from local coding assistants. No file export needed. This path scans conversation files on the machine running Nowledge Mem. It is excellent for local sync, but it is different from `nmem t sync --from ...`, which reads local session files client-side and can still upload normalized threads to a remote Mem server. Importing saves that conversation as a thread right away. If Auto-Sync is on, Mem can then append new messages to that thread, and it can remember the detected project for later sessions when that app exposes a stable project path. | Client | Sync Mode | Where | | --------------- | ------------------------------------------------------------------ | ---------------------------------------- | | **Claude Code** | Auto-discovery + incremental sync | Threads → Import → Find AI Conversations | | **Cursor** | Auto-discovery + incremental sync | Threads → Import → Find AI Conversations | | **Codex** | Auto-discovery + incremental sync | Threads → Import → Find AI Conversations | | **OpenCode** | Backfill older sessions; new work is captured by the native plugin | Threads → Import → Find AI Conversations | ### Native Capture And Save Paths [#native-capture-and-save-paths] Different integrations expose different thread-save behavior. Some support full session capture. Some auto-capture on lifecycle events. Droid and Cursor currently keep plugin handoff summaries separate from full conversation import. | Integration | What it saves | How it works | Setup | | ------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | **Claude Code** | Full session capture | Stop hook auto-saves the session after each response. Also supports explicit `/save`. `nmem` reads local session files client-side before upload. | [Claude Code guide](/docs/integrations/claude-code) | | **Grok Build** | Full session capture | Grok Build loads the shared Claude-compatible connector, but hooks route saves through `nmem t save --from grok` so the source and session format stay correct. | [Grok Build guide](/docs/integrations/grok) | | **Gemini CLI** | Full session capture plus separate handoff summary | `save-thread` imports the recorded Gemini session through `nmem t save --from gemini-cli`. The extension also imports before compression and at session end. `save-handoff` stays a separate resumable summary. | [Gemini CLI guide](/docs/integrations/gemini-cli) | | **Droid** | Handoff summary in the plugin | The Droid plugin intentionally exposes `save-handoff`, not `save-thread`. It provides Working Memory, routed recall, and resumable checkpoints now, while leaving transcript-backed thread save for a future real importer. | [Droid guide](/docs/integrations/droid) | | **Cursor** | Handoff summary in the plugin | The Cursor plugin intentionally exposes `save-handoff`, not `save-thread`. Use in-app discovery for local Cursor conversation import until a real live session importer exists. | [Cursor guide](/docs/integrations/cursor) | | **Alma** | Full session capture | Live sync saves conversations after 2 min idle, on thread switch, and on quit (on by default). | [Alma guide](/docs/integrations/alma) | | **OpenClaw** | Full session capture | Captures every agent session automatically at completion, with optional LLM distillation. | [OpenClaw guide](/docs/integrations/openclaw) | | **Hermes Agent** | Completed-turn capture with final boundary flush | The native memory provider writes cleaned `user` / `assistant` turns as replies complete, then flushes remaining changes on clean exit, `/new`, and `/reset`. | [Hermes guide](/docs/integrations/hermes) | | **Codex** | Full session capture | Stop hook captures the recorded Codex session after each turn. Explicit save remains available as a fallback. | [Codex guide](/docs/integrations/codex-cli) | | **Copilot CLI** | Full session capture | Capture hooks append newly recorded Copilot conversation content into Mem after each response, before compaction, and at session end. Explicit save/checkpoint requests still create a concise summary thread when needed. | [Copilot CLI guide](/docs/integrations/copilot-cli) | | **Pi** | Full session capture | The native Pi package syncs completed conversations automatically. Older local sessions can be imported with `nmem t sync --from pi`. | [Pi guide](/docs/integrations/pi) | | **OpenCode** | Full session capture | The native plugin captures when OpenCode reports idle and flushes before compaction. `nowledge_mem_save_thread` remains an explicit fallback; older sessions can be imported with `nmem t sync --from opencode`. | [OpenCode guide](/docs/integrations/opencode) | | **Craft Agent** | Source-guided memory + import | Craft uses a workspace source and guide for MCP-backed memory behavior. Older local Craft sessions can be imported from `session.jsonl` files with `nmem t sync --from craft-agent`. | [Craft Agent guide](/docs/integrations/craft-agent) | | **OMP** | Plugin auto-capture plus older-session backfill | The dedicated OMP plugin captures new conversations automatically. Older local OMP sessions can still be backfilled with `nmem t sync --from omp`. Do not use the Pi package as the OMP connector. | [OMP guide](/docs/integrations/omp) | | **Generic `npx skills` agents** | Handoff summary only | Use `save-handoff`. Shared skills can guide saving, but they do not control the host runtime well enough to promise transcript-backed import everywhere. | [Connectors overview](/docs/integrations) | If you need exact past conversation history, use a full-session capture or import path. Handoff summaries are for resumable continuity, not full conversation storage. ## File Import [#file-import] ### Bulk Import [#bulk-import] Import all conversations from an export file at once. | Source | File Format | How to Export | | -------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **ChatGPT** | `chat.html` | ChatGPT Settings → Data controls → Export data | | **Claude** | `data-…-batch-….zip` (`conversations.json`, `memories.json`) | claude.ai or Claude Desktop: avatar → **Settings** → **Privacy** → **Export data** ([Anthropic guide](https://support.claude.com/en/articles/9450526-how-can-i-export-my-claude-data)). Not available from Claude mobile apps. | | **DeepSeek** | `deepseek_conversations.json` | chat.deepseek.com → Settings → Data → Export data | | **ChatWise** | `.zip` (contains JSON files) | Export all chats from ChatWise app | | **Alma** | `alma-backup-YYYY-MM-DD.zip` (contains `threads.json`) | Alma Settings → Data → Export all threads | | **Raycast AI** | `.json` (e.g. `raycast_ai_chats.json`) | No vendor export, so use **[raycast-ai-exporter](https://github.com/daveonkels/raycast-ai-exporter)** on macOS (see that README) | Bulk Import saves the original conversations as Threads. They are searchable immediately, so you do not need to distill hundreds of imported chats before Mem can find them. Distillation is the second step: use it for conversations that contain decisions, procedures, preferences, or lessons worth keeping as long-term Memories. For a large archive, plan extraction in small batches from the Timeline or by selecting specific threads. ### Single Thread [#single-thread] Import one conversation from a file. | Format | File Type | Notes | | ------------------------- | --------- | --------------------------------------------------------------------------- | | **Conversation Markdown** | `.md` | `## User` / `## Assistant` / `## System` headers, optional YAML frontmatter | | **Cursor** | `.md` | Cursor's native export format (auto-detected) | | **Generic Markdown** | `.md` | Any markdown file, imported as a document | If your `.md` file is a regular document (no `## User` / `## Assistant` headers), it belongs in the [Library](/docs/library), not Threads. Drag it into the Timeline or import from the Library view. ## Conversation Markdown Format [#conversation-markdown-format] The portable format for conversation import. Any tool that writes `## User` / `## Assistant` headers produces a file Nowledge Mem can read. ### Minimal Example [#minimal-example] The simplest valid file, two turns, no frontmatter: ```markdown ## User What is Python's GIL? ## Assistant The Global Interpreter Lock (GIL) is a mutex in CPython that allows only one thread to execute Python bytecode at a time. This means CPU-bound multi-threaded programs won't see speedups from threading: use multiprocessing or async I/O instead. ``` ### Full Example [#full-example] With optional YAML frontmatter and a system message: ```markdown --- title: Python Async Patterns source: chatgpt date: 2025-06-15 --- ## System You are a senior Python developer who explains concepts clearly. ## User How does async/await work in Python? ## Assistant Python's `async`/`await` lets you write concurrent code that doesn't block while waiting for I/O. An `async def` function returns a coroutine, and `await` pauses it until the result is ready, meanwhile other coroutines can run. ## User When should I use asyncio vs threading? ## Assistant Use **asyncio** for I/O-bound work (HTTP requests, database queries, file reads): it's lighter and scales better than threads. Use **threading** when you need to call blocking libraries that don't support async. Use **multiprocessing** for CPU-bound work. ``` ### Format Rules [#format-rules] * **Headers**: `## User`, `## Assistant`, or `## System`, level-2 heading, one per message * **Content**: Everything between headers is one message. Markdown formatting, code blocks, and lists are preserved as-is * **Frontmatter**: Optional YAML block at the top. Supported fields: `title`, `source`, `date`, all optional * **Detection**: Files with at least one `## User` or `## Assistant` header are recognized as conversations automatically * **Fallback**: Files without recognized headers are imported as a single document message * **Case**: Role names are matched case-insensitively (`## user` and `## User` both work) A complete example with all supported features ## Import API [#import-api] `POST /threads/import` accepts JSON messages or Conversation Markdown, with single and batch modes. ### Single Thread (JSON messages) [#single-thread-json-messages] ```bash curl -X POST http://127.0.0.1:14242/threads/import \ -H "Content-Type: application/json" \ -d '{ "title": "My Conversation", "source": "chatgpt", "messages": [ {"role": "user", "content": "Hello!"}, {"role": "assistant", "content": "Hi there! How can I help?"} ] }' ``` ### Single Thread (Markdown) [#single-thread-markdown] ```bash curl -X POST http://127.0.0.1:14242/threads/import \ -H "Content-Type: application/json" \ -d '{ "markdown_content": "## User\n\nHello!\n\n## Assistant\n\nHi there! How can I help?" }' ``` ### Batch Import [#batch-import] ```bash curl -X POST http://127.0.0.1:14242/threads/import \ -H "Content-Type: application/json" \ -d '{ "threads": [ { "title": "Thread 1", "messages": [ {"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi"} ] }, { "title": "Thread 2", "markdown_content": "## User\n\nGoodbye\n\n## Assistant\n\nSee you!" } ] }' ``` Thread IDs are auto-generated when omitted. Titles are inferred from markdown frontmatter when available. Full request/response schema and field descriptions ## CLI [#cli] The `nmem` CLI supports thread import from files, JSON, or stdin. ```bash # Import a conversation markdown file nmem t import --file conversation.md # Import with explicit title and source nmem t import --file chat.md --title "Python Async" --source chatgpt # Import from JSON messages nmem t import --messages '[{"role":"user","content":"Hello"},{"role":"assistant","content":"Hi"}]' # Bulk JSON from Raycast AI (raycast-ai-exporter output) nmem t import --file ~/Desktop/raycast_ai_chats.json # Pipe markdown from stdin cat conversation.md | nmem t import --stdin --title "Piped Conversation" ``` Run `nmem t import --help` for all options. See the [CLI Reference](/docs/cli) for the full command list. ## Browser Extension [#browser-extension] The Nowledge Mem Exchange extension works in the browser on **supported AI chat pages**, on the **session you are actually using** with the extension (for example the tab you open in the side panel). It is not a bulk downloader for your entire web chat history; for that, use each vendor’s export plus **Bulk import** in Mem, or see **[Import existing conversations](/docs/import-existing-conversations)**. Auto-capture, manual distill, and backing up the current thread are covered in the [Browser Extension guide](/docs/integrations/browser-extension). ## MCP Tools [#mcp-tools] | Tool | What it does | | ------------------------ | ----------------------------------------------------- | | `thread_search` | Search threads by keywords or list recent threads | | `thread_fetch_messages` | Fetch full messages from a specific thread | | `search_thread_messages` | Search within a thread for messages matching keywords | MCP thread tools search and read threads that already exist in Mem. To capture local coding-agent transcripts, use the native connector for that tool. To backfill older sessions, run `nmem t sync --from ` on the client machine running the agent. Supported sources include `claude-code`, `codex`, `craft-agent`, `cursor`, `gemini-cli`, `grok`, `hermes`, `kimi-code`, `kimi-work`, `mimo-code`, `omp`, `opencode`, and `pi`. That keeps transcript discovery local and uploads the normalized thread to your Mem server. ## Next Steps [#next-steps] * **[Memories](/docs/memories)**: What happens after distillation: create, search, and organize knowledge * **[Library](/docs/library)**: Import documents alongside your memories * **[Browser Extension](/docs/integrations/browser-extension)**: Capture conversations from web AI platforms * **[Connectors](/docs/integrations)**: Connect your AI tools through native connectors, reusable packages, or MCP * **[API Reference](/docs/api)**: Full REST API documentation # Troubleshooting (/docs/troubleshooting) ## All File Locations (Desktop + CLI) [#all-file-locations-desktop--cli] This is the simplified folder map used by Nowledge Mem: * **Config/state root**: `co.nowledge.mem.desktop` * **Data root**: `NowledgeGraph` * **User workspace**: `ai-now` * **Client-side tools root** (`nmem` CLI + OpenClaw plugin): `.nowledge-mem` ```text ~/Library/Application Support/co.nowledge.mem.desktop/ # config/state ~/Library/Application Support/NowledgeGraph/ # data (DB/index/logs) ~/ai-now/ # user workspace ~/.nowledge-mem/ # nmem/OpenClaw client config ``` Legacy compatibility paths you may still see: * `~/Library/Application Support/nowledge-mem/` * `~/Library/Logs/Nowledge Graph/` ```text %APPDATA%\co.nowledge.mem.desktop\ # config/state %LOCALAPPDATA%\NowledgeGraph\ # data (DB/index/logs) %USERPROFILE%\ai-now\ # user workspace %USERPROFILE%\.nowledge-mem\ # nmem/OpenClaw client config ``` ```text ~/.config/co.nowledge.mem.desktop/ # config/state (XDG_CONFIG_HOME) ~/.local/share/NowledgeGraph/ # data (XDG_DATA_HOME) ~/ai-now/ # user workspace ~/.nowledge-mem/ # nmem/OpenClaw client config ``` Package paths you may also see (depends on install method): ```text /usr/lib/nowledge-mem/ /usr/share/nowledge-mem/ ``` Legacy compatibility paths you may still see: * `~/.local/share/co.nowledge.mem.desktop/` * `~/.local/share/Nowledge Graph/` * `~/.local/share/nowledge-mem/` ## Viewing Logs [#viewing-logs] Open **Settings → Info → Show Log Files** to reveal the log folder directly in Finder or Explorer. No terminal required. If the app fails during startup, the error screen includes a **Show Logs** button that does the same thing. On macOS, the canonical system log file is located at `~/Library/Application Support/NowledgeGraph/Logs/app.log`. You can view it by running this command in your terminal: ```bash open -a Console ~/Library/Application\ Support/NowledgeGraph/Logs/app.log ``` If you upgraded from an older build, you may still have a legacy log path: ```bash open -a Console ~/Library/Logs/Nowledge\ Graph/app.log ``` On Windows, the system log file is located on two possible locations based on the installation method: * `%LOCALAPPDATA%\Packages\NowledgeLabsLLC.NowledgeMem_1070t6ne485wp\logs\app.log` (installed from Microsoft Store) * `%LOCALAPPDATA%\NowledgeGraph\logs\app.log` (installed from package file downloaded from Nowledge Mem website) You can view it by pasting this into address bar of File Explorer: ```shell %LOCALAPPDATA%\Packages\NowledgeLabsLLC.NowledgeMem_1070t6ne485wp\logs\app.log ``` or this: ```shell %LOCALAPPDATA%\NowledgeGraph\logs\app.log ``` ## Search And Index Health [#search-and-index-health] If your issue is about search quality or search-index disk usage, start here first: * Open **Settings -> Memory Processing -> Search** * Use **Optimize** when the search index takes too much disk space * Use **Rebuild Index** when search results look clearly incomplete, stale, or badly ranked The storage line in that panel separates the main parts of your local data: * **Knowledge Graph**: memories, entities, relationships, and graph metadata * **Messages**: saved conversation messages and larger text payloads * **Search Index**: a rebuildable search projection used for ranking and snippets These two actions solve different problems: * **Optimize** compacts on-disk search storage without rebuilding everything * **Rebuild Index** recreates the search index from your saved memories, library content, and message store when the existing index may be stale or corrupted If you are on a Linux server or using Mem remotely without the desktop app open: * Run `nmem status` to see whether search is ready, needs a rebuild, or is only updating metadata * Run `nmem models status` for the same signal plus model installation state * If the status says **updating metadata**, let it finish. That path does not need a rebuild. When the search index is stale (for example after you switch embedding providers or models), Mem does not error or return 500s. It falls back to keyword (FTS) search while the index catches up, and `GET /health` reports `reindex_needed: true`. Trigger the rebuild from **Settings → Memory Processing → Search** when you are ready; search keeps working the whole time. If semantic results feel weak even when the index is current, check `embedding.mode` in `GET /health`. A value of `local-hash-fallback` means no real embedder is configured, so only keyword search is fully working. Set a remote embedding provider or download the local model to restore semantic search. ## App Takes Too Long to Start [#app-takes-too-long-to-start] **Symptom:** The app hangs or shows a timeout error during startup. **Solution:** Global proxies or VPN software can prevent the app from accessing `http://127.0.0.1:14242` directly. Configure your proxy or VPN tool to bypass localhost addresses. Add the following to your bypass/exclusion rules: ``` 127.0.0.1, localhost, ::1 ``` This allows you to keep your proxy/VPN enabled while ensuring Nowledge Mem can communicate with its local server. After updating the bypass rules, restart Nowledge Mem. ## Windows Startup Fails: Missing Visual C++ Runtime [#windows-startup-fails-missing-visual-c-runtime] **Symptom:** On startup, `app.log` shows: * `Import error: DLL load failed while importing _lbug` * or `Backend exited during startup readiness check: exit code: 1` **Cause:** A required Microsoft C++ runtime dependency is missing for the bundled database engine. **Fix:** 1. Download and install **Microsoft Visual C++ Redistributable (x64)**: [https://aka.ms/vs/17/release/vc\_redist.x64.exe](https://aka.ms/vs/17/release/vc_redist.x64.exe) 2. Restart Nowledge Mem. 3. If it still fails, attach `app.log` when reporting the issue. ## AI Now Session Fails to Start [#ai-now-session-fails-to-start] **Symptom:** Clicking **New Task** or resuming a paused task fails, and AI Now cannot open a session. **What to do first:** Check the startup diagnostics card shown in AI Now. When startup fails, AI Now now shows a diagnostics card with: * failure stage (`spawn`, `initialize`, or `new_session`) * platform and process exit code * recent `stderr` output from the startup script * a copy button for sharing diagnostics Click **Details** to expand technical fields, then click **Copy diagnostics** for support or issue reports. **Common fixes (especially on Windows):** 1. Verify your installation is complete (embedded Python and startup scripts are present). 2. Restart Nowledge Mem after plugin or model configuration changes. 3. Update to the latest build if you use Windows and have shell customizations like Conda. Recent releases isolate AI Now and the bundled `nmem` launcher from broken PowerShell profile hooks so those scripts no longer fail before Mem starts. 4. Temporarily disable antivirus/quarantine rules that may block bundled Python or PowerShell startup. 5. If a plugin is involved, reconnect expired OAuth plugins in **AI Now → Plugins** and retry. ### Optional: Open Developer Console on Windows (Hotkey) [#optional-open-developer-console-on-windows-hotkey] If AI Now is still stuck and you need extra startup logs, use the built-in Windows hotkey: * Press Ctrl + Shift + I to toggle the Tauri/WebView console. * Go to the **Console** tab. * Filter logs with keywords like `[AI Now]`, `[ACP]`, or `[kimi-cli stderr]`. This works for both Microsoft Store installs and website installer builds. Then reproduce the issue by opening AI Now and clicking **New Task**. If it still fails, include copied diagnostics plus `app.log` when reporting the issue. ## Corrupted Model Cache [#corrupted-model-cache] **Symptom:** Search, memory distillation, or knowledge extraction features stop working unexpectedly. **Solution:** Clear the model cache and re-download the models. Navigate to SettingsModels, and click: After clearing the cache, re-download the required models. ## Search Index Uses Too Much Disk Space [#search-index-uses-too-much-disk-space] **Symptom:** Search works, but the search index size in **Settings -> Memory Processing -> Search** looks much larger than expected. **What to do:** Click **Optimize** in that same panel. **Optimize** compacts the search index on disk and flushes database changes. It does not delete memories or saved conversations. From v0.6.8 onward, and more aggressively for the native LanceDB search index used in 0.9.0, this can shrink storage dramatically on machines with older index versions left behind. In real cases, users may see something like **5 GB -> 300 MB** after compaction. **When to use it:** 1. The index keeps growing after updates or repeated reindexing. 2. The search index is much larger than the knowledge you actually store. 3. Search still works, but disk usage looks obviously wasteful. If the **Search Index** number still looks wrong after optimization, run **Rebuild Index** once. If the **Messages** number is large, that usually means you have imported or saved many conversations; use [Data Transfer](/docs/data-portability) for backup and migration rather than deleting index files by hand. If storage remains abnormal, include a screenshot of the **Memory Processing** panel when reporting the issue. ## Search Ranking Looks Obviously Wrong [#search-ranking-looks-obviously-wrong] **Symptom:** Search returns clearly bad matches, misses memories that should be easy to find, or feels much worse than before. **What to do:** Open **Settings -> Memory Processing -> Search** and click **Rebuild Index**. Rebuilding recreates the full search index from your saved memories, library content, and message store. This is the right recovery step when an interrupted write, stale index state, or another indexing issue has left search quality obviously degraded. **Try this when:** 1. A memory exists, but search cannot find it with reasonable queries. 2. Results are suddenly much worse after an upgrade, crash, or heavy import. 3. Ranking looks clearly inconsistent with what you know is already in Mem. After reindexing finishes, rerun the same query. If the ranking is still clearly wrong, send the query example and the expected memory when reporting the issue. ## Windows: PATH Corrupted After Install or Upgrade [#windows-path-corrupted-after-install-or-upgrade] **Symptom:** After installing or upgrading Nowledge Mem, other command-line tools stop working. Running `pnpm`, `git`, `node`, or similar commands returns "not recognized" or "command not found". Checking your user PATH shows it has been reduced to just `C:\Users\...\Nowledge Mem\cli` or has lost entries like `%PNPM_HOME%`. **Cause:** Versions before 0.6.8 could overwrite your Windows user PATH during installation by expanding environment variable references (like `%PNPM_HOME%`) into literal paths, or in some cases replacing the entire PATH with just the Nowledge Mem CLI directory. **This is fixed in 0.6.8 and later.** The installer now preserves your PATH entries and their environment variable references exactly as they were. **If you were affected, here is how to restore your PATH:** 1. Press Win + R, type `sysdm.cpl`, and press Enter. 2. Go to **Advanced** > **Environment Variables**. 3. Under **User variables**, select **Path** and click **Edit**. 4. Re-add any missing entries. Common ones include: * `%PNPM_HOME%` * `%USERPROFILE%\AppData\Local\Programs\Microsoft VS Code\bin` * `%USERPROFILE%\.cargo\bin` * `%USERPROFILE%\AppData\Roaming\npm` 5. Click **OK** and open a new terminal window. If you're not sure what your PATH should contain, check a working machine or refer to the installation docs of each tool you use (pnpm, Node.js, Rust, etc.). Each tool's installer typically documents which PATH entry it adds. ## Windows: Memories Missing After Update (Even After Rolling Back) [#windows-memories-missing-after-update-even-after-rolling-back] **Symptom:** After a Windows update, your memory count drops to zero or near zero. Rolling back to the previous version does not bring them back. **Your data is not lost.** Your graph lives in one folder, but the app is now reading a different location where an empty database got created, and that empty one is shadowing your real data. The steps below move the real data back to where the app looks. You only copy or rename, never delete, so a wrong guess is always reversible. **Before you start:** Fully quit Nowledge Mem, including from the system tray. Open Task Manager and confirm no `nmem-server` or Nowledge Mem process is still running. **Step 1: Find the real data.** Press Win + R and open each of these in turn. Some may not exist, and that is fine: * `%LOCALAPPDATA%\NowledgeGraph` (what the app reads now, usually the empty one) * `%APPDATA%\NowledgeGraph` (older location, real data is often here) * `%USERPROFILE%\Documents\NowledgeGraph` (oldest location) In each folder, compare the size of `nowledge_graph_v2.db`. Real data is tens of MB to several GB. A fresh empty database is small and was last modified on the day things broke. Also check whether a sizeable `content.db` and any `content.db.backup.*` files are present. The folder with the largest and oldest `nowledge_graph_v2.db` is your real data folder. **Step 2: Back up the current (empty) location.** In `%LOCALAPPDATA%`, rename the `NowledgeGraph` folder to `NowledgeGraph_empty_backup`. Rename it, do not delete it. **Step 3: Copy the real data into place.** Copy your real data folder into `%LOCALAPPDATA%\` so that it is named `NowledgeGraph`. Copy it, do not move it, so the original stays as a backup. **Step 4: Start the app.** Open Nowledge Mem and go to Memories. The count should return. Updating to 0.10.6 (or 0.10.5) makes the app auto-find and open your data from these old locations, as long as the current location is still empty, meaning you have not saved any new memories into the empty one. **Still stuck, or not comfortable doing this by hand:** Take a screenshot of the `nowledge_graph_v2.db` sizes in the three folders and email them, together with your `app.log` (from **Settings → Info**), to [hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai). Do not delete any `NowledgeGraph` or `_empty_backup` folder before you hear back. ## Backend Won't Start / Crash Loop (Quarantine a Corrupt Database Journal) [#backend-wont-start--crash-loop-quarantine-a-corrupt-database-journal] **Symptom:** After an update or an interrupted rebuild, the app never finishes starting and the backend keeps restarting. Sometimes a hard crash or a power loss during a write leaves the database write-ahead journal (`.wal`) in a bad state, and the backend cannot open the graph. Nowledge Mem already tries to recover from this automatically on launch: it moves a corrupt journal aside and reopens the graph. The manual step below is only for the rare case where that automatic recovery did not run. **Steps:** 1. Fully quit the app, including from the system tray. 2. Open the graph data folder for your platform: * macOS: `~/Library/Application Support/NowledgeGraph` * Windows: `%LOCALAPPDATA%\NowledgeGraph` * Linux: `~/.local/share/NowledgeGraph` 3. If a file named `nowledge_graph_v2.db.wal` exists, rename it to `nowledge_graph_v2.db.wal.corrupt-backup`. Rename it, do not delete it. 4. If `nowledge_graph_v2.db.shm` is present, rename it aside as well. 5. Start the app. Only the most recent, not-yet-saved changes can be affected. Everything already saved is intact. If it still will not start, send your `app.log` to [hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai) and keep the renamed files. ## CLI Not Found [#cli-not-found] **Symptom:** Running `nmem` in terminal returns "command not found". **Solutions by platform:** * **macOS**: Open Nowledge Mem once, then open a new terminal. The app installs or repairs `nmem` after startup without blocking the app. If the command is still missing, use **Settings → Preferences → Developer Tools → Install CLI** to repair it manually. * **Windows**: Open a **new** terminal window after app installation (the PATH update requires a fresh session) * **Windows (WSL)**: See the [WSL setup](#using-nmem-from-wsl) section below * **Linux**: Desktop packages include the CLI and the app repairs the wrapper after startup. Open a new terminal; if `nmem` is still missing, make sure `~/.local/bin` is in your shell PATH. **Quick check:** Run `nmem status` to verify the CLI can connect to Nowledge Mem. ## CLI and Server Versions Differ [#cli-and-server-versions-differ] **Symptom:** `nmem status` shows "Version mismatch". This means the command in your terminal and the Mem server it reached were installed or updated separately. The connection can still be healthy, but an older CLI may not know the latest commands or diagnostics. **Fix the side that is older:** * **Desktop CLI:** Open **Settings → Preferences → Developer Tools → Install CLI**, then restart the terminal. * **PyPI install:** Run `python -m pip install --upgrade nmem-cli`. * **pipx install:** Run `pipx upgrade nmem-cli`. * **One-shot use:** Run `uvx --from nmem-cli nmem status`. * **Server older than CLI:** Update or restart Nowledge Mem, or check that `NMEM_API_URL` points to the server you meant to use. ## Using nmem from WSL [#using-nmem-from-wsl] If you run coding agents like Claude Code or Codex inside WSL on Windows, the Windows `nmem` CLI isn't directly available in the Linux environment. **From v0.6.9**, clicking **Install CLI** in Settings automatically creates a lightweight shim inside your default WSL distribution. If you need to set it up manually, paste this into your WSL terminal: ```bash mkdir -p ~/.local/bin && cat > ~/.local/bin/nmem << 'SHIMEOF' #!/usr/bin/env bash cd /mnt/c || exit 1 exec cmd.exe /c nmem.cmd "$@" SHIMEOF chmod +x ~/.local/bin/nmem ``` This creates a thin wrapper that calls the Windows `nmem` via interop from a Windows-mounted working directory. That avoids the common UNC-path failure mode from WSL home directories. Since the command runs as a Windows process, it connects to the desktop app on `localhost` directly, so no extra network configuration is needed. **Verify it works:** ```bash nmem status ``` If `nmem` is still not found after creating the shim, make sure `~/.local/bin` is in your PATH. On Ubuntu this happens automatically; on other distributions, add `export PATH="$HOME/.local/bin:$PATH"` to your `~/.bashrc` or `~/.zshrc`. This approach requires WSL interop (enabled by default). If you've set `interop=false` or `appendWindowsPath=false` in `/etc/wsl.conf`, re-enable them or use `pip install nmem-cli` with [Access Mem Anywhere](/docs/remote-access) instead. The shim runs `nmem` as a Windows process, so commands like `nmem t save --from claude-code` look for session files in your Windows home directory rather than your WSL home. This is fine in practice: the desktop app captures WSL sessions automatically through its built-in file watcher. If you need direct CLI thread capture from WSL, use `pip install nmem-cli` instead. ## nmem status Returns "Not Found" [#nmem-status-returns-not-found] **Symptom:** `nmem status` shows "Not Found: Resource doesn't exist" when using a remote server, but the TUI works fine. **Cause:** The CLI is hitting the wrong URL. This usually means `~/.nowledge-mem/config.json` is missing or has the wrong `apiUrl`. **Fix:** 1. Verify the config file exists and has the correct URL: ```json title="~/.nowledge-mem/config.json" { "apiUrl": "https://", "apiKey": "nmem_..." } ``` 2. Test with curl: `curl -H "Authorization: Bearer $NMEM_API_KEY" "$NMEM_API_URL/health"` 3. Update to the latest `nmem` CLI. Newer versions show clearer error messages and remote setup hints. Full setup: [Access Mem Anywhere](/docs/remote-access). ## Remote Access Returns 429 [#remote-access-returns-429] **Symptom:** `nmem status` or `curl` returns `429 Too many invalid auth attempts`. **Solution:** The client retried with an invalid API key too many times. * Re-copy URL + key from **Settings → Access Mem Anywhere** * Ensure `NMEM_API_KEY` is the exact value (no extra spaces/quotes) * If unsure, click **Rotate** to issue a new key Full setup and validation steps: [Access Mem Anywhere](/docs/remote-access). ## Remote Access Returns 401 Missing API key [#remote-access-returns-401-missing-api-key] **Symptom:** Tunnel URL is reachable, but `nmem status` or `curl` returns `401 Missing API key`. **Cause:** Some network proxies remove auth headers. **Fix:** * Update to latest `nmem` (it retries with proxy-safe fallback automatically) * Re-copy URL + key from **Settings → Access Mem Anywhere** * For manual `curl`, verify with: `curl "$NMEM_API_URL/health?nmem_api_key=$NMEM_API_KEY"` ## Mem Says Graph Memory Was Increased [#mem-says-graph-memory-was-increased] **Symptom:** Search, graph, or save operations start failing on a larger library, and Mem shows a title-bar notice that graph memory was updated. **Cause:** Mem raised the graph-memory limit for the next launch after the current session ran out of room. The running backend is still on the old limit until you reopen the app. **Fix:** 1. Quit and reopen Nowledge Mem. That applies the higher graph-memory limit. 2. If the notice keeps coming back, open **Settings → Processing → Database Tuning** and choose a larger **Graph Memory** value. 3. On headless or server installs, set `NOWLEDGE_KUZU_BUFFER_POOL_SIZE=512MB` (or higher) before starting `nmem serve`. ## Mem Looks Like It Uses a Lot of RAM [#mem-looks-like-it-uses-a-lot-of-ram] **Symptom:** Activity Monitor (macOS) or Task Manager (Windows) shows Nowledge Mem using around a gigabyte of memory, which looks high for a notes-and-memory app. **This is normal, and the number is misleading.** The figure your system monitor shows is not how much memory Mem actually needs. Most of it falls into three buckets that do not count as real pressure on your machine: * **Memory we have already finished with.** After bursts of work like search, importing, or background processing, your operating system keeps those pages parked with Mem instead of reclaiming them right away, because handing them back and forth is slow. They are free to be reused the moment anything else needs them. * **Shared program code.** Mem ships as a single self-contained app, so its program code shows up in the memory number, but it is shared and read-only and the system drops it instantly under pressure. * **Your knowledge stored on disk.** Your graph and search index live as files on disk. The system counts them toward Mem's memory because it maps them in for fast reads, but they are not really sitting in RAM, and they are released as needed. Mem's actual working memory is well under what the headline number suggests, and it holds **no AI model in memory unless you are running a local model**. You do not need to take any action. If your machine genuinely runs low on memory, the system reclaims most of this automatically. An upcoming update also changes how Mem returns idle memory to the system, so the reported number will get smaller on its own.
The actual measurement, if you want to verify Measured on a real library of about 2,100 memories, sitting idle, using each operating system's own tools. The takeaway is the same everywhere: the headline number is much larger than the memory actually in use. **macOS**: reproduce with `footprint ` or `vmmap -summary ` against the `nmem-server` process: | What | Size | | ----------------------------------------------- | ------------------- | | Reported memory (`phys_footprint`) | \~1024 MB | | Shared program code (read-only, reclaimable) | \~281 MB | | Database file mapped in (lives on disk) | \~0.3 MB resident | | Already-freed memory not yet returned to the OS | \~500 MB | | Real in-use memory | the small remainder | On a Mac, Mem runs the local embedding model on the GPU, so its working buffer stays off the main number and the figure above is mostly reclaimable. **On a computer without a usable GPU** (some Windows and Linux setups, or a headless server), the local embedding model runs on the CPU instead and reserves a larger working buffer, so the number is genuinely higher there (measured around 4-5 GB). This only applies when you run the embedding model **locally on the CPU**. The easiest way to avoid it is to use a **remote embedding model**, which keeps this buffer off your machine entirely: **Nowledge AI** (included with Mem Plus) works with no setup, or you can connect your own embedding provider with your own key. Running the local model on a machine with a GPU also keeps it small. We are additionally shrinking the local CPU buffer in an upcoming update.
## Linux Server Setup Says It Cannot Reach 127.0.0.1:14242 [#linux-server-setup-says-it-cannot-reach-12700114242] **Symptom:** Commands like `nmem license activate`, `nmem models download`, or `nmem config ...` fail with “Cannot reach [http://127.0.0.1:14242”](http://127.0.0.1:14242”). **Cause:** Those commands talk to your local Mem server. On a fresh Linux server, that usually means the server is not running yet, or you started it in the foreground and forgot you still need a second terminal. **Fix:** 1. For a real server, install the background service first: `sudo nmem service install --service-user ` 2. Then verify it is up: `nmem service status` and `nmem status` 3. If you are only doing a quick test with `nmem serve`, keep that terminal open and run the other `nmem` commands in a second terminal 4. To open the web app from your own computer over SSH, run `nmem key --show-login` first and forward the same port it prints: `ssh -L :127.0.0.1: ` 5. To print the login key again, run `nmem key --show-login` on newer builds, or `nmem key` on older ones ## Report Issue [#report-issue]
# Try These (/docs/try-these) Your Timeline input handles everything: questions, captures, URLs, files, scheduling. Type naturally and AI figures out the rest. Here are the queries that show what the system can really do. These queries get more powerful as your knowledge grows. After a week of regular use, the results will surprise you. ## The Queries [#the-queries]
### Show my Working Memory briefing [#1-show-my-working-memory-briefing] Reads your current focus surface. What topics are active, what needs attention, and what changed recently. Native integrations and well-configured agents can load the right Working Memory briefing automatically at session start.
### Which of my ideas have evolved the most? [#2-which-of-my-ideas-have-evolved-the-most] Finds the longest EVOLVES chains, ideas that went through multiple revisions. Tells the story chronologically: "In January you decided on PostgreSQL. By March, you were considering a hybrid approach. Your latest note confirms the dual-database migration."
### What wisdom has crystallized from my notes? [#3-what-wisdom-has-crystallized-from-my-notes] Shows synthesized crystals, reference articles the system distilled from multiple related memories overnight. These are the insights you couldn't get from any single note.
### Summarize my recent coding conversations [#4-summarize-my-recent-coding-conversations] If your coding sessions are already flowing into Mem through local auto-sync, native save paths, or thread import, this lists and summarizes the latest ones: what was discussed, what was built, what decisions were made.
### Just decided to use PostgreSQL for the main database [#5-just-decided-to-use-postgresql-for-the-main-database] Knowledge capture. The system saves it as a memory, searches for related decisions, and mentions connections: "This relates to your earlier note about database scaling." Just type naturally, the AI classifies what you share and stores it.
### Save `https://example.com/interesting-article` [#6-save-httpsexamplecominteresting-article] Paste a URL and the system fetches, parses, and indexes the content. AI reads the page and stores a substantive summary as a memory. The URL and its content become searchable. Add a note before the URL and AI captures both.
### Tonight, run knowledge graph extraction on my recent memories [#7-tonight-run-knowledge-graph-extraction-on-my-recent-memories] Schedule a Background Intelligence task. The agent fires at the specified time with full tool access: it can analyze memories, detect contradictions, create EVOLVES links, or produce crystals. Natural language timing: "in 2 hours", "tomorrow morning", "next week". Min 5 minutes, max 30 days.
### Search my documents for \[topic] [#8-search-my-documents-for-topic] Full-text search across all source documents in your Library. Drop files (PDF, Word, markdown) onto the Timeline input or add them through the Library. They get parsed, chunked, and indexed for semantic search.
### What are my main knowledge themes? [#9-what-are-my-main-knowledge-themes] **Note**: This requires a week of regular use and background processing. Community detection clusters your entities into topic areas with AI summaries. The system runs overnight analysis to group related concepts. You'll see themes you never consciously tracked: a "developer experience" cluster you didn't know existed, or a "data architecture" theme threading through months of notes.
## The Compound Effect [#the-compound-effect] These queries get more powerful over time: * **Week 1**: Basic search works. Communities are small or empty. * **Month 1**: Evolution chains appear. Crystals start forming. Themes emerge. * **Month 3**: Cross-domain connections surprise you. Daily briefings are genuinely useful. * **Month 6**: The system knows your expertise better than you can articulate it. ## Next Steps [#next-steps] * [Getting Started](/docs/getting-started): Set up in five minutes * [See Your Expertise](/docs/use-cases/expertise-graph): Explore the knowledge graph visually * [Background Intelligence](/docs/advanced-features): How the system learns overnight # Using Nowledge Mem (/docs/usage) Go back to [Start Here](/docs/start-here) and [How To Know Mem Is Working](/docs/verify-it-works). This page makes more sense once you have already proven one real workflow. ## The Timeline [#the-timeline] The Timeline is your home screen. Everything lives here: what you capture, what you ask, what the system discovers on its own. Nowledge Mem Timeline ### What You'll See [#what-youll-see] | Item | What it is | | ------------------ | ------------------------------------------------------------- | | **Capture** | A memory you saved, with auto-generated title and tags | | **Question** | Your question and the AI's answer, drawn from your knowledge | | **URL Capture** | A web page fetched, parsed, and stored | | **Insight** | A connection the system discovered between your memories | | **Crystal** | A crystal synthesizing multiple related memories | | **Flag** | A contradiction, stale info, or claim that needs verification | | **Working Memory** | Your daily morning briefing | ## Your AI Tools [#your-ai-tools] Connect the AI tools you actually use to your knowledge. Claude Code, Grok Build, Cursor, Codex, OpenCode, Alma, DeepChat, LobeHub, Grok Web, and more can all point back to the same memory system through the right path. If you are still deciding how to connect a tool, go to [Connectors](/docs/integrations) first. This page is about what Mem feels like after one setup path is already working. **Without Mem:** *"Help me implement caching for the API."* Your agent often asks about your stack, your infrastructure, and your preferences. You explain everything from scratch. **With Mem:** *"Help me implement caching for the API."* Your agent can search your knowledge, find your Redis decision from last month and your API rate limiting patterns, and write code that fits your architecture with much less repeated setup. In the best-integrated setups, this happens without prompting. Native integrations, well-configured reusable workflow packages, and MCP clients with clear intent rules can recognize when your knowledge is relevant and use it automatically.
Save an insight in Claude Code today. Cursor finds it tomorrow when it encounters the same topic. No copying, no exporting. You can also query directly: *"What did I decide about database migrations last month?"* Your agent searches your knowledge to answer. See [Connectors](/docs/integrations) for setup instructions. ## Search [#search] ### In the App [#in-the-app] Open memory search with Cmd + K (macOS). Search understands meaning, not just keywords. Searching "design patterns" finds memories about "architectural approaches." Memory Search Three search modes work together: * **Semantic** finds memories by meaning * **Keyword** does exact match for specific terms * **Graph** discovers memories through entity connections and topic clusters ### From Anywhere [#from-anywhere] Press Cmd + Shift + K from any application to search without opening Nowledge Mem. Copy results directly where you need them. The [Raycast extension](/docs/integrations/raycast) brings the same search into your launcher. Memory Search Launcher
## What Happens Over Time [#what-happens-over-time] After a few weeks of daily use, the system starts working for you in the background. You save a decision about PostgreSQL on Tuesday. On Thursday, you mention CockroachDB as a migration target. Friday morning, Working Memory notes: "Your database thinking is evolving." This is **Background Intelligence**: * **Knowledge evolution.** Detects when your thinking on a topic changes and links the versions. * **Crystals.** Synthesize scattered memories into reference articles. * **Flags.** Surfaces contradictions between past and present thinking. * **Working Memory.** A daily briefing your AI tools read at session start. Background Intelligence requires a configured Remote LLM and the appropriate license for your build. ## AI Now [#ai-now] A personal AI workspace connected to your Mem server. It can use your saved knowledge, connected notes, files, and enabled plugins, and the same sessions are available from desktop, web, and mobile clients. See [AI Now](/docs/ai-now) for the full guide. ## Command Line [#command-line] The `nmem` CLI gives full access from any terminal: ```bash # Search your memories nmem m search "authentication patterns" # Add a memory nmem m add "We chose JWT with 24h expiry for the auth service" # JSON output for scripting nmem --json m search "API design" | jq '.memories[0].content' ``` See the [CLI reference](/docs/cli) for the complete command set. ## Remote LLMs [#remote-llms] By default, everything runs locally. No internet required. As your knowledge base grows, a remote LLM gives you stronger processing. Remote LLM configuration depends on the license and build you are using. **What it unlocks:** * **Background Intelligence**: automatic connections, crystals, insights, and daily briefings * Faster knowledge graph extraction * More nuanced semantic understanding * AI Now agent capabilities **Privacy:** your data is sent only to the LLM provider you choose. Never to Nowledge Mem servers. Switch back to local-only at any time.
### Open Remote LLM settings [#open-remote-llm-settings-step] Go to **Settings > Remote LLM**
### Enable remote mode [#enable-remote-mode-step] Toggle **Remote** to enable
### Add provider and API key [#add-provider-and-api-key-step] Select your LLM provider and enter your API key
### Test, pick a model, and save [#test-pick-a-model-and-save-step] Test the connection, select a model, and save Remote LLM
## Next Steps [#next-steps] * **[Start Here](/docs/start-here)**: Pick the simplest path for your real workflow * **[How To Know Mem Is Working](/docs/verify-it-works)**: Confirm search, capture, and connected tools * **[Memories](/docs/memories)**: Create, search, organize, and connect your knowledge * **[Threads](/docs/threads)**: Capture, browse, and distill AI conversations * **[Library](/docs/library)**: Import documents alongside your memories * **[AI Now](/docs/ai-now)**: Deep research and analysis powered by your knowledge * **[Background Intelligence](/docs/advanced-features)**: Knowledge graph, insights, crystals, working memory * **[Your Profile](/docs/profile)**: Tell Mem who you are so agents give better results * **[Connectors](/docs/integrations)**: Choose the right connection path for each AI tool # How To Know Mem Is Working (/docs/verify-it-works) Mem is working when you can point to one result and say: * that came from my own knowledge * that thread was really captured * that tool really used my saved context This page is for proving that, quickly. ## The Core Test [#the-core-test] Before testing any connector, prove the app loop first:
### Save One Memory [#save-one-memory-step] In the Timeline, write one real fact, decision, or preference and press Enter.
### Ask For It Back [#ask-for-it-back-step] Ask a direct question about that memory: > What did I decide about deployment?
### Look For A Grounded Answer [#look-for-a-grounded-answer-step] Mem is working if the answer clearly reflects what you saved instead of giving a generic answer.
## If You Use The App Only [#if-you-use-the-app-only] You should be able to do all three: * save a memory in the Timeline * search for it again * ask a question that is answered from your own knowledge If that loop works, the base product is working. ## If You Use The Browser Extension [#if-you-use-the-browser-extension] Mem is working when all of these are true: * the extension can open its side panel * connection testing succeeds if you are using remote access * one captured or distilled web conversation shows up in Mem * you can open that saved result from the app as a memory or a thread If you have not reached that state yet, go to the [Browser Extension guide](/docs/integrations/browser-extension). ## If You Use A Coding Assistant [#if-you-use-a-coding-assistant] Mem is working when your tool can use context you already saved. Try this: 1. Save a short decision in Mem, such as your preferred caching approach. 2. Open your coding assistant through its dedicated connector. 3. Ask a question that should benefit from that saved context. Examples: * "What did I decide about caching for this service?" * "Continue the approach I used before for authentication." * "Search my prior decisions about Redis." You have a real working connection when the tool recalls your knowledge instead of asking you to restate everything from scratch. Use the matching guide: * [Claude Code](/docs/integrations/claude-code) * [Cursor](/docs/integrations/cursor) * [Gemini CLI](/docs/integrations/gemini-cli) * [Copilot CLI](/docs/integrations/copilot-cli) * [OpenClaw](/docs/integrations/openclaw) * [Alma](/docs/integrations/alma) * [Codex](/docs/integrations/codex-cli) ## If You Use AI Now [#if-you-use-ai-now] AI Now is working when: * your Remote LLM is configured if required for the feature you are using * you ask a question about your own saved knowledge * the answer is grounded in your memories, files, or enabled plugins rather than sounding generic If AI Now cannot start or cannot answer from your saved context, check [AI Now](/docs/ai-now) and [Troubleshooting](/docs/troubleshooting). ## If You Use Mem Across Multiple Devices [#if-you-use-mem-across-multiple-devices] Your sync setup is working when all of these are true: * the second device connects successfully with the same Mem URL and API key * a memory or thread created on one client appears on the other client * search results on both clients reflect the same knowledge base If you are unsure what model Mem uses here, read [Sync Across Devices](/docs/sync). For setup details, read [Access Anywhere](/docs/remote-access). ## Good Signs [#good-signs] * Search returns your own wording, decisions, or references * A captured conversation appears in Threads * Your connected tool can recall a prior decision without you pasting it again * AI Now can answer based on your saved knowledge ## Warning Signs [#warning-signs] * You only get generic model output with no sign of your saved context * You configured many paths, but none produced one visible result * You are testing MCP or CLI before verifying the app itself * You expect browser capture, coding-agent save, and AI Now to all prove themselves at the same time ## If It Still Feels Unclear [#if-it-still-feels-unclear] Go back to one path only: 1. [Start Here](/docs/start-here) 2. Save one memory in the Timeline 3. Verify the app loop 4. Connect only one real tool ## Next Steps [#next-steps] * [Start Here](/docs/start-here): Pick the right first path * [Getting Started](/docs/getting-started): Learn the Timeline workflow * [Connectors](/docs/integrations): Connect the right tool the right way * [Sync Across Devices](/docs/sync): Understand the single-Mem, multi-client sync model * [Troubleshooting](/docs/troubleshooting): Diagnose startup, connection, and session issues # API Reference (/docs/api) The Nowledge Mem server exposes a local REST API on port `14242`. Every feature in the desktop app and MCP tools uses these same endpoints, so you can build your own connectors, scripts, and automations on top of the same data. Base URL: `http://127.0.0.1:14242` *** ## Graph Visualization [#graph-visualization] Open an interactive, force-directed knowledge graph right in your browser — no desktop app required. ## Memories [#memories] Create, search, and manage your knowledge base. #### Count semantics [#count-semantics] Counts are reported per lifecycle state, so different views can differ without anything being lost. On `/stats`, `memory_count` is the **active** working set (what `/memories` returns by default and what the Memories page shows). The full picture is broken out as `memory_archived_count` (superseded and retired memories, kept in history), `memory_stored_count` (active + archived), and `crystal_count` (synthesized summaries, counted separately). The `/memories` `state` query param selects the lens: `active` (default), `archived`, or `all`. ### Knowledge Extraction [#knowledge-extraction] Extract entities and relationships from memory content into the knowledge graph. ### Distillation [#distillation] Turn conversation threads into structured memories. ## Threads [#threads] Import, search, and manage conversation threads from Claude Code, Codex, Cursor, and more. ### Session Import [#session-import] Auto-discover and import coding sessions from AI assistants. ### Import Configuration & Watcher [#import-configuration--watcher] ## Background Intelligence [#background-intelligence] The background agent that runs daily briefings, crystallization, insight detection, and more. ### Agent Triggers [#agent-triggers] Manually trigger agent tasks that normally run on a schedule. ### Feed Events [#feed-events] The event stream powering the desktop Feed view. ## Nowledge FS [#nowledge-fs] Browse Mem as a path-first tree for scripts, web clients, and agents. ## Spaces [#spaces] Manage shared space profiles and discover the current roster across clients. ## Sources (Library) [#sources-library] Ingest files, URLs, and documents into the knowledge base. ### Ingestion [#ingestion] ## Graph Analysis & Maintenance [#graph-analysis--maintenance] Advanced graph operations — community detection, centrality, orphan cleanup. ## Labels & Organization [#labels--organization] ## Favorites [#favorites] ## Skills [#skills] Procedural memory: skills born from your evidence, proven before they run, sharpened with use. ## Entities & Communities [#entities--communities] ## Models & Search Index [#models--search-index] Manage the embedding models and search infrastructure. ## Storage & Data [#storage--data] ## System [#system] ## Embeddings (OpenAI-compatible) [#embeddings-openai-compatible] Drop-in replacement for OpenAI's embedding API, powered by the local model. # AI Profiles (/docs/concepts/ai-profiles) An AI Profile is a stable identity for an agent that works for you over time. Use one when an agent is more than a one-off chat: a reviewer, a researcher, a release helper, a writing partner, or a worker launched by a multi-agent tool. The profile tells Mem who that agent is, which memory space it usually belongs to, and which rules should shape its behavior before it starts working. ## Why this exists [#why-this-exists] AI tools already have many places to keep behavior: `AGENTS.md`, `CLAUDE.md`, Cursor rules, Codex profiles, Hermes souls, and host-specific settings. That works until you have several agents and several hosts. Then "Codex" is not enough information. Codex may be running your reviewer today and your release helper tomorrow. Mem separates two facts: | Field | What it means | | -------------- | ----------------------------------------------------------------------------- | | **AI Profile** | Which long-running agent is working, such as `cindy` or `release-reviewer` | | **Source app** | Which runtime produced the event, such as `codex`, `claude-code`, or `hermes` | The source app is provenance. It is not identity. ## The first useful move [#the-first-useful-move] Create one profile only for a real recurring role. For example: * name: `Cindy` * id: `cindy` * default space: `product` * role: "Review product-facing changes. Be concise. Check tests before approving." Then start that worker with `NMEM_AGENT_ID=cindy`, or pass `agent_id="cindy"` through a supported MCP or API call. The next Context Bundle should show Cindy as the selected AI profile. ## What an AI Profile can carry [#what-an-ai-profile-can-carry] An AI Profile can define: * a display name and stable id * a short description of the agent's role * a default space for memory reads and writes * profile-specific Rules * optional external aliases, used only when an integration needs to map its own stable worker id to a Mem profile Keep it small. A profile should answer "who is working?" and "where should they usually work?", not contain every instruction the agent may ever need. ## How it differs from nearby concepts [#how-it-differs-from-nearby-concepts] | Concept | Use it for | | ---------------- | --------------------------------------------------------- | | **Your Profile** | Who you are, your language, aliases, and personal context | | **AI Profile** | Who this long-running agent is | | **Space** | Which lane of memory this work belongs to | | **Rule** | What behavior should always apply | | **Skill** | How to perform one repeatable task | If the same agent should behave differently for a different job, create a new profile. Do not overload one identity with incompatible work just because the host makes it easy to reuse a name. ## How connected tools select it [#how-connected-tools-select-it] Mem selects an AI Profile only from an explicit identity signal. For normal setups, use one of these: * `NMEM_AGENT_ID` * `agent_id` Advanced integrations may also map their own stable worker id onto a profile: * `NMEM_HOST_AGENT_ID` * `host_agent_id` Treat this as an external alias, not a second identity. Most users should never need it. It does not select a profile from `source_app`. A plain Codex session should not become Cindy just because the source app is `codex`. ## What to ignore for now [#what-to-ignore-for-now] You do not need a profile for every chat window. The default profile is fine for normal use. You do not need to create profiles for every tool you use. Create profiles for stable roles, not for runtimes. You do not need to design a full team hierarchy. Start with one real agent that comes back often. ## Where to go next [#where-to-go-next] * [Context](/docs/ai-context) to preview what a selected profile receives. * [Rules](/docs/concepts/rules) to shape behavior for everyone, one profile, or one space. * [Spaces](/docs/spaces) if profiles need separate memory lanes. # Background intelligence (/docs/concepts/background-intelligence) Most of what makes Mem useful happens in the background. Entity extraction, EVOLVES detection, contradiction flagging, Crystal synthesis, Working Memory updates: these run without you doing anything. You save a memory or import a thread, and the system takes it from there. This page explains what runs, when it runs, and what keeps it from going off the rails. ## Two kinds of triggers [#two-kinds-of-triggers] Background tasks fall into two categories based on what starts them. ### Scheduled tasks [#scheduled-tasks] These run on a clock, regardless of what you did today. * **Daily briefing** runs early morning. Reviews recent activity, generates insights, flags contradictions, and writes a fresh Working Memory briefing for each active space. The Default space keeps the familiar `~/ai-now/memory.md` compatibility file. * **Crystallization review** runs weekly. Looks for clusters of related memories that could be synthesized into a Crystal. * **Insight detection** runs weekly. Searches for cross-domain connections and patterns across your knowledge base. * **Skill suggestions** run every 3 days by default. Looks for repeated ways of working that may be worth teaching your AI as a [Skill](/docs/concepts/skills). * **Rule suggestions** run every 3 days by default. Looks for repeated preferences and standing rules your agents may need to follow. Suggestions stay as drafts until you review them. * **Memory compaction** runs weekly when enabled. Reviews redundant memories and consolidates confirmed duplicates. * **Label consolidation** runs weekly when enabled. Reviews duplicate labels, including labels written in different languages, before merging them. * **Community detection** runs periodically. Rebuilds the entity graph's community structure for community-based search. * **Memory freshness** runs daily when enabled. Recalculates freshness and confidence scores for all memories. * **Memory type review** runs every 3 days by default in small batches. Helps file memories as facts, decisions, procedures, learnings, or events so agents can retrieve the right context. ### Event-driven tasks [#event-driven-tasks] These fire in response to something you did, after a short delay. * **EVOLVES detection** is triggered when you save a new memory. The system checks whether it replaces, enriches, confirms, or challenges something you already know. See [knowledge evolution](/docs/concepts/evolves). * **Entity extraction** is triggered alongside EVOLVES detection. Extracts entities and relationships for the knowledge graph. * **Memory type review** is triggered in a small batch after new memories arrive. It improves how memories are organized without rewriting your saved memory text. * **Working Memory refresh** is triggered when new memories arrive. Updates the current space's Working Memory so connected agents see new context quickly. * **Cluster evaluation** is triggered after EVOLVES edges are created. Checks whether a new cluster has reached the threshold for Crystal formation. ## The cascade [#the-cascade] These are not independent. A single action can trigger a chain: You save a memory → EVOLVES detection runs → finds a "confirms" link to an older memory → cluster evaluation fires → discovers three related memories now form a strong enough cluster → a Crystal is created. Each step in the cascade has its own delay, so the system batches work rather than reacting to every individual event instantly. If you save five memories in quick succession, the system processes them together rather than running five separate analysis passes. ## Guardrails [#guardrails] Background intelligence burns LLM tokens. Without limits, a burst of activity could drain your token budget or produce low-quality results from rushing through too many tasks. Four layers prevent this. **Debouncing.** Event-driven tasks wait before executing. If another event of the same type arrives during the wait, the timer resets. This batches rapid-fire events (like importing a conversation with many messages) into a single analysis pass. **Hourly pacing.** When you keep a local hourly token limit, Mem also spaces out background LLM tasks so a busy backlog does not rush through the hour. Set the hourly limit to `0` or leave it blank to remove this local hourly pacing. Provider cooldowns, daily limits, and per-task safety checks still apply. **Token budget.** You can set hourly and daily token limits. When the budget runs out, the system pauses LLM tasks until the next period. Direct-function tasks (like decay refresh and community detection) are not affected because they do not use LLM calls. **Quality gates.** The system suppresses low-value output. If a daily briefing produces zero insights, zero Crystals, and zero flags, it stays silent rather than generating a "nothing to report" card. Insight detection checks against the last two weeks of previous insights to avoid duplicates. Crystal formation requires three or more converging sources before creating anything. ## Context injection [#context-injection] Each background task receives pre-computed context before it starts. The daily briefing, for instance, gets a digest of the past week's activity, yesterday's Working Memory, graph statistics, and recent resolution patterns. This avoids expensive LLM discovery steps and keeps each task focused. Context is capped to prevent prompt bloat. If the pre-computed context exceeds the cap, lower-priority sections are trimmed first. ## Working Memory [#working-memory] Working Memory is the daily briefing's most visible output. Every morning, the system archives yesterday's working memory and writes a fresh one based on recent activity. The Default space keeps a file at `~/ai-now/memory.md`. If you use spaces, other spaces get their own Working Memory briefings behind the same Mem APIs and integrations. This is how Claude Code, Grok Build, Cursor, Codex, and other tools know what you have been working on and what decisions you have made recently. Working Memory also updates during the day. When you save new memories, the system refreshes the file (after a longer delay than other event-driven tasks, since it is more expensive to run). You can also edit it manually. ## Processing settings [#processing-settings] The Processing settings page gives you two controls for most tasks: * **Run** starts that task once now. * **The switch** controls whether Mem may run that task automatically in the future. Small maintenance runs from Settings apply their safe, reviewed changes. For example, Memory Type Review only applies high-confidence type fixes from a bounded batch. The green dot in Settings means a background task is currently running. Open **Settings → Processing** to see the current task name, when it started, and any available progress. Recent runs show the latest task outcomes and reported or estimated token usage. Non-LLM housekeeping tasks show `0 tokens`; LLM-backed tasks show approximate usage, and mark provider calls whose exact usage was not reported. ## Usage boundaries [#usage-boundaries] The AI usage card in **Settings → Processing** is a local safety ledger, not a universal bill. It tracks: * automatic Mem background jobs that run on this device * built-in foreground AI sessions such as AI Now and Graph Intelligence, when the provider reports usage * Plus managed-AI credit, when you are signed in to a Plus plan It does not track every AI call made around Mem. Browser or Exchange agents, browser extensions, external IDE agents, and third-party hosts may call models through their own runtime or provider account. Those costs can be real, but they belong to that host's own bill or provider dashboard, not this local Mem ledger. If you use your own API key, the provider's dashboard is still the source of truth for billing. Mem's local numbers help you cap automatic work and notice unusual activity, but they are not a replacement for the provider invoice. Some providers do not return token usage for every response. When that happens, Mem marks the run as partially reported so you know the total may be lower than the real spend. Not every task has the same risk profile: * **Safe housekeeping**: Memory Freshness and Memory Type Review improve which memories surface first and how they are filed. They do not rewrite your saved memory text. * **Review-first maintenance**: Memory Maintenance can prepare a Timeline review when old or overlapping memories may be adding noise. The refresh itself never archives, merges, deletes, or rewrites memories. * **Merging tasks**: Memory Compaction and Label Consolidation can merge graph records after review. They are off by default; turn them on only if you want Mem to keep those graphs tidier automatically. * **Moving aside**: Low-risk facts and events can be moved out of everyday recall only after review. Preferences, decisions, procedures, plans, learnings, rules, identities, and context memories are not mechanically archived; they are treated as material for semantic organization instead. For normal use, leave Background Intelligence on and keep the defaults. If you run a server or VPS install, use the token limits on the same page to cap background AI cost. Large maintenance sweeps, such as full memory-type reclassification, can use substantial AI credit and touch many memories. Run them from the CLI, preview the result first, then apply it only when you understand the changes: ```bash nmem memories reclassify-types --target-type procedure --full-scan --wait nmem memories reclassify-types --target-type procedure --full-scan --apply --wait ``` ## Task controls [#task-controls] Every background task has its own toggle. You can turn off EVOLVES detection while keeping the daily briefing, or disable insight detection while keeping entity extraction. The master toggle disables everything at once. Token budgets and scheduling (briefing hour, community detection interval) are also configurable. Background Intelligence requires a remote LLM to be configured, since the tasks run on your machine and need a model to reason with. ## Next steps [#next-steps] * [Memory decay](/docs/concepts/memory-decay) covers the decay refresh task and how scores are calculated * [Knowledge evolution](/docs/concepts/evolves) explains EVOLVES detection in detail * [Crystals](/docs/concepts/crystals) explains crystallization review and what triggers Crystal creation # Crystals (/docs/concepts/crystals) You mention React performance tips in a ChatGPT session. A week later, you discuss the same topic in Cursor. A month after that, you save an article about it. Each memory is useful on its own, but none gives you the full picture. Crystals are what happens when the system notices this convergence and synthesizes a single, comprehensive reference from the pieces. ## What a Crystal is [#what-a-crystal-is] A Crystal is a memory, but a special kind. It is synthesized from three or more source memories that independently touch the same topic. The system reads the sources, identifies what each one contributes, and writes a unified summary that stands on its own. The result is a reference article you can read without hunting down the original conversations. It answers the question "what do I actually know about X?" with a single, coherent document instead of scattered fragments. Crystals are not auto-generated summaries. They require convergence from multiple independent sources, and the synthesis is evaluated for quality before anything is created. ## How Crystals form [#how-crystals-form] Crystal formation follows a pipeline: 1. **EVOLVES detection** finds that a new memory relates to existing ones. The system creates relationship edges (replaces, enriches, confirms, or challenges). 2. **Cluster evaluation** fires after new edges are created. It checks whether any cluster of related memories has reached the convergence threshold: three or more source memories on the same topic, with enough distinct information to warrant synthesis. 3. **Synthesis** happens if the cluster qualifies. The system reads all source memories, identifies what each one contributes, and produces a unified Crystal. The Crystal links back to every source through CRYSTALLIZED\_FROM edges, so you can always trace where the knowledge came from. This pipeline runs as part of [background intelligence](/docs/concepts/background-intelligence). A dedicated weekly crystallization review also scans for clusters that event-driven detection might have missed. ## Why three sources [#why-three-sources] Two sources is a correlation. Three is a pattern. The minimum of three independent sources is a quality gate that prevents weak connections from being elevated to reference status. The sources do not need to come from the same platform. A Crystal built from a ChatGPT conversation, a Cursor session, and a manually saved note is often more valuable than one built from three messages in the same thread, because the cross-platform convergence is stronger evidence that the knowledge matters. ## Reviewing Crystals [#reviewing-crystals] Every Crystal starts as unreviewed. You can confirm it, dismiss it, or edit it. **Confirm** means you have read the synthesis and it reflects your actual understanding. Confirmed Crystals receive a search ranking boost, so they surface more readily when you search. An amber banner on unreviewed Crystals shows Confirm and Dismiss buttons; once confirmed, a green check replaces it. **Dismiss** means the synthesis missed the mark. Dismissed Crystals receive a heavy ranking penalty and are visually dimmed in your library. They are not deleted, so you can revisit the decision later. **Edit** a Crystal's title or content and it is automatically confirmed. If the system got the gist right but the wording wrong, just fix it. Crystals you have not reviewed yet receive no ranking boost. They need to earn trust before the system treats them as authoritative. ## Speaker attribution [#speaker-attribution] When a Crystal draws from conversations between you and an AI assistant, the synthesis distinguishes who said what. Your own statements ("I will go with Postgres") are recorded as decisions. AI recommendations ("Based on your latency requirements, consider Redis") are recorded as suggestions with their reasoning. This prevents the common problem where AI-recommended options are presented as if you chose them. Exploring an idea in conversation is not the same as committing to it. ## How Crystals affect search [#how-crystals-affect-search] Confirmed Crystals receive a ranking boost in search results. The reasoning is straightforward: a confirmed Crystal represents corroborated, user-verified knowledge, which is more likely to be what you are looking for than any single raw memory. The boost is meaningful but not overwhelming. A Crystal that is only loosely relevant to your query will not outrank a raw memory that is a perfect semantic match. Semantic relevance is still the dominant ranking signal. Unreviewed Crystals get no boost; dismissed Crystals are penalized. Crystals also contribute to the [confidence score](/docs/concepts/memory-decay) of their source memories. If a memory has been used as a source for one or more Crystals, that counts as evidence of its value. ## What you see [#what-you-see] Crystals appear in your feed timeline with their source count and the platforms they drew from. You can confirm, dismiss, or edit a Crystal directly from the feed without opening a separate view. Hover over a Crystal card and click the pencil icon to edit its title and content in place, then press Cmd+Enter to save. You can also open a Crystal to read the full synthesis and drill into individual sources for original context. In the graph view, Crystals appear as distinct nodes with edges pointing back to their sources. Double-clicking a Crystal expands these edges so you can see the full provenance. ## Updates, not auto-mutation [#updates-not-auto-mutation] Knowledge evolves. The sources that formed a Crystal might get updated, contradicted, or replaced by newer understanding. When this happens, the system flags the Crystal as stale and proposes a re-evaluation rather than silently rewriting it. Crystals you have already confirmed are prioritized for re-evaluation. Crystals you dismissed are left alone. The system proposes; you decide. ## Next steps [#next-steps] * [Knowledge evolution](/docs/concepts/evolves) explains the EVOLVES edges that feed into Crystal formation * [Background intelligence](/docs/concepts/background-intelligence) covers when crystallization runs and how it is scheduled * [Search architecture](/docs/concepts/search-architecture) explains how Crystals affect ranking # Knowledge evolution (/docs/concepts/evolves) Knowledge changes. You make a decision in March, refine it in June, and reverse it in October. Most systems either overwrite the old version or keep everything as a flat list. Neither is useful when you need to understand how your thinking evolved. Nowledge Mem uses a model called EVOLVES to link related memories with explicit relationships. Instead of losing history or drowning in duplicates, you get a traceable chain of how each piece of knowledge transformed. ## Four relationship types [#four-relationship-types] When the system detects that a new memory relates to an existing one, it creates one of four links: | Relationship | What it means | When it happens | | -------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | **Replaces** | Your understanding has changed. The new memory supersedes the old one. | "Use CockroachDB" replaces "Use PostgreSQL" | | **Enriches** | You added depth or detail to something you already knew. | "React 19 adds a compiler" enriches "React 18 introduced concurrent rendering" | | **Confirms** | A separate source independently agrees with an existing memory. | Two separate code reviews both recommend the same library | | **Challenges** | New information contradicts what you recorded before. | Your March assessment disagrees with your October conclusion | These four types cover the ways knowledge actually moves: it gets updated, extended, validated, or contradicted. ## What this means in practice [#what-this-means-in-practice] When you search for a topic, EVOLVES chains appear alongside individual results. You see not just the latest version, but the full trail of how you got there. This is especially useful for decisions. Searching "database choice" does not just return the most recent decision. It returns the chain: original choice, the enrichment that added reasoning, the challenge that raised concerns, and the replacement that settled it. ### Version tracking without version control [#version-tracking-without-version-control] EVOLVES links separate two kinds of relationships: * **Progression** (`replaces`, `enriches`): these form a version chain. The system marks older replaced versions as superseded so everyday search returns the latest understanding. History views and CLI history search can still show the older versions. * **Validation** (`confirms`, `challenges`): these are evidence, not versions. Confirming or challenging a memory does not replace it. Both the original and the new information stay active. Labels propagate through progression chains automatically. If you label a memory "architecture" and a later memory replaces it, the new one inherits the label. ## How detection works [#how-detection-works] When Background Intelligence is enabled, the system checks new memories against your existing knowledge. If semantic similarity is high enough, it evaluates the relationship type and creates the appropriate link. This runs automatically as a background task, typically within a minute of saving a new memory. You can also see and manage EVOLVES links directly from any memory's detail view. ## When contradictions appear [#when-contradictions-appear] Contradictions (the `challenges` relationship) are surfaced, not auto-resolved. The system shows both memories side by side and lets you decide: keep the new one, keep both, or dismiss the challenge. This is a deliberate design choice. Automated conflict resolution would require the system to judge which version of your knowledge is "right." That judgment belongs to you. ## Next steps [#next-steps] * [Background Intelligence](/docs/concepts/background-intelligence) explains when EVOLVES detection runs and what other tasks use it * [Crystals](/docs/concepts/crystals) explains what happens when multiple EVOLVES chains converge * [Search architecture](/docs/concepts/search-architecture) covers how EVOLVES chains affect search ranking # How it works (/docs/concepts) This section explains what happens under the hood when you use Nowledge Mem. It is written for users who want to understand *why* the system behaves the way it does, not just *how* to use it. You do not need to read these pages to use Mem effectively. Everything here runs automatically. But if you have ever wondered why certain memories rank higher in search, how the system detects contradictions, or what happens while you sleep, this is where to look. The Context branch in Nowledge Mem Tree ## What is covered [#what-is-covered] * [LLM Wiki](/docs/concepts/llm-wiki) frames why the Library reads as a wiki, what the system does on its own, and what stays in your hands. This is the entry point if you want the model behind v0.8. * [Open Knowledge Format (OKF)](/docs/concepts/open-knowledge-format) covers how you export your whole graph as an open, vendor-neutral markdown bundle any tool or agent can read. * [Knowledge evolution](/docs/concepts/evolves) explains how memories transform over time. When you refine a decision or learn something that contradicts earlier thinking, the system tracks the relationship instead of overwriting history. * [Memory Links](/docs/concepts/memory-links) explain how to connect two memories inside a space when they should be read together, even when the relationship is not version history or an entity link. * [AI Profiles](/docs/concepts/ai-profiles) explain how Mem keeps long-running agents distinct from the tool that happens to run them. * [Rules](/docs/concepts/rules) explain always-on behavior rules, how they differ from Skills and Memories, and how they reach connected agents. * [Search architecture](/docs/concepts/search-architecture) describes how search combines multiple perspectives (semantic meaning, keywords, entity linking, community clusters, labels, and graph traversal) to find what you need. * [Memory decay](/docs/concepts/memory-decay) covers how the system decides what to surface first. Recent and frequently used knowledge ranks higher. Important knowledge never disappears. * [Memory lifecycle](/docs/concepts/memory-lifecycle) explains the three states a memory can be in (active, archived, removed) and why the count you see on the Memories page can differ from your graph or storage size without anything being lost. * [Background intelligence](/docs/concepts/background-intelligence) walks through the daily pipeline: what runs, when, and what safeguards keep it from wasting resources or generating noise. * [Skills](/docs/concepts/skills) explains how the system turns a repeated way of working into a procedure your AI can follow, and how a Skill earns trust before it is treated as proven. * [Crystals](/docs/concepts/crystals) explains how the system synthesizes stable reference knowledge when multiple independent sources converge on the same insight. ## Where to start [#where-to-start] If you are trying to understand why a specific search result appeared (or did not appear), start with [search architecture](/docs/concepts/search-architecture) and [memory decay](/docs/concepts/memory-decay). If you want to understand the background features (briefings, contradictions, entity extraction), start with [background intelligence](/docs/concepts/background-intelligence). If you are setting up several agents, start with [AI Profiles](/docs/concepts/ai-profiles), [Rules](/docs/concepts/rules), and [Context](/docs/ai-context). # LLM Wiki (/docs/concepts/llm-wiki) The Library now reads as a wiki, not a file pile. The wiki you are reading is the same knowledge Mem has been collecting in the background; the difference is that you can finally read it page by page, click through the connections, and ask a single concept the question you actually had. Andrej Karpathy [described the underlying pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) very clearly: many small markdown pages, each focused on one entity or one topic, cross-linked with `[[wikilinks]]`, with an `index.md` as a directory. The LLM does the bookkeeping; you curate. Mem implements that idea on top of your knowledge graph. ## First useful action [#first-useful-action] 1. Open the Library and switch to the **Wiki** tab. 2. Pick a topic that already has memories under it. Read its summary, click into one of the listed entities, then click into a related entity. 3. From an entity, crystal, or topic page, click **Investigate**. The Knowledge Graph opens with that node (or the whole cluster) already selected. You should be able to navigate three or four pages without typing once. That is the first signal that the wiki is yours to read.
## What Mem does for you [#what-mem-does-for-you] The bookkeeping side of a personal wiki is exactly what kills most attempts at one. Mem treats it as the system's job, not yours. * **Topic clustering.** Background Intelligence groups your knowledge into topics and gives each topic a name. The Wiki tab is the index for those topics. The first time you open it on a fresh install, run **Wiki Topic Detection** once from the Knowledge Graph view to fill the index; after that it refreshes automatically every 6 days, and you can change the cadence in *Settings · Processing · Advanced*. * **Entity pages, derived live.** Each entity has a wiki entry built from the graph: where it sits in your topics, when it was first seen, the agent's confidence in it, aliases it picked up, the memories that mention it, the entities sitting next to it. There is no second copy you have to maintain. * **Crystals as reference articles.** When three or more memories converge on the same idea, Mem synthesises a [Crystal](/docs/concepts/crystals): a stable reference page with `[[Entity]]` wikilinks already woven in. Every Crystal lists the source memories it was built from. * **Evolution and contradictions.** [EVOLVES](/docs/concepts/evolves) edges track when newer knowledge replaces or refines older knowledge. Crystal pages show the older memories they grew out of and the newer ones they grew into. * **Last-touched and recent activity.** Each topic page carries a "Recent on this topic" rail, so the wiki reflects what you have actually been thinking about lately. ## What you stay in charge of [#what-you-stay-in-charge-of] The wiki is built around a clear division: Mem handles the bookkeeping, you handle the thinking. * **Picking sources.** Drop in the document, conversation, or note. The wiki only grows from what you decide is worth feeding it. * **Asking the questions.** The Knowledge Graph Agent and the Library's "Study with AI" both wait for you to point at something. They do not wander. * **Deciding what to keep.** "Study with AI" proposes memories and Crystals; you tap **Save 1**, **Save all**, or **Skip**. Nothing auto-saves. ## The wiki sits on top of the writing path [#the-wiki-sits-on-top-of-the-writing-path] Mem already had a writing path in place: ingest, parse, classify, extract entities, detect EVOLVES edges, synthesise Crystals, cluster into communities, all happening in the background as you use the tool. The Wiki tab is a *reading path* layered on top, not a new datastore. That has a few useful consequences: * **Pages are derived, not stored.** Edits happen at the data layer (memories, sources, crystals), and the wiki page refreshes from there. There is no parallel copy to drift out of sync. * **Export is a snapshot, not a sync target.** [Wiki Export](/docs/library#wiki-export) gives you a one-shot folder of markdown files. Choose the Obsidian-style markdown wiki with `[[wikilinks]]`, or an [OKF bundle](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf): the same content in Google's open, vendor-neutral [Open Knowledge Format](/docs/concepts/open-knowledge-format), which formalizes this exact LLM Wiki pattern so other tools can read it. Re-export when you want a fresh copy. Editing the export does not flow back into Mem. * **Investigate keeps you on the same canvas.** When you click Investigate, you stay in Knowledge Graph overview mode, the cluster is highlighted, and Graph Intelligence Agent reads the same selection you do. Anything the agent saves comes back to the topic page in Library. ## Where to go next [#where-to-go-next] * [Library](/docs/library): the day-to-day surface where you read the wiki and run "Study with AI". * [Crystals](/docs/concepts/crystals): how stable reference pages get synthesised. * [Background Intelligence](/docs/concepts/background-intelligence): the work that keeps your wiki current without you asking. * [EVOLVES](/docs/concepts/evolves): how Mem tracks the way your understanding moves. # Memory decay (/docs/concepts/memory-decay) You remember yesterday's meeting better than last month's. You recall a fact you use every day more easily than one you read once. Human memory works this way because it has to. Infinite recall with no prioritization would be as useless as forgetting everything. Nowledge Mem applies a similar idea. Every memory carries two independent scores that influence where it appears in search results. One fades with time. The other only grows. ## Two scores, two jobs [#two-scores-two-jobs] **Decay score** reflects freshness. A memory you saved today scores higher than one you saved six months ago, all else equal. The score drops over time following an exponential curve, with a frequency boost for memories you keep coming back to. If you access a memory regularly, the decay score stays high. **Confidence score** reflects how well-supported a memory is. It starts at a baseline and increases as evidence accumulates. Confidence never decreases. A memory that has been accessed many times, linked through EVOLVES chains, or used as a source for a Crystal will have higher confidence than an isolated, untouched memory. The two scores are independent. A memory can be old (low decay) but well-supported (high confidence), or recent (high decay) but unvalidated (low confidence). Both signals feed into the final search ranking alongside semantic relevance. ## What feeds into each score [#what-feeds-into-each-score] ### Decay score [#decay-score] Two components, blended: * **Recency**: exponential decay from the last time you interacted with the memory. Recent memories score higher. The curve has a half-life measured in weeks, not hours, so memories do not vanish overnight. * **Frequency**: a logarithmic function of how many times the memory has been accessed. Frequent use keeps a memory fresh even if the last access was not today. Recency carries more weight than frequency. A memory you used heavily last year but have not touched since will still fade, just more slowly than one you never accessed. ### Confidence score [#confidence-score] Six signals, each capped so no single signal can dominate: 1. **Access frequency**: how often the memory has been retrieved 2. **Search appearances**: how often it shows up in search results 3. **Explicit clicks**: how often you open and read it 4. **Reading time**: how long you spend on it when you do open it 5. **EVOLVES edges**: how many other memories confirm or enrich it 6. **Crystal membership**: whether it has been used as a source for a Crystal These signals are tracked automatically. You do not need to rate or tag memories for the system to learn which ones matter. ## The importance floor [#the-importance-floor] Decay creates a problem: a genuinely important fact that you do not access for months will score low, even though it is still correct and valuable. Spaced repetition systems solve this by scheduling reviews. Mem is not a flashcard app. Instead, each memory has an importance floor. The decay score can drop, but it will never fall below a minimum threshold tied to the memory's importance level. A foundational decision or a critical procedure stays retrievable even if you have not looked at it in a long time. The floor is modest. It does not override semantic relevance. It just prevents "ghost memories": knowledge that exists in your system but effectively cannot be found. ## How decay affects search ranking [#how-decay-affects-search-ranking] Semantic relevance is the dominant factor in search results. Decay and confidence are secondary signals that adjust the ordering when semantic scores are close. In practice: * Two memories equally relevant to your query → the fresher one ranks higher * A semantically strong match always beats a recent but weakly relevant one * A well-supported memory (high confidence) gets a small additional boost * Crystals and latest versions in EVOLVES chains get their own ranking adjustments on top of this ## Automatic refresh [#automatic-refresh] The system recalculates decay and confidence scores daily as a background task. This refresh also updates the cached scores used in search, so results reflect current usage patterns without any manual intervention. The refresh itself never archives, deletes, merges, or rewrites memories. It keeps ranking signals current. Memory growth is handled separately by **Memory Maintenance**. When Mem sees pressure from stale or overlapping memories, it can prepare a review in the Timeline. From there, you can move low-risk facts and events out of everyday recall, queue semantic organization for richer memories, or keep everything as-is. Memory Health review in Nowledge Mem *A Memory Health review shows the current batch, recent coverage, and the remaining backlog before you choose what to tidy.* This distinction matters: * Facts and events can be low-risk cleanup candidates when they are old, unvisited, and not protected. * Preferences, decisions, plans, procedures, learnings, rules, identities, and context memories are never mechanically archived by freshness alone. * Moving something out of everyday recall is reversible. Forgetting or deletion is always an explicit action. ## Next steps [#next-steps] * [Search architecture](/docs/concepts/search-architecture) explains how decay and confidence feed into the full ranking pipeline * [Knowledge evolution](/docs/concepts/evolves) covers EVOLVES chains, which contribute to confidence scores * [Crystals](/docs/concepts/crystals) explains Crystal membership, another confidence signal # Memory lifecycle (/docs/concepts/memory-lifecycle) Nothing you save is silently thrown away. That is the one thing to hold onto while reading this page. A memory can be in everyday use, quietly kept in the background, or genuinely gone. The only way something reaches that last state is because you asked for it. Everything else is still there, still yours, still searchable. ## The three states [#the-three-states] **Active** is what your everyday recall sees. When you search, when your AI answers a question, when the Memories page lists what you know, it is drawing from active memories. This is the working set: the version of your knowledge you are actually using right now. **Archived** is kept but out of the way. A memory becomes archived when a newer version replaced it, or when you retired or paused it because it was no longer current. It has not gone anywhere. You can still find it through history views and history search. It just no longer competes for attention in everyday recall, so the latest understanding surfaces first. **Removed** is the only state that means gone. A memory reaches it when you delete or forget it, on purpose. It leaves everywhere at once. Nothing moves a memory here on its own. A helpful way to hold this: > **Stored** = Active + Archived. That is everything you still have. ## Why you may see different numbers [#why-you-may-see-different-numbers] You will sometimes notice that the count on the Memories page does not match the number implied by your graph or storage size. This is expected, and it is not a sign that anything went missing. Each view is a different lens on the same knowledge. * The **Memories page** and the **Stats headline** show your **active** memories: the working set you recall from every day. * The **graph** and your **storage size** count everything **stored**: active plus archived history. Older replaced versions still take up space and still live in the graph, so this number is larger. * **Crystals** (the synthesized summaries Mem writes when several sources agree) are counted on their own, separate from your memory count. Same knowledge, three lenses. A lower active number is not a loss. It usually just means some older versions moved into archived history, which is exactly what keeps everyday recall focused on what is current. ## What moves something between states [#what-moves-something-between-states] Most transitions happen for a clear reason: * When you refine or replace a piece of knowledge, the earlier version becomes archived history rather than being overwritten. See [Knowledge evolution](/docs/concepts/evolves) for how these version chains work. * When a memory grows stale, Mem may prepare a review so you can move low-risk facts out of everyday recall. Freshness and decay only affect *ranking*, never deletion. See [Memory decay](/docs/concepts/memory-decay). * Retiring, forgetting, and deleting are always explicit actions you take. Moving something out of everyday recall is reversible. Deletion is the one thing that is not. ## Next steps [#next-steps] * [Memory decay](/docs/concepts/memory-decay) explains how freshness affects search ranking without ever removing anything. * [Knowledge evolution](/docs/concepts/evolves) explains how superseded versions become archived history you can still trace. # Memory Links (/docs/concepts/memory-links) A Memory Link is for one plain action: telling Mem that two memories should be read together. Use it when one memory changes how another should be understood. A launch plan may depend on an earlier pricing assumption. A migration note may be the risk behind an implementation plan. A real example may be the missing context that makes a rule usable. This is different from search similarity. Search can guess that two memories look related. A Memory Link is something you, or an agent working with clear intent, decided to keep. ## Try it once [#try-it-once] 1. Open **Graph** from the sidebar. 2. Select a Memory node. 3. Choose **Connect memories**. 4. Select another Memory in the same Space. 5. Type a short relation name, or use a suggestion. 6. Add a reason if the connection is not obvious, then save. The two memories must be in the same Space. That keeps work, projects, clients, and agent teams from being linked by accident. ## How to know it worked [#how-to-know-it-worked] You should see a line between the two Memory nodes. Select that line to inspect the relation name and reason. Later, when an agent or graph tool reads one of those memories, the link gives it a stronger clue than "these two texts are similar." It can bring the other memory nearby and know why it matters. ## Good relation names [#good-relation-names] You do not need a perfect taxonomy. Start with the words you would use in your own work: | Relation | Use it when | | ------------- | ------------------------------------------------------------- | | `supports` | one memory is evidence for another | | `contradicts` | one memory conflicts with another, but is not a newer version | | `depends_on` | one memory needs another to make sense | | `example_of` | one memory is a concrete example of a rule or pattern | | `blocks` | one memory blocks a plan or action | | `same_topic` | both memories cover the same subject and are useful together | You can also type your own names, such as `migration_risk_for`, `pricing_assumption_for`, or `source_of_truth_for`. Mem normalizes names, so `same topic`, `same-topic`, and `same_topic` are treated as the same relation. ## How this differs from other links [#how-this-differs-from-other-links] | Use this | When you mean | | ---------------- | -------------------------------------------------------------------------------------- | | **Memory Link** | These two specific memories should be read together for this reason | | **EVOLVES** | This memory updates, replaces, enriches, confirms, or challenges an older version | | **Label** | Many memories belong in the same broad group | | **Entity graph** | A memory mentions people, projects, tools, concepts, or extracted entity relationships | | **Search** | Find memories that look relevant, even when no relationship has been saved | If the connection is really a newer version of old knowledge, use the EVOLVES relationship instead. If you only want a broad bucket, use a label. ## What to ignore for now [#what-to-ignore-for-now] You do not need to design a full relation system before using Memory Links. Name the relationship that is useful today. You do not need to use AI suggestion. It can draft a relation name and reason, but it only fills the form. You still decide what to save. You do not need to think about APIs or MCP tools unless you are building an integration. The Graph view is the normal starting point. ## For agents and integrations [#for-agents-and-integrations] Supported integrations can read and write Memory Links through the REST API and MCP tools: * `memory_relation_add` * `memory_relation_suggest` * `memory_relation_list` * `memory_relation_update` * `memory_relation_delete` The graph stores these as one stable memory-to-memory edge with an open relation name. That keeps the schema small while still letting your vocabulary grow over time. ## Where to go next [#where-to-go-next] * [Knowledge Graph](/docs/knowledge-graph) if you want to create or inspect Memory Links visually. * [Knowledge evolution](/docs/concepts/evolves) if you want to understand version history and contradictions. # Open Knowledge Format (OKF) (/docs/concepts/open-knowledge-format) Nowledge Mem can export your whole knowledge graph as an **Open Knowledge Format (OKF)** bundle: an open, vendor-neutral way to represent knowledge as plain markdown files with YAML frontmatter. Nothing proprietary sits between you and your knowledge, and any tool that reads OKF can read your export. OKF was published by Google Cloud's Knowledge Catalog team. It formalizes the [LLM Wiki](/docs/concepts/llm-wiki) pattern Mem was already built on, so speaking it was a natural fit. ## Export an OKF bundle [#export-an-okf-bundle] 1. Open the **Library** and switch to the **Wiki** tab. 2. Click **Download** on the tab row. 3. Choose **OKF bundle**. You get a `.zip` containing an `index.md`, a `log.md`, and your knowledge laid out as directories: your memories grouped by type (`memories/decision/`, `memories/procedure/`, and the rest), plus `crystals/`, `entities/`, `topics/`, `artifacts/`, `skills/`, and a `labels/` catalog. Every page carries YAML frontmatter, concepts link to each other with standard markdown paths, and the bundle is conformant with the OKF reference tools. Open Knowledge Format export in Nowledge Mem *The OKF export is the portable version of your Library Wiki: markdown files, frontmatter, and standard links.* For the full export flow and the second format, see [Library: Wiki Export](/docs/library#wiki-export). ## Why it is useful [#why-it-is-useful] * **Portable.** A bundle is just markdown files. Open it in any editor, render it on GitHub, or version-control it next to your code. * **Vendor-neutral.** Any OKF reader, including the reference tools Google ships, can open it. You are not locked into one app's format. * **Human- and agent-readable.** The same file works for a person skimming it and an AI agent parsing it, with no translation layer in between. ## OKF bundle vs Markdown wiki [#okf-bundle-vs-markdown-wiki] The Library export offers two formats, and both cover your whole graph. The OKF bundle uses standard markdown links and the spec's frontmatter, so it is the interoperable choice. The **Markdown wiki** keeps the `[[wikilinks]]` you see inside Mem, so it drops straight into Obsidian or Logseq. Pick OKF for an interoperable copy; pick the markdown wiki for an Obsidian-style vault. Both are a snapshot, not a sync target: edits you make outside Mem do not flow back. Re-export whenever you want a fresh copy. ## Where to go next [#where-to-go-next] * [Library](/docs/library): the day-to-day surface where you export. * [LLM Wiki](/docs/concepts/llm-wiki): the reading model OKF formalizes. * [Back up, export, and import](/docs/data-portability): the separate full-data backup and migration path. * [Read the OKF specification](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md): the canonical spec from Google Cloud. * [How Nowledge Mem came to speak OKF](https://nowledge-labs.ai/blog/open-knowledge-format): the announcement. # Rules (/docs/concepts/rules) A Rule is an always-on behavior instruction for your connected agents. Use Rules for things that should shape behavior before search, tools, or task-specific skills begin. They are the centralized version of the small instructions many power users already keep in `AGENTS.md`, `CLAUDE.md`, Cursor rules, Codex profiles, or a Hermes soul. ## What belongs in a Rule [#what-belongs-in-a-rule] A good Rule changes how an agent behaves across many tasks: * "Answer concisely unless I ask for detail." * "Do not edit generated API docs by hand." * "For release work, check tests before saying the change is ready." * "When writing Chinese docs, write natural Chinese instead of translating English line by line." Rules are not for everything. If the instruction is a repeatable task method, make it a [Skill](/docs/concepts/skills). If it is something you learned, save it as a Memory. If it only matters today, keep it in Working Memory. ## The first useful move [#the-first-useful-move] Open **Context → Rules** and add one rule you keep repeating to agents. Choose the narrowest useful scope: | Scope | Use it when | | ------------------ | --------------------------------------------- | | **Everyone** | Every connected AI should follow it | | **One AI Profile** | Only a named agent should follow it | | **One Space** | It only applies inside a project or team lane | Then open **Context → Preview**. You should see the rule in the startup context for the matching agent. ## Rules, Skills, and Memories [#rules-skills-and-memories] These three can look similar, but they do different jobs: | Thing | What it means | | ---------- | ------------------------------------------- | | **Rule** | "Always behave this way." | | **Skill** | "When doing this task, follow this method." | | **Memory** | "This is something worth remembering." | Example: * Rule: "Do not hand-edit generated OpenAPI docs." * Skill: "How to add a new API endpoint without breaking generated docs." * Memory: "The OpenAPI docs are generated from Python docstrings." The boundary matters because Rules are injected early and often. A vague or wrong Rule can steer many sessions. Keep Rules short, specific, and easy to inspect. ## Suggested Rules [#suggested-rules] Mem can suggest candidate Rules when repeated behavior shows up in your work. A suggestion is not automatically applied. You can accept it, edit it, or ignore it. This keeps the useful part of automation, noticing repeated preferences and project habits, without letting the system silently rewrite how your agents behave. ## How connected tools consume Rules [#how-connected-tools-consume-rules] Supported connectors read Rules through the Context Bundle at session start. The bundle combines your profile, the selected AI Profile, active space, Rules, Working Memory, and useful file-system paths. Some older or simpler integrations may only read Working Memory. In that case, Rules still help inside Mem and in newer connectors, but the older tool may not see them until its integration is updated. ## What to ignore for now [#what-to-ignore-for-now] You do not need to turn every preference into a Rule. If you would not want it repeated in most future sessions, do not make it always-on. You do not need to write long policy documents. Short rules are easier for agents to follow and easier for you to trust. You do not need to understand MCP or KFS paths to use Rules. Start in the Context view. ## Where to go next [#where-to-go-next] * [AI Profiles](/docs/concepts/ai-profiles) if different agents need different behavior. * [Skills](/docs/concepts/skills) if the behavior is really a task method. * [Context](/docs/ai-context) to preview the final startup bundle. # Search architecture (/docs/concepts/search-architecture) Searching personal knowledge is different from searching the web. You are looking for things you saved yourself, in your own words, sometimes months ago. The biggest challenge is not speed. It is the gap between how you phrase a question now and how you phrased the answer then. Nowledge Mem addresses this by searching from multiple angles at once, then blending the results. ## Six search strategies [#six-search-strategies] Every search query runs through up to six parallel strategies: **Semantic search.** Compares the meaning of your query against the meaning of each memory using vector embeddings. "API authentication" finds "JWT token setup" even though the words are different. This is the primary signal for most queries. **Full-text search.** Keyword matching with language-aware tokenization, including CJK (Chinese, Japanese, Korean) support. Useful when you remember exact terms, names, or code identifiers. **Entity search.** Uses the knowledge graph to find memories linked to relevant entities. Searching "database performance" can surface a memory about "PostgreSQL indexing" through their shared entity connections, even if the memory text never mentions "database performance." **Community search.** The knowledge graph groups related entities into communities (clusters of strongly connected nodes). Searching within a community surfaces memories you might not find through direct keyword or semantic matching. **Label search.** If your query matches a label you have assigned, memories with that label get a relevance boost. This lets your own organizational structure influence search results. **Graph traversal.** Follows relationship edges (EVOLVES chains, entity links, Crystal sources) to find memories connected to your query through the graph structure rather than text similarity. ## Fast mode and deep mode [#fast-mode-and-deep-mode] Not every search needs all six strategies at full power. **Fast mode** (under 100ms for most queries) runs semantic search, full-text search, and entity matching in parallel. It handles about 90% of queries well. This is the default. **Deep mode** adds LLM-powered analysis on top of the fast results. It classifies your query intent (are you looking up a fact? exploring a concept? tracing a relationship?) and adjusts strategy weights accordingly. It can also use HyDE (hypothetical document embeddings) to bridge large expression gaps, and optionally re-evaluate top results with an LLM for better ranking. Deep mode is triggered automatically for queries that include temporal intent ("what did I decide last quarter?"), or when fast mode results are low-confidence. You can also trigger it manually. ## How results are ranked [#how-results-are-ranked] The final ranking blends signals from the strategies above with memory-level scoring: * **Semantic relevance** is the dominant factor. A memory that is semantically close to your query will rank high regardless of other signals. * **Decay score** gives a modest boost to recently and frequently accessed memories. See [memory decay](/docs/concepts/memory-decay) for details. * **Confidence score** provides a small additional boost to memories with strong evidence (many accesses, EVOLVES links, Crystal citations). Crystals (synthesized reference knowledge) receive a ranking boost because they represent corroborated, high-confidence knowledge. Current memories in EVOLVES chains are returned by default; superseded memories stay in graph history and can be included when you explicitly ask for history. Every result includes a `source_thread_id` when available. If an agent or tool needs more context beyond the memory itself, it can pull the original conversation. ## Temporal search [#temporal-search] Queries with time references ("what happened in 2020?", "decisions from last quarter") activate temporal matching. The system tracks two independent timestamps for each memory: * **Event time**: when the thing happened * **Record time**: when you saved it Temporal matching adds a relevance boost but does not override semantic relevance. A memory from the right time period still needs to be semantically relevant to rank well. Time is a signal, not a filter. Date precision is tracked explicitly. If a memory's event time is known only to the year, the system will not pretend to know the month. ## Next steps [#next-steps] * [Memory decay](/docs/concepts/memory-decay) explains the decay and confidence scores that influence ranking * [Knowledge evolution](/docs/concepts/evolves) covers how EVOLVES chains affect what appears in results * [Search & Relevance](/docs/search-relevance) is the reference page with practical search tips # Skills (/docs/concepts/skills) You figure out the right order to cut a release: commit the submodules first, then move the parent pointer. You get it wrong once, learn the lesson, and from then on you just do it. It lives in your head, not in any document. A Skill is what happens when Mem captures that way of working and hands it to your AI as a procedure it can follow later. ## What a Skill is [#what-a-skill-is] A Skill is a repeatable way of performing a task, written down so an agent can do it the way you would. The useful ones are small and specific: an order of operations, a safety check, a release gotcha, a review habit, a debugging move. It is not a saved prompt, and it is not a standing rule. A standing rule ("keep answers short") belongs in [Context](/docs/ai-context) as a Rule. A Skill is the *how* of a task, the step a capable stand-in would get wrong without your experience. Skills are also not auto-generated checklists. A good model can already write a plausible-looking process. The point of a Skill is to carry the part that only came from your real work, the thing that is not obvious until you have done it. Every Skill traces back to the work that earned it, and every Skill stays off until you turn it on. Skills in Nowledge Mem ## How a Skill is born [#how-a-skill-is-born] There are three ways a Skill comes to exist, and all three flow into the same lifecycle. 1. **Suggested.** As part of [background intelligence](/docs/concepts/background-intelligence), Mem looks for repeated ways of working in your memories and threads. When the same procedure shows up across separate occasions, it proposes a Skill, with the source moments attached as evidence. This is why a memory filed as a `procedure` matters: typed procedures are what the suggestion pass reads first. See [knowledge evolution](/docs/concepts/evolves) for how memories get their type. 2. **From scratch.** You can author a Skill directly by describing what you want. Mem asks one question, drafts the procedure, and shows it back to you to review. You can bring in your own threads, sources, or notes as material. 3. **Imported.** If you already keep skill files for an agent host (a `SKILL.md` and its bundle), you can enroll them. The body is kept verbatim and then flows into the same draft, verify, and improve loop as everything else. However it starts, a Skill compiles into a small bundle: the procedure itself as a `SKILL.md`, plus any optional scripts, references, and evaluation cases. It is compiled, not merely stored, so the version your AI reads is consistent no matter where the Skill came from. ## What the trust badge tells you [#what-the-trust-badge-tells-you] Once a Skill is on, your agent follows it for real, so before you turn one on you want to know it actually works. Every Skill shows a trust badge so you can tell at a glance how far it has been tested: * **Checked** means it passed one test. It works, but on a single example. * **Proven** means it passed two or more, so you can count on it across different situations. Mem runs these tests for you, using examples drawn from the same work the Skill came from, so you do not have to set anything up. When you open a Skill, the badge is the quick answer to "can I rely on this yet?" ## How your AI uses a Skill [#how-your-ai-uses-a-skill] A Skill is only useful if the agents you already work with can read it. When you turn a Skill on, Mem materializes it as real files and registers it with your connected hosts through each host's native mechanism, for example `~/.claude/skills` for Claude Code, or the equivalent location for Codex and other agents. The format is the universal `SKILL.md` convention, so one Skill works across hosts. Some tools reach Mem over a live connection rather than a skills folder; there the agent finds the Skill through Mem when a task calls for one, instead of loading it from disk. The agent then reads the Skill the same way it reads any of its own skills. One agent learning it means the rest can use it. The host is just the runtime; the Skill, and the trust behind it, stays with you. Turning a Skill off keeps it but stops materializing it, which is different from removing it. Both are reversible. ## Sharpening a Skill [#sharpening-a-skill] You can ask Mem to sharpen a Skill over time. When you do, it tries a revision and tests it against the version you already have, using examples drawn from the Skill's own evidence. It only keeps the change if the new version tests better. If nothing beats what you have, it keeps nothing and tells you so. Sharpening can improve a Skill, but it will not quietly swap in something worse, so it is always safe to ask. A crystallized Skill with an improvement prompt ## How Skills relate to the rest of Mem [#how-skills-relate-to-the-rest-of-mem] Skills sit alongside the other things Mem keeps, each with a different job: * A **Memory** is something you know. A **Skill** is something your AI can do. A memory typed as a `procedure` is the most common raw material for a Skill. * A **[Crystal](/docs/concepts/crystals)** synthesizes stable reference knowledge when several sources converge. A Skill is closer in spirit, also compiled rather than raw, but it produces an executable procedure instead of a reference article. * A **Rule** in [Context](/docs/ai-context) shapes how an agent behaves in general. A Skill shapes how it performs one specific task. ## What you see [#what-you-see] Skills live in the **Skills** view. The home shows your active Skills and any suggestions waiting for you, each suggestion carrying the evidence from your own work that prompted it. Opening a Skill shows the procedure as the main content, its trust state, and where it came from. Turning one on, off, or removing it is always your call. ## Next steps [#next-steps] * [Background intelligence](/docs/concepts/background-intelligence) covers when skill suggestions run and the budget that governs them * [Knowledge evolution](/docs/concepts/evolves) explains how memories get the `procedure` type that suggestions read first * [Context](/docs/ai-context) is where standing rules live, the behavior layer that sits next to Skills * If you script against Mem, the [Skills API reference](/docs/api/skills/get) lists the REST endpoints # Alma (/docs/integrations/alma) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Alma. If you use Alma Skills, enable the bundled nowledge-mem Skill or copy it to ~/.config/alma/skills/nowledge-mem. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Memory that follows every Alma conversation. Install once from the marketplace, then optionally enable the bundled Alma Skill so Alma knows when to use memory tools more deliberately. Connect to a remote Mem instance with Access Anywhere for use across machines. Source: [community/nowledge-mem-alma-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-alma-plugin) Install the plugin, open a fresh Alma thread, and ask Alma: "Use the Nowledge Mem status tool and tell me whether the server is connected." The `nowledge_mem_status` result should report `ok: true` and `serverConnected: true`. If your Mem library already has memories, ask a follow-up that depends on past work. On a brand-new library, status plus thread capture is enough. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * Alma installed, with access to its plugin marketplace ## Setup [#setup]
### Install from the Alma Plugin Marketplace [#install-from-the-alma-plugin-marketplace-step] In Alma, open **Settings** → **Plugins** → **Marketplace**, search for **Nowledge Mem**, and click **Install**. Alma Marketplace - Nowledge Mem
### Restart Alma if prompted [#restart-alma-if-prompted-step]
### Optional: enable the Alma Skill [#optional-enable-the-alma-skill-step] The plugin works without this step: tools, auto-recall, and thread sync are handled by the plugin. If you use Alma's **Settings → Skills** page, look for the bundled `nowledge-mem` Skill and enable it if it appears. It teaches Alma when to read Context Bundle, search prior work, inspect source threads, and save durable decisions. If the Skill does not appear after installing the plugin, copy it into Alma's personal skills folder and refresh Skills: ```bash mkdir -p ~/.config/alma/skills/nowledge-mem cp ~/.config/alma/plugins/nowledge-mem/skills/nowledge-mem/SKILL.md \ ~/.config/alma/skills/nowledge-mem/SKILL.md ```
### Verify in a fresh thread [#verify-in-a-fresh-thread-step] Ask Alma to run the status tool: ```text Use the Nowledge Mem status tool and tell me whether the server is connected. ``` Then send one short normal message and wait a few seconds, switch threads, or quit Alma cleanly. The conversation should appear in Nowledge Mem under **Threads** with source `alma`.
## Update [#update] Open **Settings** → **Plugins** → **Marketplace** in Alma, find Nowledge Mem, and click **Update** if a newer version is available. ## Disable or Uninstall [#disable-or-uninstall] * To pause automatic thread capture without uninstalling, set `autoCapture` to off in the Nowledge Mem plugin settings. * To pause preloaded recall, set `recallPolicy` to `off` or use `strict_tools` when you only want explicit tool calls. * To remove the integration, disable or uninstall Nowledge Mem from Alma's **Settings → Plugins** page. If you installed a local copy manually, quit Alma and remove `~/.config/alma/plugins/nowledge-mem`. ## Customize Safely [#customize-safely] Alma does not expose a separate package-owned override file for this plugin. * Use Alma's plugin settings for durable behavior changes such as remote mode, recall policy, thread capture, and space selection * If you want the agent to speak or save differently, use Alma's Skills, prompts, or instruction surfaces instead of patching plugin code Do not edit installed plugin files just to keep a small preference. For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## What the Plugin Does [#what-the-plugin-does] | Feature | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Auto-recall** | Injects Working Memory + relevant memories on the first message of every thread | | **13 tools** | Memory: query, search, store, show, update, delete. Threads: search, show, create, delete. Plus Context Bundle, Working Memory, and status diagnostics | | **Access Anywhere** | Connect to a remote Mem instance via API URL + API key in plugin settings | | **Live settings** | Change API URL, API key, recall policy, or auto-capture. Takes effect immediately, no restart | | **Status diagnostics** | `nowledge_mem_status` shows connection mode, server health, CLI availability, and current config | | **Live thread sync** | Saves conversations after a few seconds of idle, on thread switch, and on quit (on by default) | | **Native Alma Skill** | Optional `nowledge-mem` Skill for better tool-selection guidance in Alma's Skills surface | | **Local-first** | Uses the Nowledge Mem API on this machine. No cloud required unless you enable Access Anywhere | ## Thread Saving [#thread-saving] Threads are saved automatically during normal use: the plugin syncs your conversation after a few seconds of idle, when you switch threads, or when you quit Alma. No action needed. Saved threads appear in the Nowledge Mem desktop app and can be distilled into structured memories later. During conversation, the AI may also save specific insights or decisions as individual memories using the `nowledge_mem_store` tool. This happens when the conversation produces something durable, such as architecture decisions, debugging conclusions, preferences. For casual chat, the AI intentionally avoids saving noise. If you want something specific remembered, just ask: "save this to memory." ## Full-library backup (optional) [#full-library-backup-optional] For a **portable archive** of every Alma thread, whether for a new Mem library, compliance, or a clean machine, use Alma **Settings → Data → Export all threads**. That produces `alma-backup-*.zip` with `threads.json` inside. In Nowledge Mem, open **Threads → Import → Bulk Import** and pick the ZIP. Imported threads use the same `alma` source label as live plugin sync, so filters stay consistent. Other bulk formats and CLI options: [Import existing conversations](/docs/import-existing-conversations) and [Bulk import formats](/docs/threads#bulk-import). ## Access Anywhere [#access-anywhere] To connect to a remote Nowledge Mem instance: 1. In Alma, open **Settings** → **Plugins** → **Nowledge Mem** 2. Set **API URL** to your remote server (e.g. `https://mem.example.com`) 3. Set **API Key** to your `nmem_...` key 4. Changes take effect immediately. Use `nowledge_mem_status` to verify The API key is read from Alma's plugin settings, sent as an `Authorization: Bearer ...` header, and never logged. ## Spaces [#spaces] Alma can keep one ambient memory lane per profile. * Use `NMEM_SPACE="Research Agent"` when you already launch Alma in one stable lane. * Or set `nowledgeMem.space` in Alma settings when one Alma profile always belongs to one lane. * `nowledgeMem.spaceTemplate` is only for advanced setups where your launcher already exports a trustworthy lane variable, such as `${ALMA_AGENT_NAME}`. If Alma does not know a real agent identity, stay on **Default** or use separate Alma profiles for separate lanes. ## Related [#related] * [Connectors overview](/docs/integrations): native connectors, reusable packages, MCP, and browser capture * [Claude Code](/docs/integrations/claude-code) · [Claude Desktop](/docs/integrations/claude-desktop) · [Codex](/docs/integrations/codex-cli) · [OpenClaw](/docs/integrations/openclaw) · [Raycast](/docs/integrations/raycast) · [Others](/docs/integrations/other-chat-ai) # Antigravity CLI (/docs/integrations/antigravity-cli) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Antigravity CLI. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Google has replaced Gemini CLI with **Antigravity CLI** (`agy`). Gemini CLI stopped serving individual-tier accounts (Google AI Pro, Ultra, and free Code Assist) on **June 18, 2026**. Antigravity CLI shares the same agent harness as the Antigravity desktop platform and reuses your existing `~/.gemini` home directory, so most Gemini CLI setups carry over. Antigravity CLI is Google's official successor to Gemini CLI. The migration story is good: it reads the same `~/.gemini` home, honors both `GEMINI.md` and `AGENTS.md`, and can import installed Gemini CLI extensions as Antigravity plugins — including the Nowledge Mem extension. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * Antigravity CLI installed: ```bash # macOS / Linux curl -fsSL https://antigravity.google/cli/install.sh | bash # Windows (PowerShell) irm https://antigravity.google/cli/install.ps1 | iex ``` * `nmem` in your `PATH` (see [installation](/docs/installation) or use the desktop app's **Settings → Preferences → Developer Tools → Install CLI**) On first launch, `agy` signs you in with your Google account and offers to import your existing Gemini CLI configuration (MCP servers, allow-listed commands, keybindings, theme). Accepting that prompt is the fastest starting point. ## One-Minute Setup [#one-minute-setup]
### Install Nowledge Mem for Gemini CLI first [#install-nowledge-mem-for-gemini-cli-first-step] If you have not already, install the Nowledge Mem extension for Gemini CLI — see [Gemini CLI](/docs/integrations/gemini-cli). The Antigravity path builds on top of it.
### Import the extension into Antigravity [#import-the-extension-into-antigravity-step] ```bash agy plugin import gemini ``` This converts installed Gemini CLI extensions — including Nowledge Mem — into Antigravity plugins.
### Run `nmem status` once [#run-nmem-status-once-step] For the default same-machine setup, this should point to `http://127.0.0.1:14242 (default)`.
### Open a new `agy` session [#open-a-new-agy-session-step] The imported plugin loads its context files, commands, and bundled MCP tools automatically, the same way it did under Gemini CLI.
## MCP Configuration [#mcp-configuration] Antigravity CLI keeps MCP servers in a dedicated `mcp_config.json` (workspace path: `.agents/mcp_config.json`). If you configure the Mem MCP server manually, note one format difference: remote server definitions use `serverUrl` instead of `url`. Generate the right block for your setup: ```bash nmem config mcp show --host gemini-cli ``` Then place it in `.agents/mcp_config.json`, renaming `url` to `serverUrl` for remote servers. This keeps Antigravity's MCP tools and `nmem` pointed at the same Mem server. ## Import Older Sessions [#import-older-sessions] Session capture uses the same local history under `~/.gemini`, so the existing Gemini CLI import path applies: ```bash # Preview nmem t sync --from gemini-cli --all-projects --limit 20 # Import nmem t sync --from gemini-cli --all-projects --apply ``` Use `-p /path/to/project` when you only want one project. ## Customize Safely [#customize-safely] Both context files work in Antigravity CLI: * project `GEMINI.md` or `AGENTS.md` * optional `~/.gemini/GEMINI.md` for personal defaults Do not edit the installed plugin files directly. Full map: [Customize Integration Behavior](/docs/integrations/customize-behavior). ## Your First Success State [#your-first-success-state] You know Antigravity CLI is wired correctly when: * `agy plugin import gemini` completes and the Nowledge Mem plugin appears in a new session * `nmem status` returns successfully * Context Bundle or Working Memory appears at the start of a fresh session when there is context to show * `save-thread` imports a real session, and long sessions are saved before compression as well as at session end ## Known Boundaries [#known-boundaries] * The import path (`agy plugin import gemini`) is Google's official migration channel and the supported way to run the Nowledge Mem extension under Antigravity today. * Session capture currently reads the shared `~/.gemini` history through the Gemini CLI connector. If Google moves Antigravity session storage, capture behavior may change; check `nmem t sync --from gemini-cli --limit 5` after upgrading `agy`. ## Related [#related] * [Gemini CLI](/docs/integrations/gemini-cli) * [Connectors overview](/docs/integrations) * [Remote access](/docs/remote-access) # Browser Extension (/docs/integrations/browser-extension) Nowledge Mem Exchange captures memories and thread backups from supported web AI chat platforms. It runs beside your conversations in Chrome, Edge, Arc, and Firefox using the browser's native side panel or sidebar. Open one supported chat, open the side panel, then do exactly one thing: auto-capture one useful insight, manually distill one conversation, or back up one thread. When that result appears in Mem, the extension path is working. Firefox uses its native sidebar. The same capture, Manual Distill, and Thread Backup workflows work there. Browse Now browser control is separate and still requires Chrome, Edge, Arc, or another Chromium browser.
## Smart Distill [#smart-distill] The extension now treats a conversation as something it can inspect intelligently, not just export blindly. Auto-Capture and Manual Distill both read the live thread selectively, check what already exists in Mem, and then decide whether to create or update memories. Exchange: Proactive capture settings Exchange: Smart Distill trigger Exchange: Capture result ## Three Ways to Capture [#three-ways-to-capture] | Mode | How it works | When to use | | ------------------ | -------------------------------------------------------------------- | -------------------------------------------------------------------- | | **Auto-Capture** | Monitors your conversations and autonomously saves valuable insights | Set it and forget it. The extension decides what's worth remembering | | **Manual Distill** | You trigger capture on a conversation you want to save | When you know a conversation contains something important | | **Thread Backup** | Imports the full conversation as a thread, with incremental dedup | Archive entire conversations for later distillation in the app | ## Auto-Capture [#auto-capture] When enabled, the extension watches the live conversation and applies a high bar before saving anything: * **Refined conclusions**: decisions, plans, finalized approaches * **Important discoveries**: breakthroughs, key findings * **Knowledge explorations**: deep dives, research synthesis Routine Q\&A and generic exchanges are skipped. Before saving, the extension can inspect the thread more closely, check for duplicates in Mem, and update an existing memory instead of creating a redundant one. If Auto-Capture does save something, it first makes sure the conversation is backed up as a canonical thread in Mem. That way the memory keeps a reliable link back to the real conversation it came from. ## Manual Distill [#manual-distill] Manual Distill is for the moments when you know a conversation matters and want Mem to do a careful pass. Instead of compressing the whole thread into one quick summary, the extension now: * reads the live conversation selectively * looks for motivations, constraints, decisions, and reusable context * checks what is already in Mem * can create or update multiple memories from one conversation when that is the better result This makes Manual Distill much better for long working sessions, design discussions, debugging threads, and conversations where the most reusable part is in the middle rather than the last answer. Auto-capture requires a configured LLM provider. Open the SidePanel, go to **Settings**, and add your API key. Supported providers: OpenAI, Anthropic, Google, xAI, OpenRouter, Ollama, and OpenAI-compatible endpoints. ## Thread Backup [#thread-backup] Imports the full conversation as a thread. Subsequent backups only capture new messages (incremental sync). You can still back up a thread explicitly whenever you want a full archive. The extension also backs up the canonical thread automatically when it writes new browser-derived memories, so those memories keep strong provenance without requiring you to back up every conversation manually. For local coding assistants, Nowledge Mem also supports native connector capture plus **AI Conversation Discovery** for older local sessions from **Claude Code, Cursor, Codex, and OpenCode**. See [Threads](/docs/threads#auto-sync) for details. ## Supported Platforms [#supported-platforms] The extension works with the supported web AI chat platforms below: | Platform | Sites | | --------------------- | -------------------------- | | **ChatGPT** | openai.com, chatgpt.com | | **Claude** | claude.ai | | **Gemini** | gemini.google.com | | **NotebookLM** | notebooklm.google.com | | **Microsoft Copilot** | copilot.microsoft.com | | **Perplexity** | perplexity.ai | | **DeepSeek** | chat.deepseek.com | | **Kimi** | kimi.moonshot.cn | | **Qwen** | qwen.ai, tongyi.aliyun.com | | **POE** | poe.com | | **Manus** | manus.im | | **Grok** | grok.com, grok.x.ai, x.ai | | **Open WebUI** | localhost, private IPs | | **ChatGLM** | chatglm.cn | | **MiniMax** | agent.minimaxi.com | The browser extension captures from ChatGPT into Mem. If you want ChatGPT itself to search Mem during a conversation, use [ChatGPT Web and Desktop](/docs/integrations/chatgpt-web) and connect Remote MCP over OAuth. Paid users with a configured LLM can auto-generate handlers for any AI chat site. Navigate to the site, open the SidePanel, and click **Generate handler**. The extension analyzes the page structure and creates a custom handler automatically. ## Connect Extension to Access Mem Anywhere [#connect-extension-to-access-mem-anywhere] If your Mem API is exposed through **Settings → Access Mem Anywhere** in the desktop app: 1. Open any supported AI chat page, then open the extension SidePanel 2. Click **Settings** 3. Set **Fixed Space** only if this browser profile should always stay in one named lane. Leave it empty to stay on `Default`. 4. In **Access Mem Anywhere**, paste: * `export NMEM_API_URL="https://"` * `export NMEM_API_KEY="nmem_..."` 5. Click **Fill URL + key** 6. Click **Save**, then **Test connection** ## Spaces [#spaces] The browser extension is a fixed-lane surface. * Leave **Fixed Space** empty if this browser profile should keep using **Default** * Set one named space if this browser profile always belongs to one lane, such as `Research Agent` * Do not expect the extension to infer per-agent routing from the web page itself When you do set a fixed space, the extension keeps memory search, memory writes, thread reads, source reads, and Working Memory reads in that same lane. Full guide (Quick link and Cloudflare account modes): [Access Mem Anywhere](/docs/remote-access). ## Download [#download] The extension also supports downloading any conversation thread as a `.md` file for archiving or sharing. A complete example with all supported features ## Next Steps [#next-steps] * **[Memories](/docs/memories)**: What the extension captures. Create, search, and organize your knowledge * **[Threads](/docs/threads)**: Thread backup and distillation workflow * **[Access Mem Anywhere](/docs/remote-access)**: Connect the extension to a remote Mem instance # Bub × Nowledge Mem (/docs/integrations/bub) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Bub. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ```bash title="One-liner install" pip install nowledge-mem-bub ``` Bub records every session through its tape system. Nowledge Mem adds the layer above: knowledge from all your other AI tools, decisions made in Claude Code, preferences set in Cursor, insights from ChatGPT, searchable inside Bub. And what you learn in Bub flows back to every other tool. ## Before You Start [#before-you-start] * **Nowledge Mem** running locally ([installation](/docs/installation)) * **Bub** installed ([bub.build](https://bub.build)) * **`nmem` CLI** in your PATH: in Nowledge Mem go to **Settings → Preferences → Developer Tools → Install CLI**, or `pip install nmem-cli` ```bash nmem status # Nowledge Mem is running uv run bub --help # Bub is available ``` ## Setup [#setup]
### Install the plugin [#install-the-plugin-step] ```bash pip install nowledge-mem-bub ```
### Verify hooks [#verify-hooks-step] ```bash uv run bub hooks ``` You should see `nowledge_mem` listed for `system_prompt`, `build_prompt`, and `save_state`.
### Try a knowledge-backed prompt [#try-a-knowledge-backed-prompt-step] Ask Bub something that depends on your past work: ```bash uv run bub run "what was I working on this week?" ``` If you have existing knowledge in Nowledge Mem, the agent should find it through `mem.search`. That's success: Bub can now see knowledge from your other tools.
## Update [#update] ```bash python3 -m pip install --upgrade nowledge-mem-bub ``` ## Customize Safely [#customize-safely] Bub does not have a separate durable instruction file for this plugin today. * Use environment variables and Bub's own runtime prompt/config surfaces for durable behavior changes * Keep the installed Python package as shipped; do not patch site-packages just to change language, recall style, or save thresholds For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## What You Can Do [#what-you-can-do] **Find knowledge from other tools** Ask "what did we decide about the database?" and the agent searches across decisions you made in Claude Code, insights from ChatGPT, notes from Cursor, not just this Bub session. **Save knowledge for everywhere** When you reach a conclusion in Bub, `mem.save` stores it so your next Claude Code session, Cursor project, or ChatGPT conversation can find it too. **Start with today's context** With session context mode on, your Working Memory briefing and relevant past knowledge are ready before you ask. No repeating yourself across tools. **Trace how ideas evolved** `mem.connections` shows how a decision changed over time, which tools you discussed it in, and what source documents back it up. ## Two Modes [#two-modes] | Mode | Config | What happens | | ------------------- | ------------------------ | -------------------------------------------------------------------------------------------- | | **Default** | nothing | The agent searches and saves on demand. Conversations flow into Mem for other tools to find. | | **Session context** | `NMEM_SESSION_CONTEXT=1` | Working Memory and relevant knowledge injected automatically each turn. | Most users should start with the default. Enable session context when you want guaranteed recall from the first message. ## Tools [#tools] | Tool | What it does | | ----------------- | ------------------------------------------------------------------------- | | `mem.search` | Search knowledge from all your tools. Supports label and date filters. | | `mem.save` | Save a decision, insight, or preference so any tool can find it. | | `mem.context` | Read today's Working Memory: focus areas, priorities, recent activity. | | `mem.connections` | Explore how a piece of knowledge relates to others across tools and time. | | `mem.timeline` | Recent activity grouped by day. | | `mem.forget` | Delete a memory by ID. | | `mem.threads` | Search past conversations from any tool. | | `mem.thread` | Fetch full messages from a conversation with pagination. | | `mem.status` | Connection and configuration diagnostics. | All tools work as Bub comma commands too: `,mem.search query=...` ## Configuration [#configuration] No config needed for local use. | Env Variable | Default | What it does | | ---------------------- | --------- | ------------------------------------------------------- | | `NMEM_SESSION_CONTEXT` | `false` | Inject Working Memory + recalled knowledge each turn | | `NMEM_SESSION_DIGEST` | `true` | Feed Bub conversations into Mem for other tools to find | | `NMEM_API_URL` | *(local)* | Remote Nowledge Mem server URL | | `NMEM_API_KEY` | *(none)* | API key for remote access | For a persistent shared setup, configure this machine once with `nmem config client ...`. Environment variables still take priority when you need a temporary override. ### Spaces [#spaces] Bub is process-scoped today. * Use `NMEM_SPACE="Research Agent"` when one Bub process belongs to one lane. * If you run several Bub agents with different memory lanes, give each process its own `NMEM_SPACE`. * If you do not have a real lane, stay on **Default**. ### Remote access [#remote-access] ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` See [Access Mem Anywhere](/docs/remote-access). ## Troubleshooting [#troubleshooting] **Plugin not loading.** Run `uv run bub hooks` and check for `nowledge_mem`. Make sure `nowledge-mem-bub` is installed in the same Python environment as Bub. **nmem not found.** `pip install nmem-cli && nmem status` **Server not responding.** Start the Nowledge Mem desktop app, or check `nmem status` for diagnostics. ## Related [#related] * [Connectors overview](/docs/integrations) * [Claude Code](/docs/integrations/claude-code) · [OpenClaw](/docs/integrations/openclaw) · [Alma](/docs/integrations/alma) · [Gemini CLI](/docs/integrations/gemini-cli) * Plugin source: [nowledge-mem-bub-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-bub-plugin) * [tape.systems](https://tape.systems) · [bub.build](https://bub.build) # ChatGPT Web and Desktop (/docs/integrations/chatgpt-web) ChatGPT can work with Nowledge Mem in two different ways: * **Browser extension**: capture insights and back up the current ChatGPT thread from the browser side panel. * **Remote MCP over OAuth**: let ChatGPT call your Mem server as a connector, so ChatGPT Web and ChatGPT desktop can search memories, threads, and library context during a chat. Use the browser extension when you want to save from ChatGPT. Use Remote MCP when you want ChatGPT to read from Mem. ## Option 1: Capture ChatGPT Conversations [#option-1-capture-chatgpt-conversations] Install **Nowledge Mem Exchange** if you want Mem to capture decisions, discoveries, and full thread backups from the ChatGPT page you are using.
### Install the browser extension [#install-the-browser-extension-step] Follow the [Browser Extension guide](/docs/integrations/browser-extension), then open the side panel on `chatgpt.com`.
### Choose what to save [#choose-what-to-save-step] Use **Always Remember** for automatic high-signal memory capture, **Manual Distill** when you know a thread matters, and **Thread Backup** when you want the full conversation saved as a thread.
## ChatGPT Business and Team History [#chatgpt-business-and-team-history] Personal ChatGPT accounts can usually use [OpenAI's official data export](https://help.openai.com/en/articles/7260999-how-do-i-export-my-chatgpt-history-and-data), then import the exported `chat.html` through [Import existing conversations](/docs/import-existing-conversations). ChatGPT Business, Enterprise, and some Team workspaces may not expose the same full conversation export in ChatGPT settings today. If you need old workspace history in Mem, treat this as a data portability workflow: * For conversations you can still open, use the Exchange side panel to save the current thread. * For files you already exported locally, import them from **Threads → Import → Bulk Import** or with the local `nmem` CLI. * For company or team data, check your workspace policy first. Do not paste ChatGPT access tokens into tools you do not fully trust. Community threads discuss tools such as [chatGPT\_extractor](https://github.com/richlow/chatGPT_extractor) and [export-chatgpt](https://github.com/brianjlacy/export-chatgpt) for ChatGPT Team or Business history. These are not OpenAI or Nowledge Mem tools. They may depend on ChatGPT web session tokens or private endpoints, may break when ChatGPT changes, and may be disallowed by your workspace policy. Use them only for data you are allowed to export, on a machine and codebase you trust. After you have a local export folder, you can ask your coding agent to do the import safely: ```text I exported my ChatGPT Business/Team conversations to: /path/to/export-folder Please inspect the files locally without uploading them anywhere. Use the local `nmem` CLI to import the conversations into Nowledge Mem as ChatGPT threads. Start with a small sample, verify with `nmem t list --source chatgpt -n 5`, then import the rest. Preserve titles and timestamps when available, set the source to `chatgpt`, and do not create long-term memories automatically. ``` For a single Markdown, JSON, or HTML file, the agent can start with: ```bash nmem t import --file /path/to/conversation.md --source chatgpt ``` For context on why this is needed, see the OpenAI community discussion about [ChatGPT Team export limitations](https://community.openai.com/t/export-chats-in-chatgpt-team/620984/29). ## Option 2: Let ChatGPT Use Mem Through MCP [#option-2-let-chatgpt-use-mem-through-mcp] Use this when ChatGPT asks for a remote MCP connector URL. Mem uses Access Anywhere plus OAuth, so you do not paste a private `nmem_` API key into ChatGPT. ChatGPT is a cloud client. It cannot reach `localhost` or a private LAN address on your machine. Configure Access Anywhere with a public HTTPS endpoint first, then copy the Mem MCP endpoint that ends with `/mcp`.
### Start Remote MCP OAuth in Mem [#start-remote-mcp-oauth-in-mem-step] Open **Mem → Connectors → AI Tools → Remote MCP over OAuth**, then click **Start setup**. You can do this from the desktop app, the desktop app in remote-client mode, or the web client at your public HTTPS Mem address. Mem opens a pairing page in your browser and copies the `/mcp` URL. Keep using that same browser profile for the ChatGPT OAuth approval step. If you accidentally close the pairing page or ChatGPT's approval page, return to **Remote MCP over OAuth** in Mem and click **Start over**. Mem opens a fresh pairing page immediately; you do not need to wait for the previous 30-minute pairing window to expire. If you are using the web client or a desktop app connected to a remote Mem server, the OAuth setup is created on that remote server. The copied MCP URL will use that server's public HTTPS address, not `127.0.0.1`. Start Remote MCP OAuth from Mem
### Create a connector in ChatGPT settings [#create-a-connector-in-chatgpt-settings-step] Open [ChatGPT Connectors Advanced settings](https://chatgpt.com/#settings/Connectors/Advanced), then choose **Create**. Create a ChatGPT connector
### Paste the Mem MCP endpoint [#paste-the-mem-mcp-endpoint-step] Copy the **Access Anywhere MCP endpoint** from Mem. It must end with `/mcp`, for example: ```text https://your-access-anywhere-domain.example/mcp ``` Paste that URL into ChatGPT and continue. Paste the Mem MCP endpoint
### Approve Mem through OAuth [#approve-mem-through-oauth-step] When Mem opens the OAuth approval page, allow ChatGPT to use Mem. If you see "Pair this browser with Mem", return to Mem, click **Start over**, and continue in the same browser profile that opened the pairing page. Approve Mem on the OAuth page
### Confirm the connector was created [#confirm-the-connector-was-created-step] ChatGPT should now show the Mem connector in its connector list. ChatGPT shows the connector after creation
### Enable the connector in ChatGPT [#enable-the-connector-in-chatgpt-step] Allow the connector for the current ChatGPT workspace or chat context. Allow the connector in ChatGPT
### Ask ChatGPT to use Mem [#ask-chatgpt-to-use-mem-step] Ask ChatGPT to search your Mem context. In ChatGPT Web or the ChatGPT desktop app, mention `@Nowledge Mem`, then ask for what you need, for example: "Search my Mem for the project decision about the database migration." Use Mem from ChatGPT ChatGPT currently creates custom connectors from the web settings page. Once the connector is added, the same ChatGPT account can use it in the ChatGPT desktop app by mentioning `@Nowledge Mem` in a chat.
## Which Path Should I Use? [#which-path-should-i-use] | Goal | Use | | ---------------------------------------------------------------------- | -------------------------------------------------------------------- | | Save useful ChatGPT conversations into Mem | Browser extension | | Let ChatGPT Web or desktop search Mem during a conversation | Remote MCP over OAuth | | Import years of old ChatGPT history | [Import existing conversations](/docs/import-existing-conversations) | | Bring over ChatGPT Team or Business history without an official export | Export locally with a tool you trust, then import files with `nmem` | ## Related [#related] * [Connectors overview](/docs/integrations) * [Access Anywhere](/docs/remote-access) * [Browser Extension](/docs/integrations/browser-extension) * [Import existing conversations](/docs/import-existing-conversations) # Claude Code (/docs/integrations/claude-code) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Claude Code. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ```bash title="One-liner install" claude plugin marketplace add https://github.com/nowledge-co/community && claude plugin install nowledge-mem@nowledge-community ``` Claude Code supports plugins: install once for built-in autonomous behavior. No system prompts or MCP configuration needed. Your agent searches what you know, saves what matters, without you asking. Install the plugin, make sure `nmem` is available, start a new Claude Code session, and verify one real behavior: Context Bundle or Working Memory loads at session start, or `/search` / `/save` works without extra wiring. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * Claude Code installed ## Setup [#setup]
### Install the plugin [#install-the-plugin-step] ```bash # Add the Nowledge community marketplace claude plugin marketplace add https://github.com/nowledge-co/community # Install the Nowledge Mem plugin claude plugin install nowledge-mem@nowledge-community ``` The plugin requires `nmem` CLI: ```bash # Option 1 -- uvx (no installation needed) curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version # Option 2 -- pip pip install nmem-cli ``` > If the Nowledge Mem desktop app is on this machine, the safest path is **Settings → Preferences → Developer Tools → Install CLI**. For remote-only machines without the desktop app, use `uvx` or install manually.
### Use slash commands and skills [#use-slash-commands-and-skills-step] **Slash commands:** * `/save`: Save the current session to Nowledge Mem * `/sum`: Distill insights from this conversation * `/search `: Search your knowledge base * `/status`: Check server connection and status **Natural language:** Say "Save this session" or "Distill this conversation" and Claude runs the right `nmem` command automatically. **Autonomous (skills):** The plugin includes three skills that run on their own: * **Read Working Memory**: loads Context Bundle when available, or your daily briefing fallback at session start and after context compaction * **Search Memory**: searches when you reference past work * **Distill Memory**: suggests distillation at breakthrough moments **On request:** **Save Thread**: saves sessions when you ask ("save this session", "checkpoint this")
## Update [#update] ```bash claude plugin marketplace add https://github.com/nowledge-co/community claude plugin marketplace update nowledge-community claude plugin update nowledge-mem@nowledge-community # Restart Claude Code to apply changes ``` ## Import Older Sessions [#import-older-sessions] Automatic capture starts after the plugin and hooks are installed. To bring older Claude Code sessions into Nowledge Mem, preview first: ```bash nmem t sync --from claude-code --all-projects --limit 20 ``` Then import: ```bash nmem t sync --from claude-code --all-projects --apply ``` Use `-p /path/to/project` instead of `--all-projects` when you only want one project. The command reads local Claude Code session files on this machine and writes to the Mem server configured in `nmem`. ## Spaces [#spaces] Spaces are optional and explicit. The Claude Code plugin does not create or select a Mem space from your current folder, git repository, branch, or project name. Without an override, Context Bundle, Working Memory, search, and automatic session capture all use your default Mem space. Set `NMEM_SPACE` only when this whole Claude Code process should use an existing Mem space: ```bash NMEM_SPACE="Research Agent" claude ``` For multi-agent launchers, prefer a stable `NMEM_AGENT_ID` for the worker identity. Add `NMEM_SPACE` only when that worker should override its identity's default space. ## Customize Safely [#customize-safely] Use Claude Code's own memory files, not the installed plugin directory: * `CLAUDE.local.md` for your personal tweaks that should survive updates * `CLAUDE.md` for repo-shared rules Do not edit the installed Nowledge Mem plugin files directly. For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## Lifecycle Hooks [#lifecycle-hooks] The plugin uses [Claude Code hooks](https://code.claude.com/docs/en/hooks) for automatic lifecycle management: | Event | Trigger | Action | | ------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------- | | `SessionStart` (startup/resume/clear) | New session, resume, or clear | Loads Context Bundle via `nmem context`, falls back to `nmem wm read`, then local file | | `SessionStart` (compact) | After context compaction | Re-loads Context Bundle or Working Memory + prompts Claude to checkpoint progress | | `UserPromptSubmit` | Every user message | Injects search/save syntax as context Claude can see | | `PreCompact` | Before manual or automatic compaction | Saves the exact Claude Code session before context is compressed | | `Stop` | Model finishes responding | Captures session to knowledge graph with a bounded retry window | Context Bundle, or Working Memory on older CLIs, is refreshed after compaction. The `PreCompact` hook saves the full local transcript before Claude Code compresses it, and the `Stop` hook keeps normal turn-by-turn capture running even when Nowledge Mem runs on a different machine (remote mode). If Claude Code needs a moment to flush the transcript file after a response, the hook waits and retries instead of reporting a silent no-op save. If the desktop app's Claude Code file watcher is also enabled, you can leave it on. The watcher and plugin hooks converge on the same `claude-code-` thread, so repeated saves update the existing thread instead of creating a second one. ### Local vs Remote [#local-vs-remote] The plugin works transparently in both modes: * **Local** (Mem on same machine): Context Bundle or Working Memory is read through Mem. The plugin keeps `~/ai-now/memory.md` only as the Default-space compatibility fallback when the API path is unavailable. Sessions are captured by the desktop app file watcher, the Stop hook, and the PreCompact hook before context compression. * **Remote** (Mem on different machine): configure this machine once: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` That writes the shared local client config used by `nmem` and the plugin. You can still use environment variables (`NMEM_API_URL`, `NMEM_API_KEY`) for temporary overrides. Priority: CLI flags > env vars > config file > defaults. When the Stop or PreCompact hook runs `nmem t save --from claude-code`, Claude's session files are read locally on the machine running Claude Code, then uploaded to Mem as normalized thread messages. By default that means `~/.claude`, but if you've moved Claude's config, `CLAUDE_CONFIG_DIR` is used automatically. The remote Mem server does not need direct access to that local folder. ## Go Further [#go-further] **[AGENTS.md](https://github.com/nowledge-co/community/blob/main/examples/AGENTS.md)**: a complete memory-keeper agent example using the [agents.md standard](https://agents.md/). Works with any AI coding agent. ## Related [#related] * [Connectors overview](/docs/integrations): native connectors, reusable packages, MCP, and browser capture * [Claude Desktop](/docs/integrations/claude-desktop) · [Codex](/docs/integrations/codex-cli) · [Alma](/docs/integrations/alma) · [OpenClaw](/docs/integrations/openclaw) · [Raycast](/docs/integrations/raycast) · [Other Chat AI](/docs/integrations/other-chat-ai) # Claude Desktop (/docs/integrations/claude-desktop) Install once on macOS or Windows. No separate Python or Node install is required. After that, Claude Desktop can search your memory, save new context, and update existing knowledge during any conversation. After install, click the `+` button in Claude Desktop and open **Connectors**. You should see **Nowledge Mem** listed there, ready to use in chat. ## Before You Start [#before-you-start] * Nowledge Mem is running on this machine ([installation](/docs/installation)), or you already have a reachable remote Mem server * Claude Desktop is installed and up to date ## Setup [#setup]
### Download the extension [#download-the-extension-step]
### Install and restart Claude Desktop [#install-and-restart-claude-desktop-step] Double-click the downloaded `claude-dxt.mcpb` file, click **Install**, then restart Claude Desktop once. Install Extension
### Use Mem in chat [#use-mem-in-chat-step] Ask Claude to save insights, search your memories, or update anything in your knowledge base. Use Mem in Claude Desktop Claude Desktop with Mem and graph view
## Access Mem Anywhere [#access-mem-anywhere] The extension connects to your local Mem by default. For remote access, it reads the same shared client config as `nmem`. If you're starting **Access Anywhere** from Nowledge Mem Desktop on the same machine, you usually do not need to do anything else. The desktop app writes this config for you automatically. If Claude Desktop is running on a different machine, configure that machine first: Recommended: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` This writes the same shared client config that Claude Desktop reads. Manual file paths are below if you prefer to inspect or edit it directly. Path: ```text ~/.nowledge-mem/config.json ``` Path: ```text %USERPROFILE%\.nowledge-mem\config.json ``` Use your server root URL in `apiUrl`. If you already have an older config that ends in `/remote-api` or `/mcp`, the extension still accepts it. Restart Claude Desktop after changing the connection. ## Troubleshooting [#troubleshooting] If Mem does not appear in Claude Desktop: 1. Click the `+` button in the chat box and open **Connectors**. Confirm **Nowledge Mem** is listed. 2. Open **Settings → Extensions → Advanced Settings** in Claude Desktop and inspect the extension status and logs. 3. If you're using remote access, run `nmem config client show` and verify the URL and API key state are correct on that machine. ## Related [#related] * [Connectors overview](/docs/integrations): native connectors, reusable packages, MCP, and browser capture * [Claude Code](/docs/integrations/claude-code) · [Codex](/docs/integrations/codex-cli) · [Alma](/docs/integrations/alma) · [OpenClaw](/docs/integrations/openclaw) · [Raycast](/docs/integrations/raycast) · [Other Chat AI](/docs/integrations/other-chat-ai) # CodeBuddy × Nowledge Mem (/docs/integrations/codebuddy) Paste this into CodeBuddy: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for CodeBuddy. Verify with nmem status and the Context Bundle or Working Memory check, then run a short session and confirm the thread appears with nmem t list --source codebuddy. ``` CodeBuddy can use Nowledge Mem through a native CodeBuddy plugin. The plugin gives CodeBuddy startup context, Mem MCP tools, quick commands, and lifecycle hooks that sync CodeBuddy's local transcript into Mem Threads. This guide is for **CodeBuddy Code**, the terminal coding agent. For Tencent's office-agent surface, use the [WorkBuddy guide](/docs/integrations/workbuddy); WorkBuddy uses the same plugin abstraction but stores configuration under `.workbuddy`. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * CodeBuddy Code is installed * `nmem` works on the same machine as CodeBuddy ```bash nmem status codebuddy --version ``` If `nmem` exists but rejects `t sync --from codebuddy` or `config mcp show --host codebuddy`, update the CLI before debugging MCP or session sync: * Desktop-bundled CLI: open Mem and run **Settings → Preferences → Developer Tools → Install bundled CLI** again. * PyPI CLI: `python3 -m pip install --user --upgrade nmem-cli` * pipx CLI: `pipx upgrade nmem-cli` If CodeBuddy runs on a different machine from the Mem desktop app, install the standalone CLI there first and point it at your Mem server: ```bash python3 -m pip install --user nmem-cli nmem config client set url https://your-server nmem config client set api-key your-key ``` ## Install The Plugin [#install-the-plugin] Add the Nowledge community marketplace, then install the plugin: ```text /plugin marketplace add nowledge-co/community /plugin install nowledge-mem@nowledge-community ``` The marketplace is backed by `community/.codebuddy-plugin/marketplace.json`. The plugin includes: * a CodeBuddy plugin manifest * a local MCP server for `http://127.0.0.1:14242/mcp/` * startup guidance and a Nowledge Mem skill * hooks for `Stop`, `SessionEnd`, `PreCompact`, and `SubagentStop` * quick commands under `/nowledge-mem:*` For remote Mem or authenticated localhost, generate a CodeBuddy MCP block: ```bash nmem config mcp show --host codebuddy ``` Paste the generated `nowledge-mem` server into `~/.codebuddy/.mcp.json`, `$CODEBUDDY_CONFIG_DIR/.mcp.json`, or a project `.mcp.json`. ## Thread Sync [#thread-sync] CodeBuddy passes `session_id` and `transcript_path` to lifecycle hooks. The Nowledge Mem plugin uses those fields instead of guessing where the latest transcript is. After install, the hook runs: ```bash nmem --json t sync --from codebuddy --session-id --session-dir --all-projects --apply ``` That command runs on the CodeBuddy machine, reads the local `.jsonl` transcript under `$CODEBUDDY_CONFIG_DIR/projects` or `~/.codebuddy/projects`, and uploads normalized messages to your local or remote Mem server. It is safe to rerun; Mem deduplicates repeated imports. ## Verify [#verify] Start a new CodeBuddy session and ask: ```text Is Nowledge Mem connected? Read my current context. ``` Success means CodeBuddy can call the Nowledge Mem MCP tools and return Context Bundle, Working Memory, or an empty-but-successful memory result. Then finish a short exchange and check: ```bash nmem t list --source codebuddy -n 5 ``` You should see the recent CodeBuddy thread after the hook has run. If hooks do not appear to run, check: ```bash tail -n 50 ~/.codebuddy/logs/nowledge-mem-hook.log ``` If you set `CODEBUDDY_CONFIG_DIR`, check that directory's `logs/nowledge-mem-hook.log` instead. ## Import Older Sessions [#import-older-sessions] Preview first: ```bash nmem t sync --from codebuddy --limit 20 ``` Import when the preview looks right: ```bash nmem t sync --from codebuddy --apply ``` For a custom CodeBuddy config directory: ```bash CODEBUDDY_CONFIG_DIR="$HOME/.my-codebuddy-config" nmem t sync --from codebuddy --apply ``` ## Customize Behavior [#customize-behavior] Use CodeBuddy's own instruction surfaces: * `~/.codebuddy/CODEBUDDY.md` for personal global guidance * project `CODEBUDDY.md` for shared repo guidance * `.codebuddy/rules/*.md` for structured project rules Do not edit installed plugin files. Marketplace updates can replace them. ## Related [#related] * [Connectors overview](/docs/integrations) * [Threads](/docs/threads) * CodeBuddy docs: [Plugin Reference](https://www.codebuddy.ai/docs/cli/plugins-reference) · [Hooks Reference](https://www.codebuddy.ai/docs/cli/hooks) · [MCP](https://www.codebuddy.ai/docs/cli/mcp) # Codex (/docs/integrations/codex-cli) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Codex. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Best result on modern Codex: install the plugin, keep the bundled Nowledge Mem MCP server enabled, and run the hook setup once. SessionStart injects your current Nowledge context, prompt routing keeps historical work pointed at the cross-tool source, MCP gives Codex low-friction retrieval and write tools, and the Stop hook captures the real transcript. Switch between Codex, Claude Code, Gemini, and Cursor without losing context. The Codex package injects Context Bundle / Working Memory at startup, bundles a local MCP server, routes continuation work toward search, and captures threads automatically. Codex still decides when a targeted search is useful, but it no longer has to choose Nowledge from skill descriptions alone. That is why the recommended setup is hybrid: plugin + MCP + hook. Codex desktop app and Codex CLI use the same `~/.codex` configuration, plugin cache, hooks, and MCP settings. This guide uses `codex` commands because setup is managed by the CLI, but the installed connector applies to both. Start a session and ask "What was I working on?" You should see your recent focus areas and priorities. Then ask a continuation-style question such as "What did we decide before about this release?" On a healthy setup, Codex should move from Working Memory into retrieval instead of stopping at the briefing. After a short turn, `nmem t search "phrase from that turn" --source codex` should find the captured Codex thread. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * Codex desktop app or Codex CLI installed * `nmem` CLI in your `PATH` ## Setup [#setup]
### Install `nmem` [#install-nmem-step] ```bash # Option 1: uvx curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version # Option 2: pip pip install nmem-cli ``` If Nowledge Mem is already running on the same machine through the desktop app, the cleanest setup is **Settings → Preferences → Developer Tools → Install CLI**.
### Install the plugin [#install-the-plugin-step] If you run into older instructions that copy files into `~/.codex/plugins/cache/local/...`, treat that as legacy fallback only. The primary path is: add the marketplace, install the plugin from that marketplace, then enable it in config. ```bash codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin codex plugin add nowledge-mem@nowledge-community ``` If your Codex build only supports the legacy top-level subcommand: ```bash codex marketplace add nowledge-co/community ``` You can also open Codex `/plugins` and install `nowledge-mem@nowledge-community` from there. Prefer the sparse marketplace command when your Codex build supports it. Codex only pulls the marketplace metadata and the Codex plugin package instead of cloning the whole community repository, which avoids 30-second clone timeouts on slower networks.
### Enable the plugin [#enable-the-plugin-step] Put this in `~/.codex/config.toml`: ```toml [features] plugins = true hooks = true [plugins."nowledge-mem@nowledge-community"] enabled = true ``` Restart Codex after installation. The current package includes a local Nowledge Mem MCP server at `http://127.0.0.1:14242/mcp/`. Codex user config wins if you define your own `mcp_servers.nowledge-mem`, so remote Mem and custom local ports stay explicit.
### Enable lifecycle context and thread capture [#enable-lifecycle-context-and-thread-capture-step] Codex uses hooks for automatic startup context, memory routing, and thread capture. Current Codex builds load hooks from enabled plugins automatically. Older builds used a separate `plugin_hooks` feature gate; the setup script detects that host capability and adds the compatibility flag only when it is still required. Run the plugin's hook setup once after install or update: ```bash HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" if [ -z "$HOOK_SETUP" ]; then echo "Hook setup was not found. Open Codex, run /plugins, install nowledge-mem@nowledge-community, then retry." else python3 "$HOOK_SETUP" fi ``` Restart Codex after setup. When Codex asks you to review changed hooks, trust the Nowledge Mem SessionStart, UserPromptSubmit, and Stop hooks; enabling a hook and trusting its command are separate safeguards. The SessionStart hook injects Context Bundle, falling back to Working Memory when needed. A short UserPromptSubmit hook keeps continuation, review, regression, release, connector, prior-decision, and exact-history work routed to Nowledge search. The Stop hook calls `nmem t save --from codex`, reads the local transcript, and uploads through your normal `nmem` client configuration. Local and remote Mem use the same setup. If Codex sees both the plugin Stop hook and the host-level fallback, the hook skips the duplicate save for the same transcript state. The same setup also checks your `nmem` client configuration. If `nmem` has a saved API key or a non-default endpoint, it writes a managed Codex MCP block into `~/.codex/config.toml` so Codex uses the same Mem server as the CLI. On Windows PowerShell, run the installed setup script with the Python launcher: ```powershell $HookSetup = Get-ChildItem "$env:USERPROFILE\.codex\plugins\cache" -Recurse -Filter install_hooks.py | Where-Object { $_.FullName -like "*nowledge-mem*" } | Sort-Object FullName | Select-Object -Last 1 if ($null -eq $HookSetup) { Write-Host "Hook setup was not found. Open Codex, run /plugins, install nowledge-mem@nowledge-community, then retry." } else { py -3 $HookSetup.FullName } ```
### If you also use Codex Memory [#if-you-also-use-codex-memory-step] Codex local Memory and Nowledge Mem can run together, but they are not the same store. Codex Memory is generated state under your local `CODEX_HOME`; Nowledge Mem carries current Working Memory, exact conversations, sourced decisions, Spaces, and knowledge across every connected AI tool. In **Codex Settings → Personalization**, turn off **Allow memory generation from tool-assisted tasks**. This keeps tasks that used Nowledge MCP, web search, or tool search out of Codex's separate memory generator. You may leave **Enable memories** on if you still want Codex's local recall layer. The equivalent `~/.codex/config.toml` setting is: ```toml [memories] disable_on_external_context = true ``` Without this isolation, Codex can generate a local summary from a task that just retrieved Nowledge context. Future tasks may then answer from that older local summary without consulting the current cross-tool source. Plugin `0.1.26` and newer also inject an explicit routing boundary, but the isolation toggle closes the write-side duplicate-learning loop. The setup script reports this recommendation when needed; it never changes Codex Memory settings for you. Leaving Codex local Memory off is also a complete setup. Nowledge startup context, search, distillation, and transcript capture continue to work normally.
### Optionally add project-level guidance [#optionally-add-project-level-guidance-step] Copy or merge the plugin's `AGENTS.md` into your project root for stronger default memory behavior: ```bash git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community cp /tmp/nowledge-community/nowledge-mem-codex-plugin/AGENTS.md ./AGENTS.md rm -rf /tmp/nowledge-community ``` If your project already has an `AGENTS.md`, merge the Nowledge section instead of overwriting. This is the clean way to make Codex do more than the basic startup context check on continuation-heavy repos. Use your repo's own `AGENTS.md` as the override layer. Treat the package `AGENTS.md` as source text to copy or merge, not as a file to patch inside the Codex plugin install directory.
### Configure remote Mem when needed [#configure-remote-mem-when-needed-step] ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` `nmem` resolves connection settings in this order: 1. `--api-url` / `--api-key` flags 2. `NMEM_API_URL` / `NMEM_API_KEY` 3. `~/.nowledge-mem/config.json` 4. defaults If Mem is remote, override the bundled local MCP server in `~/.codex/config.toml` too: ```bash nmem config mcp show --host codex ``` Paste the generated TOML into `~/.codex/config.toml`, or rerun the hook setup if your installed plugin is `0.1.11` or newer. Direct MCP clients do not read `~/.nowledge-mem/config.json` automatically; this keeps Codex MCP and `nmem` pointed at the same Mem server. MCP gives Codex direct tools; `nmem` still powers the plugin-side fallback flows and real `save-thread`.
## Repo-level install (alternative) [#repo-level-install-alternative] Instead of a shared marketplace source, you can bundle the plugin in a project repo using a local Codex marketplace file. This makes the plugin available to anyone who clones the repo. ```bash git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community mkdir -p .agents cp -r /tmp/nowledge-community/nowledge-mem-codex-plugin ./.agents/nowledge-mem rm -rf /tmp/nowledge-community mkdir -p .agents/plugins ``` Create `.agents/plugins/marketplace.json`: ```json { "name": "local", "plugins": [ { "name": "nowledge-mem", "source": { "source": "local", "path": "./.agents/nowledge-mem" }, "policy": { "installation": "INSTALLED_BY_DEFAULT", "authentication": "ON_INSTALL" }, "category": "Productivity" } ] } ``` The `path` is relative to the repo root, not to the marketplace file. For this local setup, use: ```toml [plugins."nowledge-mem@local"] enabled = true ``` Then run the hook setup from the repo-local plugin: ```bash python3 ./.agents/nowledge-mem/scripts/install_hooks.py ``` ## Update [#update] If you installed the Codex package before `0.1.14`, refresh the marketplace first. Current Codex builds may refresh the marketplace checkout without reinstalling the already-installed package cache, so the hook setup file or bundled hook changes may still be missing until the package itself is updated. ```bash (codex plugin marketplace remove nowledge-community || codex marketplace remove nowledge-community || true) codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin codex plugin add nowledge-mem@nowledge-community ``` This intentionally re-adds the marketplace with Codex sparse checkout. Older installs used a full clone of the community repository; if Codex reports `git clone marketplace source timed out after 30s` or `early EOF`, this is the recovery path. You can also update or reinstall `nowledge-mem@nowledge-community` from Codex `/plugins`. Restart Codex after the package is updated. After the package itself is updated, refresh the hook runtime: ```bash HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" if [ -z "$HOOK_SETUP" ]; then echo "Hook setup is still missing. Reinstall nowledge-mem@nowledge-community from Codex /plugins, then retry." else python3 "$HOOK_SETUP" fi ``` If the marketplace is not registered yet, run: ```bash codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin || codex marketplace add nowledge-co/community ``` Then restart Codex. If you are using a repo-local `@local` source, update that local source path instead. ## Skills [#skills] The plugin skills still matter in the hybrid setup. They teach Codex when to use memory at all, while MCP gives Codex a lower-friction execution path once it decides to act. | Skill | Trigger | What it does | | ------------------------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `$nowledge-mem:working-memory` | Session start, "what am I working on" | Loads your daily Working Memory briefing and prefers MCP `read_working_memory` when available | | `$nowledge-mem:search-memory` | Prior work, past decisions, "why did we..." | Searches memories and threads with progressive inspection, preferring MCP retrieval when available | | `$nowledge-mem:save-thread` | Manual save request, or hook setup unavailable | Real Codex transcript import via `nmem t save --from codex` | | `$nowledge-mem:distill-memory` | Decisions, learnings, procedures emerge | Proactively saves durable insights to memory, preferring MCP writes when available | | `$nowledge-mem:status` | "Is Mem working?", errors | Checks server connectivity and configuration | ## Nowledge FS for Codex [#nowledge-fs-for-codex] [Nowledge FS](/docs/nowledge-fs) is the shared path-first layer behind Knowledge Tree. It is not a Codex-only feature. Codex can use the same layer through the MCP server with `mem_fs`, a path-first view across memories, threads, wiki pages, working memory, activities, sources, and artifacts. ```text mem_fs: recall "why did we change token refresh?" --in /memories -k 5 mem_fs: cat /memories/by-id/.memory.md mem_fs: ls /memories/by-label/auth ``` If MCP is not available, use the CLI: ```bash nmem fs recall "session token strategy" --in /memories -k 5 nmem fs grep "JWT rotation" /memories nmem fs cat /memories/by-id/.memory.md ``` Use `recall` for fuzzy intent, `find` for metadata constraints, `grep` for exact strings, `stat` before loading large bodies, and `cat` after a useful path has been found. `grep` is case-insensitive by default; add `--case-sensitive` for exact casing or `-E` for regex. This preview release is API-backed and works in desktop, web, and remote setups; mounting it as a real folder is planned for a later phase. ## Direct `nmem` Use [#direct-nmem-use] `nmem` remains the universal fallback and the real Codex thread-import path. The Stop hook uses the same command automatically: ```bash nmem --json wm read nmem --json m search "auth token rotation" --mode deep nmem --json t save --from codex -p . -s "Finished the auth refactor." nmem --json m add "JWT refresh failures came from clock skew." --title "JWT refresh failures traced to clock skew" --importance 0.9 --unit-type learning -l auth -s codex ``` By default, `nmem t save --from codex` reads sessions from `~/.codex`. If your Codex home lives somewhere else, set `CODEX_HOME` and the save path follows automatically. To import older Codex sessions, preview first: ```bash nmem t sync --from codex --all-projects --limit 20 ``` Then import: ```bash nmem t sync --from codex --all-projects --apply ``` Use `-p /path/to/project` instead of `--all-projects` when you only want one project. The command reads local Codex transcript files and writes to the Mem server configured in `nmem`. ## Migrating from Custom Prompts [#migrating-from-custom-prompts] If you previously used `nowledge-mem-codex-prompts`, the plugin covers everything the prompts did: 1. Install the plugin (see Setup above). 2. Remove old prompts: `rm ~/.codex/prompts/{read_working_memory,search_memory,save_session,distill}.md` 3. The plugin skills replace the prompts one-to-one. | Old prompt | New skill | | ------------------------------ | ------------------------------ | | `/prompts:read_working_memory` | `$nowledge-mem:working-memory` | | `/prompts:search_memory` | `$nowledge-mem:search-memory` | | `/prompts:save_session` | `$nowledge-mem:save-thread` | | `/prompts:distill` | `$nowledge-mem:distill-memory` | | *(none)* | `$nowledge-mem:status` | ## Troubleshooting [#troubleshooting] **"Command not found: nmem"** Install with `pip install nmem-cli` or use `uvx --from nmem-cli nmem`. See [Getting Started](/docs/installation). **"Cannot connect to server"** Run `nmem status` and `nmem config client show` for remote setups. See [Remote Access](/docs/remote-access). **Skills not appearing** Restart Codex after installing the plugin. Verify three things: the marketplace was added, `nowledge-mem@nowledge-community` was installed with `codex plugin add` or from `/plugins`, and `~/.codex/config.toml` has `[features] plugins = true`, `hooks = true`, and `[plugins."nowledge-mem@nowledge-community"] enabled = true`. Older hosts may also need `plugin_hooks = true`; rerun setup and let it detect that requirement instead of adding the flag by hand. If you intentionally use a repo-local source, use `[plugins."nowledge-mem@local"]`. **Codex says `unknown field description, expected hooks`** Update the plugin package to `0.1.19` or newer, then restart Codex: ```bash (codex plugin marketplace remove nowledge-community || codex marketplace remove nowledge-community || true) codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin codex plugin add nowledge-mem@nowledge-community ``` This warning came from a strict Codex hook parser rejecting extra metadata in `hooks/hooks.json`. Current packages keep that file schema-only. **Using Codex inside WSL** Install and update the Codex plugin from the same WSL distro that runs Codex. The Windows desktop app can show that a WSL Codex plugin is outdated, but it cannot safely run the update in Windows because that would use the wrong shell, plugin cache, Python, and `~/.codex` home. Copy the update command from Mem and run it inside WSL, then restart Codex there. **Startup context or Codex threads are not appearing automatically** Run the hook setup again, then restart Codex: ```bash HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" test -n "$HOOK_SETUP" && python3 "$HOOK_SETUP" ``` The setup enables the current hook feature, adds the legacy plugin-hook gate only on hosts that still expose it, and keeps a host-level Stop fallback for Codex builds that still need `~/.codex/hooks.json`. Open `/hooks` and make sure the Nowledge Mem SessionStart, UserPromptSubmit, and Stop hooks are both enabled and trusted. Trust is intentionally user-owned, so setup does not bypass it. **`codex mcp list` shows `Not logged in`** Update `nmem` so it matches your Mem app/server, install the CLI config from the desktop app if you use local desktop Mem, then rerun the hook setup: ```bash pip install -U nmem-cli nmem status HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" test -n "$HOOK_SETUP" && python3 "$HOOK_SETUP" ``` Do not run `codex mcp login nowledge-mem`. That command is for OAuth MCP servers. Nowledge Mem uses the URL and headers generated by `nmem config mcp show --host codex`. **"plugin is not installed"** Run `codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin` (or `codex marketplace add nowledge-co/community` on legacy Codex), install with `codex plugin add nowledge-mem@nowledge-community` or from `/plugins`, then verify the plugin key in `~/.codex/config.toml`. **It only reads Working Memory, but never searches or distills** Update the package to `0.1.26` or newer, rerun the hook setup, and confirm the bundled `nowledge-mem` MCP server plus the UserPromptSubmit hook are visible in Codex. If Codex local Memory is enabled, turn off **Allow memory generation from tool-assisted tasks**. For stronger repo-specific behavior, merge the package `AGENTS.md` into your project root. If Mem is remote or not on the default local port, add `mcp_servers.nowledge-mem` in `~/.codex/config.toml` to override the bundled endpoint. ## Related [#related] * [Connectors overview](/docs/integrations) * [Nowledge FS](/docs/nowledge-fs) * [Gemini CLI](/docs/integrations/gemini-cli) * [Claude Code](/docs/integrations/claude-code) * [Remote access](/docs/remote-access) # Copilot CLI (/docs/integrations/copilot-cli) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Copilot CLI. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ```bash title="One-minute install" copilot plugin marketplace add nowledge-co/community copilot plugin install nowledge-mem@nowledge-community ``` Copilot CLI supports plugins and lifecycle hooks. Install the plugin once, keep nmem available locally, and Copilot can start with Context Bundle or Working Memory, search when past context matters, and keep appending your session into Mem before the host compresses or closes the conversation. This is the dedicated Nowledge path for GitHub Copilot CLI. It is closer to Claude Code than to generic MCP: the plugin brings its own hooks, skills, and capture runtime. At the same time, Copilot still decides when to use the model-mediated skills, so project guidance such as AGENTS.md still helps when you want stronger proactive recall and distillation. Start a new Copilot session and ask What was I working on? You should see your recent focus and priorities. Then ask Copilot to save or checkpoint the session and confirm the thread appears in Mem. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * GitHub Copilot CLI installed * `nmem` CLI in your `PATH` ## Setup [#setup]
### Install `nmem` [#install-nmem-step] ```bash # Option 1: use the bundled CLI from the Mem desktop app # Settings → Preferences → Developer Tools → Install CLI # Option 2: pip pip install nmem-cli # Option 3: pipx pipx install nmem-cli ``` Then verify: ```bash nmem status ``` On Windows and Linux with the Nowledge Mem desktop app, `nmem` is already bundled.
### Install the plugin [#install-the-plugin-step] ```bash copilot plugin marketplace add nowledge-co/community copilot plugin install nowledge-mem@nowledge-community ``` Restart Copilot CLI after installation. The plugin now runs its capture runtime from its own packaged `hooks/` directory. Older installs can still fall back to `~/.copilot/nowledge-mem-hooks/` if that compatibility copy already exists.
### WSL bridge when needed [#wsl-bridge-when-needed-step] If Copilot CLI runs inside WSL, but `nmem` is installed on Windows through the Mem desktop app, create this bridge inside WSL: ```bash mkdir -p ~/.local/bin && cat > ~/.local/bin/nmem << 'SHIMEOF' #!/bin/bash python3 - "$@" <<'PY' import subprocess import sys cmd = subprocess.list2cmdline(["nmem.cmd", *sys.argv[1:]]) raise SystemExit(subprocess.run(["cmd.exe", "/s", "/c", cmd]).returncode) PY SHIMEOF chmod +x ~/.local/bin/nmem ``` This lets Copilot running in WSL call the Windows `nmem` cleanly.
### Add project guidance when you want stronger initiative [#add-project-guidance-when-you-want-stronger-initiative-step] The plugin handles Context Bundle / Working Memory bootstrap and session capture on its own. If you also want Copilot to search or distill more proactively in continuation-heavy repos, merge the package `AGENTS.md` into your project root: ```bash git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community cp /tmp/nowledge-community/nowledge-mem-copilot-cli-plugin/AGENTS.md ./AGENTS.md rm -rf /tmp/nowledge-community ``` If your repo already has an `AGENTS.md`, merge the Nowledge section instead of overwriting the file.
### Configure remote Mem when needed [#configure-remote-mem-when-needed-step] ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` This writes the shared local client config used by the plugin and `nmem`.
## What Happens Automatically [#what-happens-automatically] The plugin uses Copilot CLI hooks for five things: * **SessionStart** on startup, resume, and clear: load Context Bundle with `nmem --json context --source-app copilot-cli`, then fall back to Working Memory * **SessionStart** after compaction: reload Context Bundle or Working Memory and remind Copilot to checkpoint important findings * **UserPromptSubmit**: keep search and save guidance close to each turn * **Stop**: capture the recorded Copilot session asynchronously after each response * **PreCompact** and **SessionEnd**: capture the latest recorded session before compaction and when a session closes The capture hooks append only the new conversation content. They do not keep re-importing the whole session each time. ## Skills [#skills] The Copilot plugin keeps the user-facing surface simple. It does not ship a separate command-doc layer for save, search, or status. Instead, it relies on skills and the underlying `nmem` CLI. | Skill | When it helps | What it does | | --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------- | | `read-working-memory` | Session start, "what am I working on?" | Loads Context Bundle when available, or today's Working Memory briefing as the lightweight fallback | | `search-memory` | Prior work, earlier rationale, past discussions | Searches durable memories and prior threads | | `distill-memory` | A real decision or learning emerged | Saves durable knowledge into Mem | | `save-thread` | "Save this session", "Checkpoint this" | Saves a concise session summary thread on explicit request | For direct troubleshooting outside the skill surface, run `nmem status` in your terminal. ## Update [#update] ```bash copilot plugin marketplace add nowledge-co/community copilot plugin marketplace update nowledge-community copilot plugin update nowledge-mem ``` Then restart Copilot CLI. ## Customize Safely [#customize-safely] Use Copilot's own instruction files instead of editing the installed plugin: * `.github/copilot-instructions.md` or `.github/instructions/*.instructions.md` for shared repo rules * `~/.copilot/copilot-instructions.md` for your personal rules across repos For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## Troubleshooting [#troubleshooting] **`nmem` not found** Install `nmem-cli` with `pip` or `pipx`, or use the bundled CLI from the Mem desktop app. **Startup context never appears** Restart Copilot CLI after installation. Then run `nmem status` to confirm the local client can reach Mem. **Threads are not appearing in Mem** Restart Copilot CLI after install or update, then check `~/.copilot/nowledge-mem-hooks/hook-log.jsonl`. If you are on an older install or local development checkout, you can still run `scripts/install-hooks.sh` from the source tree as a compatibility fallback. **Copilot only reads startup context, but rarely searches or distills** That usually means the bootstrap hook is working, but your repo does not yet give Copilot strong enough behavioral guidance. Merge the plugin `AGENTS.md` into your project root, then retry with a continuation-style question. ## Related [#related] * [Connectors overview](/docs/integrations) * [Codex](/docs/integrations/codex-cli) * [Claude Code](/docs/integrations/claude-code) * [Remote access](/docs/remote-access) # Craft Agent × Nowledge Mem (/docs/integrations/craft-agent) Paste this into Craft Agent after setup: ```text Read the Nowledge Mem guide in the nowledge-mem source, check whether Mem is reachable, and tell me what context you can see. ``` Craft Agent can use Nowledge Mem through Craft's workspace source system. The source gives Craft the Mem MCP tools. The guide teaches Craft when to read Working Memory, search prior decisions, and save durable knowledge. For recorded conversations, use the CLI importer. Craft stores sessions locally as `session.jsonl`; `nmem` reads those files on the Craft machine and uploads normalized threads to your local or remote Mem server. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * Craft Agent is installed * `nmem` works on the same machine as Craft Agent ```bash nmem status ``` ## Setup [#setup] Generate the Craft source and guide: ```bash nmem config mcp show --host craft-agent ``` In the Craft workspace you want to connect: 1. Create `sources/nowledge-mem/`. 2. Save the generated `sourceConfig` JSON as `sources/nowledge-mem/config.json`. 3. Save the generated guide markdown as `sources/nowledge-mem/guide.md`. 4. Restart or reload Craft Agent. For remote Mem, configure the shared `nmem` client first, then regenerate: ```bash nmem config client set url https://your-server nmem config client set api-key your-key nmem config mcp show --host craft-agent ``` ## Verify [#verify] Ask Craft: ```text Is Nowledge Mem connected? Read my Working Memory or Context Bundle and summarize the current focus. ``` Success means Craft can call the Mem tools from the `nowledge-mem` source and can see your current context. ## Import Craft Sessions [#import-craft-sessions] Use this when you want the real Craft transcript saved in Mem: ```bash nmem t sync --from craft-agent --all-projects --limit 20 ``` Then import: ```bash nmem t sync --from craft-agent --all-projects --apply ``` The importer scans Craft workspaces under your Craft config directory. It uses each session's workspace header when available and writes stable `craft-agent-*` thread IDs, so reruns append with deduplication instead of creating duplicate threads. Useful filters: ```bash nmem t sync --from craft-agent --session-dir ~/.craft-agent/workspaces --limit 20 nmem t sync --from craft-agent --space work --apply ``` If you keep Craft config somewhere else, set `CRAFT_CONFIG_DIR` or pass `--session-dir`. ## What Is Automatic [#what-is-automatic] Craft can use memory tools whenever the source and guide are available, but Craft does not need a Nowledge npm package today. The workspace source handles MCP access; `nmem t sync --from craft-agent` handles transcript import. If Craft adds a stable lifecycle hook later, Nowledge Mem can add live capture on top of the same source name. Until then, treat real session capture as explicit CLI import. ## Related [#related] * [Connectors overview](/docs/integrations) * [Threads](/docs/threads) * Craft Agent repo: [craft-ai-agents/craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss) # Cumora (/docs/integrations/cumora) Cumora is an AI teammate workspace. Its agents have personas, can start conversations, and may carry their own internal memory. Nowledge Mem should not replace that. It should give each Cumora teammate access to the same durable, cross-tool knowledge layer the user already shares with Codex, Claude Code, Pi, OpenClaw, browsers, notes, and the Library. The important rule: do not give a shared computer-level daemon one `NMEM_AGENT_ID` if several Cumora teammates use it. If Atlas, Iris, Bram, and Nova all inherit the same daemon identity, Mem will treat them as one teammate. That is worse than leaving identity unset. ## Best Current Path [#best-current-path] Use a two-step setup: 1. Connect the AI coding tool Cumora launches. 2. Add a small Mem AI Identity instruction to each Cumora agent persona. This works even when Cumora gives you only one local npx or daemon command per computer, because the identity is selected by the agent's instruction, not by the daemon's environment. ## Connect The Runtime [#connect-the-runtime] Install and verify Nowledge Mem on the computer where Cumora starts the AI tool: ```bash nmem status ``` Then connect the tool Cumora launches, such as Codex or Claude Code: * [Codex](/docs/integrations/codex-cli) * [Claude Code](/docs/integrations/claude-code) * [Pi](/docs/integrations/pi) This gives that tool access to Mem tools, Context Bundle / Working Memory, and any session-sync hooks it supports. For example, if Cumora launches Codex or Claude Code and those connectors are installed, those tool sessions can sync through their Nowledge Mem hooks. ## Add The Persona Bridge [#add-the-persona-bridge] For each long-lived Cumora teammate, create a Mem AI Identity: ```bash nmem agents upsert atlas \ --name "Atlas" \ --default-space research \ --instructions "Research across the user's knowledge. Cite sources and separate facts from interpretation." ``` `Atlas` is the display name. `atlas` is the stable id. This command only creates the identity record; it is used when the Cumora persona passes `agent_id="atlas"` or when a future per-agent environment sets `NMEM_AGENT_ID=atlas`. Then add this short block to that Cumora agent's persona or system prompt: ```text Nowledge Mem: - At the start of a task, read Context Bundle as agent_id="atlas". - If the tool supports it, also pass host_agent_id="cumora:atlas". - Keep source_app as the AI tool when known, such as "codex" or "claude-code". - For later Nowledge Mem calls, pass agent_id="atlas" again so memory_search, thread_search, read_working_memory, and memory_add use the same identity and default space. - Save durable decisions, preferences, and procedures when they matter beyond this conversation. ``` If the agent only has CLI access, the same behavior is: ```bash nmem --json context --agent-id atlas --host-agent-id cumora:atlas --source-app codex ``` Use the returned active space for later commands: ```bash nmem --json m search "recent research decisions" --space research nmem --json m add "Atlas learned that ..." -t "Research note" --space research -s codex ``` If the agent has MCP access, prefer passing `agent_id` directly: ```text read_context_bundle(agent_id="atlas", source_app="codex", host_agent_id="cumora:atlas") read_working_memory(agent_id="atlas", source_app="codex", host_agent_id="cumora:atlas") memory_search(query="recent research decisions", agent_id="atlas", source_app="codex") thread_search(query="last onboarding discussion", agent_id="atlas", source_app="codex") memory_add(content="Atlas learned that ...", title="Research note", agent_id="atlas", source_app="codex") ``` This is the clean fallback until Cumora exposes per-agent environment variables or an official integration point. ## If Cumora Adds Per-Agent Env [#if-cumora-adds-per-agent-env] If Cumora later lets each agent set environment variables, move the identity out of the persona prompt and into that per-agent environment: ```bash NMEM_AGENT_ID=atlas NMEM_HOST_AGENT_ID=cumora:atlas ``` Do not set these on the shared daemon unless that daemon belongs to exactly one Cumora teammate. ## What Syncs [#what-syncs] Supported AI-tool sessions can sync. If Cumora launches Codex, Claude Code, Pi, OpenClaw, or another tool with a Nowledge Mem connector, use that connector's normal sync path. Cumora-native history is different. Nowledge Mem cannot directly import Cumora rooms or Cumora's internal agent memory unless Cumora exposes a local API, export, hook, or per-agent runtime integration point. Until then, Cumora's own internal memory stays inside Cumora. Nowledge Mem remains the user's cross-tool, cross-agent knowledge layer for the connected AI tools, saved memories, notes, and Library. ## Next [#next] * [Customize Connector Behavior](/docs/integrations/customize-behavior) * [Raft](/docs/integrations/raft) * [Multica](/docs/integrations/multica) # Cursor (/docs/integrations/cursor) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Cursor. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` The most reliable path today is local install from `~/.cursor/plugins/local/nowledge-mem-cursor`. It works before Marketplace acceptance and uses the same package you would later publish. If **Nowledge Mem** eventually becomes visible in Cursor Marketplace for your account, you can switch to that path later. The local package path below is the user-ready path now. The practical benefit is simple: install once, start a new agent session, and Cursor gets the rule, skills, hook, and MCP wiring together. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * Cursor IDE installed * Recommended: `nmem` in your `PATH` if you want automatic Context Bundle / Working Memory bootstrap and resumable handoff creation through the terminal tool If Nowledge Mem is already running on the same machine through the desktop app, the easiest path is **Settings → Preferences → Developer Tools → Install CLI**. That gives Cursor access to `nmem` for session-start Context Bundle / Working Memory bootstrap and explicit handoff creation. For real Cursor Agent thread history, Mem reads Cursor's local Agent transcript files from `~/.cursor/projects`. The desktop app can auto-sync them on the same machine. For a deliberate backfill, preview first: ```bash nmem t sync --from cursor --all-projects ``` Then import after you confirm the list: ```bash nmem t sync --from cursor --all-projects --apply ``` If you only want one project, point at its transcript folder: ```bash nmem t sync --from cursor --session-dir ~/.cursor/projects/Users-me-project/agent-transcripts --apply ``` ## One-Minute Setup [#one-minute-setup]
### Clone or open the package folder [#clone-or-open-the-package-folder-step] ```bash git clone https://github.com/nowledge-co/community.git cd community ```
### Copy the plugin into Cursor's local plugin folder [#copy-the-plugin-into-cursors-local-plugin-folder-step] ```bash mkdir -p ~/.cursor/plugins/local rm -rf ~/.cursor/plugins/local/nowledge-mem-cursor cp -R nowledge-mem-cursor-plugin ~/.cursor/plugins/local/nowledge-mem-cursor ``` If you want faster local iteration, you can try a symlink instead: ```bash ln -s "$(pwd)/nowledge-mem-cursor-plugin" ~/.cursor/plugins/local/nowledge-mem-cursor ``` Cursor staff have confirmed that local plugin symlink resolution is currently buggy in practice, so copy-first is the reliable path.
### Reload Cursor [#reload-cursor-step] Restart Cursor or run **Developer: Reload Window**. If Cursor still shows Claude Code wording, `save-thread`, or hooks like `beforeSubmitPrompt` and `stop`, remove the older imported `nowledge-mem` package from Cursor first. The local package here should expose only `sessionStart` plus the four Nowledge Mem skills. The local plugin id is `nowledge-mem-cursor` specifically to avoid colliding with that imported package.
### Start a new agent session [#start-a-new-agent-session-step] For the default same-machine setup, the bundled plugin assets are the intended zero-config path: * plugin manifest * rule * skills * session-start hook * local `mcp.json` If `nmem` is installed, the session-start hook can preload Working Memory into the new Cursor session before the agent begins.
### Configure MCP for remote Mem only [#configure-mcp-for-remote-mem-only-step] Only if you use remote Mem, open **Settings** (`Cmd/Ctrl+Shift+J`) -> **Features** -> **Model Context Protocol** and update the `nowledge-mem` server URL and headers. If you also want the `sessionStart` hook and `save-handoff` skill to work against remote Mem, point the local `nmem` client at the same remote server: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` The split is intentional: * Cursor MCP settings drive the plugin's memory tools * `nmem config client ...` drives the terminal-side bootstrap and handoff flow on this machine
## Update [#update] If you installed through the local plugin folder: * recommended copied path: replace `~/.cursor/plugins/local/nowledge-mem-cursor` with a fresh copy, then reload Cursor * optional symlink path: pull the latest `community` changes and reload Cursor, but switch back to copied install if Cursor stops detecting the plugin If Marketplace support appears later, you can uninstall the local copy and move to Marketplace. ## Customize Safely [#customize-safely] Use Cursor's own rule files for behavior changes: * `.cursor/rules/*.mdc` * `.cursorrules` Keep the packaged Nowledge Mem rule as the default. Do not patch the installed plugin files under `~/.cursor/plugins/...`. Full map: [Customize Integration Behavior](/docs/integrations/customize-behavior). ## Your First Success State [#your-first-success-state] You know the plugin is set up correctly when: * the plugin is installed from `~/.cursor/plugins/local/nowledge-mem-cursor` * you start a new Cursor agent session * if `nmem` is installed, Working Memory is already available at the start of the session * same-machine setup works without hand-editing MCP config * in remote mode, updating the `nowledge-mem` MCP server is enough to restore the same behavior * Cursor is not showing a stale Claude-oriented package surface such as `save-thread`, `beforeSubmitPrompt`, or `stop` ## What You Get [#what-you-get] * Bundled `.cursor-plugin/plugin.json` * Bundled `hooks/hooks.json` with a `sessionStart` Context Bundle / Working Memory bootstrap * Bundled `mcp.json` for local Nowledge Mem MCP connectivity * An always-on rule for Working Memory, routed recall, distillation, and handoff semantics * Four skills: `read-working-memory`, `search-memory`, `distill-memory`, and `save-handoff` * Real Cursor Agent transcript import through Mem desktop auto-sync or `nmem t sync --from cursor` ## What Users Usually Care About [#what-users-usually-care-about] For a fresh install, the important answers are simple: * local Mem: install the plugin and start a new session * remote Mem: install the plugin, then update the `nowledge-mem` MCP server URL and headers; if you want bootstrap and handoff too, also point `nmem` at the same remote server * best Cursor experience: keep `nmem` installed so the session-start hook can preload Working Memory and Cursor can create handoff summaries when needed ## Important Constraint [#important-constraint] This package intentionally does **not** expose `save-thread`. Cursor's plugin surface still does not expose a direct live transcript hook, so summary-only behavior must stay named `save-handoff`, not `save-thread`. Real Cursor Agent threads are imported by Mem desktop or `nmem t sync --from cursor`, which reads Cursor's local `agent-transcripts` JSONL files and appends deduplicated messages into Mem. ## Package Shape [#package-shape] This package is already arranged in Cursor's plugin format: ```text .cursor-plugin/plugin.json rules/nowledge-mem.mdc skills/*/SKILL.md hooks/hooks.json hooks/session-start.mjs mcp.json ``` Cursor's local plugin folder expects `.cursor-plugin/plugin.json` at the package root. This package already matches that contract, so the local install path above is stable and direct. ## Marketplace Later [#marketplace-later] If Cursor Marketplace accepts the package later, install **Nowledge Mem** there and keep the same behavior. Until then, the local plugin folder is the right path for users. ## Related [#related] * [Connectors overview](/docs/integrations) * [Claude Code](/docs/integrations/claude-code) * [Gemini CLI](/docs/integrations/gemini-cli) * [Remote access](/docs/remote-access) # Customize Integration Behavior (/docs/integrations/customize-behavior) If you tune how an integration behaves, that change should survive the next plugin update. The safe rule is simple: put your rule in the host's own instruction file or settings surface. Do not edit installed plugin files inside a cache or marketplace directory. Pick the tool you use, add one small rule in the file or settings listed below, then update the plugin once later to confirm your tweak still survives. ## Where To Put Your Changes [#where-to-put-your-changes] | Tool | Put your custom behavior here | Best for | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | | **Codex** | project `AGENTS.md` | Repo-specific memory behavior shared by Codex desktop app and CLI | | **Claude Code** | `CLAUDE.local.md` for personal rules, `CLAUDE.md` for shared repo rules | Personal tweaks or team-wide repo guidance | | **Copilot CLI** | `.github/copilot-instructions.md` or `.github/instructions/*.instructions.md` for shared repo rules, `~/.copilot/copilot-instructions.md` for personal rules | Shared or personal Copilot guidance | | **Cursor** | `.cursor/rules/*.mdc` or `.cursorrules` | Project-local Cursor behavior | | **Gemini CLI** | project `GEMINI.md`, optional `~/.gemini/GEMINI.md` | Shared repo rules or personal defaults | | **Hermes Agent** | `HERMES.md` for repo rules, `~/.hermes/SOUL.md` for personal rules | Repo-specific or global Hermes behavior | | **OpenCode** | project `AGENTS.md`, `~/.config/opencode/AGENTS.md`, or files listed in `opencode.json` `instructions` | Shared or personal OpenCode guidance | | **Pi** | project `AGENTS.md` | Project-local Pi guidance | | **OpenClaw** | OpenClaw plugin settings and OpenClaw's own prompt or agent config | Behavior toggles and custom prompting | | **Alma** | Alma plugin settings and the optional native `nowledge-mem` Skill | Recall and capture behavior, extra instructions | | **Bub** | Bub's own runtime prompt or config, plus shared `nmem` config | Bub-specific behavior and connection settings | | **Droid** | Droid's own prompt or instruction surface, plus shared `nmem` config | Droid-specific behavior and connection settings | | **Raycast** | Raycast preferences | Fixed launcher behavior such as server, key, and optional space | ## What Not To Do [#what-not-to-do] * Do not edit files inside installed plugin directories such as `~/.codex/...`, `~/.copilot/installed-plugins/...`, `~/.cursor/plugins/...`, or similar cache paths. * Do not patch bundled skills in place and expect updates to preserve those changes. * Do not invent a new override filename unless the host actually reads it. ## What Success Looks Like [#what-success-looks-like] Your setup is in a good state when all three are true: 1. Your custom rule lives in a file or settings surface the host actually owns. 2. The integration still works after a normal plugin or extension update. 3. Your behavior tweak is still active after that update without re-editing installed files. ## Good First Tweaks [#good-first-tweaks] * "Search prior release work before answering regression questions." * "Prefer saving Chinese notes when the user is working in Chinese." * "Be more aggressive about thread search when the user asks what we decided before." Keep the rule short. The goal is to shape behavior, not replace the whole integration guide. ## Multi-Agent Orchestrators [#multi-agent-orchestrators] If another app launches your agents for you, give each named worker a stable Mem AI Identity instead of letting every child process share the default identity. ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "Help with onboarding. Explain one step at a time." ``` This creates the Mem AI Identity named Cindy. Its command and environment ID is `cindy`. This command only creates the identity record; it does not make every Codex session use Cindy. Then configure that worker's environment: ```bash NMEM_AGENT_ID="cindy" ``` The identity is portable. You can move Cindy from Raft to another orchestrator, or from Codex to Pi, as long as the new AI tool is connected to Mem and receives the same `NMEM_AGENT_ID`. Only add `NMEM_SPACE="onboarding"` when this whole run should override the identity's default space. Keep `source_app` as the AI tool being launched. For example, a Codex worker launched by an orchestrator should still read Context Bundle as Codex. `NMEM_HOST_AGENT_ID` is an advanced external alias, not a second required identity field. If you want a variation of the same persona, create a new identity such as `cindy-reviewer` instead of changing every launcher setting. The new identity can start from Cindy's Rules, then evolve separately. For the Raft screenshot walkthrough, see [Raft](/docs/integrations/raft). ## Next [#next] * [Connectors overview](/docs/integrations) * [Codex](/docs/integrations/codex-cli) * [Claude Code](/docs/integrations/claude-code) * [Copilot CLI](/docs/integrations/copilot-cli) # Droid (/docs/integrations/droid) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Droid. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Add the Nowledge community marketplace, install `nowledge-mem@nowledge-community`, run `nmem status` once, then start a new Droid session. Droid gets a native connector surface for Context Bundle / Working Memory startup context, routed recall, distillation, status checks, and resumable handoffs. It intentionally does **not** claim `save-thread` yet. Droid is a good fit for Nowledge Mem because Factory plugins can bundle hooks, commands, and skills into one product surface while letting `nmem` stay the execution layer underneath. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * Factory Droid installed * `nmem` in your `PATH` If Nowledge Mem is already running on the same machine through the desktop app, the easiest path is still **Settings → Preferences → Developer Tools → Install CLI**. That gives Droid a clean `nmem` path for both local and remote setups. You can also install `nmem` standalone: ```bash # Option 1: pip pip install nmem-cli # Option 2: uvx curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version ``` ## One-Minute Setup [#one-minute-setup]
### Add the Nowledge community marketplace [#add-the-nowledge-community-marketplace-step] ```bash droid plugin marketplace add https://github.com/nowledge-co/community ```
### Install the plugin [#install-the-plugin-step] ```bash droid plugin install nowledge-mem@nowledge-community ```
### Run `nmem status` once [#run-nmem-status-once-step] For the default same-machine setup, it should point to `http://127.0.0.1:14242`.
### Start a new Droid session [#start-a-new-droid-session-step] The plugin will load Context Bundle when available, fall back to Working Memory, and make its commands and skills available inside Droid.
## Update [#update] ```bash droid plugin marketplace update nowledge-community droid plugin update nowledge-mem@nowledge-community ``` ## Customize Safely [#customize-safely] Droid does not yet expose a separate durable instruction file for this package. * Use Droid's own prompt or instruction surfaces when you want different memory style or saving behavior * Keep the installed plugin package untouched so marketplace updates stay clean For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## What You Get [#what-you-get] * Context Bundle / Working Memory bootstrap at session start, resume, clear, and compaction * Routed recall across memories and prior sessions * Distillation into durable memories * Explicit handoff creation when you want a resumable checkpoint * One stable remote path through `nmem` ## Commands [#commands] * `/nowledge-read-working-memory` * `/nowledge-search-memory` * `/nowledge-distill-memory` * `/nowledge-save-handoff` * `/nowledge-status` ## Remote Mem [#remote-mem] The recommended remote setup is: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` That writes the shared local client config for this machine and keeps Droid aligned with the same contract used by Gemini, Codex, and other `nmem`-based paths. ## Important Constraint [#important-constraint] This package intentionally exposes `save-handoff`, not `save-thread`. That distinction matters: * `save-thread` should mean importing the real recorded session messages * `save-handoff` means storing a concise resumable summary Droid does not yet have a real Nowledge transcript importer, so the plugin keeps the boundary honest instead of pretending a summary is a full session save. ## Local Checkout Fallback [#local-checkout-fallback] If you prefer validating from a local checkout: ```bash git clone https://github.com/nowledge-co/community.git cd community droid plugin marketplace add . droid plugin install nowledge-mem@nowledge-community ``` This works because the `community` repository publishes a repository-level Factory marketplace manifest and the Droid plugin as one package inside it. ## Related [#related] * [Connectors overview](/docs/integrations) * [Threads](/docs/threads) * [Cursor](/docs/integrations/cursor) * [Gemini CLI](/docs/integrations/gemini-cli) * [Remote access](/docs/remote-access) # Gemini CLI (/docs/integrations/gemini-cli) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Gemini CLI. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Google has replaced Gemini CLI with **Antigravity CLI** (`agy`). Gemini CLI stopped serving individual-tier accounts on **June 18, 2026**. If you are migrating, see the [Antigravity CLI guide](/docs/integrations/antigravity-cli) — the Nowledge Mem extension converts via `agy plugin import gemini`. Install `Nowledge Mem` from the official Gemini Extensions Gallery, restart Gemini CLI, and get both bundled MCP tools and `nmem` lifecycle capture. You can still install from GitHub or a local checkout at the end of this page. The official gallery path below is now the default recommendation. For most users, the mental model is simple: install the extension from the gallery, make sure `nmem` works once, then start a new Gemini session. The extension includes a local MCP connection for retrieval and memory writes; `nmem` still handles startup context, real thread save, status, and remote client config. ## Before You Start [#before-you-start] * Nowledge Mem running locally ([installation](/docs/installation)) or a reachable remote Mem server * Gemini CLI installed * `nmem` in your `PATH` If Nowledge Mem is already running on the same machine through the desktop app, the easiest path is **Settings → Preferences → Developer Tools → Install CLI**. That installs the bundled `nmem` CLI and points it at the default local Mem server. You can also install `nmem` standalone: ```bash # Option 1: pip pip install nmem-cli # Option 2: uvx curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version ``` ## One-Minute Setup [#one-minute-setup]
### Find Nowledge Mem in the gallery [#find-nowledge-mem-in-the-gallery-step] Open the **Gemini CLI Extensions Gallery** and search for **Nowledge Mem**.
### Install and restart [#install-and-restart-step] Install the extension, then restart Gemini CLI.
### Run `nmem status` once [#run-nmem-status-once-step] For the default same-machine setup, this should point to `http://127.0.0.1:14242 (default)`.
### Open a new Gemini CLI session [#open-a-new-gemini-cli-session-step] The extension will load `GEMINI.md`, discover its commands, expose the bundled MCP tools, and make the bundled skills available automatically.
## Update [#update] ```bash gemini extensions update nowledge-mem-gemini-cli ``` If you prefer the gallery, opening the Gemini CLI Extensions Gallery and updating Nowledge Mem reaches the same result. The important part is to start a fresh Gemini session after the update. ## Import Older Sessions [#import-older-sessions] Automatic capture starts after the extension is installed. To bring older Gemini CLI sessions into Nowledge Mem, preview first: ```bash nmem t sync --from gemini-cli --all-projects --limit 20 ``` Then import: ```bash nmem t sync --from gemini-cli --all-projects --apply ``` Use `-p /path/to/project` instead of `--all-projects` when you only want one project. The command reads local Gemini CLI session files on this machine and writes to the Mem server configured in `nmem`. ## Customize Safely [#customize-safely] Use Gemini's own context files for behavior changes: * project `GEMINI.md` * optional `~/.gemini/GEMINI.md` for personal defaults If the rule grows, split it into files and import them with `@file.md`. Do not edit the installed extension files directly. Full map: [Customize Integration Behavior](/docs/integrations/customize-behavior). ## Your First Success State [#your-first-success-state] You know Gemini is wired correctly when: * the gallery install succeeds * `nmem status` returns successfully * a new Gemini session exposes the Nowledge commands * Context Bundle or Working Memory appears at the start of a fresh session when there is context to show * `save-thread` imports a real Gemini session, and long sessions are saved before compression as well as at session end ## Remote Mem [#remote-mem] The recommended remote setup is: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` That writes the shared local client config for this machine. `nmem t save --from gemini-cli` reads Gemini's local session files on the machine where Gemini is running, then uploads normalized thread messages to Mem. The remote Mem server does not need direct access to `~/.gemini`. For Gemini MCP tools in remote mode, define a `nowledge-mem` server in Gemini `settings.json`. Gemini gives user settings precedence over the extension's bundled local MCP server: ```bash nmem config mcp show --host gemini-cli ``` Paste the generated JSON into Gemini's `settings.json`. Direct MCP clients do not read `~/.nowledge-mem/config.json` automatically; this keeps Gemini MCP and `nmem` pointed at the same Mem server. ## What You Get [#what-you-get] * Gemini-native Context Bundle / Working Memory startup context, hooks, commands, and skills * Bundled local MCP tools for retrieval and memory writes * Full session capture through `nmem t save --from gemini-cli`, including before context compression and at session end * Direct `nmem` composition whenever the built-in commands are too narrow * Clean local and remote auth through `nmem` ## Commands [#commands] * `/nowledge:read-working-memory` * `/nowledge:search-memory ` * `/nowledge:distill-memory` * `/nowledge:save-thread` * `/nowledge:save-handoff` * `/nowledge:status` ## Thread Save And Handoff [#thread-save-and-handoff] Gemini supports two distinct save paths, and they should stay distinct: * `save-thread` imports the real Gemini session through `nmem t save --from gemini-cli` * `save-handoff` stores a concise resumable summary for restart and continuation The extension also runs the same thread import before Gemini compresses context and when the session ends. That keeps the full recorded conversation searchable without turning handoff summaries into fake transcripts. ## Manual Install [#manual-install] If you prefer installing from GitHub or a local checkout, use this path: ```bash git clone https://github.com/nowledge-co/nowledge-mem-gemini-cli.git cd nowledge-mem-gemini-cli gemini extensions link . ``` Gemini's official docs also support `gemini extensions install ` for GitHub or local sources, and `gemini extensions link ` for local development. For most users, the listed gallery install path above is the simplest choice. ## Related [#related] * [Connectors overview](/docs/integrations) * [Claude Code](/docs/integrations/claude-code) * [Codex](/docs/integrations/codex-cli) * [Remote access](/docs/remote-access) # Grok Build (/docs/integrations/grok) This page is for **Grok Build**, xAI's coding agent with plugins, hooks, skills, and local `~/.grok/` sessions. It is not the setup path for the consumer Grok chat experience on grok.com or x.com. For web Grok conversations, use the [browser extension guide](/docs/integrations/browser-extension) or the [Grok Web connector](/integrations/grok-web). Nowledge Mem connects to Grok Build through its plugin system. Install it once, restart Grok Build, and new coding-agent sessions can start with your Mem context and save real transcript history back into Mem. ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Grok Build. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Paste that into Grok Build if you want the agent to do the setup. If you prefer the terminal, use the steps below. ## What success looks like [#what-success-looks-like] After setup, start a fresh Grok Build session and ask "What was I working on?" It should receive Context Bundle or Working Memory. After one normal turn, this should find the captured thread: ```bash nmem t search "a phrase from the Grok Build turn" --source grok ``` ## Requirements [#requirements] * Grok Build installed and signed in * `nmem` available on the same machine that runs Grok Build * Nowledge Mem desktop app running locally, or `nmem` configured for your remote Mem server If Grok Build runs on the same Mac as the Mem desktop app, install the CLI from **Settings → Preferences → Developer Tools → Install CLI**. If Grok Build runs on another machine, install the standalone CLI there: ```bash python3 -m pip install --user nmem-cli # or pipx install nmem-cli ``` ## Install [#install] ```bash grok plugin install nowledge-co/community#nowledge-mem-claude-code-plugin --trust ``` Restart Grok Build after installation. The package is shared with our Claude Code connector because Grok Build can load Claude-compatible plugin assets. The hook detects Grok Build at runtime, so its sessions are saved as `source=grok`, not as Claude Code. ## Update [#update] ```bash grok plugin update nowledge-mem ``` Restart Grok Build after updating. ## Import older Grok Build sessions [#import-older-grok-build-sessions] Automatic capture starts after the plugin is installed. To backfill older Grok Build sessions, preview first: ```bash nmem t sync --from grok --all-projects --limit 20 ``` Then import: ```bash nmem t sync --from grok --all-projects --apply ``` Use `-p /path/to/project` instead of `--all-projects` when you only want one project. The command reads Grok Build's local `~/.grok/sessions` files on this machine and writes to the Mem server configured in `nmem`. ## Remote Mem [#remote-mem] For remote Mem, configure this machine once: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` The Grok Build hook still reads local session files on the machine where Grok Build runs, then uploads normalized messages through `nmem`. The remote server does not need filesystem access to `~/.grok`. ## Customize behavior [#customize-behavior] Do not edit the installed plugin files under `~/.grok/installed-plugins`. Put behavior changes in Grok Build project rules or the project instruction files it already reads. For multi-agent launchers, set `NMEM_AGENT_ID=` before launching the Grok Build worker when that worker represents a stable long-term AI identity. Add `NMEM_SPACE` only when the whole run should be forced into one Mem space. ## What the connector includes [#what-the-connector-includes] * Session-start Context Bundle / Working Memory injection * Guided memory search and distillation skills * `/save`, `/search`, `/sum`, and `/status` commands * Stop and PreCompact hooks that call `nmem t save --from grok` * Historical import through `nmem t sync --from grok` ## Troubleshooting [#troubleshooting] **`nmem` is not found** Install the CLI on the same machine that runs Grok Build, then run `nmem status`. **The Grok Build thread is not appearing** Restart Grok Build after install or update. Then run: ```bash nmem --json t save --from grok -p . ``` If that works, the connection is healthy and the hook will keep new sessions current. **You see Claude Code wording in the package** That is expected in a few shared package filenames. The runtime behavior is Grok Build-aware: hooks pass `--source-app grok` and `nmem t save --from grok`. ## Related [#related] * [Claude Code](/docs/integrations/claude-code) * [Codex](/docs/integrations/codex-cli) * [Cursor](/docs/integrations/cursor) * [Connectors overview](/docs/integrations) # Hermes Agent × Nowledge Mem (/docs/integrations/hermes) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Hermes Agent. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ```bash title="One-command setup (plugin)" bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) ``` ```powershell title="Windows PowerShell" irm https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.ps1 | iex ``` Hermes v0.7.0+ supports memory providers. Install the plugin once for built-in behavior: Context Bundle loads at session start when available, relevant memories surface before each turn, and Hermes captures cleaned transcript turns into Mem threads while the conversation runs. No SOUL.md guidance needed. Hermes keeps new memory providers outside the core `hermes-agent` repository. The installer on this page is the supported Nowledge Mem path: it places the provider in `~/.hermes/plugins/nowledge-mem/`, where Hermes loads it through the same memory-provider lifecycle. Your cross-tool knowledge, accessible in every Hermes session. Decisions from Claude Code, preferences from Cursor, insights from ChatGPT: one knowledge graph, always available. Install the plugin, restart Hermes, and start a new session. Send one short message that includes a unique phrase, then cleanly exit, run `/new`, or run `/reset`. `nmem t search "that phrase" --source hermes` should find the captured Hermes thread. If your Mem library already has memories, also ask "what decisions have I made recently?" and Hermes should search your knowledge graph without you pointing it at a tool. The plugin captures new Hermes sessions as they run. To import conversations that already exist in `~/.hermes/state.db`, run a historical sync from the machine where Hermes is installed: ```bash nmem t sync --from hermes # preview only nmem t sync --from hermes --apply # import into Mem ``` This is the right path for remote Mem too: your laptop reads the local Hermes database, then uploads normalized threads to the Mem server configured in `nmem status`. ## Before You Start [#before-you-start] * **Nowledge Mem** running locally ([installation](/docs/installation)) or a reachable remote server * **Hermes Agent** v0.7.0+ installed (v0.6.x works with MCP mode) * **`nmem` CLI** available in `PATH`. If the desktop app is on this machine, use **Settings → Preferences → Developer Tools → Install CLI**. On a remote-only machine, install it with `pip install nmem-cli`. ```bash nmem status # Nowledge Mem is running hermes --version # Hermes is available ``` ## Setup [#setup]
### Plugin install (recommended) [#plugin-install-recommended-step] ```bash bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) ``` Installs the native memory provider plugin. Restart Hermes after running. On Windows, use the native PowerShell installer; Git Bash and WSL are not required: ```powershell irm https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.ps1 | iex ``` Or install manually: 1. Copy plugin files to `~/.hermes/plugins/nowledge-mem/`: ```bash mkdir -p ~/.hermes/plugins/nowledge-mem cd ~/.hermes/plugins/nowledge-mem for f in plugin.yaml __init__.py provider.py client.py; do curl -sLO "https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/$f" done ``` 2. Set the provider in `~/.hermes/config.yaml`: ```yaml memory: provider: "nowledge-mem" ``` 3. Restart Hermes.
### MCP mode (Hermes \< v0.7.0) [#mcp-mode-hermes--v070-step] If you are on an older version of Hermes or prefer a standard MCP connection: ```bash bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) --mcp ``` ```powershell title="Windows PowerShell" & ([scriptblock]::Create((irm https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.ps1))) -Mcp ``` This adds the MCP server to `config.yaml` and installs behavioral guidance in `~/.hermes/SOUL.md`. Tools appear with the `mcp_nowledge_mem_` prefix. Without behavioral guidance, MCP mode gives Hermes tools but no instruction on when to use them proactively. If Hermes recalls but never saves, this is usually why. The plugin mode does not need guidance because behavior is built into the provider lifecycle.
### Verify [#verify-step] First verify thread capture with an empty-library-safe check. In Hermes, send: ``` Please reply with: hermes nmem smoke test ``` Then exit cleanly, run `/new`, or run `/reset` so Hermes performs its final thread flush. In a terminal, check: ```bash nmem t search "hermes nmem smoke test" --source hermes ``` You should see the Hermes thread. After that, if your Mem library already has memories, ask Hermes something that depends on past work: ```text What decisions have I made recently? ``` In plugin mode, Hermes should call `nmem_search`. In MCP mode, it should call `mcp_nowledge_mem_memory_search`. Then ask Hermes to save a conclusion or watch whether it chooses the native `nmem_save` tool when the conversation reaches a durable decision.
## What Happens Automatically [#what-happens-automatically] The plugin hooks into Hermes' memory provider lifecycle. No manual tool calls needed for these: * **Context Bundle** loads at the start of every session when available, with Working Memory fallback on older CLIs * **Relevant memories** surface before each turn (proactive recall) * **User profile facts** from Hermes sync to your cross-tool knowledge graph * **Session transcripts** are captured into Mem threads as turns complete, with a final delta flush when Hermes exits, starts a new session, or resets cleanly * **Compression recovery hint** is provided on Hermes builds that consume provider compression output In MCP mode, these behaviors depend on the SOUL.md guidance and are not guaranteed. ## Hermes Memory vs Nowledge Mem [#hermes-memory-vs-nowledge-mem] Hermes has a built-in memory system for facts specific to Hermes sessions. Nowledge Mem is complementary: it stores knowledge that spans tools. Use both: * **Hermes memory**: Hermes-specific preferences, environment details, tool quirks * **Nowledge Mem**: Decisions, procedures, and learnings that future sessions in any tool should know about The plugin automatically mirrors user profile facts from Hermes to Nowledge Mem, so cross-tool knowledge stays in sync. ## What You Can Do [#what-you-can-do] **Find knowledge from other tools.** Ask "what did we decide about the database?" and Hermes searches across decisions you made in Claude Code, insights from ChatGPT, notes from Cursor. **Save knowledge for everywhere.** When you reach a conclusion in Hermes, it saves to your knowledge graph so your next Claude Code session, Cursor project, or ChatGPT conversation can find it too. **Search past conversations.** Find past conversations by keyword across every tool. Retrieve the full exchange with pagination. **Keep Hermes sessions searchable.** The provider captures cleaned `user` / `assistant` turns into a Mem thread while the conversation runs. A clean exit, `/new`, or `/reset` performs a final delta flush. The first write for each Hermes `session_id` imports the thread; later writes for the same session append only the new turns. **Backfill older Hermes sessions.** Historical Hermes conversations live in `~/.hermes/state.db`. Run `nmem t sync --from hermes` to preview them, then add `--apply` to import. The command is safe to rerun: it reuses Hermes `session_id` as the Mem thread ID and appends with message deduplication. In MCP mode, you also get graph exploration tools to trace how decisions evolved and discover related memories. ## Tools [#tools] Plugin mode uses clean `nmem_` names. MCP mode uses the `mcp_nowledge_mem_` prefix. | Plugin | MCP mode tool name | Purpose | | ---------------------- | ---------------------------------------- | ----------------------------------------------- | | `nmem_search` | `mcp_nowledge_mem_memory_search` | Search memories | | `nmem_save` | `mcp_nowledge_mem_memory_add` | Save or upsert a decision, insight, or learning | | `nmem_update` | `mcp_nowledge_mem_memory_update` | Refine an existing memory | | `nmem_delete` | `mcp_nowledge_mem_memory_delete` | Remove one or more memories | | `nmem_thread_search` | `mcp_nowledge_mem_thread_search` | Search past conversations | | `nmem_thread_messages` | `mcp_nowledge_mem_thread_fetch_messages` | Fetch messages from a thread | MCP mode also includes `list_memory_labels`, `memory_neighbors`, and `memory_evolves_chain`. These will be added to the plugin when the `nmem` CLI supports them. ## Configuration [#configuration] No configuration needed for local use. The plugin uses the shared `nmem` client config for server URL and API key. Normal memory operations go through `nmem`; long transcript payloads are sent directly to the Mem API. If the Nowledge Mem desktop app is on the same machine, `nmem` is already bundled. For remote-only setups without the desktop app: `pip install nmem-cli`. ### Remote access [#remote-access] Configure the local `nmem` client to point at your remote server: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` This updates the client-side connection settings for the machine running Hermes. It is separate from server-side Access Anywhere or LAN bind configuration on the Mem host. The only plugin-specific setting is request timeout, in `~/.hermes/nowledge-mem.json`: ```json { "timeout": 60 } ``` ### Spaces [#spaces] Hermes supports three clean mapping levels: * `space`: one fixed lane for this Hermes profile * `space_by_identity`: a small explicit map from Hermes identities to named spaces * `space_template`: one derived lane per Hermes identity, for example `agent-{identity}` If none of those are set, Hermes can still inherit `NMEM_SPACE`. For MCP mode, update the URL directly in `config.yaml`: ```yaml title="~/.hermes/config.yaml" mcp_servers: nowledge-mem: url: "https://your-server/mcp" headers: Authorization: "Bearer your-key" timeout: 120 ``` See [Access Mem Anywhere](/docs/remote-access). ## Update [#update] Use the same mode you installed with: * Plugin mode, the default for Hermes v0.7.0+: re-run the setup command without flags, then restart Hermes. * MCP mode, for Hermes v0.6.x or a deliberate standard MCP setup: re-run the setup command with `--mcp`, then restart Hermes. ```bash # Plugin mode bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) # MCP mode bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) --mcp ``` The MCP tools themselves are served by Nowledge Mem and update with the desktop app. The Hermes plugin files update through the setup script. After updating, the script prints the version and endpoint from the files Hermes will load: ```text Installed version: 0.5.18 Thread import endpoint: /threads/import ``` If those lines still show an old version or a different endpoint, Hermes is reading a different `HERMES_HOME`. Set `HERMES_HOME` to the profile you use to launch Hermes, run the setup command again, then restart Hermes. ## Disable or Roll Back [#disable-or-roll-back] Quit Hermes before changing files. * Plugin mode: set `memory.provider` in `~/.hermes/config.yaml` back to your previous provider, or remove that line if you did not use Hermes memory before. Then remove `~/.hermes/plugins/nowledge-mem`. On older Hermes builds that needed a compatibility copy, also remove `~/.hermes/hermes-agent/plugins/memory/nowledge-mem`. * MCP mode: remove the `mcp_servers.nowledge-mem` block from `~/.hermes/config.yaml`. If you no longer want the behavior guidance, remove the section headed `# Nowledge Mem for Hermes` from `~/.hermes/SOUL.md`. * Restart Hermes and run `hermes --version` plus `nmem status` to confirm the host and Mem client are still healthy. ## Customize Safely [#customize-safely] Use Hermes' own guidance files, not the installed plugin directory: * `~/.hermes/SOUL.md` for personal default behavior across sessions * `HERMES.md` at the project root for repo-specific rules Do not patch the installed Nowledge Mem plugin files under `~/.hermes/plugins/`. For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## Troubleshooting [#troubleshooting] **Cannot connect to Nowledge Mem.** Confirm the server is running with `nmem status`. Check that the URL matches the address shown by `nmem status`. **Hermes recalls but never saves durable memories (MCP mode).** Behavioral guidance is missing. Run the setup command, then restart Hermes. The guidance must be in `~/.hermes/SOUL.md` (always loaded) or a `HERMES.md` at the git root. In plugin mode, recall and transcript capture are built into the provider lifecycle and do not depend on guidance. **Hermes threads are not appearing in Mem.** The provider captures completed turns and also flushes at real session boundaries. Test with a normal completed turn, then try a clean exit, `/new`, or `/reset`. If Hermes is killed abruptly during a turn, that unfinished turn may never reach the provider. **An agent says `client.py` differs from community/main.** That usually means Hermes is running a stale local plugin copy. Re-run the plugin setup command, confirm it prints `Thread import endpoint: /threads/import`, and restart Hermes. Use `SOUL.md` or `HERMES.md` for custom behavior instead of editing files under `~/.hermes/plugins/nowledge-mem/`. **Older Hermes sessions are missing.** This is expected until you run a historical import. The desktop watcher does not read Hermes' SQLite database. Run `nmem t sync --from hermes` to preview older sessions from `~/.hermes/state.db`, then run `nmem t sync --from hermes --apply` when the preview looks right. **Tools not appearing (plugin).** Confirm `memory.provider: "nowledge-mem"` in `config.yaml` and plugin files exist in `~/.hermes/plugins/nowledge-mem/`. Restart Hermes. **Tools not appearing (MCP).** Confirm the `mcp_servers.nowledge-mem` block in `config.yaml`. Restart Hermes. Verify the YAML is valid (correct indentation, no tabs). **Slow responses.** Default timeout is 30 seconds. Increase in `nowledge-mem.json` (plugin) or `config.yaml` (MCP). If the issue persists, check `nmem status` for server health. ## Related [#related] * [Connectors overview](/docs/integrations) * [Claude Code](/docs/integrations/claude-code) · [OpenCode](/docs/integrations/opencode) · [Pi](/docs/integrations/pi) · [OpenClaw](/docs/integrations/openclaw) · [Alma](/docs/integrations/alma) · [Bub](/docs/integrations/bub) * Source: [nowledge-mem-hermes](https://github.com/nowledge-co/community) # Connectors (/docs/integrations) > API reference page. OpenAPI operation details could not be extracted from this page. # Kimi Code × Nowledge Mem (/docs/integrations/kimi-code) Paste this into Kimi Code: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Kimi Code. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Kimi Code can use Nowledge Mem through a Kimi-native package. It loads Mem guidance at session start, connects to Mem through MCP, and can sync Kimi Code conversations into Mem Threads with a local lifecycle hook. Recent Kimi Code builds load those hooks directly from `kimi.plugin.json`, so the connector now feels native: install the package, enable it, reload, and Kimi Code can start reading memory and saving sessions. Older Kimi Code sessions still use the same safe backfill command: preview first, then import with `nmem t sync --from kimi-code --apply`. This guide is for **Kimi Code**, the terminal and IDE coding agent. Kimi web chat is covered by the [Browser Extension](/docs/integrations/browser-extension). Kimi Work is a separate desktop product with its own embedded runtime; use the [Kimi Work guide](/docs/integrations/kimi-work) for that setup. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * Kimi Code is installed * `nmem` 0.9.19 or newer works on the same machine as Kimi Code. Kimi Code thread sync depends on the CLI support for `--from kimi-code`. ```bash nmem status nmem --version ``` If `nmem` exists but rejects `t sync --from kimi-code`, `config mcp show --host kimi-code`, or another Kimi-specific command, update the CLI before debugging MCP or session sync: * Desktop-bundled CLI: open Mem and run **Settings → Preferences → Developer Tools → Install bundled CLI** again. * PyPI CLI: `python3 -m pip install --user --upgrade nmem-cli` * pipx CLI: `pipx upgrade nmem-cli` If Kimi Code runs on a different machine from the desktop app, install the standalone CLI there first: ```bash python3 -m pip install --user nmem-cli nmem --version nmem config client set url https://your-server nmem config client set api-key your-key ``` ## Install The Package [#install-the-package] Install the package in Kimi Code: ```text /plugins install https://github.com/nowledge-co/community /plugins enable nowledge-mem /reload ``` The community repo has a root `kimi.plugin.json` shim for Kimi Code, so the GitHub install path loads the Kimi package directly. Kimi downloads the repository zip for this install; it does not clone submodules. The package includes a session-start skill and a local MCP server for the desktop app at `http://127.0.0.1:14242/mcp/`. It also includes native plugin hooks for `Stop`, `SessionEnd`, `PreCompact`, `SubagentStop`, and `Interrupt`, plus quick commands: ```text /nowledge-mem:status /nowledge-mem:sync-now /nowledge-mem:import-history ``` For remote Mem or authenticated localhost, generate a user-level Kimi MCP block: ```bash nmem config mcp show --host kimi-code ``` Paste the generated `nowledge-mem` server into `$KIMI_CODE_HOME/mcp.json` or `~/.kimi-code/mcp.json`. If your installed `nmem` does not recognize `--host kimi-code` yet, update the same CLI source first. Until then, use the generic streamable HTTP MCP block from the [Connectors overview](/docs/integrations#direct-mcp) and set the URL/API key for your Mem server manually. ## Thread Sync [#thread-sync] Modern Kimi Code reads the Nowledge Mem hook declarations from the plugin manifest. After `/reload`, the connector syncs sessions automatically when a turn stops, a session exits, context is compacted, a subagent finishes, or a turn is interrupted. If you are on an older Kimi Code build that does not load plugin manifest hooks, run the fallback installer once. It writes the same hook rules into your Kimi Code config and leaves the rest of the file untouched: ```bash python3 ~/.cache/nowledge-community/nowledge-mem-kimi-code-plugin/scripts/install_hooks.py ``` ## Verify [#verify] Restart Kimi Code and ask: ```text Is Nowledge Mem connected? Read my current context. ``` Success means Kimi Code can call the Nowledge Mem MCP tools and return Context Bundle, Working Memory, or an empty-but-successful memory result. Then finish a short Kimi Code exchange and check: ```bash nmem t list --source kimi-code -n 5 ``` You should see the recent Kimi Code thread after the hook has run. If you delegated work to a Kimi subagent, that subagent's wire log is imported into the same thread with subagent provenance metadata. ## Import Older Sessions [#import-older-sessions] Kimi Code stores local sessions under `~/.kimi-code/sessions`. Import them with: ```bash nmem t sync --from kimi-code --limit 20 nmem t sync --from kimi-code --apply ``` This works for local Mem and remote Mem because the `nmem` CLI reads the local Kimi Code transcript files and uploads normalized thread messages to your configured Mem server. It is safe to rerun; Mem uses stable thread and message IDs to deduplicate repeated imports. ## Related [#related] * [Connectors overview](/docs/integrations) * [OpenCode](/docs/integrations/opencode) · [Pi](/docs/integrations/pi) · [ZCode](/docs/integrations/zcode) * Kimi Code source: [MoonshotAI/kimi-code](https://github.com/MoonshotAI/kimi-code) # Kimi Work × Nowledge Mem (/docs/integrations/kimi-work) Paste this into Kimi Work: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Kimi Work. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Kimi Work can use Nowledge Mem through the Kimi Work connector. It installs a session-start skill and local MCP declaration into Kimi Work's embedded Kimi Code runtime, which is separate from any Kimi Code CLI you installed yourself. Kimi Work does not expose lifecycle hooks today. That means Mem can give Kimi Work context and memory tools, but conversation import is explicit: preview and run `nmem t sync --from kimi-work --apply` when you want Kimi Work history in Mem Threads. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * Kimi Work Desktop is installed * `nmem` 0.9.23 or newer works on the same machine as Kimi Work ```bash nmem status nmem --version ``` If Kimi Work runs on a different machine from the desktop app, install the standalone CLI there first: ```bash python3 -m pip install --user nmem-cli nmem --version nmem config client set url https://your-server nmem config client set api-key your-key ``` ## Install The Connector [#install-the-connector] Get the community checkout if you do not already have it: ```bash git clone --depth 1 https://github.com/nowledge-co/community.git ~/.cache/nowledge-community ``` Install into Kimi Work's embedded runtime: ```bash python3 ~/.cache/nowledge-community/nowledge-mem-kimi-work-connector/scripts/install_kimi_work_plugin.py ``` The installer uses `KIMI_WORK_HOME` when set. Otherwise it uses the default macOS Kimi Work runtime path: ```text ~/Library/Application Support/kimi-desktop/daimon-share/daimon/runtime/kimi-code/home ``` Restart Kimi Work after installing. ## Remote Mem Or Authenticated Localhost [#remote-mem-or-authenticated-localhost] The connector bundles a local MCP server for the desktop app at `http://127.0.0.1:14242/mcp/`. For remote Mem or authenticated localhost, generate a Kimi Work MCP block: ```bash nmem config mcp show --host kimi-work ``` Paste the generated `nowledge-mem` server into `$KIMI_WORK_HOME/mcp.json`, or into the default runtime path shown above plus `/mcp.json`. Restart Kimi Work after changing MCP config. ## Verify [#verify] Start a new Kimi Work session and ask: ```text Is Nowledge Mem connected? Read my current context. ``` Success means Kimi Work can call the Nowledge Mem MCP tools and return Context Bundle, Working Memory, or an empty-but-successful memory result. ## Import Kimi Work Sessions [#import-kimi-work-sessions] Preview first: ```bash nmem t sync --from kimi-work --limit 20 ``` Import when the preview looks right: ```bash nmem t sync --from kimi-work --apply nmem t list --source kimi-work -n 5 ``` This works for local Mem and remote Mem because the `nmem` CLI reads Kimi Work's local transcript files and uploads normalized thread messages to your configured Mem server. It is safe to rerun; Mem uses stable thread and message IDs to deduplicate repeated imports. If Kimi Work stores sessions somewhere else, pass the runtime sessions folder explicitly: ```bash nmem t sync --from kimi-work --session-dir "/path/to/kimi-work/home/sessions" --apply ``` ## Kimi Work vs Kimi Code [#kimi-work-vs-kimi-code] Kimi Code CLI and Kimi Work share the same underlying Kimi Code session format, but they do not share the same home directory. * Use [Kimi Code](/docs/integrations/kimi-code) when you run the terminal or IDE coding agent. It supports a hook installer for automatic local thread sync. * Use this Kimi Work guide for Kimi Work Desktop. It has MCP and startup guidance, but no lifecycle hook, so thread import is explicit. ## Related [#related] * [Connectors overview](/docs/integrations) * [Import existing conversations](/docs/import-existing-conversations) * [Kimi Code](/docs/integrations/kimi-code) # Lody (/docs/integrations/lody) Lody runs local sessions through an Agent Config. That config chooses an AI tool, such as Claude Code or Codex, and can carry environment variables into it. This is not the same as an always-on teammate identity. Treat Lody as a session and runtime launcher first. Add a Mem AI Identity only when you intentionally use one Lody Agent Config as a stable role, such as "reviewer" or "onboarding assistant". Use this rule: * First connect the AI tool Lody launches, such as Claude Code or Codex. * Add `NMEM_AGENT_ID` only when this Lody Agent Config represents a stable role, such as Cindy. * Leave `NMEM_AGENT_ID` unset for generic runtime presets. ## Setup [#setup] First connect the AI tool Lody launches. For example, install the [Claude Code](/docs/integrations/claude-code) or [Codex](/docs/integrations/codex-cli) connector. If this Agent Config is meant to represent a durable role, create the Mem AI Identity: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "Help with onboarding. Explain one step at a time." ``` This creates the Mem AI Identity named Cindy. Its command and environment ID is `cindy`. It does not make every Codex session use Cindy; the identity is used only where `NMEM_AGENT_ID=cindy` or `agent_id="cindy"` is passed. Add this environment variable to that Lody Agent Config: ```bash NMEM_AGENT_ID=cindy ``` If the Lody config is only a generic Codex or Claude runtime preset, leave `NMEM_AGENT_ID` unset. That avoids pretending every Lody session is the same long-term person. If you create another Lody config for the same durable role, keep the same `NMEM_AGENT_ID`. If the config switches from Codex to Claude Code, update the runtime connector and `--source-app`, not the identity. ## Space [#space] Do not set `NMEM_SPACE` by default. Use the identity's default space unless this entire Lody config should always read and write one specific Mem space: ```bash NMEM_SPACE=onboarding ``` ## Advanced Host Ids [#advanced-host-ids] Most users should not set `NMEM_HOST_AGENT_ID`. Use it only when you need to map a Lody-internal stable id, such as `lody:`, onto a Mem AI Identity. In normal setup, either leave identity unset or use `NMEM_AGENT_ID=cindy` for a role-specific config. ## Forking [#forking] If the same person should behave differently, create a new Mem AI Identity instead of overloading one identity: ```bash nmem agents upsert cindy-reviewer \ --name "Cindy Reviewer" \ --instructions "Review code. Leave concise comments. Do not edit files unless asked." ``` Then point that Lody config at: ```bash NMEM_AGENT_ID=cindy-reviewer ``` ## Next [#next] * [Customize Connector Behavior](/docs/integrations/customize-behavior) * [Raft](/docs/integrations/raft) * [Multica](/docs/integrations/multica) # MiMo Code × Nowledge Mem (/docs/integrations/mimo-code) Paste this into MiMo Code: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for MiMo Code. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` MiMo Code is OpenCode-derived, but its package names, config roots, and lifecycle APIs are not identical. Use the MCP path for live memory tools, and use `nmem t sync --from mimo-code` when you want MiMo Code's local transcripts imported into Mem. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * MiMo Code is installed * `nmem` works on the same machine as MiMo Code ```bash nmem status ``` ## Setup [#setup] Generate the MCP config: ```bash nmem config mcp show --host mimo-code ``` Add the generated MCP server to MiMo Code's MCP configuration or project config. Then add Nowledge Mem guidance to your project instructions so the agent knows when to read context, search memory, and save durable decisions. ## Verify [#verify] Restart MiMo Code and ask: ```text Is Nowledge Mem connected? Search my memory for this project. ``` Success means MiMo Code can call the Nowledge Mem MCP tools and return results or a clean empty result. ## Session Capture [#session-capture] MiMo Code stores local conversation data in its `mimocode.db` store. Import it with: ```bash nmem t sync --from mimo-code --limit 20 nmem t sync --from mimo-code --apply ``` This works for local Mem and remote Mem because `nmem` reads the local MiMo Code database and uploads normalized thread messages to your configured Mem server. Do not install the OpenCode plugin package into MiMo Code unless you are intentionally testing compatibility. The two hosts are close, but a safe live connector must respect MiMo Code's own plugin and session contracts. Until a native package ships, use this import path plus handoff summaries for conversations you want to preserve immediately. ## Related [#related] * [OpenCode](/docs/integrations/opencode) * [Kimi Code](/docs/integrations/kimi-code) · [ZCode](/docs/integrations/zcode) · [OMP](/docs/integrations/omp) * MiMo Code source: [XiaomiMiMo/MiMo-Code](https://github.com/XiaomiMiMo/MiMo-Code) # Multica (/docs/integrations/multica) Multica runs named agents by starting local AI tools such as Claude Code, Codex, Pi, OpenCode, or OpenClaw. Connect Nowledge Mem at that launched-tool layer, then give each durable Multica agent one Mem AI Identity. This means: * Sessions inside the launched AI tool can sync through that tool's Nowledge Mem connector and hooks. * MCP access must be configured for the Multica agent, not only for the outer terminal you are using. * The Multica agent keeps the same Mem AI Identity when you move it to another workspace or switch the AI tool it uses. * Multica's own workspace history is separate unless Multica exposes an export, API, or hook for it. ## Setup [#setup] First connect the AI tool Multica launches. For example, install the [Codex](/docs/integrations/codex-cli), [Claude Code](/docs/integrations/claude-code), [Pi](/docs/integrations/pi), or [OpenClaw](/docs/integrations/openclaw) connector on the machine running the Multica daemon. If the Multica agent runs Claude Code, also open that Multica agent's **MCP** settings and save the Nowledge Mem MCP config there. Claude Code does not automatically inherit MCP servers from your outer shell or another Claude session when Multica starts it. Multica forwards the saved agent MCP config to Claude Code with `--mcp-config`. Use the same MCP config you would give Claude Code directly: ```json { "mcpServers": { "nowledge-mem": { "url": "http://127.0.0.1:14242/mcp/", "type": "streamableHttp", "headers": { "APP": "Claude Code", "Authorization": "Bearer ", "X-NMEM-API-Key": "" } } } } ``` You can generate the exact config for your machine with: ```bash nmem config mcp show --host claude-code --json ``` For remote Mem, replace the URL with your Access Anywhere MCP endpoint and keep the token headers from your Mem config. Do not put `--mcp-config` in Multica custom args; current Multica owns that flag and derives it from the agent's MCP config. Create the Mem AI Identity: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "Help with onboarding. Explain one step at a time." ``` This creates the Mem AI Identity named Cindy. Its command and environment ID is `cindy`. It does not make every Codex session use Cindy; the identity is used only where `NMEM_AGENT_ID=cindy` or `agent_id="cindy"` is passed. Then add this custom environment variable to the Multica agent: ```bash NMEM_AGENT_ID=cindy ``` Keep Cindy's ID if she moves to another Multica workspace, squad, or AI tool. Change the connector only when the underlying AI tool changes. ## What Syncs [#what-syncs] New sessions sync only when the launched AI tool has a working Nowledge Mem connector or hook. For example, Claude Code and Codex use their own Nowledge Mem connectors; Pi uses the Pi package; OMP uses the OMP plugin. Multica itself is the orchestrator. Its issue comments, workspace history, and task timeline are separate data. Mem can import those directly only if Multica later exposes message-level export, API, or hook data for those surfaces. ## Space [#space] Leave `NMEM_SPACE` unset unless every task assigned to this Multica agent should use one Mem space: ```bash NMEM_SPACE=onboarding ``` If the agent works across multiple repos or projects, let the Mem AI Identity's default space handle the usual case and switch space explicitly only when needed. ## Security [#security] Do not put broad secrets in Multica agent environment variables. `NMEM_AGENT_ID` is safe because it is only an identity selector. Mem API keys, provider keys, and production tokens should stay limited in scope and managed through the runtime or Mem client config. ## Next [#next] * [Customize Connector Behavior](/docs/integrations/customize-behavior) * [Lody](/docs/integrations/lody) * [Cumora](/docs/integrations/cumora) # OMP × Nowledge Mem (/docs/integrations/omp) Paste this into OMP: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for OMP. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` Install the OMP plugin when you want OMP to start with the right Mem context and save new coding conversations without a manual import step. After setup, OMP can read Context Bundle or Working Memory at startup, use the bundled memory skills during a task, and sync completed conversation turns into Mem threads with `source_app=omp`. Do not install `nowledge-mem-pi` for OMP. OMP is Pi-derived, but it has its own plugin command, config root, and source tag. The dedicated OMP plugin keeps OMP threads separate from Pi threads. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * OMP is installed * `nmem` works on the same machine as OMP ```bash nmem status ``` ## Setup [#setup] ```bash omp plugin install nowledge-mem-omp ``` Restart OMP after install or update so the extension lifecycle loads. For most local setups, that is the only OMP-specific install step. If you also want direct MCP tool calls, or need to point OMP at a custom remote MCP endpoint, generate the optional OMP MCP config: ```bash nmem config mcp show --host omp ``` Add the generated server to OMP's MCP config. OMP's documented MCP locations include project `.omp/mcp.json` and user `~/.omp/agent/mcp.json`. ## Verify [#verify] Restart OMP and ask: ```text Read my Nowledge Mem context and tell me whether the connection is working. ``` Success means OMP can see the injected Context Bundle or Working Memory. After you complete a normal OMP turn, the conversation should also appear in Mem as an OMP thread. ## Session Capture [#session-capture] New OMP conversations are captured automatically by the plugin after completed agent turns, before compaction, before session switches, and at shutdown. They are saved with `source_app=omp`. Only use the sync command when you want to backfill older OMP sessions that existed before the plugin was installed. OMP stores those sessions under `~/.omp/agent/sessions`: ```bash nmem t sync --from omp --limit 20 nmem t sync --from omp --apply ``` This works for local Mem and remote Mem because `nmem` reads the local OMP JSONL files on the OMP machine and uploads normalized thread messages to your configured Mem server. ## Related [#related] * [Pi](/docs/integrations/pi) * [OpenCode](/docs/integrations/opencode) · [Kimi Code](/docs/integrations/kimi-code) · [ZCode](/docs/integrations/zcode) * OMP docs: [omp.sh/docs](https://omp.sh/docs) # OpenClaw × Nowledge Mem (/docs/integrations/openclaw) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for OpenClaw. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ```bash title="One-liner install" openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem ``` Configure the plugin and the conversations you have with OpenClaw land in Mem as searchable threads. Background cron-style runs do not. Mem can still distill what matters into linked memories, and what you saved in other tools, documents, or imports stays available to the agent. Local-first by default; add `apiUrl` and an optional `apiKey` if you use a shared server. Behind that, Nowledge Mem is doing more than storing notes. It links related knowledge into a graph, tracks how ideas evolve, and can keep processing in the background so OpenClaw can benefit from daily briefings, contradiction checks, and crystals built from multiple sources. The fastest proof is simple: remember one fact, recall it in a fresh session, then confirm the session itself shows up as a searchable thread. The package is now published on ClawHub. Use the explicit `clawhub:` install form when you want to make the source clear. Bare package names still work because OpenClaw resolves ClawHub before npm. ## Before You Start [#before-you-start] You need: * **Nowledge Mem** running locally ([installation](/docs/installation)) * **OpenClaw 2026.5.3 or later** ([OpenClaw getting started](https://docs.openclaw.ai/start/openclaw)). Older 2026.4.x builds can reject current ClawHub packages with an archive integrity mismatch before the plugin is installed. * **`nmem` CLI** on your PATH. In Nowledge Mem, go to **Settings → Preferences → Developer Tools → Install CLI**. Or install standalone: `pip install nmem-cli` ```bash nmem status # should show Nowledge Mem is running openclaw --version ``` ## Setup [#setup]
### Install the plugin [#install-the-plugin-step] ```bash openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem ``` The installer enables the plugin and switches OpenClaw's `memory` slot to `openclaw-nowledge-mem` automatically. On current OpenClaw builds, that same install flow may also set `plugins.slots.contextEngine` to `openclaw-nowledge-mem`. Plugin `0.8.18+` accepts that automatically as a compatibility alias. Current OpenClaw releases require an explicit grant before a non-bundled plugin can read the `agent_end` conversation used as the thread-sync safety net: ```bash openclaw config set plugins.entries.openclaw-nowledge-mem.hooks.allowConversationAccess true --strict-json ``` Next, run `openclaw config get tools`. If you use a restrictive profile such as `coding`, preserve any existing `tools.alsoAllow` entries and add `openclaw-nowledge-mem`. If `tools.allow` already exists, add the plugin id to that list instead. Do not replace an existing list or enumerate individual `nowledge_mem_*` tools; the plugin id grants the complete manifest-declared contract. If an earlier ClawHub install was blocked with `dangerous code patterns detected`, update to `0.8.17+`. That release removes test-only files from the published plugin artifact, so OpenClaw only scans real runtime code during install. If you prefer the default resolver path, this also works: ```bash openclaw plugins install @nowledge/openclaw-nowledge-mem ``` To update to the latest version: ```bash openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem --force ``` This refreshes the plugin from ClawHub and replaces the installed copy. Use it instead of `openclaw plugins update openclaw-nowledge-mem` if your local OpenClaw install was previously pinned to a specific plugin version. If OpenClaw reports `archive integrity mismatch` during install, update OpenClaw first, then run the same `--force` install command again.
## Customize Safely [#customize-safely] OpenClaw does not use a separate project instruction file for this plugin. * Use the plugin settings and OpenClaw config for durable behavior changes * Use your agent or prompt configuration when you want different memory style, language, or recall policy * Do not patch installed plugin source under `~/.openclaw/extensions/` For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior).
### Pin trust for non-bundled plugins (recommended) [#pin-trust-for-non-bundled-plugins-recommended-step] If OpenClaw warns that `plugins.allow` is empty, add this: ```json { "plugins": { "allow": ["openclaw-nowledge-mem"] } } ``` If you also use linked or workspace copies, review `plugins.load.paths` too. OpenClaw allowlists plugin ids, not install provenance.
### Restart OpenClaw and verify [#restart-openclaw-and-verify-step] ```bash openclaw nowledge-mem status ``` If Nowledge Mem is reachable, you're done. If you manage OpenClaw config manually instead of using `openclaw plugins install`, make sure `plugins.slots.memory` is `openclaw-nowledge-mem` and `plugins.entries.openclaw-nowledge-mem.enabled` is `true`. For local mode, no API key is needed. If you are connecting to a remote Nowledge Mem server instead, set `apiUrl`, and add `apiKey` when that server has auth enabled.
## Spaces [#spaces] OpenClaw can keep one ambient memory lane per profile or process. * Use `NMEM_SPACE="Research Agent"` when one OpenClaw process already belongs to one lane. * Or set plugin config `space` for one fixed lane in the OpenClaw UI. * Use `spaceTemplate` only when your launcher already exports a trustworthy lane variable such as `${OPENCLAW_AGENT_NAME}`. If the runtime does not expose agent identity cleanly, do not fake per-agent mapping. Use one profile per lane or stay on **Default**. ## Verify It Works (1 Minute) [#verify-it-works-1-minute] In OpenClaw chat: 1. `/remember We chose PostgreSQL for task events` 2. `/recall PostgreSQL`: should find it immediately 3. `/new`: start a fresh session 4. Ask: `What database did we choose for task events?`: it remembers across sessions 5. Ask: `What was I working on this week?`: weekly activity view 6. Ask: `What was I doing on February 17?`: down to the exact day 7. `/forget PostgreSQL task events`: clean deletion If all seven steps work, the memory system is fully running. ## What You Can Do [#what-you-can-do] **Your chats stay. Automation does not.** Talk in OpenClaw and those turns save as threads you can search later. The plugin skips automation sessions such as `cron-worker`, so the list stays readable. When something in a session is worth keeping, Mem can distill it into structured memories and point back to the chat with `sourceThreadId`. **Use graph-based memory, not a flat archive** Memories are linked to related entities, earlier and later versions of the same idea, and the source conversations they came from. That means OpenClaw can do more than keyword recall. It can trace how a decision changed, follow connected topics, and explain where an answer came from. **Let knowledge improve in the background** When Background Intelligence is enabled in Nowledge Mem, the system keeps working after the session ends: deduplicating overlap, surfacing contradictions, writing Working Memory briefings, and creating crystals when several memories converge into something worth keeping. OpenClaw can read those outputs the next time you work. **Remember anything, forever** Tell the AI `/remember We decided against microservices, the team is too small`. Next week, in a different session, ask "what was that decision about microservices?" It finds it. **Browse your work by date** Ask "what was I doing last Tuesday?" and the AI lists everything you saved, documents you added, and insights generated that day. You can ask for a specific date, not just "the past N days." **Bring the rest of your AI work into OpenClaw** What you learned in Claude, decided in Cursor, captured from browser chats, or imported from past threads can all become part of the same memory layer. OpenClaw is not an island. It is one connected path in a larger system. **Trace a decision's history** Ask the AI "how did this idea develop?" and it shows you: the original source documents that informed it, which related memories were synthesized into a higher-level insight, and how your understanding changed over time. **Optional: start every session already in context** If you enable `sessionContext`, Context Bundle / Working Memory and relevant memories are injected before the first response. That gives OpenClaw immediate context from turn one. In the default mode, the agent still gets memory tools and a short system hint, but it decides when to search. **Save knowledge with structure, not just text** When you ask the AI to remember something, it doesn't just store text. It records the type (decision, learning, preference, plan...), when it happened, and links it to related knowledge. Searching by type, by date, by topic all work because the structure is there. **Trace a memory to its source conversation** When a memory was distilled from a conversation, it includes a `sourceThreadId`. The agent can fetch the full conversation with `nowledge_mem_thread_fetch` to see the complete context: what was said, what was decided, and how the conclusion was reached. **Search past conversations directly** Ask "find the conversation where we discussed Redis caching" and the agent uses `nowledge_mem_thread_search` to find matching threads with message snippets. Then fetch full messages with `nowledge_mem_thread_fetch` for progressive retrieval of long conversations. **Slash commands**: `/remember`, `/recall`, `/forget` ## How It Works [#how-it-works] ### Per-turn flow [#per-turn-flow] Every time you send a message, the plugin injects behavioral guidance before the agent processes it. The agent then decides which tools to call. The behavioral skill and always-on hook nudge the agent to **search before answering** and **save after deciding**. Here's when each tool fires: | Scenario | Tool | What happens | | ------------------------------------------------ | ---------------------------- | -------------------------------------------------------------------------------- | | User asks a question | `memory_search` | Search knowledge base before answering. Returns `sourceThreadId` when available. | | Decision made, insight learned | `nowledge_mem_save` | Structured save: type + labels + temporal context. | | "What was I doing last week?" | `nowledge_mem_timeline` | Activity feed grouped by day. Supports exact date ranges. | | "How is X connected to Y?" | `nowledge_mem_connections` | Graph walk: edges, entities, EVOLVES chains, provenance. | | Need startup context or today's focus/priorities | `nowledge_mem_context` | Read Context Bundle when available, with Working Memory fallback. | | Memory has `sourceThreadId` | `nowledge_mem_thread_fetch` | Fetch full source conversation with pagination. | | "Find our discussion about X" | `nowledge_mem_thread_search` | Search past conversations by keyword. | | "Forget X" | `nowledge_mem_forget` | Delete by ID or search query. | | "Is my setup working?" | `nowledge_mem_status` | Show config, connectivity, and version. | ### Session lifecycle (automatic capture) [#session-lifecycle-automatic-capture] When sessions end, conversations are automatically captured and optionally distilled into structured memories. Key points: * Sessions where you are really chatting in OpenClaw are saved automatically. They show up in Mem like threads from other assistants. * Isolated cron or other automation sessions are not captured. OpenClaw gives them separate keys; you might notice `cron-worker` in diagnostics. Leaving them out of Threads is deliberate. * Distillation runs when the transcript grows on a normal path (`agent_end`, or each Context Engine turn). A compaction-only checkpoint does not, by itself, trigger a new distill pass. * If you enable the Context Engine, prompt assembly moves there, but thread capture still keeps the lifecycle hooks as a backstop. That makes session sync more resilient without creating duplicate threads. * Distilled memories include `sourceThreadId` so you can open the source conversation. ### Progressive retrieval (memory to thread to messages) [#progressive-retrieval-memory-to-thread-to-messages] Memories distilled from conversations carry a `sourceThreadId`. This creates a chain: search memories, trace to source conversation, read full messages with pagination. Two entry points into past conversations: 1. **From a memory**: `memory_search` or `memory_get` returns `sourceThreadId`, then fetch the source conversation 2. **Direct search**: `nowledge_mem_thread_search` finds conversations by keyword, then fetch any match ### Three modes [#three-modes] The plugin supports three operating modes. Choose based on how much you want to guarantee versus how much token budget you're willing to spend. | Mode | Config | Behavior | Token cost | | ------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | | **Default** (recommended) | `sessionContext: false` | Agent calls 10 tools on demand. Conversations captured + distilled at session end. | Lowest overhead. The agent decides when to search. | | **Session context** | `sessionContext: true` | Context Bundle / Working Memory + relevant memories injected at prompt time, plus all 10 tools still available. | Higher per-turn context cost, but context is present from turn one. | | **Minimal** | `sessionDigest: false` | Tool-only, no automatic capture. | Small overhead from the always-on system hint only. | **Which mode should you use?** * **Most users**: start with default. The agent gets behavioral guidance nudging it to search before answering and save after deciding. It works well for most conversations. * **Short sessions or critical accuracy**: enable `sessionContext`. This guarantees relevant memories are present from the first turn. The agent doesn't need to decide whether to search. The tradeoff is a larger prompt on each turn. * **Full manual control**: set `sessionDigest: false`. You control what gets saved (via `/remember` or `nowledge_mem_save`) and nothing is captured automatically. ### sessionContext - Automatic context injection [#sessioncontext---automatic-context-injection] When enabled, the plugin injects context at prompt time: 1. Reads **Context Bundle** when available: owner identity, agent identity, active space, Rules, Working Memory, and KFS paths. Older `nmem` clients fall back to Working Memory. 2. Searches your knowledge graph for **memories relevant to your current prompt** 3. Appends the recalled material as run-specific context in system-prompt space, so the stable prefix stays cached and token costs stay low The behavioral guidance automatically adjusts when `sessionContext` is on. It tells the agent that context has already been injected, so `memory_search` should only be used for specific follow-up queries, not broad recall. This prevents redundant searches for the same context. Useful for giving the agent immediate context without waiting for it to search proactively. Best for short sessions and critical workflows where you want guaranteed recall. ### sessionDigest - Thread capture + LLM distillation (default: on) [#sessiondigest---thread-capture--llm-distillation-default-on] On by default. Two things happen at session lifecycle events (`agent_end`, `after_compaction`, `before_reset`): **1. Thread capture (interactive sessions).** The full chat is appended to a Mem thread and stays searchable with `nowledge_mem_thread_search`. Cron and other isolated automation use different session keys; the plugin skips them so scheduled runs do not sit next to the conversations you started yourself. **2. LLM distillation (when worthwhile).** After thread capture, a lightweight LLM triage determines if the conversation contains save-worthy content (decisions, insights, preferences). If yes, a full distillation pass extracts structured memories with proper types, labels, and temporal data. Works in **any language**. **Context compaction**: when OpenClaw compresses a long conversation, the plugin captures the transcript first. Nothing is lost. **Deduplication**: thread appends are idempotent by message ID. No duplicates. ## Common Questions [#common-questions] **Does the agent always search before answering?** The plugin uses two layers to drive recall. First, a behavioral skill (auto-discovered by OpenClaw) teaches the agent when and how to use memory tools. Second, a short always-on system hint reminds it to search before answering questions about prior work, decisions, or preferences. In practice, modern LLMs follow this directive guidance reliably for knowledge-related questions. For messages that don't need past context, the agent skips the search, which is the right tradeoff. If guaranteed recall matters for your use case, enable `sessionContext: true`. That injects relevant memories at prompt time, before the agent processes your message. **What stops the agent from saving the same thing twice?** Two layers. First, the plugin checks for near-identical existing memories before every save. If a memory with very high similarity already exists, the save is skipped and the existing memory is returned instead. Second, Nowledge Mem's Background Intelligence runs in the background and handles deeper deduplication, identifying semantic overlap across memories and linking them via EVOLVES chains (replaces, enriches, confirms, or challenges). The plugin catches obvious duplicates; Background Intelligence catches subtle ones. **What happens to conversations I don't explicitly save?** With `sessionDigest` on (the default), chats you have in OpenClaw are stored as searchable threads. The boundary follows OpenClaw's own session lifecycle: one active chat becomes one Mem thread, `/new` or `/reset` starts a fresh thread, and transcript rotation during compaction stays inside the same thread. Context Engine capture and hook-based capture still converge on the same conversation. Helper sessions such as `temp:*` and subagent runs are filtered out, so your recent threads stay focused on real chats. Find them later with `nowledge_mem_thread_search`. A small LLM pass may promote a rich session into structured memories; casual small talk usually stops at the thread. Cron runs never enter this path. **Can memories become outdated?** Yes, and that's by design. Nowledge Mem's EVOLVES chains track how understanding changes: a newer memory can supersede, enrich, or challenge an older one. Background Intelligence identifies these relationships automatically. When you search, the relevance scoring considers recency, so newer memories rank higher by default. ## Configuration [#configuration] No config is needed for a normal npm install. The installer already enables the plugin and selects the memory slot. To change settings, open the OpenClaw dashboard and go to **Automation > Plugins**. Under **Plugin Entries**, expand **Nowledge Mem**, then **Nowledge Mem Config**. You can also type "nowledge" in the search bar to jump straight there. OpenClaw Automation, Nowledge Mem plugin settings Changes take effect after restarting OpenClaw. | Setting | Default | What it does | | ------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Session context injection | off | Inject Context Bundle / Working Memory + relevant memories at prompt time | | Session digest at end | on | Capture conversations + distill key memories at session end | | Minimum digest interval | 300s | Seconds between session digests (0 = no limit) | | Max context results | 5 | Memories to inject at prompt time (1-20) | | Min recall score | 0 | Only inject memories scoring above this threshold (0-100%). 0 includes all results. | | Max thread message chars | 800 | Characters kept per captured thread message (200-20000). Raise for long code or technical conversations. | | Corpus supplement | off | Feed your knowledge into OpenClaw's dreaming system (see below) | | Corpus max results | 5 | Max results per dreaming search (1-20) | | Corpus min score | 0 | Min score for dreaming results (0-100%). 0 includes all. | | Dreaming | managed by OpenClaw | Optional OpenClaw dreaming settings. When Nowledge Mem owns the memory slot, OpenClaw may store its native `dreaming` object here. `memory-core` still runs the dreaming engine. | | Server URL | empty | Remote server URL (empty = local) | | API key | empty | API key for remote access | ### Remote access [#remote-access] To connect to a Nowledge Mem server on another machine, configure this machine once: ```bash nmem config client set url https:// nmem config client set api-key nmem_... ``` That writes the shared local client config used by `nmem`, OpenClaw, Bub, Claude Code, and other integrations on this machine. You can also set **Server URL** and **API key** in the OpenClaw dashboard plugin settings. The same resolved credentials are used everywhere in the plugin: CLI-backed memory tools and API-backed thread sync both follow the same `apiUrl` and `apiKey`. The API key never appears in logs or command history. See [Access Mem Anywhere](/docs/remote-access). ## Troubleshooting [#troubleshooting] **Plugin is installed but OpenClaw isn't using it** Check that `plugins.slots.memory` is exactly `openclaw-nowledge-mem`, and that you restarted OpenClaw after editing the config. **`plugins.allow is empty` warning** This means OpenClaw found a non-bundled plugin without an explicit allowlist entry yet. If this is your npm-installed plugin, add: ```json { "plugins": { "allow": ["openclaw-nowledge-mem"] } } ``` If you also use `plugins.load.paths` or linked workspace copies, review those paths too. OpenClaw allowlists ids, not install provenance. **"Duplicate plugin id detected" warning** This happens if you previously installed the plugin locally (e.g. with `--link`) and then installed from npm. OpenClaw is loading it from both places. Fix it by removing the local path from your config: Open `~/.openclaw/openclaw.json` and delete the `plugins.load.paths` entry that points to the local plugin directory: ```json "load": { "paths": [] } ``` Then restart OpenClaw. The warning will be gone and only the npm-installed version will load. **Status shows not responding** ```bash nmem status curl -sS http://127.0.0.1:14242/health ``` **Memory tools work, but the session itself does not show up in Threads** Run `nowledge_mem_status` inside a normal chat session and confirm: * `sessionDigest` is still on * the backend is reachable * which capture route is active * whether you changed plugin settings recently without restarting OpenClaw yet If you enabled `plugins.slots.contextEngine: "nowledge-mem"`, plugin `0.8.6+` keeps lifecycle hooks as a safety net for thread sync. On current OpenClaw installer builds, `plugins.slots.contextEngine` may instead be `openclaw-nowledge-mem`; plugin `0.8.18+` treats that as the same engine. On `0.8.5` and earlier, a useful isolation step is to remove the `contextEngine` slot temporarily, restart OpenClaw, and see whether thread capture returns on the hook-only path. If threads stopped updating right after an OpenClaw upgrade, update the Nowledge Mem plugin and restart OpenClaw. Plugin `0.8.24+` handles newer per-turn capture events from OpenClaw's Codex runtime. Plugin `0.8.27+` is also required for OpenClaw builds that log `must declare contracts.tools before registering agent tools`; that error means OpenClaw rejected the plugin's tools before capture hooks could run. OpenClaw `2026.6.11` emits numeric message timestamps. Plugin `0.8.30+` converts them to the textual timestamp contract used by Mem Threads. It also reports when OpenClaw is blocking the `agent_end` fallback. Grant access and restart after upgrading: ```bash openclaw config set plugins.entries.openclaw-nowledge-mem.hooks.allowConversationAccess true --strict-json openclaw gateway restart ``` OpenClaw applies plugin setting changes after restart. If `sessionDigest` was turned off earlier but OpenClaw had not restarted yet, thread sync could appear to keep working until the next restart, then stop. Healthy OpenClaw thread sync looks like this: * one active OpenClaw chat becomes one Mem thread * running `/new` or `/reset` starts a fresh Mem thread * compaction does not fork a second thread for the same chat * helper sessions like `temp:slug-generator` do not appear * the synthetic `/new` / `/reset` startup prompt is not saved as the first user message To inspect the recent synced threads directly: ```bash nmem t list --source openclaw -n 20 ``` **Only `memory_search` and `memory_get` work, saves go to local files** First run `openclaw config get tools`. If a restrictive profile such as `coding` is active, preserve its policy and add `openclaw-nowledge-mem` to `tools.alsoAllow`; if `tools.allow` already exists, add the plugin id there. Then check the memory slot. OpenClaw 3.22+ defaults the memory slot to `memory-core` when no explicit slot is configured, so a manual install or upgrade can require the slot to be set again. Verify your config has the explicit slot: ```json { "plugins": { "slots": { "memory": "openclaw-nowledge-mem" } } } ``` Or reinstall, which sets the slot automatically: ```bash openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem ``` Restart OpenClaw after either change. **Plugin tools not available** Plugin trust and tool policy are separate gates. Make sure the plugin is in `plugins.allow`: ```json { "plugins": { "allow": ["openclaw-nowledge-mem"] } } ``` Then inspect `openclaw config get tools`. A restrictive profile needs `openclaw-nowledge-mem` in `tools.alsoAllow`, unless an explicit `tools.allow` already exists, in which case add the plugin id there. Preserve existing entries. Do not list individual `nowledge_mem_*` names: using the plugin id keeps the granted surface aligned with the manifest. **Search is slow with many concurrent agents** When running many agents in parallel (10+), search performance can degrade because all operations share a single database connection. Recommendations: * Upgrade to Nowledge Mem v0.6.12+ (backend): scoring writes no longer block search responses * If your agents use the CLI transport, consider setting a remote API URL in the plugin config to reduce subprocess overhead **Search returns too few results** Raise `maxContextResults` to `8` or `12`. ## Why Nowledge Mem? [#why-nowledge-mem] Other memory tools store what you said as text and retrieve it by semantic similarity. Nowledge Mem is different. **Knowledge has structure.** Every memory knows what type it is (decision, learning, plan, preference), when it happened, which source documents it came from, and how it relates to other memories. That's what makes search precise and reasoning reliable. **Knowledge evolves.** The understanding you wrote today connects to the updated version you saved three months later. You can see how your thinking changed, without losing the intermediate steps. **Knowledge has provenance.** Every piece of knowledge extracted from a PDF, document, or web page links back to its source. When the AI says "based on your March design doc," you can verify it. **Knowledge travels across tools.** What you learned in Cursor, saved in Claude, refined in ChatGPT, all available in OpenClaw. Your knowledge belongs to you, not to any one tool. **Local first, no cloud required.** Your knowledge lives on your machine. Remote access is available when you need it, not imposed by default. How search ranking works: [Search & Relevance](/docs/search-relevance). ## Working with memory-core (v0.8.0+) [#working-with-memory-core-v080] The default setup makes Nowledge Mem the memory slot. You get the full tool surface and all 10 tools. Most users should stay here. Some users prefer to keep OpenClaw's built-in memory-core as the memory slot. memory-core has `MEMORY.md` management and dreaming (an experimental consolidation system that periodically promotes frequently recalled content into long-term storage). The plugin supports both paths. When `corpusSupplement` is enabled, memory-core's recall pipeline can search your Nowledge Mem knowledge graph directly. Memories you saved from Claude, Cursor, ChatGPT, or other tools show up in memory-core's search results and feed into dreaming. Use `0.8.15` or later for this setup. Earlier builds could leave the plugin effectively inactive beside `memory-core`, which made some users patch local source files just to keep supplement mode alive. ### What corpus supplement does [#what-corpus-supplement-does] When memory-core runs a search, it also queries Nowledge Mem. Results from your knowledge graph appear alongside memory-core's own results, scored and ranked together. This means: * memory-core's recall includes your cross-tool knowledge * Dreaming (experimental) can promote frequently recalled Nowledge Mem content into `MEMORY.md` * Weekly pattern extraction can find connections between your knowledge graph and memory-core's data ### Setup [#setup-1] Keep the memory slot on memory-core (or leave it unset). Then set `corpusSupplement: true` in the plugin settings, or via environment variable `NMEM_CORPUS_SUPPLEMENT=true`. The plugin handles deduplication automatically. When Nowledge Mem is the memory slot, it handles recall directly. When memory-core is the memory slot and corpus supplement is on, it feeds into memory-core's pipeline instead. You won't get the same content twice. If OpenClaw stores a top-level `dreaming` object under the Nowledge Mem plugin entry, that is normal. OpenClaw now writes dreaming settings onto the selected memory-slot owner. The plugin accepts that config so memory-core can continue running the dreaming engine alongside Nowledge Mem. ### How to decide [#how-to-decide] | Setup | Best for | | ------------------------------------- | ------------------------------------------------------------------------------------------------------ | | Nowledge Mem as memory slot (default) | All 10 tools, structured memory types, thread provenance. One system manages everything. | | memory-core + corpus supplement | You use memory-core's `MEMORY.md` workflow or want dreaming. Your cross-tool knowledge still feeds in. | Capture and distillation work the same either way. The difference is which system handles recall and long-term consolidation. ## Context Engine (v0.7.0+) [#context-engine-v070] Starting with plugin v0.7.0, Nowledge Mem can run as a full **Context Engine** in OpenClaw, not just as prompt hooks. This gives it deeper integration with OpenClaw's lifecycle: * **Memory-aware compaction**: when OpenClaw compresses a long conversation, key decisions and learnings already saved in your knowledge graph are preserved by reference, not lost in summarization * **Subagent memory propagation**: when OpenClaw spawns parallel research agents, they inherit your memory context automatically * **Session bootstrap**: Context Bundle or Working Memory is pre-loaded before the first turn, so context is ready immediately * **Per-turn capture**: conversations are captured after every turn, not just at session end To activate, add this to your OpenClaw config: ```json { "plugins": { "slots": { "memory": "openclaw-nowledge-mem", "contextEngine": "nowledge-mem" } } } ``` If you don't activate the Context Engine, the existing hook-based setup continues to work exactly as before. If you do activate it, the Context Engine handles prompt assembly and per-turn capture, while the lifecycle hooks remain as a quiet reliability backstop for thread sync. That split is intentional: it keeps context injection clean without making capture depend on a single runtime path. ## For Advanced Users [#for-advanced-users] OpenClaw's `MEMORY.md` workspace file still works for workspace context. Memory tool calls are handled by Nowledge Mem, but both can coexist. The plugin uses one shared connection config across its transport paths. Most memory operations still use `nmem`, while conversation-thread sync talks to the Mem server directly so large sessions travel in a normal request body instead of a giant command-line argument. You still configure the address once, and local and remote mode continue to work the same way from the user's point of view. ## Related [#related] * [Connectors overview](/docs/integrations): native connectors, reusable packages, MCP, and browser capture * [Claude Code](/docs/integrations/claude-code) · [Claude Desktop](/docs/integrations/claude-desktop) · [Codex](/docs/integrations/codex-cli) · [Alma](/docs/integrations/alma) · [Raycast](/docs/integrations/raycast) · [Other Chat AI](/docs/integrations/other-chat-ai) ## References [#references] * Plugin source: [nowledge-mem-openclaw-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-openclaw-plugin) * OpenClaw docs: [Plugin system](https://docs.openclaw.ai/tools/plugin) * Changelog: [CHANGELOG.md](https://github.com/nowledge-co/community/blob/main/nowledge-mem-openclaw-plugin/CHANGELOG.md) # OpenCode × Nowledge Mem (/docs/integrations/opencode) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for OpenCode. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ```bash title="Install" opencode plugin opencode-nowledge-mem -g ``` OpenCode is a terminal coding agent. Nowledge Mem adds the layer above: knowledge from all your other AI tools, decisions made in Claude Code, preferences set in Cursor, insights from ChatGPT, searchable inside OpenCode. New OpenCode sessions are also captured after OpenCode goes idle, so what you learn there can feed later recall and crystallization without switching tools. ## Before You Start [#before-you-start] * **Nowledge Mem** running locally ([installation](/docs/installation)) or a reachable remote Mem server * **OpenCode** installed * **`nmem` CLI** in your PATH. In Nowledge Mem go to **Settings → Preferences → Developer Tools → Install CLI**, or `pip install nmem-cli` ```bash nmem status # Nowledge Mem is running opencode --version # OpenCode is available ``` ## Setup [#setup]
### Install the plugin [#install-the-plugin-step] Install the npm plugin and let OpenCode update your config: ```bash opencode plugin opencode-nowledge-mem -g ``` Use `-g` for global use across all projects. Omit it when you only want the plugin in the current project. If you prefer editing config manually, add the plugin name yourself: ```json title="~/.config/opencode/opencode.json" { "plugin": ["opencode-nowledge-mem"] } ```
### Restart OpenCode [#restart-opencode-step] Close and reopen OpenCode so it loads the plugin.
### Verify the integration [#verify-the-integration-step] Ask OpenCode to check your Nowledge Mem connection: ``` What was I working on recently? ``` You should see OpenCode call `nowledge_mem_context_bundle` when full startup context matters, or `nowledge_mem_working_memory` as the lightweight fallback, then return your current context. That's success: OpenCode can now see knowledge from your other tools. To verify thread capture, finish a short turn and wait a moment after OpenCode becomes idle. In another terminal, search for a phrase from the turn: ```bash nmem t search "the phrase you just used" --source opencode ``` You should see an `opencode-...` thread. If you do not, update the plugin and restart OpenCode so the event hook is loaded.
## Update [#update] Refresh the global plugin package and replace the installed copy: ```bash opencode plugin opencode-nowledge-mem -g --force ``` ## Customize Safely [#customize-safely] Use OpenCode's own instruction surfaces, not the installed plugin files: * `AGENTS.md` in the repo when this project needs shared behavior * `~/.config/opencode/AGENTS.md` for your personal defaults * `instructions` in `opencode.json` when you want host-level config instead of file-based guidance Do not edit the installed Nowledge Mem plugin package directly. For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## What You Can Do [#what-you-can-do] **Find knowledge from other tools** Ask "what did we decide about the database?" and OpenCode searches across decisions you made in Claude Code, insights from ChatGPT, notes from Cursor, not just this session. **Save knowledge for everywhere** When you reach a conclusion in OpenCode, the agent saves it so your next Claude Code session, Cursor project, or ChatGPT conversation can find it too. **Start with today's context** Your Context Bundle, Working Memory briefing, and relevant past knowledge are available before you repeat yourself across tools. **Keep the full session searchable** When OpenCode finishes a turn and reports idle, the plugin saves the session as a Mem thread. Long sessions also flush before compaction, so the transcript stays available for search, review, and later knowledge crystallization. **Create resumable handoffs** Wrap up in OpenCode, then pick up right where you left off in Claude Code or any other tool. Decisions, plans, and context carry over automatically. ## Tools [#tools] | Tool | What it does | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | `nowledge_mem_context_bundle` | Read startup context: owner identity, agent identity, active space, Rules, Working Memory, and KFS paths. | | `nowledge_mem_working_memory` | Read today's lightweight Working Memory: focus areas, priorities, recent activity. | | `nowledge_mem_search` | Search knowledge from all your tools. Supports label, date, and deep mode filters. | | `nowledge_mem_save` | Save a decision, insight, or preference so any tool can find it. | | `nowledge_mem_update` | Update an existing memory with refined information. | | `nowledge_mem_thread_search` | Search past conversations from any tool. | | `nowledge_mem_save_thread` | Save the current session as a full conversation thread on demand. Automatic idle capture normally handles this for new work. | | `nowledge_mem_save_handoff` | Save a curated handoff summary (lighter, agent-composed). | | `nowledge_mem_status` | Check Nowledge Mem server connectivity and diagnostics. | ## How Session Capture Works [#how-session-capture-works] Nowledge Mem captures OpenCode sessions in four complementary ways: **Plugin automatic live capture.** When OpenCode reports `session.status=idle` (or the older `session.idle` event), the plugin waits briefly for messages to flush, reads the current session through OpenCode's SDK, and writes the matching `opencode-...` thread to Mem. This is the path you should rely on for new work. **Pre-compaction flush.** Before OpenCode compacts a long session, the plugin saves the current transcript through the same thread path, then reminds the agent to reload Mem context after compaction. **Manual full session capture.** `nowledge_mem_save_thread` reads the current session's messages via OpenCode's SDK client and posts them to Nowledge Mem over HTTP. It is safe to run multiple times and remains useful as an explicit fallback. **Plugin proactive knowledge save.** `nowledge_mem_save` captures individual decisions and insights during the conversation, stamped with `source=opencode`. `nowledge_mem_save_handoff` creates a curated summary at wrap-up. Both complement the full transcript with focused, high-value takeaways. Desktop import reads OpenCode's local database directly, so it only sees sessions on the machine where Mem is running. In [remote mode](/docs/remote-access), use the native plugin's live capture or run `nmem t sync` on the client machine where OpenCode stores its sessions. ### Import older sessions [#import-older-sessions] To backfill older OpenCode sessions, preview first: ```bash nmem t sync --from opencode --all-projects --limit 20 ``` Then import: ```bash nmem t sync --from opencode --all-projects --apply ``` Use `-p /path/to/project` instead of `--all-projects` when you only want one project. The command reads OpenCode's local session database or legacy JSON storage on this machine and writes to the Mem server configured in `nmem`. Imported history becomes searchable immediately; deeper distillation remains an explicit review step. ## Configuration [#configuration] No config needed for local use. | Env Variable | Default | What it does | | -------------- | --------- | ------------------------------ | | `NMEM_API_URL` | *(local)* | Remote Nowledge Mem server URL | | `NMEM_API_KEY` | *(none)* | API key for remote access | For a persistent shared setup, configure this machine once with `nmem config client ...`. Environment variables still take priority when you need a temporary override. ### Remote access [#remote-access] ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` OpenCode uses that same shared config for `nmem` command tools, automatic idle capture, manual session capture, and historical sync. See [Access Mem Anywhere](/docs/remote-access). ## Troubleshooting [#troubleshooting] **nmem not found.** Install with `pip install nmem-cli`, then run `nmem status` to verify. **Server not responding.** Start the Nowledge Mem desktop app, or check `nmem status` for diagnostics. **Plugin not loading.** Re-run `opencode plugin opencode-nowledge-mem -g --force`, confirm `"opencode-nowledge-mem"` appears in your `opencode.json` plugin array, then restart OpenCode. ## Related [#related] * [Connectors overview](/docs/integrations) * [Claude Code](/docs/integrations/claude-code) · [Pi](/docs/integrations/pi) · [Hermes Agent](/docs/integrations/hermes) · [OpenClaw](/docs/integrations/openclaw) · [Alma](/docs/integrations/alma) * Plugin source: [nowledge-mem-opencode-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-opencode-plugin) # Other Chat AI (/docs/integrations/other-chat-ai) Both DeepChat and LobeHub ship with Nowledge Mem built in. No server config, no MCP setup. Just toggle on. ## DeepChat [#deepchat]
### Enable MCP in DeepChat [#enable-mcp-in-deepchat-step] Toggle on the switch under Settings > MCP Settings
### Enable Nowledge Mem [#enable-nowledge-mem-step] Toggle on the nowledge-mem switch under Custom Servers DeepChat Toggle Highlight
## LobeHub [#lobehub] LobeHub (formerly LobeChat) offers one-click install from its plugin marketplace.
### One-click install [#one-click-install-step]
### Confirm in the install dialog [#confirm-in-the-install-dialog-step] Click Install in the dialog LobeHub Installation Demo
## Related [#related] * [Connectors overview](/docs/integrations): native connectors, reusable packages, MCP, and browser capture * [Claude Code](/docs/integrations/claude-code) · [Claude Desktop](/docs/integrations/claude-desktop) · [Codex](/docs/integrations/codex-cli) · [Alma](/docs/integrations/alma) · [OpenClaw](/docs/integrations/openclaw) · [Raycast](/docs/integrations/raycast) # Paseo (/docs/integrations/paseo) Paseo runs coding agents such as Claude Code, Codex, Copilot, OpenCode, Pi, and OMP on your own machine. Nowledge Mem should connect to those launched AI tools. Paseo is the orchestration layer: it decides which worker runs, while the launched tool owns MCP, hooks, and transcript files. Paseo's own MCP tools are for orchestration, such as creating agents or worktrees. Keep using them if you like. They do not replace the Nowledge Mem connector inside the launched AI tool, and they do not automatically capture every transcript for Mem. ## What You Need [#what-you-need] 1. Nowledge Mem is running on the machine where Paseo starts agents. 2. The AI tools Paseo launches are already connected to Mem, such as [Codex](/docs/integrations/codex-cli), [Claude Code](/docs/integrations/claude-code), [OpenCode](/docs/integrations/opencode), [Pi](/docs/integrations/pi), or [OMP](/docs/integrations/omp). 3. You know which Paseo agents are durable roles, not one-off tasks. ## First Useful Setup [#first-useful-setup] Connect the launched AI tool first. For example, if Paseo starts Codex, install and verify the Codex connector. If it starts Pi, install and verify the Pi package. If it starts OMP, install and verify the OMP plugin. If a Paseo agent represents a stable role, create one Mem AI Identity: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "Help with onboarding. Explain one step at a time." ``` Then pass the identity into that launched child runtime: ```bash NMEM_AGENT_ID=cindy ``` Leave `NMEM_AGENT_ID` unset for one-off advisors, short-lived implementation agents, and generic provider presets. Those can still use Mem through the child tool connector; they just do not need a named identity. ## Keep Source App Honest [#keep-source-app-honest] Do not label every child session as `paseo`. Use the launched AI tool as `source_app`: * Paseo starts Codex: `source_app=codex` * Paseo starts Claude Code: `source_app=claude-code` * Paseo starts OpenCode: `source_app=opencode` * Paseo starts Pi: `source_app=pi` * Paseo starts OMP: `source_app=omp` This keeps thread filters, icons, and capture paths correct. The Mem AI Identity is the worker's long-term role; the source app is the tool that actually produced the transcript. ## What Syncs [#what-syncs] Supported child-tool sessions sync in two ways. ### While You Work [#while-you-work] Automatic new-thread capture comes from the connector installed in the launched AI tool. If Paseo starts Codex, install the Codex connector. If Paseo starts Claude Code, install the Claude Code connector. If Paseo starts OpenCode, Pi, or OMP, install those packages. Paseo can run those tools, but Paseo itself does not provide a Mem hook that fires after every child turn. ### Backfill Older Paseo Agents [#backfill-older-paseo-agents] Older Paseo-managed sessions can be imported from Paseo's local agent registry: ```bash nmem t sync --from paseo --all-projects --apply ``` That command reads Paseo's agent records, finds supported child sessions, and imports the real child transcript. Imported threads keep the child source, such as `codex`, `claude-code`, `opencode`, `pi`, or `omp`; they are not labeled as `paseo`. The import is safe to rerun. Paseo-guided sync uses the same child thread id as direct child-tool sync, so a Codex session imported through Paseo still lands on the same `codex-*` thread instead of creating a second `paseo-*` copy. Paseo's terminal activity, schedules, and chat rooms are separate. Nowledge Mem can import them directly only if Paseo later exposes message-level transcript export, API, or hook data for those surfaces. ## What Success Looks Like [#what-success-looks-like] Inside the AI tool launched by Paseo, run: ```bash nmem --json context --source-app codex ``` Use the matching source app for the launched tool. If the child runtime received `NMEM_AGENT_ID=cindy`, the Context Bundle should show Cindy's identity and default space. From a normal terminal, pass the identity explicitly: ```bash nmem --json context --agent-id cindy --source-app codex ``` ## Next [#next] * [Codex](/docs/integrations/codex-cli) * [Claude Code](/docs/integrations/claude-code) * [OpenCode](/docs/integrations/opencode) * [Pi](/docs/integrations/pi) * [OMP](/docs/integrations/omp) * [Customize Connector Behavior](/docs/integrations/customize-behavior) # Pi × Nowledge Mem (/docs/integrations/pi) Give this line to your agent. It should use the universal install skill first; this page remains the behavior and troubleshooting reference: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Pi. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ```bash title="One-liner install" pi install npm:nowledge-mem-pi ``` Pi is a minimal, extensible terminal coding agent. Nowledge Mem adds the layer above: knowledge from all your other AI tools, decisions made in Claude Code, preferences set in Cursor, insights from ChatGPT, searchable inside Pi. After you install the package, completed Pi conversations also sync back to Nowledge Mem as threads, so future tools can find what happened in Pi. The package now has two automatic paths: Pi receives your Context Bundle or Working Memory at session startup, and completed Pi conversations are captured as searchable threads. Skills remain available for live search, saving decisions, and explicit handoffs. ## Before You Start [#before-you-start] * **Nowledge Mem** running locally ([installation](/docs/installation)) * **Pi** installed * **`nmem` CLI** in your PATH. In Nowledge Mem go to **Settings → Preferences → Developer Tools → Install CLI**, or `pip install nmem-cli` ```bash nmem status # Nowledge Mem is running pi --version # Pi is available ``` ## Setup [#setup]
### Install the package [#install-the-package-step] ```bash pi install npm:nowledge-mem-pi ```
### Verify the integration [#verify-the-integration-step] Ask Pi to check your Nowledge Mem connection: ``` Is Nowledge Mem connected? Run the status skill. ``` You should see connection details and a confirmation that the server is reachable. That's success: Pi can now see knowledge from your other tools. Start a fresh Pi session after install or update. Pi should already have a Nowledge Mem startup block in its system context; it should not need to run the `read-working-memory` skill just to know today's Context Bundle.
## Update [#update] ```bash pi update ``` Restart Pi after updating so the Nowledge Mem extension reloads. ## Import Older Sessions [#import-older-sessions] Automatic sync starts after the package is installed. If you have older Pi sessions you want in Nowledge Mem, run a one-time history import. Preview first: ```bash nmem t sync --from pi --limit 20 ``` Then import: ```bash nmem t sync --from pi --apply ``` The command reads Pi session files on this machine and writes them to the Mem server configured for your CLI or extension. It is safe to run again: Pi session IDs become stable thread IDs, and repeated messages are deduplicated. Useful filters: ```bash nmem t sync --from pi --session-dir ~/.pi/agent/sessions --limit 20 nmem t sync --from pi --space work --apply ``` When you pass `--session-dir`, only that directory is scanned. Without it, the command uses Pi's standard session locations. If your installed `nmem` does not have `t sync` yet, use the package fallback: ```bash npx -p nowledge-mem-pi nowledge-mem-pi-sync --apply ``` ## Customize Safely [#customize-safely] Use your project's own `AGENTS.md`, not the installed package cache. * Merge the package guidance into `AGENTS.md` when you want Pi to search or save more proactively in this repo * Keep package files as shipped defaults so updates stay clean Pi does not expose a separate durable override file beyond its normal project guidance surface. For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## What You Can Do [#what-you-can-do] **Keep Pi conversations searchable** The package includes a native Pi extension. After installation, completed turns and session boundaries sync the active Pi session branch into a `pi` thread in Nowledge Mem. `/new`, resume, compaction, and clean exit all get a final bounded flush. **Find knowledge from other tools** Ask "what did we decide about the database?" and Pi can search across decisions you made in Claude Code, insights from ChatGPT, notes from Cursor, not just this session. **Save knowledge for everywhere** When you reach a conclusion in Pi, `distill-memory` lets Pi save it so your next Claude Code session, Cursor project, or ChatGPT conversation can find it too. **Start with today's context** The extension injects Context Bundle first, then falls back to Working Memory when needed. Pi starts with owner identity, AI Identity, active scope, Rules, and today's priorities when your Mem server supports them. Project `AGENTS.md` is still useful, but for behavior rather than bootstrapping: use it to make Pi search and save more proactively in a specific repo. **Create resumable handoffs** Automatic thread sync keeps the transcript available. When you ask Pi to save a handoff, you also get a concise structured summary you can pick up in Claude Code or any other tool. ## Skills [#skills] | Skill | What it does | | --------------------- | ---------------------------------------------------------------------- | | `read-working-memory` | Read today's Working Memory: focus areas, priorities, recent activity. | | `search-memory` | Search knowledge from all your tools. Supports label and date filters. | | `distill-memory` | Save a decision, insight, or preference so any tool can find it. | | `save-thread` | Create an extra structured handoff summary when you ask for one. | | `status` | Connection and configuration diagnostics. | ## Configuration [#configuration] No config needed for local use. | Env Variable | Default | What it does | | -------------------- | ----------------- | --------------------------------------------------- | | `NMEM_API_URL` | *(local)* | Remote Nowledge Mem server URL | | `NMEM_API_KEY` | *(none)* | API key for remote access | | `NMEM_SPACE` | *(default space)* | Optional lane for this Pi process | | `NMEM_AGENT_ID` | *(none)* | Optional Mem AI Identity for orchestrated Pi agents | | `NMEM_HOST_AGENT_ID` | *(none)* | Advanced external alias | For a persistent shared setup, configure this machine once with `nmem config client ...`. The Pi extension uses the same `~/.nowledge-mem/config.json` as the CLI. Environment variables still take priority when you need a temporary override. ### Remote access [#remote-access] ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` See [Access Mem Anywhere](/docs/remote-access). ## Troubleshooting [#troubleshooting] **nmem not found.** Install with `pip install nmem-cli`, then run `nmem status` to verify. **Server not responding.** Start the Nowledge Mem desktop app, or check `nmem status` for diagnostics. **Skills not loading.** Run `pi list` to confirm the package is installed. If `nowledge-mem-pi` does not appear, reinstall with `pi install npm:nowledge-mem-pi`. **Pi conversations are not appearing in Threads.** Restart Pi after installing or updating, then run a short conversation with both a user message and an assistant reply. Check: ```bash nmem t list --source pi -n 5 ``` The extension intentionally skips one-message sessions so `/new` or empty starts do not create noise. **Older Pi conversations are missing.** Automatic sync cannot see conversations that happened before the package was installed. Use `nmem t sync --from pi` to preview and import historical Pi session files. ## Related [#related] * [Connectors overview](/docs/integrations) * [Claude Code](/docs/integrations/claude-code) · [OpenCode](/docs/integrations/opencode) · [Hermes Agent](/docs/integrations/hermes) · [OpenClaw](/docs/integrations/openclaw) · [Alma](/docs/integrations/alma) · [Bub](/docs/integrations/bub) * Plugin source: [nowledge-mem-pi-package](https://github.com/nowledge-co/community/tree/main/nowledge-mem-pi-package) # Proma × Nowledge Mem (/docs/integrations/proma) Give this line to your agent if you want it to help with setup: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for Proma. Verify with nmem status, startup context, and a saved Proma thread, then summarize what changed. ``` Proma can use Nowledge Mem in three ways: * **MCP tools** let Proma search memories, save durable knowledge, and browse Mem when the task needs it. * **Lifecycle hooks** save Proma conversations into Mem threads. * **Startup context** writes your current Mem context into Proma's workspace `CLAUDE.md`, so new Proma sessions begin with the right memory. Proma v0.13.0 and newer include a Nowledge Mem card in Proma's Memory settings. Start there if you are setting this up for the first time: it copies a setup prompt you can paste into Proma Agent mode. Keep this page open for the exact files, update steps, and verification checks. Open a new Proma session and ask What was I working on?. Then send a message with a unique phrase, wait for Proma to reply, and run nmem t search "that phrase" --source proma. You should see the Proma thread in Mem. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server. * Proma is installed. * Python 3.9+ is available as `python3`. * `nmem` works in your terminal. ```bash nmem status ``` If `nmem` is missing, install it from the Mem desktop app developer tools or run: ```bash pip install nmem-cli ``` ## Install [#install] If you are on Proma v0.13.0 or newer, open **Proma Settings → Memory → Nowledge Mem**, copy the setup prompt, and paste it into Proma Agent mode. The manual steps below are the same contract, written out so you can audit or repair the setup. The examples use Proma's `default` workspace. If your workspace has a different name, replace `default` with the directory name under `~/.proma/agent-workspaces/`. If your platform exposes Python only as `python`, replace `python3` with `python` in the hook commands.
### Download the plugin files \[step] [#1-download-the-plugin-files-step] ```bash rm -rf /tmp/nowledge-community git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community mkdir -p ~/.proma/scripts ~/.proma/agent-workspaces/default/skills cp /tmp/nowledge-community/nowledge-mem-proma-plugin/hooks/save-to-nmem.py ~/.proma/scripts/ cp /tmp/nowledge-community/nowledge-mem-proma-plugin/hooks/read-working-memory.py ~/.proma/scripts/ chmod +x ~/.proma/scripts/save-to-nmem.py ~/.proma/scripts/read-working-memory.py cp -R /tmp/nowledge-community/nowledge-mem-proma-plugin/skills/{read-working-memory,search-memory,distill-memory,save-thread,status} ~/.proma/agent-workspaces/default/skills/ ```
### Add the MCP server \[step] [#2-add-the-mcp-server-step] Create or edit: ```text ~/.proma/agent-workspaces/default/mcp.json ``` If the file already exists, merge `nowledge-mem` into the existing `servers` object. ```json title="~/.proma/agent-workspaces/default/mcp.json" { "servers": { "nowledge-mem": { "url": "http://127.0.0.1:14242/mcp/", "type": "streamableHttp", "headers": { "APP": "Proma" } } } } ``` For remote Mem, replace the URL and add your key: ```json title="~/.proma/agent-workspaces/default/mcp.json" { "servers": { "nowledge-mem": { "url": "https://mem.example.com/mcp/", "type": "streamableHttp", "headers": { "APP": "Proma", "Authorization": "Bearer nmem_your_key", "X-NMEM-API-Key": "nmem_your_key" } } } } ```
### Enable hooks \[step] [#3-enable-hooks-step] Create or edit: ```text ~/.proma/sdk-config/.claude/settings.json ``` Merge this into the `hooks` object. Use absolute paths if your Proma build does not expand `$HOME`. ```json title="~/.proma/sdk-config/.claude/settings.json" { "hooks": { "SessionStart": [ { "matcher": "startup|resume", "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/read-working-memory.py\"", "timeout": 15000 } ] } ], "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/save-to-nmem.py\" --event user-prompt-submit", "timeout": 30000 } ] } ], "Stop": [ { "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/save-to-nmem.py\" --event stop", "timeout": 30000 } ] }, { "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/read-working-memory.py\" --rewake", "timeout": 15000, "async": true, "asyncRewake": true, "rewakeMessage": "Nowledge Mem context refreshed" } ] } ] } } ```
### Restart Proma \[step] [#4-restart-proma-step] Restart Proma after changing MCP, hooks, or skills.
## What Happens [#what-happens] * `UserPromptSubmit` saves the current Proma thread before the next user turn. * `Stop` saves again after a response, so missed or delayed transcript writes are covered. * The save hook reads Proma transcripts from `~/.proma/sdk-config/projects/**/.jsonl` and writes them as source `proma`. * `SessionStart` refreshes the Nowledge Mem block inside `~/.proma/agent-workspaces/default/CLAUDE.md`. * `Stop` asyncRewake can push a compact Working Memory reminder after assistant turns. Proma's current Claude Agent SDK does not reliably inject SessionStart stdout as model context. That is why this connector writes a marked `CLAUDE.md` block instead: ```markdown ... ``` Keep your own Proma instructions outside that block, or in `CLAUDE.md.template`. ## Update [#update] ```bash cd /tmp/nowledge-community git pull cp nowledge-mem-proma-plugin/hooks/save-to-nmem.py ~/.proma/scripts/ cp nowledge-mem-proma-plugin/hooks/read-working-memory.py ~/.proma/scripts/ chmod +x ~/.proma/scripts/save-to-nmem.py ~/.proma/scripts/read-working-memory.py cp -R nowledge-mem-proma-plugin/skills/{read-working-memory,search-memory,distill-memory,save-thread,status} ~/.proma/agent-workspaces/default/skills/ ``` Then merge the latest `nowledge-mem-proma-plugin/hooks/hooks.json` into `~/.proma/sdk-config/.claude/settings.json` and restart Proma. ## Remote Mode [#remote-mode] For MCP, keep the remote URL and key in Proma's `mcp.json`. For hooks and CLI fallback, configure the local `nmem` client once on the machine running Proma: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` ## Troubleshooting [#troubleshooting] **MCP tools do not appear.** Confirm `mcp.json` uses `servers` as the top-level key, then restart Proma. **Startup context does not appear.** Run `python ~/.proma/scripts/read-working-memory.py`, then check `~/.proma/agent-workspaces/default/CLAUDE.md` for the `nowledge-mem:start` block. **Threads do not appear in Mem.** Wait for Proma to finish a turn, then check `~/.proma/logs/nm-hooks.log` and search with `nmem t search "" --source proma`. **Remote MCP works, but hooks do not.** MCP uses Proma's `mcp.json`; hooks use the local `nmem` client config. Set both to the same remote Mem server. ## Related [#related] * [Connectors overview](/docs/integrations) * [Claude Code](/docs/integrations/claude-code) * [Remote access](/docs/remote-access) # Raft (/docs/integrations/raft) Raft can run several named agents on the same computer. Nowledge Mem treats those agents as separate workers, not as one anonymous Codex or Claude session. The setup is deliberately small: connect the AI tool Raft launches first, then set one environment variable on each Raft agent. ## What You Need [#what-you-need] 1. Nowledge Mem is running. 2. The AI tool Raft launches is already connected to Mem, such as [Codex](/docs/integrations/codex-cli) or [Claude Code](/docs/integrations/claude-code). 3. Each Raft worker has a stable role, such as Cindy, Alice, or Reviewer. ## First Useful Setup [#first-useful-setup] Create one Mem AI Identity for the Raft worker: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "Help with onboarding. Explain one step at a time." ``` This creates the Mem AI Identity named Cindy. Its command and environment ID is `cindy`. This command only creates the identity record. It does not make every Codex session use Cindy. The identity is used only where you set `NMEM_AGENT_ID=cindy` or explicitly pass `agent_id="cindy"`. Then open the Raft agent's runtime config and add one environment variable: ```bash NMEM_AGENT_ID=cindy ``` Raft runtime config with a per-agent environment variable That is enough when the Mem AI Identity already has a default space. ## Moving Cindy Later [#moving-cindy-later] The Cindy identity belongs to Mem, not to Raft. If you later move Cindy to another orchestrator, keep `NMEM_AGENT_ID=cindy` and configure the new launcher to pass that environment variable. The AI tool can change too. Cindy can start in Codex and later run in Pi or Claude Code. In that case, update the connector and `--source-app` to the new AI tool, but keep the same Mem AI Identity. If you need a related but different worker, create a new identity such as `cindy-reviewer`. That keeps Cindy stable while letting the new worker evolve its own Rules. ## When To Add Space [#when-to-add-space] `NMEM_SPACE` is optional. It applies to the whole Raft runtime process. Use it only when this Raft agent should override the identity's default space for every Mem read and write during that run: ```bash NMEM_SPACE=onboarding ``` If the agent may work across different projects, leave `NMEM_SPACE` unset and change the active space from Mem or from the command the agent runs. ## Do Not Add A Second Identity By Default [#do-not-add-a-second-identity-by-default] Most users should not set `NMEM_HOST_AGENT_ID`. Use `NMEM_HOST_AGENT_ID` only when an integration author or advanced user needs to map an immutable external worker ID, such as `raft:`, onto a Mem AI Identity. For normal Raft setup, `NMEM_AGENT_ID=cindy` is clearer and enough. The legacy `slock:` prefix remains supported. ## Keep Execution Traces Out of Threads [#keep-execution-traces-out-of-threads] Raft's managed compute uses Codex as a worker, but Raft owns the human conversation through its inbox and message transport. The Codex rollout records control notices and tool execution; replies sent with Raft's messaging tool are not preserved there as normal Codex assistant messages. Importing that rollout would create a misleading Thread. Nowledge Mem therefore skips Codex rollouts whose structured session originator is `raft-daemon`. The legacy `slock-daemon` originator remains supported. This is checked per transcript, so ordinary Codex sessions on the same computer continue to capture automatically. Use Mem skills or MCP inside Raft for Working Memory, recall, and durable saves. Lossless Raft conversation history requires a Raft-native conversation connector; until that boundary is available, do not use `nmem t save --from codex` for a Raft-managed worker. ## What Success Looks Like [#what-success-looks-like] With `nmem` 0.9.0 or later, start a fresh Raft worker session and ask it to check Mem: ```bash nmem --json context --source-app codex ``` Inside the Raft worker, the command should inherit `NMEM_AGENT_ID=cindy` and return the worker identity you configured. If you run the same check from a normal terminal instead, pass the identity explicitly: ```bash nmem --json context --agent-id cindy --source-app codex ``` Memory calls inside the worker use `codex`, `claude-code`, or whichever runtime Raft launched as their source. A future native Raft Thread connector will use `raft` for the human-visible conversation and retain the child runtime as metadata. ## Next [#next] * [Codex](/docs/integrations/codex-cli) * [Claude Code](/docs/integrations/claude-code) * [Customize Connector Behavior](/docs/integrations/customize-behavior) # Raycast (/docs/integrations/raycast) Source: [community/nowledge-mem-raycast](https://github.com/nowledge-co/community/tree/main/nowledge-mem-raycast) This page is the **Nowledge Mem Raycast extension**: keyboard-first commands against Mem over the API. **Raycast AI Chat** history does not ship as a vendor export; bring it into Threads with the community tool and Mem bulk import. See [Import existing conversations](/docs/import-existing-conversations), the [raycast-ai-exporter](https://github.com/daveonkels/raycast-ai-exporter) community tool, and [Bulk import formats](/docs/threads#bulk-import). ## Install [#install] **Raycast Store:** search "Nowledge Mem" or [open the store link](https://www.raycast.com/wey-gu/nowledge-mem) to add the extension directly. **From source** (for development or customization): ```bash git clone https://github.com/nowledge-co/community.git cd community/nowledge-mem-raycast npm install && npm run dev ``` You can connect in two ways: * **Local default:** keep the default `http://127.0.0.1:14242` * **Remote Mem:** set **Server URL** and **API Key** in Raycast preferences, or if you want one shared config for Raycast + CLI + other plugins, run: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` Raycast also supports one optional fixed lane through a **Space** preference. Use it when this Raycast profile always belongs to one named lane such as `Research Agent`. Leave it empty to stay on **Default**. Most commands work with either local or remote Mem. `Edit Working Memory` is the one local-only convenience command because it edits the **Default** Working Memory file on your own machine. Raycast - Nowledge Mem ## Commands [#commands] | Command | What it does | | ----------------------- | --------------------------------------------------------------------------------------------- | | **Search Memories** | Semantic search with relevance scores. When the search box is empty, it shows recent memories | | **Add Memory** | Save a memory with title, content, and importance | | **Read Working Memory** | Read your daily briefing through the Mem API | | **Edit Working Memory** | Edit the Default Working Memory file from Raycast on your local machine | ## Customize Safely [#customize-safely] Raycast is a launcher-style integration, not an agent runtime with its own project instruction file. * Use Raycast preferences for durable changes such as server URL, API key, and fixed space * Do not edit extension source unless you are developing the extension itself For the full host-by-host map, see [Customize Integration Behavior](/docs/integrations/customize-behavior). ## Spaces [#spaces] Raycast is a launcher. The best space model here is one optional fixed lane: * Leave **Space** empty to use the shared `nmem` client space, which is normally **Default** * Set **Space** when this Raycast profile always belongs to one stable lane * Do not expect Raycast to derive per-agent routing on its own When you do set a space, **Search Memories**, **Add Memory**, and **Read Working Memory** all follow it automatically. `Edit Working Memory` stays intentionally local and Default-only. ## Best Flow [#best-flow] * Use **Search Memories** when you want the fastest answer * Use **Add Memory** when you want to save something quickly from the keyboard * Use **Read Working Memory** when you want today’s focus without opening the full app Graph exploration is not part of the Raycast extension. For graph work, use the Mem app or an MCP-capable connector such as Claude Code or Codex. Search Memories Add Memory ## Related [#related] * [Connectors overview](/docs/integrations): native connectors, reusable packages, MCP, and browser capture * [Claude Code](/docs/integrations/claude-code) · [Claude Desktop](/docs/integrations/claude-desktop) · [Codex](/docs/integrations/codex-cli) · [Alma](/docs/integrations/alma) · [OpenClaw](/docs/integrations/openclaw) · [Other Chat AI](/docs/integrations/other-chat-ai) # WorkBuddy × Nowledge Mem (/docs/integrations/workbuddy) Paste this into WorkBuddy: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for WorkBuddy. Verify with nmem status and the Context Bundle or Working Memory check, then run a short session and confirm the thread appears with nmem t list --source workbuddy. ``` WorkBuddy can use Nowledge Mem through the CodeBuddy-compatible plugin system. The plugin gives WorkBuddy startup context, Mem MCP tools, quick commands, and lifecycle hooks that sync WorkBuddy's local transcript into Mem Threads. CodeBuddy's release notes document that WorkBuddy uses an independent `.workbuddy/` configuration directory, separated from CodeBuddy's `.codebuddy/`. The Nowledge Mem connector treats WorkBuddy as its own source: `nmem t sync --from workbuddy`. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * WorkBuddy is installed * `nmem` works on the same machine as WorkBuddy ```bash nmem status ``` If `nmem` exists but rejects `t sync --from workbuddy` or `config mcp show --host workbuddy`, update the CLI before debugging MCP or session sync: * Desktop-bundled CLI: open Mem and run **Settings → Preferences → Developer Tools → Install bundled CLI** again. * PyPI CLI: `python3 -m pip install --user --upgrade nmem-cli` * pipx CLI: `pipx upgrade nmem-cli` If WorkBuddy runs on a different machine from the Mem desktop app, install the standalone CLI there first and point it at your Mem server: ```bash python3 -m pip install --user nmem-cli nmem config client set url https://your-server nmem config client set api-key your-key ``` ## Install The Plugin [#install-the-plugin] Add the Nowledge community marketplace, then install the plugin: ```text /plugin marketplace add nowledge-co/community /plugin install nowledge-mem@nowledge-community ``` The marketplace is backed by `community/.workbuddy-plugin/marketplace.json`. The shared plugin includes: * a WorkBuddy plugin manifest * a local MCP server for `http://127.0.0.1:14242/mcp/` * startup guidance and a Nowledge Mem skill * hooks for `Stop`, `SessionEnd`, `PreCompact`, and `SubagentStop` * quick commands under `/nowledge-mem:*` For remote Mem or authenticated localhost, generate a WorkBuddy MCP block: ```bash nmem config mcp show --host workbuddy ``` Paste the generated `nowledge-mem` server into `~/.workbuddy/.mcp.json`, `$WORKBUDDY_CONFIG_DIR/.mcp.json`, or a project `.mcp.json`. ## Thread Sync [#thread-sync] WorkBuddy passes `session_id` and `transcript_path` to lifecycle hooks. The Nowledge Mem plugin uses those fields instead of guessing where the latest transcript is. After install, the hook runs: ```bash nmem --json t sync --from workbuddy --session-id --session-dir --all-projects --apply ``` That command runs on the WorkBuddy machine, reads the local transcript under `$WORKBUDDY_CONFIG_DIR/projects` or `~/.workbuddy/projects`, and uploads normalized messages to your local or remote Mem server. It is safe to rerun; Mem deduplicates repeated imports. ## Verify [#verify] Start a new WorkBuddy session and ask: ```text Is Nowledge Mem connected? Read my current context. ``` Success means WorkBuddy can call the Nowledge Mem MCP tools and return Context Bundle, Working Memory, or an empty-but-successful memory result. Then finish a short exchange and check: ```bash nmem t list --source workbuddy -n 5 ``` You should see the recent WorkBuddy thread after the hook has run. If hooks do not appear to run, check: ```bash tail -n 50 ~/.workbuddy/logs/nowledge-mem-hook.log ``` If you set `WORKBUDDY_CONFIG_DIR`, check that directory's `logs/nowledge-mem-hook.log` instead. ## Import Older Sessions [#import-older-sessions] Preview first: ```bash nmem t sync --from workbuddy --limit 20 ``` Import when the preview looks right: ```bash nmem t sync --from workbuddy --apply ``` For a custom WorkBuddy config directory: ```bash WORKBUDDY_CONFIG_DIR="$HOME/.my-workbuddy-config" nmem t sync --from workbuddy --apply ``` ## Customize Behavior [#customize-behavior] Use WorkBuddy's own instruction surfaces when available: * `~/.workbuddy/CODEBUDDY.md` or `~/.workbuddy/MEMORY.md` for personal global guidance * project `CODEBUDDY.md` for shared workspace guidance * `.workbuddy/rules/*.md` for structured project rules Do not edit installed plugin files. Marketplace updates can replace them. ## Related [#related] * [Connectors overview](/docs/integrations) * [CodeBuddy guide](/docs/integrations/codebuddy) * [Threads](/docs/threads) * WorkBuddy: [Product page](https://www.codebuddy.cn/work/) * CodeBuddy docs: [Plugin Reference](https://www.codebuddy.ai/docs/cli/plugins-reference) · [Hooks Reference](https://www.codebuddy.ai/docs/cli/hooks) · [MCP](https://www.codebuddy.ai/docs/cli/mcp) # ZCode × Nowledge Mem (/docs/integrations/zcode) Paste this into ZCode: ```text Read https://mem.nowledge.co/SKILL.md and follow the instructions to install or update Nowledge Mem for ZCode. Verify with nmem status and the Context Bundle or Working Memory check, then summarize what changed. ``` ZCode supports MCP servers and `SKILL.md`-based skills. Use those native settings to give ZCode access to your Nowledge Mem knowledge without editing ZCode internals. ## Before You Start [#before-you-start] * Nowledge Mem is running locally, or you have a reachable remote Mem server * ZCode is installed * `nmem` works on the same machine as ZCode ```bash nmem status ``` ## Setup [#setup] Generate the MCP config: ```bash nmem config mcp show --host zcode ``` In ZCode: 1. Open **Settings → MCP Servers**. 2. Add the generated `nowledge-mem` server. ZCode supports configured MCP servers through the settings UI. 3. Open **Settings → Skills**. 4. Import or copy the Nowledge Mem skills. 5. Restart or reload ZCode Agent. ## Verify [#verify] Ask ZCode: ```text Search my memories for recent decisions about this project. ``` Success means the ZCode Agent can call the Nowledge Mem MCP tools and returns results or a clean empty result. ## Session Capture [#session-capture] ZCode has a plugin model that can bundle skills, MCP servers, hooks, and commands. Nowledge Mem does not yet publish a ZCode-native hook package, so this connector does not promise automatic transcript capture. Use handoff summaries when a ZCode conversation should be searchable later. ## Related [#related] * [Connectors overview](/docs/integrations) * [Kimi Code](/docs/integrations/kimi-code) · [MiMo Code](/docs/integrations/mimo-code) · [OMP](/docs/integrations/omp) * ZCode docs: [Plugin](https://zcode.z.ai/en/docs/plugin), [MCP Servers](https://zcode.z.ai/en/docs/mcp-services), [Skills](https://zcode.z.ai/en/docs/skill) # Self-hosted auto-update (/docs/self-host/auto-update) Self-hosted Docker servers can check for new Nowledge Mem releases from the web app. Installing those releases from the browser is opt-in, because it changes the server itself. In-app auto-update requires the official `community/docker` layout and its `nmemctl` helper. If you installed Mem through a NAS app store, a NAS Container Manager template, Portainer, Unraid, or your own custom compose file, the app may still show that a new version exists, but it cannot safely rewrite that deployment for you. Update from the same place you installed it, or use your own Docker image pull/recreate flow. If your Settings page says auto-update is not configured, SSH to the server once and run: ```bash cd community/docker ./nmemctl auto-update enable ``` That command creates a per-deploy updater token, starts a small companion updater container, and lets the web app download and install future Mem images. If `community/docker` or `./nmemctl` is not present on your server, you are not on this update path. The updater companion container needs access to Docker so it can replace the Mem container. That is why browser installs are disabled until you explicitly enable them on the server host. ## What changes in the app [#what-changes-in-the-app] After official auto-update is enabled: * The title bar shows an update badge when a newer server image is available. * Settings shows the current server version, the latest available version, and a link to the release notes. * Download pulls the image in the background without taking Mem offline. * Install takes a pre-upgrade snapshot, recreates the container, and reconnects the page when the server is back. Every install keeps the last three pre-upgrade snapshots in `./cache`. If the new image fails to boot, Settings shows the snapshot path so you can restore it from the server: ```bash ./nmemctl import --force ``` ## Useful commands [#useful-commands] ```bash ./nmemctl auto-update status ./nmemctl auto-update rotate ./nmemctl auto-update upgrade ./nmemctl auto-update disable ``` * `status` shows whether auto-update is enabled and which snapshots are retained. * `rotate` replaces the updater token. * `upgrade` updates the companion updater container itself. * `disable` removes the updater container but keeps existing snapshots. ## Remote installs [#remote-installs] Checking for updates is always safe and available from the web UI. Download and Install are server-side operations, so they are protected by the server's remote-operations setting. `./nmemctl auto-update enable` configures this for the normal web-upgrade flow. If you turned it off later, enable **Remote server upgrades** from Settings when you are on a trusted private network, or run upgrades from SSH: ```bash ./nmemctl upgrade ``` ## More detail [#more-detail] For the full Docker deployment guide, including backup, memory sizing, TLS, and migration, see [Docker Deployment](/docs/docker). # Search Through Time (/docs/use-cases/bi-temporal) ## The Problem [#the-problem] The board asks: *"Why did you choose React Native over Flutter in Q1?"* You remember the decision. But you remember it through the lens of everything that happened after: the pivot, the performance issues, the rewrite. You need to answer: **What did you know THEN?** > "I can search my notes for 'React Native'. But I can't search for 'what I believed in March about React Native'." ## The Solution [#the-solution] Nowledge Mem uses **bi-temporal search**: two dimensions of time that let you find exactly what you're looking for. Bi-temporal Search **Event Time**: When did the thing actually happen? **Record Time**: When did you capture it? Search either. Search both. Travel through your own history. Search Query Details Blog: [How We Taught Nowledge Mem to Forget](https://nowledge-labs.ai/blog/memory-decay-temporal). Documentation about [Search & Relevance](/docs/search-relevance). ## How It Works [#how-it-works] ### Natural Language Queries [#natural-language-queries] Just search naturally. Nowledge Mem understands temporal intent: > "What did I decide about React Native in Q1 2024?" The system: 1. Detects temporal intent: "Q1 2024" 2. Searches memories where the **event** occurred in that period 3. Returns results with original context No special syntax needed. ### Explicit Temporal Filters [#explicit-temporal-filters] For precise control, use the advanced search: | Filter | Meaning | Example | | -------------------- | --------------------- | ---------- | | **Event Date From** | Event happened after | 2024-01-01 | | **Event Date To** | Event happened before | 2024-03-31 | | **Record Date From** | Written down after | 2024-01-01 | | **Record Date To** | Written down before | 2024-12-31 | **Power Query Example:** > Event Time: March 2024 > Record Time: Any Returns: *"All memories about events from March 2024, regardless of when you recorded them."* ### Flexible Date Precision [#flexible-date-precision] Nowledge Mem handles flexible dates: * **Year**: "2024" -> Matches anything in 2024 * **Month**: "2024-03" -> Matches March 2024 * **Day**: "2024-03-15" -> Matches that specific day The system preserves your original precision and displays accordingly. ## Knowledge Evolution [#knowledge-evolution] Bi-temporal search gets even more powerful with Knowledge Evolution. Background Intelligence automatically detects when your thinking on a topic changes: **Tuesday**: You save "Using PostgreSQL for the new service." **Thursday**: You mention CockroachDB as a migration target. **Friday**: Background Intelligence links them with an EVOLVES relationship and flags the tension. Now when you search "database decisions," you don't just get isolated memories. You get the **evolution chain**: the original decision, the update, and the relationship between them. You can see exactly how your thinking shifted and when. Evolution types: * **Replaces**: Newer information makes older obsolete * **Enriches**: Newer adds detail to older * **Confirms**: Same conclusion from a different source * **Challenges**: Contradictory information flagged for review ## Real Examples [#real-examples] ### Board Retrospective [#board-retrospective] > **Query**: "architecture decisions in Q1 2024" > > **Result**: Original decision memos with Q1 context, plus evolution chains showing how decisions changed after ### Compliance Audit [#compliance-audit] > **Query**: "security policies before the incident" > > **Result**: What policies existed before the breach, with record timestamps proving when they were documented ### Project Post-Mortem [#project-post-mortem] > **Query**: "project-x assumptions from kickoff" > > **Result**: Original assumptions that turned out wrong, linked to the later insights that proved them wrong ## Knowledge Graph + Time [#knowledge-graph--time] Your graph view has a **timeline slider** that filters nodes and edges by date range. Set the range to "March 2024" and see: * Only entities that existed then * Only connections that were known then * The state of your knowledge at that moment Drag the slider forward and watch your understanding evolve. Play the animation to see knowledge accumulate over time. ## How Memory Decay Works [#how-memory-decay-works] Not all memories age equally. Like your brain, Nowledge Mem: * **Prioritizes recent memories** by default (30-day half-life) * **Boosts frequently accessed** memories (logarithmic scaling) * **Respects importance** scores you set (importance floor prevents full decay) * **Learns from your behavior** (clicks, dwell time) This means casual searches surface fresh, relevant results, but temporal searches bypass decay to find exactly what you asked for. Temporal intent detection requires **Deep Mode** search. In Fast Mode, temporal references are matched by keywords only. Enable Deep Mode for queries like "recently working on" or "decisions from last quarter." See [Search & Relevance](/docs/search-relevance) for the full technical breakdown of how scoring, decay, and temporal matching work. ## The Two Times [#the-two-times] Understanding the difference is key: | Question | Which Time? | | ------------------------------------ | ----------- | | "What did I decide in March?" | Event Time | | "What did I write last week?" | Record Time | | "Show recent notes about old events" | Both | | "What did I know before the pivot?" | Event Time | Most searches use **event time** because you're asking about when things happened. **Record time** is useful for: * Finding recent captures * Reviewing what you've been documenting * Auditing when knowledge was recorded ## Why This Matters [#why-this-matters] Traditional search finds content. Temporal search finds **context**. Knowledge Evolution finds **the story**. > "We didn't make a bad decision. We made the best decision with what we knew. Here's the proof. And here's exactly when and why our thinking changed." Your memories are time-stamped, version-controlled, and historically accurate. ## Next Steps [#next-steps] * [Own Your Knowledge](/docs/use-cases/shared-memory) -> Use any tool without losing context * [See Your Expertise](/docs/use-cases/expertise-graph) -> Visualize your knowledge * [Background Intelligence](/docs/advanced-features) -> Knowledge graph capabilities # See Your Expertise (/docs/use-cases/expertise-graph) ## The Problem [#the-problem] You've been learning for years. Building expertise. Accumulating knowledge. But can you see it? > I know I'm good at... stuff. Technical stuff. But if someone asked me to describe my expertise, I'd struggle. It's all intuition. Nothing concrete. Your knowledge is invisible. Scattered across memories, notes, conversations. You can't see the patterns. The connections. The clusters of expertise. ## The Solution [#the-solution] Nowledge Mem visualizes your knowledge as a **living graph**. Nodes are your memories and entities. Edges are relationships. And the graph **builds itself**: Background Intelligence automatically extracts entities and relationships from your memories overnight. Run **community detection** and watch your expertise clusters emerge: Expertise Graph ## How It Works [#how-it-works]
### The Graph Builds Itself [#the-graph-builds-itself-step] You don't need to manually tag or categorize anything. Background Intelligence reads your memories and extracts: * **Entities**: Technologies, people, concepts, projects * **Relationships**: How they connect to each other * **Evolution chains**: How your thinking on a topic has changed This happens automatically. Save memories through any channel (auto-sync, browser extension, Timeline, `/sum`) and the graph grows on its own. Automatic entity extraction requires a configured Remote LLM and the appropriate license for your build.
### Run Community Detection [#run-community-detection-step] In the right panel, find **Graph Algo** and click Compute under **Clustering**. The Louvain algorithm analyzes your knowledge structure and finds natural clusters: | Community | Size | Theme | | ------------------- | ----------- | ----------------------------- | | Distributed Systems | 87 memories | Backend architecture, scaling | | Team Leadership | 45 memories | Mentoring, communication | | Performance | 62 memories | Optimization, profiling | | Side Projects | 23 memories | Creative experiments | Each cluster gets a colored "bubble" around its nodes.
### Travel Through Time [#travel-through-time-step] The **timeline slider** at the bottom of the graph lets you filter by date range. Drag to "January 2024" and see your knowledge at that point. Drag forward and watch new clusters form, existing ones grow, and connections multiply. Play the animation to watch your expertise evolve over months. See when a new interest emerged, when it connected to existing knowledge, and when it grew into a full cluster.
### Explore and Discover [#explore-and-discover-step] Navigate the graph: * **Click** any node to see its details * **Double-click** to expand neighbors * **Shift+drag** to lasso-select multiple nodes * **Press C** to toggle community bubbles * **Press E** to expand selected node's neighbors Find patterns you never noticed: > Every leadership memory links back to debugging sessions. I lead by teaching debugging.
## What You'll Discover [#what-youll-discover] ### Expertise Clusters [#expertise-clusters] Community detection reveals where your knowledge naturally groups: * **Core strengths**: Large, dense clusters * **Emerging areas**: Small but growing clusters * **Bridges**: Nodes that connect multiple clusters (often your most unique skills) ### Knowledge Evolution [#knowledge-evolution] Background Intelligence tracks how your thinking changes: * **Tuesday**: "Using PostgreSQL for the new service" * **Thursday**: "Considering CockroachDB for migration" * **Friday briefing**: "Your database thinking is evolving" These evolution chains appear as linked nodes in the graph. You can see exactly where your opinions shifted and follow the trail. ### Hidden Patterns [#hidden-patterns] Explore and find: * Recurring themes you never consciously tracked * Connections between seemingly unrelated projects * Your unique perspective and approach * Gaps between related topics ## Asking AI About Your Graph [#asking-ai-about-your-graph] With your graph in view, ask AI Now to interpret it: > Based on my knowledge graph, what career paths fit me best? AI Now synthesizes: > Your memories show a unique intersection of deep systems knowledge with teaching ability. Your most central concepts (event-driven architecture, debugging) connect to both technical and leadership clusters. Consider: Staff Engineer, Developer Advocate, or Engineering Manager with technical focus. Other questions to try: * "What are my strongest expertise areas?" * "Where are the gaps in my knowledge?" * "What topics should I explore next?" * "How has my focus shifted over time?" ## The Compound Effect [#the-compound-effect] More memories = richer graph = deeper insights. **After 1 month:** > I can see my main topics, but clusters are small **After 6 months:** > Clear expertise areas. Unexpected connections emerging. Background Intelligence is finding patterns I missed. **After 1 year:** > I can literally see how my thinking has evolved. The connections I made last year laid groundwork for this year. **For performance reviews:** > I explored my graph before the review. Had concrete examples of growth across every dimension. ## Next Steps [#next-steps] * [Background Intelligence](/docs/advanced-features) -> How the graph grows automatically * [Own Your Knowledge](/docs/use-cases/shared-memory) -> Use any tool without losing context * [Search Through Time](/docs/use-cases/bi-temporal) -> Temporal queries and evolution chains # Overview (/docs/use-cases) Nowledge Mem learns from your work with AI. It captures conversations through the right path for each supported tool, keeps sessions and memories searchable, and builds a knowledge graph that grows overnight. Connected tools can start with richer context. Pick the use case that matches the problem you want to solve first. You do not need every part of Mem on day one. Tell Claude once. Cursor can pick it up too. One knowledge base across the AI tools you connect to Mem. Native save paths, connector live capture, local backfill, and browser capture keep important conversations searchable. The board asks why you chose React Native. Find what you believed then, not what you know now. Obsidian, Notion, PDFs, Word docs. One search covers all your knowledge sources. The graph builds itself from your memories. Community detection reveals expertise clusters you didn't know you had. A personal AI agent that can use your saved knowledge, files, and enabled plugins. Deep research, file analysis, and presentations on your machine. ## Three Things That Change [#three-things-that-change] **It captures through the right path.** The browser extension grabs insights and thread backups from supported web AI chats. Native connectors capture new coding-agent work where the host supports hooks, local import backfills older sessions, and the Timeline is always there for direct capture. **It learns while you sleep.** Background Intelligence detects when your thinking evolves, synthesizes reference articles from scattered memories, and flags contradictions. Your morning Working Memory briefing tells your AI tools what you're working on before you say anything. **It goes where you go.** Native integrations, reusable workflow packages, and direct MCP all connect back to the same memory system. Switch tools freely. Your knowledge stays. ## How It Works [#how-it-works] 1. **Capture** -- browser capture, native save paths, connector live capture, local backfill, or direct Timeline input 2. **Connect** -- the system links it to everything you already know 3. **Grow** -- Background Intelligence builds evolution chains, crystals, and flags overnight 4. **Use** -- connected tools can find it when it's relevant Your knowledge compounds in Mem, independent of any single tool. ## Ready to Start? [#ready-to-start] Pick a use case above if one problem stands out. If not, go back to [Start Here](/docs/start-here) or [Getting Started](/docs/getting-started) and prove one small workflow first. # Your Notes, Everywhere (/docs/use-cases/notes-everywhere) ## The Problem [#the-problem] You've been taking notes for years. Obsidian. Notion. Maybe both. Thousands of entries. Carefully tagged. Extensively linked. And yet... > I know I wrote about this. I just can't find it. The search is useless. The tags don't help. Worse: Your AI assistant has no idea any of this exists. You're explaining context that's already in your notes. Every. Single. Time. ## The Solution [#the-solution] We don't replace your note app. We **wire it into your knowledge**. Keep using Obsidian, Notion, Apple Notes or folders of Markdown files exactly as you do now. Nowledge Mem connects to them, making your notes searchable alongside your memories in AI Now and across the AI tools you connect to Mem. And with the **Library**, you can drop PDFs, Word documents, and presentations in too. Everything becomes searchable from one place. Notes Everywhere ## How It Works [#how-it-works]
### Connect Your Notes [#connect-your-notes-step] **Obsidian:** 1. Open AI Now in Nowledge Mem 2. Go to **Plugins** -> Enable **Obsidian** 3. Set your vault path (e.g., `/Users/you/Documents/ObsidianVault`) 4. Done. AI Now can now search your vault Notes Everywhere **Notion:** 1. Open AI Now -> **Plugins** -> Enable **Notion** 2. Click **Connect with Notion** 3. Authorize access in the browser popup 4. Your workspace is now accessible
### Import Documents to the Library [#import-documents-to-the-library-step] Drop files directly into the Timeline input or open the Library view: | Format | Extensions | What Happens | | ----------------- | ----------- | -------------------------------------------- | | **PDF** | .pdf | Text extracted, split into segments, indexed | | **Word** | .docx, .doc | Parsed to text, segmented, indexed | | **Presentations** | .pptx | Slide content extracted and indexed | | **Markdown** | .md | Parsed and indexed directly | Once indexed, document content is searchable alongside your memories and notes.
### Search Across Everything [#search-across-everything-step] Ask AI Now any question: > What do my notes say about quantum computing? AI Now: 1. Searches your Obsidian vault 2. Searches your Notion workspace 3. Searches your Nowledge memories 4. Searches your Library documents 5. Combines and synthesizes results One question. All your knowledge sources.
### Distill Into Memories [#distill-into-memories-step] Found valuable notes? Turn them into permanent memories: > Distill the key insights from these quantum computing notes AI Now creates: * **Insight**: "Quantum error correction requires O(n^2) qubits" * **Decision**: "Focus on NISQ algorithms for near-term research" * **Fact**: "IBM claimed quantum advantage Dec 2023" These memories are now: * Searchable with semantic understanding * Connected in the knowledge graph * Accessible across the AI tools you connect to Mem * Part of your Working Memory briefing when relevant
## Obsidian Integration [#obsidian-integration] ### Setup [#setup]
#### Open Nowledge Mem [#open-nowledge-mem-step] Open the Nowledge Mem app.
#### Click the AI Now tab [#click-the-ai-now-tab-step] Select the **AI Now** tab in the sidebar.
#### Go to Plugins [#go-to-plugins-step] Open **Plugins** in the sidebar.
#### Enable Obsidian [#enable-obsidian-step] Find **Obsidian** and toggle it on.
#### Enter your vault path [#enter-your-vault-path-step] Example: `/Users/yourname/Documents/ObsidianVault`
### What You Can Do [#what-you-can-do] Once connected: * Search notes by content: *"Find my notes about machine learning"* * Read specific notes: *"Show me the note about project kickoff"* * Reference in context: *"Based on my Obsidian notes about X, help me..."* Your vault is read locally. Notes are never uploaded anywhere. Nowledge Mem just reads the files on your machine. ## Notion Integration [#notion-integration] ### Setup [#setup-1]
#### Open AI Now Plugins [#open-ai-now-plugins-step] Open AI Now → **Plugins**.
#### Connect Notion [#connect-notion-step] Find **Notion** and click **Connect**.
#### Authorize in the browser [#authorize-in-the-browser-step] Complete authorization in the browser popup.
#### Select workspaces [#select-workspaces-step] Select the workspaces you want to connect.
### What You Can Do [#what-you-can-do-1] * Search your workspace: *"Find pages about quarterly planning"* * Read page content: *"What's in my Product Roadmap page?"* * Cross-reference: *"Compare my Notion notes with my memories about X"* * Deep Research with both public information and private knowledge: *"What's the latest on quantum computing?"* Notion uses secure OAuth. You control exactly which pages Nowledge Mem can access. Revoke anytime from Notion settings. ## Built-in Connectors [#built-in-connectors] Some tools have Nowledge Mem built in: * **DeepChat**: Toggle Nowledge Mem in settings. Your memories become available in every chat. * **LobeHub**: Install from the marketplace. Full MCP integration. * **Apple Notes (macOS)**: Search your Apple Notes through AI Now after enabling the built-in plugin. Join the [Community](/docs/community) to request connectors. ## Next Steps [#next-steps] * [AI Now](/docs/ai-now) -> Learn what else AI Now can do * [Library](/docs/library) -> Import and search documents * [See Your Expertise](/docs/use-cases/expertise-graph) -> Visualize your knowledge graph * [Connectors](/docs/integrations) -> Full setup guides # Never Lose a Session (/docs/use-cases/session-backup) ## The Problem [#the-problem] You just had an epic debugging session. Three hours with Claude Code. You found a race condition, traced it through 15 files, built a bulletproof fix with tests. But AI conversations are ephemeral. Context gets compacted, token limits hit, and sessions expire. That 200-message thread? The early context is already gone. > "I solved this exact problem before. I just can't remember how. Or where. Or when." ## The Solution [#the-solution] Your sessions can flow into Mem through the right path for each tool. Native integrations save real session transcripts where the host supports it. Local import backfills older coding-agent sessions from disk. Browser conversations from ChatGPT, Claude, and Gemini are captured by the extension. You only need exports when that is the source you already have. When you're ready, distill a thread into permanent, searchable, graph-connected memories. Pick one conversation you already care about, get it into Threads, then distill one useful memory from it. Once you can find both the original thread and the distilled takeaway later, this workflow is working. ## How It Works [#how-it-works]
### Sessions Reach Mem Through Different Paths [#sessions-reach-mem-through-different-paths-step] **Native live capture (Claude Code, Codex, Gemini CLI, OpenCode):** Dedicated connectors save the real transcript from the machine where the agent runs. For OpenCode, the plugin captures after OpenCode reports idle and flushes before compaction. **Local backfill (Claude Code, Cursor, Codex, OpenCode):** Nowledge Mem can scan local coding sessions from disk when you want older history in Threads. Use the import view or run `nmem t sync --from ` on the machine that stores those sessions. **Native handoff-first paths (Droid, Cursor):** Some tools already have a dedicated native package, but intentionally stop at resumable handoff summaries until a real transcript importer exists. That still gives you cross-session continuity without pretending to store the full recorded conversation. **Browser capture (ChatGPT, Gemini, Claude Web):** The Exchange v2 extension captures conversations from supported web AI chat platforms. Insights and thread backups flow into Mem as you chat. **Manual distill or handoff:** ``` /sum -> Distill durable insights into memories /save -> Create a resumable handoff or tool-specific save path, depending on the integration ```
### Distill Into Permanent Knowledge [#distill-into-permanent-knowledge-step] Open a saved thread and click **Distill**. The AI reads the entire conversation and extracts: * **Decisions**: "Chose sliding window over token bucket because..." * **Insights**: "Race conditions in async callbacks need mutex locks" * **Patterns**: "Testing time-based bugs requires mock clocks" * **Facts**: "Redis SETNX provides atomic lock acquisition" Each becomes a standalone, searchable memory with proper labels.
### Background Intelligence Connects It [#background-intelligence-connects-it-step] Your new memories don't sit in isolation. Background Intelligence: * Links them to previous work on the same codebase * Detects if they update or contradict earlier decisions * Connects them to related entities in the knowledge graph * Surfaces them in your next morning's Working Memory briefing Three months later, a colleague hits the same bug. Your briefing mentions it before they even ask.
### Search Anytime [#search-anytime-step] Three months later, similar bug appears: > Search: "payment race condition" Nowledge Mem returns the full context: the problem, the debugging steps, the solution, the test approach. No more re-solving solved problems.
## What Gets Captured [#what-gets-captured] | Source | How | What You Get | | ------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | | **Claude Code** | Native connector save or local auto-sync | Full session with code context | | **Gemini CLI** | Native extension `save-thread` | Real recorded Gemini session | | **Droid** | Native connector `save-handoff` | Resumable handoff summaries inside Droid, with honest boundaries around full session import | | **Codex** | Native connector Stop hook or local auto-sync | Full session with code context | | **Cursor** | Plugin `save-handoff`, local auto-sync, or manual import | Resumable handoff summaries in the plugin, plus local conversation import on your machine | | **OpenCode** | Native plugin idle-event capture; CLI/import backfill for older sessions | New conversations as they happen, plus searchable history when imported | | **ChatGPT** | Browser extension (auto-capture) | Insights and full thread backups from web chats | | **Claude Web** | Browser extension (auto-capture) | Insights and full thread backups from web chats | | **Gemini** | Browser extension (auto-capture) | Insights and full thread backups from web chats | | **More supported web AI chats** | Browser extension | The same capture model on supported sites | ## What Gets Extracted [#what-gets-extracted] When you distill a thread, the AI creates memories categorized by type: | Type | Example | Labels | | -------------- | --------------------------------------- | ---------------------- | | **Decision** | "Used Redis for distributed locking" | decision, architecture | | **Insight** | "Async callbacks need careful ordering" | insight, debugging | | **Procedure** | "Steps to reproduce race conditions" | procedure, testing | | **Fact** | "SETNX returns 1 if key was set" | fact, redis | | **Experience** | "Debugging session on payment service" | experience, project | ## The Compound Effect [#the-compound-effect] One thread saved is useful. Ten threads saved is a knowledge base. A hundred threads? That's institutional memory. > "Junior dev hit the same bug today. Sent them my memory. They fixed it in 20 minutes instead of 3 hours." Your debugging sessions aren't just conversations. They're training data for your future self. ## Pro Tips [#pro-tips] You don't need to distill every thread. Save important sessions: the breakthroughs, the architectural decisions, the hard-won solutions. For sensitive codebases, review what you're saving. Threads might contain proprietary code or credentials. ## Next Steps [#next-steps] * [Own Your Knowledge](/docs/use-cases/shared-memory) -> Use any tool without losing context * [Search Through Time](/docs/use-cases/bi-temporal) -> Find memories from specific time periods * [Connectors](/docs/integrations) -> Setup guides for each tool # Own Your Knowledge (/docs/use-cases/shared-memory) ## The Problem [#the-problem] You told Claude Code about your project architecture last week. Today, you're explaining it again to Cursor. Tomorrow, you'll try the new tool everyone's talking about, and start from scratch. This isn't a memory problem. It's a lock-in problem. Your knowledge is trapped inside whichever tool you used last. > "I already explained this. Why do I have to start over in a different tool?" ## The Solution [#the-solution] Nowledge Mem is a knowledge layer that sits between you and the AI tools you connect to Mem. It captures your insights automatically, brings sessions and memories back into one searchable system, and writes a daily briefing so supported tools can start with richer context. Use the setup path that matches your tool. The memory model stays the same. If this is the problem you want to solve first, save one decision in Mem, connect the tool you use most, then ask a second tool about that same topic later. When it can recall the earlier decision, the loop is working. Shared Memory ## How It Works [#how-it-works]
### Connect The Right Way For Each Tool [#connect-the-right-way-for-each-tool-step] * **Dedicated integrations** for Claude Code, Grok Build, Codex, Gemini CLI, OpenClaw, Hermes Agent, Alma, Cursor, Droid, OpenCode, and Copilot CLI give you the best first-time experience. * **Reusable workflow packages** cover agent environments that do not have a dedicated package yet. * **Direct MCP** remains the fallback when a client has no dedicated package. For many coding agents, the fastest reusable path is still: ```bash npx skills add nowledge-co/community/nowledge-mem-npx-skills ``` After setup, your agent can read your briefing at session start, search your knowledge mid-task, and preserve durable insights.
### Capture Happens Automatically [#capture-happens-automatically-step] You don't need to remember to save. Mem captures from multiple channels: **Browser Extension (Exchange v2):** The extension monitors your AI chats on supported web AI chat platforms. Insights are captured automatically as you work. **Session Capture and Sync:** Native integrations can capture new coding-agent work where the runtime supports hooks. Local import and `nmem t sync` backfill older sessions from disk. **Timeline Input:** Type a thought, paste a URL, drop a file. For the times you want to save something specific. **Manual Commands:** ``` /sum -> Summarize this conversation into memories /save -> Create the tool's save or handoff action, depending on the integration ```
### Supported Tools Start Informed [#supported-tools-start-informed-step] Each morning, Background Intelligence writes a Working Memory briefing. Connected tools can load the right briefing for the active space through their own path at session start. Your agent already knows: * What you're working on * Decisions you made recently * Open questions and contradictions * How your thinking has evolved No re-explanation needed. Open Claude Code at 9 AM and it picks up where you left off.
### Switch Tools Freely [#switch-tools-freely-step] New tool? Connect it to Mem through the best path it supports. Then it can work from the same shared context. **Example:** You saved: *"Architecture decision: Using Redis for session management because..."* Later, in Cursor: *"Help me add session handling"* Cursor searches your knowledge, finds the Redis decision, applies the same pattern. No re-explanation needed.
## Real Example [#real-example] **Without Nowledge Mem:** > You: "Help me implement rate limiting" > > Claude: "What kind? Token bucket? Sliding window? What's your use case?" > > You: *\[Explains for the 5th time this month]* **With Nowledge Mem:** > You: "Help me implement rate limiting" > > Claude: *\[Reads your Working Memory briefing, searches your memories]* "Based on your decision last month to use sliding window rate limiting for the payment service, here's an implementation matching your Redis patterns..." ## What Gets Connected [#what-gets-connected] | Channel | How It Works | What Gets Captured | | -------------------------------- | ------------------------------ | ---------------------------------------------------------------------- | | **Native integrations** | Tool-specific package | Working Memory, recall, distill, and the right save path for that tool | | **Reusable workflow packages** | Shared prompts or skills | Working Memory, search, save, distill | | **Browser Extension** | Auto-capture from AI chats | Insights from supported web AI chat platforms | | **Session capture and backfill** | Native hooks plus local import | Claude Code, Cursor, Codex, OpenCode sessions | | **MCP** | Direct protocol connection | Any MCP-compatible tool | | **Claude Desktop** | One-click extension | Full integration | | **Built-in** | Toggle in settings | DeepChat, LobeHub | ## The Compound Effect [#the-compound-effect] A few weeks in, any new tool you connect already knows how you work. Your preferences persist across tools. Your decisions compound. Every insight you've ever saved is available to every tool you'll ever use. The value lives in Mem, not in any single tool. ## Next Steps [#next-steps] * [Never Lose a Session](/docs/use-cases/session-backup) -> Auto-sync and backup AI conversations * [Search Through Time](/docs/use-cases/bi-temporal) -> Find what you knew when * [Connectors](/docs/integrations) -> Connect all your tools # 后台智能 (/docs/zh/advanced-features) 后台智能让 Mem 不只是把内容存下来。 你保存了记忆、对话和文档之后,系统还会继续在后台工作:把相关想法连接起来、找出矛盾、综合出知识结晶,并写出一份你的工具可以读取的每日简报。 一月,你保存了一个使用 PostgreSQL 的决策。七月,你又记录了正在迁移到 CockroachDB。你没有专门回头整理过这件事,但 Mem 会把两者连起来,追踪这段变化。下次你搜索其中任意一个主题时,都能看到这条思路是怎样一路演变过来的。 这些整理发生在后台。你下次打开应用时,相关连接就已经在那里了。 不要一开始就试图验证后台智能的所有能力。更好的第一步是:先积累一些真实内容,然后确认 Mem 至少出现了一个真正有帮助的结果,比如一条相关的晨间简报、一条你自己没主动想到的连接,或一个被指出来的矛盾。
知识图谱 后台智能需要已配置的远程 LLM,以及你的当前版本所对应的许可能力。在 **设置 > 知识处理** 中启用。 ## 第一个有用的信号 [#第一个有用的信号] 当 Mem 开始出现下面这些结果时,就说明后台智能已经开始真正帮上忙了: * 它指出了你自己未必会注意到的矛盾 * 它把跨时间的相关工作聚到一起 * 它写出的晨间简报确实和你今天要做的事相关 ## 知识图谱 [#知识图谱] 你保存的每条记忆都会变成图谱里的一个节点。系统提取人物、技术、概念和项目,把它们和你已有的知识关联起来。 结果是:搜索"分布式系统"就能找到你关于"Node.js 微服务"的记忆。用词不同,含义相通。 启用后台智能后,知识图谱提取会为新记忆自动运行。你也可以为旧记忆手动触发。 ### 提取内容 [#提取内容] 当一条记忆被处理时,LLM 会识别: * **实体**: 人物、技术、概念、组织、项目 * **关系**: 实体之间如何相互关联 * **与现有知识的连接**: 与图谱中已有记忆的关联 你可以为任何记忆触发提取,方法是点击记忆卡上的 **Knowledge Graph** 按钮。 Distill with Knowledge Graph ### 知识演变 [#知识演变] 当你保存了一个之前写过的主题的新内容,系统检测到关系并创建版本链接: | 链接类型 | 发生了什么 | 示例 | | ------ | ------ | ---------------------------------- | | **替换** | 你改变了想法 | "使用 CockroachDB"替换"使用 PostgreSQL" | | **丰富** | 你学到了更多 | "React 19 新增编译器"丰富了"React 18 并发渲染" | | **确认** | 独立的认同 | 两篇独立评测推荐了同一个库 | | **挑战** | 检测到矛盾 | 你三月份的评估与十月份的结论不一致 | 你可以追踪对任何主题的理解如何随时间变化。看到你在哪里改变了想法。理解原因。 ### 社区检测 [#社区检测] 图算法会发现你知识里的自然聚类,也就是一组组彼此紧密相关的记忆。你的图谱里可能会慢慢浮现出“React 模式”“API 设计”“数据库优化”这样的主题区块,不需要你自己手动画出来。 在 **图视图** 中,点击 **计算** 运行社区检测。 Graph Algorithm Compute ## 可视化探索 [#可视化探索] 你的知识,呈现为交互式网络。点击一条记忆,查看与它连接的一切。放大集群。追踪你从未想过要比较的主题之间的连接。
时间线滑块按日期范围过滤。观察某个领域的知识在数周或数月内如何增长。 ## 系统会发现什么 [#系统会发现什么] 图谱是基础。在此之上,后台智能主动分析你的知识,并将发现呈现在 Timeline 中。 ### 洞察 [#洞察] 最有用的洞察,往往是你自己原本不会主动去找的连接。 * 跨领域关联:三月你记录了 JWT refresh token 在支付服务中引发竞态条件。九月你在新认证服务中选了同样的 token 轮换方案。系统发现了:同一个失败模式,不同项目。 * 时间模式:"你在两个月内第三次重新审视这个数据库迁移决策。"也许是时候做决定了。 * 被遗忘的上下文:"你三月份的评估与十月份选择的方案相矛盾。"系统记住你写过什么,即使你自己忘了。 每条洞察都引用其来源。你可以自己追溯推理过程。 一个改变你思维方式的连接,胜过十个显而易见的陈述。严格的质量门控把噪音挡在外面。 ### 知识结晶 [#知识结晶] 三个月内保存的五条关于 React 模式的记忆。散落在你的时间线中。难以拼凑。 知识结晶将它们综合为一篇参考文章。标注来源。新信息到达时自动更新。 你不需要专门去请求知识结晶。当系统手里已经有足够素材,可以整理出一篇真正有用的参考内容时,它就会自己出现。 ### 标记 [#标记] 有时系统发现的是问题,而非连接: | 标记类型 | 含义 | 示例 | | ------- | ---------- | -------------------------------------- | | **矛盾** | 两条记忆存在分歧 | "使用 JWT token" vs "Session cookie 更安全" | | **过时** | 更新的知识取代了旧的 | 一份 6 个月前的部署指南,已被最近的笔记覆盖 | | **待验证** | 强烈的论断,无佐证 | 一条没有支持证据的单独断言 | 每个标记出现在 Timeline 中。你可以忽略、确认或链接到解决方案。 ### 工作记忆简报 [#工作记忆简报] 每天早上,Mem 会为当前分区写出一份 Working Memory 简报: * 基于近期活动的活跃话题 * 需要你关注的未解决标记 * 知识库的近期变化 * 基于频率和近期度的优先事项 已连接的 AI 工具会在会话开始时加载这份简报。MCP、原生连接、其他打包好的接入方式都可以读取它。 Default 分区仍然保留兼容文件 `~/ai-now/memory.md`。如果你打开了 [Spaces](/zh/docs/spaces),其他分区也会通过同样的 Mem 接口各自拥有一份 Working Memory 简报。 你仍然可以直接编辑 Working Memory。你的改动会被保留。 你的 AI 工具可以通过 MCP、原生连接或其他打包好的接入方式加载 Working Memory。只要工具知道当前处于哪个 space,就会自动读取对应那一份简报。 ## 配置 [#配置] 在 **设置 > 知识处理** 中控制后台处理: Memory Processing Settings | 设置 | 默认值 | 控制内容 | | -------- | ------ | --------------- | | **后台智能** | 关 | 所有后台处理的主开关 | | **每日简报** | 开(启用时) | 每日工作记忆简报生成 | | **简报时间** | 8 | 每日简报运行的时间(本地时间) | | **自动提取** | 开(启用时) | 新记忆的自动知识图谱丰富 | 在 Linux 服务器上,通过 CLI 配置: ```bash nmem config settings set backgroundIntelligence true nmem config settings set autoDailyBriefing true nmem config settings set briefingHour 8 ``` ## 下一步 [#下一步] * **[记忆](/zh/docs/memories)**:创建、搜索、组织和连接你的知识 * **[对话](/zh/docs/threads)**:捕获、浏览和提炼 AI 对话 * **[快速入门](/zh/docs/getting-started)**: Timeline、文档导入和所有添加知识的方式 * **[连接](/zh/docs/integrations)**: 通过原生连接、复用包、MCP 和浏览器捕获连接 AI 工具 * **[故障排除](/zh/docs/troubleshooting)**: 常见问题的解决方案 # 上下文 (/docs/zh/ai-context) 上下文用来检查一个接入的 AI 开始工作前会看到什么:你是谁、它使用哪个 AI 档案、能用哪些记忆、要遵守哪些规则,以及当前的工作记忆。 可以把它理解成 Mem 递给 AI 工具的“开场卡片”。 ## 它和其他界面是什么关系 [#它和其他界面是什么关系] Memories、Threads、Library、Skills、Spaces 和 AI Now 各自负责不同事情。上下文不是替代它们,而是把这些信息组合成某一次 AI 工作前会收到的内容。 | 界面 | 作用 | | -------------------------------------- | ------------------------------ | | **Memories** | 值得长期保存的事实、偏好、决策、计划、流程、学习、事件和背景 | | **Threads** | 已保存的对话和完整讨论历史 | | **Library** | 文件、文档、来源和生成的资料 | | **[Skills](/zh/docs/concepts/skills)** | AI 反复执行某类任务时应该采用的方法 | | **Spaces** | 某个项目、工具或长期 Agent 应该使用的记忆范围 | | **AI Now** | 直接和 Mem 内置 AI 一起工作的地方 | | **上下文** | 预览和编辑接入的 AI 开始工作前会收到什么 | ## 第一个有用动作 [#第一个有用动作] 打开 **上下文 → 预览**。 你应该看到类似这样的一句话: > 默认 AI 会收到你的个人资料、工作记忆,而且没有额外规则。它只能使用 Default 里的记忆。 如果这句话符合预期,就不需要继续配置。 ## 这里可以改什么 [#这里可以改什么] * **你**:姓名、别名、语言和个人背景 * **AI 档案**:长期运行的命名 Agent,可设置默认空间和专属规则 * **规则**:适用于所有 AI、某个 AI 或某个空间的常驻行为规则 * **空间**:记忆范围、共享上下文和空间级规则 每次修改后,都可以回到 **预览** 确认这个 AI 实际会看到什么。 上下文里的 AI 身份 上下文里的长期规则 ## 什么时候需要创建 AI 档案 [#什么时候需要创建-ai-档案] 当某个 AI 长期扮演稳定角色时再创建: * 总是负责代码审查的 reviewer * 负责新人引导、需要慢慢解释的 assistant * 应该固定在某个项目空间里的研究 Agent 普通临时对话不需要建档案。默认 AI 档案已经够用。 ## 接入的工具怎么使用它 [#接入的工具怎么使用它] 支持的连接器会在会话开始时优先读取 Context Bundle,里面包含上下文和当前 Working Memory。较旧或更简单的集成可能只读取 Working Memory。 对于多 Agent 工具,只有当工具明确传入 Mem agent ID 或稳定的 host agent ID 时,才会选中某个 AI 档案。工具名本身,比如 `codex` 或 `claude-code`,只表示来源,不表示身份。 ## 暂时不用担心什么 [#暂时不用担心什么] * 上下文不是新的 memory 类型。 * 它不会进入搜索索引,也不会重新 embedding。 * 修改它不需要重建索引。 * 使用这个页面不需要先理解 Context Bundle、MCP 或 KFS 路径。 ## 下一步 [#下一步] * [你的档案](/zh/docs/profile):如果 AI 还不够了解你 * [AI 档案](/zh/docs/concepts/ai-profiles):如果某个长期 Agent 需要自己的身份 * [规则](/zh/docs/concepts/rules):如果你想让某些行为在搜索或 Skills 前就生效 * [Spaces](/zh/docs/spaces):如果两个项目或 Agent 需要不同记忆范围 * [连接](/zh/docs/integrations):如果你想让其他 AI 工具使用这些上下文 # AI Now (/docs/zh/ai-now) AI Now 是你直接使用已保存知识的工作区。它跟随你的 Mem 服务器运行,所以桌面端、网页版和移动端连接到同一台 Mem 时,都能看到同一组 AI Now 会话。 它和普通聊天窗口的区别在于,它不是从空白开始。AI Now 会从你已经积累下来的知识出发,所以它更适合做研究、分析、演示文稿,以及那些应该建立在你自己历史之上的多步骤任务。
AI Now 需要配置 **远程 LLM**。 前往 **设置** → **远程 LLM** 进行设置,详情参考[远程 LLM](/zh/docs/usage#远程-llm)。 如果你通过[随处访问](/zh/docs/remote-access)连接到另一台 Nowledge Mem,AI Now 会使用那台服务器上的 LLM 配置。你不需要在每台客户端上重复配置模型提供商。 ## 第一个值得做的任务 [#第一个值得做的任务] 如果你是第一次打开 AI Now,先从一个明确依赖你自己知识的问题开始: > 我做过哪些关于缓存的架构决定? 这比泛泛地闲聊更适合作为第一次体验,因为它会直接把产品模型展示出来: AI Now 会读取你已经保存的知识,在相关时结合文件或已启用插件,必要时还可以把结果继续沉淀回知识库。 只要 AI Now 能对一个明确依赖你自己知识的问题给出有用回答,而且你不用从头把背景重新讲一遍,就说明它已经在帮你干真正的活了。 ## AI Now 能做什么 [#ai-now-能做什么] | 类别 | 功能 | | ----------------------------- | ------------------------------------------ | | **记忆搜索** | 通过语义理解找到相关记忆 | | **[资料库搜索](/zh/docs/library)** | 搜索、阅读并分析你导入资料库的文档:PDF、电子表格、Word、幻灯片、代码 | | **深度研究** | 结合你的记忆和网络搜索的多源研究 | | **文件分析** | 分析你提供的 Excel、CSV、Word、PDF 文件 | | **数据可视化** | 根据你的数据生成图表 | | **演示文稿** | 创建幻灯片,带实时预览和 PowerPoint 导出 | | **旅行规划** | 创建交互式逐日行程 | | **集成** | 连接 Notion、Obsidian、Apple Notes 和自定义 MCP 插件 | ## 快速入门 [#快速入门]
### 配置远程 LLM [#配置远程-llm-step] 前往 **设置** → **远程 LLM** 并添加你的 API 密钥。
### 打开 AI Now [#打开-ai-now-step] 点击侧边栏中的 **AI Now** 标签,或按 Cmd/Ctrl + 5
### 开始一个有根据的任务 [#开始一个有根据的任务-step] 先从一个和你已经给过 Mem 的上下文相匹配的任务开始: > 我做过哪些关于缓存的架构决定? 在相关时,它会使用你的记忆、网络搜索,以及你已经连接并启用的笔记或插件能力来组织答案。 你也可以拖入文件或文件夹进行分析,或让它基于你的知识生成报告。在工作过程中,AI Now 也可以在合适的时候创建或更新记忆。 如果你使用了 [Spaces](/zh/docs/spaces),AI Now 会跟随应用里当前激活的 space。这样一个 AI Now 会话就可以专注在某个项目或某个 Agent 分区里,而不需要改动整套 Mem 的使用方式。
## 在聊天中引用记忆 [#在聊天中引用记忆] 使用 @ 搜索并在对话中引用特定记忆。 ## 深度研究 [#深度研究] AI Now 可以运行并行子任务,跨多个来源搜索并综合结果。 深度研究 在 AI Now 聊天界面中点击 研究 切换以启用深度研究。 ### 工作原理 [#工作原理] 提出研究问题: > 研究量子纠错的当前状态 AI Now 将: 1. 搜索你的记忆了解已有知识 2. 从多个角度搜索网络 3. 综合为一个答案 4. 引用来源并附带可靠性指标 ## 可选技能 [#可选技能] 技能是针对特定任务的专门能力。 | 技能 | 启用的功能 | | -------------- | ---------------------- | | **文档** | Excel/CSV 分析、图表生成、文件操作 | | **演示文稿创建器** | 幻灯片生成,带实时预览和导出 | | **旅行规划器** | 交互式行程创建 | | **Browse Now** | 用真实浏览器完成登录态和交互型网页任务 | 在 **AI Now** → **插件** → **技能** 中启用技能。 ### 文件分析 [#文件分析] 将文件或文件夹附加到你的对话中进行即时分析。 发送消息时,AI Now 会先把这些附件复制到当前任务工作区的 `inputs/` 文件夹。智能体读取这份工作区内的副本,也会把新生成的图表、脚本、报告或幻灯片写回同一个任务文件夹。 如果你连接的是远程 Mem 服务器,AI Now 会运行在那台服务器上。请附加服务器能读取到的文件,或者先把文件加入资料库。 在 AI Now 插件中切换 文档 技能以启用数据分析能力。 #### 支持的文件 [#支持的文件] | 类型 | 扩展名 | AI Now 做什么 | | -------- | --------------- | -------------- | | **电子表格** | .xlsx、.xls、.csv | 分析数据、发现模式、生成图表 | | **文档** | .docx、.doc、.pdf | 总结、提取要点、回答问题 | | **代码** | .py、.js、.ts 等 | 审查、解释、建议改进 | #### 示例 [#示例] 1. 点击文件夹图标附加 `sales_q4.xlsx` 2. 问:"这个数据中的前 3 个趋势是什么?" 3. AI Now 分析并生成可视化 你也可以附加整个文件夹一次分析多个文件。 拖入文件夹即可分析: 数据分析 ### 演示文稿 [#演示文稿] AI Now 可以创建带实时预览和编辑的演示文稿。 在 AI Now 插件中切换 演示文稿 技能以启用演示文稿创建能力。 #### 创建幻灯片 [#创建幻灯片] > 根据我们上面的研究创建一个演示文稿,包括一些图表或图形来支持洞察 AI Now 生成结构清晰、包含图表和洞察的幻灯片。 演示文稿创建 #### 编辑 [#编辑] 生成后,通过后续请求进行优化: * "让第三张幻灯片更有视觉效果" * "添加一张关于客户细分的幻灯片" * "简化结论" 或者,点击 编辑 按钮编辑演示文稿。 #### 导出 [#导出] 点击 PPTX 按钮下载为 PowerPoint(.pptx)以在其他工具中使用。 ### 旅行规划 [#旅行规划] AI Now 可以创建详细的旅行行程。 在 AI Now 插件中切换 旅行规划器 技能以启用旅行规划能力。 > 规划一个以美食和文化为重点的 5 天东京之旅 AI Now 生成一个交互式逐日行程,包含活动、地点和提示,以你最近的记忆和深度研究作为上下文。 旅行规划 ### Browse Now [#browse-now] 在 **AI Now** → **插件** → **技能** 中打开 Browse Now,让 AI Now 在需要时调用你的真实浏览器。 当任务依赖的是你的浏览器会话,而不是普通抓取时,就该打开它。常见场景包括: * 需要登录态的网站 * 需要点击、输入、滚动或多步操作的页面 * 需要截图或读取渲染后页面内容的任务 * 动态页面很多,普通抓取拿不到真实界面的情况 这项能力只能在本机使用。浏览器桥接运行在 AI Now 所在机器上,不会通过「随处访问 Mem」暴露出去。 完整的设置、边界和命令行示例见 [Browse Now 指南](/zh/docs/browse-now)。 ## 插件 [#插件] 通过插件连接你的其他应用。 ### 自定义 MCP 服务 [#自定义-mcp-服务] 如果某个工具已经提供 HTTP MCP 地址,可以在 **AI Now** → **插件** → **添加自定义 MCP** 中粘贴服务地址,填入需要的请求头,启用插件后再让 AI Now 使用它。 像 Lemonade 这类本地提供商,聊天模型请在服务商设置里选择 Lemonade;如果还想让 AI Now 调用 Lemonade 暴露的工具,再把它的 MCP 地址单独添加为自定义 MCP。内置 Rust 运行时目前只接入 HTTP MCP,暂不支持 STDIO MCP。 ### 内置插件 [#内置插件] #### Obsidian [#obsidian] 连接你的本地 Obsidian 知识库: 1. 前往 **AI Now** → **插件** 2. 启用 **Obsidian** 3. 设置你的知识库路径 现在 AI Now 可以与你的记忆一起搜索和阅读你的 Obsidian 笔记。 #### Notion [#notion] 连接你的 Notion 工作区: 1. 前往 **AI Now** → **插件** 2. 启用 **Notion** 3. 点击 **连接** 并在浏览器中授权 AI Now 现在可以搜索你的 Notion 页面和数据库。 #### Apple Notes (macOS) [#apple-notes-macos] 在 macOS 上,AI Now 可以搜索和阅读你的 Apple Notes: 1. 前往 **AI Now** → **插件** 2. 启用 **Apple Notes** 3. 在提示时授予权限 无需设置路径或同步,直接以只读方式读取系统数据库。 ### 自定义 MCP 插件 [#自定义-mcp-插件] AI Now 支持模型上下文协议(MCP)用于自定义集成。
### 打开自定义插件 [#打开自定义插件-step] 前往 **AI Now** → **插件** → **自定义插件**
### 添加 MCP 服务器 [#添加-mcp-服务器-step] 点击 **添加 MCP 服务器**
### 配置服务器 [#配置服务器-step] 配置服务器(stdio 命令或 HTTP 端点)
### 测试连接 [#测试连接-step] 点击 **测试连接** 进行验证
### 启用插件 [#启用插件-step] 启用插件 带有 OAuth 的 MCP 插件(如 GitHub、Slack)会自动检测并提示你授权。
## 会话管理 [#会话管理] 对话自动保存。点击之前的会话恢复,或创建新会话并行处理不同工作流。 ## 自动批准模式 [#自动批准模式] 为了更快的工作流程,启用 自动 以跳过文件操作和其他操作的确认提示。 自动批准授予 AI Now 在不询问的情况下采取行动的权限。仅在可信工作流程中启用。 ## 从其他设备使用 AI Now [#从其他设备使用-ai-now] 如果你的 Nowledge Mem 运行在一台常开设备上(Mac Mini、服务器或办公桌面电脑),你可以从其他任何设备通过[随处访问](/zh/docs/remote-access)使用 AI Now。 这不是另一套独立知识库,而是你在另一台客户端上继续使用同一个 Mem。想先理解整体模型,可阅读[多设备同步](/zh/docs/sync)。 工作原理: * 通过桌面端、`/app` 网页版或移动端,使用**随处访问**连接到你的主 Mem * AI Now 运行在你连接的 Mem 服务器上,并使用那台服务器的 LLM 配置 * 会话列表、消息历史和粘贴的图片都保存在服务器侧,所以你可以换一台客户端继续同一项工作 * 你的记忆、对话和资料库都来自同一个知识库,并通过安全连接访问 AI Now 可以从已连接的客户端使用,因为智能体运行在 Mem 服务器上。从另一台设备使用时,请保持那台服务器在线。 Obsidian、Apple Notes、Browse Now 这类读取本地应用或文件的插件,会在承载 Mem 服务器的那台机器上运行。如果你从手机或另一台电脑连接,它们看到的仍然是服务器机器上的应用和文件。 ## 提示 [#提示] * **要具体**: "我们上个月关于数据库迁移做了什么决定?"比"数据库相关的东西"效果更好 * **附加上下文**: 拖放文件或使用 `@` 引用特定记忆 * **使用会话**: 不同项目用不同会话 ## 下一步 [#下一步] * **[随处访问](/zh/docs/remote-access)**: 从任何设备使用 Mem,多设备工作的基础 * **[多设备同步](/zh/docs/sync)**: 理解“一台 Mem,多端接入”的同步模型 * **[远程 LLM 设置](/zh/docs/usage#远程-llm)**: 配置你的 AI 提供商 * **[连接](/zh/docs/integrations)**: 连接你的 AI 工具与捕获入口 * **[后台智能](/zh/docs/advanced-features)**: 你的知识如何自动成长 # Browse Now (/docs/zh/browse-now)
Browse Now 让 Mem 使用一个已经连接的本机 Chromium 浏览器。 有些页面不能靠普通抓取解决:它们需要你的登录态、需要 JavaScript 完整渲染、需要点击、填写表单,或者需要截图。Browse Now 给 AI Now 和受支持的智能体提供了一条本机浏览器路径,让它们能在你的 Chrome、Edge、Arc 或其他 Chromium 浏览器里工作。 Nowledge Mem Exchange 浏览器扩展也支持 Firefox,用来捕获和保存网页 AI 聊天。这是另一件事:Firefox 可以用于捕获、手动提炼和对话备份;Browse Now 的浏览器控制依赖 Chrome DevTools Protocol,目前仍需要 Chromium 浏览器。 这是 Mem 的浏览器能力。AI Now 做网页任务时会用到它;Feed 和 Timeline 智能体检查 URL 时会用到它;Library 学习需要浏览器渲染的网页时,也会用到它。 Browse Now 只能控制与 Mem 应用或 Mem 服务器位于同一台机器上的浏览器。「随处访问 Mem」不会暴露浏览器桥接端点;远程客户端也不能让服务器去控制你当前笔记本或手机上的浏览器。 ## 第一件值得尝试的事 [#第一件值得尝试的事] 如果你在使用 AI Now,可以先拿一个只有你的浏览器才能访问的页面来试: 1. 打开 **AI Now**。 2. 进入 **插件 → 技能**,启用 **Browse Now**。 3. 提一个需要真实页面状态的任务: > 打开我已登录的项目看板,总结这周发生了哪些变化。 当浏览器在本机打开,智能体能读取渲染后的页面,并且回答内容确实来自这个浏览器会话时,就说明它已经工作正常。 如果页面是公开、静态的,Mem 可能会直接用普通网页搜索或 URL 获取。这不是问题。Browse Now 只在真实浏览器会改变结果时才有必要。 ## 它会出现在哪里 [#它会出现在哪里] | 位置 | Browse Now 的作用 | | ----------------------- | ---------------------------------- | | **AI Now** | 让智能体在任务中浏览登录态或动态页面。 | | **Feed / Timeline 智能体** | 当 URL 需要页面渲染时,给后台智能体一条检查页面的路径。 | | **Library URL 学习** | 帮助 Mem 学习那些不能通过普通下载完整读取的网页。 | | **外部智能体** | 通过 CLI 和复用型技能,让受支持的智能体可以有意识地操作浏览器。 | Browse Now 不是记忆检索的替代品。它负责的是:当任务必须看到真实网页时,让 Mem 可以看到。 ## 使用条件 [#使用条件] 你需要同时具备: * 已安装 Nowledge Mem 桌面应用 * 在 Chrome、Edge、Arc 或其他受支持的 Chromium 浏览器中安装了 Nowledge Mem Exchange 扩展 * 至少有一个已连接且扩展处于可用状态的浏览器 * 如果要在 AI Now 中使用,需要在 **AI Now → 插件 → 技能** 中启用 **Browse Now** Firefox 目前还不是 Browse Now 的控制浏览器。用 Firefox 保存网页 AI 聊天;用 Chrome、Edge、Arc 或其他 Chromium 浏览器运行 Browse Now 自动化。 如果你通过「随处访问 Mem」连接到另一台 Mem,Browse Now 仍然只会运行在承载 Mem 服务器、并且连接了浏览器扩展的那台机器上。它不会控制远程客户端设备上的浏览器。 日常使用 AI Now、Feed、Timeline 或 Library 时,一般不需要手动运行命令行。 ## 命令行工具 [#命令行工具] 桌面应用同时内置了一个名为 `browse-now` 的 CLI。智能体会在底层调用它;如果你是高级用户,也可以直接在终端运行。 如果应用已经安装好,CLI 通常会自动就绪。你可以先检查: ```bash browse-now status browse-now --help ``` 核心顺序是: 1. 打开页面 2. 查看可交互元素 3. 按引用点击或填写 4. 确认当前页面地址 5. 页面变化后再次查看 `@e5` 这样的引用来自 `snapshot -i`。它们通常比猜选择器或坐标更可靠。 ```bash browse-now open https://example.com browse-now snapshot -i browse-now click @e5 browse-now wait 2 browse-now get url browse-now snapshot -i ``` 如果页面的无障碍信息很弱,CLI 也支持文本查找、按可见文本点击、截图、滚动、按键和读取页面文本: * `browse-now find "query"` * `browse-now click -T "可见文本"` * `browse-now screenshot /tmp/page.png` ## 常用命令 [#常用命令] ```bash browse-now open https://example.com browse-now snapshot -i browse-now find "search button" browse-now click @e12 browse-now fill @e3 "Nowledge Mem" --submit browse-now get page-text --max-chars 4000 browse-now screenshot /tmp/page.png ``` ## 一开始不必纠结什么 [#一开始不必纠结什么] * 普通公开网页不一定需要 Browse Now。搜索或 URL 学习通常更快。 * 日常使用 AI Now 时,不需要手动运行 CLI。打开技能,让智能体在需要时调用即可。 * 它不会绕过付费墙、权限提示、反爬限制,也不能访问你的浏览器本身打不开的页面。 ## 为智能体安装技能 [#为智能体安装技能] 让智能体学会使用 `browse-now`,通常有两条路: * 如果你在用 AI Now,直接打开内置的 **Browse Now** 技能开关 * 如果你在用外部智能体,安装下面的复用型 `npx skills` 技能包 如果你希望支持的智能体学会何时、怎样使用 `browse-now`,可以安装 `community` 里的复用型技能包: ```bash npx skills add nowledge-co/community/nowledge-mem-browse-now-npx-skills ``` 这个技能包会教智能体: * 遇到登录态或交互型网页任务时优先使用 `browse-now` * 以 `snapshot -i` 返回的 ref 作为主要操作路径 * 导航后重新抓取页面 * 用 `get url` 和 `get title` 验证结果 ## 它和 Mem 的关系 [#它和-mem-的关系] 一个更完整的组合通常是: * 先用 Nowledge Mem 的技能或集成读取上下文 * 当任务需要真实浏览器时,再调用 `browse-now` * 如果这次浏览器操作产出了值得长期保留的信息,再把它保存回 Mem ## PyPI 与远程使用 [#pypi-与远程使用] `browse-now` 也发布到了 PyPI。这个发布主要是为了让你在桌面应用捆绑之外,也能安装 CLI 或 Python API。 但这并不表示浏览器自动化可以通过远程访问来暴露。即使你使用的是 PyPI 包,浏览器桥接能力仍然只保留在本机,这一点是出于安全考虑。 ## 相关指南 [#相关指南] * [AI Now](/zh/docs/ai-now) * [后台智能](/zh/docs/advanced-features) * [Library](/zh/docs/library) * [浏览器扩展](/zh/docs/integrations/browser-extension) * [连接](/zh/docs/integrations) * [Nowledge Mem CLI](/zh/docs/cli) # 社区与支持 (/docs/zh/community) 获取帮助、反馈问题、参与贡献。 ## 社区频道 [#社区频道] ## 获得支持 [#获得支持] 按问题类型选择最快的入口: * **Discord**:适合安装求助、工作流建议、快速产品问题 * **GitHub Issues**:适合提交 bug、功能请求、可复现的问题 * **邮件 / 私密渠道**:适合账号相关或涉及隐私的支持 ### 文档 [#文档] 从安装到高级功能,文档覆盖了主要使用场景: * **[快速入门](/zh/docs/getting-started)** - 通过 Timeline 完成前五分钟和第一条知识保存 * **[连接](/zh/docs/integrations)** - 为每个 AI 工具选择合适的连接路径 * **[后台智能](/zh/docs/advanced-features)** - 知识图谱、洞察、知识结晶、工作记忆 * **[故障排除](/zh/docs/troubleshooting)** - 常见问题和解决方案 ### 报告问题和请求功能 [#报告问题和请求功能] 发现 bug 或有功能建议?通过 GitHub Issues 提交: ### 邮件支持 [#邮件支持] 直接联系团队:
[hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai)
持证用户可能会根据购买方式和当前发布阶段,获得响应更快、更贴身的支持渠道。如果你不确定自己该走哪条支持路径,先从邮件或 Discord 开始就好。 ## 保持联系 [#保持联系] 关注最新动态: 1. **加入 [Discord](https://nowled.ge/discord)** 获取实时讨论和支持 2. **在 Twitter 上关注** ([@NowledgeMem](https://x.com/nowledgemem)) 获取产品更新 3. **关注我们的 GitHub 仓库** ([nowledge-co/community](https://github.com/nowledge-co/community)) 获取技术更新和发布 4. **查看博客** 在 [nowledge-labs.ai/blog](https://nowledge-labs.ai/blog) 获取深度文章 # 备份、导出与导入 (/docs/zh/data-portability) Nowledge Mem 是本地优先的。Data Transfer(数据传输)让这件事真正落到实处:你可以把自己的知识导出来,自己保存,需要时再导入到另一台 Mem。 适合在这些场景使用:大版本升级前备份、换电脑、迁移到服务器、保留一份离线归档,或者把旧 Mem 的数据导入到新安装的 Mem。 Mem 自身导出的核心内容不是看不懂的二进制数据库备份,而是文本化的数据包:JSON manifest、JSONL 格式的记忆、线程、来源、实体、技能与图谱关系,非敏感的 AI 档案和长期指令,以及 Markdown 格式的 Working Memory。如果你选择包含 Library 原始文件或已管理的技能包,那些文件会保留原来的格式。`.zip` 只是打包方式。 ## 什么时候用 Data Transfer [#什么时候用-data-transfer] 打开 **Settings -> Data Transfer**,可以用来: * 在重装或升级前备份知识库 * 从一台电脑迁移到另一台电脑 * 在桌面版、Linux 服务器和 headless 部署之间迁移 * 保留一份可以自己查看的 Mem 数据归档 * 把已经形成的可复用技能和它们来自的知识一起带走 * 把以前导出的数据导入到全新的 Mem 这和[多设备同步](/zh/docs/sync)不是一回事。同步指的是“一台常开的 Mem,多端连接同一个知识库”。Data Transfer 面向的是备份、导出、导入和一次性迁移。 它和 [Open Knowledge Format(OKF)](/zh/docs/concepts/open-knowledge-format) 导出也不一样:Data Transfer 是一份可以重新导入的完整备份,OKF 导出则是一份可移植、可阅读的知识包,用来把你的知识交给别的工具。 ## Data Transfer 和搜索维护的区别 [#data-transfer-和搜索维护的区别] 需要保留一份知识副本,或迁移到另一台机器时,用 **Data Transfer**。 本机维护搜索状态时,去 **Settings -> Memory Processing -> Search**: * **Optimize** 会压缩可重建的搜索索引,适合搜索索引占用空间过大时使用。 * **Rebuild Index** 会从已保存的记忆、资料库内容和消息库重新生成搜索索引,适合搜索结果明显陈旧或缺失时使用。 这两个操作都不会生成备份,也不能替代导出/导入。如果你准备进行大版本升级或换机器,请先导出一次。 ## 从应用里导出 [#从应用里导出] 1. 打开 **Settings**。 2. 进入 **Data Transfer**。 3. 选择要包含的内容。 4. 如果想得到单个文件,保持 **Compress as .zip** 打开。 5. 点击 **Export**。 桌面版可以导出为 `.zip` 文件,也可以导出为展开后的文件夹。网页端或远程客户端模式下,浏览器会下载 `.zip`,因为客户端不能直接写入服务器文件系统。 导出成功后,你会得到一个包含 `manifest.json` 的 `.zip` 文件或文件夹。建议把它放在你自己掌控的位置,比如外置硬盘、加密备份、NAS,或你平时使用的备份系统。 ## 导入到另一台 Mem [#导入到另一台-mem] 1. 在目标 Mem 打开 **Settings -> Data Transfer**。 2. 选择导入模式。 3. 选择之前导出的 `.zip` 或文件夹。 4. 开始导入并等待完成。 5. 检查 Timeline、Library、Search 和 Knowledge Graph。 导入会作为后台任务运行。数据量较大时会花一些时间,因为 Mem 需要恢复记录并重建搜索索引。 ## 导入模式怎么选 [#导入模式怎么选] 当导出包里有一条内容,而目标 Mem 里已经有同一条内容时,导入模式决定该怎么处理。 | 模式 | 适合场景 | 行为 | | ----------------- | --------------- | -------------------------------------- | | **Merge(合并)** | 大多数恢复和迁移 | 保留目标端已有记录,并尽量补齐缺失的关联数据。 | | **Skip(跳过)** | 把归档导入到正在使用的 Mem | 如果目标端已经有同一条内容,就不改动它。 | | **Overwrite(覆盖)** | 目标端只是测试库或旧库 | 用导出包里的版本替换目标端匹配的记录。只有在“导出包应该作为准”的时候使用。 | 如果不确定,先选 **Merge(合并)**。 ## 导出包里有什么 [#导出包里有什么] 具体内容取决于你勾选的选项,但一个 Mem 导出包通常可以包含: | 路径 | 作用 | | ------------------------- | ----------------------------------- | | `manifest.json` | 导出格式、版本、数量统计和包含的部分。 | | `nodes/*.jsonl` | 记忆、线程、来源、实体、标签、社区等图谱节点。 | | `relationships/*.jsonl` | 节点之间的图谱关系。 | | `content_store/*.jsonl` | 线程消息和较大的内容载荷。这是 Mem 消息库的可移植形式。 | | `working_memory.md` | 当前 Working Memory,Markdown 格式。 | | `working_memory_archive/` | 归档的 Working Memory 快照。 | | `skills/` | 已管理的技能包,包括 `SKILL.md` 和随技能保存的文件。 | | `settings/*.json` | 非敏感的 AI 档案和长期指令,让已命名智能体在迁移后保留身份和规则。 | | 原始来源文件 | 可选的 Library 原始文件,保持原格式。 | 这个格式的目标是可恢复、可检查。你的知识不应该被锁在一个隐藏的桌面数据库文件里。 ## 它不会迁移什么 [#它不会迁移什么] Data Transfer 迁移的是你的知识数据,不是把整个应用安装环境完整克隆过去。 换到新机器后,你可能还需要重新连接模型服务商、集成、随处访问设置、许可证,或系统级的应用偏好设置。AI 档案和长期指令会随导出迁移,但 API keys、模型服务商凭据和许可证 token 不会导出。 搜索索引、embedding,以及活动技能投射目录不是源数据,不会作为源数据迁移。Mem 会从恢复后的记忆、消息、资料库文件和已管理的技能包重新生成这些投射。 后台任务队列、正在执行的追上计划,以及本机 AI 用量账本也不会随 Data Transfer 迁移。导入后,新的 Mem 会根据恢复后的记忆重新计算需要维护的 backlog。如果旧机器还处在“正在追上”,请在新机器上重新启动追上。 如果你部署的是自托管 Docker 或 Linux 服务器,还应阅读[服务器部署](/zh/docs/server-deployment)。服务器运维可以在快速的卷级别快照和应用级导出之间选择;应用级导出使用的就是同一套可移植 Mem 数据格式。 如果你要把同一套流程自动化,API 参考里也有对应的[导出](/docs/api/data/export/post)、[下载导出](/docs/api/data/export/download/post)、[导入](/docs/api/data/import/post)和[上传导入](/docs/api/data/import/upload/post)接口。 对于较大的浏览器/API 下载导出,Mem 会把临时导出文件放在应用自己的存储卷上,而不是容器里很小的 `/tmp`。请确保 Mem 的 data/config 卷有足够空间容纳临时工作目录和最终 `.zip`;除非你明确启用覆盖,Mem 不会覆盖已有导出文件。 ## 好的备份习惯 [#好的备份习惯] * 大版本升级或换机器前先导出一次。 * 至少保留一份最近的导出在运行 Mem 的电脑之外。 * 想要单个可携带文件时,使用 `.zip`。 * 想直接查看文件结构时,在桌面版使用文件夹导出。 * 删除旧机器前,先在备用 Mem 上试导入一次。 你的知识应该属于你自己。Data Transfer 就是让这件事可执行的那一步。 # Docker 部署 (/docs/zh/docker) **不确定要不要走这条路?** 绝大多数用户直接用 Nowledge Mem 桌面应用:在 macOS、Windows 或 Linux 上装一次即用,数据保留在本机,完全不需要懂 Linux 或 Docker。请看 **[安装](/zh/docs/installation)**。 这一页只针对一个特定场景:你想让 Mem 在你自己管的一台**无头服务器**上常驻,比如 VPS、家庭 NAS、云主机、homelab 机器,之后从笔记本、手机或其他设备上通过网络连接它的网页应用和 `nmem` CLI。 官方镜像 `nowledgelabs/mem` 跑的就是和桌面版同一份后端,在 `/app` 直接提供网页应用,所有数据保存在主机上三个普通的 bind mount 目录里(`./data`、`./config`、`./cache`)。你用现成的工具备份就行,`rsync`、`restic`、`tar`、ZFS 快照都可以。 它处于预览阶段:已经发布、并在真实主机上做了端到端验证;运维相关的细节还会继续完善。 ## 这条路适合你吗? [#这条路适合你吗] 下面这些条件**全部**满足时,再选 Docker: * 你有一台自己管的长期运行的主机,比如 VPS、家庭 NAS、云主机、homelab 服务器,并希望 Mem 作为一个服务常驻在上面。 * 你已经在那台主机上用 Docker 跑其他长期服务,或者至少能在 shell 里跑几条命令、改一下 `compose.yaml`。 * 你想要一份**集中部署**的 Mem 服务器,让笔记本 / 手机 / 其他机器上的网页应用和 `nmem` CLI 都通过网络连接它。 如果上面任何一条不成立,直接装 **[桌面应用](/zh/docs/installation)** 即可,这是绝大多数用户的正确路径,并且你的数据仍然完全保留在自己的机器上。 ## 支持的架构 [#支持的架构] 镜像以多架构清单发布,`docker pull nowledgelabs/mem:<版本>` 在你常见的服务器架构上都能正确解析: | 架构 | 常见运行环境 | | ------------- | --------------------------------------------------------------- | | `linux/amd64` | 主流 x86\_64 VPS、云主机、x86 NAS(群晖 DSx+、QNAP TS-x73AU 等)、homelab 服务器 | | `linux/arm64` | Ampere / AWS Graviton 系列 VPS、arm64 NAS、树莓派 5 这类板卡 | 你不需要手动选架构,Docker 会自动按主机架构拉取对应镜像。如果你恰好在 Apple Silicon Mac 上用 Docker Desktop 做开发,它会拉到 `arm64` 镜像并能跑通,但这不是推荐路径:个人 Mac 上直接用桌面应用更省事。 ## GPU 镜像(可选) [#gpu-镜像可选] 如果你的主机有 NVIDIA 显卡,想让本地嵌入算得更快,可以选用 `:<版本>-cuda` 这个可选 tag,代替默认镜像: ```bash docker run --gpus all ... nowledgelabs/mem:<版本>-cuda ``` 在 compose 里,把 `mem` 服务的 `image:` 指向 `:<版本>-cuda`,再加上 `gpus: all`(Compose v2.30+),或用等价的 `deploy.resources` 预留。 切换前有几点要先知道: * GPU 镜像只有 `linux/amd64` 一个架构。默认的 `:<版本>` tag 仍然是多架构(`amd64` + `arm64`)、纯 CPU 的,除非你明确要 GPU 加速,否则继续用它就好。 * 主机要先装好 [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)。没装也能启动容器,但会退回 CPU 运行,等于白换。 * 镜像里打包的是 GPU 加速的嵌入运行时,不是语言模型。模型还得你自己提供 GGUF 文件,方式和 CPU 镜像完全一样。 这一页其他内容(数据布局、备份、升级、验证)两个 tag 完全相同。 ## AMD 和 Intel 显卡镜像(Vulkan) [#amd-和-intel-显卡镜像vulkan] 如果你的主机用的是 AMD 或 Intel 显卡,请选用 `:<版本>-vulkan` 这个 tag。它走 Vulkan,所以 NVIDIA 显卡也能用,只是在 NVIDIA 上 `:<版本>-cuda` 通常更快。 AMD 或 Intel 显卡只要把显卡的渲染节点传进去,不用额外装工具: ```bash docker run --device /dev/dri -p 14242:14242 ... nowledgelabs/mem:<版本>-vulkan ``` 这个镜像上跑 NVIDIA,则要用 NVIDIA Container Toolkit,并开启 graphics 能力: ```bash docker run --gpus all -e NVIDIA_DRIVER_CAPABILITIES=graphics,compute,utility \ -p 14242:14242 ... nowledgelabs/mem:<版本>-vulkan ``` 在 compose 里,把 `mem` 服务的 `image:` 指向 `:<版本>-vulkan`,再按显卡类型加上对应的设备直通(AMD 或 Intel 用 `devices: ["/dev/dri:/dev/dri"]`)。 切换前有几点要先知道: * 这个镜像只有 `linux/amd64` 一个架构。默认的 `:<版本>` tag 仍然是多架构(`amd64` + `arm64`)、纯 CPU 的,除非你明确要 GPU 加速,否则继续用它就好。 * 主机上没有可用的 Vulkan 显卡时,容器照样能起来,会退回 CPU 运行,所以没显卡也能跑,只是慢一些。 * 和 CUDA 镜像一样,里面打包的是 GPU 加速运行时,不是语言模型。模型还得你自己提供 GGUF 文件,方式和 CPU 镜像完全一样。 这一页其他内容(数据布局、备份、升级、验证)三个 tag 完全相同。 ## 快速开始 [#快速开始] 完整的 compose 套件在 community 仓库里: ```bash git clone https://github.com/nowledge-co/community.git cd community/docker ./nmemctl up ``` `nmemctl` 是这套部署的生命周期控制器,会启动容器、等待 `/livez` 通过,然后打印 API 密钥并告诉你网页应用的 URL。如果你已经有许可证: ```bash ./nmemctl license activate ``` 其他命令:`./nmemctl status`(健康检查 + 密钥 + URL)、`./nmemctl logs -f`、`./nmemctl upgrade <版本>`、`./nmemctl wipe`(出厂重置)、`./nmemctl help` 查看完整命令列表。 如果你想手动来,三条命令也够了: ```bash docker compose up -d docker compose exec -T mem nmem key # 显示 API 密钥 docker compose exec -T mem nmem license activate # 可选 ``` 然后在浏览器打开 `http://<你的主机>:14242/app`,按提示粘贴 API 密钥。 把下面这个链接交给 Claude / Codex / Cursor / 任意 agent,它就能自己安装、巡检、升级你的 Mem 服务器。所有破坏性操作(wipe、轮换密钥、激活许可证)始终需要你本人执行。 ``` https://raw.githubusercontent.com/nowledge-co/community/main/skills/nowledge-mem-docker/SKILL.md ``` 这是原始文件链接,`curl` 下来就是 markdown 本体。下文是同一套流程的人类可读版本。 ## 你能得到什么 [#你能得到什么] * 一个容器里跑的就是和桌面版同一份 Mem 后端,`/app` 直接提供网页应用。 * 非 root 用户运行、镜像文件系统只读、所有数据都在 `compose.yaml` 旁边的三个本地目录里。不需要学 docker volume 那一套,直接用 `rsync`、`restic`、`tar`、ZFS 快照备份就行。 * 较小的镜像体积(压缩后约 1.3 GB),从源码直接构建,Python bundle 与桌面发行版完全一致。 * 多架构:一个 tag 在 `amd64` 与 `arm64` 主机上都通用。 ## API 密钥怎么找? [#api-密钥怎么找] 容器首次启动时 Mem 会自动生成一个 API 密钥。如果你错过了输出、丢了、想换一个,下面任意一条命令都行: ```bash ./nmemctl status # 重新打印密钥、许可证、URL、健康 ./nmemctl key # 只打印当前密钥 ./nmemctl key --rotate # 轮换成新密钥 ./nmemctl logs | grep -A 1 "API Key" # 翻一下首次启动横幅 ``` 密钥保存在主机的 `./config/co.nowledge.mem.desktop/remote-access.json`(容器内挂在 `/etc/nowledge-mem/...`),所以升级镜像不会丢。备份 `./config` 就是在备份密钥。一旦轮换,现有的 Web 应用、MCP 客户端、远端机器上的 `nmem` CLI 都要重新粘贴新值,旧值立刻失效。 ### 一键安装(NAS 应用商店) [#一键安装nas-应用商店] 上面这些都得有命令行。如果你是在 NAS 应用商店(群晖、QNAP、Unraid 之类)里一键装的,可能根本开不了终端。这种情况,在 compose 的 `environment` 里把 **`NOWLEDGE_NAS_BOOTSTRAP: "1"`** 打开(它默认是注释掉的、关着的)。然后用同一个网络里的浏览器打开 Web 应用,进 **设置 → 随处访问**,会有一张「最后一步:复制访问密钥」的卡片,直接点一下就能把密钥复制走,不用碰命令行。 它的口子开得很小:必须你主动打开;密钥一旦被首次使用,这个入口就永久关闭;任何经由「随处访问」隧道进来的请求都会被拒。服务器会去看访客的来源地址(包括反向代理转发过来的真实地址),挡掉公网访客。在标准的 Linux Docker 主机上,真实的客户端 IP 会被保留,所以这一关确实能拦下外网访客;但某些网络配置下,看到的会是网桥网关地址,这时候就分不清局域网和外网了。正因为没法每次都确定,只在你信任的家庭局域网里才建议打开它;要是把容器端口直接暴露到公网,请改用 `nmemctl` 取密钥。 ## 数据放在哪 [#数据放在哪] 三个本地目录就在 `compose.yaml` 旁边,由你来管。标准工具直接可用: | 目录 | 存什么 | 等级 | | ---------- | ----------------------- | -------------- | | `./data` | 你的图谱、对话、文件 | **不可替代**,请务必备份 | | `./config` | 设置、许可证、插件选择、API 密钥、设备身份 | **重要**,请务必备份 | | `./cache` | 嵌入模型、搜索索引投影 | **可重建**,可以放心删除 | 容器内进程以 UID 10001 运行;`./nmemctl up` 首次启动时会通过一次性辅助容器把这三个目录 chown 到 10001:10001,所以你完全不需要自己敲 `chown` 或 `sudo`。 `./nmemctl upgrade <版本>`(或手动的 `docker compose pull && docker compose up -d`)升级 Mem 时,这三个目录都会保留:许可证仍然有效,数据和对话原封不动,`./cache` 里的嵌入模型不必重新下载。只有 `./nmemctl wipe` 这种「清空一切、从头开始」的操作才会把它们清掉,那是刻意的恢复出厂行为。 SELinux 用户(RHEL / Fedora / Rocky):把 `compose.yaml` 里每个 bind mount 末尾加上 `:Z`,SELinux 就会替你重新打标签。默认未开启,因为首次应用是破坏性的,在非 SELinux 系统上无意义甚至会报错。 ## 从任何地方连上你的服务器 [#从任何地方连上你的服务器] 镜像里已经内置了 `cloudflared`,所以 Docker 上的「随处访问」开箱即用:不用再加 sidecar,也不用跑 `cloudflared service install`,隧道由服务器自己拉起和管理。 在网页 **设置 → 随处访问** 里配置,或者直接在容器内用 `nmem` CLI: ```bash docker compose exec -T mem nmem config access ... ``` 隧道一旦连上,把 URL 和 API 密钥复制走,其他设备就能连进来。配置、密钥处理、客户端连接这些步骤和桌面应用是一套,完整说明都在这一页:[随处访问 Mem](/zh/docs/remote-access)。 终端界面也打包进镜像了。在容器里跑一下,就能配置随处访问、显示 API 密钥、查看状态,全程不用离开 shell: ```bash docker compose exec -it mem nmem tui ``` ## 内存与数据规模增长 [#内存与数据规模增长] 默认的 `mem_limit: 4g` 是按 **被动使用** 估算的:图谱、网页应用、空闲搜索。如果你打算在服务器上主动跑 AI Now 或 Feed 智能助理,需要把它调高。粗略对照: | 图谱大小 | 建议的 `mem_limit` | | ------------ | ------------------------------------- | | 小于 200 MB | 2 GB | | 小于 1 GB | **4 GB**(compose 默认值) | | 1 GB 到 4 GB | 8 GB | | 4 GB 到 16 GB | 16 GB | | 超过 16 GB | 显式调整(参见 `community/docker/README.md`) | 如果某次文件上传或智能助理请求让界面卡在 500,最稳妥的恢复方式是 `docker compose restart mem`。镜像下次启动时会自动把图数据库的内部内存预算抬一档,相同的负载应该就能跑过去。如果问题反复出现,那就按上面的表把 `mem_limit` 调高。 在 arm64 单板机上(树莓派 5、Orange Pi 5 等),同样的对照表依然适用,但注意这些主板的 GPU 和其他加速器通常和主机共享 RAM,请给操作系统留足余量。 ## 确认搜索完全可用 [#确认搜索完全可用] 搜索全程都能用,不用等。`GET /health` 会直接告诉你哪一块在工作: ```bash curl -s http://<你的主机>:14242/health | python3 -m json.tool ``` 重点看两个字段: * **`embedding.mode`** 说明语义搜索现在怎么跑: * `remote`:用的是远程嵌入服务(比如 Nowledge AI 或你自己的 key),语义搜索完整可用。 * `local-gguf`:用的是镜像里打包的 GGUF 嵌入模型,语义搜索完整可用。 * `local-hash-fallback`:没有配真正的嵌入器,语义排序会降级,但关键词搜索照常工作。看到这个值,就该去配一个嵌入服务或模型了。 * **`reindex_needed`** 为 `true`,说明搜索索引已过期,通常是因为嵌入身份变了(你换了服务商或模型)。 服务器不会为了重建索引卡在启动阶段。它会立刻起来,索引追上之前先用关键词(FTS)搜索顶着,所以索引过期时只是悄悄退回关键词结果,不会报错。等你准备好了,去 **设置 → Memory Processing → Search** 触发重建,或者手动来: ```bash curl -X POST -H "Authorization: Bearer $NMEM_API_KEY" http://<你的主机>:14242/search-index/reindex ``` 如果你更希望服务器在对外提供搜索之前先把索引重建完(也就是旧行为),在 compose 的 `environment` 里设置 `NMEM_BOOT_AUTO_REINDEX=1`。大多数情况用不到这一项:默认的「先顶着」路径会让搜索全程可用。 ## 验证镜像来自我们 [#验证镜像来自我们] 每次发布的镜像都附带了一份 Sigstore 证明。如果你想在拉取之前确认这个 tag 真的来自我们的构建流水线(而不是别处恰好同名),可以跑: ```bash cosign verify docker.io/nowledgelabs/mem:0.9.4 \ --certificate-identity-regexp='https://github.com/nowledge-co/mem/.github/workflows/release-docker.yml@.*' \ --certificate-oidc-issuer='https://token.actions.githubusercontent.com' ``` 通过的话,会显示构建时使用的 GitHub Actions 身份;失败说明你拉到的镜像不是我们流水线产出的,请不要使用。 证明挂在 manifest 上,所以同一条 `cosign verify` 对 `amd64` 和 `arm64` 都生效。 想确认正在运行的容器到底是从哪个 commit 构建出来的,可以读一下 build SHA: ```bash docker compose exec -T mem nmem-server --build-info ``` `GET /health` 的 `.build_sha` 字段也是同一个值,想通过网络或脚本核对一次部署时很方便。 ## 公网主机加 TLS [#公网主机加-tls] 如果服务器从公网可达,并且你希望使用真实证书,同一个 `community/docker/` 目录附带了 Caddy 备用方案: ```bash export NOWLEDGE_DOMAIN=mem.example.com export NOWLEDGE_LE_EMAIL=you@example.com docker compose -f compose.yaml -f compose.tls.yaml up -d ``` 你需要:把域名 DNS 指向这台主机,打开 80、443 端口供 Let's Encrypt 校验,并使用 **Docker Compose v2.24.4 及以上版本**(TLS overlay 用到了一个 YAML 合并标签,早期版本会静默忽略)。Caddy 会自动续期证书。 ## 备份与迁移 [#备份与迁移] 两层方案,按你的迁移类型选其一: **卷级别快照**(两端镜像版本完全一致,恢复最快): ```bash ./nmemctl export # 停容器,打包 ./data ./config ./cache,重启 ./nmemctl export --no-cache # 跳过可重建的 cache,归档更小 ./nmemctl import mem-export--.tar.gz # 在新主机上恢复 ``` **应用级别导出**(跨版本,或从 `.deb` / 桌面版迁过来,使用与桌面版「导出到文件」相同的可移植 JSONL 格式): ```bash ./nmemctl backup-app # 生成 mem-app-export--.zip ./nmemctl restore-app mem-app-export--.zip ``` 如果想了解应用里这套可移植导出格式,请阅读[备份、导出与导入](/zh/docs/data-portability)。 两种方式都会有意丢掉 `machine_id`:目的主机会拿到全新的设备身份,首次启动时重新激活许可证(消耗一次设备额度)。迁移成功后请下线源服务器:双跑会让状态分叉、把许可证额度多花一份。 你也可以直接对 `./data` 和 `./config` 跑 `rsync`、`restic`、`borg`、ZFS 快照或 `tar`,它们就是普通的主机目录。如果要绝对一致的快照,先 `./nmemctl down`,做完再 `./nmemctl up`。 跨架构迁移(比如从 amd64 VPS 迁到 arm64 NAS)请走 `backup-app` / `restore-app`:卷级别快照绑定了源架构的某些落盘投影,跨架构恢复不一定能直接还原。 ## 在网页里升级(可选) [#在网页里升级可选] 默认情况下,给自托管的 Mem 升级需要 SSH 上去跑一次 `./nmemctl upgrade <版本>`。如果你想直接在 Mem 的网页里完成升级,启用一次自动升级: ```bash ./nmemctl auto-update enable ``` 这条路径只适用于官方 `community/docker` 部署。NAS 应用商店、NAS Container Manager 模板、Portainer、Unraid 模板,或你自己维护的 compose 文件,都应该从创建它们的系统里升级。Mem 仍然可以提示「有新版本」,但不应该改写一套它不了解的部署布局。 这一步会生成本机专用的随机令牌,加上一个负责升级的伴随容器,并允许从浏览器触发 Install。之后: * **标题栏徽章**:发布新版本时亮起,和桌面应用提示更新的方式一致。 * **设置 → 服务器 卡片**:显示当前版本、最新版本、Download 按钮(后台拉取,无停机)以及 Install 按钮(约 30 秒停机,重建容器前会先做一次快照)。 * **可以跳版本升级。** 如果你在 0.9.2 而最新是 0.9.4,Install 会直接升级到 0.9.4。Schema 迁移会在新镜像首次启动时按顺序执行。 启用前要了解: * 负责升级的伴随容器会挂载 `/var/run/docker.sock`,这就是为什么默认不开。这个容器拥有等同于宿主 root 的权限;Mem 容器本身从来不接触 socket。 * **远端 Install 是显式开关。** 只读的更新检查在网页上一直可用,但 Download 和 Install 默认只接受 loopback 请求,需要 `NOWLEDGE_ADMIN_REMOTE_OPS=1` 才打开。`auto-update enable` 会替你设置这个开关,因为在浏览器里点 Install 本质上是在让服务器改变自身状态。只在可信网络上启用。 * 每次 Install 之前,Mem 会先把 `./data` 和 `./config` 打包到 `./cache/_pre-upgrade-<时间戳>.tar.gz`。最近 3 份快照会保留在本机。如果新镜像启动失败,网页上会显示快照路径,SSH 上去执行 `./nmemctl import <路径> --force` 就能还原到升级前的状态。 ```bash ./nmemctl auto-update status # 状态、最近一次拉取、保留的快照 ./nmemctl auto-update rotate # 轮换升级令牌 ./nmemctl auto-update upgrade # 升级伴随容器自身的镜像 ./nmemctl auto-update disable # 移除伴随容器,保留所有快照 ``` ## 完整运维笔记 [#完整运维笔记] 如果你想看完整的运维约定,包括每一个环境变量、安全加固细节、设备身份不变式、详细的故障排查方法,请阅读 community 仓库里的 [`community/docker/README.md`](https://github.com/nowledge-co/community/tree/main/docker)。 ## 相关 [#相关] * [安装](/zh/docs/installation):桌面应用路径,也是绝大多数用户该走的路径。 * [Linux 服务器部署](/zh/docs/server-deployment):`.deb` + systemd 安装路径,适合更偏好包管理而非容器的 Linux 服务器。 * [备份、导出与导入](/zh/docs/data-portability):应用级别的可移植导出格式与恢复流程。 * [远程访问](/zh/docs/remote-access):Access Anywhere 密钥、API 访问、多设备同步。同样适用于 Docker 部署。 * [LLM 提供商](/zh/docs/llm-providers):后台智能(每日简报、洞见、图谱扩充)需要先配置。 * [故障排除](/zh/docs/troubleshooting):常见运维问题,包括无头容器部署路径。 # 用完全本地的模型运行 Nowledge Mem (/docs/zh/fully-local-models) Nowledge Mem 可以把知识数据和处理这些知识的模型请求都留在自己的设备上。LM Studio、Ollama 之类的本地推理服务会提供一个回环地址,Mem 把请求发给这个地址,而不是云端模型提供商。 这篇文档给出一条可以实际完成、可以验证的配置路径,也说明在什么条件下,整条工作流才能称为“完全本地”。 你启用的内容处理,包括记忆整理、Agent 回答、向量化,以及可选的视觉或 OCR,只能调用内置模型或同一台设备上的本地端点。内容不发送给云端模型;本地模型失败时,也不能静默切到远程提供商。 只把“记忆整理模型”换成本地模型,还不足以证明整条链路完全本地。 ## 0.10 之后,本地 AI 不只在 Mac 上运行 [#010-之后本地-ai-不只在-mac-上运行] 从 0.10 开始,Nowledge Mem 的无 Python 本地运行时覆盖桌面端与 Linux headless 部署。官方 Docker 镜像提供 CPU 版,以及按需选择的 CUDA、Vulkan 版。你可以在个人电脑上运行,也可以放在自己的 Linux 服务器上。 内置 Gemma 4 模型具备多模态能力。目前已经接入产品的是视觉:Library 会用它处理扫描 PDF、图片文字和其他需要视觉理解的文档。底层模型也为音频留下了能力基础,但生产环境的音频路由、PII 过滤和音频会议处理仍是后续方向,不要把它们当作当前页面已经交付的功能。 除了 App 内置模型,Nowledge Mem 也把 [Lemonade](https://lemonade-server.ai/)、Ollama 和 LM Studio 作为一等本地模型提供商支持。特别感谢社区贡献者和资深用户 [abn](https://github.com/abn),他为 Lemonade 集成做了大量工作。 ## 开始之前 [#开始之前] 你需要准备: * 本地桌面模式或本地服务器模式的 Nowledge Mem * [Lemonade](https://lemonade-server.ai/)、[LM Studio](https://lmstudio.ai/)、[Ollama](https://ollama.com/) 或其他本地推理服务 * 已经加载到推理服务里的聊天模型 * 足够同时运行模型和日常应用的内存 Lemonade 默认的 OpenAI 兼容地址是 `http://127.0.0.1:13305/v1`,LM Studio 是 `http://127.0.0.1:1234/v1`,Ollama 是 `http://127.0.0.1:11434/v1`。如果 Mem 和模型服务运行在不同容器或不同设备上,请改用 Mem 能访问的地址;在容器里,`127.0.0.1` 只指向当前容器。
## 启动本地模型服务 [#1-启动本地模型服务] 在 Lemonade、LM Studio 或 Ollama 中加载模型并启动本地服务,然后确认 OpenAI 兼容的 `/v1` 地址已经运行。 用下面的命令确认服务能返回至少一个模型: ```bash # Lemonade curl http://127.0.0.1:13305/v1/models # LM Studio curl http://127.0.0.1:1234/v1/models # Ollama curl http://127.0.0.1:11434/v1/models ``` 返回结果里的模型 ID,才是应该填进 Mem 的值。不要根据模型的显示名称猜测。
## 在 Mem 里添加提供商 [#2-在-mem-里添加提供商] 1. 打开 **设置 → Providers**。 2. 添加 **Lemonade**、**LM Studio** 或 **Ollama**。 3. 填入回环地址,以及本地服务返回的准确模型 ID。 4. 除非本地服务要求鉴权,否则 API Key 留空。 5. 测试连接,然后保存。 如果你使用其他本地运行时,可以添加 **OpenAI 兼容自定义端点**。端点必须实现 Chat Completions,或者你所选择的 Responses API 格式。
## 检查每一种模型用途 [#3-检查每一种模型用途] “添加提供商”和“把任务路由给它”是两件事。请在 Providers 页面逐项检查: | 用途 | 完全本地时的选择 | 影响范围 | | ---------------- | ---------------------------------------------- | ----------------------------------------------------------------- | | **Default** | 你的本地提供商 | 其他选择“Same as default”的用途会继承它 | | **Agents** | 你的本地提供商;如果 Default 已经是本地,也可以选“Same as default” | Background Intelligence、AI Now、Timeline、浏览器扩展 Agent 和其他 Agent 工作流 | | **Embedding** | **Built-in local** | 搜索索引与向量检索 | | **Vision / OCR** | 内置本地视觉模型,或本地视觉模型提供商;如果都没有,就不要启用相关工作流 | Library 中需要模型参与的图片理解与 OCR | 最简单的做法,是让 **Embedding** 继续使用 **Built-in local**。如果你换成了不同的 embedding 模型或维度,请先完成界面要求的重新索引,再判断搜索效果。 如果外接的本地模型不能处理图片,不要把它分配给 Vision 或 OCR 后就认为这部分也已经本地化。请改用内置本地视觉模型、另一个支持视觉的本地模型,或者暂时不使用图片工作流。以后每启用一种新的增强能力,都要重新检查它的路由。
## 验证整条链路 [#4-验证整条链路] 用一个小而且可观察的测试收尾: 1. 在 **设置 → Providers** 中断开或停用所有云端提供商。 2. 保持本地推理服务的请求日志可见。 3. 新建一条测试记忆,里面同时放一个长期偏好和一条临时噪声。 4. 运行相关的 Background Intelligence 动作,再让 AI Now 找回长期偏好。 5. 确认请求只出现在本地服务日志里,而且 Mem 正常保存或返回了结果。 6. 停止本地模型服务,再重复一次。此时任务应该明确失败,而不是通过云端 fallback 继续成功。 本地服务收到请求、Mem 得到预期结果、没有远程提供商参与,三项同时满足才算通过。
## 一组 Apple Silicon 实测 [#一组-apple-silicon-实测] 社区用户 [Versun](https://x.com/VersunPan) 在一台 M4 Pro、64 GB 统一内存的 Mac mini 上测试了三个 4-bit 模型。三个模型都连续三次通过同一组受控记忆整理任务;差距主要出现在延迟和内存,而不是通用智能高低。 | 模型 | 冷加载 | 常驻后的记忆整理 | 长文首字 | LM Studio 总 RSS 峰值 | | ------------------- | ------: | -------: | ------: | -----------------: | | Gemma 4 12B GGUF | 3.82 秒 | 7.38 秒 | 36.79 秒 | 10.65 GiB | | Gemma 4 26B-A4B MLX | 8.17 秒 | 2.68 秒 | 13.83 秒 | 17.69 GiB | | Qwen3.6 35B-A3B MLX | 11.55 秒 | 2.64 秒 | 9.87 秒 | 17.72 GiB | 原作者给出的实际选择是: * **内存小于 32 GB**:12B GGUF 给其他应用留出的空间更多。 * **32 GB 到 64 GB 之间**:26B-A4B MLX 是更稳妥的平衡。 * **64 GB,而且模型常驻**:35B-A3B MLX 在这组测试里的综合延迟最好。 * **经常加载和卸载模型**:26B-A4B 的“加载 + 任务”总时间更短。 这只代表一台设备、一个运行时版本和一组固定提示词。进程间共享内存页还可能让 RSS 求和高于系统可用内存的精确减少量。请把表格当成选型起点,再用自己的真实任务复测。 你可以阅读 [Versun 的 X 原文](https://x.com/VersunPan/status/2077967423689707679),或阅读 [Nowledge Labs Blog 的排版转载](https://nowledge-labs.ai/zh/blog/nowledge-mem-local-model-benchmark)。 ## 还需要检查的隐私边界 [#还需要检查的隐私边界] 本地模型端点能让推理留在本机,但产品的其他功能仍可能使用网络: * Sync 与远程访问会把实现这些功能所需的数据发送到你配置的服务。 * 浏览器连接器与导入功能需要从来源服务获取内容。 * 更新、登录和外部链接可能访问各自的服务。 * 自定义端点如果位于另一台设备上,仍然是自托管,但已经不是“同一台设备”。 如果你的要求是离线设备,而不只是本地推理,请关闭同步和远程提供商,断开网络,然后重新运行上面的验证。 ## 常见问题 [#常见问题] ### Mem 读不到模型列表 [#mem-读不到模型列表] 先确认本地服务正在运行,而且地址以 `/v1` 结尾。请先用 `curl` 访问 `/v1/models`,再排查 Mem。 ### 连接成功,但 Agent 任务失败 [#连接成功但-agent-任务失败] 模型可能不支持该工作流需要的聊天格式或工具调用。换一个更强的指令模型,并确认 **Agents** 已经指向它。 ### 第一次请求特别慢 [#第一次请求特别慢] 这通常是冷加载。只要运行时和内存允许,可以让模型常驻。评测时要把冷加载和常驻后的请求分开记录。 ### 切换 embedding 后搜索变了 [#切换-embedding-后搜索变了] 不同模型或不同维度的向量不能混用。先完成重新索引,再测试搜索。 接下来可以阅读 [LLM 提供商](/zh/docs/llm-providers),了解各提供商和上下文窗口的详细设置。 # 快速入门 (/docs/zh/getting-started) 先在 Timeline 里保存一条真实记忆,再确认你能把它找回来。如果你还没选好路径,请先看 [从这里开始](/zh/docs/start-here)。 ## Timeline [#timeline] 打开 Nowledge Mem,你看到的就是这个界面: Nowledge Mem Timeline Timeline 是你的主界面。 ### 先存下一条你想记住的内容 [#先存下一条你想记住的内容] 写下你刚刚做出的一个决定,或者一段对话里的一个洞察。按回车。 剩下的交给 Mem:标题、关键概念、图谱连接都会自动处理。你只需要先把内容写下来。打开图谱视图后,你会看到它已经和相关记忆连在一起了。 ### 提一个问题 [#提一个问题] 输入一个问题:*"上个月我对认证方案做了什么决定?"* 答案来自**你自己的知识**,不是互联网。每次提问时,Mem 都会搜索你的记忆,并基于相关内容组织答案。 ### 放入一个 URL 或文件 [#放入一个-url-或文件] 粘贴一个 URL,页面内容自动解析并索引。拖入 PDF、Word 文档、演示文稿,同样处理。每次输入都在扩展你的知识库。 Nowledge Mem Timeline ## 先拿到第一个明确结果 [#先拿到第一个明确结果] 在连接任何 AI 工具之前,先在应用里确认最基础的一步已经工作:保存一条记忆,再把它问回来,确认答案确实基于你自己的知识。 如果你想要更具体的验证清单,请看 [如何确认 Mem 已经在工作](/zh/docs/verify-it-works)。 ## 迁入已有对话 [#迁入已有对话] 如果你不是从零开始,手头已有**编程助手本地会话**、**ChatGPT / DeepSeek / ChatWise / Alma 等官方导出**,或者**单条 `.md` 对话**,请先看 **[导入已有对话](/zh/docs/import-existing-conversations)**。它说明对话 → 导入里各按钮对应:本机编程扫描、厂商批量包、单文件,以及扩展在**当前网页会话**上能做什么,不必在菜单里瞎试。 ## 连接你的第一个工具 [#连接你的第一个工具] 不要一开始就在列表里选工具、查安装文档。先给 AI 工具一段提示词,让它按当前宿主选择最合适的接入路径: ```text 读取 https://mem.nowledge.co/SKILL.md,并按其中说明为我当前使用的 AI 工具安装或更新 Nowledge Mem。 ``` 把它粘到 Claude Code、Grok Build、Codex、Cursor、Gemini CLI、Copilot CLI、OpenClaw、Hermes、Droid、Alma、Bub、Pi、OpenCode 或 Claude Desktop 中。AI 工具会读取这份安装契约、识别自己所在的宿主、选择匹配的安装或设置路径、用 `nmem status` 验证连接,并在需要时让你重启宿主。命令行宿主通常可以直接安装;桌面应用型工具可能仍需要你确认市场安装或手动步骤。 先选你日常用得最多的那个 AI 工具,把提示词粘进去,重启它,到这里就停。下次想加其它工具时,还是同一段提示词的同一种动作。 ### 远程或跨设备接入 [#远程或跨设备接入] 如果你只在本机使用 Mem,最上面的通用提示词就够了。 如果 AI 工具运行在另一台机器上,或者你使用的是托管 / 自托管的远程 Mem,先配置共享客户端连接: ```bash nmem config client set --url https://your-mem-server.example --api-key nmem_... ``` 在桌面应用里,远程 URL 和 API key 相关设置位于 **设置 → Access Anywhere**。 ### Connect 提示词不适用时 [#connect-提示词不适用时] 少数接入路径走另一条路: * **网页 AI 聊天(ChatGPT、Claude.ai、Gemini、NotebookLM、Poe)**:从 Chrome 应用商店安装 [浏览器扩展](/zh/docs/integrations/browser-extension),打开侧边栏 * **Raycast**:从 Raycast Store 安装。指南:[Raycast](/zh/docs/integrations/raycast) * **轨迹提取器**(Windsurf、Antigravity):独立 CLI,把会话导出到本地后再批量导入。指南:[导入已有对话](/zh/docs/import-existing-conversations) 连接完成后,每个工具的行为细节(skills、检索策略、提炼方式)还是看对应的连接页面。连接本身先从这一段提示词开始。 ## 其他内容进入 Mem 的方式 [#其他内容进入-mem-的方式] * **已有对话(先看地图)**:[导入已有对话](/zh/docs/import-existing-conversations),覆盖本机编程助手、厂商导出包、单文件,以及扩展与当前标签页的配合方式 * **网页里正在聊的这一帖**:[浏览器扩展](/zh/docs/integrations/browser-extension)针对你在侧栏里配合使用的那段会话;整库历史请走应用的**批量导出**再 **批量导入** * **对话格式(参考)**:[对话(Threads)](/zh/docs/threads) 了解 Markdown 规则与批量文件细节 * **手动创建**:在记忆视图中点击 **+ 创建**,或在任何终端中使用 `nmem m add`([CLI 参考](/zh/docs/cli)) ## 试试这些 [#试试这些] 保存几条记忆后,在 Timeline 中试试: *"哪些想法变化最大?"*:找到经历了多次修订的想法,按时间线讲述演变过程。 *"总结我最近的编程对话"*:如果你的编程对话已经通过自动同步、原生保存路径或导入进入 Mem,就会列出并总结最新的编程会话。 *"在我的文档中搜索 \[主题]"*:全文搜索资料库中所有内容,包括 PDF、电子表格、代码文件,任何你放进来的东西。 你的知识越多,这些查询就越有价值。持续使用一段时间后,结果会明显不一样。 ## 下一步 [#下一步] * **[从这里开始](/zh/docs/start-here)**:为你的真实工作流选择第一条路径 * **[使用 Nowledge Mem](/zh/docs/usage)**:日常工作流、搜索,以及知识如何成长 * **[如何确认 Mem 已经在工作](/zh/docs/verify-it-works)**:验证应用闭环和工具连接 * **[记忆](/zh/docs/memories)**:可搜索、可连接、可演变的原子化知识 * **[导入已有对话](/zh/docs/import-existing-conversations)**:一页看清所有导入路径 * **[对话](/zh/docs/threads)**:格式、导入界面与提炼 * **[AI Now](/zh/docs/ai-now)**:拥有你全部知识的个人 AI 助手 * **[连接](/zh/docs/integrations)**:为每个 AI 工具选择合适的连接路径 # 导入已有对话 (/docs/zh/import-existing-conversations) 可以把已有对话迁进 Mem 的方式主要是三种:**扫描本机编程助手会话**、**从应用里导出的文件**,以及**在浏览器里对当前正在看的会话用扩展捕获**。下面按你的情况对应到 **对话 → 导入**(以及 **连接 → 对话导入**)里的按钮。 批量文件名、Markdown 标题和边角情况见 **[对话(Threads)](/zh/docs/threads)**。 ## 先选对场景 [#先选对场景] | 你有什么 | 在 Mem 里点哪里 | 说明 | | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------- | | 本机 **Claude Code、Cursor、Codex、OpenCode** 会话 | **对话** → **导入** → **查找 AI 对话**(**连接 → 对话导入** 里也有入口) | 扫描后由你勾选再导入 | | **Antigravity、Claude Code、Grok Build、Codex、Craft Agent、Gemini CLI、Kimi Code、Kimi Work、MiMo Code、OpenCode、OMP 或 Pi** 的旧本机会话,尤其是 Mem 不在同一台机器上时 | 在保存会话的那台机器上运行 `nmem t sync --from ...` | 先预览;确认列表正确后再加 `--apply` | | **ChatGPT / Google Gemini Apps / AI Mode / Claude(claude.ai 或 Claude Desktop)/ DeepSeek / ChatWise / Alma** 的官方整包导出,或 **Raycast AI** 的导出 JSON | **对话** → **导入** → **批量导入** | 一个文件(见下表) | | **一条** `.md` 等单文件 | **对话** → **导入** → **单个对话** | 见 [对话里的「单个对话」](/zh/docs/threads#文件导入) | | **浏览器里正在进行的**那段网页对话 | [浏览器扩展](/zh/docs/integrations/browser-extension) | 只针对你**当前与扩展配合使用的那一个会话**,不是整套账号历史 |
## 编程助手(本机) [#1-编程助手本机] **查找 AI 对话**会在本机找 Claude Code、Cursor、Codex、OpenCode 的会话数据。在你确认之前不会写入 Mem。 有原生连接时也可以长期同步;这里的扫描更适合 **换机或第一次接进来** 时补一段历史。 如果这个工具还不在桌面端扫描列表里,使用 CLI 补导。当前支持 `antigravity`、`claude-code`、`grok`、`codex`、`craft-agent`、`gemini-cli`、`kimi-code`、`kimi-work`、`mimo-code`、`opencode`、`omp` 和 `pi`: ```bash nmem t sync --from grok --all-projects --limit 20 nmem t sync --from codex --all-projects --limit 20 nmem t sync --from craft-agent --all-projects --limit 20 nmem t sync --from antigravity --limit 20 nmem t sync --from kimi-code --limit 20 nmem t sync --from kimi-work --limit 20 nmem t sync --from mimo-code --limit 20 nmem t sync --from omp --limit 20 ``` 第一次运行只是预览。确认列表没问题后,用同一条命令加上 `--apply`。 当前的 Antigravity CLI 与 Antigravity 2.0 会把会话写入公开约定的本地 `transcript.jsonl`;`nmem t sync --from antigravity` 会直接读取它,只导入用户与助手的对话,并保留原始 conversation ID,因此能与实时捕获汇合,而不会再生成一条重复对话。 部分旧会话只存在于 Antigravity 的私有缓存中。遇到这种情况,请在 Antigravity 运行时使用 [Antigravity Trajectory Extractor](https://github.com/jijiamoer/antigravity-trajectory-extractor) 导出 JSON,再运行 `nmem t sync --from antigravity --session-dir <导出目录>` 预览。Mem 不会猜测私有 protobuf 或数据库格式。 在 AI 工具保存会话文件的那台电脑上运行 `nmem t sync`。命令会使用这台电脑上的 `nmem` 客户端配置,所以既可以上传到本机 Mem,也可以上传到远程 Mem。远程服务器不需要直接访问你的 `~/.grok`、`~/.codex`、`~/.craft-agent`、`~/.claude`、`~/.gemini`、`~/.kimi-code`、Kimi Work 运行时、`~/.pi`、`~/.omp`、OpenCode 或 MiMo Code 数据。
## 导出文件(批量) [#2-导出文件批量] **批量导入**要用各应用**官方给你的**那份文件: | 应用 | 文件 | 导出路径 | | -------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ChatGPT** | 数据包里的 `chat.html` | 设置 → 数据控制 → 导出数据 | | **Google Gemini Apps / AI Mode** | Takeout ZIP,或解压后的 `MyActivity.html` | [takeout.google.com](https://takeout.google.com) → **取消全选** → 勾选 **My Activity** → 点 **包含的所有活动数据** → 只选择 **Gemini Apps** 或 **AI Mode** → 导出。不要勾选最外层的 **Gemini**,那里主要是 Gems 设置,不是聊天历史。 | | **Claude** | 邮件里的 `data-…-batch-….zip`(含 `conversations.json` 与 `memories.json`) | 网页或 Desktop:头像 → **设置** → **隐私** → **导出数据**,Anthropic 会发下载链接([官方说明](https://support.claude.com/en/articles/9450526-how-can-i-export-my-claude-data))。iOS/Android 上无法发起导出。 | | **DeepSeek** | `deepseek_conversations.json` | chat.deepseek.com → 设置 → 数据 → 导出数据 | | **ChatWise** | 全部聊天的 `.zip` | 在 ChatWise 导出 | | **Alma** | 带 `threads.json` 的 `alma-backup-…zip` | 设置 → 数据 → 导出全部对话 | | **Raycast AI** | 默认 `raycast_ai_chats.json`(或该工具生成的任意 `.json`) | Raycast 无官方整包导出,请使用 **[raycast-ai-exporter](https://github.com/daveonkels/raycast-ai-exporter)**(macOS,见项目 README) | 用下载下来的原文件即可;Mem 会识别格式。 Gemini 和 AI Mode 的聊天正文在 Google Takeout 的 **My Activity** 里,不在最外层的 Gemini 导出项里。你可以直接上传完整 Takeout ZIP,也可以解压后单独上传 `Takeout/My Activity/Gemini Apps/MyActivity.html` 或 `Takeout/My Activity/AI Mode/MyActivity.html`。 导入后的对话会立刻作为「对话」进入搜索。Mem 不会自动把每一条历史对话都提炼成记忆,因为大型归档可能消耗很多 AI token,也容易产生噪音。先搜索这些已导入的对话;只有当里面有值得长期保留的决策、事实、流程或经验时,再提炼成记忆。 如果确实要处理一批存量对话,进入 **对话**,点 **选择**,选择当前页或 **选择全部结果**,再点 **规划提炼**。Mem 会先规划一个安全小批次,而不是一次把几百条对话全部塞进后台队列;特别长的对话会留到单独的一轮处理。 请使用邮件里的 **ZIP**(例如 `data-2026-04-01-08-10-35-batch-0000.zip`)。Mem 会从 `conversations.json` 读入全部对话,并在你勾选的对话导入完成后,把 `memories.json` 里 Claude 保存的**档案型记忆**写入资料库为一条带导入标注的记忆卡片。若只解压并选择单独的 `conversations.json`,则仅导入对话、不包含该记忆。 该工具为第三方脚本:需打开 Raycast 的 **AI Chat** 窗口,为本机终端授予**辅助功能**权限,脚本会写出结构化 JSON(多会话、`role` / `content` 消息)。文件里的日期为**近似值**(与侧栏分组有关)。同一 JSON 可走 **批量导入** 或 `nmem t import --file`。
## 浏览器:只管当前焦点会话 [#3-浏览器只管当前焦点会话] 扩展**不会**下载你在网页版里的全部聊天记录。它处理的是你**正在看、并与扩展一起用的这一个会话**。要厂商**一次性打包的全部历史**,用 **批量导入**(或在本机能扫到编程助手会话时走扫描)。
## 单文件 [#4-单文件] **单个对话**用于对话 Markdown、Cursor 导出等单文件,详见 **[对话](/zh/docs/threads#文件导入)**。
## 在应用里怎么找 [#在应用里怎么找] * **对话** → **导入**:查找 AI、批量、单个。 * **连接** → **对话导入**:同一套说明,并可跳到对话视图。 ## 接下来 [#接下来] * **[对话](/zh/docs/threads)**:格式与提炼 * **[入门](/zh/docs/getting-started)**:第一次打开应用 * **[连接](/zh/docs/integrations)**:AI 工具、MCP、扩展 # Nowledge Mem (/docs/zh) 你的 AI 工具不会替你记住已经做过的工作。Nowledge Mem 会。 0.10.0 用原生 Rust 重写了核心引擎:每个平台都更快更轻,Windows 和 Linux 上都能原生运行,本地模型能看图,还能用上你的 GPU。安装包体积约为原来的四分之一,内存占用减少约三分之一。哪些已经上线、哪些正在陆续到位,见[更新日志](/zh/changelog)。 它是面向 AI 工作的个人知识层。你保存决策、洞察、资料或对话,之后可以搜索回来、和其他内容关联起来,也可以让你接入的工具直接从同一份上下文继续。 你不需要一开始就把所有东西都接好。先保存一条内容,把它找回来,再让一个真实工具用上它。只要亲眼看到这一步发生,你就会很快明白 Mem 到底有什么用。 如果你想在多台设备之间使用 Mem,现在也已经可以:让一台常开机器运行主 Mem,再让桌面端、网页端、移动端和受支持工具连接到同一个知识库。详见[多设备同步](/zh/docs/sync)。 如果你是第一次使用,最短路径就是: 1. [先看从这里开始](/zh/docs/start-here) 2. [先完成安装](/zh/docs/installation) 3. [保存第一条记忆](/zh/docs/getting-started) 4. [确认 Mem 真的已经在工作](/zh/docs/verify-it-works)
从这里开始
给新用户的最短起步方式:先保存一条记忆,选一条工具路径,再确认它真的已经工作。
用任何工具,不丢上下文
先把一个真实工具接进来。之后,同一套记忆就能在 Claude Code、Grok Build、Cursor、Codex、ChatGPT、Grok Web 等工具之间继续被使用。
它在你睡觉时学习
系统会在后台把相关想法连起来、标记矛盾,并在早上写一份简报给你的 AI 工具参考。
一切互联
你的记忆通过共享实体形成图谱。可以按语义搜索、可视化浏览,也能让你看到自己不会主动去找的关联。
Nowledge FS 预览
预览给人的知识树,以及给 Agent 的 Nowledge FS:记忆、对话、Wiki、工作记忆、动态、来源和产物使用同一套路径结构。
掌握自己的数据
导出可移植的文本化快照,用来备份或迁移;之后可以再导入另一台 Mem,不被锁在一台机器上。
## 选择你的第一条路径 [#选择你的第一条路径] 不要一次把所有东西都配上。先按你最常用的工具来选择路径。只有在没有专属路径时,再考虑复用包或直接 MCP。 原生连接,自动读取简报、检索知识并保存会话 编程智能体原生连接,支持启动上下文、hooks 和会话捕获 原生连接,带来工作记忆简报、路由式检索与清晰的交接摘要语义 原生扩展,带命令、生命周期钩子和真实会话保存 原生连接,内含 MCP、AGENTS 指导和自动 Codex 线程捕获 原生连接,提供 Working Memory 启动、检索引导与会话捕获 OpenClaw 原生连接的首次配置指南 一键安装扩展,支持搜索、保存和更新记忆 从受支持的 Web AI 聊天平台捕获对话 ## 导入你的文档 [#导入你的文档] 拖入 PDF、Word 文档或演示文稿,自动解析并与记忆一起索引。在 Timeline 中提问时,答案同时来自文档和记忆。 ## 本地优先隐私 [#本地优先隐私] Nowledge Mem 是本地优先的。默认情况下,你的知识都保留在自己的设备上。需要更强处理能力时可以连接远程 LLM,但你的数据不会经过 Nowledge 服务器。 如果你需要备份或一次性迁移,请看[备份、导出与导入](/zh/docs/data-portability)。Mem 会导出可移植的文本化数据包,让你的知识继续掌握在自己手里。 安装后最该先看的页面 几分钟内上手 你的前五分钟 快速验证搜索、捕获和工具连接 # 安装 (/docs/zh/installation) Nowledge Mem 可以直接下载: * **下载**:打开[下载页](/zh/download),获取 macOS、Windows 和 Linux 版本 * **管理权限**:前往 [mem.nowledge.co/licenses](https://mem.nowledge.co/licenses) 管理终身许可证设备和收据 不要一上来把所有东西都配好。先看 [从这里开始](/zh/docs/start-here),在 Timeline 保存一条记忆,然后只为你真正使用的工具选择一条连接路径。 ## 系统要求 [#系统要求] 最低系统要求: | 要求 | 规格 | | ------------ | --------------------------------------------------------------------------------------------------------------------- | | **操作系统** | macOS 15 或更高版本
Windows 10 或更高版本
Linux x86\_64(Ubuntu 22.04+、Debian 12+,其他发行版可使用 AppImage) | | **内存 (RAM)** | 最低 16 GiB | | **磁盘空间** | 10 GiB 可用空间 | | **网络** | 如果使用网络代理,请确保绕过 `127.0.0.1` 和 `localhost` | **Linux 无头服务器**同样受支持。参阅 **[Linux 服务器部署](/zh/docs/server-deployment)** 指南,在没有桌面环境的服务器上运行 Nowledge Mem。 **GPU 加速。** 在 Apple Silicon 的 Mac 上,本机处理(本地搜索和内置模型)会通过 Metal 自动用上 GPU,不用任何设置。Windows 和 Linux 上的桌面应用在 CPU 上运行,对绝大多数人来说这就够用。如果你想在服务器或工作站上用 GPU 加速,用 Docker 部署即可:NVIDIA 的 CUDA 镜像、AMD 和 Intel 的 Vulkan 镜像,详见 **[Docker 部署](/zh/docs/docker)**。 ## 安装步骤 [#安装步骤] ## 步骤 1:安装应用 [#step-1-place-app] 将 Nowledge Mem 拖到 `/Applications` 文件夹。 Nowledge Mem 需要 **Microsoft Visual C++ Redistributable** 才能在 Windows 上运行。如果尚未安装,请先下载并运行安装程序: 从 [mem.nowledge.co/licenses](https://mem.nowledge.co/licenses) 下载 Windows 安装程序并运行。后续更新可直接在应用内完成,无需重新下载。 Microsoft Store 版本已停止维护。如果你之前从 Store 安装了 Nowledge Mem,请先通过 **设置 → 应用 → Nowledge Mem → 卸载** 将其移除,然后安装上方链接的版本。你的数据会保留,只有应用本体会被替换。 通过 APT 仓库安装以获取自动更新,或直接下载 `.deb` / `.AppImage`。 如果你是在终端里下载,请直接照着下面的命令执行。 这些命令已经带上了浏览器 User-Agent,因为有些下载链接会拦截普通的 `curl` / `wget`,直接返回 `403`。 如果这台机器本来就是无头 Linux 服务器,请优先用 APT 或 `.deb`,然后继续看 [Linux 服务器部署](/zh/docs/server-deployment)。 AppImage 更适合便携式手动运行,不是服务器主路径。 一行命令完成设置,添加 GPG 密钥和仓库,然后安装: ```bash curl -fsSL https://nowledge-co.github.io/community/apt/install.sh | sudo bash sudo apt-get install nowledge-mem ``` 后续更新通过 `sudo apt-get upgrade` 自动到达。 ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # 下载最新的 .deb curl -A "$BROWSER_UA" -L -o nowledge-mem.deb https://nowled.ge/download-mem-deb # 安装 sudo dpkg -i nowledge-mem.deb sudo apt-get install -f # 修复缺失的依赖 ``` ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # 下载最新的 AppImage curl -A "$BROWSER_UA" -L -o nowledge-mem.AppImage https://nowled.ge/download-mem-appimage # 添加可执行权限并运行 chmod +x nowledge-mem.AppImage ./nowledge-mem.AppImage ``` 这种方式不会把 `nmem` CLI 装进 PATH。服务器场景请优先用 APT 或 `.deb`。 ## 步骤 2:启动应用 [#step-2-first-boot] 首次启动时,双击“应用程序”文件夹中的 Nowledge Mem 图标。 如果应用启动时间过长或显示错误: * **服务超时**:如果你看到“启动服务时间过长”,这通常意味着全局代理阻止了对 `localhost` 的访问。禁用代理后重试。 * **macOS 版本**:确保你运行的是 macOS 15 或更高版本。不支持旧版本。 * **需要更多帮助?** 查看[故障排除指南](/zh/docs/troubleshooting)获取日志查看方式和详细诊断。你也可以把日志发到社区,或通过邮件联系支持。 安装完成后,从开始菜单启动 Nowledge Mem,搜索“Nowledge Mem”即可。 如果应用启动时间过长或显示错误: * **缺少 Visual C++ 运行库**:如果出现 `DLL load failed` 或应用启动时退出,请安装 [Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe) 后重启应用。详见[故障排除](/zh/docs/troubleshooting#windows-missing-visual-c-runtime)。 * **服务超时**:如果你看到“启动服务时间过长”,这通常意味着全局代理阻止了对 `localhost` 的访问。禁用代理后重试。 * **需要更多帮助?** 查看[故障排除指南](/zh/docs/troubleshooting)获取日志查看方式和详细诊断。你也可以把日志发到社区,或通过邮件联系支持。 从应用菜单启动 Nowledge Mem,或从终端运行: ```bash nowledge-mem ``` 如果应用启动时间过长或显示错误: * **服务超时**:如果你看到“启动服务时间过长”,这通常意味着全局代理阻止了对 `localhost` 的访问。禁用代理后重试。 * **缺少库文件**:如果看到 `libwebkit2gtk` 错误,请安装依赖:`sudo apt-get install libgtk-3-0 libwebkit2gtk-4.1-0 libayatana-appindicator3-1` * **需要更多帮助?** 查看[故障排除指南](/zh/docs/troubleshooting)以查看日志并获取详细诊断。 ## 步骤 3:安装所需模型 [#step-3-download-models] 启动 Nowledge Mem 后,按照应用提示安装所需模型(总共约 2.4GB): * **Apple 芯片 Mac**:支持设备端 LLM。 * **Windows**:需要远程 LLM。 * **Intel Mac**:需要远程 LLM。 * **Linux**:需要远程 LLM。
### 检查通知 [#检查通知-step] 你会在应用右上角看到下载提示
### 导航到模型 [#导航到模型-step] 点击通知按钮,或前往 **设置** → **模型**
### 安装模型 [#安装模型-step] 在应用提示下载的模型卡片上点击 **安装** LLM 模型安装 下载将自动开始,你可以监控进度: LLM 模型安装进度 根据你的网络连接,下载可能需要 5-15 分钟。模型只需下载一次。
## 可选:安装浏览器扩展 [#step-4-browser-extension] 如果你希望把受支持的 Web AI 聊天平台里的对话也接入 Mem,可以额外安装 **Nowledge Mem Exchange** 浏览器扩展。它会捕获值得保留的洞察,也能保存完整对话备份。 安装后,点击扩展图标打开侧边面板或侧栏。在**设置**中配置你的 LLM 提供商以启用自动捕获。 ChatGPT、Claude、Gemini、NotebookLM、Microsoft Copilot、Perplexity、DeepSeek、Kimi、Qwen、POE、Manus、Grok 等。扩展可以从受支持的网站捕获高价值洞察,也可以保存完整对话备份。详情请参阅[浏览器扩展指南](/zh/docs/integrations/browser-extension)。 ## 安装之后做什么 [#安装之后做什么] 安装应用本身,只是先把 Mem 装到你的机器上。下一步不是把所有能力一次配满,而是先完成一个最小可用流程: 1. 在 Timeline 里保存一条记忆 2. 为你已经在用的工具选择一条路径 3. 在继续配置其他东西之前,先确认它真的工作 对大多数用户来说,先看这三条主路径就够了: * 如果你的工具已经有**专属集成**,优先安装专属集成:Claude Code、Grok Build、Codex、Gemini CLI、OpenClaw、Hermes Agent、Alma、Cursor、Droid、OpenCode、Copilot CLI、Pi 或 Bub * 如果你的工作主要发生在 ChatGPT、Claude、Gemini、Microsoft Copilot 等网页聊天里,就安装**浏览器扩展** * 如果你想先理解 Mem 本体,再连接外部工具,就先直接使用应用本身 其他路径,例如复用型工作流包、`nmem` CLI 和直接 MCP,只有在你的工具真的需要时再考虑。 如果你已经明确想采用“一台常开 Mem,多台设备接入”的方式,建议先看[多设备同步](/zh/docs/sync),再按照[随处访问](/zh/docs/remote-access)完成配置。 ## 移动端 App(预览版) [#移动端-app预览版] iOS 和 Android 原生客户端现已推出预览版。它们通过[随处访问](/zh/docs/remote-access)连接你桌面上的 Mem,数据始终留在你的主机上,手机上随时都能搜索和记录。 * **iOS**:[加入 TestFlight](https://nowled.ge/mem-ios) * **Android**:[下载 APK](https://nowled.ge/mem-android) 两个客户端都需要桌面端 Mem 保持运行并开启”随处访问”。 ## 下一步 [#下一步] * **[从这里开始](/zh/docs/start-here)**: 给新用户的最短路径 * **[快速入门](/zh/docs/getting-started)**: 你的前五分钟 * **[如何确认 Mem 已经在工作](/zh/docs/verify-it-works)**: 验证搜索、捕获与工具连接 * **[连接](/zh/docs/integrations)**: 连接 Claude Code、Grok Build、Codex、Cursor 等 AI 工具 * **[多设备同步](/zh/docs/sync)**: 理解”一台 Mem,多端接入”的同步模型 * **[Linux 服务器部署](/zh/docs/server-deployment)**: 在 Linux 服务器上以无头模式运行 # 知识图谱 (/docs/zh/knowledge-graph) 你在 Mem 里保存的所有东西,都活在同一张[「超图」知识图谱](https://nowledge-labs.ai/zh/blog/building-memory-systems-for-ai-agents#heading-11)上:三种知识形态(Trace / Unit / Crystal)落在七种节点、十一种边上,按 *渐进式揭露* 来设计。先做轻量查询,需要更多上下文时再走实体关系,需要历史时再走版本链,需要全局视角时再去看社区聚类和 Crystal 洞察。 知识图谱视图,就是这张超图从一个隐喻变成你可以平移、可以点击、可以提问的画布。**Graph Intelligence** 是和你共享这张画布的智能体:你选,它推理;你问,图谱亮起来。整段对话还会沉淀下来,留下可读的产物:知识结晶、报告、可重放的探索会话。 资料库回答的是「我知道什么」。知识图谱回答的是「这些东西怎么连起来、接下来该用它做什么」。 ## 先做这一步 [#先做这一步] 1. 从侧边栏打开 **Graph** 视图,第一屏是 overview,里面是连接最密的记忆、实体、和 Crystal。 2. 点任意一个节点;或者直接按 **Compute**,让 Louvain 检测把整张图按主题聚类上色。 3. 当两条 Memory 应该一起读时,用 **Connect memories** 创建一条[记忆连接](/zh/docs/concepts/memory-links):给关系起名、写一句原因,让这条连接留在图谱里。 4. 打开右栏的 **Chat**,对着你看到的内容问一句真问题:*「这一簇在讲什么?」*、*「这里哪些地方在自相矛盾?」*、*「找一下这两个之间的最短路径。」* 智能体会读你选中的部分、调用合适的工具、把答案写回这同一张画布。你应该能在不离开图谱的情况下,对你自己的知识问出一个真问题,并拿到回答。
## 两种使用方式 [#两种使用方式] ### 你自己用视觉去翻 [#你自己用视觉去翻] 整张图是一个交互式网络。拖拽平移、滚轮缩放、点节点查看详情和邻边。时间轴滑块可以按时间过滤,让你看到一个领域的知识是怎么在几周或几个月里长起来的。按住 Cmd/Ctrl 多选节点;切到套索模式可以画一个区域。点 **Compute** 跑一次 Louvain 社群检测,图谱会按社群上色,主题结构就直接可见,不再被一千个点埋掉。当你发现一段系统应该记住的关系时,可以直接把两条 Memory 连起来。这条边会成为图谱的一部分,而不只是留在你脑子里的一个判断。 Overview 还可以切到 3D:把整张图当作一片可以环绕视察的地形 —— 社群是星图,影响力是海拔:
### 和 Graph Intelligence 一起推理 [#和-graph-intelligence-一起推理] Chat 标签是一位和你共享画布的推理伙伴。你在图谱上选了什么,它读到的就是同一份选区。它每次调用工具都会在画布上实时高亮对应节点,你能跟着它推理、也能审计它推理。 几个常用的问法: * 选中一个社群,问 *「这一簇在讲什么?」*。智能体会把这个簇的核心议题总结出来,并交还几条最强的来源。 * 选中一个主题、实体、或者一条记忆,问 *「这里哪些地方在自相矛盾?」*。智能体会沿着 EVOLVES 链回溯,把彼此打架的版本指出来。 * 多选两个节点,问 *「找一下这两个之间的最短路径。」*。智能体走过去,把每一跳解释给你听,沿途常常会冒出你自己没注意到的桥节点。 * 选中一个簇,问 *「写一份阶段总结。」*。智能体会产出一篇结晶或一份报告,最后由你决定是否保留。 ## 这不是「AI 聊聊知识图谱」 [#这不是ai-聊聊知识图谱] 几个架构决定加在一起,让它和「外接一个 LLM 聊天的图谱」是两种东西。 **冻结上下文,唯一信任源。** 当你发出一条消息时,智能体看到的就是你当时盯着的那一张图谱。没有漂移、没有 split-brain、没有需要双向同步的状态镜像。你在它思考时移动画布,它会把新视角带到下一轮里。会话本身(Thread)才是这片探索的唯一信任源。 **可视的推理链。** 智能体调用的每一个工具都可以发出 canvas 命令:`highlight_nodes`、`highlight_path`、`select_community`。你能看着它的推理过程发生,而不是只拿到一个黑盒答案。如果它说「这条路径经过这三座桥」,那三座桥这时候已经在画布上亮起来了。 **产物落进你已经熟悉的界面。** 智能体合成出来的结晶,是一条 `is_crystal=true` 的真实 Memory,进 Memories 视图、进 Library Wiki,自带 `[[Entity Name]]` wikilink。它写出来的报告或博客草稿,是一份真实的 Source,进资料库、进搜索索引。没有新实体类型要你去理解,所有产物都和你已经在用的界面无缝衔接。 **步骤化的探索历史。** 每一轮都会把「用户当时冻结的图谱上下文」和「智能体发出的 canvas 命令」一起存进消息元数据里。这意味着探索可以回放、可以中途停下来明天继续、可以分享。这不是一个聊天记录,是一段完整的探索过程。 ## 智能体的能力 [#智能体的能力] 二十来个专用工具,按它们替你回答的问题分组: * **图谱导航。** 概念之间的最短路径、`RELATES_TO` 边的时间感知遍历、选区节点的批量详情查询、邻居展开、社群成员列表。 * **找证据。** 一条结晶或一个实体背后的源记忆、EVOLVES 链上一段知识是怎么变化的、支撑某个观点的资料文档、过去你在这个话题上做过的探索会话。 * **结构分析。** 选中子图上的 PageRank 中心性、连接两个社群的桥节点、社群摘要(成员数、核心实体、AI 总结)。 * **合成与保存。** 由 3 条以上源记忆合成出一个稳定的结晶(自带 wikilink),或者一份更长的报告 / 博客草稿,落到资料库里、进搜索索引、可以再被翻出来读。 你不需要挑工具,你提问,智能体来挑。我们暴露给你的不是工具列表,是一种纪律:它说出来的每一个判断,都能追溯到某条具体的记忆、来源、或对话线程;结晶要求至少三条独立来源;报告要列出依据。 ## 从资料库进来:深入研究 [#从资料库进来深入研究] 大多数情况下,你不会先开 Graph 视图,而是会先在 [资料库](/zh/docs/library) 里读着读着,碰到一个想深究的问题。这时候在任意一张 wiki 页面(实体、结晶、主题)上点 **深入研究**:知识图谱会自动打开,对应的节点已经被选中(如果是主题页,整个聚类一次性高亮)。Graph Intelligence 的对话框上方会显示「正在研究:\<这个主题的名字>」,它在这次会话里合成的结晶都会以这个聚类为种子。 这个动作就是整套循环:在资料库里读,在图谱里挖,再把结果保存回资料库。 ## 边界 [#边界] 有几条边界是我们有意保持的: * 智能体只「提议」。它产出的结晶和报告以提议形式出现在对话里,最终由你决定是否保留。 * 智能体读到的就是你看到的画布。没有隐藏上下文:你看不到的东西,它也看不到。 * Graph Intelligence 通过你配置的 Remote LLM 来运行,到 **设置 > LLM Providers** 里配。 * 一次密集的探索会消耗 token。后台和按需调用各自有独立预算和频率限制,可以在 **设置 > 知识处理** 里调整。 ## 接下来读哪里 [#接下来读哪里] * [LLM Wiki](/zh/docs/concepts/llm-wiki):资料库的 wiki 视角和「资料库 → 深入研究 → Graph Intelligence」整套阅读路径背后的模型。 * [记忆连接](/zh/docs/concepts/memory-links):当两条记忆应该一起读时,怎么在同一个空间里把它们明确连起来。 * [资料库](/zh/docs/library):大多数「深入研究」开始的地方。 * [Background Intelligence](/zh/docs/concepts/background-intelligence):把这张图先建起来、并且持续维护它的那一层。 * [知识结晶](/zh/docs/concepts/crystals):稳定参考页面是怎么被合成出来的,智能体的 `CreateCrystal` 到底产出什么。 * [Building memory systems for AI agents](https://nowledge-labs.ai/zh/blog/building-memory-systems-for-ai-agents):完整阐述「超图」知识图谱、以及它为什么不只是一张普通的知识图谱。文章里嵌了北京 vLLM Meetup / KCD 的中文 talk 录像。 # 资料库 (/docs/zh/library) 资料库是让文件变成可用知识的地方。 它适合那些应该整体保留下来的来源材料:PDF、报告、电子表格、幻灯片、Markdown 笔记和代码。Mem 会解析、索引,并让这些内容和你的记忆一起工作,而不是变成孤立的附件。 资料库存放你想整体保留的来源材料,记忆保存的是长期有价值的结论。一个很自然的顺序是:先导入文档,先提问;只有当你希望其中的知识长期进入记忆图谱时,再提取记忆。
把一份 40 页的架构评审拖进资料库。在 Timeline 里问:*"评审文档里关于 API 限流是怎么说的?"* 回答会同时引用文档第 12 页的内容,以及你三个月前保存的 Redis 限流决策。文档和记忆会一起参与搜索。 资料库可以存放 PDF、电子表格、Word 文件、演示文稿、代码和其他格式。系统会解析内容、切分片段并建立索引。文档进入**可搜索**状态后,就会出现在你日常思考时真正用到的地方: * **AI Now**:按文件名、主题或一个具体问题提问。AI Now 会检索资料库、读取匹配段落,并和你的记忆一起给出带引用的回答。 * **Timeline Feed Agent**:后台把对话转化为记忆的内置 Agent,现在也可以在线程提到某份文档时反向进入资料库内容。 * **Graph Intelligence Agent**:在探索知识图谱时,Source 节点现在可以被直接检索和读取;你可以从一组相关记忆直接深入到对应的原始文档,而不用离开画布。 * **通过 MCP 连接的 AI 工具**:Claude Code、Cursor 以及任何支持 MCP 的客户端都可以调用 `query_sources`、`read_source_content`、`search_source_chunks` 和 `analyze_source_data`,让它们的回答真正建立在你自己的文件之上。 * **`nmem` 命令行**:终端与脚本工作流可以用 `nmem sources search`、`read`、`search-chunks` 和 `analyze` 检索、阅读并分析资料库。详见 [CLI 参考](/docs/cli)。 ## 把资料库当一本 wiki 来读 [#把资料库当一本-wiki-来读] v0.8 起,资料库也可以像一本 wiki 一样去读。你之前积累的记忆、资料、知识结晶,现在都以主题页、实体页、结晶页的形式呈现出来,互相之间用链接连起来,可以一路点着翻。
切到资料库里的 **Wiki** 标签,就能看到知识按主题分簇。每张卡片下面列了这个簇里被提到最多的概念,以及总结了它们的几条结晶。点卡片打开主题页,点实体打开它的 wiki 词条,点结晶里的 `[[实体]]` chip 继续往下翻。 读到真正想细看的地方,就在那张 wiki 页上点 **深入研究**。知识图谱会自动打开,把对应的东西预选好:实体页或结晶页选中那一个节点,主题页一次性把整个聚类高亮。然后你可以接着平移、展开邻居,也可以把这个选区交给 Graph Intelligence Agent,让它把你心里的那个问题问出来。 想理解背后的模型(系统替你做的事、仍然由你做的事),见 [LLM Wiki 概念页](/zh/docs/concepts/llm-wiki)。 ## Wiki 导出 [#wiki-导出] Wiki 标签的分页栏右上角有一个 Download 按钮,点它会让你选一种格式: 两种导出的都是**你的整张知识图谱**:话题、实体、结晶,你按类型分好的记忆(`memories/decision/`、`memories/procedure/` 等等)、智能体生成的报告和博客草稿、你激活的技能,还有一份标签清单。区别只在风味: * Markdown wiki 是 Obsidian 风格那一版,用你在 Mem 里看到的同一套 `[[wikilink]]` 连起来,丢进 Obsidian、Logseq 或随便哪个 markdown 阅读器都能读。 * OKF 知识包是不绑厂商那一版,按 [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf) 这份开放规范来组织:链接走标准 markdown 路径而不是 wikilink,前言按规范写,整个知识包能过 OKF 参考工具的校验。想留一份可互通的副本,或者把知识交给另一个会读 OKF 的工具,就选它。 两种都是纯 markdown,哪个阅读器都打得开,区别只在链接写法和前言。想刷新就再导出一次。这是某一刻的快照,不是双向同步:在 Mem 之外做的修改,不会自动流回来。 想多了解 OKF 这个格式、以及导出是怎么对应到它的,见 [Open Knowledge Format(OKF)](/zh/docs/concepts/open-knowledge-format)。 ## 第一份有用的文档 [#第一份有用的文档] 如果你是新用户,先导入一份你真的在意的文档。然后在 Timeline 里针对它问一个具体问题。 最基本的一步就是: * 先加进来一份真实来源 * 再提一个有上下文的问题 * 看答案怎样同时使用文档内容和你已有的知识 第一次验证到这里就够了。提取记忆可以等到这套用法对你确实有用时再做。 ## 支持的格式 [#支持的格式] | 格式 | 扩展名 | 处理方式 | | ------------ | ----------------------------------------------------- | ----------------------------------- | | **PDF** | .pdf | 感知版面提取原生文本;扫描页可用配置好的视觉模型读取 | | **Word** | .docx | 解析为文本并提取图片,分段,索引 | | **演示文稿** | .pptx | 提取幻灯片内容和图片,索引 | | **电子表格** | .xlsx, .csv | 解析为 Markdown 表格,索引。多工作表 XLSX 按标签页展示 | | **Markdown** | .md | 直接解析并索引 | | **纯文本** | .txt, .org | 直接索引 | | **代码** | .py, .js, .ts, .rs, .go, .java, .c, .cpp, .rb, .swift | 索引 | | **URL** | .html, .pdf | 转换为 Markdown,索引 | ## 添加文档 [#添加文档] 将文件拖入 Timeline 输入框,或在资料库视图中导入。也可以直接拖入文件夹,其中所有支持的文件都会自动导入。 文档经过以下处理流程: 1. **解析**: 从文件格式中提取内容 2. **分段**: 切分为可搜索的段落 3. **索引**: 加入向量索引和关键词索引 处理状态可在资料库视图中查看。索引完成后,文档进入**可搜索**状态,可以立刻在对话、全局搜索和已连接的 AI 工具里使用。 ### 添加网页 [#添加网页] 把公开网页链接贴到 Timeline 或资料库里,Mem 会先在本地尝试读取。很多文章、文档页、PDF 和博客,不需要浏览器也能直接变成可搜索内容。 有些现代网页会拦截普通抓取,或者只返回一个空的前端壳。如果你打开**设置 → 后台处理 → 公共网页兜底解析**,Mem 可以在这种情况下使用 Firecrawl 获取干净的公开内容。这个能力默认关闭,只用于安全的公开 URL。Mem 不会把 Cookie、浏览器登录态或需要登录才能看的页面发给 Firecrawl。 如果是受支持的网页 AI 聊天,请使用浏览器扩展保存对话。如果页面需要真正的浏览器控制,比如公司后台、私有文档、付费内容、Dashboard,或者任何"只有你登录后才能看到"的页面,请在 Chrome、Edge、Arc 或其他 Chromium 浏览器中使用 Browse Now。 对于扫描版 PDF,Mem 会先完成普通导入,避免应用卡住。如果某一页没有文本层,Mem 可以用当前实际生效的视觉模型在后台读取扫描文字,并补回文档内容中。 视觉默认继承**默认**服务商;如果你想单独指定,请打开**设置 → 服务商 → 视觉**。请确认实际生效的视觉模型支持图片输入。如果不支持,或后台智能预算达到上限,资料库会暂停处理,并告诉你下一步该做什么。设置好模型后,回到这份资料并点击**继续**。 ## 可搜索、和 AI 一起精读、提取记忆 [#可搜索和-ai-一起精读提取记忆] 资料库里有三件不同的事: | 模式 | 含义 | 如何触发 | | ------------- | ----------------------------------------------------------------- | ----------------------- | | **可搜索** | 内容已解析、分段、索引。在 Timeline 中提问时,AI 可以直接读取和引用该文档。一份文档可以只保持可搜索,不是在等待提取。 | 自动:导入文件时即发生。 | | **和 AI 一起精读** | 一次带引导的阅读。AI 读取这份来源,和已有记忆对照,提出哪些内容值得保存。除非你主动保存,否则不会写入记忆或结晶。 | 手动:点击来源上的**和 AI 一起精读**。 | | **已提取记忆** | 完整提取流程会创建结构化记忆、图谱关联和交叉引用。文档里值得长期保留的内容会进入你的记忆图谱。 | 手动:点击来源上的**提取记忆**。 | 在 Timeline 中直接询问某个文件时,AI 会读取这份文档当前可搜索的内容。和 AI 一起精读,是帮你判断哪些内容值得留下。提取记忆,才会把这些内容写成长期记忆并接入图谱。 ### 提取记忆会产生什么 [#提取记忆会产生什么] 当你对一个来源执行提取记忆时,AI 会完整分析其内容。对电子表格,它会计算和理解结构化数据;对文档,它会通读文本并抽取重点。最终会生成: * **记忆**:每份文档 2-5+ 条原子化洞察(决策、事实、流程),每条都可独立搜索 * **图谱关联**:与你现有相关记忆的连接,帮你发现可能没注意到的关系 * **知识结晶**:当 3+ 条记忆围绕同一主题聚类时,生成可持续更新的知识结晶 * **矛盾检测**:标记与现有知识的冲突(例如,新策略推翻了之前的决定) 提取记忆需要一定的 AI 处理时间。完成后,结果数量会显示在流程指示器中,例如 `记忆 (5)`。 ## 搜索文档 [#搜索文档] 文档和记忆一起被搜索。在 Timeline 中问 *"Q4 报告对用户流失怎么说的?"*,搜索同时覆盖你的记忆和导入的文档。 在资料库视图中,可以按状态筛选:**可搜索**、**已有记忆**、**已过期**或**错误**。只有当你想把文档里的内容长期保存为记忆时,才需要提取;只保持可搜索本身就是正常状态。 如果你有很多客户、项目或不同用途的资料,可以在导入时加标签或来源 metadata。之后 API、MCP 和 CLI 搜索会先缩小资料库范围,再排序结果。例如: ```bash nmem sources search "renewal terms" --label customer-acme --metadata purpose=contract-review nmem sources list --metadata material_type=case-study ``` 标签适合人能直接理解的大类。metadata 适合脚本和集成已经知道的字段,比如 `customer`、`project`、`material_type` 或 `purpose`。 ## 与文档对话 [#与文档对话] 在 Timeline 中直接对任何文档提问。答案同时来自文档和你的记忆,引用具体页码。 *"架构评审文档里关于 API 限流是怎么说的?"* 会返回一个答案,其中既引用文档第 12 页,也引用你三个月前的 Redis 决策。 ## 批量操作 [#批量操作] 在资料库视图中选择多份文档,可以: * **发送到 AI Now** 进行跨文档分析:比较报告、综合发现,或提出跨文档的问题 * **提取记忆**:选择还没有记忆的来源,点击 `提取记忆 (N)` 批量处理。对于已经提取过记忆的来源,按钮会显示 `Re-analyze (N)`,用于刷新提取出的知识 ## 文档、记忆和对话 [#文档记忆和对话] 三种内容类型,各有不同的用途: | 类型 | 是什么 | 示例 | | ------ | ------------ | ------------------------------ | | **记忆** | 原子化的洞察、决策或事实 | "新服务选择 PostgreSQL,因为 jsonb 支持" | | **文档** | 整体导入的参考材料 | 一份 40 页的架构评审 PDF | | **对话** | AI 会话存档 | 你在 ChatGPT 上关于异步模式的讨论 | 文档和对话是来源。记忆是提炼后的知识。当你从文档或对话中提取记忆时,独立的洞察会被保存为记忆并连接到知识图谱。原件保留在资料库或对话视图中作为来源。 ## 下一步 [#下一步] * **[快速入门](/zh/docs/getting-started)**: Timeline 和所有添加知识的方式 * **[后台智能](/zh/docs/advanced-features)**: 导入的知识如何连接到你的图谱 * **[搜索与相关性](/zh/docs/search-relevance)**: 搜索如何在记忆和文档间排序结果 # LLM 提供商 (/docs/zh/llm-providers) 选择远程 LLM 时,可以分成三层来理解: * **套餐或订阅**:你已经在用、也已经付费的账号体系 * **提供商或端点**:请求最终发到哪里 * **模型**:你日常真正运行的具体模型 在设置中(或 `nmem` CLI/TUI)配置一次之后,就可以长期使用。 请阅读[用完全本地的模型运行 Nowledge Mem](/zh/docs/fully-local-models),完成 LM Studio / Ollama 配置、用途路由、验证与隐私边界检查。 Nowledge Mem 当前推荐优先使用**订阅型默认路径**,日常体验更稳定: * **OpenAI ChatGPT/Codex 订阅** * **Kimi Code 订阅** * **SuperGrok 订阅** 日常 AI Now 使用,建议默认优先选择**支持工具调用且更快的模型**,不必一开始就用 SOTA。\ 如果使用 ChatGPT/Codex,请先在设置中获取当前模型列表,再选择订阅支持的 Codex 或基础 GPT-5 模型。Kimi Coding Plan 相关模型也适合作为日常默认选择。 如果你现在 token 消耗偏高(例如长期固定使用 `gpt-5.3-codex`),优先切换到更轻量、支持 tool use 的默认模型。 ## 如何选择 [#如何选择] 代码与通用任务都稳定,适合作为默认选择。 适合编程工作流,AI Now 工具调用表现稳定。 通过 xAI 登录使用 Grok 订阅,不需要手动粘贴 API Key。 ## 提供商章节指南 [#提供商章节指南]
OpenAI(ChatGPT/Codex)
适合: 编程 + 日常助手主力场景。
  • AI Now 与智能体工具调用稳定
  • 生态兼容性强,默认选择更省心
  • 如果你用的是 ChatGPT Subscription,这里请选择 Codex 模型或基础 GPT-5 版本,不要选 gpt-5-chat-latest 这类聊天别名。
Kimi / Moonshot
适合: Kimi Code 订阅与编码工作流。
  • AI Now 工具调用体验稳定
  • 日常编码使用顺畅
Anthropic Claude
适合: 看重自主工作流稳定性的用户。
  • 工具调用与规划质量可靠
  • 适合长链路、多步骤任务
DeepSeek
适合: 关注成本/性能平衡的场景。
  • AI Now 与智能体优先使用 deepseek-v4-flash
  • 更看重质量时可选择 deepseek-v4-pro
OpenRouter
适合: 一个端点接入多模型。
  • 多模型路由灵活
  • AI Now 场景请选择支持工具调用的模型
Gemini
适合: 已在 Google 生态中的用户。
  • AI Now 与智能体场景可用
  • 已有 Google AI Studio 凭据时接入顺滑
xAI
适合: 使用 xAI API Key 的用户。
  • 支持 AI Now 工具工作流
  • 如果你使用 xAI API 额度,请选择这个提供商
  • 如果你想使用 Grok 订阅登录,请选择 SuperGrok
SuperGrok
适合: 已有 Grok 订阅的用户。
  • 在设置中通过 xAI 登录,不需要手动粘贴 API Key
  • 本地 OAuth 凭据保存后,AI Now 与智能体工作流都可以使用
  • 如果你更想按 xAI API 额度计费,请继续使用 xAI 提供商
MiniMax
适合: 已在 MiniMax 生态中的用户。
  • AI Now 与扩展工作流均支持
  • 兼容当前可用的 MiniMax 聊天模型
Z.AI
适合: 智谱生态用户。
  • AI Now 与智能体流程支持
  • 区域与生态匹配度友好
Ollama
适合: 本地优先 / 自托管用户。
  • 模型运行不依赖公有云
  • AI Now 建议选择支持工具调用的模型
LM
LM Studio
适合: 希望用桌面模型管理器运行本地 OpenAI 兼容模型的用户。
  • 默认本地地址: [http://127.0.0.1:1234/v1](http://127.0.0.1:1234/v1)
  • 除非主动开启鉴权,否则 API Key 可以留空
  • 远程模式下,LM Studio 必须运行在 Nowledge Mem 服务器所在设备上
LM
Lemonade
适合: 使用 Lemonade 本地模型,尤其是 Windows GPU 本地推理的用户。
  • 请直接选择 Lemonade 提供商,不必再手动配置成通用自定义端点
  • 默认本地地址: [http://127.0.0.1:13305/v1](http://127.0.0.1:13305/v1)
  • 如果你要在 AI Now 里使用 Lemonade 的额外工具,可把它的 HTTP MCP 地址作为自定义 MCP 服务添加
GitHub Copilot
适合: 已有 Copilot 订阅体系的团队。
  • AI Now 支持
  • 对既有 Copilot 用户迁移成本低
API
OpenAI 兼容自定义端点
适合: 私有网关、自托管、企业代理。
  • 端点需实现 OpenAI 兼容 chat completions
  • 工具调用能力取决于网关与模型本身
DeepSeek 在 AI Now 与智能体场景中,建议先选 `deepseek-v4-flash`。如果更看重模型质量,可以选 `deepseek-v4-pro`。`deepseek-chat` 仍可使用;`deepseek-reasoner` 不支持工具调用,因此不会作为智能体推荐模型。 ## 上下文窗口 [#上下文窗口] 每个模型对单次请求可处理的 token 数有上限。Nowledge Mem 会根据模型名称自动检测这一限制,例如 `gpt-4o` 默认 128k,`gemini-2.0-flash` 默认 1M。 你可以在**设置 → 服务商 → 高级选项**中手动覆盖上下文窗口大小(也可通过 `nmem config provider set --context-window ` 命令行设置)。 什么时候需要手动调整: * **小型或微调模型**(8k–32k 上下文):设置实际限制,让 AI Now 在溢出前自动压缩对话。 * **超大上下文模型**(500k–1M+):增大窗口,让 AI Now 充分利用模型容量,避免过早压缩。 * **自定义或自托管模型**:如果模型名称不匹配已知模式,默认为 128k。设置真实值以获得准确的压缩行为。 当对话接近上下文上限时,AI Now 会自动总结较早的消息并保留最近的交互。这让长对话可以持续进行而不丢失重要上下文。正确设置上下文窗口,可以确保压缩在恰当的时机触发,不会太早,也不会太晚。 ## 自定义提供商建议 [#自定义提供商建议] 如果你使用 OpenAI 兼容自定义端点(`openai_compatible`)接入 DeepSeek V4,AI Now 与智能体场景中请使用 `deepseek-v4-flash`、`deepseek-v4-pro`,或你的网关实际暴露的 DeepSeek V4 模型 id。DeepSeek V4 默认启用专有 thinking 模式;Mem 会在智能体工具循环中关闭该模式,避免严格校验的 DeepSeek 接口因为历史工具调用格式不匹配而中断。 如果你通过 OpenRouter 使用 DeepSeek V4,请继续选择 OpenRouter 提供商。Mem 会遵守 OpenRouter 自己的请求协议,不会额外加入 DeepSeek 原生的 `thinking` 字段。 自定义端点还支持新版 **Responses API**(`/v1/responses`),与传统的 Chat Completions 格式并存。添加或编辑服务商时可选择 API 格式。 Linux 无头部署配置请参考:[Linux 服务器部署](/zh/docs/server-deployment)。 # Mem Lifetime Pro (/docs/zh/mem-pro) ## 免费、Plus、Max 与 Lifetime Pro [#免费plusmax-与-lifetime-pro] Nowledge Mem 提供**免费**、**Plus**、**Max** 和 **Lifetime Pro**。 **免费版**适合先在本地试用。你可以登录账号,最多保存 50 条记忆,并使用自己的 AI 密钥。 **Plus** 是账号服务计划。它包含每月 Nowledge AI 额度、1 个托管 Nowledge Link,以及未来的加密备份、选择性跨设备同步等账号能力。你的 Mem 数据仍保留在本机,除非你主动启用会上传加密数据的账号功能。 **Max** 是未来的高用量服务计划,面向需要更多 AI 额度、更大备份容量、高阶模型通道和团队控制的用户。 **Lifetime Pro** 和 Plus 不同。它是一次性本地解锁:无限本地记忆、自带 AI 密钥、3 台本地桌面设备,以及本地应用功能终身可用。它不包含 Nowledge AI 额度、托管 Nowledge Link、加密云备份或跨设备同步。 Nowledge Mem 应用里的计划页面 详细对比见[定价页面](https://mem.nowledge.co/zh/pricing)。 ## 激活 Lifetime Pro [#激活-lifetime-pro]
### 从定价页面开始结账 [#从定价页面开始结账-step] 访问定价页面并选择 **Lifetime Pro** 进入结账:
### 完成付款 [#完成付款-step] 使用你的电子邮件地址完成付款。 此邮箱用于接收许可证密钥,并永久关联到你的 Lifetime Pro 激活。 付款页面
### 收到许可证密钥 [#收到许可证密钥-step] 你会收到一封包含许可证密钥的邮件。 你可以随时在 mem.nowledge.co/licenses 使用你的电子邮件地址检索许可证密钥。
### 在应用中打开计划 [#在应用中打开计划-step] 打开 Nowledge Mem 并导航到 **设置** → **计划**: 免费计划
### 使用许可证密钥激活 [#使用许可证密钥激活-step] 粘贴你的许可证密钥,然后点击 **激活许可证**: 激活许可证
### 确认 Lifetime Pro 已激活 [#确认-lifetime-pro-已激活-step] 激活后会显示 Lifetime Pro 状态: 已激活许可证 随时在 mem.nowledge.co/licenses 管理你的已激活设备。 激活或许可证问题?联系 [hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai)。
# 记忆 (/docs/zh/memories) 记忆就是一条值得长期留下来的内容:一个事实、偏好、决策、计划、流程、经验、事件,或重要背景。每条记忆都应该能够独立成立,不依赖原始对话也能被理解。 记忆是 Nowledge Mem 最核心的单位。搜索、知识图谱、知识结晶、每日简报,以及你连接的 AI 工具之所以越来越有用,都是因为下面有这些记忆在支撑。 如果你要保留的是长期有价值的结论,请用记忆;如果你需要保留原始上下文和完整来龙去脉,请用对话。最常见的强路径是:先保存或导入对话,再把值得留下来的部分提炼成记忆。 ## 第一条值得保存的记忆 [#第一条值得保存的记忆] 如果你是新用户,先不要纠结结构。先保存一条真实内容,例如: * 一个你已经做出的决定 * 一条你刚学到的经验 * 一个你反复使用的工作流程 然后再去 Timeline 里把它问回来。只要你能把它重新问出来,这一页后面的内容就会更容易理解。 ## 记忆的结构 [#记忆的结构] | 字段 | 说明 | | -------- | -------------------------- | | **标题** | 简短摘要。通过时间线捕获时自动生成,也可手动设置 | | **内容** | 知识本身,支持 Markdown | | **类型** | 这条长期知识属于哪一种 | | **标签** | 分类,用于过滤和组织 | | **重要性** | 0.1 到 1.0 的评分,影响搜索排名和简报优先级 | | **创建时间** | 时间戳,用于时间搜索和知识演化追踪 | ### 重要性等级 [#重要性等级] | 范围 | 含义 | 示例 | | --------- | -- | --------------- | | 0.8 – 1.0 | 关键 | 架构决策、突破性发现、生产事故 | | 0.5 – 0.7 | 有用 | 常规决策、良好洞察、项目心得 | | 0.1 – 0.4 | 背景 | 参考信息、细节备忘、随手记录 | 默认值为 0.5。AI 工具和后台智能使用此评分来排序搜索结果和每日简报。 ### 记忆类型 [#记忆类型] 每条记忆都有一个主类型。它帮助 Agent 判断这条记忆应该怎么用: | 类型 | 用途 | | ------------ | ---------------- | | `fact` | 稳定的参考信息 | | `preference` | 用户偏好、风格选择、工作约束 | | `decision` | 选择及其理由和权衡 | | `plan` | 未来意图、下一步、路线图 | | `procedure` | 操作指南、工作流程、分步说明 | | `learning` | 经验、领悟、调试结论 | | `context` | 帮助理解后续工作的背景 | | `event` | 已发生的事情、结果、带时间的节点 | 如果 Agent 没有显式传类型,Mem 会在创建时自动分类。但当连接工具已经知道这是一条 `decision` 或 `procedure` 时,应该直接把类型传给 Mem,这样后续检索和使用会更准确。 ### 标签 [#标签] 新记忆在创建时会自动打标签。系统根据内容分配 2–4 个标签,并优先复用已有标签,保持分类体系一致。你随时可以编辑、添加或移除标签。 也支持自定义标签。标签使用小写加连字符格式(`api-design`、`team-standup`)。在记忆视图中按标签筛选,聚焦特定领域。 ## 创建记忆 [#创建记忆] ### 在时间线中 [#在时间线中] 在顶部输入框中输入并按 Enter。AI 自动识别你的意图: * 想法变成带自动标题和标签的**记忆** * 问题从已有知识中获取**回答** * URL 被**抓取**、解析并索引 * 文件被**解析**并存储 详见[快速上手](/zh/docs/getting-started)。 ### 从 AI 对话中 [#从-ai-对话中] [浏览器扩展](/zh/docs/integrations/browser-extension)可从受支持的 Web AI 聊天平台捕获记忆: * **自动捕获**持续监控对话,自主保存有价值的内容 * **手动提炼**让你对特定对话触发捕获 ### 从对话中提炼 [#从对话中提炼] 导入一段对话,然后提炼为独立记忆。每条提取的记忆都有自己的标题、标签和重要性评分。这就是把数小时的 AI 对话转化为可搜索、可连接知识的方式。详见[对话](/zh/docs/threads)。 ### 从 AI 工具中 [#从-ai-工具中] 已连接的 AI 工具可以在你工作时读取上下文、搜索旧知识,并保存值得长期保留的记忆。具体会怎么工作,取决于你选择的接入路径: | 连接方式 | 如何保存记忆 | 配置 | | -------------------------------------------------------------------------------------------------------------- | --------------------------------------- | -------------------------------- | | **专属连接**(Claude Code、Grok Build、Codex、Gemini CLI、OpenClaw、Hermes Agent、Alma、Cursor、Droid、OpenCode、Copilot CLI) | 专属连接会教智能体何时检索、何时提炼、何时新增记忆,某些场景下也会更新已有记忆 | [连接](/zh/docs/integrations) | | **复用型工作流包**(`npx skills`、OpenCode 与更多智能体) | 共享技能或工作流包代你调用 `nmem` | [快速上手](/zh/docs/getting-started) | | **直接 MCP**(没有专属包的 MCP 客户端) | 智能体直接调用 `memory_add` 与 `memory_update` | [连接](/zh/docs/integrations) | 最好的连接不只是把 `memory_add` 暴露出来,还会教智能体先搜索,再判断是新增一条记忆,还是更新一条已经存在的记忆,避免越用越重复。 ### 通过命令行 [#通过命令行] ```bash # 添加记忆(自动生成标题) nmem m add "新服务选择 PostgreSQL,因为 jsonb 支持和团队熟悉度" # 指定标题和标签 nmem m add "选择 PostgreSQL,因为 jsonb 支持和团队熟悉度" \ --title "数据库决策:PostgreSQL" \ --unit-type decision \ --labels "decision,infrastructure" \ --importance 0.8 ``` ### 通过 API [#通过-api] ```bash curl -X POST http://127.0.0.1:14242/memories \ -H "Content-Type: application/json" \ -d '{ "content": "新服务选择 PostgreSQL", "title": "数据库决策", "unit_type": "decision", "labels": ["decision", "infrastructure"], "importance": 0.8 }' ``` 完整文档见 [API 参考(英文)](/docs/api)。 ## 搜索记忆 [#搜索记忆] ### 在应用中 [#在应用中] 按 Cmd + K(macOS)或 Ctrl + K(Windows/Linux)打开搜索。三种搜索模式协同工作: * **语义搜索**按含义查找,搜索"设计模式"能找到关于"架构方案"的记忆 * **关键词搜索**做精确匹配 * **图谱搜索**通过实体连接和主题聚类发现记忆 在任意应用中按 Cmd + Shift + K 可直接搜索,无需打开 Nowledge Mem。 ### 从 AI 工具中 [#从-ai-工具中-1] 已连接的 AI 工具会通过原生连接、共享工作流包或 MCP 工具来自动搜索。当当前话题很可能关联到过往工作时,做得好的接入路径会主动查询你的知识库,而不是等你额外提醒。 ### 通过命令行 [#通过命令行-1] ```bash # 语义搜索 nmem m search "认证模式" # 用已有业务字段缩小范围 nmem m search "续约决策" --metadata customer=acme --metadata purpose=contract-review # JSON 输出用于脚本 nmem --json m search "API 设计" | jq '.memories[0].content' ``` 当你的集成或导入流程已经知道稳定字段时,用 metadata 过滤,比如 `customer`、`project`、`material_type` 或 `purpose`。Mem 会先缩小记忆范围, 再做排序,让 Agent 搜索正确的一部分,而不是靠宽泛排序碰运气。 ## 编辑和组织 [#编辑和组织] ### 更新记忆 [#更新记忆] 在记忆视图中点击任意记忆,编辑内容、标题、标签或重要性。更改立即生效。 通过命令行: ```bash # 更新重要性 nmem m update --importance 0.9 # 更新标签 nmem m update --labels "decision,infrastructure,critical" ``` ### 删除记忆 [#删除记忆] 在记忆详情页面删除,或通过命令行: ```bash nmem m delete nmem m delete -f # 脚本或非交互环境请加 -f ``` `nmem m delete` 默认会先询问确认。在脚本、Agent 或任何非交互终端里,请加 `-f`,否则命令会停在等待输入。 ## 记忆如何连接 [#记忆如何连接] 启用[后台智能](/zh/docs/advanced-features)后,记忆会自动生长连接: * 知识图谱:每条记忆成为图的一个节点。系统提取实体(人物、技术、概念)并映射关系。搜索"分布式系统"能找到关于"Node.js 微服务"的记忆,词不匹配,但含义匹配。 * 知识演化:保存一个已记录过的主题的新内容时,系统创建版本链接:*替换*、*丰富*、*确认*或*质疑*。追溯你对任何主题的理解如何随时间变化。 * 知识结晶:当足够多的记忆覆盖同一主题时,系统将它们合成为一篇参考文章,并标注来源。后续保存相关内容时,知识结晶自动更新。 * 工作记忆简报:每天早晨,Mem 会基于你近期和重要的记忆生成简报。Default 分区保留 `~/ai-now/memory.md`;如果你使用了 [Spaces](/zh/docs/spaces),其他分区也会有各自的简报。 详见[后台智能](/zh/docs/advanced-features)完整指南。 ## 记忆来源 [#记忆来源] | 来源 | 方式 | 了解更多 | | ----- | --------------------------- | ------------------------------------------------ | | 时间线 | 输入后按 Enter | [快速上手](/zh/docs/getting-started) | | 浏览器扩展 | 自动捕获或手动提炼 Web AI 对话 | [浏览器扩展](/zh/docs/integrations/browser-extension) | | 对话提炼 | 从导入的 AI 对话中提取 | [对话](/zh/docs/threads) | | AI 工具 | Skills、插件或 MCP `memory_add` | [连接](/zh/docs/integrations) | | 命令行 | `nmem m add` | [CLI 参考](/zh/docs/cli) | | API | `POST /memories` | [API 参考(英文)](/docs/api) | ## MCP 工具 [#mcp-工具] | 工具 | 功能 | | --------------------- | ----------------------- | | `memory_search` | 按含义、关键词或图谱连接搜索记忆 | | `memory_add` | 创建新记忆,包含内容、标题、类型、标签和重要性 | | `memory_update` | 更新内容、标题、重要性或标签 | | `memory_delete` | 删除一条或多条记忆 | | `list_memory_labels` | 列出所有标签及使用次数 | | `read_working_memory` | 读取今日简报 | ## 下一步 [#下一步] * **[对话](/zh/docs/threads)**:导入和提炼 AI 对话为记忆 * **[资料库](/zh/docs/library)**:导入文档,与记忆一起搜索 * **[AI Now](/zh/docs/ai-now)**:拥有你全部知识的个人 AI 助手 * **[后台智能](/zh/docs/advanced-features)**:记忆如何自动生长连接 * **[浏览器扩展](/zh/docs/integrations/browser-extension)**:从 Web AI 对话中捕获记忆 * **[连接](/zh/docs/integrations)**:通过原生连接、复用包或 MCP 连接你的 AI 工具 # Nowledge FS (/docs/zh/nowledge-fs) Nowledge FS 是 Mem 预览中的路径层,同时服务人、Agent 和脚本。 在应用里,人看到的是**知识树**:把你知道的东西放进一个熟悉的树状视图里。记忆、对话、Wiki、工作记忆、动态、来源和产物仍然保持各自原本的体验。知识树不是把底层实现文件暴露给你看,而是给 Mem 本身加了一张安静的地图:点开一个对象,就进入它应该有的预览。 Agent 看到的则是同一张地图的虚拟文件系统形态。这才是它真正重要的地方:人可以在应用里浏览,脚本和 Agent 可以按路径列出、读取、搜索、召回,并更新可写对象的正式路径。 这是知识树和 Nowledge FS 的第一个公开形态。应用、CLI、API 和 MCP 已经可以试用;真正挂载成系统文件夹、来源片段、SQL/Cypher、replay 和 tail 会在后续阶段继续设计。 ## 什么时候用它 [#什么时候用它] 当你需要“知道东西在哪里”时,用知识树。 * 你记得某件事存在,但不确定它是在记忆、对话、Wiki 还是来源里。 * 你想按类型、日期、标签或主题扫一遍,而不是来回切换多个页面。 * 你希望 Agent 先看周围上下文,再决定是否读取大内容。 * 你需要能复制进命令、脚本、提示词或 MCP 调用的路径。 如果只是问一个问题,搜索仍然可以。知识树更适合导航、定位和逐步检查。 ## 第一次有用的循环 [#第一次有用的循环] 1. 在应用侧边栏打开 **Tree**。 2. 打开一个分支,比如 **Memories**、**Threads**、**Wiki**、**Working Memory**、**Activities** 或 **Artifacts**。 3. 点开一个对象。预览应该像 Mem 里原本的对象:记忆是记忆上下文,对话是可读的会话,Wiki 是 Wiki 页面,动态是 Timeline 风格事件。 4. 如果你用 CLI,运行: ```bash nmem fs ls / nmem fs recall "what did we decide about auth?" --in /memories -k 5 ``` 好的结果不是一大段文本,而是下一步可以检查的路径: ```bash nmem fs stat /memories/by-id/.memory.md nmem fs cat /memories/by-id/.memory.md ``` ## 如何理解路径 [#如何理解路径] 这些路径是 Mem 地址,不是你磁盘上的文件。 ```text /memories/by-id/.memory.md /threads///messages.jsonl /wiki/entities/.entity.md /working-memory/today.md /feed/2026-05-15/.feed.jsonl /artifacts/imports/.artifact.pdf ``` 有些路径是对象的正式位置,可以在对象可写时更新。另一些路径是别名,比如同一条记忆出现在标签或日期分支下。别名适合浏览;真正修改时应回到正式路径。 ## Agent 应该怎么用 [#agent-应该怎么用] Agent 应该一步一步在树里走: 1. 模糊的记忆问题用 `recall`。 2. 类型、标签、日期、提及对象等结构化条件用 `find`。 3. 精确短语用 `grep`;需要正则时再用 `grep -E`。 4. 读取大内容前先用 `stat`。 5. 找到有价值的路径后再用 `cat`。 这样既节省上下文,也更容易检查 Agent 做了什么。你在应用、CLI、API 或 MCP 工具里看到的都是同一套路径。 ```bash nmem fs recall "why did we change token refresh?" --in /memories -k 5 nmem fs ls /memories/by-label/auth nmem fs cat /memories/by-id/.memory.md ``` 遇到很长的对话或文档时,Agent 不应该一上来读取全文。先搜索分支,再只读取相关行附近的一小段: ```bash nmem fs grep "JWT rotation" /threads nmem fs cat /threads///messages.jsonl --line 42 --lines 12 nmem fs grep "rate limit" /sources nmem fs cat /sources/.pdf --line 120 --lines 80 ``` 对话记录是 JSONL,一行就是一条消息。资料库里已解析的文档会以 Markdown 呈现,所以 `grep` 返回的行号可以直接交给 `cat --line`。`grep` 默认是忽略大小写的固定字符串搜索;需要严格大小写时用 `--case-sensitive`,需要 `JWT|token` 这类正则时用 `-E`。 在这个预览版里,`recall` 主要面向记忆搜索。对话和已解析的资料库文档请先用 `grep` 做精确搜索。 MCP 客户端可以通过 `mem_fs` 使用同样的动词。Codex、Claude、Cursor、Gemini、OpenClaw 和其他 Agent 都只是这套 Mem 视图的使用者;它不属于某一个集成。 具体入口保持简短:CLI 里是 `nmem fs`,API 里是 `/fs/*`,MCP 工具里是 `mem_fs`。 如果你在写工具或适配器,先让 Mem 告诉你当前服务器支持什么: ```bash nmem fs capabilities --json ``` 返回结果会包含当前根目录、可用动词、限制和功能开关。这样集成就不需要猜测本地挂载、来源片段、SQL、Cypher、replay 或 tail 是否已经发布。 ## 现在还不用关心什么 [#现在还不用关心什么] * 你不需要先挂载成本地文件夹。 * 你不需要理解图谱 schema。 * 你不需要在知识树和 Library 之间二选一。Library 仍然是阅读文档和 Wiki 的丰富界面;知识树是跨所有 Mem 对象的地图。 * 预览版不要求你使用 SQL 或 Cypher。那些查询入口要等安全边界和结果形态确定后再进入后续阶段。 ## 如何确认可用 [#如何确认可用] 知识树正常工作时,你应该看到: * 应用里出现主要分支,而不是底层实现文件; * 点开对象后进入原生 Mem 预览,不是普通文本 dump; * `nmem fs ls /` 返回和应用里一致的顶层结构; * `nmem fs recall ...` 返回路径; * Web 端和远程客户端可以使用和桌面端相同的 `/fs/*` API。 ## 下一步 [#下一步] 在终端或脚本里使用 `nmem fs`。 直接调用 `/fs/*` 端点。 为你的工具选择原生连接或 MCP 路径。 需要最丰富的文档和 Wiki 阅读体验时,继续使用 Library。 # 你的档案 (/docs/zh/profile) 你的档案决定了 Mem 的代理怎样理解你。不填的话,代理只能泛泛地处理。写上几句话,每次简报、标签和洞察就会更贴近你真正在做的事。 ## 档案的作用 [#档案的作用] 你填好档案之后,系统里的每个代理都会读取它: * **每日简报**会围绕你的角色和当前工作来取舍重点 * **自动标签**会选择符合你思维习惯的分类,而不是泛泛的标签 * **知识提取**能理解你常用的领域术语 * **AI Now** 每次对话一开始就已经知道你的背景 你只需要填一次。每个代理每次运行时都会读取。 ## 设置你的档案 [#设置你的档案]
### 打开档案 [#打开档案-step] 进入 **上下文 → 你**。
### 姓名和别名 [#姓名和别名-step] 姓名帮助代理在导入的对话和会话中认出你。别名是你在其他平台上使用的标识(GitHub 用户名、Twitter 账号、Slack 显示名)。代理在处理来自不同来源的会话时,通过这些名称判断哪些消息是你说的。
### 关于你 [#关于你-step] 用几句话描述你的角色、当前的工作和兴趣。这是影响最大的字段。代理在处理你的知识时,靠它来判断什么重要。 示例: * *金融科技创业公司的产品设计师,专注移动支付和新用户引导流程* * *正在为合规团队搭建知识库,减少重复的法务审查* * *对 AI 辅助写作、第二大脑方法论和个人知识管理感兴趣* 不需要全写。哪怕只有一句话,也能改变代理排列优先级的方式。
### 自定义指令 [#自定义指令-step] 你可以在这里告诉代理,哪些事要和默认行为不一样。 示例: * **标签**:*"客户反馈相关的记忆始终加上 'customer-voice' 标签。用项目代号,不要用全名。"* * **语言**:*"简报用法语写。编程概念保留英文技术术语。"* * **风格**:*"简报精简,不超过 5 条要点。跳过显而易见的关联。"* 自定义指令会应用到每日简报、后台知识处理和 AI Now 对话中。
### 输出语言 [#输出语言-step] 选择代理撰写简报、洞察、标签等生成内容时使用的语言。这和应用界面语言是分开的。 语言选择器现已覆盖欧盟全部官方语言、挪威语(Bokmål)、冰岛语,以及原有的全球语言;本地空间和 Cloud 空间遵循同一套选择。
## 档案如何传递给代理 [#档案如何传递给代理] 你的档案会注入到三条代理路径中: | 代理 | 读取内容 | 用途 | | ---------- | ------------ | ----------------------- | | **后台智能** | 完整档案 + 自定义指令 | 围绕你的工作来组织简报、标签和洞察 | | **知识代理** | 完整档案 + 自定义指令 | 指导 EVOLVES 检测、标签分配和知识提取 | | **AI Now** | 完整档案 + 自定义指令 | 每次对话开始时就已加载你的上下文 | 支持的连接工具会在会话开始时通过 **上下文** 读取你的档案。即便是较旧或较简单的集成,也能间接受益:搜索结果、标签和简报越准确,工具拿到的上下文质量就越高。 ## 建议 [#建议] * **具体胜过全面。**"正在主导从 MongoDB 到 PostgreSQL 的迁移"比"十年经验的高级工程师"有用得多。 * **工作变了就更新。** 档案不是简历。换了项目,就更新一下。 * **自定义指令会积累效果。** 一条"始终用项目代号做标签"的规则,能省掉你手动重标几百条记忆的工作。 * **可以留空。** 没填的字段,代理会退回到默认行为。 ## 下一步 [#下一步] * **[后台智能](/zh/docs/advanced-features)**:看看代理怎样利用你的档案 * **[上下文](/zh/docs/ai-context)**:检查每个接入的 AI 开始工作前会收到什么 * **[AI Now](/zh/docs/ai-now)**:你的个人 AI 工作台,启动时就已加载你的上下文 * **[连接](/zh/docs/integrations)**:连接那些能从更好上下文中受益的工具 # 随处访问 Mem (/docs/zh/remote-access) Nowledge Mem 运行在你自己的设备上,数据完全在你掌控之中。「随处访问」让你通过安全隧道,从其他任何设备、智能体或浏览器访问同一个实例。 一个 Mem,多种连接方式:咖啡店里的笔记本、手机上的浏览器、CI 上的编程智能体、另一台电脑上的 AI Now。你常开设备上的 Mem 就是中枢,其他一切都连接到它。 这也是 Mem 现在的同步方式:一台常开 Mem,多端接入。如果你想先看简短说明,再回来做配置,可以先读[多设备同步](/zh/docs/sync)。 如果你订阅了 Plus 或 Max,打开 **设置 → 随处访问 Mem**,开启 **Nowledge Link** 即可。Mem 会自动为你创建稳定链接,不需要自己购买域名或配置 Cloudflare。下面的快速链接和 Cloudflare 账号路径仍适合 Lifetime Pro 用户、服务器部署和自有域名高级配置。 Plus 里的 Nowledge Link 在一台常开设备上运行 Nowledge Mem,比如 Mac Mini、Linux 服务器或始终通电的桌面电脑。然后从其他地方连接:第二台笔记本、浏览器或 iOS 移动应用。这样你可以 24/7 访问知识库、后台智能持续运行、所有工具和设备共享同一数据源。 ## 先选连接方式 [#先选连接方式] | 类型 | 适用场景 | 你会得到的 URL | | ----------------- | ---------------------- | ------------------------------------------ | | **Nowledge Link** | 想一键完成设置的 Plus / Max 用户 | 稳定的 `*.nowledge-mem.com` URL | | **快速链接** | 1 分钟内快速可用 | 随机 `*.trycloudflare.com` | | **Cloudflare 账号** | 日常长期稳定使用 | 你自己域名下的固定 URL(如 `https://mem.example.com`) | ## 开始前确认 [#开始前确认] 请从 **设置 → 随处访问 Mem → Guide** 打开本指南。 * Nowledge Link 需要有效的 Plus 或 Max 订阅,并在 Nowledge Mem 内登录账号。 * 快速链接不需要 Cloudflare 账号,也不需要域名。 * Cloudflare 账号模式要求你已经有一个在 Cloudflare 托管的域名。 * 如果你还没有域名,先使用 **快速链接**。 * 在 Cloudflare 账号模式里,只有创建 hostname route 之后才会出现最终公网 URL。 如果你是服务器 / 终端工作流,可打开 nmem tuiSettings 标签 → Access Anywhere。 你可以在这里配置稳定链接、启动/停止 tunnel、轮换/显示 key、查看终端变量配置。 Access Anywhere 的管理接口仅允许本机调用。\ 如果你当前使用的是远程 API(NMEM\_API\_URL=https\://...),请先临时切回本机([http://127.0.0.1:14242](http://127.0.0.1:14242))再做 tunnel 配置。 ## 路径 A:快速链接(无需账号) [#路径-a快速链接无需账号]
### 在 Mem 中打开远程访问 [#在-mem-中打开远程访问-step] 打开 **设置 → 随处访问 Mem**。 如果还需要局域网访问,可打开 **Allow devices on same Wi-Fi**。 开启后会自动生成 API key。同一 Wi-Fi 上的其他设备连接时需要这个 key。它和 tunnel 用的是同一个 key,可以在下方出现的 **API Key** 区域复制。
### 选择 Quick link 并启动 [#选择-quick-link-并启动-step] 在 **Access from Anywhere** 选择 **Quick link**,点击 **Start**。 等待状态变为 **Live**。
### 复制 URL 和 API Key [#复制-url-和-api-key-step] 在 **Ready to connect** 区域复制: * **URL** * **API key** 需要换新 key 时点击 **Rotate**。
### 在另一台设备验证 [#在另一台设备验证-step] ```bash export NMEM_API_URL="https://" export NMEM_API_KEY="nmem_..." nmem status ``` 预期:`status ok`。 有些 VPS、公司网络、校园网或运营商网络会拦截 UDP/QUIC。现在如果 QUIC 启动失败,Mem 会自动改用 HTTP/2 重试 Cloudflare tunnel。 如果你希望在 headless / systemd 部署里直接强制使用 TCP,可设置: ```bash export TUNNEL_TRANSPORT_PROTOCOL=http2 ``` 然后重启 Mem,再重新启动 Access Anywhere。
## 路径 B:Cloudflare 账号(固定 URL) [#路径-bcloudflare-账号固定-url] 你需要先在 Cloudflare DNS 中管理自己的域名(例如 `example.com`),才能拿到固定 URL。
### 创建 tunnel 并复制 token [#创建-tunnel-并复制-token-step] 在 Cloudflare Zero Trust 中: 1. 打开 NetworksConnectorsCreate a tunnel。 2. 点击 Select CloudflaredCloudflare Connectors 页面 3. 输入 tunnel 名称并点击 Save tunnel填写 tunnel 名称 4. 在 **Install and run connectors** 中,Cloudflare 会给出一条命令,例如: ```bash sudo cloudflared service install ... ``` 这条命令你不用真的去执行。隧道由 Mem 替你跑起来,你只需要里面的 token。复制 token 后,在 Mem 里粘贴: * 原始 token;或 * 完整命令(支持 `service install `、`--token `、`--token=`)。 Mem 会自动提取 token。 桌面应用以及 `.deb` / AppImage 主机安装里,Mem 自带了 `cloudflared`,你从来不需要自己装或自己跑。这一点没有变化。 [Docker 部署](/zh/docs/docker) 现在也把 `cloudflared` 打进了镜像(默认 tag 和 `:cuda` tag 都有)。早先那种「在容器里另起一个 cloudflared sidecar」的说法已经不适用了:直接在 **设置 → 随处访问** 或容器内的 `nmem` CLI 里配置,隧道由服务器自己管理。 从命令复制 token
### 创建 Public Hostname 路由 [#创建-public-hostname-路由-step] 在 tunnel 的路由 / hostname routes 页面: 1. 创建 hostname(如 `mem.example.com`)。 2. 绑定到你刚创建的 tunnel。 这一步会创建可用的固定公网 URL。 Hostname routes 列表 创建 hostname 路由
### 将 hostname 映射到本机 Mem API [#将-hostname-映射到本机-mem-api-step] 1. 打开 NetworksConnectors → 你创建的 tunnel。 进入 tunnel 详情 2. 在 Published application routes 点击 Add a published application route添加应用路由 3. 将 `mem.example.com` 映射到本机 Mem 服务: * Subdomain:`mem` * Domain:你在 Cloudflare 托管的域名 * Service Type:`HTTP` * Service URL:`http://127.0.0.1:14242` 不要追加 `/remote-api`。 映射到本机 Mem API
### 回到 Mem 保存并启动 [#回到-mem-保存并启动-step] 回到 设置随处访问 MemCloudflare account: * Public URL:`https://mem.example.com` * Tunnel token:粘贴原始 token 或完整 `cloudflared` 命令 然后: * 点击 Save * 点击 Start * 如需新 key,点击 Rotate * 点击 Copy 复制 URL 和 API key
### 在另一台设备验证 [#在另一台设备验证-step-1] ```bash export NMEM_API_URL="https://mem.example.com" export NMEM_API_KEY="nmem_..." nmem status ``` 预期:`status ok`。
## 在其他客户端使用 [#在其他客户端使用] 先按场景选择最合适的连接入口: * **移动应用**:在手机或平板上获得原生 iOS / Android 体验 * **桌面应用**:从第二台电脑获得完整体验(包括 AI Now) * **浏览器**:从任意设备快速访问 * **`~/.nowledge-mem/config.json`**:`nmem config client ...` 写入的共享客户端配置文件,`nmem`、OpenClaw、Bub、Claude Code 等连接都会自动复用 * **浏览器扩展**:在 SidePanel 设置中粘贴 URL + key * **ChatGPT / OAuth MCP 客户端**:粘贴公开 `/mcp` endpoint,并通过 OAuth 授权 Mem * **直接 MCP**:用于没有更好专属路径的 MCP 客户端,或像 Codex 这样需要插件包 + MCP 一起配合的 hybrid 宿主 ### 移动应用(iOS 和 Android) [#移动应用ios-和-android] 移动应用目前为 Alpha 版本。iOS 通过 TestFlight 提供,Android 通过未签名 APK 下载。请通过 [Discord](https://discord.gg/nowledge) 获取 TestFlight 访问权限,或前往[社区发布页面](https://github.com/nowledge-co/community/releases/tag/v0.6.11)下载 APK。 移动应用是一个原生壳应用,连接到你的 Mem 服务器,本身不需要本地数据库或 Python 后端。你可以在手机上使用完整功能:搜索、记忆、对话、文库、知识图谱和动态。 1. 安装应用(iOS 使用 TestFlight,Android 使用 APK) 2. 输入你的 **Mem URL** 和 **API Key** 3. 点击**连接** 应用会在本地存储你的凭据,后续启动时自动重新连接。 ### 桌面应用(客户端模式) [#桌面应用客户端模式] 在另一台电脑上安装 Nowledge Mem,然后连接到你的主实例: 1. 打开**设置 → 随处访问** 2. 输入主 Mem 的 URL 和 API Key 3. 点击**连接** 你将获得完整的桌面体验:搜索、记忆、对话、文库、知识图谱以及 **AI Now**。AI Now 运行在你连接的 Mem 服务器上,并使用那台服务器的 LLM 配置。客户端不需要额外设置模型。 标题栏显示 **远程** 表示你已连接到另一台 Mem。AI Now 的会话、消息历史和粘贴的图片会跟随那台服务器,因此你可以在不同客户端之间切换。 ### 浏览器 [#浏览器] 在你的 Mem URL 后面加上 `/app` 打开即可,例如 `https://mem.example.com/app`,支持任何现代浏览器。 输入 API key 登录后,你可以使用搜索、记忆、对话、知识图谱和 AI Now。AI Now 会显示同一台服务器上的会话列表。 这是从未安装桌面端或移动应用的电脑上查看知识库最快的方式。 在手机上,推荐使用原生移动应用(见上方)。如果你偏好浏览器,点击 **分享 → 添加到主屏幕**(iOS)或安装横幅(Android),即可像快捷方式一样全屏打开,无需浏览器边框。 ### nmem CLI [#nmem-cli] **同一台电脑无需手动配置。** 如果 `nmem` 与桌面应用运行在同一台电脑上,当"随时访问"生成 API 密钥时会自动创建此文件。你可以直接运行 `nmem status`。 先在这台机器上执行一次,之后所有 `nmem` 命令、以及所有使用 `nmem` 的插件,都会自动连接: ```bash nmem config client set url https:// nmem config client set api-key nmem_... ``` ```bash nmem status # 自动读取 config.json nmem m search "project notes" ``` 这条命令写入的是当前机器的本地客户端连接配置。OpenClaw、Bub、Claude Code、Claude Desktop 等集成都直接复用它。它和 `nmem config access ...` 不同,后者控制的是 Mem 服务器如何向其他设备开放访问。 OpenClaw、Bub、Claude Code 插件也读取这个文件。一个文件,所有工具自动连接。 CI 或脚本场景也可以使用 `NMEM_API_URL` 和 `NMEM_API_KEY` 环境变量。优先级:CLI 参数 > 环境变量 > 配置文件 > 默认值。 ### 浏览器扩展(侧边面板或侧栏) [#浏览器扩展侧边面板或侧栏] 打开任意受支持的 AI 对话页面,然后打开 **Nowledge Mem Exchange** 侧边栏: 1. 点击 **Settings** 2. 在 **Access Mem Anywhere** 中粘贴从 Mem 桌面端复制的终端环境变量: ```bash export NMEM_API_URL="https://" export NMEM_API_KEY="nmem_..." ``` 3. 点击 **Fill URL + key** 4. 点击 **Save** 5. 点击 **Test connection**(应显示成功) 也可以在同一区域手动填写 URL + key。 ### ChatGPT / OAuth MCP 客户端 [#chatgpt--oauth-mcp-客户端] 有些云端 MCP 客户端,包括 ChatGPT Connectors,不能使用私有 `nmem_` API-key 请求头。对这些客户端,请使用 **Remote MCP over OAuth**: 1. 在 Mem 中打开**连接 → AI 工具 → 通过 OAuth 远程连接 MCP**。 2. 点击**开始设置**。 3. 让 Mem 在你准备用来授权 AI 客户端的同一个浏览器 Profile 中打开配对页面。 4. 复制 Access Anywhere MCP endpoint。它必须以 `/mcp` 结尾。 5. 把这个 URL 粘贴到 AI 客户端的 MCP connector 设置里。 6. 在同一个浏览器 Profile 的 OAuth 页面授权 Mem。 对 ChatGPT 来说,先从 ChatGPT 网页设置创建 connector。连接完成后,同一个 connector 也能在 ChatGPT 网页版和桌面版使用;在对话中输入 `@Nowledge Mem`,即可让 ChatGPT 搜索 Mem。 ChatGPT 截图步骤见 [ChatGPT 网页版与桌面版](/zh/docs/integrations/chatgpt-web)。 ### OpenClaw 插件 [#openclaw-插件] 如果你已经创建了 `~/.nowledge-mem/config.json`(上面 nmem CLI 步骤中的那个文件),那就已经搞定了,OpenClaw 插件会自动读取同一个文件。 如果还没有,现在创建即可: ```json title="~/.nowledge-mem/config.json" { "apiUrl": "https://", "apiKey": "nmem_..." } ``` 也可以在 OpenClaw 仪表盘的 **Automation → Plugins → Nowledge Mem** 中配置。 API key 只通过环境变量传给 `nmem` 子进程,不会出现在日志或命令行参数里。插件附带的行为技能(如 memory guide)在远程模式下照常工作,它们是插件的一部分,不依赖服务端。 ### Bub 插件 [#bub-插件] 如果你已经在这台机器上执行过 `nmem config client ...`,Bub 插件会自动读取同一份共享客户端配置。 ```json title="~/.nowledge-mem/config.json" { "apiUrl": "https://", "apiKey": "nmem_..." } ``` 也可以在启动 Bub 前设置 `NMEM_API_URL` 和 `NMEM_API_KEY` 环境变量。 ### Alma 插件 [#alma-插件] 两种方式都可以,选你顺手的: **方式 A:插件设置(推荐)** 在 Alma 中打开设置,配置 Nowledge Mem 插件: * **`nowledgeMem.apiUrl`**:远程 URL(如 `https://mem.example.com`)。留空则使用本机。 * **`nowledgeMem.apiKey`**:Mem API key(`nmem_...`)。仅通过环境变量传递,不会出现在日志或命令行参数中。 插件在激活日志中会显示 `mode=remote` 或 `mode=local`,方便确认当前模式。 **方式 B:环境变量** 在启动 Alma 前设置: ```bash export NMEM_API_URL="https://" export NMEM_API_KEY="nmem_..." ``` 两种方式效果相同。想让配置自成一体用方式 A;想把密钥放在配置文件之外用方式 B。 ### MCP / 智能体节点 [#mcp--智能体节点] MCP 客户端通过 HTTP 连接。这条连接由 MCP 宿主自己管理,所以它不会自动读取 `~/.nowledge-mem/config.json`。 如果你已经用 `nmem config client ...` 配好了这台机器,可以直接从同一份 URL 和 API key 生成宿主配置: ```bash nmem config mcp show --host codex nmem config mcp show --host gemini-cli nmem config mcp show --host cursor nmem config mcp show --host claude-desktop ``` 把生成的配置粘贴到对应宿主的 MCP 设置里。生成内容会包含你的 API key,请只放在该宿主的私人用户配置中。 如果手写配置,需要在 `Authorization` 请求头中传入 API key,或使用 `X-NMEM-API-Key` 头。 请使用带结尾斜杠的精确 MCP 地址:`https:///mcp/`。 **Cursor**(`~/.cursor/mcp.json` 或工作区 `.cursor/mcp.json`): ```json { "mcpServers": { "nowledge-mem": { "url": "https:///mcp/", "type": "streamableHttp", "headers": { "APP": "Cursor", "Authorization": "Bearer nmem_..." } } } } ``` 或者 ```json { "mcpServers": { "nowledge-mem": { "url": "https:///mcp/", "type": "streamableHttp", "headers": { "APP": "Cursor", "X-NMEM-API-Key": "nmem_..." } } } } ``` **Claude Desktop.** 如果你使用 [Nowledge Mem 扩展](/zh/docs/integrations/claude-desktop),它会直接读取和 `nmem` 一样的共享客户端配置: * macOS / Linux: `~/.nowledge-mem/config.json` * Windows: `%USERPROFILE%\.nowledge-mem\config.json` ```json { "apiUrl": "https://", "apiKey": "nmem_..." } ``` 如果你在同一台机器上的 Nowledge Mem 桌面端里开启了「随处访问 Mem」,这个文件通常会自动写好。 或者手动编辑 `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json { "mcpServers": { "nowledge-mem": { "url": "https:///mcp/", "type": "streamableHttp", "headers": { "APP": "Claude", "Authorization": "Bearer nmem_..." } } } } ``` **Codex**(`~/.codex/config.toml`,桌面端和 CLI 共用): 如果你已经按 [Codex 指南](/zh/docs/integrations/codex-cli) 装好了专属插件包,请保留那条路径。插件默认内置本地 MCP 地址;远程 Mem 场景下,运行 `nmem config mcp show --host codex`,把生成的 TOML 放进 `~/.codex/config.toml`。 **Gemini CLI**(`settings.json`,用于覆盖 Gemini 扩展的默认连接): 如果你安装了 [Gemini CLI 扩展](/zh/docs/integrations/gemini-cli),扩展默认内置本地 MCP 地址。远程 Mem 场景下,运行 `nmem config mcp show --host gemini-cli`,把生成的 JSON 放进 Gemini 用户设置。 **Claude Code.** 安装 [Nowledge Mem 插件](/zh/docs/integrations/claude-code)即可获得自动工作记忆简报、搜索和会话捕获。远程模式下,在客户端机器上执行一次 `nmem config client set url ...` 和 `nmem config client set api-key ...` 即可,插件中的 `nmem` 命令会自动读取这份共享客户端配置。 **CI / 其他基于 Shell 的工具。** 设置 `NMEM_API_URL` 和 `NMEM_API_KEY` 环境变量即可。 对于 `nmem t save --from claude-code`、`grok`、`gemini-cli`、`codex` 这类基于真实会话记录的保存,远程模式并不意味着 Mem 服务器会去远程读取这些智能体的会话文件。真正的本地发现与解析,仍然发生在运行该智能体的那台客户端机器上,然后再把规范化后的线程数据上传到 Mem。 ## 快速健康检查 [#快速健康检查] ```bash curl -H "Authorization: Bearer $NMEM_API_KEY" "$NMEM_API_URL/health" ``` 预期:返回健康检查 JSON。 错误 key 检查: ```bash curl -H "Authorization: Bearer wrong_key" "$NMEM_API_URL/health" ``` 预期:`401`。 如果代理会剥离鉴权头: ```bash curl "$NMEM_API_URL/health?nmem_api_key=$NMEM_API_KEY" ``` ## 安全与运行建议 [#安全与运行建议] * 所有远程请求都需要 API key,包括 tunnel 和局域网连接。 * 开启局域网访问后,同一 Wi-Fi 上的其他设备连接时需要 API key。来自这台电脑本身的请求始终免 key,除非你在设置中开启了 **Require API key on localhost**。 * 可随时在设置中 **Rotate**(旧 key 立即失效)。 * 首次成功 **Start** 后,应用重启会自动重连,直到你点击 **Stop**。 * Browse-Now / Browser Bridge 自动化端点仅限本机访问,不会通过「随处访问 Mem」暴露。 * 不需要远程访问时请关闭 tunnel。 ## 常见问题 [#常见问题] * **Start 超时**:网络/代理可能拦截了 Cloudflare 流量,重试或切换到账号模式。 * **`401 Missing API key`**:通常是代理移除了鉴权头。升级 `nmem`,或手动使用 query 回退验证。 * **`429 Too many invalid auth attempts`**:错误 key 被连续重试。重新复制 key 或点击 **Rotate**。 # 搜索与相关性 (/docs/zh/search-relevance) 搜索由多信号评分、时间衰减和反馈循环驱动。下面逐一说明。 ## 评分管道 [#评分管道] 搜索时,Nowledge Mem 不只匹配关键词,而是综合多个信号来排列结果。 Nowledge Mem 评分管道 ### 语义评分 [#语义评分] 这一组信号负责找出和你想找的内容意思对得上的记忆: * **按含义搜索**:按语义相似度查找记忆,而不只是精确字面匹配。搜索"设计模式",也能找到关于"架构方法"的记忆。 * **关键词搜索**:用 BM25 排序,抓住精确短语和技术术语。 * **标签匹配**:带有匹配标签的记忆会被提上来。 * **图遍历**:顺着实体和主题社区,找到相互关联的记忆。 ### 衰减、置信度与时间评分 [#衰减置信度与时间评分] 这一组信号会根据新鲜度、验证程度和你的使用情况来调整排序: * **时效性**:最近访问过的记忆得分更高。衰减按指数曲线计算,半衰期约 30 天。 * **频率**:你反复访问的记忆会越来越稳固(按对数缩放,收益递减)。 * **重要性底线**:重要性高的记忆即使没怎么用,也保有一个最低的可见度。 * **置信度**:被使用过、并在知识图谱里建立了连接的记忆会得到一点加成。置信度只随证据增长,不会下降。 * **时间匹配**:事件时间和你查询对得上的记忆会被提升(仅深度模式)。 这几组信号汇总成最终分数,决定结果的排序。 ## 记忆衰减 [#记忆衰减] 记忆会随时间自然消退,使用即强化。 ### 工作原理 [#工作原理] **时效性**:昨天访问的记忆,得分比三个月前的高出很多。半衰期 30 天的意思是:只要不再访问,分数大约每个月减半。 **频率**:第 10 次访问的作用,比第 100 次大得多。早期反复访问把记忆"焊"得更牢,之后收益递减。 **重要性底线**:重要性高的记忆永远不会完全衰减。即使长期没访问,也保有最低的可见度,避免基础知识丢失。 ### 搜索强化 [#搜索强化] 从 v0.6.6 开始,每次搜索展示都会更新记忆的最后访问时间和访问次数,自动增强其新鲜度分数。 在此之前,只有真正点开才会更新新鲜度。现在,出现在搜索结果里也算一次轻度访问,避免那些一直有用的记忆悄悄衰减下去。 ### 置信度 [#置信度] 置信度评分在每日新鲜度刷新时计算。 和衰减各自独立,每条记忆还会积累一个**置信度评分**,反映它被验证到什么程度。置信度从一个基线起步,证据越多就越高: * **搜索使用**:展示次数、点击和阅读时间 * **知识图谱**:被其他记忆确认或丰富的记忆,或被用作知识结晶来源的记忆 新鲜度会随时间衰减,置信度则只增不减。一条经常被访问、点击、并和其他知识关联起来的记忆,在语义匹配相当的情况下,得分会比刚创建的记忆更高。 这个影响不大(置信度约占最终评分的 5%),但能让沉淀下来的知识始终占一点先手。 ### 这意味着什么 [#这意味着什么] * 常用的知识保持新鲜,出现在搜索结果里也算 * 旧记忆不会消失,只是在同样相关时排得靠后一些 * 不管你怎么访问,重要的知识都会一直留着 * 被验证过的记忆会得到一点排名加成 * 系统会自动从你的使用习惯里学习 ### 自动维护 [#自动维护] 这些功能为可选启用,位于设置 → 处理 → 高级。 为了保持衰减分数准确和记忆质量,Nowledge Mem 可以运行后台维护: * **新鲜度刷新**:每日任务重新计算所有记忆的衰减和置信度分数,使排序保持准确。它只更新分数,不会归档、合并、删除或改写记忆。 * **Memory Maintenance**:先审查再维护的任务,用来发现记忆增长压力。它会在 Timeline 里准备审查建议:低风险事实/事件可以移出日常召回,重要的偏好、决定、流程、计划、经验和上下文则进入语义整理。 * **记忆整理**:每周任务识别相似或冗余记忆的聚类,可以创建关联、摘要或审查项。它不会静默删除你保存的记忆正文。 ## 时间理解 [#时间理解] Nowledge Mem 理解两种时间。 ### 事件时间 vs 记录时间 [#事件时间-vs-记录时间] **事件时间**是事情真正发生的时间: * "2020年的产品发布" * "上季度的决定" * "在我们迁移之前" **记录时间**是你保存记忆的时间。你今天可能记录一条关于2020年事件的记忆。 这对于像"关于2020年事件的最近记忆"这样的查询很重要:你最近保存的东西(记录时间)关于2020年的事件(事件时间)。 ### 时间意图检测 [#时间意图检测] 时间意图检测需要深度模式搜索。在快速模式下,时间引用仅按关键词匹配。 在深度模式下,系统解释时间引用: | 查询 | 理解 | | -------------- | ------------- | | "2023年的决定" | 事件时间:2023 | | "最近的记忆" | 记录时间:最近 | | "关于2020年的最近记忆" | 事件:2020,记录:最近 | | "迁移之前" | 事件:在那个事件之前 | "上季度"、"大约 2020 年"、"今年初"这类模糊说法,会被转换成实际可用的时间过滤条件。 ### 日期精度 [#日期精度] 当你保存关于"2020年初"的记忆时,系统: 1. 规范化为可搜索的日期(2020-01-01) 2. 跟踪精度级别(年、月或日) 3. 保留原始含义以实现准确匹配 这让"2020年的记忆"(年精度)与"2020年1月的记忆"(月精度)工作方式不同。 ## 反馈循环 [#反馈循环] 你的使用模式持续改进搜索相关性。 ### 我们跟踪什么 [#我们跟踪什么] | 信号 | 捕获的内容 | | -------- | ----------- | | **展示次数** | 记忆在结果中出现的频率 | | **点击** | 当你打开记忆查看详情时 | | **停留时间** | 你花多长时间阅读 | ### 如何改进搜索 [#如何改进搜索] * 点击率高,说明这条记忆确实有用 * 停留时间长,说明内容有价值 * 经常被展示却没人点,可能说明相关性在下降 你什么都不用做,正常使用就行。 ### 自动标签 [#自动标签] 创建新记忆时自动分配标签。 每当你创建一条记忆,后台智能会读一遍内容,给它打上 2–4 个描述性标签。它会优先复用已有标签,并统一用小写加连字符的写法(如 `machine-learning` 或 `project-alpha`)。这样一来,记忆从创建那一刻起就归好了类,你不用自己动手标记。 ## 图驱动的发现 [#图驱动的发现] 知识图谱通过实体连接扩展搜索范围。 ### 记忆如何连接 [#记忆如何连接] 每条记忆可以链接到: * **实体**:提到的人员、概念、技术、地点 * **其他记忆**:通过共享实体或关系 * **社区**:图分析检测到的主题集群 ### 通过连接搜索 [#通过连接搜索] **经由实体**:即使标签不同,也能借助 PostgreSQL、索引这类共享实体,找到关于"数据库优化"的记忆。 **经由社区**:搜索"认证"时,可能会带出你"安全实践"社区里的记忆。 **图扩展**:从一条记忆出发,顺藤摸瓜找到相关联的知识。 ## 搜索模式 [#搜索模式] 所有界面都有两种模式可用: ### 快速模式 [#快速模式] * 通常不到100毫秒响应 * 直接语义和关键词匹配 * 实体和社区搜索,无需语言模型分析 * 最适合快速查找 ### 深度模式 [#深度模式] * 完整的语言模型分析 * **时间意图检测**(例如,"最近在做的;过去十年的社交活动") * 查询扩展以获得更好的召回率 * 上下文感知的策略加权 * 更适合探索性搜索 两种模式都适用于主搜索、全局启动器和 API。 ## 结果透明度 [#结果透明度] 每条结果都附带排序原因。 ### 搜索查询详情 [#搜索查询详情] 每次搜索后,你可以查看你的查询如何被解释的详细分析: * 使用了哪些搜索策略 * 时间意图检测结果(在深度模式下) * 查询扩展和实体提取 ### 分数分解 [#分数分解] 把鼠标停在任意一条结果的分数上,就能看到它是怎么算出来的: * **语义分数**:内容与你的查询匹配程度 * **衰减分数**:基于时效性和频率的新鲜度 * **置信度**:通过使用和图连接的验证程度 * **时间提升**:事件时间相关性(适用时) * **图信号**:实体和社区连接 搜索查询详情 这帮助你理解使用模式如何影响排序,以及某条记忆为什么会出现在特定查询中。 # Linux 服务器部署 (/docs/zh/server-deployment) Nowledge Mem 可以在没有图形界面的 Linux 服务器上以**无头模式**运行。真正的服务器部署,建议直接使用 Linux 安装包,然后通过命令行管理;之后你可以在同一台机器的浏览器里打开内置 Web App,也可以用 API key 让其他客户端连接。 每日简报、洞察检测、知识图谱丰富等后台智能能力,需要先配好远程 LLM,也取决于你当前版本拥有的授权。本页只讲怎么部署,不谈套餐定价。 `sudo` 只用于安装软件包和安装 system 服务。 平时运行 `nmem serve`、`nmem config ...`、`nmem license ...`、`nmem tui` 这类命令时,请使用你的普通 Linux 用户。 新版本会默认阻止你通过 `sudo` 或其他提权方式去运行这些会写本地状态的命令,避免 fresh install 之后在错误的用户环境里悄悄留下 `root` 属主的 Mem 文件。 如果你本来就是直接登录 `root`、并且希望把 Mem 放在 `/root` 下运行,这种场景仍然支持。 ## 系统要求 [#系统要求] | 要求 | 规格 | | ------------ | ----------------------------------------------------------- | | **操作系统** | Ubuntu 22.04+、Debian 12+,或兼容版本(通过 AppImage) | | **架构** | `.deb` / AppImage 为 `x86_64`;Docker 同时支持 `x86_64` 与 `arm64` | | **内存 (RAM)** | 最低 8 GiB(推荐 16 GiB) | | **磁盘空间** | 10 GiB 可用空间 | | **依赖** | `libgtk-3-0`、`libwebkit2gtk-4.1-0`、`zstd`(`.deb` 自动安装) | ## 安装 [#安装] 设置 APT 仓库以通过 `apt upgrade` 自动更新: ```bash curl -fsSL https://nowledge-co.github.io/community/apt/install.sh | sudo bash sudo apt-get install nowledge-mem ``` 添加 GPG 签名密钥和仓库源。之后如果只想更新 Mem,可运行 `sudo apt-get update && sudo apt-get install --only-upgrade nowledge-mem`。常规整机升级仍可使用 `sudo apt-get update && sudo apt-get upgrade`,或通过 `unattended-upgrades`(如已配置)自动应用。 如果你想把 Mem 跑在 VPS、NAS、云主机或 homelab 上以无头模式提供服务,Docker 是单独的一条路径: ```bash git clone https://github.com/nowledge-co/community.git cd community/docker ./nmemctl up ``` 完整内容请看 **[Docker 部署](/zh/docs/docker)**:多架构(`amd64` + `arm64`)、「给你的 Agent」技能、bind mount 布局、镜像验证、Caddy TLS、备份与迁移,以及可选的网页内自动升级。 ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # 下载 .deb curl -A "$BROWSER_UA" -L -o nowledge-mem.deb https://nowled.ge/download-mem-deb # 安装包 sudo dpkg -i nowledge-mem.deb # 修复缺失的依赖 sudo apt-get install -f -y ``` ```bash BROWSER_UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # 下载 AppImage curl -A "$BROWSER_UA" -L -o nowledge-mem.AppImage https://nowled.ge/download-mem-appimage # 仅适合便携式手动运行 chmod +x nowledge-mem.AppImage ./nowledge-mem.AppImage ``` 如果你要的是一台真正的无头 Linux 服务器,请优先用 APT、Docker 或 `.deb`。 AppImage 更适合便携式、手动运行,不适合作为长期的 server + systemd 主路径。 它不会把 `nmem` CLI 装进 PATH,所以在没有桌面会话的机器上,也不是最顺手的 `nmem` 工作流。 如果你是在终端里下载安装包,请直接照着上面的命令执行。 这些命令已经带上了浏览器 User-Agent,因为有些下载链接会拦截普通的 `curl` / `wget`,直接返回 `403`。 APT 和 `.deb` 安装后会自动完成以下操作: * 解压内置的 Python 运行时 * 在 `/usr/local/bin/nmem` 创建 `nmem` CLI * 配置 APT 仓库以自动更新(通过 APT 安装时) * 设置桌面启动项(在无头服务器上可忽略) 验证 CLI 可用: ```bash nmem --version ``` 如果你用的是 AppImage,那么之后每次都需要直接运行 AppImage 文件。它不会把 `nmem` 命令加到 PATH 里。 ## Docker(预览) [#docker预览] 本页讲的是 Linux 服务器上的 `.deb` / APT / systemd 路径。Docker 是另一条独立的部署路径,后端、网页应用、数据都和这里一样,只是生命周期(compose、bind mount、镜像升级、可选的网页内自动升级)和 .deb/systemd 差别足够大,所以单独放一页。 完整内容请看 **[Docker 部署](/zh/docs/docker)**:什么时候选 Docker(VPS、NAS、云主机、homelab)、支持的架构(`amd64` + `arm64`)、用 `nmemctl` 快速开始、「给你的 Agent」技能、数据放在哪、内存调优、镜像验证、Caddy TLS、备份与迁移,以及可选的网页内自动升级。 ## 快速开始 [#快速开始] 如果你是要搭一台真正的 Linux 服务器,先把后台服务装好。这样后面的许可证、模型、配置命令都能在新的 SSH 会话里直接用,也不怕重启以后丢掉。
### 先安装后台服务 [#先安装后台服务-step] 服务器场景推荐: ```bash sudo nmem service install --service-user ``` 如果你确实要用用户级服务: ```bash nmem service install --user ``` 无头服务器上,优先用 system 服务。 用户级服务只有在该账号开启 lingering 之后,才会在退出登录和重启后继续存在: ```bash sudo loginctl enable-linger ```
### 确认服务已经起来 [#确认服务已经起来-step] ```bash nmem service status nmem status ``` 想确认正在运行的到底是哪个构建,打印一下 build SHA: ```bash nmem-server --build-info ``` `GET /health` 的 `.build_sha` 字段也是同一个值,方便通过网络或脚本核对一次部署。
### 激活许可证 [#激活许可证-step] ```bash nmem license activate <许可证密钥> # 通常会自动从密钥中识别邮箱 nmem license status # 验证激活状态 nmem license renew # 以后如果授权过期,可刷新这台设备的授权 ``` 如果自动识别失败,再显式运行 `nmem license activate <许可证密钥> <邮箱>`。
### 打开 Web App [#打开-web-app-step] 先把浏览器登录信息打印出来: ```bash nmem key --show-login ``` 如果你当前这个版本还不支持 `--show-login`,就先运行: ```bash nmem key ``` 然后打开它打印出来的地址。默认情况下通常是: ```text http://127.0.0.1:14242/app ``` 无头服务器上,浏览器通常在另一台电脑上。请直接使用 `nmem key --show-login` 打印出来的那个地址和端口。 如果需要 SSH 转发,也转发同一个端口: ```bash ssh -L :127.0.0.1: ``` 然后在你自己的浏览器里打开对应的本地地址,再粘贴 API key。
### 下载搜索索引模型 [#下载搜索索引模型-step] ```bash nmem models download nmem models status # 验证安装 ``` 下载用于混合搜索的索引模型(约 500 MB),只需下载一次。 如果你是在无头服务器上使用,建议把下面两个命令当作搜索健康检查入口: * `nmem status`:看搜索现在是已就绪、需要重建,还是只是在后台补齐元数据 * `nmem models status`:同时查看模型状态,以及当前搜索索引是否需要你介入 脚本或远程核查时,`GET /health` 给的是同一套信号,重点看两个字段: * `embedding.mode` 取值为 `remote`、`local-gguf` 或 `local-hash-fallback`。其中 `local-hash-fallback` 表示没有配真正的嵌入器,语义搜索会降级,但关键词搜索照常工作,看到它就该去配远程服务商或下载本地模型了。 * `reindex_needed` 为 `true` 表示搜索索引已过期,通常是嵌入身份变了(换了服务商或模型)之后。 服务器不会为了重建索引卡在启动阶段。它会立刻起来,索引追上之前先用关键词(FTS)搜索顶着,索引过期时只是悄悄退回关键词结果,不会报错。等你准备好了,去 **设置 → Memory Processing → Search** 触发重建,或用 `POST /search-index/reindex`。如果你更想让服务器启动时就把索引重建完,启动前设置 `NMEM_BOOT_AUTO_REINDEX=1` 即可。
### 配置 LLM 提供商 [#配置-llm-提供商-step] Linux 上需要远程 LLM(不支持本地 LLM): ```bash nmem config provider set anthropic \ --api-key sk-ant-xxx \ --model claude-sonnet-4-20250514 nmem config provider test # 验证连接 ``` 支持的提供商包括:`anthropic`、`openai`、`gemini`、`xai`、`deepseek`、`minimax`、`zai`、`moonshot`、`ollama`、`openrouter` 以及 OpenAI 兼容端点。\ 完整提供商矩阵与注意事项见:[LLM 提供商](/zh/docs/llm-providers)。
### 启用后台智能 [#启用后台智能-step] ```bash nmem config settings set backgroundIntelligence true nmem config settings set autoDailyBriefing true ```
### 验证所有配置 [#验证所有配置-step] ```bash nmem status ```
### 如果你暂时不想装 systemd 服务 [#如果你暂时不想装-systemd-服务-step] 也可以先直接前台跑: ```bash nmem serve ``` 但要记住:这个终端会一直被占着。后面的 `nmem license ...`、`nmem models ...`、`nmem config ...` 需要在第二个终端里执行。
## 作为 systemd 服务运行 [#作为-systemd-服务运行] 生产部署建议使用 `nmem service install` 设置后台 systemd 服务,开机自动启动: ```bash # 以你的日常 Linux 用户身份安装、启用并启动 sudo nmem service install --service-user # 如果你本来就是从那个 Linux 用户直接 sudo 上来的,Mem 通常也能自动识别 sudo nmem service install # 自定义主机/端口 sudo nmem service install --service-user --host 0.0.0.0 --port 8080 ``` ```bash # 无需 root 权限 nmem service install --user ``` system 服务应当以你的日常 Linux 用户运行,而不是 `root`。 如果 `sudo` 不能正确识别目标账号,请加上 `--service-user `。 如果你用的是用户级服务,请直接以该用户运行 `nmem service install --user`,不要加 `sudo`。 如果你希望用户级服务在退出登录和重启后继续存在,还需要额外执行一次 `sudo loginctl enable-linger `。 如果你的 VPS 本来就是只用 `root`,并且你也是直接登录 `root`,那么 `nmem service install` 仍然可以一致地使用 `/root`。 如果你之前在旧版本里用 `root` 运行过,`~/.config/co.nowledge.mem.desktop/` 下面有些文件可能仍然属于 `root`。 这时许可证操作、LLM 提供商设置保存,或者 Access Anywhere 设置都可能失败,先把这些文件的属主改回运行服务的 Linux 用户。 新版本在发生这种情况时会直接告诉你是哪一个路径有问题。 常见修复命令如下: ```bash sudo chown -R : ~/.config/co.nowledge.mem.desktop sudo chown -R : ~/.local/share/NowledgeGraph ``` 如果你自定义了 `XDG_CONFIG_HOME` 或 `XDG_DATA_HOME`,请改成对应目录。 ### 管理服务 [#管理服务] ```bash nmem service status # 查看服务状态 nmem service logs -f # 跟踪服务日志 nmem service stop # 停止服务 nmem service start # 启动服务 nmem service uninstall # 停止、禁用并删除服务 ``` 如果安装的是用户级服务,请在任何 `nmem service` 命令后添加 `--user`。 ### serve 与 service 的区别 [#serve-与-service-的区别] | | `nmem serve` | `nmem service install` | | -------- | ------------ | ------------------------- | | **运行方式** | 前台(当前终端) | 后台(systemd) | | **何时停止** | Ctrl+C 或关闭终端 | `nmem service stop` 或系统关机 | | **开机自启** | 否 | 是(自动启用) | | **适用场景** | 测试、开发 | 生产部署 | ## 数据位置 [#数据位置] 所有数据(图数据库、搜索索引、版本元数据)存储在一个目录中: ``` ~/.local/share/NowledgeGraph/ ├── nowledge_graph_v2.db/ # KuzuDB 图数据库 ├── search_index/ # LanceDB 向量 + BM25 索引 └── db_version.json # Schema 版本追踪 ``` 服务器使用 `XDG_DATA_HOME`(默认为 `~/.local/share`)自动解析此路径。如需使用自定义位置,请在启动服务器**之前**设置 `NOWLEDGE_DB_PATH` 环境变量: ```bash export NOWLEDGE_DB_PATH=/mnt/data/NowledgeGraph/nowledge_graph_v2.db nmem serve ``` 旧版本将数据存储在运行 `nmem serve` 的工作目录下的 `./data/` 文件夹中。升级后,服务器会自动检测旧数据并打印迁移说明。如果数据似乎丢失,请参阅下方[故障排除:升级后数据丢失](#升级后数据丢失)。 ## 远程访问 [#远程访问] 默认情况下,`nmem serve` 只监听 `127.0.0.1`。这已经足够支持: * 服务器本机上的 `nmem` 命令 * 本机浏览器访问同一个本地地址(默认是 `http://127.0.0.1:14242/app`) 如果你把服务绑定到 `0.0.0.0` 或其他非 loopback 地址,Mem 就会要求其他设备带 API key 才能连接。需要时会自动生成 key,你之后也可以随时重新打印: ```bash nmem key # 或 nmem key --show-login ``` 当服务器已经可访问之后,客户端应优先走自己支持的最高层入口:先用原生连接,其次是插件设置界面或 `nmem` 配置,只有没有更好专属路径时才直接配置 MCP。 ```bash # 在服务器上 nmem serve nmem key ``` 在远程机器上安装独立 CLI: ```bash pip install nmem-cli # 或 uv pip install nmem-cli ``` 然后配置连接方式。推荐的持久化方式是: ```bash nmem config client set url http://你的服务器:14242 nmem config client set api-key nmem_... ``` 这会为当前机器写入 `~/.nowledge-mem/config.json`。如果你只想在当前终端会话里临时覆盖,再使用环境变量: ```bash title="临时终端覆盖" export NMEM_API_URL=http://你的服务器:14242 export NMEM_API_KEY="nmem_..." ``` ```bash nmem status nmem m search "查询内容" ``` 优先级:CLI 参数 > 环境变量 > 配置文件 > 默认值。 像 `nmem t save --from claude-code`、`grok`、`gemini-cli`、`codex` 这样的真实会话保存,仍然会在运行该智能体的客户端机器上读取本机会话文件。把 `nmem` 指向远程服务器,只会改变规范化数据上传到哪里,不会把会话发现工作转移到服务器端。 如需关闭鉴权(不建议在生产环境使用): ```bash nmem serve --no-auth ``` 默认情况下,其他机器连进来时都需要 API key。你如果启用了 localhost auth,本机浏览器访问 `/app` 也会要求输入 key。更严格的部署场景,建议再配合防火墙规则,或者直接使用[随处访问 Mem](/zh/docs/remote-access)的 Cloudflare tunnel。 ## 交互式 TUI [#交互式-tui] 使用 TUI 获得交互式终端体验: ```bash nmem tui ``` TUI 提供完整的设置管理界面,包括许可证激活、LLM 配置和知识处理开关。 它也打包进了 Docker 镜像。容器部署时,在容器里跑就行: ```bash docker compose exec -it mem nmem tui ``` 现在你也可以在 `Settings` 中直接配置 **Access Anywhere**(快速链接 / Cloudflare 账号稳定链接),而且同一个界面也能把本地 Web 登录地址和当前 API key 展示出来,所以即使在纯终端环境里,也能把 `/app` 的登录流程走通。\ 完整指南见:[随处访问 Mem](/zh/docs/remote-access)。 如果服务器网络会拦截 UDP/QUIC,导致 Access Anywhere 启动不上来,可以在重启 Mem 前先强制 Cloudflare 使用 HTTP/2: ```bash export TUNNEL_TRANSPORT_PROTOCOL=http2 ``` ## 配置参考 [#配置参考] ### 环境变量 [#环境变量] | 变量 | 默认值 | 描述 | | ----------------------- | ------------------------ | ------------------------------------ | | `NMEM_API_URL` | `http://127.0.0.1:14242` | CLI 命令的服务器地址 | | `NMEM_API_KEY` | `-` | 用于鉴权的 API key | | `NOWLEDGE_DB_PATH` | 自动检测 | 覆盖数据库位置 | | `NOWLEDGE_BACKEND_HOST` | `127.0.0.1` | 服务器绑定地址 | | `NMEM_LAN_AUTH` | `-` | 设为 `disabled` 可跳过鉴权(等同于 `--no-auth`) | ### CLI 命令摘要 [#cli-命令摘要] | 命令 | 描述 | | -------------------------------------------- | -------------------------- | | `nmem serve` | 启动服务器(默认只监听本机) | | `nmem serve --no-auth` | 启动服务器但不要求 API key 鉴权 | | `nmem service install` | 安装并启动 systemd 服务 | | `nmem service status` | 查看 systemd 服务状态 | | `nmem service logs -f` | 跟踪服务日志 | | `nmem service stop` / `start` | 停止或启动服务 | | `nmem service uninstall` | 删除 systemd 服务 | | `nmem status` | 检查服务器状态 | | `nmem license activate [email]` | 激活许可证(通常会自动识别邮箱) | | `nmem license renew` | 刷新或续期这台设备的授权 | | `nmem models download` | 下载索引模型 | | `nmem config provider set

--api-key ` | 配置 LLM 提供商 | | `nmem config provider test` | 测试 LLM 连接 | | `nmem config settings` | 显示处理设置 | | `nmem config settings set ` | 更新设置 | | `nmem update` | 检查可用更新 | | `nmem update apply` | 下载并应用更新 | | `nmem tui` | 交互式终端 UI | | `nmem key` | 打印当前 API key | | `nmem key --show-login` | 同时打印本地 Web App 地址和 API key | ## 故障排除 [#故障排除] ### 升级后数据丢失 [#升级后数据丢失] 旧版本(0.7 之前)将数据库存储在运行 `nmem serve` 的工作目录下的 `./data/` 文件夹中。当前版本将数据存储在标准位置(`~/.local/share/NowledgeGraph/`)。如果升级后记忆消失了,你的数据很可能仍在磁盘上,只是在旧位置。

#### 查找旧数据 [#查找旧数据-step] 搜索旧数据库可能存在的常见位置: ```bash find / -name "nowledge_graph*.db" -type d 2>/dev/null ``` 常见位置包括: * `~/data/nowledge_graph.db`,如果从主目录运行 `nmem serve` * `/data/nowledge_graph.db`,如果 systemd 系统服务在 `/` 目录下运行(未设置 `WorkingDirectory`) * `/你运行nmem的路径/data/nowledge_graph.db`,其他工作目录
#### 移动到标准位置 [#移动到标准位置-step] ```bash # 先停止服务器 nmem service stop # 如果使用 systemd # 或按 Ctrl+C # 如果在前台运行 # 如需创建标准目录 mkdir -p ~/.local/share/NowledgeGraph # 移动数据库和相关文件 mv /旧路径/data/nowledge_graph*.db* ~/.local/share/NowledgeGraph/ mv /旧路径/data/search_index ~/.local/share/NowledgeGraph/ 2>/dev/null mv /旧路径/data/db_version.json ~/.local/share/NowledgeGraph/ 2>/dev/null # 重启服务器 nmem serve # 或: nmem service start ```
#### 验证恢复 [#验证恢复-step] ```bash nmem m search "测试" # 搜索你的记忆 nmem status # 检查服务器状态 ``` 从当前版本开始,`nmem serve` 会在启动时打印数据库路径,方便确认使用的存储位置。如果在 `./data/` 下检测到旧数据,服务器会自动打印迁移说明。
## 下一步 [#下一步] * **[CLI 参考](/zh/docs/cli)**:完整的 CLI 文档 * **[API 参考(英文)](/docs/api)**:REST API 端点 * **[连接](/zh/docs/integrations)** - 连接 AI 工具 # Spaces (/docs/zh/spaces) Spaces 是一种可选的“分区”机制。它的作用不是把 Mem 拆成几套系统,而是在你真的需要时,让不同上下文各自更专注。 大多数人一开始不需要它。先一直用 **Default**,等你明确感觉到两个上下文已经互相打扰,再打开也不晚。 如果你还没有明显感觉到项目、团队或 Agent 之间的记忆混在一起,那就先别开 spaces,继续用默认分区。 ## 第一个有用动作 [#第一个有用动作] 只有在你已经知道“为什么要分开”时,再创建第二个 space。 最适合的第一批场景: * 一个长期工作项目,不想和个人内容混在一起 * 一个会持续积累经验的 Agent * 一个给团队共用的上下文分区 进入 **上下文 → 空间**,打开它,然后创建一个名字明确的分区。 在新 space 里保存一条记忆,切回 **Default**,确认它不会出现在默认的 Memories 视图里。再切回去,能立刻找到它。 ## Spaces 会改变什么 [#spaces-会改变什么] 当某个 space 处于激活状态时,下面这些界面默认都跟着它走: * **Memories** * **Threads** * **Library** * **Working Memory** * **AI Now** **Timeline** 也会先从当前 space 出发,但你仍然可以切回看全部活动。 **实体图谱仍然是全局的**。Mem 还是会理解你整个知识网络。Spaces 改变的是日常默认读写的记忆类界面,而不是把图谱硬切开。 ## 这些设置到底是什么意思 [#这些设置到底是什么意思] 一个 space 里最关键的是这三个设置: * **这个空间里的自动回忆** * **只留在这个空间**:开始回答前,第一步自动回忆只看当前分区。 * **留在这里 + 共享空间**:先看这里,再一起读你标记为共享上下文的空间。 * **搜索全部空间**:只给少数天生就该跨全局工作的分区用。 * **作为共享上下文一起读的空间** * 这里只影响检索范围。 * **不会**把记忆自动搬过去。 * **不会**把两个空间偷偷合并。 * **智能体在这里该怎么工作** * AI Now、Feed 和内置后台任务在这个空间里工作时会读它。 * 它影响的是检索和表达方式。 * **不会**改变记录保存在哪里。 ## Spaces 里的 Working Memory [#spaces-里的-working-memory] Working Memory 已经不再只是一个全局文件。 * **Default** 仍然保留兼容路径 `~/ai-now/memory.md` * 其他 space 也会有各自的 Working Memory 简报 * 当连接的工具知道自己当前在哪个分区时,它会自动读取对应那一份 这样研究 Agent 打开时看到的是研究上下文,你的默认个人分区仍然可以保持安静。 如果某个 space 已经没有记忆、对话或资料库条目了,但还留着自己的 Working Memory 笔记,删除它时 Mem 会直接说明这一点,并允许你在同一步里把这些自动生成的内容一起移除。 ## 移动已有记录 [#移动已有记录] 如果你是在使用 Mem 一段时间后才创建新的 space,不需要重新导入历史数据。 在 **Memories** 或 **Threads** 里进入选择模式,选中要移动的项目,然后用 **Move** 把它们移动到另一个 space。需要整理更多内容时,可以先选中当前页,再选择 **All pages**,一次移动或删除当前 space 里的全部主记录。 Shared context 不会移动记录。它只是在检索设置允许时,让一个 space 读取另一个 space 的内容。 ## AI 工具怎么使用 Spaces [#ai-工具怎么使用-spaces] 好的集成会把它当作“环境上下文”,而不是每一轮都让你重新解释一遍的新概念。 * **AI Now** 跟随应用里当前选中的 space * **原生连接** 如果宿主已经知道当前项目或 Agent 分区,应该优先把这个 lane 存在自己的配置里 * **CLI** 需要时可以显式加上 `--space ""` * HTTP 和 MCP API 仍然沿用 `space_id` 这个字段名做兼容,但也可以直接传可见的空间名称。 开始新的工具会话前,可以在 **上下文** 里预览这个 AI 实际会使用哪些记忆范围。 ```bash nmem --json wm read --space "Research Agent" nmem --json m search "token rotation" --space "Research Agent" nmem spaces ``` 如果某个工具本身并没有自然的项目分区或 Agent 分区,就应该继续留在 **Default**,不要硬造一个。 如果一个连接本身已经有设置页或 provider 配置,就应该优先在那里选择 lane。环境变量只适合没有更好配置面的 CLI-first 工具。 ## 多 Agent 宿主怎么设计 [#多-agent-宿主怎么设计] 不是所有集成都能以同样的粒度处理 spaces。 * **编程类工具**,例如 Claude Code、Grok Build、Codex、Gemini CLI,通常只需要给整段会话设一个可选 space。 * **Agent 宿主**,例如 Hermes、Alma、Bub、OpenClaw,可能需要按 profile、进程或稳定的 Agent 身份来分配不同 lane。 更合理的做法通常只有三种: * **固定 lane**:一个 profile 或一个进程始终只用一个 space * **派生 lane**:宿主本来就知道稳定的身份、项目或工作区,再据此推导出 space * **明确映射**:宿主暴露一小组可枚举身份,再把它们一一映射到命名好的 spaces 如果宿主并没有可靠的身份或工作区信号,就不要强行做“每个 Agent 一个 space”的自动路由。此时最稳妥的选择仍然是:一个 profile 对应一个固定 lane,或者继续使用 Default ## 什么情况下最值得用 [#什么情况下最值得用] Spaces 真正有价值的时候,是你想提高专注度,而不是为了“隔离而隔离”。 它尤其适合: * 一个所有者,同时运行很多长期 Agent * 工作和个人上下文明显不同 * 一个项目共用分区,再加一个更安静的默认分区 * 团队想共享上下文,但不想把每个人的私人笔记全混进去 ## 现在先别担心什么 [#现在先别担心什么] * 不是因为有这个功能,你就必须立刻建 work / life 两个 space * 不需要为了 spaces 重做标签体系 * 不需要把实体图谱切开,Mem 本来就故意把它保持为全局 ## 下一步 [#下一步] * [记忆](/zh/docs/memories):如果你想先看捕获和搜索怎么配合 * [上下文](/zh/docs/ai-context):如果你想看接入的 AI 会收到什么 * [AI Now](/zh/docs/ai-now):如果你想让 Agent 工作区跟随当前分区 * [后台智能](/zh/docs/advanced-features):如果你想理解 Working Memory 和后台任务在 spaces 下怎么运作 * [连接](/zh/docs/integrations):如果你想让已连接的 AI 工具自然跟随当前分区 # 从这里开始 (/docs/zh/start-here) 理解 Nowledge Mem,最好的方式是先走一遍: * 存一条真实内容 * 把它找回来 * 再让一个工具用上它 这一页是这条路径里最短的一段。如果还没安装,先看 [安装](/zh/docs/installation),下面的所有步骤都假设应用已经在运行。 ## Mem 到底是什么 [#mem-到底是什么] 简单说,Mem 做三件事: * 把你的决定、洞察、文件和对话存下来 * 让它们之后还能被搜索和复用 * 让你连接的工具不用每次从零开始 如果你要跨多台设备使用 Mem,模型很明确:在一台常开机器上运行主 Mem,其他客户端连过来。详见 [多设备同步](/zh/docs/sync)。 你不需要把整个产品研究明白,才开始得到帮助。 ## 第一轮使用 [#第一轮使用]
### 保存一条真实记忆 \[step] [#1-保存一条真实记忆-step] 在 Timeline 里,写下一条你真的想留住的内容:一个已经做出的决定、工作中的洞察,或一个你常重复的偏好。按回车。
### 确认搜索能把它找回来 \[step] [#2-确认搜索能把它找回来-step] 直接在 Timeline 里问一句: > 我之前对认证方案做过什么决定? 如果答案能反映你刚刚保存的内容,说明搜索已经正常工作了。
### 连接一个真实工具 \[step] [#3-连接一个真实工具-step] 不要一开始就在长列表里挑工具。先给 AI 工具一段提示词,让它按当前宿主选择最合适的接入路径。
## 连接任意 AI 工具 [#连接任意-ai-工具] 打开你日常使用的 AI 工具,比如 Claude Code、Grok Build、Codex、Cursor、Gemini CLI、Copilot CLI、OpenClaw、Hermes、Droid、Alma、Bub、Pi、OpenCode、OMP、Paseo 或 Claude Desktop,粘贴这段提示词: ```text 读取 https://mem.nowledge.co/SKILL.md,并按其中说明为我当前使用的 AI 工具安装或更新 Nowledge Mem。 ``` 那个 URL 是一份可机读的安装契约。AI 工具读完之后,会识别自己运行在哪个宿主里,选择对应的安装或设置路径,用 `nmem status` 验证连接,并在需要时提示你重启。命令行宿主通常可以直接由 Agent 安装;桌面应用型工具可能仍需要你确认一次市场安装或手动步骤。 AI 工具通常知道自己在哪个宿主里运行。它可以读取 [SKILL.md](https://mem.nowledge.co/SKILL.md)、在宿主允许时运行匹配的插件安装或 MCP 配置命令,并告诉你它改了什么。需要你确认的手动步骤和重启,它会明确说出来。 ### 远程或跨设备接入 [#远程或跨设备接入] 如果你只在本机使用 Mem,最上面那段通用提示词就够了。AI 工具会使用本地 `127.0.0.1:14242` 端点。 如果 AI 工具运行在另一台机器上,或者你使用的是托管 / 自托管的远程 Mem,先把这台机器上的 `nmem` 指向同一个服务器: ```bash nmem config client set --url https://your-mem-server.example --api-key nmem_... ``` 在桌面应用里,远程 URL 和 API key 相关设置位于 **设置 → Access Anywhere**。下面这些情况需要先处理这一步: * 你已订阅 **Pro**,想让 AI 工具走你的 Nowledge Link 托管端点 * 你是 **Lifetime**、自托管 Mem,需要跨设备访问 * 你想从一台不运行 Mem 的机器上让 AI 工具连接到主 Mem ## 第一轮成功清单 [#第一轮成功清单] 你应该能对下面每一条都回答“是”: * 我已经在 Timeline 里保存了一条记忆 * 我能把它重新搜出来 * 我已经把 Connect 提示词粘到 AI 工具里,它完成安装或告诉我明确的手动步骤,我也重启了该工具 * 在重启后的会话里,AI 工具能读到我的 Working Memory(第一天为空也算成功) 如果有任何一项还差,请继续看 [如何确认 Mem 已经在工作](/zh/docs/verify-it-works)。 ## Connect 提示词不适用时 [#connect-提示词不适用时] 少数接入路径走另一条路,因为它们不是由对话式 AI 驱动的: * **浏览器扩展**(网页版 ChatGPT、Claude.ai、Gemini、Poe):从 Chrome 应用商店安装,打开侧边栏,连接到 Mem。指南:[浏览器扩展](/zh/docs/integrations/browser-extension) * **Raycast**:从 Raycast Store 安装。指南:[Raycast](/zh/docs/integrations/raycast) * **轨迹提取器**(Windsurf、Antigravity):独立 CLI,把会话导出到本地后再批量导入。指南:[导入已有对话](/zh/docs/import-existing-conversations) 其它情况都用 Connect 提示词。如果你的宿主暂时没在 `SKILL.md` 的列表里,也可以让 AI 工具先读这个文件,再把它尝试过的步骤告诉你;我们会按真实出现的宿主继续补。 ## 把已有对话搬进来 [#把已有对话搬进来] 如果你手里已经有 ZIP/JSON/HTML 导出(ChatGPT、DeepSeek、ChatWise、Alma)、本机编程助手会话,或单条 `.md` 对话,请从 [导入已有对话](/zh/docs/import-existing-conversations) 开始。它会说明每种情况对应 Mem 里的哪个界面,省得在「对话」和「连接」之间来回猜。 保存一条记忆,运行一次 Connect 提示词,重启该工具。到这里就停。第一天的目的,是先把这一遍完整走一次,而不是把所有接入方式一口气全配好。 ## 下一步 [#下一步] * [安装](/zh/docs/installation):完成安装与首次启动 * [快速入门](/zh/docs/getting-started):Timeline 与第一次输入 * [连接](/zh/docs/integrations):每个工具的行为、skills、提炼策略 * [如何确认 Mem 已经在工作](/zh/docs/verify-it-works):验证完整闭环 * [随处访问](/zh/docs/remote-access):一台机器跑 Mem,全设备接入 * [多设备同步](/zh/docs/sync):理解“一台 Mem,多端接入”的同步模型 # 多设备同步 (/docs/zh/sync) 可以。Nowledge Mem 现在已经支持同步。 但它的同步方式很明确: * 以一个 Nowledge Mem 实例作为唯一事实来源 * 其他客户端连接到这一台 Mem * 记忆、线程、图谱、文库之所以保持一致,是因为大家访问的是同一个后端 这和“每台设备各跑一份独立数据库,之后再互相合并”不是一回事。 如果你要的是备份或一次性迁移,而不是多端持续访问,请使用[备份、导出与导入](/zh/docs/data-portability)。 ## Mem 里的同步到底指什么 [#mem-里的同步到底指什么] 推荐的方式很简单: 1. 在一台常开机器上运行 Nowledge Mem。 2. 打开 [随处访问](/zh/docs/remote-access)。 3. 让其他客户端连接到这同一个 Mem。 这些客户端可以是: * 另一台电脑上的桌面应用 * `/app` 网页版 * 移动应用 * 浏览器扩展 * `nmem` CLI * 运行在其他机器上的受支持智能体集成 只要它们都连接到同一个 Mem URL 和 API Key,它们看到的就是同一个知识库。 ## 这不是什么 [#这不是什么] Mem 目前的同步**不是**: * 多台设备上各自独立运行的 Mem 自动互相复制、合并 * 由 Nowledge 托管的中心化账号后端 * 多个独立数据库之间的离线优先、多主同步 现在的同步模型,本质上是:一台 Mem 中枢,多端接入。 ## 什么时候这种方式最合适 [#什么时候这种方式最合适] 如果你本来就有下面这类设备,这种方式会非常合适: * 一台长期开机的 Mac Mini * 一台 Linux 服务器 * 一台作为主知识中枢的桌面电脑 * 一台专门跑 OpenClaw 或其他智能体的机器 你只需要让 Mem 在那台机器上长期运行,其他设备再来连接它。 过去大家最常看到的远程入口主要还是浏览器扩展和 `nmem` CLI,所以很容易误以为 Mem 只是“能远程访问一点点”,而不是真正支持同步。这个判断已经过时了。现在网页访问、桌面客户端模式和移动应用都已经补上了这一层。 ## 接下来读什么 [#接下来读什么] * 看 [随处访问](/zh/docs/remote-access):了解具体配置、安全要求、Cloudflare tunnel 步骤,以及各类客户端怎么接入。 * 看 [备份、导出与导入](/zh/docs/data-portability):如果你需要的是可移植备份或一次性迁移。 * 看 [AI Now](/zh/docs/ai-now):如果你想在另一台电脑上远程使用同一个知识库里的 AI Now。 * 看 [如何确认 Mem 已经在工作](/zh/docs/verify-it-works):确认另一台设备是否真的已经连到同一个 Mem。 # 对话 (/docs/zh/threads) 对话是你的会话层。它保留了 AI 会话原本发生的过程:你问了什么、工具回答了什么、任务是怎样一步步推进的。 它让你之后还能重新搜索过去的讨论、回到当时的上下文,并把其中真正值得长期保留的部分提炼成[记忆](/zh/docs/memories)。 如果你需要保留原始消息,请保存或导入对话;如果你只需要长期有价值的结论,请提炼成记忆再继续使用。 若你在选择**如何把已有对话迁入 Mem**(批量文件、编程助手扫描、浏览器还是单条 Markdown),请先读 **[导入已有对话](/zh/docs/import-existing-conversations)**。本文仍是「对话」功能的**格式与细节**说明。 ## 第一条有用的对话 [#第一条有用的对话] 如果你是新用户,先做下面任意一件事: * 导入一条你本来就在意的对话 * 让一个受支持的工具捕获一条完整会话 * 通过浏览器扩展捕获一段 Web 对话 然后打开这条对话,从里面提炼出一条真正有价值的记忆。这也是多数人第一次真正感受到对话为什么值得保存的时刻。 | 我想要... | 跳转到 | | ------------------------------------------------------- | ------------------------------------------------ | | **一眼看清所有导入方式** | [导入已有对话](/zh/docs/import-existing-conversations) | | 浏览和搜索对话 | [浏览对话](#浏览对话) | | 将对话提炼为记忆 | [对话提炼](#对话提炼) | | 从**编程工具**自动导入 | [自动同步](#自动同步) | | 从 **Web AI 聊天**中捕获 | [浏览器扩展](#浏览器扩展) | | 导入 **ChatGPT**、**DeepSeek** 或 **Raycast AI**(导出 JSON)对话 | [批量导入](#批量导入) | | 导入**对话文件**(含 `## User`/`## Assistant` 标题的 `.md`) | [单个对话](#单个对话) | | 了解 **.md** 对话格式 | [对话 Markdown 格式](#对话-markdown-格式) | | 通过 **API** 导入 | [Import API](#import-api) | | 通过**命令行**导入 | [CLI](#cli) | ## 浏览对话 [#浏览对话] 对话视图集中展示所有已导入的会话。 * **搜索**对话内容或标题 * **筛选**来源(Claude Code、ChatGPT、Cursor 等) * **收藏**重要对话,方便随时查看 * **查看**对话中的每条消息 从侧边栏打开对话,或按 Cmd + 3(macOS)。 ## 对话提炼 [#对话提炼] 这里是对话和记忆真正连起来的地方。打开任意一条对话并触发提炼,系统会从会话中提取独立记忆。每条记忆都有自己的标题、标签和重要性评分,之后会进入知识图谱,并和其他内容一起参与搜索。 这也是把几小时的 AI 对话,慢慢变成可连接知识的方式。 普通大小的对话会直接开始提炼。很长的对话现在会提供 **智能后台提炼**:几秒后由 Knowledge Agent 在后台启动,按需渐进式阅读这条对话,再保存一小组真正值得长期保留的记忆。它不会像过去那样在前台一次性硬读完整个长对话,所以更稳,也更适合大线程。 [浏览器扩展](/zh/docs/integrations/browser-extension)支持直接从 Web 对话中智能提炼,无需先导入完整对话即可捕获记忆。 ## 对话是如何进入 Mem 的 [#对话是如何进入-mem-的] 对话进入 Nowledge Mem 的方式不止一种。它们彼此相关,但并不相同: * **专属插件与扩展**:像 Claude Code、Grok Build、Codex、Gemini CLI、OpenClaw、Hermes Agent、Alma、Cursor、Droid、OpenCode、Craft Agent、Copilot CLI 这样的工具专属连接 * **本地发现/回填**:应用内导入运行 Mem 的那台机器上受支持的编程智能体对话 * **共享技能或工作流包**:比如 `npx skills`、Pi 之类的共享工作流 * **浏览器捕获**:Exchange 扩展只处理你在侧栏里**实际配合使用的那一个网页会话**,不是整账号历史;总览见 [导入已有对话](/zh/docs/import-existing-conversations) * **手动导入**:文件、导出记录、API 调用和 CLI 导入 这里最重要的区分是: * **完整会话捕获**:Mem 收到的是这个工具里真实录制的整段对话 * **交接摘要**:Mem 保存的是一个可继续工作的摘要,而不是整段会话本身 共享 skills 也应该放在这个框架里理解。它们可以在很多智能体里复用,但除非宿主运行时真的暴露了可读取的会话文件或稳定的 transcript API,否则它们不能诚实承诺“完整会话捕获”。 多数用户只需要记住一条判断: * 如果你的工具已经支持真实会话保存,就直接用那条路径 * 如果它今天只支持交接摘要,就保持这个心智模型清楚;需要完整历史时,请使用导入或 `nmem t sync` ## 自动同步 [#自动同步] ### 应用内发现 [#应用内发现] 扫描本机编程工具的对话并自动导入,无需手动导出。 这条路径会扫描运行 Nowledge Mem 的那台机器上的对话文件,很适合做本地同步。但它和 `nmem t save --from ...` 不是一回事。后者会在客户端本机读取会话文件,再把规范化后的会话线程上传到远程 Mem。 第一次导入会先把这段对话存成线程。打开自动同步后,Mem 会继续为同一线程追加新消息;如果某个应用还能稳定暴露项目路径,Mem 也会记住这个识别出的项目,把后续会话继续带进来。 | 客户端 | 同步方式 | 入口 | | --------------- | ---------------- | ------------------ | | **Claude Code** | 自动发现 + 增量同步 | 对话 → 导入 → 查找 AI 对话 | | **Cursor** | 自动发现 + 增量同步 | 对话 → 导入 → 查找 AI 对话 | | **Codex** | 自动发现 + 增量同步 | 对话 → 导入 → 查找 AI 对话 | | **OpenCode** | 回填旧会话;新工作由原生插件捕获 | 对话 → 导入 → 查找 AI 对话 | ### 原生连接里的保存路径 [#原生连接里的保存路径] 不同连接提供的对话保存能力并不相同。有些支持完整会话捕获,有些会在生命周期事件里自动捕获,而 Droid 和 Cursor 当前仍然把插件内的交接摘要与完整对话导入分开。 | 连接 | 保存的是什么 | 工作方式 | 配置 | | ----------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | **Claude Code** | 完整会话捕获 | 每轮响应后通过 Stop 钩子自动保存当前会话,也支持显式 `/save`。`nmem` 会先在客户端本机读取会话文件,再上传。 | [Claude Code 指南](/zh/docs/integrations/claude-code) | | **Grok Build** | 完整会话捕获 | Grok Build 加载共享的 Claude 兼容连接包,但 hooks 会通过 `nmem t save --from grok` 保存,因此来源标识和会话格式仍按 Grok Build 处理。 | [Grok Build 指南](/zh/docs/integrations/grok) | | **Gemini CLI** | 完整会话捕获 + 单独的交接摘要 | `save-thread` 通过 `nmem t save --from gemini-cli` 导入 Gemini 记录下来的会话;扩展也会在压缩前和会话结束时导入;`save-handoff` 继续单独保存可恢复的交接摘要。 | [Gemini CLI 指南](/zh/docs/integrations/gemini-cli) | | **Droid** | 插件内的交接摘要 | Droid 插件刻意只暴露 `save-handoff`,不暴露 `save-thread`。它已经能提供工作记忆简报、路由式检索与可恢复交接,但真实 transcript 级会话导入会留到未来真正具备运行时支持时再提供。 | [Droid 指南](/zh/docs/integrations/droid) | | **Cursor** | 插件内的交接摘要 | Cursor 插件刻意只暴露 `save-handoff`,不暴露 `save-thread`。如果你要导入真实 Cursor 对话,请使用应用内发现。等未来有真正的实时会话导入器后,再提供对应的会话线程保存能力。 | [Cursor 指南](/zh/docs/integrations/cursor) | | **Alma** | 完整会话捕获 | 空闲 2 分钟、切换线程、退出应用时自动保存对话(默认开启)。 | [Alma 指南](/zh/docs/integrations/alma) | | **OpenClaw** | 完整会话捕获 | 每次智能体运行结束时自动捕获会话,并支持可选的 LLM 提炼。 | [OpenClaw 指南](/zh/docs/integrations/openclaw) | | **Hermes Agent** | 完整轮次捕获 + 边界刷新 | 原生记忆提供者会在回复完成后写入清洗后的 `user` / `assistant` 轮次,并在正常退出、`/new`、`/reset` 时刷新剩余增量。 | [Hermes 指南](/zh/docs/integrations/hermes) | | **Codex** | 完整会话捕获 | Stop hook 会在每个回合后捕获 Codex 记录下来的会话;显式保存仍可作为兜底。 | [Codex 指南](/zh/docs/integrations/codex-cli) | | **Copilot CLI** | 完整会话捕获 | 捕获钩子会在每次回复后、压缩前和会话结束时,把新记录下来的 Copilot 对话内容追加进 Mem;如果用户明确要求保存,还可以另外写入一条简洁的摘要线程。 | [Copilot CLI 指南](/zh/docs/integrations/copilot-cli) | | **Pi** | 完整会话捕获 | 原生 Pi package 会自动同步完成后的对话;旧会话可以用 `nmem t sync --from pi` 导入。 | [Pi 指南](/zh/docs/integrations/pi) | | **OpenCode** | 完整会话捕获 | 原生插件会在 OpenCode 报告 idle 后捕获,并在压缩前 flush。`nowledge_mem_save_thread` 仍是显式兜底;旧会话可以用 `nmem t sync --from opencode` 导入。 | [OpenCode 指南](/zh/docs/integrations/opencode) | | **Craft Agent** | source 引导记忆 + 导入 | Craft 通过 workspace source 和 guide 使用 MCP 记忆能力。本地旧 Craft 会话可以从 `session.jsonl` 用 `nmem t sync --from craft-agent` 导入。 | [Craft Agent 指南](/zh/docs/integrations/craft-agent) | | **OMP** | 插件自动捕获 + 历史导入 | OMP 专用插件会自动捕获新会话;本地旧 OMP 会话继续用 `nmem t sync --from omp` 补导。不要用 Pi package 代替 OMP connector。 | [OMP 指南](/zh/docs/integrations/omp) | | **通用 `npx skills` 智能体** | 仅交接摘要 | 使用 `save-handoff`。共享 skills 可以指导保存行为,但无法在所有宿主上承诺 transcript 级导入。 | [连接总览](/zh/docs/integrations) | 如果你需要的是准确的历史对话,请优先使用完整会话捕获或导入路径。交接摘要适合中断后继续,不等于保存整段会话本身。 ## 文件导入 [#文件导入] ### 批量导入 [#批量导入] 一次性导入导出文件中的全部对话。 | 来源 | 文件格式 | 如何导出 | | -------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ChatGPT** | `chat.html` | ChatGPT 设置 → 数据控制 → 导出数据 | | **Claude** | `data-…-batch-….zip`(含 `conversations.json`、`memories.json`) | claude.ai 或 Claude Desktop:头像 → **设置** → **隐私** → **导出数据**([Anthropic 说明](https://support.claude.com/en/articles/9450526-how-can-i-export-my-claude-data));移动端不支持 | | **DeepSeek** | `deepseek_conversations.json` | chat.deepseek.com → 设置 → 数据 → 导出数据 | | **ChatWise** | `.zip`(含 JSON 文件) | 从 ChatWise 导出全部聊天 | | **Alma** | `alma-backup-YYYY-MM-DD.zip`(内含 `threads.json`) | Alma 设置 → 数据 → 导出全部对话 | | **Raycast AI** | `.json`(如 `raycast_ai_chats.json`) | 没有官方导出,macOS 上用 **[raycast-ai-exporter](https://github.com/daveonkels/raycast-ai-exporter)**(见其 README) | 批量导入会先把原始对话保存为「对话」。它们立刻可以被搜索,所以不需要先把几百条历史聊天全部提炼成记忆,Mem 才能找到它们。提炼是第二步:只在某些对话里有值得长期保留的决策、流程、偏好或经验时再做。大量历史归档可以从时间线规划小批量提炼,或在对话列表中勾选具体线程后提炼。 ### 单个对话 [#单个对话] 从文件导入一条对话。 | 格式 | 文件类型 | 备注 | | --------------- | ----- | -------------------------------------------------------- | | **对话 Markdown** | `.md` | `## User` / `## Assistant` / `## System` 标题,可选 YAML 前置信息 | | **Cursor** | `.md` | Cursor 原生导出格式(自动识别) | | **通用 Markdown** | `.md` | 任意 Markdown 文件,作为文档导入 | 如果你的 `.md` 文件是普通文档(没有 `## User` / `## Assistant` 标题),它属于[资料库](/zh/docs/library),而非对话。拖入时间线或从资料库视图导入。 ## 对话 Markdown 格式 [#对话-markdown-格式] 通用的对话导入格式。任何输出 `## User` / `## Assistant` 标题的工具,生成的文件都能被 Nowledge Mem 识别。 ### 最简示例 [#最简示例] 最简单的格式,两轮对话,无前置信息: ```markdown ## User Python 的 GIL 是什么? ## Assistant 全局解释器锁(GIL)是 CPython 中的互斥锁,同一时刻只允许一个线程执行 Python 字节码。这意味着 CPU 密集型的多线程程序不会因多线程而加速,可以改用多进程或异步 I/O。 ``` ### 完整示例 [#完整示例] 包含可选的 YAML 前置信息和系统消息: ```markdown --- title: Python 异步编程 source: chatgpt date: 2025-06-15 --- ## System 你是一位资深 Python 开发者,擅长清晰地解释技术概念。 ## User Python 的 async/await 是怎么工作的? ## Assistant Python 的 `async`/`await` 让你编写在等待 I/O 时不阻塞的并发代码。`async def` 函数返回一个协程,`await` 会暂停它直到结果就绪,与此同时其他协程可以继续执行。 ## User 什么时候该用 asyncio,什么时候该用线程? ## Assistant **asyncio** 适用于 I/O 密集型任务(HTTP 请求、数据库查询、文件读写),比线程更轻量,扩展性更好。**threading** 适用于调用不支持异步的阻塞库。**multiprocessing** 适用于 CPU 密集型任务。 ``` ### 格式规则 [#格式规则] * **标题**:`## User`、`## Assistant` 或 `## System`,二级标题,每条消息一个 * **内容**:标题之间的所有内容为一条消息,Markdown 格式、代码块和列表会原样保留 * **前置信息**:文件开头可选的 YAML 块,支持 `title`、`source`、`date` 字段,均为可选 * **识别**:包含至少一个 `## User` 或 `## Assistant` 标题的文件会被自动识别为对话 * **兜底**:不含上述标题的文件作为单条文档消息导入 * **大小写**:角色名不区分大小写(`## user` 和 `## User` 均可) 包含所有支持功能的完整示例 ## Import API [#import-api] `POST /threads/import` 接受 JSON 消息或对话 Markdown,支持单条和批量模式。 ### 单条对话(JSON 消息) [#单条对话json-消息] ```bash curl -X POST http://127.0.0.1:14242/threads/import \ -H "Content-Type: application/json" \ -d '{ "title": "我的对话", "source": "chatgpt", "messages": [ {"role": "user", "content": "你好!"}, {"role": "assistant", "content": "你好!有什么可以帮你的?"} ] }' ``` ### 单条对话(Markdown) [#单条对话markdown] ```bash curl -X POST http://127.0.0.1:14242/threads/import \ -H "Content-Type: application/json" \ -d '{ "markdown_content": "## User\n\n你好!\n\n## Assistant\n\n你好!有什么可以帮你的?" }' ``` ### 批量导入 [#批量导入-1] ```bash curl -X POST http://127.0.0.1:14242/threads/import \ -H "Content-Type: application/json" \ -d '{ "threads": [ { "title": "对话 1", "messages": [ {"role": "user", "content": "你好"}, {"role": "assistant", "content": "嗨"} ] }, { "title": "对话 2", "markdown_content": "## User\n\n再见\n\n## Assistant\n\n下次见!" } ] }' ``` 未指定对话线程 ID 时会自动生成。标题可从 Markdown 前置信息中推断。 完整的请求/响应结构和字段说明 ## CLI [#cli] `nmem` 命令行支持从文件、JSON 或标准输入导入对话。 ```bash # 导入对话 Markdown 文件 nmem t import --file conversation.md # 指定标题和来源 nmem t import --file chat.md --title "Python 异步" --source chatgpt # 从 JSON 消息导入 nmem t import --messages '[{"role":"user","content":"你好"},{"role":"assistant","content":"嗨"}]' # Raycast AI 多会话 JSON(raycast-ai-exporter 输出) nmem t import --file ~/Desktop/raycast_ai_chats.json # 从标准输入导入 Markdown cat conversation.md | nmem t import --stdin --title "管道导入" ``` 运行 `nmem t import --help` 查看所有选项。完整命令列表见 [CLI 参考](/zh/docs/cli)。 ## 浏览器扩展 [#浏览器扩展] Nowledge Mem Exchange 在受支持的 AI 聊天网页上工作,针对的是你**正在与扩展一起使用的这一帖会话**(例如侧栏对准的标签页)。它**不会**把网页版聊天记录整库搬下来;要全部历史,请用各平台官方导出,再在 Mem 里 **批量导入**,或先看 **[导入已有对话](/zh/docs/import-existing-conversations)**。自动捕获、手动提炼、备份当前会话等能力见[浏览器扩展指南](/zh/docs/integrations/browser-extension)。 ## MCP 工具 [#mcp-工具] | 工具 | 功能 | | ------------------------ | ---------------- | | `thread_search` | 按关键词搜索对话或列出最近的对话 | | `thread_fetch_messages` | 获取特定对话的完整消息 | | `search_thread_messages` | 在指定对话中按关键词搜索消息 | MCP 的线程工具负责搜索和读取 Mem 里已经保存的对话。要采集本地编程智能体的 transcript,请优先使用该工具的原生连接。要补导旧会话,请在运行智能体的客户端执行 `nmem t sync --from `。当前支持的 source 包括 `claude-code`、`codex`、`craft-agent`、`cursor`、`gemini-cli`、`grok`、`hermes`、`kimi-code`、`kimi-work`、`mimo-code`、`omp`、`opencode` 和 `pi`。这样会话发现始终发生在本机,规范化后的线程再上传到 Mem 服务器。 ## 下一步 [#下一步] * **[记忆](/zh/docs/memories)**:提炼后的知识:创建、搜索和组织 * **[资料库](/zh/docs/library)**:导入文档,与记忆一起搜索 * **[浏览器扩展](/zh/docs/integrations/browser-extension)**:从 Web AI 平台捕获对话 * **[连接](/zh/docs/integrations)**:通过原生连接、复用包或 MCP 连接你的 AI 工具 * **[API 参考(英文)](/docs/api)**:完整的 REST API 文档 # 故障排除 (/docs/zh/troubleshooting) ## 全部文件路径总览(桌面端 + CLI) [#全部文件路径总览桌面端--cli] 这里给你一个简化后的目录总览(按大目录层级): * **配置/状态根目录**:`co.nowledge.mem.desktop` * **数据根目录**:`NowledgeGraph` * **用户工作目录**:`ai-now` * **客户端工具目录**(`nmem` CLI + OpenClaw 插件):`.nowledge-mem` ```text ~/Library/Application Support/co.nowledge.mem.desktop/ # 配置/状态 ~/Library/Application Support/NowledgeGraph/ # 数据(DB/索引/日志) ~/ai-now/ # 用户工作目录 ~/.nowledge-mem/ # nmem/OpenClaw 客户端配置 ``` 升级后你可能仍会看到这些兼容旧路径: * `~/Library/Application Support/nowledge-mem/` * `~/Library/Logs/Nowledge Graph/` ```text %APPDATA%\co.nowledge.mem.desktop\ # 配置/状态 %LOCALAPPDATA%\NowledgeGraph\ # 数据(DB/索引/日志) %USERPROFILE%\ai-now\ # 用户工作目录 %USERPROFILE%\.nowledge-mem\ # nmem/OpenClaw 客户端配置 ``` ```text ~/.config/co.nowledge.mem.desktop/ # 配置/状态(XDG_CONFIG_HOME) ~/.local/share/NowledgeGraph/ # 数据(XDG_DATA_HOME) ~/ai-now/ # 用户工作目录 ~/.nowledge-mem/ # nmem/OpenClaw 客户端配置 ``` 你也可能看到这些安装路径(取决于安装方式): ```text /usr/lib/nowledge-mem/ /usr/share/nowledge-mem/ ``` 升级后你可能仍会看到这些兼容旧路径: * `~/.local/share/co.nowledge.mem.desktop/` * `~/.local/share/Nowledge Graph/` * `~/.local/share/nowledge-mem/` ## 查看日志 [#查看日志] 打开**设置 → 关于 → 显示日志文件**,即可直接在访达或资源管理器中打开日志所在文件夹,无需使用终端。 如果应用在启动时遇到错误,启动界面也会显示**显示日志**按钮,效果相同。 在 macOS 上,系统日志文件的规范路径是 `~/Library/Application Support/NowledgeGraph/Logs/app.log`。 你可以在终端中运行此命令查看: ```bash open -a Console ~/Library/Application\ Support/NowledgeGraph/Logs/app.log ``` 如果你是从旧版本升级,也可能仍有旧路径: ```bash open -a Console ~/Library/Logs/Nowledge\ Graph/app.log ``` 在 Windows 上,系统日志文件位于两个可能的位置,取决于安装方法: * `%LOCALAPPDATA%\Packages\NowledgeLabsLLC.NowledgeMem_1070t6ne485wp\logs\app.log`(从 Microsoft Store 安装) * `%LOCALAPPDATA%\NowledgeGraph\logs\app.log`(从 Nowledge Mem 网站下载的安装包安装) 你可以将此粘贴到文件资源管理器的地址栏中查看: ```shell %LOCALAPPDATA%\Packages\NowledgeLabsLLC.NowledgeMem_1070t6ne485wp\logs\app.log ``` 或者: ```shell %LOCALAPPDATA%\NowledgeGraph\logs\app.log ``` ## 搜索与索引健康检查 [#搜索与索引健康检查] 如果你的问题与搜索质量或搜索索引占用空间有关,先从这里开始: * 打开 **设置 -> Memory Processing -> Search** * 如果搜索索引占用磁盘过大,使用 **Optimize** * 如果搜索结果明显不对、缺失、过时或排序异常,使用 **Rebuild Index** 这个面板里的存储大小会拆成几块看: * **Knowledge Graph**:记忆、实体、关系和图谱元数据 * **Messages**:已保存对话消息和较大的文本内容 * **Search Index**:用于排序和摘要片段的可重建搜索投影 这两个操作解决的是不同问题: * **Optimize**:压缩磁盘上的搜索索引占用,不需要整套重建 * **Rebuild Index**:从已保存的记忆、资料库内容和消息库重新生成搜索索引,适合索引状态陈旧或异常时使用 如果你是在 Linux 服务器上使用,或当前没有打开桌面端界面: * 运行 `nmem status`,查看搜索是已就绪、需要重建,还是只是在后台补齐元数据 * 运行 `nmem models status`,同时查看模型安装状态和搜索索引状态 * 如果状态显示 **updating metadata**,只需要等待,不需要手动重建 搜索索引过期时(比如你换了嵌入服务商或模型),Mem 不会报错,也不会返回 500。它会先退回关键词(FTS)搜索顶着,等索引追上来,同时 `GET /health` 会报 `reindex_needed: true`。等你准备好了,再去 **设置 → Memory Processing → Search** 触发重建,全程搜索都能用。 如果索引已经是最新的,但语义结果还是偏弱,看一下 `GET /health` 里的 `embedding.mode`。取值是 `local-hash-fallback` 时,说明没有配真正的嵌入器,只有关键词搜索完全可用。配一个远程嵌入服务商,或下载本地模型,就能恢复语义搜索。 ## 应用启动时间过长 [#应用启动时间过长] **症状:** 应用在启动期间挂起或显示超时错误。 **解决方案:** 全局代理或 VPN 软件可能阻止应用直接访问 `http://127.0.0.1:14242`。 配置你的代理或 VPN 工具绕过 localhost 地址。将以下内容添加到你的绕过/排除规则: ``` 127.0.0.1, localhost, ::1 ``` 这允许你保持代理/VPN 启用,同时确保 Nowledge Mem 可以与其本地服务器通信。更新绕过规则后,重启 Nowledge Mem。 ## Windows 启动失败:缺少 Visual C++ 运行库 [#windows-启动失败缺少-visual-c-运行库] **症状:** 启动时,`app.log` 出现: * `Import error: DLL load failed while importing _lbug` * 或 `Backend exited during startup readiness check: exit code: 1` **原因:** 系统缺少数据库引擎所需的 Microsoft C++ 运行时依赖。 **解决方案:** 1. 下载并安装 **Microsoft Visual C++ Redistributable (x64)**:\ [https://aka.ms/vs/17/release/vc\_redist.x64.exe](https://aka.ms/vs/17/release/vc_redist.x64.exe) 2. 安装后重启 Nowledge Mem。 3. 若仍失败,请反馈时附上 `app.log`。 ## AI Now 会话启动失败 [#ai-now-会话启动失败] **症状:** 点击 **新任务** 或恢复已暂停任务时失败,AI Now 无法打开会话。 **第一步:** 先查看 AI Now 内的启动诊断卡片。 会话启动失败时,AI Now 会显示诊断卡片,包含: * 失败阶段(`spawn`、`initialize` 或 `new_session`) * 平台和进程退出码 * 启动脚本最近的 `stderr` 输出 * 可复制的诊断信息按钮 点击 **详情** 展开技术字段,再点击 **复制诊断信息**,用于反馈或提交 issue。 **常见修复(尤其 Windows):** 1. 确认安装完整(嵌入式 Python 与启动脚本存在)。 2. 修改插件或模型配置后,重启 Nowledge Mem 再重试。 3. 如果你在 Windows 上装了 Conda 或其他 PowerShell 自定义,请先更新到最新版本。最近的版本已经把 AI Now 和内置 `nmem` 启动器与 PowerShell profile 钩子隔离开,避免在 Mem 自己启动前就失败。 4. 临时关闭会拦截 bundled Python / PowerShell 启动的杀毒或隔离规则。 5. 若与插件有关,在 **AI Now → 插件** 中重新连接已过期 OAuth 插件后再试。 ### 可选:在 Windows 使用热键打开开发者控制台 [#可选在-windows-使用热键打开开发者控制台] 如果 AI Now 仍然卡在会话启动,可直接使用内置热键查看日志: * 按 Ctrl + Shift + I 切换 Tauri/WebView 控制台。 * 打开 **Console** 标签页。 * 使用关键词过滤日志,例如 `[AI Now]`、`[ACP]`、`[kimi-cli stderr]`。 该方法同时适用于 Microsoft Store 安装版和官网安装包版本。 然后进入 AI Now 并点击 **新任务** 复现问题。 如果仍失败,请在反馈时附上“复制诊断信息”内容和 `app.log`。 ## 模型缓存损坏 [#模型缓存损坏] **症状:** 搜索、记忆提炼或知识提取功能意外停止工作。 **解决方案:** 清除模型缓存并重新下载模型。 导航到 设置模型,然后点击: 清除缓存后,重新下载所需的模型。 ## 搜索索引占用磁盘过大 [#搜索索引占用磁盘过大] **症状:** 搜索本身还能用,但你在 **设置 -> Memory Processing -> Search** 里看到搜索索引体积明显大得不合理。 **怎么做:** 直接点击同一面板里的 **Optimize**。 **Optimize** 会压缩磁盘上的搜索索引,并顺带刷写数据库变更。它不会删除记忆或已保存的对话。 从 v0.6.8 开始,这一步会更积极地清理旧索引版本;0.9.0 使用原生 LanceDB 搜索索引后,也会清理旧的原生索引版本。在一些真实案例里,压缩后可能出现 **5 GB -> 300 MB** 这样的大幅下降。 **适合在这些情况下使用:** 1. 更新版本后,索引体积一直涨。 2. 你并没有很多内容,但搜索索引看起来异常大。 3. 搜索还能工作,但磁盘占用明显不正常。 如果执行 **Optimize** 后 **Search Index** 的体积仍明显不对,再执行一次 **Rebuild Index**。如果 **Messages** 体积较大,通常说明你保存或导入了很多对话;备份和迁移应使用 [Data Transfer](/zh/docs/data-portability),不要手动删除索引文件。如果仍异常,反馈时请附上 **Memory Processing** 面板截图。 ## 搜索结果明显不对 [#搜索结果明显不对] **症状:** 搜索结果明显不靠谱,应该很容易搜到的记忆搜不出来,或者排序质量突然变差很多。 **怎么做:** 打开 **设置 -> Memory Processing -> Search**,点击 **Rebuild Index**。 **Rebuild Index** 会基于已保存的记忆、资料库内容和消息库完整重建搜索索引。 当索引写入过程中出现中断、索引状态陈旧,或其他索引问题导致搜索质量明显下降时,这是最合适的恢复步骤。 **适合在这些情况下使用:** 1. 某条记忆明明存在,但用合理查询就是搜不到。 2. 升级、崩溃或大批量导入后,搜索质量突然明显变差。 3. 搜索排序结果和你确信已经存进 Mem 的内容明显对不上。 重建完成后,用同一条查询再试一次。如果结果仍明显不对,反馈时请附上查询示例,以及你预期应该出现的那条记忆。 ## Windows:安装或升级后 PATH 被覆盖 [#windows安装或升级后-path-被覆盖] **症状:** 安装或升级 Nowledge Mem 之后,其他命令行工具突然无法使用。运行 `pnpm`、`git`、`node` 等命令时提示"不是内部或外部命令"或"command not found"。检查用户 PATH 后发现它被缩减为仅剩 `C:\Users\...\Nowledge Mem\cli`,或者 `%PNPM_HOME%` 等环境变量引用丢失。 **原因:** 0.6.8 之前的版本在安装过程中可能会展开 PATH 中的环境变量引用(如 `%PNPM_HOME%` 被展开为实际路径),甚至在某些情况下将整个 PATH 替换为仅包含 Nowledge Mem CLI 目录的值。 **此问题已在 0.6.8 及更新版本中修复。** 安装程序现在会完整保留你的 PATH 条目及其环境变量引用。 **如果你受到了影响,可以按以下步骤恢复 PATH:** 1. 按 Win + R,输入 `sysdm.cpl`,回车。 2. 进入 **高级** > **环境变量**。 3. 在 **用户变量** 下,选中 **Path** 并点击 **编辑**。 4. 补回缺失的条目。常见的包括: * `%PNPM_HOME%` * `%USERPROFILE%\AppData\Local\Programs\Microsoft VS Code\bin` * `%USERPROFILE%\.cargo\bin` * `%USERPROFILE%\AppData\Roaming\npm` 5. 点击 **确定**,然后打开新的终端窗口。 如果你不确定 PATH 里应该包含哪些条目,可以参考另一台正常的电脑,或者查阅你使用的各工具(pnpm、Node.js、Rust 等)的安装文档。每个工具的安装程序通常都会说明它往 PATH 里加了哪一条。 ## Windows:更新后记忆不见了(回退版本也没用) [#windows更新后记忆不见了回退版本也没用] **症状:** 在 Windows 上更新之后,记忆数量掉到零或接近零。就算回退到上一个版本,记忆也没回来。 **你的数据没有丢。** 你的图谱其实还在原来的文件夹里,只是应用现在读的是另一个位置,而那个位置新建了一个空数据库,把你真正的数据挡住了。下面的步骤会把真正的数据挪回应用会读取的位置。全程只做复制或重命名,绝不删除,所以哪怕猜错了也随时能改回来。 **开始之前:** 彻底退出 Nowledge Mem,包括系统托盘里的图标。打开任务管理器,确认没有残留的 `nmem-server` 或 Nowledge Mem 进程还在运行。 **第一步:找到真正的数据。** 按 Win + R,依次打开下面这几个位置。有些可能不存在,这没关系: * `%LOCALAPPDATA%\NowledgeGraph`(应用现在读的位置,通常就是那个空的) * `%APPDATA%\NowledgeGraph`(较旧的位置,真正的数据常常在这里) * `%USERPROFILE%\Documents\NowledgeGraph`(最早的位置) 在每个文件夹里,对比 `nowledge_graph_v2.db` 的大小。真正的数据一般有几十 MB 到几个 GB。而全新的空数据库体积很小,最后修改时间就是出问题的那一天。同时看看有没有一个体积不小的 `content.db`,以及 `content.db.backup.*` 这类备份文件。`nowledge_graph_v2.db` 最大、最旧的那个文件夹,就是你真正的数据文件夹。 **第二步:把当前(空的)位置备份起来。** 在 `%LOCALAPPDATA%` 里,把 `NowledgeGraph` 文件夹重命名为 `NowledgeGraph_empty_backup`。是重命名,不要删除。 **第三步:把真正的数据放到位。** 把你真正的数据文件夹复制到 `%LOCALAPPDATA%\` 下,并命名为 `NowledgeGraph`。是复制,不要移动,这样原来那份还能留作备份。 **第四步:启动应用。** 打开 Nowledge Mem,进入记忆页面,数量应该就回来了。 更新到 0.10.6(或 0.10.5)后,只要当前位置还是空的(也就是你没有往那个空库里存过新记忆),应用就会自动从这些旧位置找到并打开你的数据。 **还是搞不定,或者不太敢手动操作:** 把这三个文件夹里 `nowledge_graph_v2.db` 的大小截个图,连同你的 `app.log`(在**设置 → 关于**里)一起发到 [hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai)。在我们回复之前,不要删除任何 `NowledgeGraph` 或 `_empty_backup` 文件夹。 ## 后端起不来 / 反复重启(隔离损坏的数据库日志) [#后端起不来--反复重启隔离损坏的数据库日志] **症状:** 更新之后,或者一次重建被中途打断之后,应用一直卡在启动、后端反复重启。有时候写入过程中遇到硬崩溃或断电,会让数据库的预写日志(`.wal`)处于损坏状态,后端就打不开图谱了。 Nowledge Mem 在启动时已经会尝试自动从这种情况恢复:它会把损坏的日志挪到一边,然后重新打开图谱。下面的手动步骤只在极少数自动恢复没有触发的情况下才需要。 **操作步骤:** 1. 彻底退出应用,包括系统托盘里的图标。 2. 打开你所在平台的图谱数据文件夹: * macOS:`~/Library/Application Support/NowledgeGraph` * Windows:`%LOCALAPPDATA%\NowledgeGraph` * Linux:`~/.local/share/NowledgeGraph` 3. 如果有一个叫 `nowledge_graph_v2.db.wal` 的文件,把它重命名为 `nowledge_graph_v2.db.wal.corrupt-backup`。是重命名,不要删除。 4. 如果还有 `nowledge_graph_v2.db.shm`,也一并挪到一边(重命名)。 5. 启动应用。 只有最近那些还没保存的改动可能受影响,已经保存的内容都完好无损。如果仍然起不来,把你的 `app.log` 发到 [hello@nowledge-labs.ai](mailto:hello@nowledge-labs.ai),并把重命名后的文件保留好。 ## 找不到 CLI [#找不到-cli] **症状:** 在终端中运行 `nmem` 返回"command not found"。 **各平台解决方案:** * **macOS**:先打开一次 Nowledge Mem,然后打开新的终端。应用会在启动完成后 后台安装或修复 `nmem`,不阻塞主界面。如果仍然找不到命令,再到 **设置 → 偏好设置 → 开发者工具 → 安装 CLI** 手动修复。 * **Windows**:应用安装后打开**新的**终端窗口(PATH 更新需要新会话) * **Windows (WSL)**:参见下方 [WSL 设置](#using-nmem-from-wsl) * **Linux**:桌面包内置 CLI,应用启动后会自动修复 wrapper。请打开新的终端; 如果仍然找不到 `nmem`,确认 `~/.local/bin` 已在当前 shell 的 PATH 中。 **快速检查:** 运行 `nmem status` 以验证 CLI 可以连接到 Nowledge Mem。 ## CLI 与服务器版本不一致 [#cli-与服务器版本不一致] **症状:** `nmem status` 显示 "Version mismatch"。 这表示你终端里运行的 `nmem` 命令,和它连接到的 Mem 服务器,不是同一次安装或更新得到的。连接本身可能仍然正常,但旧版 CLI 可能不认识新版命令或诊断信息。 **更新较旧的一侧:** * **桌面应用内置 CLI**:打开 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**,然后重启终端。 * **通过 PyPI 安装**:运行 `python -m pip install --upgrade nmem-cli`。 * **通过 pipx 安装**:运行 `pipx upgrade nmem-cli`。 * **临时运行一次**:执行 `uvx --from nmem-cli nmem status`。 * **服务器比 CLI 旧**:更新或重启 Nowledge Mem,或者检查 `NMEM_API_URL` 是否指向了你真正想连接的服务器。 ## 在 WSL 中使用 nmem [#在-wsl-中使用-nmem] 如果你在 Windows 的 WSL 环境中运行 Claude Code、Codex 等编程代理,Windows 上的 `nmem` CLI 不会直接出现在 Linux 环境中。 **从 v0.6.9 起**,在设置中点击 **安装 CLI** 会自动在默认 WSL 发行版中创建一个轻量桥接脚本。如果需要手动设置,在 WSL 终端中粘贴以下命令: ```bash mkdir -p ~/.local/bin && cat > ~/.local/bin/nmem << 'SHIMEOF' #!/usr/bin/env bash cd /mnt/c || exit 1 exec cmd.exe /c nmem.cmd "$@" SHIMEOF chmod +x ~/.local/bin/nmem ``` 这会创建一个薄封装脚本,从 Windows 挂载目录通过 WSL 互操作调用 Windows 端的 `nmem`。这样可以避开在 WSL 主目录下常见的 UNC 路径报错。由于命令实际作为 Windows 进程运行,它会直接连接到桌面端应用的 `localhost`,不需要额外的网络配置。 **验证是否正常工作:** ```bash nmem status ``` 如果创建脚本后 `nmem` 仍然找不到,请确认 `~/.local/bin` 在你的 PATH 中。Ubuntu 默认会自动添加;其他发行版需要在 `~/.bashrc` 或 `~/.zshrc` 中加入 `export PATH="$HOME/.local/bin:$PATH"`。 此方法依赖 WSL 互操作功能(默认已启用)。如果你在 `/etc/wsl.conf` 中设置了 `interop=false` 或 `appendWindowsPath=false`,请重新启用,或者改用 `pip install nmem-cli` 配合[随处访问 Mem](/zh/docs/remote-access)。 此桥接脚本以 Windows 进程运行 `nmem`,因此 `nmem t save --from claude-code` 等命令会在 Windows 主目录查找会话文件,而非 WSL 主目录。实际使用中这并不影响什么:桌面端应用会通过内置的文件监视器自动捕获 WSL 中的会话。如果你需要从 WSL 直接通过 CLI 保存会话,请改用 `pip install nmem-cli`。 ## nmem status 提示"Not Found" [#nmem-status-提示not-found] **症状:** 使用远程服务器时,`nmem status` 显示 "Not Found: Resource doesn't exist",但 TUI 能正常使用。 **原因:** CLI 访问了错误的 URL。通常是因为这台机器的客户端连接配置不存在,或者 URL 配错了。 **解决方案:** 1. 重新写入客户端连接配置: ```bash nmem config client set url https://<你的地址> nmem config client set api-key nmem_... ``` 2. 用 curl 验证连接:`curl -H "Authorization: Bearer $NMEM_API_KEY" "$NMEM_API_URL/health"` 3. 更新到最新版 `nmem` CLI,新版本会给出更清晰的错误提示和远程配置引导。 完整流程见:[随处访问 Mem](/zh/docs/remote-access)。 ## 远程访问返回 429 [#远程访问返回-429] **症状:** `nmem status` 或 `curl` 返回 `429 Too many invalid auth attempts`。 **解决方案:** 客户端多次使用了错误的 API key。 * 在 **设置 → 随处访问 Mem** 重新复制 URL + key * 确认 `NMEM_API_KEY` 完整且没有多余空格/引号 * 如果不确定,点击 **Rotate** 生成新 key 完整流程见:[随处访问 Mem](/zh/docs/remote-access)。 ## 远程访问返回 401 Missing API key [#远程访问返回-401-missing-api-key] **症状:** Tunnel URL 可访问,但 `nmem status` 或 `curl` 返回 `401 Missing API key`。 **原因:** 某些网络代理会移除鉴权头。 **解决方案:** * 升级到最新版 `nmem`(会自动使用代理兼容回退) * 在 **设置 → 随处访问 Mem** 重新复制 URL + key * 手动 `curl` 可用: `curl "$NMEM_API_URL/health?nmem_api_key=$NMEM_API_KEY"` ## Mem 提示图谱内存已调高 [#mem-提示图谱内存已调高] **症状:** 资料库变大后,搜索、图谱或保存开始失败,标题栏还会出现“图谱内存已更新”之类的提示。 **原因:** Mem 已经把下次启动要用的图谱内存调大了,但你当前这次运行还在用旧额度,所以问题会继续出现,直到你退出再打开。 **解决办法:** 1. 先退出,再重新打开 Nowledge Mem,让新的图谱内存额度生效。 2. 如果这个提示反复出现,去 **设置 → Processing → Database Tuning**,把 **图谱内存** 再调大一档。 3. 如果你是无头 / 服务器部署,在启动 `nmem serve` 之前设置 `NOWLEDGE_KUZU_BUFFER_POOL_SIZE=512MB`(或更高)。 ## 为什么 Mem 看起来占用了不少内存 [#为什么-mem-看起来占用了不少内存] **症状:** 在活动监视器(macOS)或任务管理器(Windows)里,看到 Nowledge Mem 占用接近 1 GB 内存,对一个做记忆、记笔记的应用来说显得有点高。 **这是正常的,而且这个数字会骗人。** 系统显示的数字,并不是 Mem 真正需要的内存。里面大部分都算不上对你机器的真实压力,主要是三块: * **已经用完、还没被收回的内存。** 搜索、导入、后台整理这些活忙完之后,系统会先把这些内存页留在 Mem 名下,而不是马上收回去,因为来回交还很慢。别的程序一需要,它们随时会被拿走。 * **程序自身的代码。** Mem 是一个自带运行环境的整体应用,它的程序代码也会被算进这个数字;但这部分是只读、可共享的,系统一缺内存就能立刻丢掉。 * **存在磁盘上的你的知识。** 你的图谱和搜索索引其实是磁盘上的文件。系统为了读得快把它们映射进来,于是算进了 Mem 的内存,但它们并不是真的待在内存里,需要时会被释放。 Mem 真正在用的内存远小于这个显示数字,而且**除非你在用本地模型,否则它不会把任何 AI 模型常驻内存**。 这里你什么都不用做。如果机器真的内存吃紧,系统会自动收回其中的大部分。后续还有一个更新会改进 Mem 把闲置内存交还给系统的方式,到时候这个显示数字也会自己变小。
想自己核实的话,这是实测数据 在一个约 2100 条记忆的真实库、空闲状态下,用各系统自带的工具测得。结论在每个平台都一样:显示出来的数字,远大于实际在用的内存。 **macOS**:用 `footprint ` 或 `vmmap -summary ` 对着 `nmem-server` 进程就能复现: | 项目 | 大小 | | ----------------------- | ----------- | | 显示的内存(`phys_footprint`) | \~1024 MB | | 共享的程序代码(只读、可回收) | \~281 MB | | 映射进来的数据库文件(实际在磁盘上) | 常驻 \~0.3 MB | | 已释放、还没还给系统的内存 | \~500 MB | | 真正在用的内存 | 剩下的一小部分 | 在 Mac 上,Mem 把本地向量模型放到 GPU 上跑,所以它的工作缓冲不计入主进程数字,上面这个数大部分是可回收的。 **在没有可用 GPU 的机器上**(部分 Windows / Linux,或无头服务器),本地向量模型改在 CPU 上跑,会预留一块更大的工作缓冲,所以那里的数字确实会更高(实测约 4–5 GB)。这只在你**用 CPU 跑本地向量模型**时才会出现。最省事的办法是改用**远程向量模型**,这样这块缓冲根本不会占用你的机器:**Nowledge AI**(Mem Plus 自带)开箱即用、无需配置,你也可以接入自己的向量模型服务(用自己的 key)。如果坚持本地跑,换一台带 GPU 的机器也能把占用压下来。此外,我们也会在后续更新里缩小本地 CPU 这块缓冲。
## Linux 服务器部署时提示无法连接 127.0.0.1:14242 [#linux-服务器部署时提示无法连接-12700114242] **症状:** `nmem license activate`、`nmem models download`、`nmem config ...` 这类命令报错,说“Cannot reach [http://127.0.0.1:14242”。](http://127.0.0.1:14242”。) **原因:** 这些命令需要先连上本机的 Mem 服务。fresh install 的 Linux 服务器里,最常见的情况就是服务还没启动,或者你用了 `nmem serve` 前台启动,但没有意识到后面的命令要在第二个终端里跑。 **解决办法:** 1. 真正的服务器场景,先装后台服务:`sudo nmem service install --service-user ` 2. 然后确认服务已经起来:`nmem service status` 和 `nmem status` 3. 如果你只是临时用 `nmem serve` 测一下,那就保持那个终端别关,再开第二个终端执行其他 `nmem` 命令 4. 如果你要从自己电脑上的浏览器打开 Web App,先运行 `nmem key --show-login`,然后把它打印出来的那个端口做 SSH 转发:`ssh -L :127.0.0.1: ` 5. 需要重新看登录 key 时,新版本用 `nmem key --show-login`,老版本用 `nmem key` ## 报告问题 [#报告问题]
# 试试这些 (/docs/zh/try-these) 时间线输入处理一切:问题、知识捕获、URL、文件、定时任务。自然输入,AI 自动判断类型。下面这些查询可以帮你验证各项功能是否已经接通。 这些查询随着知识增长越来越有用。持续使用一周后,结果会明显不同。 ## 查询列表 [#查询列表]
### 展示今日焦点简报 [#1-展示今日焦点简报] 读取你的焦点简报。你当前在推进什么、哪些事项需要注意、最近发生了什么。原生连接和配置得当的智能体可以在会话开始时自动读取对应的 Working Memory。
### 哪些想法变化最大? [#2-哪些想法变化最大] 找到最长的 EVOLVES 链,经历了多次修订的想法。按时间讲述故事:"一月你决定用 PostgreSQL。三月,你开始考虑混合方案。最新笔记确认迁移到双数据库架构。"
### 从我的笔记中生成了哪些知识结晶? [#3-从我的笔记中生成了哪些知识结晶] 展示合成的知识结晶,系统在夜间从多条相关记忆中提炼的参考文章。这些是你从单条笔记中无法获得的洞察。
### 总结我最近的编程对话 [#4-总结我最近的编程对话] 如果你的编程会话已经通过本地自动同步、原生保存路径,或对话导入进入 Mem,这个查询会列出并总结最近的会话:讨论了什么、构建了什么、做了哪些决策。
### 刚决定主数据库用 PostgreSQL [#5-刚决定主数据库用-postgresql] 知识捕获。系统保存为记忆,搜索相关决策,并提及关联:"这与你之前关于数据库扩展的笔记相关。"自然输入即可,AI 自动分类并存储。
### 记一下 `https://example.com/interesting-article` [#6-记一下-httpsexamplecominteresting-article] 粘贴 URL,系统会抓取、解析并索引内容。AI 阅读页面并将实质性摘要存储为记忆。URL 及其内容变得可搜索。在 URL 前加注释,AI 会同时捕获两者。
### 今晚对我最近的记忆执行知识图谱抽取 [#7-今晚对我最近的记忆执行知识图谱抽取] 安排后台智能任务。后台智能在指定时间触发,拥有完整工具访问权限:可以分析记忆、检测矛盾、创建 EVOLVES 链接或生成知识结晶。自然语言定时:"2小时后"、"明天早上"、"下周"。最短5分钟,最长30天。
### 在我的文档中搜索 \[主题] [#8-在我的文档中搜索-主题] 全文搜索资料库中所有源文档。将文件(PDF、Word、Markdown)拖放到时间线输入框,或通过资料库添加。文件会被解析、分块并索引,支持语义搜索。
### 我的知识有哪些主要主题? [#9-我的知识有哪些主要主题] 这一条需要持续用满一周,并跑过后台处理才会有结果。 社区检测将你的实体聚类为主题领域,附带 AI 摘要。系统执行夜间分析,将相关概念分组。你会看到从未有意识追踪的主题:一个你不知道存在的"开发者体验"聚类,或贯穿数月笔记的"数据架构"主题。
## 复合效应 [#复合效应] 这些查询随时间推移越来越有用: * **第 1 周**:基本搜索可用,社区聚类可能还没形成。 * **第 1 月**:演变链开始出现,知识结晶逐渐成型,主题聚类变得可用。 * **第 3 月**:跨领域连接开始浮现,每日简报的实际参考价值明显提高。 * **第 6 月**:系统积累的上下文足以在多数查询中给出有针对性的回答。 ## 下一步 [#下一步] * [快速开始](/zh/docs/getting-started):五分钟完成设置 * [查看你的专业知识](/zh/docs/use-cases/expertise-graph):可视化探索知识图谱 * [后台智能](/zh/docs/advanced-features):系统如何在夜间学习 # 使用 Nowledge Mem (/docs/zh/usage) 先回到 [从这里开始](/zh/docs/start-here) 和 [如何确认 Mem 已经在工作](/zh/docs/verify-it-works)。当你已经先完成一次保存、找回、再给工具使用的过程以后,这一页会更容易理解。 ## Timeline [#timeline] Timeline 是你的主页。你捕获的、你提问的、系统自己发现的,都在一个流里。 Nowledge Mem Timeline ### 你会看到什么 [#你会看到什么] Timeline 中会出现这些类型: | 项目 | 说明 | | --------------- | ------------------- | | **Capture** | 你保存的记忆,自动生成标题和标签 | | **Question** | 你的提问和 AI 基于知识库给出的回答 | | **URL Capture** | 抓取、解析并存储的网页 | | **Insight** | 系统在你的记忆之间发现的关联 | | **知识结晶** | 对多条相关记忆的综合提炼 | | **标记** | 矛盾信息、过时内容或需要验证的观点 | | **工作记忆** | 你的每日晨间简报 | 不需要手动整理。 ## 你的 AI 工具 [#你的-ai-工具] 把你真正使用的 AI 工具连接到知识库里。Claude Code、Grok Build、Cursor、Codex、OpenCode、Alma、DeepChat、LobeHub、Grok Web 等,都可以通过合适的路径连接回同一个记忆系统。 如果你还在判断某个工具该怎么接入,请先看[连接](/zh/docs/integrations)。这一页讲的是:当其中一条路径已经接通之后,Mem 用起来会是什么感觉。 **没有 Mem:** *"帮我给 API 加缓存。"* 智能体通常会继续追问你用什么技术栈、什么基础设施、什么偏好。你从头解释一遍。 **有 Mem:** *"帮我给 API 加缓存。"* 智能体可以搜索你的知识,找到上个月的 Redis 决策和 API 限流方案,更快写出符合你架构的代码,少很多重复解释。 在连接做得好的情况下,这一步不需要你反复提醒。原生连接、配置好的复用型工作流包,或带有清晰意图规则的 MCP 客户端,都会在需要时主动去找你的知识。
今天在 Claude Code 中保存一条洞察,明天 Cursor 遇到同一主题时自动找到。不需要导出,不需要复制。 你也可以直接询问 Agent:*"上个月我对数据库迁移做了什么决定?"*,它会搜索你的知识来回答。 详见[连接](/zh/docs/integrations)了解设置说明。 ## 搜索 [#搜索] ### 应用内 [#应用内] 按 Cmd + K(macOS)打开记忆搜索。搜索理解语义,不仅仅是关键词。搜索"设计模式"会找到关于"架构方法"的记忆。 记忆搜索 三种搜索模式协同工作: * 语义搜索:按含义查找记忆 * 关键词搜索:精确匹配特定术语 * 图搜索:通过连接和关系发现记忆 ### 全局搜索 [#全局搜索] 全局启动器让你无需打开 Nowledge Mem 就能搜索。在任何应用中按 Cmd + Shift + K,搜索后直接将结果粘贴到需要的地方。如果你使用 [Raycast](https://raycast.com),[Nowledge Mem 扩展](/zh/docs/integrations/raycast)可以将同样的搜索直接带入你的启动器。 Memory Search Launcher
## 知识如何随时间成长 [#知识如何随时间成长] 持续使用几周后,系统会开始在后台帮你整理线索。 周二你保存了一条 PostgreSQL 决策。周四你提到 CockroachDB 是迁移目标。周五早上,Working Memory 简报写道:"你的数据库选型在演变。" 这就是后台智能在做的事: * 知识演变:发现你对同一话题的想法在变,自动把各个版本串起来。 * 知识结晶:把分散的记忆综合成一篇参考文章。 * 标记:过去和现在的想法打架时主动提醒你。 * 工作记忆:每天的简报,AI 工具开始会话时自动读取。 后台智能需要已配置的远程 LLM,以及你的当前版本所对应的许可能力。 ## AI Now [#ai-now] 连接到你的 Mem 服务器的个人 AI 工作区,可以使用你保存的知识、连接的笔记、文件和已启用的插件。同一组会话可在桌面端、网页版和移动端继续使用。详见 [AI Now](/zh/docs/ai-now) 完整指南。 ## 命令行 [#命令行] `nmem` CLI 让你从任何终端获得完整访问: ```bash # 搜索你的记忆 nmem m search "authentication patterns" # 添加记忆 nmem m add "We chose JWT with 24h expiry for the auth service" # JSON 输出用于脚本 nmem --json m search "API design" | jq '.memories[0].content' ``` 详见 [CLI 参考](/zh/docs/cli)获取完整命令集。 ## 远程 LLM [#远程-llm] 默认在本地运行,不需要联网。知识库增长后,远程 LLM 能给你更强的处理能力。 远程 LLM 配置取决于你当前使用的版本和许可方式。 配好之后能多用上这些: * 后台智能:自动发现关联、生成知识结晶、产出洞察以及每日简报 * 更快的知识图谱提取 * 更细腻的语义理解 * AI Now Agent 能力 隐私方面,你的数据只会发往你自己选的 LLM 提供商,绝不会经过 Nowledge Mem 服务器。你随时可以切回纯本地模式。
### 打开远程 LLM 设置 [#打开远程-llm-设置-step] 前往 **Settings > Remote LLM**
### 开启远程模式 [#开启远程模式-step] 开启 **Remote** 模式
### 添加提供商与 API 密钥 [#添加提供商与-api-密钥-step] 选择你的 LLM 提供商并输入 API 密钥
### 测试连接、选择模型并保存 [#测试连接选择模型并保存-step] 测试连接,选择模型,保存 Remote LLM
## 下一步 [#下一步] * **[从这里开始](/zh/docs/start-here)**:为你的真实工作流选择最简单的第一条路径 * **[如何确认 Mem 已经在工作](/zh/docs/verify-it-works)**:确认搜索、捕获与工具连接 * **[记忆](/zh/docs/memories)**:创建、搜索、组织和连接你的知识 * **[对话](/zh/docs/threads)**:捕获、浏览和提炼 AI 对话 * **[资料库](/zh/docs/library)**:导入文档,与记忆一起搜索 * **[AI Now](/zh/docs/ai-now)**:基于你的知识进行深度研究和分析 * **[后台智能](/zh/docs/advanced-features)**:知识图谱、洞察、知识结晶、工作记忆 * **[你的档案](/zh/docs/profile)**:让 Mem 了解你是谁,代理的结果会更准确 * **[连接](/zh/docs/integrations)**:为每个 AI 工具选择合适的连接路径 # 如何确认 Mem 已经在工作 (/docs/zh/verify-it-works) 当你能明确地指着一个结果,说出下面这些话时,Mem 才算真的开始工作: * 这确实来自我自己的知识 * 这段对话确实被保存进来了 * 这个工具确实用上了我已经存下来的上下文 这一页的目标,就是帮你尽快证明这一点。 ## 核心测试 [#核心测试] 在测试任何集成之前,先确认应用本身最基础的一步已经成立:
### 保存一条记忆 [#保存一条记忆-step] 在 Timeline 里写下一条真实的事实、决定或偏好,然后按回车。
### 再把它问回来 [#再把它问回来-step] 针对这条记忆直接问一句: > 我之前对部署做过什么决定?
### 看回答是否真正基于你自己的内容 [#看回答是否真正基于你自己的内容-step] 如果回答明显反映了你刚刚保存的内容,而不是泛泛而谈,说明 Mem 已经在工作。
## 如果你先只用应用本身 [#如果你先只用应用本身] 你应该能做到这三件事: * 在 Timeline 里保存一条记忆 * 再次搜索并找到它 * 问一个问题,并得到基于你自己知识的回答 如果这一步成立,说明应用本身已经能正常工作。 ## 如果你使用浏览器扩展 [#如果你使用浏览器扩展] 当下面几项都成立时,说明 Mem 已经接通: * 扩展可以正常打开侧边栏 * 如果你使用远程访问,连接测试能够成功 * 至少有一段网页对话被成功捕获或提炼进 Mem * 你能在应用里把它打开成一条记忆或一个线程 如果你还没有达到这个状态,就回到 [浏览器扩展指南](/zh/docs/integrations/browser-extension)。 ## 如果你使用编程助手 [#如果你使用编程助手] 当工具能够调用你之前保存过的上下文时,才算是真的接通。 可以这样测试: 1. 先在 Mem 里保存一条简短决定,例如你偏好的缓存方案。 2. 通过这个工具的专属集成打开你的编程助手。 3. 提一个本应受这条上下文帮助的问题。 例如: * “我之前对缓存方案做过什么决定?” * “继续我之前在认证模块上的做法。” * “搜索我以前关于 Redis 的决策。” 当工具不再让你从头解释,而是能调用你已有的知识时,这条连接才算真的建立。 请使用对应指南: * [Claude Code](/zh/docs/integrations/claude-code) * [Cursor](/zh/docs/integrations/cursor) * [Gemini CLI](/zh/docs/integrations/gemini-cli) * [Copilot CLI](/zh/docs/integrations/copilot-cli) * [OpenClaw](/zh/docs/integrations/openclaw) * [Alma](/zh/docs/integrations/alma) * [Codex](/zh/docs/integrations/codex-cli) ## 如果你使用 AI Now [#如果你使用-ai-now] 当下面几项成立时,说明 AI Now 已经工作正常: * 你已经为所需功能配置好了远程 LLM * 你提问的是和自己已保存知识相关的内容 * 回答明显建立在你的记忆、文件或已启用插件之上,而不是泛泛的模型回答 如果 AI Now 无法启动,或无法利用你的已保存上下文,请查看 [AI Now](/zh/docs/ai-now) 和 [故障排除](/zh/docs/troubleshooting)。 ## 如果你在多台设备上使用 Mem [#如果你在多台设备上使用-mem] 当下面这些都成立时,说明你的同步已经正常工作: * 第二台设备能用同一个 Mem URL 和 API Key 成功连接 * 在一个客户端创建的记忆或线程,会出现在另一个客户端里 * 两边搜索到的是同一套知识库内容 如果你还不确定 Mem 这里说的“同步”到底是什么模型,先看[多设备同步](/zh/docs/sync)。具体配置步骤请看[随处访问](/zh/docs/remote-access)。 ## 正常工作的信号 [#正常工作的信号] * 搜索结果里能看到你自己的措辞、决定或引用 * 捕获的对话出现在 Threads 里 * 你连接的工具能调用过去的决策,而不需要你重新粘贴 * AI Now 能够基于你的知识来回答问题 ## 值得警惕的信号 [#值得警惕的信号] * 你得到的始终是泛化模型输出,看不出和你保存内容的关系 * 你一次配置了很多路径,但没有任何一条给出明确结果 * 在还没确认应用本身已经工作之前,就开始测试 MCP 或 CLI * 希望浏览器捕获、编程助手接入和 AI Now 同时证明自己 ## 如果你仍然觉得不清楚 [#如果你仍然觉得不清楚] 回到最小路径: 1. [从这里开始](/zh/docs/start-here) 2. 在 Timeline 保存一条记忆 3. 先验证应用本身 4. 只连接一个你真实在用的工具 ## 下一步 [#下一步] * [从这里开始](/zh/docs/start-here):先选对第一条路径 * [快速入门](/zh/docs/getting-started):了解 Timeline 工作流 * [连接](/zh/docs/integrations):用正确方式连接合适的工具 * [多设备同步](/zh/docs/sync):理解“一台 Mem,多端接入”的同步模型 * [故障排除](/zh/docs/troubleshooting):诊断启动、连接与会话问题 # Capabilities (/docs/api/capabilities/get) ## GET /capabilities **Summary:** Capabilities Server capabilities — unauthenticated, used by clients to adapt UI. Returns the server version and feature flags. Clients (desktop remote, web /app, mobile) use this to hide features the server cannot support or the operator has disabled. ### OpenAPI Operation ```json { "/capabilities": { "get": { "tags": [ "health" ], "summary": "Capabilities", "description": "Server capabilities — unauthenticated, used by clients to adapt UI.\n\nReturns the server version and feature flags. Clients (desktop remote,\nweb /app, mobile) use this to hide features the server cannot support\nor the operator has disabled.", "operationId": "capabilities_capabilities_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } } } ``` # List Communities (/docs/api/communities/get) ## GET /communities **Summary:** List Communities List knowledge communities with AI summaries. ### OpenAPI Operation ```json { "/communities": { "get": { "tags": [ "analytics" ], "summary": "List Communities", "description": "List knowledge communities with AI summaries.", "operationId": "list_communities_communities_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 50, "minimum": 1, "default": 20, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Entities (/docs/api/entities/get) ## GET /entities **Summary:** List Entities List entities with optional filtering. When ``include_stats=true`` returns ``[{"entity": EntityNode, "mention_count": int}, ...]`` sorted by mention_count DESC. Otherwise returns the legacy ``List[EntityNode]`` sorted by created_at DESC, preserving backwards compatibility for older callers (Tauri commands, MCP tools). ### OpenAPI Operation ```json { "/entities": { "get": { "tags": [ "entities" ], "summary": "List Entities", "description": "List entities with optional filtering.\n\nWhen ``include_stats=true`` returns\n``[{\"entity\": EntityNode, \"mention_count\": int}, ...]`` sorted by\nmention_count DESC. Otherwise returns the legacy ``List[EntityNode]``\nsorted by created_at DESC, preserving backwards compatibility for\nolder callers (Tauri commands, MCP tools).", "operationId": "list_entities_entities_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "default": 50, "title": "Limit" } }, { "name": "entity_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Entity Type" } }, { "name": "include_stats", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Return entities sorted by mention_count DESC and include the count alongside each entity. Powers the Library Entities tab's signal-first ranking. When false (default), the response shape is the legacy List[EntityNode].", "default": false, "title": "Include Stats" }, "description": "Return entities sorted by mention_count DESC and include the count alongside each entity. Powers the Library Entities tab's signal-first ranking. When false (default), the response shape is the legacy List[EntityNode]." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Nowledge FS API (/docs/api/fs) The Nowledge FS API is the preview API behind [Knowledge Tree](/docs/nowledge-fs). It projects Mem as a stable tree and is the same surface used by the app's Tree view, the `nmem fs` CLI, and the `mem_fs` MCP tool. Use it when an integration or agent should browse memories, threads, wiki pages, working memory, activities, sources, and artifacts through paths. This is not a mounted filesystem yet. Paths are Mem API identifiers, not local OS paths. Mounting, source fragments, SQL/Cypher, replay, and tail are planned for later phases. ## Read [#read] ```bash curl "http://127.0.0.1:14242/fs/capabilities" curl "http://127.0.0.1:14242/fs/ls?path=/" curl "http://127.0.0.1:14242/fs/cat?path=/memories/by-id/mem_abc.memory.md" curl "http://127.0.0.1:14242/fs/cat?path=/sources/report_abc.pdf&line=120&lines=80" curl "http://127.0.0.1:14242/fs/stat?path=/memories/by-id/mem_abc.memory.md" ``` | Endpoint | Purpose | | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | `GET /fs/capabilities` | Discover supported roots, verbs, limits, entry points, and feature flags. Use this before writing adapters. | | `GET /fs/ls?path=/...&limit=200&cursor=...` | List a directory. Cursors are opaque. | | `GET /fs/cat?path=/...&line=...&lines=...` | Read a rendered file body and frontmatter, or a small line window. | | `GET /fs/stat?path=/...` | Read metadata without loading the body. | ## Search [#search] ```bash curl "http://127.0.0.1:14242/fs/find?path=/memories&type=memory&label=decisions" curl "http://127.0.0.1:14242/fs/grep?path=/memories&q=JWT%20rotation" curl "http://127.0.0.1:14242/fs/grep?path=/threads&q=JWT%20rotation" curl "http://127.0.0.1:14242/fs/grep?path=/sources&q=JWT%20rotation" curl "http://127.0.0.1:14242/fs/grep?path=/threads&q=JWT%7Ctoken®ex=true" curl "http://127.0.0.1:14242/fs/recall?path=/memories&query=session%20token%20strategy&k=5" ``` | Endpoint | Purpose | | ---------------- | ------------------------------------------------------------------------------------------------------------- | | `GET /fs/find` | Structural search. Use this for type, label, date, and mention constraints. | | `GET /fs/grep` | Exact-string search over memories, thread messages, and parsed Library documents. Add `regex=true` for regex. | | `GET /fs/recall` | Semantic search that returns paths. | `find` and `recall` return `paths`. `grep` returns `matches` with paths and line numbers. Grep is case-insensitive by default; pass `case_sensitive=true` when casing matters, or `regex=true` for patterns such as `JWT|token`. Agents should feed returned paths into `stat`, `ls`, or `cat`; for long files, use `cat` with `line` and `lines` to read only the useful window. ## Write [#write] ```bash curl -X POST "http://127.0.0.1:14242/fs/write" \ -H "Content-Type: application/json" \ -d '{"path":"/memories/by-id/mem_abc.memory.md","body":"Updated note"}' curl -X POST "http://127.0.0.1:14242/fs/delete" \ -H "Content-Type: application/json" \ -d '{"path":"/memories/by-id/mem_abc.memory.md"}' ``` Writes are deliberately narrow. Canonical writable paths write through the existing Mem APIs. Alias paths, derived wiki pages, and implementation views are read-only. | Code | Meaning | | --------- | -------------------------------------------------------------- | | `ENOENT` | Path does not exist. | | `EROFS` | Derived path is read-only. | | `EXDEV` | Alias path cannot be written directly; use the canonical path. | | `EINVAL` | Invalid path, argument, or body. | | `ENOTSUP` | Designed but not implemented in this release. | ## Agent pattern [#agent-pattern] ```text recall "what did we decide about auth?" --in /memories cat /memories/by-id/.memory.md ls /memories/by-label/auth stat /wiki/entities/PostgreSQL--.entity.md ``` The important property is that every result is navigable. Search is an entry point into the tree, not a terminal list of snippets. # Health Check (/docs/api/health/get) ## GET /health **Summary:** Health Check Health check endpoint. ### OpenAPI Operation ```json { "/health": { "get": { "tags": [ "health" ], "summary": "Health Check", "description": "Health check endpoint.", "operationId": "health_check_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } } } } } ``` # List Labels (/docs/api/labels/get) ## GET /labels **Summary:** List Labels List labels with usage counts. Paginate with ``offset`` to read past the first ``limit`` rows; the vocabulary can exceed a single page (the prior no-offset cap left labels beyond 1000 unreachable). ### OpenAPI Operation ```json { "/labels": { "get": { "tags": [ "labels" ], "summary": "List Labels", "description": "List labels with usage counts.\n\nPaginate with ``offset`` to read past the first ``limit`` rows; the\nvocabulary can exceed a single page (the prior no-offset cap left labels\nbeyond 1000 unreachable).", "operationId": "list_labels_labels_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 100, "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset" } }, { "name": "order_by", "in": "query", "required": false, "schema": { "type": "string", "default": "name", "title": "Order By" } }, { "name": "order_desc", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Order Desc" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/LabelResponse" }, "title": "Response List Labels Labels Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Create Label (/docs/api/labels/post) ## POST /labels **Summary:** Create Label Create a new label. ### OpenAPI Operation ```json { "/labels": { "post": { "tags": [ "labels" ], "summary": "Create Label", "description": "Create a new label.", "operationId": "create_label_labels_post", "parameters": [ { "name": "name", "in": "query", "required": true, "schema": { "type": "string", "description": "Label name", "title": "Name" }, "description": "Label name" }, { "name": "color", "in": "query", "required": false, "schema": { "type": "string", "description": "Label color (hex)", "default": "#3b82f6", "title": "Color" }, "description": "Label color (hex)" }, { "name": "description", "in": "query", "required": false, "schema": { "type": "string", "description": "Label description", "default": "", "title": "Description" }, "description": "Label description" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Memories (/docs/api/memories/get) ## GET /memories **Summary:** List Memories List memories with filtering and pagination. ### OpenAPI Operation ```json { "/memories": { "get": { "tags": [ "memories" ], "summary": "List Memories", "description": "List memories with filtering and pagination.", "operationId": "list_memories_memories_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset" } }, { "name": "state", "in": "query", "required": false, "schema": { "type": "string", "default": "active", "title": "State" } }, { "name": "importance_min", "in": "query", "required": false, "schema": { "type": "number", "maximum": 1, "minimum": 0, "default": 0, "title": "Importance Min" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "type": "string", "description": "Isolation space to list", "default": "default", "title": "Space Id" }, "description": "Isolation space to list" }, { "name": "is_crystal", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "description": "Filter by crystal flag: true for crystals only, false for non-crystal only, omit for both.", "title": "Is Crystal" }, "description": "Filter by crystal flag: true for crystals only, false for non-crystal only, omit for both." }, { "name": "unit_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by memory unit type: fact, preference, decision, plan, procedure, learning, context, or event.", "title": "Unit Type" }, "description": "Filter by memory unit type: fact, preference, decision, plan, procedure, learning, context, or event." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryListResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Create Memory (/docs/api/memories/post) ## POST /memories **Summary:** Create Memory Create a new memory with automatic entity extraction. Provenance is recorded only when a caller supplies a real id it owns: ``source_thread_id``/``source_message_id`` link the memory to its originating thread/message (UI, launcher, distillation). We never infer provenance, so absence is honest rather than a guess. ### OpenAPI Operation ```json { "/memories": { "post": { "tags": [ "memories" ], "summary": "Create Memory", "description": "Create a new memory with automatic entity extraction.\n\nProvenance is recorded only when a caller supplies a real id it owns:\n``source_thread_id``/``source_message_id`` link the memory to its\noriginating thread/message (UI, launcher, distillation). We never infer\nprovenance, so absence is honest rather than a guess.", "operationId": "create_memory_memories_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryCreateRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryCreateResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Skills (/docs/api/skills/get) ## GET /skills **Summary:** List Skills List skills. Cross-space unless ``space_id`` is given. ### OpenAPI Operation ```json { "/skills": { "get": { "tags": [ "skills", "skills" ], "summary": "List Skills", "description": "List skills. Cross-space unless ``space_id`` is given.", "operationId": "list_skills_skills_get", "parameters": [ { "name": "stage", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by lifecycle stage", "title": "Stage" }, "description": "Filter by lifecycle stage" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Scope to a space (else all)", "title": "Space Id" }, "description": "Scope to a space (else all)" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "default": 100, "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response List Skills Skills Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Sources (/docs/api/sources/get) ## GET /sources **Summary:** List Sources List sources with optional filtering and pagination. ### OpenAPI Operation ```json { "/sources": { "get": { "tags": [ "sources" ], "summary": "List Sources", "description": "List sources with optional filtering and pagination.", "operationId": "list_sources_sources_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "default": 50, "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset" } }, { "name": "source_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by source_type", "title": "Source Type" }, "description": "Filter by source_type" }, { "name": "lifecycle_state", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by lifecycle_state", "title": "Lifecycle State" }, "description": "Filter by lifecycle_state" }, { "name": "labels", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Filter by source label name or label_id. Repeat for AND semantics.", "title": "Labels" }, "description": "Filter by source label name or label_id. Repeat for AND semantics." }, { "name": "label", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Alias for labels. Repeat for AND semantics.", "title": "Label" }, "description": "Alias for labels. Repeat for AND semantics." }, { "name": "metadata", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Filter by source metadata equality, e.g. metadata=customer=acme. Repeat for AND semantics; repeat the same key for OR values.", "title": "Metadata" }, "description": "Filter by source metadata equality, e.g. metadata=customer=acme. Repeat for AND semantics; repeat the same key for OR values." }, { "name": "space_id", "in": "query", "required": false, "schema": { "type": "string", "description": "Isolation space to list", "default": "default", "title": "Space Id" }, "description": "Isolation space to list" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SourceListResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Spaces (/docs/api/spaces/get) ## GET /spaces **Summary:** Get Spaces ### OpenAPI Operation ```json { "/spaces": { "get": { "tags": [ "spaces", "spaces" ], "summary": "Get Spaces", "operationId": "get_spaces_spaces_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceSettingsResponse" } } } } } } } } ``` # Create Space (/docs/api/spaces/post) ## POST /spaces **Summary:** Create Space ### OpenAPI Operation ```json { "/spaces": { "post": { "tags": [ "spaces", "spaces" ], "summary": "Create Space", "operationId": "create_space_spaces_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpacePayload" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceSettingsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Threads (/docs/api/threads/get) ## GET /threads **Summary:** List Threads List threads with filtering and pagination. ### OpenAPI Operation ```json { "/threads": { "get": { "tags": [ "threads" ], "summary": "List Threads", "description": "List threads with filtering and pagination.", "operationId": "list_threads_threads_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 20, "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset" } }, { "name": "source", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Source" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space to list", "title": "Space Id" }, "description": "Optional isolation space to list" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadListResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Create Thread (/docs/api/threads/post) ## POST /threads **Summary:** Create Thread Create a new thread with messages. ### OpenAPI Operation ```json { "/threads": { "post": { "tags": [ "threads" ], "summary": "Create Thread", "description": "Create a new thread with messages.", "operationId": "create_thread_threads_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadCreateRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadCreateResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # AI 档案 (/docs/zh/concepts/ai-profiles) AI 档案,是一个长期替你工作的 Agent 在 Mem 里的稳定身份。 当某个 Agent 不只是一次性聊天,而是会反复回来工作时,就适合给它建档案:代码 reviewer、研究 Agent、发版助手、写作搭档,或者多 Agent 工具里启动的某个 worker。档案告诉 Mem:这个 Agent 是谁,通常在哪个记忆空间里工作,开始前应该带上哪些规则。 ## 为什么需要它 [#为什么需要它] AI 工具已经有很多地方可以放行为设置:`AGENTS.md`、`CLAUDE.md`、Cursor rules、Codex profile、Hermes soul,以及各个宿主自己的设置。一个 Agent、一个工具时还好;多个 Agent、多个宿主一起用时,光知道“这是 Codex”就不够了。今天 Codex 里跑的可能是 reviewer,明天可能是 release helper。 Mem 把两件事分开: | 字段 | 含义 | | --------- | ------------------------------------------------ | | **AI 档案** | 正在工作的长期 Agent 是谁,比如 `cindy` 或 `release-reviewer` | | **来源应用** | 这条记录来自哪个运行时,比如 `codex`、`claude-code` 或 `hermes` | 来源应用只表示出处,不表示身份。 ## 第一个有用动作 [#第一个有用动作] 只给一个真实会反复出现的角色建档案。 例如: * 名字:`Cindy` * ID:`cindy` * 默认空间:`product` * 角色:负责审查面向产品的改动;回答简洁;确认测试后再说可以合并。 然后用 `NMEM_AGENT_ID=cindy` 启动这个 worker,或者在支持的 MCP / API 调用里传 `agent_id="cindy"`。下一次 Context Bundle 里,应该能看到选中的 AI 档案是 Cindy。 ## AI 档案里可以有什么 [#ai-档案里可以有什么] 一个 AI 档案可以包含: * 显示名称和稳定 ID * 对这个 Agent 角色的简短描述 * 默认读写的空间 * 只对这个档案生效的规则 * 可选的外部别名;只有集成需要把自己宿主里的稳定 worker ID 映射到 Mem 档案时才用 保持简短。档案应该回答“谁在工作”和“通常在哪个范围里工作”,不要把所有可能的指令都塞进去。 ## 它和相近概念的区别 [#它和相近概念的区别] | 概念 | 用来表达 | | --------- | -------------- | | **你的档案** | 你是谁、语言、别名和个人背景 | | **AI 档案** | 这个长期 Agent 是谁 | | **空间** | 这份工作属于哪一条记忆通道 | | **规则** | 哪些行为总是应该生效 | | **Skill** | 某类任务应该怎么做 | 如果同一个 Agent 在另一份工作里应该表现得不同,建一个新的档案。不要因为宿主很方便复用名字,就把互相冲突的工作塞进同一个身份里。 ## 接入工具如何选择它 [#接入工具如何选择它] Mem 只会从明确的身份信号里选择 AI 档案。 普通设置里,用其中一种: * `NMEM_AGENT_ID` * `agent_id` 高级集成也可以把自己的稳定 worker ID 映射到某个档案: * `NMEM_HOST_AGENT_ID` * `host_agent_id` 把它理解成外部别名,不是第二个身份。大多数用户不需要设置它。 它不会从 `source_app` 里选择档案。一个普通 Codex 会话,不应该因为来源应用是 `codex` 就自动变成 Cindy。 ## 暂时不用担心什么 [#暂时不用担心什么] 不需要给每个聊天窗口都建档案。普通使用时,默认档案已经够用。 不需要给每个工具都建档案。档案对应的是稳定角色,不是运行时。 也不需要一开始就设计完整团队层级。先从一个真的会反复回来的 Agent 开始。 ## 接下来读哪里 [#接下来读哪里] * [上下文](/zh/docs/ai-context):预览某个档案开始前会收到什么。 * [规则](/zh/docs/concepts/rules):为所有 Agent、某个档案或某个空间设置行为规则。 * [空间](/zh/docs/spaces):如果不同档案需要不同记忆范围。 # 后台智能 (/docs/zh/concepts/background-intelligence) Mem 里大部分有用的工作都在后台完成。实体提取、EVOLVES 检测、矛盾标记、知识结晶合成、工作记忆更新,都不需要你动手。你存一条记忆或导入一段对话,剩下的系统来。 这个页面讲跑了什么、什么时候跑、怎么防止失控。 ## 两类触发方式 [#两类触发方式] 后台任务按触发方式分为两类。 ### 定时任务 [#定时任务] 按固定时间运行,和你今天做了什么无关。 * 每日简报,每天清晨。回顾近期活动,生成洞察,标记矛盾,为每个活跃分区写一份新的 Working Memory。Default 分区保留兼容文件 `~/ai-now/memory.md`。 * 结晶审查,每周一次。找出可以合成为知识结晶的相关记忆集群。 * 洞察检测,每周一次。在知识库里搜索跨领域关联和模式。 * 技能建议,默认每 3 天运行一次。寻找你反复使用、值得教给 AI 的工作方式,做成一条 [Skill](/zh/docs/concepts/skills)。 * 规则建议,默认每 3 天运行一次。寻找反复出现、可能值得智能体长期遵守的偏好和规则。建议会先保持草稿状态,等你确认。 * 记忆整理,开启后每周运行。审查冗余记忆,并合并确认重复的内容。 * 标签整合,开启后每周运行。审查重复标签,包括不同语言写法,再决定是否合并。 * 社区检测,定期运行。重建实体图谱的社区结构,供搜索使用。 * 记忆新鲜度,开启后每天运行。重新计算所有记忆的新鲜度和置信分数。 * 记忆类型维护,默认每 3 天小批量运行。把记忆归到事实、决策、流程、经验或事件里,让智能体更容易找对上下文。 ### 事件驱动任务 [#事件驱动任务] 这些因为你做了某件事而触发,有一个短暂的延迟。 * EVOLVES 检测:保存新记忆时触发。检查新记忆是替代、丰富、印证还是质疑了已有知识。详见[知识演化](/zh/docs/concepts/evolves)。 * 实体提取:同步触发。为知识图谱提取实体和关系。 * 记忆类型维护:新记忆到达后小批量触发。它会改善记忆的组织方式,但不会改写你保存的记忆正文。 * 工作记忆刷新:新记忆到达时触发。更新当前分区的 Working Memory,让连接的智能体尽快看到新上下文。 * 集群评估:EVOLVES 边创建后触发。看新集群是否达到了结晶的形成条件。 ## 级联 [#级联] 这些任务不是独立的,一个动作可以触发一整条链。 你存一条记忆 → EVOLVES 检测跑起来 → 发现和一条旧记忆的"印证"关系 → 集群评估触发 → 发现三条相关记忆构成了足够强的集群 → 知识结晶被创建。 每一步都有自己的延迟窗口,系统是攒一批再处理。连续存五条记忆,系统会放在一起分析,不会跑五遍。 ## 四层保护 [#四层保护] 后台智能消耗 LLM token。没有限制的话,一波密集操作可能耗尽 token 预算,或者赶工太多产出低质量结果。四层机制防住这个。 防抖:事件驱动任务执行前等一段时间。等待期间又来了同类事件,计时器重置。导入一个长对话时,系统不会每条消息都分析一遍,而是合并成一次。 小时分批:保留本机每小时 token 限额时,Mem 也会把后台 LLM 任务按小时节奏分批,避免一大批积压在短时间内冲完。把每小时限额设为 `0` 或留空,就会取消这层本机小时分批。服务商冷却、每日限额和单任务安全保护仍然会生效。 Token 预算:可以设每小时和每天的 token 上限。预算花完后 LLM 任务暂停到下一个周期。不用 LLM 的任务(衰减刷新、社区检测)不受影响。 质量门控:抑制低价值输出。每日简报如果产出零洞察、零结晶、零标记,就保持沉默,不会生成一张"无事可报"的卡片。洞察检测会比对过去两周的记录避免重复。结晶至少需要三个汇聚来源。 ## 上下文注入 [#上下文注入] 每个后台任务启动前会收到预算好的上下文。每日简报拿到的是过去一周的活动摘要、昨天的工作记忆、图谱统计和最近的矛盾解决记录。省掉 LLM 自己探索的步骤,直接聚焦。 上下文有大小上限,超了就先裁低优先级的部分。 ## 工作记忆 [#工作记忆] 工作记忆是每日简报最直接的产出。每天早上归档昨天的,基于近期活动写一份新的。 Default 分区保留文件 `~/ai-now/memory.md`。如果你使用 spaces,其他分区也会通过同样的 Mem 接口拥有各自的 Working Memory。Claude Code、Grok Build、Cursor、Codex 这些工具之所以知道你最近在做什么、做了什么决定,靠的就是这份简报。 白天也会更新。存了新记忆后系统会刷新它,延迟比其他事件驱动任务长一些(因为跑一次成本更高)。你也可以手动编辑。 ## 处理设置 [#处理设置] 处理设置页里,大多数任务都有两类控制: * **运行按钮**:现在立即跑一次。 * **右侧开关**:控制之后是否允许 Mem 自动运行。 从设置里启动的小型维护任务会应用安全、已审查的结果。例如,记忆类型维护只会在一个有限批次里应用高置信的类型修正。 设置左下角出现绿色点,表示现在有后台任务正在跑。进入 **设置 → 处理** 后,可以看到当前任务名称、开始时间和可用进度。 最近运行会显示任务结果,以及已上报或估算的 token 用量。不调用 LLM 的日常整理任务会显示 `0 tokens`;调用 LLM 的任务会显示近似消耗,并标出服务商没有返回精确用量的步骤。 ## 用量统计边界 [#usage-boundaries] **设置 → 处理** 里的 AI 用量,是本机安全账本,不是所有 AI 消耗的总账单。 它会统计: * 这台设备上由 Mem 自动运行的后台任务 * AI Now、Graph Intelligence 这类内置前台 AI 会话,前提是服务商返回了用量 * 登录 Plus 后,由订阅计划提供的托管 AI 额度 它不会统计 Mem 周围所有工具发起的 AI 调用。Browser / Exchange agent、浏览器扩展、外部 IDE agent、第三方宿主工具,可能会通过它们自己的运行环境或模型账户调用模型。这些消耗可能真实存在,但应该在那个宿主工具或模型服务商的账单里确认,不属于本机 Mem 账本。 如果你使用自己的 API key,模型服务商后台仍然是账单的准确信源。Mem 的本机数字用于限制自动任务、发现异常消耗,但不能替代服务商账单。 有些服务商不会为每次响应返回 token 用量。遇到这种情况,Mem 会把对应运行标记为“部分上报”,提醒你看到的总数可能低于真实消耗。 这些任务的风险级别不一样: * **安全的日常整理**:记忆新鲜度和记忆类型维护会改善哪些记忆更容易出现、以及它们如何归类;不会改写你保存的记忆正文。 * **先审查再维护**:Memory Maintenance 会在旧记忆或重叠记忆可能造成噪音时,在 Timeline 里准备一条审查建议。新鲜度刷新本身不会归档、合并、删除或改写记忆。 * **合并类任务**:记忆整理和标签整合会在审查后合并图谱记录。它们默认关闭;只有你希望 Mem 自动保持图谱整洁时再打开。 * **移出日常召回**:低风险事实和事件可以在你确认后移出日常召回。偏好、决定、流程、计划、经验、规则、身份和上下文记忆不会被机械归档,只会作为语义整理的候选。 普通用户保持默认设置即可。如果你在服务器或 VPS 上运行 Mem,可以用同页的 token 限额控制后台 AI 成本。 全量维护任务,比如全量记忆类型重分类,可能消耗较多 AI 额度,也会触达很多记忆。请通过 CLI 运行,先预览结果,再确认是否应用: ```bash nmem memories reclassify-types --target-type procedure --full-scan --wait nmem memories reclassify-types --target-type procedure --full-scan --apply --wait ``` ## 任务控制 [#任务控制] 每个后台任务都有独立的开关。你可以关掉 EVOLVES 检测但保留每日简报,或者禁用洞察检测但保留实体提取。总开关可以一次性关闭全部。 Token 预算和调度参数(简报时间、社区检测间隔)也可以配置。后台智能需要配置远程 LLM,因为任务在你的机器上运行,需要一个模型来推理。 ## 延伸阅读 [#延伸阅读] * [记忆衰减](/zh/docs/concepts/memory-decay)讲解衰减刷新任务以及分数如何计算 * [知识演化](/zh/docs/concepts/evolves)详细解释 EVOLVES 检测 * [知识结晶](/zh/docs/concepts/crystals)解释结晶审查和什么触发结晶创建 # 知识结晶 (/docs/zh/concepts/crystals) 你在一次 ChatGPT 对话中提到了 React 性能优化。一周后,在 Cursor 里又讨论了同一个话题。一个月后,你保存了一篇相关的文章。每条记忆本身都有用,但没有哪条能给你完整的图景。 知识结晶就是系统注意到这种汇聚,从碎片中合成出一份完整参考。 ## 什么是知识结晶 [#什么是知识结晶] 知识结晶是一种特殊的记忆。三条以上独立触及同一话题的源记忆,由系统读取、识别各自的贡献、合成为一份独立可读的文档。 你不用翻原始对话就能知道"关于 X,我到底了解多少"。一份连贯的文档,不是散落的碎片。 这不是自动摘要。需要多个独立来源汇聚,合成过程有质量评估,不达标就不会创建。 ## 结晶如何形成 [#结晶如何形成] 形成过程分三步: 1. EVOLVES 检测发现新记忆和已有记忆相关,创建关系边(替代、丰富、印证或质疑)。 2. 集群评估在新边创建后触发。看有没有集群达到汇聚条件:三条以上同一话题的源记忆,且信息足够多样,值得合成。 3. 条件满足就进入合成。系统读所有源记忆,识别各自贡献,产出统一的结晶。结晶通过 CRYSTALLIZED\_FROM 边链接回每个来源,出处始终可追溯。 这个管线是[后台智能](/zh/docs/concepts/background-intelligence)的一部分。每周还有一次专门的结晶审查,扫描事件驱动检测可能漏掉的集群。 ## 为什么是三个来源 [#为什么是三个来源] 两个来源是巧合,三个才算规律。这道门控防止弱关联被当成参考知识。 来源不需要在同一个平台。ChatGPT 对话、Cursor 会话、手动存的笔记共同形成的结晶,比同一个对话里三条消息形成的更有说服力。跨平台汇聚本身就是知识重要性的更强证据。 ## 审核结晶 [#审核结晶] 每条结晶初始状态是未审核。你可以确认、忽略或编辑它。 **确认**表示你读过合成内容,认为它准确反映了你的理解。确认后的结晶在搜索中获得排序加分,更容易被找到。未审核的结晶有一条琥珀色的横幅,带有确认和忽略按钮;确认后会变成绿色对勾。 **忽略**表示合成结果不够准确。被忽略的结晶在搜索中会受到较大降权,在资料库中视觉上也会变淡。它们不会被删除,你随时可以改变决定。 **编辑**结晶的标题或内容会自动确认它。如果大方向对但措辞需要调整,直接改就好。 未审核的结晶不享受排序加分,需要先获得你的信任。 ## 发言归属 [#发言归属] 当结晶的素材来自你和 AI 助手的对话时,合成内容会区分谁说了什么。你自己的表述("我决定用 Postgres")会被记录为决策,AI 的建议("根据你的延迟需求,可以考虑 Redis")会连同推理一起记录为建议。 这样可以避免一个常见问题:AI 推荐的选项被呈现为你做出的选择。在对话中探索一个想法和真正承诺它是两码事。 ## 结晶如何影响搜索 [#结晶如何影响搜索] 确认后的结晶在搜索结果中有排序加分。道理很简单:经过用户验证和合成的知识,比单条原始记忆更可能是你想找的。 加分有意义但不会碾压一切。一个和查询只是松散相关的结晶,排不到语义完美匹配的原始记忆前面。语义相关性始终是主导信号。未审核的结晶没有加分;被忽略的结晶会被降权。 结晶还会影响其源记忆的[置信分数](/zh/docs/concepts/memory-decay)。如果一条记忆被用作一个或多个结晶的来源,这会被算作该记忆价值的证据。 ## 你看到的是什么 [#你看到的是什么] 结晶在你的动态时间线中出现,附带来源数量和来源平台。你可以直接在动态中确认、忽略或编辑结晶,无需打开单独的页面。将鼠标悬停在结晶卡片上,点击铅笔图标即可原地编辑标题和内容,按 Cmd+Enter 保存。你也可以打开结晶阅读完整合成内容,深入到各个来源查看原始上下文。 在图视图中,结晶作为独特的节点呈现,边指向它们的来源。双击结晶可以展开这些边,查看完整的来源追溯。 ## 更新而不是自动修改 [#更新而不是自动修改] 知识会变。形成结晶的来源可能被更新、被质疑、被新认知替代。发生这种情况时,系统将结晶标记为过期,提议重新评估,不会悄悄改写。 已确认的结晶会优先被重新评估,已忽略的不会被打扰。系统提议,你来定。 ## 延伸阅读 [#延伸阅读] * [知识演化](/zh/docs/concepts/evolves)解释为结晶形成提供素材的 EVOLVES 边 * [后台智能](/zh/docs/concepts/background-intelligence)讲解结晶审查何时运行、如何调度 * [搜索架构](/zh/docs/concepts/search-architecture)解释结晶如何影响排序 # 知识演化 (/docs/zh/concepts/evolves) 认知是会变的。三月做了一个决定,六月调整了一下,十月推翻了。大多数系统要么直接覆盖旧版本,要么把所有东西堆在一个平铺列表里。当你需要理解自己的思路是怎么演变的,这两种方式都不好用。 Nowledge Mem 用一个叫 EVOLVES 的模型,把相关的记忆用明确的关系链接起来。历史不会丢,重复也不会淹没你。你看到的是知识怎么一步步变成现在这样的。 ## 四种关系类型 [#四种关系类型] 当系统检测到一条新记忆与已有记忆相关时,会创建以下四种链接之一: | 关系 | 含义 | 典型场景 | | ------------------ | ------------------- | -------------------------------------- | | **替代(Replaces)** | 你的认知发生了变化,新记忆取代旧记忆。 | "用 CockroachDB"替代"用 PostgreSQL" | | **丰富(Enriches)** | 你给已有知识增加了深度或细节。 | "React 19 增加了编译器"丰富了"React 18 引入了并发渲染" | | **印证(Confirms)** | 另一个独立来源认同了已有记忆。 | 两次独立的代码审查都推荐了同一个库 | | **质疑(Challenges)** | 新信息与之前记录的内容相矛盾。 | 三月的评估与十月的结论不一致 | 这四种类型覆盖了知识真正变化的方式:被更新、被扩展、被验证、被质疑。 ## 实际效果 [#实际效果] 搜索一个话题时,EVOLVES 链会和单条结果一起呈现。你看到的不只是最新版本,而是你怎么走到这一步的完整路径。 对决策类知识尤其有用。搜索"数据库选型"不会只返回最近的决定,而是整条链:最初的选择、补充了理由的丰富、提出顾虑的质疑、最终定论的替代。 ### 不需要版本控制的版本追踪 [#不需要版本控制的版本追踪] EVOLVES 链接区分了两类关系: * 演进(替代、丰富)构成版本链。旧版本被标记为已过时,搜索优先展示最新认知。 * 验证(印证、质疑)是证据,不是版本。印证或质疑一条记忆不会替代它,两边都保持活跃。 标签会沿着演进链自动传播。如果你给一条记忆打了"架构"标签,后来一条新记忆替代了它,新记忆会继承这个标签。 ## 检测机制 [#检测机制] 开启后台智能后,系统会将新记忆与你的已有知识进行比对。如果语义相似度足够高,就会评估关系类型并创建对应的链接。 这个过程在后台自动运行,通常在保存新记忆后一分钟内完成。你也可以在任何记忆的详情页直接查看和管理 EVOLVES 链接。 ## 矛盾的处理 [#矛盾的处理] 矛盾(质疑关系)会被呈现出来,而不是自动解决。系统把两条记忆并排展示,让你来决定:保留新的、两个都保留、或者忽略这个质疑。 这是有意为之。让系统替你判断哪个版本是"对的",不是我们想做的事。 ## 延伸阅读 [#延伸阅读] * [后台智能](/zh/docs/concepts/background-intelligence)解释 EVOLVES 检测什么时候运行,以及其他后台任务如何使用它 * [知识结晶](/zh/docs/concepts/crystals)解释当多条 EVOLVES 链汇聚时会发生什么 * [搜索架构](/zh/docs/concepts/search-architecture)讲解 EVOLVES 链如何影响搜索排序 # 运作原理 (/docs/zh/concepts) 这个章节解释 Nowledge Mem 在后台做了什么。写给那些不只想知道怎么用,还想知道为什么这么设计的用户。 你不需要读完这些页面才能用好 Mem。这里讲的一切都是自动运行的。但如果你好奇过为什么某些记忆在搜索中排得更靠前、系统怎么发现矛盾、或者你睡觉的时候它在干什么,答案都在这里。 Nowledge Mem Tree 里的 Context 分支 ## 这个章节讲什么 [#这个章节讲什么] * [LLM Wiki](/zh/docs/concepts/llm-wiki):为什么资料库现在可以像一本 wiki 一样去读,Mem 在背后帮你做的整理工作有哪些,又有哪些事情仍然由你来决定。想理解 v0.8 背后的模型,从这里开始。 * [Open Knowledge Format(OKF)](/zh/docs/concepts/open-knowledge-format):怎么把你的整张图谱导出成一份开放、不绑厂商、任何工具或 agent 都能读的 markdown 知识包。 * [知识演化](/zh/docs/concepts/evolves):你修正了一个决定,或者学到了和之前矛盾的东西。系统怎么追踪这种变化,同时保留完整历史。 * [记忆连接](/zh/docs/concepts/memory-links):当两条记忆应该一起读,但它们既不是版本历史、也不是实体关系时,怎么在同一个空间里把它们明确连起来。 * [AI 档案](/zh/docs/concepts/ai-profiles):Mem 如何区分长期 Agent 的身份,和运行它的具体工具。 * [规则](/zh/docs/concepts/rules):常驻行为规则是什么,它和 Skills、记忆有什么区别,又如何进入接入工具。 * [搜索架构](/zh/docs/concepts/search-architecture):搜索不只看关键词。语义相似度、实体关联、社区聚类、标签、图遍历,六种策略并行,然后混合排序。 * [记忆衰减](/zh/docs/concepts/memory-decay):为什么有些记忆排得更靠前。最近用的、经常用的知识优先级更高,但重要的知识不会消失。 * [记忆的生命周期](/zh/docs/concepts/memory-lifecycle):一条记忆的三种状态(活跃、已归档、已移除),以及为什么记忆页面上的数字会和图谱或存储占用对不上,但其实什么都没丢。 * [后台智能](/zh/docs/concepts/background-intelligence):你睡觉的时候系统在干什么。跑了哪些任务、什么时候跑、怎么防止它浪费资源。 * [Skills](/zh/docs/concepts/skills):系统怎么把一套反复出现的做事方法变成 AI 能照着做的流程,以及一条 Skill 在被当成已被证明之前,如何先挣到信任。 * [知识结晶](/zh/docs/concepts/crystals):多个独立来源说了同一件事,系统把它们合成一份参考文档。 ## 从哪里开始 [#从哪里开始] 如果你想搞清楚某个搜索结果为什么出现(或没出现),先看[搜索架构](/zh/docs/concepts/search-architecture)和[记忆衰减](/zh/docs/concepts/memory-decay)。 如果你想理解后台功能(简报、矛盾检测、实体提取),从[后台智能](/zh/docs/concepts/background-intelligence)开始。 如果你在配置多个 Agent,先看 [AI 档案](/zh/docs/concepts/ai-profiles)、[规则](/zh/docs/concepts/rules) 和[上下文](/zh/docs/ai-context)。 # LLM Wiki (/docs/zh/concepts/llm-wiki) 资料库现在可以像一本 wiki 一样去读了。这本 wiki 里的内容不是新的,是 Mem 在你日常使用 AI 的时候顺带攒下来的那一切;新的,是你终于可以一页一页地看、顺着连接点开下去,并且就一个具体概念问出你心里那个问题。 Andrej Karpathy [给出了背后的方法论](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f):许多小篇幅的 markdown 页面,每页只聚焦一个实体或一个话题,互相之间用 `[[wikilink]]` 连起来,再配一个 `index.md` 当目录。LLM 帮你做整理,你来策划。Mem 把这套思路落在了你已有的知识图谱上面。 ## 先做这一步 [#先做这一步] 1. 打开资料库,切到 **Wiki** 标签。 2. 选一个已经有些记忆的主题,读读它的摘要,点进它列出来的某一个实体,再从那个实体点进一个相邻的实体。 3. 在任意一张实体、结晶或主题页面上点 **深入研究**,知识图谱会自动打开,把对应的节点(或者整个聚类)预先选好。 如果你能不打字就翻完三四页,就说明这本 wiki 已经是你自己可以读的了。
## Mem 替你做的事 [#mem-替你做的事] 让大多数个人 wiki 死掉的,是那份整理负担。Mem 把这部分当成系统的职责: * **主题聚类。** Background Intelligence 在后台把你的知识按主题聚成簇,并且给每个簇起好名字。Wiki 标签里看到的就是这些主题。第一次在新装的 Mem 里打开 Wiki 标签时,先去知识图谱视图里跑一次「Wiki 主题检测」把它填上;之后会自动每 6 天刷新一次,节奏可以在 *设置 · 处理 · 高级* 里调。 * **实体页是从图谱里实时投影出来的。** 每个实体的 wiki 词条包含:它属于哪个主题、第一次什么时候被识别出来、Mem 给的置信度有多高、有哪些别名、哪些记忆里提过它、它身边还有哪些相邻实体。这些信息没有第二份副本要你维护。 * **结晶作为可读的参考文章。** 当三条以上的记忆在同一个想法上汇合时,Mem 会合成一篇[结晶](/zh/docs/concepts/crystals):一篇稳定的参考页面,里面已经织好了 `[[实体]]` wikilink。每篇结晶都列了它来自哪些源记忆。 * **演化与矛盾。** [EVOLVES](/zh/docs/concepts/evolves) 记录新知识何时替换或细化了旧知识。结晶页里能看到它是从哪些更早的记忆里长出来、又演化成了什么新版本。 * **「最近更新」和「最新动静」。** 每张主题页都有一栏「这个主题上的最新动静」,让 wiki 反映你最近在想的事情,而不只是历史的沉淀。 ## 仍然由你来决定的部分 [#仍然由你来决定的部分] 这本 wiki 的设计很清楚:整理交给 Mem,思考留给你。 * **挑选什么进来。** 把文档、对话、笔记交给 Mem 之前,要不要进来这件事是你决定的。wiki 只会从你愿意喂给它的东西里长出来。 * **问什么问题。** Knowledge Graph Agent 和资料库里的「和 AI 一起精读」都等你先指。它们不会自己跑题。 * **决定留下什么。**「和 AI 一起精读」会建议要保存哪几条记忆或结晶,最后由你点 **保存 1**、**全部保存** 或 **跳过**。任何东西都不会自动保存。 ## Wiki 是叠在写入路径上的阅读路径 [#wiki-是叠在写入路径上的阅读路径] Mem 一直就有一条写入路径:导入、解析、分类、抽取实体、检测 EVOLVES 关系、合成结晶、社群聚类,这些都在你正常使用产品时在后台运行。Wiki 标签是叠在它上面的一条 *阅读路径*,不是另开了一份数据。 这意味着几条边界,是我们有意保持的: * **页面是派生出来的,不是另存的。** 编辑发生在数据层(记忆、资料、结晶),页面再从那里刷新。没有第二份副本要担心同步。 * **导出是切片,不是双向同步。**[Wiki 导出](/zh/docs/library#wiki-export) 给你一份一次性的 markdown 文件夹。可以选 Obsidian 风格、带 `[[wikilink]]` 的 markdown wiki,也可以选 OKF 知识包:同样的内容,按 Google 那份开放、不绑厂商的 [Open Knowledge Format](/zh/docs/concepts/open-knowledge-format) 来组织,它正是把这套 LLM Wiki 做法写成了规范,让别的工具也读得懂。要刷新再导出一次。在导出文件里改的内容不会自动流回 Mem。 * **深入研究让你和 Agent 同处一张画布。** 点击「深入研究」之后,你停留在知识图谱的 overview,对应的聚类已经被选中;Graph Intelligence Agent 看到的也是这一份选区。它生成的结晶会回到资料库里那张主题页底下。 ## 接下来读哪里 [#接下来读哪里] * [资料库](/zh/docs/library):日常用来读 wiki、跑「和 AI 一起精读」的地方。 * [知识结晶](/zh/docs/concepts/crystals):稳定参考页面是怎么合成出来的。 * [Background Intelligence](/zh/docs/concepts/background-intelligence):后台在做的、让你不用手动维护 wiki 的那些事。 * [EVOLVES](/zh/docs/concepts/evolves):Mem 怎么记录你理解的演变。 # 记忆衰减 (/docs/zh/concepts/memory-decay) 你记得昨天的会议比上个月的更清楚。你每天都用的事实比只看过一次的更容易回想起来。人类记忆之所以这样运作,是因为不得不如此。无限回忆但没有优先级,和忘掉一切一样没用。 Nowledge Mem 应用了类似的思路。每条记忆都有两个独立的分数,影响它在搜索结果中的位置。一个随时间衰减,另一个只增不减。 ## 两个分数,两个职责 [#两个分数两个职责] 衰减分数反映新鲜度。今天存的记忆比半年前存的分数更高(其他条件相同)。分数按指数曲线随时间下降,但你经常访问的记忆因为频率加成会保持较高分数。 置信分数反映支撑程度。从一个基线开始,随证据积累而增长,永远不会下降。被多次访问、通过 EVOLVES 链关联、或者被用作知识结晶来源的记忆,置信度比孤立的、没碰过的记忆高。 两个分数互相独立。一条记忆可以很旧(低衰减)但有充分支撑(高置信),或者很新(高衰减)但未经验证(低置信)。两个信号都会和语义相关性一起,参与最终的搜索排序。 ## 各个信号的来源 [#各个信号的来源] ### 衰减分数 [#衰减分数] 两个分量混合而成: * 时近性:从上次交互到现在的指数衰减。越近分数越高。半衰期按周算,不是按小时,所以记忆不会一夜消失。 * 频率:访问次数的对数函数。经常用的记忆保持新鲜,哪怕最近几天没碰。 时近性的权重高于频率。一条去年大量使用但此后没碰过的记忆仍然会衰减,只是比从未访问过的慢一些。 ### 置信分数 [#置信分数] 六种信号,每种都有上限以防单一信号主导: 1. 访问频率:被检索了多少次 2. 搜索出现次数:在搜索结果里露面的频率 3. 主动点击:你打开它读了多少回 4. 阅读时长:每次打开停留了多久 5. EVOLVES 边:有多少其他记忆印证或丰富了它 6. 结晶归属:有没有被用作知识结晶的来源 这些信号都是自动追踪的。你不需要手动评分或标记,系统就能学会哪些记忆重要。 ## 重要性地板 [#重要性地板] 衰减有个问题:一条真正重要的事实,几个月没访问,分数就会很低。它依然正确、有价值,但排不上来了。间隔重复系统靠安排复习解决这个,不过 Mem 不是闪卡应用。 所以每条记忆有一个重要性地板。衰减分数可以降,但不会低于一个和重要性等级挂钩的最低值。基础性的决定、关键操作流程,哪怕你很久没看,也始终能搜到。 地板是温和的。不会压过语义相关性,只是防止"幽灵记忆":知识明明在系统里,但搜不到。 ## 衰减如何影响搜索排序 [#衰减如何影响搜索排序] 语义相关性是搜索结果中的主导因素。衰减和置信是次要信号,在语义分数接近时调整排序。 实际效果: * 两条与查询同样相关的记忆 → 更新的那条排得更高 * 语义匹配度强的结果总是胜过最近但弱相关的 * 支撑充分的记忆(高置信)获得小幅额外提升 * 知识结晶和 EVOLVES 链中的最新版本在此基础上还有各自的排序调整 ## 自动刷新 [#自动刷新] 系统每天作为后台任务重新计算衰减和置信分数。刷新同时更新搜索中使用的缓存分数,所以结果能反映当前的使用模式,无需手动干预。 刷新本身不会归档、删除、合并或改写记忆。它只负责让排序信号保持准确。 记忆增长由 **Memory Maintenance** 单独处理。当 Mem 发现旧记忆或重叠记忆可能带来噪音时,会在 Timeline 里准备审查。你可以选择把低风险事实和事件移出日常召回、把更复杂的记忆交给语义整理,或者什么都不改。 Nowledge Mem 里的 Memory Health 审查 *Memory Health 审查会在你决定整理前,先展示当前批次、近期覆盖率和剩余积压。* 这个区分很重要: * 事实和事件在足够旧、没人访问、且没有保护标记时,才可能成为低风险清理候选。 * 偏好、决定、计划、流程、经验、规则、身份和上下文记忆,不会因为“不新鲜”就被机械归档。 * 移出日常召回是可恢复的。遗忘或删除永远需要明确操作。 ## 延伸阅读 [#延伸阅读] * [搜索架构](/zh/docs/concepts/search-architecture)解释衰减和置信如何参与完整的排序管线 * [知识演化](/zh/docs/concepts/evolves)讲解 EVOLVES 链,它是置信分数的信号之一 * [知识结晶](/zh/docs/concepts/crystals)解释结晶归属,另一个置信信号 # 记忆的生命周期 (/docs/zh/concepts/memory-lifecycle) 先说最要紧的一句:你存进来的东西,不会被悄悄扔掉。 一条记忆可能正在日常使用,可能安静地待在后台,也可能真的没了。而只有最后这一种,是因为你主动要求才发生的。除此之外,东西都还在,还是你的,也还能搜到。 ## 三种状态 [#三种状态] **活跃**,就是日常召回看得到的那一部分。你搜索的时候、AI 帮你回答的时候、记忆页面列出你都知道些什么的时候,用的都是活跃记忆。这是你此刻真正在用的那一份知识。 **已归档**,是留着、但先挪到一边。当一条记忆被更新的版本替换掉,或者你因为它已经过时而把它退役、暂停了,它就进入归档。它哪儿也没去,你依然能在历史视图和历史搜索里找到它。它只是不再和别人抢日常召回的位置,好让最新的理解先冒出来。 **已移除**,是唯一意味着「没了」的状态。只有你主动删除或遗忘,一条记忆才会走到这一步。它会同时从所有地方消失。系统自己不会把任何记忆挪到这里。 可以这样记: > **已存储** = 活跃 + 已归档,这就是你手上还留着的全部。 ## 为什么数字会对不上 [#为什么数字会对不上] 你有时会发现,记忆页面上的数字,跟图谱或存储占用暗示的数量对不上。这是正常的,也不代表有东西丢了。每个视图,都是从不同角度去看同一份知识。 * **记忆页面**和**统计栏**给你看的是**活跃**记忆,也就是你每天召回的那一份。 * **图谱**和**存储占用**算的是**已存储**的全部,活跃加上归档的历史。那些被替换掉的旧版本仍然占空间、仍然在图谱里,所以这个数字会更大。 * **知识结晶**(多个来源说法一致时,Mem 帮你合成的那份摘要)是单独计数的,不算进记忆数里。 同一份知识,三个角度看。活跃数字变小,不是丢了东西。多半只是一些旧版本挪进了归档历史,而这恰恰是让日常召回始终盯着「当前有效」那一份的原因。 ## 什么会让状态发生变化 [#什么会让状态发生变化] 大多数变化都有明确的缘由: * 当你修正或替换一条知识时,早先的版本会变成归档历史,而不是被覆盖掉。这种版本链是怎么运作的,见[知识演化](/zh/docs/concepts/evolves)。 * 当一条记忆变旧,Mem 可能会准备一次审查,让你把低风险的事实移出日常召回。新鲜度和衰减只影响**排序**,从不删除。见[记忆衰减](/zh/docs/concepts/memory-decay)。 * 退役、遗忘、删除,永远是你亲手做的操作。移出日常召回是可以恢复的,只有删除不能。 ## 延伸阅读 [#延伸阅读] * [记忆衰减](/zh/docs/concepts/memory-decay):新鲜度如何影响搜索排序,但从不删掉任何东西。 * [知识演化](/zh/docs/concepts/evolves):被替换的旧版本如何变成归档历史,而且仍然能追溯。 # 记忆连接 (/docs/zh/concepts/memory-links) 记忆连接解决的是一个很具体的动作:告诉 Mem,这两条记忆以后应该一起看。 当一条记忆会改变你理解另一条记忆的方式,就适合连起来。一个发布计划可能依赖之前的定价假设;一条迁移笔记可能是某个实现方案背后的风险;一个真实例子,可能正好让某条规则变得可用。 这和搜索相似度不一样。搜索可以猜两条记忆看起来相关。记忆连接是你,或者带着明确意图工作的 Agent,决定要留下来的关系。 ## 先试一次 [#先试一次] 1. 从侧边栏打开 **Graph**。 2. 选中一条 Memory 节点。 3. 选择 **Connect memories**。 4. 在同一个空间里选择另一条 Memory。 5. 输入一个简短的关系名,或使用建议。 6. 如果关系不是一眼能看懂,补一句原因,然后保存。 两条记忆必须在同一个空间里。这样可以避免把不同工作、项目、客户或 Agent 团队的上下文意外连在一起。 ## 怎么知道成功了 [#怎么知道成功了] 你应该能在两条 Memory 节点之间看到一条线。点这条线,可以看到关系名和原因。 之后,当 Agent 或图谱工具读到其中一条记忆时,这条连接会比「两段文字有点像」更有用。它能把另一条记忆带到旁边,并知道为什么要带上。 ## 关系名怎么写 [#关系名怎么写] 不用先设计一整套分类。先用你工作里自然会说的话: | 关系 | 什么时候用 | | ------------- | ------------------- | | `supports` | 一条记忆是另一条的证据 | | `contradicts` | 一条记忆和另一条冲突,但不是新版本 | | `depends_on` | 理解一条记忆需要另一条 | | `example_of` | 一条记忆是某个规则或模式的例子 | | `blocks` | 一条记忆挡住了某个计划或行动 | | `same_topic` | 两条记忆在讲同一个主题,放在一起更有用 | 你也可以写自己的关系名,比如 `migration_risk_for`、`pricing_assumption_for`、`source_of_truth_for`。Mem 会标准化关系名,所以 `same topic`、`same-topic` 和 `same_topic` 会被当成同一种关系。 ## 它和其他关系有什么区别 [#它和其他关系有什么区别] | 用这个 | 当你想表达 | | ----------- | ----------------------------- | | **记忆连接** | 两条具体记忆应该因为这个原因一起读 | | **EVOLVES** | 这条记忆更新、替代、丰富、确认或挑战了旧版本 | | **标签** | 很多条记忆属于同一个大类 | | **实体图谱** | 一条记忆提到了人、项目、工具、概念,或自动抽取出的实体关系 | | **搜索** | 找到看起来相关的记忆,即使还没有保存关系 | 如果这其实是旧知识的新版本,用 EVOLVES。只是想做大类归档,用标签。 ## 现在先不用管什么 [#现在先不用管什么] 不用一开始就设计完整的关系体系。先写下今天有用的那种关系。 不用一定让 AI 建议。AI 可以帮你起草关系名和原因,但它只会填表,保存前还是你决定。 如果你不是在做集成,也不用先理解 API 或 MCP 工具。Graph 视图就是正常入口。 ## 给 Agent 和集成开发者 [#给-agent-和集成开发者] 受支持的集成可以通过 REST API 和 MCP 工具读写记忆连接: * `memory_relation_add` * `memory_relation_suggest` * `memory_relation_list` * `memory_relation_update` * `memory_relation_delete` 图谱里保存的是一条稳定的 Memory-to-Memory 边,关系名保持开放。这样 schema 不会膨胀,你自己的关系词也能慢慢长出来。 ## 接下来读哪里 [#接下来读哪里] * [知识图谱](/zh/docs/knowledge-graph):如果你想在图里创建或检查记忆连接。 * [知识演化](/zh/docs/concepts/evolves):如果你想理解版本历史和矛盾关系。 # Open Knowledge Format(OKF) (/docs/zh/concepts/open-knowledge-format) Nowledge Mem 可以把你的整张知识图谱导出成 **Open Knowledge Format(OKF)** 知识包:用带 YAML 前言的纯 markdown 文件来表示知识,开放、不绑任何厂商。你的知识和你之间没有专有格式挡着,任何认 OKF 的工具都能读你的导出。 OKF 由 Google Cloud 的 Knowledge Catalog 团队发布。它把 Mem 一直在用的 [LLM Wiki](/zh/docs/concepts/llm-wiki) 做法写成了规范,所以我们让 Mem 说这门语言,是很自然的事。 ## 导出一个 OKF 知识包 [#导出一个-okf-知识包] 1. 打开 **Library**,切到 **Wiki** 标签。 2. 点标签栏上的 **Download**。 3. 选 **OKF 知识包**。 你会拿到一个 `.zip`,里面有 `index.md`、`log.md`,以及按目录铺开的知识:按类型分好的记忆(`memories/decision/`、`memories/procedure/` 等等),还有 `crystals/`、`entities/`、`topics/`、`artifacts/`、`skills/`,以及一份 `labels/` 清单。每页都带 YAML 前言,概念之间用标准 markdown 路径互相指,整个知识包能过 OKF 的参考工具校验。 Nowledge Mem 里的 Open Knowledge Format 导出 *OKF 导出就是 Library Wiki 的可移植版本:markdown 文件、前言信息和标准链接都在里面。* 完整的导出流程和另一种格式,见 [Library:Wiki 导出](/zh/docs/library#wiki-export)。 ## 它有什么用 [#它有什么用] * **可移植。** 知识包就是一堆 markdown 文件。随便哪个编辑器都能打开,丢到 GitHub 上直接渲染,也能跟代码一起进版本库。 * **不绑厂商。** 任何认 OKF 的阅读器都能打开它,包括 Google 自己放出来的那套参考工具。你不会被锁死在某一个应用的格式里。 * **人和 agent 都能读。** 同一份文件,人能扫一眼看懂,AI agent 也能直接解析,中间不用再转一道手。 ## OKF 知识包和 Markdown wiki 的区别 [#okf-知识包和-markdown-wiki-的区别] Library 的导出给两种格式,两种都覆盖你的整张图谱。OKF 知识包用标准 markdown 链接和规范规定的前言,所以它是可互通的那一档。**Markdown wiki** 保留你在 Mem 里看到的 `[[wikilink]]`,丢进 Obsidian、Logseq 就能直接用。想留一份可互通的副本,选 OKF;想要一个 Obsidian 风格的库,选 markdown wiki。 两种都是某一刻的快照,不是双向同步:在 Mem 之外做的修改不会自动流回来。想要新的,再导一次就行。 ## 接下来读哪里 [#接下来读哪里] * [Library](/zh/docs/library):你平时导出的地方。 * [LLM Wiki](/zh/docs/concepts/llm-wiki):OKF 规范化的那套阅读模型。 * [备份、导出与导入](/zh/docs/data-portability):另一条用于完整数据备份和迁移的路径。 * [读 OKF 规范](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md):Google Cloud 给出的权威规范。 * [Nowledge Mem 是怎么开始说 OKF 的](https://nowledge-labs.ai/zh/blog/open-knowledge-format):发布博客。 # 规则 (/docs/zh/concepts/rules) 规则,是给接入的 Agent 的常驻行为指令。 当某件事应该在搜索、工具调用、具体 Skill 之前就影响 Agent 行为时,就适合放进规则。你可以把它理解成重度用户已经在手动维护的 `AGENTS.md`、`CLAUDE.md`、Cursor rules、Codex profile 或 Hermes soul 的集中管理版本。 ## 什么适合成为规则 [#什么适合成为规则] 好的规则,会在很多任务里持续改变 Agent 的行为: * “除非我要求展开,否则回答简洁。” * “不要手动编辑自动生成的 API 文档。” * “做发版相关工作时,说可以合并前先确认测试。” * “写中文文档时,写自然中文,不要逐句翻译英文。” 规则不是万能入口。如果它是一套可重复执行的任务方法,应该做成 [Skill](/zh/docs/concepts/skills)。如果它是你学到的一件事,应该保存成记忆。如果它只影响今天,放在 Working Memory 更合适。 ## 第一个有用动作 [#第一个有用动作] 打开 **上下文 → 规则**,加一条你经常反复提醒 Agent 的规则。 选择尽量窄、但仍然有用的范围: | 范围 | 什么时候用 | | ------------ | --------------- | | **Everyone** | 每个接入的 AI 都应该遵守 | | **某个 AI 档案** | 只对某个命名 Agent 生效 | | **某个空间** | 只在某个项目或团队通道里生效 | 然后打开 **上下文 → 预览**。匹配的 Agent 启动上下文里,应该能看到这条规则。 ## 规则、Skills 和记忆的区别 [#规则skills-和记忆的区别] 这三者有时看起来相近,但职责不同: | 类型 | 含义 | | --------- | ---------------- | | **规则** | “以后总是这样做。” | | **Skill** | “做这类任务时,按这个方法做。” | | **记忆** | “这是一件值得记住的事。” | 例如: * 规则:“不要手动编辑自动生成的 OpenAPI 文档。” * Skill:“如何新增 API endpoint,同时不破坏生成文档。” * 记忆:“OpenAPI 文档来自 Python docstring 自动生成。” 这个边界很重要,因为规则会很早、很频繁地进入上下文。一条模糊或错误的规则,会影响很多会话。规则应该短、具体、容易检查。 ## 推荐规则 [#推荐规则] 当 Mem 从你的工作里看到反复出现的行为,它可以建议候选规则。建议不会自动生效。你可以接受、编辑,或者忽略。 这样保留了自动化里有价值的部分:发现重复偏好和项目习惯;但不会让系统悄悄改写 Agent 的行为。 ## 接入工具如何使用规则 [#接入工具如何使用规则] 支持的连接器会在会话开始时,通过 Context Bundle 读取规则。这个 bundle 会把你的档案、选中的 AI 档案、当前空间、规则、Working Memory 和有用的文件路径组合在一起。 一些较旧或更简单的集成,可能只读取 Working Memory。那种情况下,规则仍然会影响 Mem 内部和较新的连接器,但旧工具可能要等集成升级后才能看到。 ## 暂时不用担心什么 [#暂时不用担心什么] 不需要把每个偏好都变成规则。如果你不希望它在大多数未来会话里重复出现,就不要把它设成常驻。 不需要写很长的 policy 文档。短规则更容易被 Agent 遵守,也更容易让你信任。 使用规则不需要先理解 MCP 或 KFS 路径。从上下文页面开始就够了。 ## 接下来读哪里 [#接下来读哪里] * [AI 档案](/zh/docs/concepts/ai-profiles):如果不同 Agent 需要不同规则。 * [Skills](/zh/docs/concepts/skills):如果这其实是一套任务方法。 * [上下文](/zh/docs/ai-context):预览最终启动上下文。 # 搜索架构 (/docs/zh/concepts/search-architecture) 搜索个人知识和搜索网页是两回事。你在找的是自己存下来的东西,用的是当时自己的措辞,可能已经过了好几个月。最大的挑战不是速度,而是你现在的提问方式和当初的记录方式之间的差距。 Nowledge Mem 通过同时从多个角度搜索来解决这个问题,然后混合排序。 ## 六种搜索策略 [#六种搜索策略] 每次搜索查询最多并行跑六种策略: 语义搜索用向量嵌入比较查询和每条记忆的含义。"API 认证"能匹配到"JWT token 配置",即使用词完全不同。大多数查询靠这个。 全文检索做关键词匹配,支持中日韩分词。你记得确切的术语、函数名或代码标识符时,这个最管用。 实体搜索通过知识图谱找关联。搜"数据库性能"可以找到关于"PostgreSQL 索引"的记忆,因为两者共享实体关联,即使原文从没提过"数据库性能"。 社区搜索利用图谱中的社区聚类(强连接节点的集群)。有些记忆靠关键词或语义匹配找不到,但在同一个社区里就能找到。 标签搜索让你自己打的标签参与排序。查询命中某个标签时,带这个标签的记忆相关性会提高。 图遍历沿关系边(EVOLVES 链、实体关联、结晶来源)查找,靠的是图结构连接而非文本相似度。 ## 快速模式和深度模式 [#快速模式和深度模式] 不是每次搜索都需要全部六种策略全力运行。 快速模式(大多数查询 100ms 以内)并行跑语义搜索、全文检索和实体匹配。大约 90% 的查询用这个就够了,也是默认行为。 深度模式在快速结果基础上加一层 LLM 分析。先分类查询意图(查事实?探索概念?追踪关系?),再调整策略权重。需要的话还会用 HyDE(假设文档嵌入)来弥合表达差距,或者让 LLM 重新评估头部结果来改善排序。 查询带时间意图("我上个季度决定了什么?")或者快速模式结果置信度不高时,深度模式自动触发。也可以手动开。 ## 结果排序 [#结果排序] 最终排序混合了上述策略的信号与记忆级别的评分: * 语义相关性是主导因素。语义上接近查询的记忆排得高,其他信号影响有限。 * 衰减分数给最近和频繁访问的记忆适度加分。详见[记忆衰减](/zh/docs/concepts/memory-decay)。 * 置信分数给证据充分的记忆(多次访问、EVOLVES 链接、结晶引用)小幅额外加分。 知识结晶因为是经过验证的合成知识,有排序加分。EVOLVES 链中的最新版本也比被取代的旧版排得更高。 每条结果都附带 `source_thread_id`(如果有的话)。如果智能体或工具需要记忆本身之外的更多上下文,可以拉取原始对话。 ## 时间搜索 [#时间搜索] 带有时间引用的查询("2020 年发生了什么?"、"上个季度的决定")会激活时间匹配。系统为每条记忆追踪两个独立的时间戳: * **事件时间**:事情发生的时间 * **记录时间**:你保存它的时间 时间匹配会增加相关性提升,但不会覆盖语义相关性。来自正确时间段的记忆仍然需要语义上相关才能排名靠前。时间是信号,不是过滤器。 日期精度会被明确追踪。如果一条记忆的事件时间只精确到年,系统不会假装知道具体月份。 ## 延伸阅读 [#延伸阅读] * [记忆衰减](/zh/docs/concepts/memory-decay)解释影响排序的衰减分数和置信分数 * [知识演化](/zh/docs/concepts/evolves)讲解 EVOLVES 链如何影响搜索结果中的呈现 * [搜索与相关性](/zh/docs/search-relevance)是包含实用搜索技巧的参考页面 # Skills (/docs/zh/concepts/skills) 你摸索出了发版的正确顺序:先提交子仓库,再动父仓库的指针。你踩过一次坑,记住了教训,从那以后就自然这么做。它只在你脑子里,不在任何文档里。 一条 Skill,就是 Mem 把这套做事的方法记下来,再交给你的 AI,让它之后也能照着做。 ## 什么是 Skill [#什么是-skill] 一条 Skill,是一种可复用的做事方法,写下来之后,Agent 就能照着你的方式去做。真正有用的那些通常都很小、很具体:一个操作顺序、一处安全检查、一个发版的坑、一个 review 习惯、一个排查动作。 它不是存起来的 prompt,也不是一条常驻规则。常驻规则(比如「回答简短点」)属于 [Context](/zh/docs/ai-context) 里的 Rule。Skill 管的是一件事「怎么做」,是那个换个能干的人、但没有你的经验就会做错的步骤。 Skill 也不是自动生成的 checklist。好模型本来就能写出一份看着像样的流程。Skill 的意义,在于带上那些只能从你真实工作里长出来、做过才知道的东西。每一条 Skill 都能追溯到当初让它成立的那段工作,并且在你亲手打开之前,一直关着。 Nowledge Mem 里的 Skills ## 一条 Skill 怎么诞生 [#一条-skill-怎么诞生] 一条 Skill 有三种诞生方式,三者最终都汇入同一条生命周期。 1. **被推荐。** 作为[后台智能](/zh/docs/concepts/background-intelligence)的一部分,Mem 会从你的记忆和线程里寻找反复出现的做事方法。当同一套流程在不同场合多次出现,它就会推荐一条 Skill,并把那些来源时刻作为证据附上。这也是为什么一条被标为 `procedure` 的记忆很要紧:推荐流程最先读的就是带类型的 procedure。记忆如何获得类型,见[知识演化](/zh/docs/concepts/evolves)。 2. **从零创建。** 你也可以直接描述你想要什么来创建一条 Skill。Mem 问你一个问题,起草出流程,再拿回来给你审。你可以把自己的线程、来源或笔记作为素材带进来。 3. **导入。** 如果你已经为某个 Agent 宿主维护着技能文件(一个 `SKILL.md` 和它的 bundle),可以直接接入。正文会被原样保留,再和其他来源一样,进入同一条起草、验证、打磨的循环。 无论从哪种方式开始,一条 Skill 都会编译成一个小 bundle:流程本身作为 `SKILL.md`,外加可选的脚本、参考资料和评测用例。它是被编译出来的,而不只是存起来,所以无论 Skill 来自哪里,你的 AI 读到的版本都是一致的。 ## 信任徽标告诉你什么 [#信任徽标告诉你什么] 一条 Skill 打开后,Agent 就真的会照着做,所以打开之前,你会想知道它确实管用。每条 Skill 都带一个信任徽标,让你一眼看出它被验证到了什么程度: * **已检验(Checked)** 表示它通过了一个测试。能用,但只在一个例子上验证过。 * **已证明(Proven)** 表示它通过了两个或更多测试,也就是说你可以在不同情形下都依赖它。 这些测试由 Mem 替你来跑,用的是从这条 Skill 自己的来源工作里取出的例子,你不用做任何设置。当你打开一条 Skill 时,这个徽标就是「现在能依赖它了吗」最快的答案。 ## 你的 AI 如何使用一条 Skill [#你的-ai-如何使用一条-skill] 一条 Skill 只有在你日常用的 Agent 能读到它时才有用。当你打开一条 Skill,Mem 会把它落成真实的文件,并通过每个宿主自己的机制注册给你已连接的宿主,比如 Claude Code 的 `~/.claude/skills`,或者 Codex 及其他 Agent 的对应位置。格式采用通用的 `SKILL.md` 约定,所以一条 Skill 能跨宿主通用。有些工具是通过与 Mem 的实时连接来读取,而不是一个技能文件夹;这时 Agent 会在需要时通过 Mem 找到对应的 Skill,而不是从磁盘里加载。 之后,Agent 读这条 Skill 的方式,和读它自己任何一条技能没有区别。一个 Agent 学会了,其余的也能用。宿主只是 runtime,而 Skill 以及它背后的信任,始终在你手里。 把一条 Skill 关掉,是保留它但不再落成文件,这和移除它不一样。两者都可以撤销。 ## 把一条 Skill 磨得更利 [#把一条-skill-磨得更利] 你可以随时让 Mem 把一条 Skill 磨得更利。这时它会试出一版改动,拿它和你已有的版本对比,用的是从这条 Skill 自己来源里取出的例子。 只有当新版本测得更好时,它才会留下这次改动。如果没有一版能赢过你已有的,它就一个都不留,并且如实告诉你。打磨只会让一条 Skill 变得更好,而不会悄悄换上一个更差的,所以你尽管放心地让它去磨。 一条已结晶 Skill 和改进提示 ## Skills 与 Mem 其他部分的关系 [#skills-与-mem-其他部分的关系] Skills 与 Mem 保存的其他东西并列,各司其职: * 一条**记忆**是你知道的事。一条 **Skill** 是你的 AI 能做的事。一条被标为 `procedure` 的记忆,是 Skill 最常见的原料。 * 一个[结晶](/zh/docs/concepts/crystals)在多个来源汇聚时,综合出稳定的参考知识。Skill 在气质上更接近它,同样是被编译而非原始的,但它产出的是一段可执行的流程,而不是一篇参考文章。 * [Context](/zh/docs/ai-context) 里的一条 **Rule** 塑造 Agent 总体上如何行事。一条 Skill 塑造它如何完成某一件具体的事。 ## 你会看到什么 [#你会看到什么] Skills 在 **Skills** 视图里。主页展示你已启用的 Skill,以及等你处理的推荐,每条推荐都带着促成它的、来自你自己工作的证据。打开一条 Skill,会看到作为主体内容的流程、它的信任状态,以及它的来处。打开、关闭还是移除,始终由你决定。 ## 延伸阅读 [#延伸阅读] * [后台智能](/zh/docs/concepts/background-intelligence)讲解技能推荐何时运行,以及约束它的预算 * [知识演化](/zh/docs/concepts/evolves)解释记忆如何获得推荐最先读取的 `procedure` 类型 * [Context](/zh/docs/ai-context) 是常驻规则所在之处,那是紧挨着 Skills 的行为层 * 如果你想用脚本读写 Skills,REST 接口见 [Skills API 参考(英文)](/docs/api/skills/get) # Alma (/docs/zh/integrations/alma) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Alma 安装或更新 Nowledge Mem。如果你使用 Alma Skills,请启用随插件附带的 nowledge-mem Skill,或复制到 ~/.config/alma/skills/nowledge-mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` 记忆随 Alma 对话流动。从插件市场一键安装;如果你使用 Alma Skills,再启用随插件附带的 Alma Skill,让 Alma 更清楚什么时候该使用记忆工具。通过 Access Anywhere 连接远程 Mem 实例,跨设备使用。 来源:[community/nowledge-mem-alma-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-alma-plugin) 安装插件后,打开一个新的 Alma 线程,直接问:"请使用 Nowledge Mem status 工具,告诉我服务器是否已连接。" `nowledge_mem_status` 的结果应显示 `ok: true` 和 `serverConnected: true`。如果你的 Mem 里已经有记忆,再问一个依赖过往工作的追问;如果是全新的空库,状态检查加对话捕获成功就足够。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行([安装指南](/zh/docs/installation)),或你已经有可访问的远程 Mem 服务 * 已安装 Alma,并且能打开它的插件市场 ## 安装步骤 [#安装步骤]
### 从 Alma 插件市场安装 [#从-alma-插件市场安装-step] 在 Alma 中打开**设置** → **插件** → **市场**,搜索 **Nowledge Mem**,点击**安装**。 Alma 市场 - Nowledge Mem
### 如需请重启 Alma [#如需请重启-alma-step]
### 可选:启用 Alma Skill [#可选启用-alma-skill-step] 不做这一步插件也能工作:工具、自动回忆和对话同步都由插件负责。如果你使用 Alma 的 **设置 → Skills** 页面,先看看是否出现随插件附带的 `nowledge-mem` Skill;如果出现,建议启用。它会提醒 Alma 什么时候读取 Context Bundle、搜索过往工作、查看来源对话,以及保存值得长期保留的决策。 如果安装插件后没有看到这个 Skill,可以复制到 Alma 的个人 Skills 目录,然后刷新 Skills: ```bash mkdir -p ~/.config/alma/skills/nowledge-mem cp ~/.config/alma/plugins/nowledge-mem/skills/nowledge-mem/SKILL.md \ ~/.config/alma/skills/nowledge-mem/SKILL.md ```
### 在新线程里验证 [#在新线程里验证-step] 请 Alma 调用状态工具: ```text 请使用 Nowledge Mem status 工具,告诉我服务器是否已连接。 ``` 然后发送一条普通短消息,等待几秒、切换线程,或正常退出 Alma。该对话应出现在 Nowledge Mem 的**对话**页面,来源为 `alma`。
## 更新 [#更新] 在 Alma 中打开 **设置** → **插件** → **市场**,找到 Nowledge Mem,如有新版本点击 **更新** 即可。 ## 禁用或卸载 [#禁用或卸载] * 如果只想暂停自动对话捕获,在 Nowledge Mem 插件设置里关闭 `autoCapture`。 * 如果只想暂停预加载回忆,把 `recallPolicy` 设为 `off`;如果只希望显式工具调用,使用 `strict_tools`。 * 如需移除连接,在 Alma 的**设置 → 插件**页面禁用或卸载 Nowledge Mem。如果你是手动复制本地插件目录安装的,先退出 Alma,再删除 `~/.config/alma/plugins/nowledge-mem`。 ## 安全地自定义 [#安全地自定义] Alma 这条连接没有单独的插件级 override 文件。 * 想做稳定的行为调整,优先使用 Alma 的插件设置,比如远程模式、回忆策略、对话捕获和 space * 如果你想让智能体的表达方式或保存偏好不同,优先走 Alma 自己的 Skills、prompt 或 instruction 入口,而不是改插件代码 不要为了一个小偏好去修改安装后的插件文件。完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 插件功能 [#插件功能] | 功能 | 说明 | | ----------------- | --------------------------------------------------------------------------------------------------- | | **自动回忆** | 每个线程的第一条外发消息发送前,自动注入工作记忆简报与相关记忆 | | **13 个工具** | 记忆:query、search、store、show、update、delete。线程:search、show、create、delete。另有 Context Bundle、工作记忆简报和状态诊断 | | **随处访问** | 在插件设置中配置 API URL + API Key,连接远程 Mem 实例 | | **设置即时生效** | 修改 API URL、API Key、回忆策略或自动捕获后立即生效,无需重启 | | **状态诊断** | `nowledge_mem_status` 显示连接模式、服务器状态、CLI 可用性和当前配置 | | **实时对话同步** | 空闲几秒后、切换线程、退出应用时自动保存对话(默认开启) | | **原生 Alma Skill** | 可选的 `nowledge-mem` Skill,用于在 Alma 的 Skills 页面中增强工具选择引导 | | **本地优先** | 使用本机 Nowledge Mem API;不启用 Access Anywhere 则无需联网 | ## 对话保存 [#对话保存] 对话在日常使用中自动同步到 Nowledge Mem:空闲几秒后、切换线程时、退出应用时都会触发保存,无需任何操作。保存的对话会出现在桌面端的"对话"页面,之后可以提炼为结构化记忆。可在插件设置中通过 `autoCapture` 关闭。 对话过程中,AI 也可能主动使用 `nowledge_mem_store` 工具将有价值的决策、结论或偏好保存为记忆。这是 AI 根据对话内容自主判断的:只有真正值得长期保留的信息才会被保存,日常闲聊不会被记录。 如果你想让 AI 保存某条信息,直接说"把这个存到记忆里"就行。 ## 全库备份(可选) [#全库备份可选] 若你需要 **全部 Alma 对话的可携带归档**(迁入新资料库、留存备查或更换设备),在 Alma 中使用 **设置 → 数据 → 导出全部对话**,会生成包含 `threads.json` 的 `alma-backup-*.zip`。 在 Nowledge Mem 中打开 **对话 → 导入 → 批量导入** 并选择该 ZIP。导入的对话来源标记为 `alma`,与插件实时同步一致,筛选与来源展示保持一致。其他批量格式与命令行说明见 [导入已有对话](/zh/docs/import-existing-conversations) 与 [对话:批量导入](/zh/docs/threads#批量导入)。 ## 随处访问 [#随处访问] 连接远程 Nowledge Mem 实例: 1. 在 Alma 中打开**设置** → **插件** → **Nowledge Mem** 2. 设置 **API URL** 为远程服务器地址(如 `https://mem.example.com`) 3. 设置 **API Key** 为你的 `nmem_...` 密钥 4. 修改立即生效。使用 `nowledge_mem_status` 验证连接 API Key 从 Alma 插件设置中读取,并通过 `Authorization: Bearer ...` 请求头发送,不会被记录到日志。 ## Spaces [#spaces] Alma 适合按 profile 保持一个稳定的记忆 lane。 * 如果一个 Alma profile 本来就对应一个固定上下文,可以直接设置 `nowledgeMem.space` * 如果你的启动器已经能提供可靠的 lane 变量,可以使用 `nowledgeMem.spaceTemplate` * 如果这个 Alma 实例始终只服务一个 space,也可以直接用 `NMEM_SPACE="Research Agent"` 启动 如果 Alma 本身并不知道真实的 Agent 身份,就不要硬做“每个 Agent 自动分 space”的路由。此时更稳妥的做法是:一个 Alma profile 对应一个 space,或者继续留在 **Default**。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations): 原生连接、复用包、MCP 与浏览器捕获 * [Claude Code](/zh/docs/integrations/claude-code) · [Claude Desktop](/zh/docs/integrations/claude-desktop) · [Codex](/zh/docs/integrations/codex-cli) · [OpenClaw](/zh/docs/integrations/openclaw) · [Raycast](/zh/docs/integrations/raycast) · [内置 Web 聊天](/zh/docs/integrations/other-chat-ai) # Antigravity CLI (/docs/zh/integrations/antigravity-cli) 把这行给你的 agent。它应该先使用通用安装 skill;本页作为行为与排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按指引为 Antigravity CLI 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证,然后总结改动。 ``` Google 已用 **Antigravity CLI**(`agy`)取代 Gemini CLI。Gemini CLI 已于 **2026 年 6 月 18 日**停止为个人版账号(Google AI Pro、Ultra 及免费 Code Assist)提供服务。Antigravity CLI 与 Antigravity 桌面平台共用同一套 agent harness,并复用你现有的 `~/.gemini` 目录,大多数 Gemini CLI 配置可以直接过渡。 Antigravity CLI 是 Google 官方指定的 Gemini CLI 继任者。迁移路径相当友好:它读取同一个 `~/.gemini` 目录,`GEMINI.md` 和 `AGENTS.md` 都继续生效,并且可以把已安装的 Gemini CLI 扩展(包括 Nowledge Mem 扩展)导入为 Antigravity 插件。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行(见[安装](/docs/installation))或有可访问的远程 Mem 服务器 * 已安装 Antigravity CLI: ```bash # macOS / Linux curl -fsSL https://antigravity.google/cli/install.sh | bash # Windows(PowerShell) irm https://antigravity.google/cli/install.ps1 | iex ``` * `nmem` 已在 `PATH` 中(见[安装](/docs/installation),或使用桌面端 **Settings → Preferences → Developer Tools → Install CLI**) 首次启动 `agy` 时会用 Google 账号登录,并主动询问是否导入现有 Gemini CLI 配置(MCP 服务器、免确认命令、快捷键、主题)。接受导入是最快的起步方式。 ## 一分钟接入 [#一分钟接入]
### 先为 Gemini CLI 安装 Nowledge Mem [#先为-gemini-cli-安装-nowledge-mem-step] 如果还没装过,先按 [Gemini CLI](/docs/integrations/gemini-cli) 页安装 Nowledge Mem 扩展。Antigravity 路径建立在它之上。
### 把扩展导入 Antigravity [#把扩展导入-antigravity-step] ```bash agy plugin import gemini ``` 这会把已安装的 Gemini CLI 扩展(包括 Nowledge Mem)转换为 Antigravity 插件。
### 运行一次 `nmem status` [#运行一次-nmem-status-step] 默认本机部署下,应指向 `http://127.0.0.1:14242 (default)`。
### 打开一个新的 `agy` 会话 [#打开一个新的-agy-会话-step] 导入的插件会自动加载上下文文件、命令和内置 MCP 工具,行为与 Gemini CLI 下一致。
## MCP 配置 [#mcp-配置] Antigravity CLI 把 MCP 服务器放在独立的 `mcp_config.json` 中(工作区路径:`.agents/mcp_config.json`)。手动配置 Mem MCP 时注意一个格式差异:远程服务器定义使用 `serverUrl` 字段,而不是 `url`。 生成与你环境匹配的配置块: ```bash nmem config mcp show --host gemini-cli ``` 把它放进 `.agents/mcp_config.json`,远程服务器记得把 `url` 改名为 `serverUrl`。这样 Antigravity 的 MCP 工具与 `nmem` 指向同一个 Mem 服务器。 ## 导入历史会话 [#导入历史会话] 会话捕获读取 `~/.gemini` 下的同一份本地历史,因此沿用 Gemini CLI 的导入方式: ```bash # 先预览 nmem t sync --from gemini-cli --all-projects --limit 20 # 再导入 nmem t sync --from gemini-cli --all-projects --apply ``` 只想导入单个项目时,用 `-p /path/to/project`。 ## 安全地自定义行为 [#安全地自定义行为] Antigravity CLI 下两种上下文文件都有效: * 项目级 `GEMINI.md` 或 `AGENTS.md` * 个人默认 `~/.gemini/GEMINI.md` 不要直接修改已安装的插件文件。完整说明见[自定义集成行为](/docs/integrations/customize-behavior)。 ## 成功的标志 [#成功的标志] 满足以下几条,说明 Antigravity CLI 已正确接入: * `agy plugin import gemini` 完成,新会话中能看到 Nowledge Mem 插件 * `nmem status` 正常返回 * 新会话启动时能看到 Context Bundle / Working Memory(有上下文可展示时) * `save-thread` 能导入真实会话;长会话在压缩前和结束时也都会被保存 ## 已知边界 [#已知边界] * `agy plugin import gemini` 是 Google 官方的迁移通道,也是当前在 Antigravity 下运行 Nowledge Mem 扩展的支持路径。 * 会话捕获目前通过 Gemini CLI connector 读取共享的 `~/.gemini` 历史。如果 Google 后续改变 Antigravity 的会话存储位置,捕获行为可能变化;升级 `agy` 后可用 `nmem t sync --from gemini-cli --limit 5` 做一次快速验证。 ## 相关 [#相关] * [Gemini CLI](/docs/integrations/gemini-cli) * [连接器总览](/docs/integrations) * [远程访问](/docs/remote-access) # 浏览器扩展 (/docs/zh/integrations/browser-extension) Nowledge Mem Exchange 是一款浏览器扩展,可从受支持的 Web AI 聊天平台捕获记忆与对话备份。在 Chrome、Edge、Arc 和 Firefox 中,它会使用浏览器原生的侧边面板或侧栏,与当前对话并排运行。 打开一个受支持的网站,再打开侧边栏,只做一件事就够了:自动捕获一条洞察、手动提炼一段对话,或备份一条线程。只要对应结果出现在 Mem 里,就说明连通了。 Firefox 使用自己的原生侧栏。捕获、手动提炼和对话备份这些流程都可以在 Firefox 中使用。Browse Now 浏览器控制是另一项能力,仍然需要 Chrome、Edge、Arc 或其他 Chromium 浏览器。
## 智能提炼 [#智能提炼] 现在扩展不再把整段对话一股脑打包丢给后端。无论是自动捕获还是手动提炼,它都会先读一遍当前对话,挑出真正重要的地方,再查 Mem 里已有的内容,最后决定是新建一条记忆,还是补充到已有记忆上。 Exchange:主动捕获设置 Exchange:智能提炼触发 Exchange:捕获结果 ## 三种捕获方式 [#三种捕获方式] | 模式 | 工作方式 | 适用场景 | | -------- | ------------------ | ------------------- | | **自动捕获** | 持续监控对话,自主保存有价值的洞察 | 配置好就不用管。扩展自行判断什么值得记 | | **手动提炼** | 由你触发对特定对话的捕获 | 当你知道这次对话有重要内容时 | | **对话备份** | 将完整对话作为线程导入,支持增量去重 | 归档整个对话,稍后在应用中提炼 | ## 自动捕获 [#自动捕获] 启用后,扩展会一直盯着当前对话,并且把门槛抬得很高,只有这几类内容才会保存:拿定的结论(决策、计划、最终方案)、重要的发现(突破性进展、关键洞察)、以及成体系的探索(深度研究、综合分析)。 日常问答和闲聊会被跳过。真正动手写之前,扩展会先把线程仔细看一遍,再去 Mem 里查有没有重复;如果已经有相关记忆,它会优先更新,而不是再造一条差不多的。 如果自动捕获真的写入了记忆,它还会先把当前对话保存成 Mem 中的标准线程,再把记忆挂到这条线程上。这样以后回看时,你能知道这条记忆到底来自哪次真实对话。 ## 手动提炼 [#手动提炼] 手动提炼适合「我知道这段对话很重要,想认真整理一下」的时候。 现在它不再把整段对话压成一段粗略摘要,而是会先读出线程里真正重要的部分,重点抓动机、约束、决策、取舍和以后还用得上的背景,先看看 Mem 里有没有相关知识,必要时还会在一次对话里创建或更新好几条记忆。 所以它更适合长讨论、设计推演、调试过程,以及那种「最关键的话其实不在最后一句」的对话。 自动捕获需要配置 LLM 提供商。打开侧边栏,进入**设置**,添加 API 密钥。支持:OpenAI、Anthropic、Google、xAI、OpenRouter、Ollama 以及 OpenAI 兼容端点。 ## 对话备份 [#对话备份] 你仍然可以随时把完整对话显式备份成线程,后续备份只会导入新增消息(增量同步)。 另外,当扩展真的从浏览器对话里写入新记忆时,它也会自动先保存标准线程。这样你不需要手动备份每一段对话,也依然能保留清晰的来源关系。 对于本地 AI 编程助手,Nowledge Mem 还支持原生连接捕获,以及面向 **Claude Code、Cursor、Codex、OpenCode** 旧本机会话的 **AI 对话发现**。详见[对话](/zh/docs/threads#自动同步)。 ## 支持的平台 [#支持的平台] | 平台 | 网站 | | --------------------- | -------------------------- | | **ChatGPT** | openai.com, chatgpt.com | | **Claude** | claude.ai | | **Gemini** | gemini.google.com | | **NotebookLM** | notebooklm.google.com | | **Microsoft Copilot** | copilot.microsoft.com | | **Perplexity** | perplexity.ai | | **DeepSeek** | chat.deepseek.com | | **Kimi** | kimi.moonshot.cn | | **通义千问** | qwen.ai, tongyi.aliyun.com | | **POE** | poe.com | | **Manus** | manus.im | | **Grok** | grok.com, grok.x.ai, x.ai | | **Open WebUI** | localhost、私有 IP | | **ChatGLM** | chatglm.cn | | **MiniMax** | agent.minimaxi.com | 浏览器扩展负责把 ChatGPT 内容保存进 Mem。如果你想让 ChatGPT 在对话中搜索 Mem,请看 [ChatGPT 网页版与桌面版](/zh/docs/integrations/chatgpt-web),使用 Remote MCP over OAuth 连接。 配置了 LLM 的付费用户可以为任意 AI 聊天网站自动生成处理器。打开侧边栏,点击**生成处理器**,扩展会自动分析页面并生成处理器。 ## 接入「随处访问 Mem」 [#接入随处访问-mem] 如果你已通过**设置 → 随处访问 Mem** 暴露了 Mem API: 1. 打开任意受支持的 AI 对话页面,打开扩展侧边栏 2. 点击 **Settings** 3. 只有当这个浏览器 profile 应该长期停留在一个命名好的 lane 时,才填写 **Fixed Space**。留空就继续使用 `Default`。 4. 在 **Access Mem Anywhere** 中粘贴: * `export NMEM_API_URL="https://"` * `export NMEM_API_KEY="nmem_..."` 5. 点击 **Fill URL + key** 6. 点击 **Save**,再点击 **Test connection** ## Spaces [#spaces] 浏览器扩展适合的空间模型,就是「一个固定 lane」: * 如果这个浏览器 profile 继续用 **Default**,就把 **Fixed Space** 留空 * 如果这个 profile 天然只属于一个上下文,再填一个命名好的空间 * 别指望扩展自己从网页里判断「当前 agent 属于哪个 lane」 当你设置了固定空间后,扩展中的记忆搜索、记忆写入、线程读取、来源读取和 Working Memory 读取都会跟着这个 lane 走。 完整流程:[随处访问 Mem](/zh/docs/remote-access)。 ## 下载 [#下载] 扩展还支持将任意对话线程下载为 `.md` 文件,用于归档或分享。 包含所有支持功能的完整示例 ## 下一步 [#下一步] * **[记忆](/zh/docs/memories)**:扩展捕获的内容。创建、搜索和组织你的知识 * **[对话](/zh/docs/threads)**:对话备份和提炼工作流 * **[随处访问 Mem](/zh/docs/remote-access)**:从远程设备连接扩展 # Bub × Nowledge Mem (/docs/zh/integrations/bub) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Bub 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` ```bash title="安装" pip install nowledge-mem-bub ``` Bub 通过 Tape 系统记录每次会话。Nowledge Mem 在此之上提供跨工具知识层:你在 Claude Code 里做的决策、在 Cursor 里设的偏好、在 ChatGPT 里得到的结论,在 Bub 里都能搜到。反过来,你在 Bub 里学到的东西,也会流回其他所有工具。 ## 准备工作 [#准备工作] * **Nowledge Mem** 正在本地运行([安装指南](/zh/docs/installation)) * **Bub** 已安装([bub.build](https://bub.build)) * **`nmem` CLI** 在 PATH 中。在 Nowledge Mem 中前往 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**,或 `pip install nmem-cli` ```bash nmem status # 确认 Nowledge Mem 正在运行 uv run bub --help # 确认 Bub 可用 ``` ## 配置 [#配置]
### 安装插件 [#安装插件-step] ```bash pip install nowledge-mem-bub ```
### 验证 hooks [#验证-hooks-step] ```bash uv run bub hooks ``` 你应该在 `system_prompt`、`build_prompt` 和 `save_state` 下看到 `nowledge_mem`。
### 试一个依赖知识的提问 [#试一个依赖知识的提问-step] 问 Bub 一个需要过去知识的问题: ```bash uv run bub run "我这周在做什么?" ``` 如果 Nowledge Mem 中已有知识,智能体会通过 `mem.search` 找到它。这说明 Bub 已经能看到你其他工具里的知识了。
## 更新 [#更新] ```bash python3 -m pip install --upgrade nowledge-mem-bub ``` ## 安全地自定义 [#安全地自定义] Bub 这条连接目前没有单独的持久化指引文件。 * 想做稳定的行为调整,优先使用环境变量,以及 Bub 自己的运行时 prompt / config * 保持安装好的 Python 包为默认状态,不要为了语言、回忆风格或保存阈值去改 site-packages 完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 能做什么 [#能做什么] ### 从其他工具获取知识 [#从其他工具获取知识] 问"我们之前关于数据库的决定是什么?",智能体会搜索你在 Claude Code 中做的决策、ChatGPT 中的讨论、Cursor 中的笔记,不局限于当前 Bub 会话。 ### 为所有工具保存知识 [#为所有工具保存知识] 在 Bub 中得出结论时,`mem.save` 会将它保存下来,下次在 Claude Code、Cursor 或 ChatGPT 中都能找到。 ### 带着今天的上下文开始 [#带着今天的上下文开始] 开启会话上下文模式后,Working Memory 和相关知识会在对话开始前就准备好,不用在不同工具间重复说明背景。 ### 追溯想法的演变 [#追溯想法的演变] `mem.connections` 展示一个决策如何随时间变化、在哪些工具中讨论过、有哪些源文档支撑。 ## 两种模式 [#两种模式] | 模式 | 配置 | 行为 | | --------- | ------------------------ | ------------------------------ | | **默认** | 无需配置 | 智能体按需搜索和保存。对话自动流入 Mem,供其他工具发现。 | | **会话上下文** | `NMEM_SESSION_CONTEXT=1` | 每轮自动注入 Working Memory 和相关知识。 | 建议从默认模式开始。如果你希望从第一句话就有完整的上下文回忆,再开启会话上下文。 ## 工具 [#工具] | 工具 | 说明 | | ----------------- | ----------------------------------- | | `mem.search` | 搜索所有工具中的知识,支持标签和日期过滤。 | | `mem.save` | 保存决策、洞察或偏好,让任何工具都能找到。 | | `mem.context` | 读取今天的 Working Memory:关注领域、优先级、近期动态。 | | `mem.connections` | 探索一条知识与其他知识的关联,跨工具、跨时间。 | | `mem.timeline` | 按天分组的近期活动。 | | `mem.forget` | 按 ID 删除一条记忆。 | | `mem.threads` | 搜索所有工具中的历史对话。 | | `mem.thread` | 获取完整对话消息,支持分页。 | | `mem.status` | 连接状态和配置诊断。 | 所有工具也可作为 Bub 逗号命令使用:`,mem.search query=...` ## 环境变量 [#环境变量] 本地使用无需配置。 | 变量 | 默认值 | 说明 | | ---------------------- | ------- | ------------------------- | | `NMEM_SESSION_CONTEXT` | `false` | 每轮注入 Working Memory 和相关知识 | | `NMEM_SESSION_DIGEST` | `true` | 将 Bub 对话流入 Mem,供其他工具发现 | | `NMEM_API_URL` | *(本地)* | 远程 Nowledge Mem 服务器地址 | | `NMEM_API_KEY` | *(无)* | 远程访问的 API 密钥 | 如果你想用一套持久化的共享配置,先在这台机器上执行 `nmem config client ...`。如果只是临时覆盖,环境变量仍然优先。 ### Spaces [#spaces] Bub 目前最稳妥的做法仍然是按进程分 lane。 * 如果一个 Bub 进程天然只属于一个上下文,直接设置 `NMEM_SPACE="Research Agent"` * 如果你同时运行多个 Bub agent,就给每个进程各自设置一个 `NMEM_SPACE` * 如果 Bub 这边没有可靠的 Agent 身份信号,就继续使用 **Default** 也就是说,Bub 现在适合“一个进程一个 lane”,而不是在同一个进程里伪造复杂的多 Agent 自动映射。 ### 远程访问 [#远程访问] ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` 详见[远程访问 Mem](/zh/docs/remote-access)。 ## 常见问题 [#常见问题] **插件未加载。** 运行 `uv run bub hooks`,确认列表中有 `nowledge_mem`。确保 `nowledge-mem-bub` 与 Bub 装在同一个 Python 环境里。 **nmem 未找到。** 运行 `pip install nmem-cli && nmem status`。 **服务器无响应。** 启动 Nowledge Mem 桌面应用,或用 `nmem status` 查看诊断信息。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations) * [Claude Code](/zh/docs/integrations/claude-code) · [OpenClaw](/zh/docs/integrations/openclaw) · [Alma](/zh/docs/integrations/alma) · [Gemini CLI](/zh/docs/integrations/gemini-cli) * 插件源码:[nowledge-mem-bub-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-bub-plugin) * [tape.systems](https://tape.systems) · [bub.build](https://bub.build) # ChatGPT 网页版与桌面版 (/docs/zh/integrations/chatgpt-web) ChatGPT 和 Nowledge Mem 有两种不同的连接方式: * **浏览器扩展**:从你正在使用的 ChatGPT 网页捕获洞察,或备份当前对话线程。 * **通过 OAuth 远程连接 MCP**:把 Mem 作为 ChatGPT connector 接入,让 ChatGPT 网页版和桌面版在对话中搜索你的记忆、对话和资料库上下文。 想把 ChatGPT 的内容保存进 Mem,就用浏览器扩展。想让 ChatGPT 读取 Mem,就用 Remote MCP。 ## 方式一:捕获 ChatGPT 对话 [#方式一捕获-chatgpt-对话] 如果你想从 ChatGPT 页面保存决策、发现或完整对话备份,请安装 **Nowledge Mem Exchange**。
### 安装浏览器扩展 [#安装浏览器扩展-step] 按照[浏览器扩展指南](/zh/docs/integrations/browser-extension)安装,然后在 `chatgpt.com` 打开侧边栏。
### 选择要保存的内容 [#选择要保存的内容-step] 用 **Always Remember** 自动捕获高价值记忆;用 **Manual Distill** 手动提炼你认为重要的对话;用 **Thread Backup** 把完整对话保存为 Mem 线程。
## ChatGPT Team / Business 的旧对话 [#chatgpt-team--business-的旧对话] 个人版 ChatGPT 通常可以走 [OpenAI 官方数据导出](https://help.openai.com/en/articles/7260999-how-do-i-export-my-chatgpt-history-and-data),再把导出的 `chat.html` 通过[导入已有对话](/zh/docs/import-existing-conversations)放进 Mem。ChatGPT Business、Enterprise,以及部分 Team workspace 目前不一定有同样的全量导出入口。 如果你需要把旧 workspace 对话带进 Mem,请把它当成一个“数据可携带性”流程: * 还能打开的当前对话:用 Exchange 侧边栏保存当前线程。 * 已经导出到本地的文件:从 **Threads → Import → Bulk Import** 导入,或用本机 `nmem` CLI 导入。 * 公司或团队数据:先确认 workspace 政策。不要把 ChatGPT access token 粘给你不完全信任的工具。 社区讨论里有人提到 [chatGPT\_extractor](https://github.com/richlow/chatGPT_extractor) 和 [export-chatgpt](https://github.com/brianjlacy/export-chatgpt) 这类工具,用来导出 ChatGPT Team 或 Business 历史。它们不是 OpenAI 或 Nowledge Mem 官方工具,可能依赖 ChatGPT 网页 session token 或内部接口;ChatGPT 改版后也可能失效,并且不一定符合你的 workspace 政策。只在你信任的本机环境中运行,并确认你有权导出这些数据。 拿到本地导出文件夹后,可以让你的 coding agent 安全地批量导入: ```text 我已经把 ChatGPT Team/Business 的对话导出到: /path/to/export-folder 请只在本机检查这些文件,不要上传到其他服务。参考 `nmem t import --help`, 用本机 `nmem` CLI 把这些对话作为 ChatGPT threads 导入 Nowledge Mem。 先导入少量样本,用 `nmem t list --source chatgpt -n 5` 验证标题、顺序和内容, 再继续批量导入。能保留标题和时间就保留,source 设为 `chatgpt`, 不要自动创建长期记忆。 ``` 如果只有单个 Markdown、JSON 或 HTML 文件,可以先从这个命令开始: ```bash nmem t import --file /path/to/conversation.md --source chatgpt ``` 关于为什么需要这条路径,可以参考 OpenAI 社区里关于 [ChatGPT Team 导出限制](https://community.openai.com/t/export-chats-in-chatgpt-team/620984/29)的讨论。 ## 方式二:让 ChatGPT 通过 MCP 使用 Mem [#方式二让-chatgpt-通过-mcp-使用-mem] 当 ChatGPT 要求填写远程 MCP connector URL 时,使用这条路径。Mem 会通过 Access Anywhere 和 OAuth 授权连接,所以你不需要把私有 `nmem_` API key 粘贴到 ChatGPT。 ChatGPT 是云端客户端,不能访问你机器上的 `localhost` 或内网地址。请先配置一个公开 HTTPS 的 Access Anywhere endpoint,然后复制以 `/mcp` 结尾的 Mem MCP endpoint。
### 在 Mem 中启动 Remote MCP OAuth [#在-mem-中启动-remote-mcp-oauth-step] 打开 **Mem → 集成 → Plugins → 通过 OAuth 远程连接 MCP**,点击**开始设置**。 Mem 会在浏览器中打开配对页面,并复制 `/mcp` 地址。后续 ChatGPT 的 OAuth 授权也请使用同一个浏览器 Profile。 如果你误关了配对页或 ChatGPT 的授权页,回到 Mem 的**通过 OAuth 远程连接 MCP**, 点击**重新开始**即可立刻打开新的配对页,不需要等待上一个 30 分钟配对窗口过期。 在 Mem 中启动 Remote MCP OAuth
### 在 ChatGPT 设置中创建 connector [#在-chatgpt-设置中创建-connector-step] 打开 [ChatGPT Connectors Advanced 设置](https://chatgpt.com/#settings/Connectors/Advanced),选择 **Create**。 创建 ChatGPT connector
### 粘贴 Mem MCP endpoint [#粘贴-mem-mcp-endpoint-step] 从 Mem 复制 **Access Anywhere MCP endpoint**。这个地址必须以 `/mcp` 结尾,例如: ```text https://your-access-anywhere-domain.example/mcp ``` 把这个 URL 粘贴到 ChatGPT,然后继续。 粘贴 Mem MCP endpoint
### 通过 OAuth 授权 Mem [#通过-oauth-授权-mem-step] 当 Mem 打开 OAuth 授权页面时,允许 ChatGPT 使用 Mem。如果你看到“Pair this browser with Mem”,请回到 Mem,点击**重新开始**,并在打开配对页的同一个浏览器 Profile 中继续。 在 OAuth 页面授权 Mem
### 确认 connector 已创建 [#确认-connector-已创建-step] ChatGPT 现在应该会在 connector 列表里显示 Mem。 ChatGPT 显示已创建的 connector
### 在 ChatGPT 中启用 connector [#在-chatgpt-中启用-connector-step] 在当前 ChatGPT workspace 或对话上下文中允许这个 connector。 在 ChatGPT 中允许 connector
### 让 ChatGPT 使用 Mem [#让-chatgpt-使用-mem-step] 在 ChatGPT 网页版或桌面版里输入 `@Nowledge Mem`,然后让它搜索 Mem,例如:"Search my Mem for the project decision about the database migration." 在 ChatGPT 中使用 Mem 目前创建自定义 connector 需要从 ChatGPT 网页设置进入。添加完成后,同一个 ChatGPT 账号可以在桌面版里通过 `@Nowledge Mem` 调用它。
## 应该用哪条路径? [#应该用哪条路径] | 目标 | 使用 | | ------------------------------------- | ------------------------------------------------ | | 把有价值的 ChatGPT 对话保存进 Mem | 浏览器扩展 | | 让 ChatGPT 网页版或桌面版在对话中搜索 Mem | Remote MCP over OAuth | | 导入多年 ChatGPT 历史记录 | [导入已有对话](/zh/docs/import-existing-conversations) | | 没有官方全量导出的 ChatGPT Team / Business 旧历史 | 用你信任的工具导出到本地,再用 `nmem` 导入 | ## 相关 [#相关] * [连接总览](/zh/docs/integrations) * [Access Anywhere](/zh/docs/remote-access) * [浏览器扩展](/zh/docs/integrations/browser-extension) * [导入已有对话](/zh/docs/import-existing-conversations) # Claude Code (/docs/zh/integrations/claude-code) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Claude Code 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` ```bash title="一键安装" claude plugin marketplace add https://github.com/nowledge-co/community && claude plugin install nowledge-mem@nowledge-community ``` Claude Code 支持插件,一次安装即可获得内置自主行为,无需配置系统提示或 MCP。 智能体会自动搜索你已经知道的内容,并在正确的时机保存值得留下的东西,无需你手动触发。 安装好插件、确认 `nmem` 可用,然后开一个新的 Claude Code 会话。只要你能看到工作记忆简报在开局被读取,或者 `/search` / `/save` 无需额外配置就能工作,这条路径就已经接通了。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行([安装指南](/zh/docs/installation)),或你已经有可访问的远程 Mem 服务 * 已安装 Claude Code ## 设置 [#设置]
### 安装插件 [#安装插件-step] ```bash # 添加 Nowledge 社区插件市场 claude plugin marketplace add https://github.com/nowledge-co/community # 安装 Nowledge Mem 插件 claude plugin install nowledge-mem@nowledge-community ``` 插件需要 `nmem` CLI: ```bash # 方式一(推荐):使用 uvx,无需额外安装 curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version # 方式二:pip 安装 pip install nmem-cli ``` > 如果这台机器上已经安装 Nowledge Mem 桌面端,最稳妥的方式是打开 **Settings → Preferences → Developer Tools → Install CLI**。只有在远程机器或没有桌面端的环境中,才需要用 `uvx` 或手动安装。
### 使用斜杠命令与技能 [#使用斜杠命令与技能-step] **斜杠命令:** * `/save`:保存当前会话到 Nowledge Mem * `/sum`:将对话洞察提炼成记忆 * `/search <关键词>`:搜索知识库 * `/status`:检查服务器连接状态 **自然语言:** 说「保存这个会话」或「提炼这次对话」,Claude 会自动运行对应的 `nmem` 命令。 **自主运行(技能):** 插件包含三个自动触发的技能: * **Read Working Memory**:会话开始和上下文压缩后加载工作记忆简报 * **Search Memory**:引用过去工作时自动搜索 * **Distill Memory**:在关键发现时建议提炼 **按需触发:** **Save Thread**:当你说「保存会话」或「checkpoint」时保存对话
## 更新 [#更新] ```bash claude plugin marketplace add https://github.com/nowledge-co/community claude plugin marketplace update nowledge-community claude plugin update nowledge-mem@nowledge-community # 重启 Claude Code 以应用更改 ``` ## 导入旧会话 [#导入旧会话] 自动捕获会从插件和 hooks 安装完成后开始。如果你想把更早的 Claude Code 会话也导入 Nowledge Mem,先预览: ```bash nmem t sync --from claude-code --all-projects --limit 20 ``` 确认无误后再导入: ```bash nmem t sync --from claude-code --all-projects --apply ``` 如果只想导入某个项目,用 `-p /path/to/project` 代替 `--all-projects`。这个命令会读取本机 Claude Code 会话文件,并写入 `nmem` 当前配置的 Mem 服务器。 ## Spaces [#spaces] Spaces 是显式选择,不是目录名自动生成。Claude Code 插件不会根据当前文件夹、git 仓库、分支或项目名创建或选择 Mem space。没有额外设置时,Context Bundle、Working Memory、搜索和自动会话捕获都会使用默认 space。 只有当整个 Claude Code 进程都应该使用某个已存在的 Mem space 时,才设置 `NMEM_SPACE`: ```bash NMEM_SPACE="Research Agent" claude ``` 如果是多 Agent 启动器,优先用稳定的 `NMEM_AGENT_ID` 表示 worker 身份。只有这个 worker 需要覆盖身份默认 space 时,再加 `NMEM_SPACE`。 ## 安全地自定义 [#安全地自定义] 优先使用 Claude Code 自己的记忆文件,而不是去改插件安装目录: * 个人调整放在 `CLAUDE.local.md` * 仓库共享规则放在 `CLAUDE.md` 不要直接修改已安装的 Nowledge Mem 插件文件。完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 生命周期钩子 [#生命周期钩子] 插件使用 [Claude Code hooks](https://code.claude.com/docs/en/hooks) 实现自动生命周期管理: | 事件 | 触发条件 | 操作 | | ------------------------ | --------- | -------------------------------------------------------------- | | `SessionStart`(启动/恢复/清除) | 新会话、恢复或清除 | 先通过 `nmem context` 加载 Context Bundle,再回退到 `nmem wm read` 和本地文件 | | `SessionStart`(压缩) | 上下文压缩后 | 重新加载 Context Bundle 或 Working Memory,提示 Claude 保存重要发现 | | `UserPromptSubmit` | 每条用户消息 | 注入搜索/保存语法提示,Claude 可见 | | `PreCompact` | 手动或自动压缩前 | 在上下文被压缩前,先保存这条 Claude Code 会话 | | `Stop` | 模型完成响应 | 在有界重试窗口内捕获会话到知识图谱 | 上下文压缩后,Context Bundle 或 Working Memory 会重新加载。`PreCompact` 钩子会在 Claude Code 压缩上下文前先保存完整本地会话,`Stop` 钩子则继续负责平时每轮回复后的捕获。即使 Nowledge Mem 运行在另一台机器上(远程模式),这条路径也能工作。如果 Claude Code 在回复后还需要一点时间把 transcript 写完,钩子会等待并重试,而不是静默产生一次空保存。 如果桌面应用里的 Claude Code 文件监听也已开启,可以继续保留。文件监听和插件钩子会写入同一个 `claude-code-` 线程;重复保存只会更新已有线程,不会再生成第二条。 ### 本地与远程模式 [#本地与远程模式] 插件在两种模式下透明运行: * **本地**(Mem 在同一台机器上):优先通过 Mem 读取 Context Bundle,旧版 CLI 会回退到 Working Memory。只有 API 路径不可用时,插件才会把 `~/ai-now/memory.md` 当作 Default 分区的兼容回退。会话会由桌面应用文件监听、Stop 钩子,以及压缩前的 PreCompact 钩子一起捕获。 * **远程**(Mem 在不同机器上):先在这台机器上执行一次: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` 这会写入 `nmem` 和插件共用的本地客户端配置。也可使用环境变量(`NMEM_API_URL`、`NMEM_API_KEY`)做临时覆盖。优先级:CLI 参数 > 环境变量 > 配置文件 > 默认值。 当 Stop 或 PreCompact 钩子运行 `nmem t save --from claude-code` 时,Claude 的会话文件会先在运行 Claude Code 的那台机器上被本地读取,再以规范化后的线程消息上传到 Mem。默认会读取 `~/.claude`;如果你把 Claude 配置放在别的位置,设置 `CLAUDE_CONFIG_DIR` 就可以了。远程 Mem 服务器不需要直接访问这个本地目录。 ## 进阶 [#进阶] **[AGENTS.md](https://github.com/nowledge-co/community/blob/main/examples/AGENTS.md)**:基于 [agents.md 标准](https://agents.md/) 的完整记忆守护 Agent 示例,适配任何 AI 编程工具。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations):原生连接、复用包、MCP 与浏览器捕获 * [Claude Desktop](/zh/docs/integrations/claude-desktop) · [Codex](/zh/docs/integrations/codex-cli) · [Alma](/zh/docs/integrations/alma) · [OpenClaw](/zh/docs/integrations/openclaw) · [Raycast](/zh/docs/integrations/raycast) · [内置 Web 聊天](/zh/docs/integrations/other-chat-ai) # Claude Desktop (/docs/zh/integrations/claude-desktop) 在 macOS 和 Windows 上装一次就能用。不需要额外安装 Python 或 Node。之后 Claude Desktop 可以在任意对话里直接搜索记忆、保存新内容、更新已有知识。 安装完成后,在 Claude Desktop 对话框左下角点击 `+`,打开 **Connectors**。如果能看到 **Nowledge Mem**,这条连接就已经通了。 ## 开始之前 [#开始之前] * 这台机器上已经运行了 Nowledge Mem([安装指南](/zh/docs/installation)),或者你已经有可访问的远程 Mem 服务 * 已安装并更新到最新 Claude Desktop ## 设置 [#设置]
### 下载扩展 [#下载扩展-step]
### 安装并重启 Claude Desktop [#安装并重启-claude-desktop-step] 双击下载好的 `claude-dxt.mcpb` 文件,在弹窗里点击**安装**,然后重启一次 Claude Desktop。 安装扩展
### 在对话中使用 Mem [#在对话中使用-mem-step] 在对话中让 Claude 保存洞察、搜索记忆或更新知识库。 在 Claude Desktop 中使用 Mem Claude Desktop 与 Mem 及图谱视图
## 随处访问 Mem [#随处访问-mem] 扩展默认连接本机 Mem。要连接远程 Mem,它会直接读取和 `nmem` CLI 相同的共享客户端配置。 如果你是在同一台机器上的 Nowledge Mem 桌面端里开启 **随处访问 Mem**,通常不需要再额外配置。桌面端会自动把连接信息写进去。 如果 Claude Desktop 跑在另一台机器上,先在那台机器上完成配置: 推荐先执行: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` 这会写入 Claude Desktop 读取的那份共享客户端配置。如果你想手动查看或编辑文件,路径如下。 路径: ```text ~/.nowledge-mem/config.json ``` 路径: ```text %USERPROFILE%\.nowledge-mem\config.json ``` `apiUrl` 建议填写你的服务器根地址。如果你手里已有旧配置,结尾是 `/remote-api` 或 `/mcp` 也可以继续用,扩展会自动兼容。 改完连接配置后重启 Claude Desktop。 ## 排查问题 [#排查问题] 如果 Claude Desktop 里没有出现 Mem: 1. 点击对话框左下角的 `+`,打开 **Connectors**,确认里面能看到 **Nowledge Mem**。 2. 打开 **Settings → Extensions → Advanced Settings**,查看扩展状态和日志。 3. 如果你走的是远程连接,在那台机器上运行 `nmem config client show`,确认 URL 和 API Key 状态都正确。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations): 原生连接、复用包、MCP 与浏览器捕获 * [Claude Code](/zh/docs/integrations/claude-code) · [Codex](/zh/docs/integrations/codex-cli) · [Alma](/zh/docs/integrations/alma) · [OpenClaw](/zh/docs/integrations/openclaw) · [Raycast](/zh/docs/integrations/raycast) · [内置 Web 聊天](/zh/docs/integrations/other-chat-ai) # Codex (/docs/zh/integrations/codex-cli) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Codex 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` 现代 Codex 的推荐做法是:安装插件、保留插件内置的 Nowledge Mem MCP,并运行一次 hook setup。SessionStart 会自动注入当前 Nowledge 上下文,每轮的轻量路由会把历史问题指向跨工具知识源,MCP 提供更顺手的检索和写入工具,Stop hook 则自动捕获真实会话。 在 Codex、Claude Code、Gemini、Cursor 之间切换,不丢失上下文。这个 Codex 包会在启动时注入 Context Bundle / Working Memory,内置本地 MCP 连接,把延续型工作引导到检索,并自动捕获 Codex 对话线程。Codex 仍会判断何时需要进一步检索,但不再只靠 skill 描述来发现 Nowledge,因此推荐组合是:插件 + MCP + hook。 Codex 桌面端和 Codex CLI 共用同一个 `~/.codex` 配置、插件缓存、hook 和 MCP 设置。这份指南会使用 `codex` 命令,因为安装和更新由 CLI 管理;但装好之后,这个连接同时适用于桌面端和 CLI。 开始一次会话,先问「我在做什么?」你应该看到最近的工作重点和优先事项。然后再问一个延续型问题,比如「我们之前对这个发布流程做过什么决定?」正常情况下,Codex 不应该停在简报这里,而会继续进入检索。完成一个短回合后,运行 `nmem t search "这轮里的一句话" --source codex`,应该能看到被捕获的 Codex 线程。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行([安装指南](/zh/docs/installation)),或有可访问的远程 Mem 服务 * 已安装 Codex 桌面端或 Codex CLI * `nmem` CLI 在你的 `PATH` 中 ## 设置 [#设置]
### 安装 `nmem` [#安装-nmem-step] ```bash # 方式一:uvx curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version # 方式二:pip pip install nmem-cli ``` 如果 Nowledge Mem 桌面应用已在同一台机器上运行,推荐的方式是 **Settings → Preferences → Developer Tools → Install CLI**。
### 安装插件 [#安装插件-step] 如果你看到旧文档让你手动复制文件到 `~/.codex/plugins/cache/local/...`,请把它当作兼容旧流程。当前推荐路径是:先添加 marketplace,从这个 marketplace 安装插件,最后在配置里启用。 ```bash codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin codex plugin add nowledge-mem@nowledge-community ``` 如果你的 Codex 还是旧版顶层子命令: ```bash codex marketplace add nowledge-co/community ``` 你也可以打开 Codex 的 `/plugins`,从那里安装 `nowledge-mem@nowledge-community`。 优先使用上面的 sparse marketplace 命令。它只让 Codex 拉取 marketplace 元数据和 Codex 插件包,不再克隆整个 community 仓库,可以避开网络稍慢时 30 秒 clone 超时的问题。
### 启用插件 [#启用插件-step] 把下面这段放进 `~/.codex/config.toml`: ```toml [features] plugins = true hooks = true [plugins."nowledge-mem@nowledge-community"] enabled = true ``` 安装完成后重启 Codex。 当前插件包已经内置本地 Nowledge Mem MCP,地址是 `http://127.0.0.1:14242/mcp/`。如果你在 `~/.codex/config.toml` 里自己定义 `mcp_servers.nowledge-mem`,Codex 会优先使用你的配置,所以远程 Mem 和自定义端口仍然是显式可控的。
### 开启生命周期上下文与线程捕获 [#开启生命周期上下文与线程捕获-step] Codex 依靠 hook 自动加载启动上下文、完成记忆路由并捕获线程。当前 Codex 会自动读取已启用插件内置的 hook;旧版曾经需要单独的 `plugin_hooks` 开关。setup 会先检测宿主能力,只在旧版仍需要时添加兼容开关。安装或更新插件后,运行一次插件自带的 hook setup: ```bash HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" if [ -z "$HOOK_SETUP" ]; then echo "没有找到 hook setup。请打开 Codex,运行 /plugins,安装 nowledge-mem@nowledge-community,然后重试。" else python3 "$HOOK_SETUP" fi ``` setup 完成后重启 Codex。Codex 提示你检查新增或变更的 hook 时,请信任 Nowledge Mem 的 SessionStart、UserPromptSubmit 和 Stop hook;“启用”与“信任命令”是两道独立的安全确认。 SessionStart hook 会注入 Context Bundle,必要时退回 Working Memory。一段很短的 UserPromptSubmit 路由会确保延续、复盘、回归、发布、连接器、历史决策和精确会话问题进入 Nowledge 检索。Stop hook 则调用 `nmem t save --from codex`,先读取本机 transcript,再通过你的 `nmem` 客户端配置上传。因此本地 Mem 和远程 Mem 使用同一套配置。如果 Codex 同时看到插件内置 Stop hook 和宿主级兜底 hook,同一份 transcript 状态只会保存一次。 同一个 setup 也会检查你的 `nmem` 客户端配置。如果 `nmem` 里已经保存了 API key,或你使用的不是默认本地地址,setup 会在 `~/.codex/config.toml` 里写入一段托管的 Codex MCP 配置,让 Codex 和 CLI 指向同一个 Mem。 在 Windows PowerShell 中,用 Python launcher 运行同一个已安装 setup 脚本: ```powershell $HookSetup = Get-ChildItem "$env:USERPROFILE\.codex\plugins\cache" -Recurse -Filter install_hooks.py | Where-Object { $_.FullName -like "*nowledge-mem*" } | Sort-Object FullName | Select-Object -Last 1 if ($null -eq $HookSetup) { Write-Host "没有找到 hook setup。请打开 Codex,运行 /plugins,安装 nowledge-mem@nowledge-community,然后重试。" } else { py -3 $HookSetup.FullName } ```
### 如果你也使用 Codex 官方 Memory [#如果你也使用-codex-官方-memory-step] Codex 本地 Memory 和 Nowledge Mem 可以同时使用,但它们不是同一个知识库。Codex Memory 是当前 `CODEX_HOME` 下的本地生成状态;Nowledge Mem 负责当前 Working Memory、精确会话、可追溯决策、Spaces,以及跨所有已连接 AI 工具的知识。 在 **Codex Settings → Personalization** 中关闭 **Allow memory generation from tool-assisted tasks**。这样,使用过 Nowledge MCP、网页搜索或工具搜索的任务就不会再进入 Codex 自己的记忆生成器。若你仍想保留 Codex 的本地回忆层,可以继续开启 **Enable memories**。 对应的 `~/.codex/config.toml` 配置是: ```toml [memories] disable_on_external_context = true ``` 如果不做这层隔离,Codex 可能把刚从 Nowledge 取回的内容再次总结进本地 Memory;后续任务就可能直接使用这份较旧的摘要,而不再查询当前的跨工具知识源。插件 `0.1.26` 起会额外注入明确的路由边界,但这个开关才能从写入侧关闭重复学习回路。setup 检测到这种组合时只会提示,不会替你修改 Codex Memory 设置。 你也可以继续关闭 Codex 本地 Memory。Nowledge 的启动上下文、检索、蒸馏和线程捕获都不受影响。
### 可选:添加项目级引导 [#可选添加项目级引导-step] 将插件的 `AGENTS.md` 复制或合并到你的项目根目录,增强该仓库中的记忆行为: ```bash git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community cp /tmp/nowledge-community/nowledge-mem-codex-plugin/AGENTS.md ./AGENTS.md rm -rf /tmp/nowledge-community ``` 如果你的项目已经有 `AGENTS.md`,请把 Nowledge 部分合并进去,而不是直接覆盖。这一步能明显改善 continuation-heavy 仓库里只读 Working Memory、不继续搜索的情况。 把你仓库自己的 `AGENTS.md` 当作长期 override 层。插件包里的 `AGENTS.md` 只是参考文本,用来复制或合并,不要直接去改 Codex 插件安装目录里的那份。
### 需要远程 Mem 时配置 [#需要远程-mem-时配置-step] ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` `nmem` 的连接优先级: 1. `--api-url` / `--api-key` 参数 2. `NMEM_API_URL` / `NMEM_API_KEY` 环境变量 3. `~/.nowledge-mem/config.json` 4. 默认值 如果 Mem 在远程机器上,也要在 `~/.codex/config.toml` 中覆盖插件内置的本地 MCP 地址: ```bash nmem config mcp show --host codex ``` 把生成的 TOML 放进 `~/.codex/config.toml`。如果你安装的插件版本是 `0.1.11` 或更新,也可以直接重新运行上面的 hook setup。直接 MCP 客户端不会自动读取 `~/.nowledge-mem/config.json`;这一步能确保 Codex MCP 和本机 `nmem` 客户端指向同一台 Mem 服务器。MCP 给 Codex 直接工具,`nmem` 继续负责插件里的兜底行为和真实 `save-thread`。
## 项目级安装(可选方案) [#项目级安装可选方案] 除了共享 marketplace 源,也可以把插件打包进项目仓库,通过本地 Codex marketplace 文件让 Codex 自动发现。这样克隆仓库的人可以直接使用。 ```bash git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community mkdir -p .agents cp -r /tmp/nowledge-community/nowledge-mem-codex-plugin ./.agents/nowledge-mem rm -rf /tmp/nowledge-community mkdir -p .agents/plugins ``` 创建 `.agents/plugins/marketplace.json`: ```json { "name": "local", "plugins": [ { "name": "nowledge-mem", "source": { "source": "local", "path": "./.agents/nowledge-mem" }, "policy": { "installation": "INSTALLED_BY_DEFAULT", "authentication": "ON_INSTALL" }, "category": "Productivity" } ] } ``` `path` 相对于仓库根目录,而非 marketplace 文件本身。这个本地方案需要使用: ```toml [plugins."nowledge-mem@local"] enabled = true ``` 然后从项目内插件运行 hook setup: ```bash python3 ./.agents/nowledge-mem/scripts/install_hooks.py ``` ## 更新 [#更新] 如果你是在 `0.1.14` 之前安装的 Codex 包,请先刷新 marketplace。当前 Codex 有时只会刷新 marketplace checkout,不会重新安装已经缓存的插件包;在插件包本身更新之前,hook setup 文件或插件内置 hook 的变化仍可能不存在。 ```bash (codex plugin marketplace remove nowledge-community || codex marketplace remove nowledge-community || true) codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin codex plugin add nowledge-mem@nowledge-community ``` 这会用 Codex sparse checkout 重新添加 marketplace。旧安装使用的是完整 community 仓库 clone;如果 Codex 报 `git clone marketplace source timed out after 30s` 或 `early EOF`,这就是恢复路径。你也可以从 Codex 的 `/plugins` 更新或重新安装 `nowledge-mem@nowledge-community`。插件包更新后,请重启 Codex。 插件包本身更新完成后,再刷新 hook runtime: ```bash HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" if [ -z "$HOOK_SETUP" ]; then echo "hook setup 仍然不存在。请从 Codex /plugins 重新安装 nowledge-mem@nowledge-community,然后重试。" else python3 "$HOOK_SETUP" fi ``` 如果这个 marketplace 还没有注册,请运行: ```bash codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin || codex marketplace add nowledge-co/community ``` 然后重启 Codex。如果你用的是项目内 `@local` 源,请更新本地源路径。 ## 技能 [#技能] 在 hybrid 配置里,这些技能仍然重要。它们负责告诉 Codex 什么时候该用记忆,而 MCP 负责在 Codex 决定行动时,给它一个更顺手的执行入口。 | 技能 | 触发条件 | 功能 | | ------------------------------ | -------------------------- | ---------------------------------------------- | | `$nowledge-mem:working-memory` | 会话开始、”我在做什么” | 读取当天的工作记忆简报;如果有 MCP,就优先走 `read_working_memory` | | `$nowledge-mem:search-memory` | 涉及过往工作、过去的决策 | 搜索记忆和对话,支持逐层深入查看;如果有 MCP,就优先走检索工具 | | `$nowledge-mem:save-thread` | 用户明确要求保存,或 hook setup 不可用时 | 通过 `nmem t save --from codex` 导入真实 Codex 会话 | | `$nowledge-mem:distill-memory` | 做出决策、发现经验教训 | 主动将有价值的洞察保存为记忆;如果有 MCP,就优先走写入工具 | | `$nowledge-mem:status` | "Mem 能用吗"、出错时 | 检查服务器连接和配置状态 | ## Codex 使用 Nowledge FS [#codex-使用-nowledge-fs] [Nowledge FS](/zh/docs/nowledge-fs) 是知识树背后的共享路径层,不是 Codex 专属功能。Codex 可以通过同一个 MCP 服务器使用 `mem_fs`,在记忆、线程、Wiki、工作记忆、动态、来源和产物之间按路径浏览。 ```text mem_fs: recall "为什么改了 token refresh?" --in /memories -k 5 mem_fs: cat /memories/by-id/.memory.md mem_fs: ls /memories/by-label/auth ``` 如果当前环境没有 MCP,可以直接用 CLI: ```bash nmem fs recall "session token strategy" --in /memories -k 5 nmem fs grep "JWT rotation" /memories nmem fs cat /memories/by-id/.memory.md ``` 模糊问题用 `recall`,结构化条件用 `find`,精确短语用 `grep`;读取大内容前先用 `stat` 看元数据,确定路径后再 `cat`。`grep` 默认忽略大小写;需要严格大小写时用 `--case-sensitive`,需要正则时用 `-E`。这个预览版走 API,可用于桌面端、Web 端和远程连接;真正挂载成系统文件夹会在后续阶段实现。 ## 直接使用 `nmem` [#直接使用-nmem] `nmem` 仍然是通用兜底层,也是 Codex 真实线程导入的正确路径。Stop hook 自动调用的也是同一个命令: ```bash nmem --json wm read nmem --json m search "auth token rotation" --mode deep nmem --json t save --from codex -p . -s "完成了 auth 重构" nmem --json m add "JWT 刷新失败源于时钟偏移" --title "JWT 刷新失败追溯到时钟偏移" --importance 0.9 --unit-type learning -l auth -s codex ``` 默认情况下,`nmem t save --from codex` 会去 `~/.codex` 里找会话。如果 Codex Home 在其他位置,设置 `CODEX_HOME` 即可。 如果要导入更早的 Codex 会话,先预览: ```bash nmem t sync --from codex --all-projects --limit 20 ``` 确认无误后再导入: ```bash nmem t sync --from codex --all-projects --apply ``` 如果只想导入某个项目,用 `-p /path/to/project` 代替 `--all-projects`。这个命令会读取本机 Codex transcript 文件,并写入 `nmem` 当前配置的 Mem 服务器。 ## 从自定义提示词迁移 [#从自定义提示词迁移] 如果之前使用的是 `nowledge-mem-codex-prompts`,这个插件完整覆盖了原有功能: 1. 安装插件(见上方步骤)。 2. 删除旧提示词:`rm ~/.codex/prompts/{read_working_memory,search_memory,save_session,distill}.md` 3. 插件技能一一对应替代旧提示词。 | 旧提示词 | 新技能 | | ------------------------------ | ------------------------------ | | `/prompts:read_working_memory` | `$nowledge-mem:working-memory` | | `/prompts:search_memory` | `$nowledge-mem:search-memory` | | `/prompts:save_session` | `$nowledge-mem:save-thread` | | `/prompts:distill` | `$nowledge-mem:distill-memory` | | (无) | `$nowledge-mem:status` | ## 常见问题 [#常见问题] **找不到 nmem 命令** 用 `pip install nmem-cli` 安装,或使用 `uvx --from nmem-cli nmem`。参见[安装指南](/zh/docs/installation)。 **无法连接服务器** 运行 `nmem status` 和 `nmem config client show` 检查远程配置是否正确。参见[远程访问](/zh/docs/remote-access)。 **技能没有出现** 安装插件后需重启 Codex。确认三件事:已经添加 marketplace、已经通过 `codex plugin add` 或 `/plugins` 安装 `nowledge-mem@nowledge-community`,以及 `~/.codex/config.toml` 中包含 `[features] plugins = true`、`hooks = true` 和 `[plugins."nowledge-mem@nowledge-community"] enabled = true`。旧版宿主可能还需要 `plugin_hooks = true`;请重新运行 setup 让它检测,不要手工猜测。如果你是项目内本地源方案,使用 `[plugins."nowledge-mem@local"]`。 **Codex 提示 `unknown field description, expected hooks`** 把插件更新到 `0.1.19` 或更新版本,然后重启 Codex: ```bash (codex plugin marketplace remove nowledge-community || codex marketplace remove nowledge-community || true) codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin codex plugin add nowledge-mem@nowledge-community ``` 这个提示来自 Codex 的严格 hook 解析器:它不接受 `hooks/hooks.json` 里的额外元数据。当前版本已经让这个文件只保留 Codex 需要的 hook schema。 **在 WSL 里使用 Codex** 请在实际运行 Codex 的同一个 WSL 发行版里安装和更新插件。Windows 桌面端可以提示 WSL 里的 Codex 插件已过期,但不能安全地替你在 Windows 侧执行更新,因为 shell、插件缓存、Python 和 `~/.codex` home 都不是同一个环境。请从 Mem 复制更新命令,在 WSL 终端里运行,然后重启那里的 Codex。 **启动上下文或 Codex 线程没有自动出现** 重新运行 hook setup,然后重启 Codex: ```bash HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" test -n "$HOOK_SETUP" && python3 "$HOOK_SETUP" ``` setup 会开启当前的 hook 功能,只在宿主仍暴露旧版 plugin-hook gate 时添加兼容开关,并为仍需要 `~/.codex/hooks.json` 的 Codex 版本保留宿主级 Stop 兜底。打开 `/hooks`,确认 Nowledge Mem 的 SessionStart、UserPromptSubmit 和 Stop hook 均已启用并受信任。信任确认必须由用户完成,setup 不会绕过它。 **`codex mcp list` 显示 `Not logged in`** 先更新 `nmem`,确保它和你的 Mem app/server 版本一致。如果你使用本机桌面版 Mem,请在桌面端重新安装 CLI 配置,然后重新运行 hook setup: ```bash pip install -U nmem-cli nmem status HOOK_SETUP="$(find ~/.codex/plugins/cache -path '*/nowledge-mem/*/scripts/install_hooks.py' -print 2>/dev/null | sort | tail -1)" test -n "$HOOK_SETUP" && python3 "$HOOK_SETUP" ``` 不要运行 `codex mcp login nowledge-mem`。这个命令是给 OAuth MCP 服务器用的。Nowledge Mem 的 Codex 路径使用 `nmem config mcp show --host codex` 生成的 URL 和 headers。 **显示 "plugin is not installed"** 先运行 `codex plugin marketplace add nowledge-co/community --sparse .agents --sparse nowledge-mem-codex-plugin`(旧版 Codex 用 `codex marketplace add nowledge-co/community`),再用 `codex plugin add nowledge-mem@nowledge-community` 或 `/plugins` 安装,然后检查 `~/.codex/config.toml` 里的插件 key 是否正确。 **只会读取 Working Memory,不继续搜索或蒸馏** 请先把插件更新到 `0.1.26` 或更高版本,重新运行 hook setup,并确认 Codex 能看到内置的 `nowledge-mem` MCP 与 UserPromptSubmit hook。如果你开启了 Codex 本地 Memory,请关闭 **Allow memory generation from tool-assisted tasks**。需要更强的仓库级行为时,再把插件里的 `AGENTS.md` 合并到项目根目录。如果 Mem 在远程机器上,或本地端口不是默认值,请在 `~/.codex/config.toml` 中添加 `mcp_servers.nowledge-mem` 来覆盖内置地址。 ## 相关内容 [#相关内容] * [连接总览](/zh/docs/integrations) * [Nowledge FS](/zh/docs/nowledge-fs) * [Gemini CLI](/zh/docs/integrations/gemini-cli) * [Claude Code](/zh/docs/integrations/claude-code) * [远程访问](/zh/docs/remote-access) # Copilot CLI (/docs/zh/integrations/copilot-cli) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Copilot CLI 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` ```bash title="一分钟安装" copilot plugin marketplace add nowledge-co/community copilot plugin install nowledge-mem@nowledge-community ``` Copilot CLI 支持插件和生命周期钩子。安装一次插件、确保本地能调用 nmem,Copilot 就可以在开局读取 Working Memory,在需要时 搜索过去上下文,并在宿主压缩或关闭会话前把新内容追加进 Mem。 这是 GitHub Copilot CLI 对应的专属 Nowledge 路径。它比通用 MCP 更完整: 插件自带 hooks、skills 和会话捕获运行时。但它又不像 OpenClaw 那样几乎把 行为都塞进宿主生命周期里,Copilot 仍然需要依赖模型去决定何时调用技能。 所以如果你希望它更主动地检索和蒸馏,项目里的 `AGENTS.md` 依然很重要。 启动一个新的 Copilot 会话,问一句 What was I working on?。 如果能看到最近的重点和优先事项,再让 Copilot 保存或 checkpoint 当前会话, 并确认这条线程出现在 Mem 里,这条路径就接通了。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行([安装指南](/zh/docs/installation)),或你已经有可访问的远程 Mem 服务 * 已安装 GitHub Copilot CLI * `nmem` CLI 在你的 `PATH` 中 ## 设置 [#设置]
### 安装 `nmem` [#安装-nmem-step] ```bash # 方式一:使用 Mem 桌面应用附带的 CLI # 设置 → 偏好设置 → 开发者工具 → 安装 CLI # 方式二:pip pip install nmem-cli # 方式三:pipx pipx install nmem-cli ``` 然后先确认: ```bash nmem status ``` 如果你在 Windows 或 Linux 上使用 Nowledge Mem 桌面应用,`nmem` 一般已经随应用提供。
### 安装插件 [#安装插件-step] ```bash copilot plugin marketplace add nowledge-co/community copilot plugin install nowledge-mem@nowledge-community ``` 安装完成后重启 Copilot CLI。 插件现在会直接从自己打包好的 `hooks/` 目录运行会话捕获。 如果你本地已经有旧版留下的兼容副本,也仍然可以回退到 `~/.copilot/nowledge-mem-hooks/`。
### 在 WSL 里桥接 `nmem`(按需) [#在-wsl-里桥接-nmem按需step] 如果 Copilot CLI 跑在 WSL 里,而 `nmem` 是通过 Windows 上的 Mem 桌面应用提供的, 就在 WSL 中创建下面这个桥接脚本: ```bash mkdir -p ~/.local/bin && cat > ~/.local/bin/nmem << 'SHIMEOF' #!/bin/bash python3 - "$@" <<'PY' import subprocess import sys cmd = subprocess.list2cmdline(["nmem.cmd", *sys.argv[1:]]) raise SystemExit(subprocess.run(["cmd.exe", "/s", "/c", cmd]).returncode) PY SHIMEOF chmod +x ~/.local/bin/nmem ``` 这样 WSL 里的 Copilot 也能干净地调用 Windows 侧的 `nmem`。
### 想让 Copilot 更主动时,加上项目引导 [#想让-copilot-更主动时加上项目引导-step] 插件会自己处理 Working Memory 启动和会话捕获。如果你还希望 Copilot 在 这种经常续接历史任务的仓库里更主动地搜索或蒸馏,把插件里的 `AGENTS.md` 合并到项目根目录: ```bash git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community cp /tmp/nowledge-community/nowledge-mem-copilot-cli-plugin/AGENTS.md ./AGENTS.md rm -rf /tmp/nowledge-community ``` 如果仓库里已经有 `AGENTS.md`,请合并 Nowledge 相关部分,而不是直接覆盖。
### 需要远程 Mem 时配置 [#需要远程-mem-时配置-step] ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` 这会写入插件和 `nmem` 共用的本地客户端配置。
## 自动发生的事 [#自动发生的事] 插件会通过 Copilot CLI hooks 做五件事: * **SessionStart** 在 startup、resume、clear 时:先用 `nmem --json context --source-app copilot-cli` 读取 Context Bundle,再回退到 Working Memory * **SessionStart** 在 compaction 后:重新读取 Context Bundle 或 Working Memory,并提醒 Copilot 保存重要进展 * **UserPromptSubmit**:把搜索与保存提示放到每一轮附近 * **Stop**:在每次回复结束后,异步捕获当前 Copilot 会话 * **PreCompact** 和 **SessionEnd**:在压缩前、会话关闭时捕获最新会话记录 这些捕获钩子只会追加新的对话内容,不会每次都把整段历史重新导入。 ## Skills [#skills] Copilot 这条连接刻意保持了一个更简单的用户表面。它不再额外附带一层独立的 命令文档,而是依赖 skills 和底层的 `nmem` CLI。 | Skill | 什么时候有用 | 它做什么 | | --------------------- | ------------------------------------ | ----------------------- | | `read-working-memory` | 会话开始,“我最近在做什么?” | 读取当天的 Working Memory 简报 | | `search-memory` | 需要过去工作、过去理由、过去讨论时 | 搜索持久记忆和历史线程 | | `distill-memory` | 出现了真正值得留下的决策或经验 | 把长期知识保存进 Mem | | `save-thread` | “Save this session”“Checkpoint this” | 在明确请求时保存一条简洁的会话摘要线程 | 如果你只是想直接排查连接问题,可以在终端里运行 `nmem status`。 ## 更新 [#更新] ```bash copilot plugin marketplace add nowledge-co/community copilot plugin marketplace update nowledge-community copilot plugin update nowledge-mem ``` 然后重启 Copilot CLI。 ## 安全地自定义 [#安全地自定义] 优先使用 Copilot 自己的 instruction files,而不是去改已安装插件: * 仓库共享规则放 `.github/copilot-instructions.md` 或 `.github/instructions/*.instructions.md` * 跨仓库的个人规则放 `~/.copilot/copilot-instructions.md` 完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 常见问题 [#常见问题] **找不到 `nmem`** 用 `pip` 或 `pipx` 安装 `nmem-cli`,或者直接使用 Mem 桌面应用附带的 CLI。 **看不到 Working Memory** 安装后先重启 Copilot CLI。然后运行 `nmem status`,确认本地客户端确实能连到 Mem。 **线程没有出现在 Mem 里** 安装或更新后先重启 Copilot CLI,再检查 `~/.copilot/nowledge-mem-hooks/hook-log.jsonl`。 如果你用的是旧版安装方式,或者正在本地开发插件,也仍然可以从源码目录手动运行 `scripts/install-hooks.sh` 作为兼容回退。 **Copilot 只会读取启动上下文,不太会继续搜索或蒸馏** 这通常说明启动钩子已经正常工作,但仓库里给 Copilot 的行为引导还不够强。 把插件里的 `AGENTS.md` 合并到项目根目录,再用 continuation 型问题重试。 ## 相关内容 [#相关内容] * [连接总览](/zh/docs/integrations) * [Codex](/zh/docs/integrations/codex-cli) * [Claude Code](/zh/docs/integrations/claude-code) * [远程访问](/zh/docs/remote-access) # Craft Agent × Nowledge Mem (/docs/zh/integrations/craft-agent) 完成设置后,把这句话发给 Craft Agent: ```text 读取 nowledge-mem source 里的 Nowledge Mem guide,检查 Mem 是否可用,并告诉我你能看到哪些上下文。 ``` Craft Agent 可以通过自己的 workspace source 系统使用 Nowledge Mem。source 提供 Mem MCP 工具;guide 告诉 Craft 什么时候读取 Working Memory、什么时候搜索历史决策、什么时候保存值得长期保留的知识。 如果你要保存真实对话记录,请使用 CLI 导入。Craft 会把会话保存在本机 `session.jsonl` 里;`nmem` 在运行 Craft 的机器上读取这些文件,再把规范化后的线程上传到本机或远程 Mem。 ## 开始前 [#开始前] * Nowledge Mem 已在本机运行,或你有可访问的远程 Mem * 已安装 Craft Agent * `nmem` 在运行 Craft Agent 的同一台机器上可用 ```bash nmem status ``` ## 设置 [#设置] 生成 Craft source 和 guide: ```bash nmem config mcp show --host craft-agent ``` 在你要连接的 Craft workspace 里: 1. 创建 `sources/nowledge-mem/`。 2. 把生成的 `sourceConfig` JSON 保存为 `sources/nowledge-mem/config.json`。 3. 把生成的 guide markdown 保存为 `sources/nowledge-mem/guide.md`。 4. 重启或重新加载 Craft Agent。 如果使用远程 Mem,先配置共享 `nmem` 客户端,再重新生成: ```bash nmem config client set url https://your-server nmem config client set api-key your-key nmem config mcp show --host craft-agent ``` ## 验证 [#验证] 问 Craft: ```text Nowledge Mem 连接好了吗?读取我的 Working Memory 或 Context Bundle,并总结当前重点。 ``` 如果 Craft 能从 `nowledge-mem` source 调用 Mem 工具,并能看到当前上下文,就说明连接成功。 ## 导入 Craft 会话 [#导入-craft-会话] 当你想把真实 Craft transcript 保存进 Mem 时,先预览: ```bash nmem t sync --from craft-agent --all-projects --limit 20 ``` 再导入: ```bash nmem t sync --from craft-agent --all-projects --apply ``` 导入器会扫描 Craft config 目录下的 workspaces。能读到 workspace header 时会用它做项目匹配,并写入稳定的 `craft-agent-*` thread ID;重复运行会去重追加,不会制造重复线程。 常用过滤: ```bash nmem t sync --from craft-agent --session-dir ~/.craft-agent/workspaces --limit 20 nmem t sync --from craft-agent --space work --apply ``` 如果你的 Craft config 不在默认位置,可以设置 `CRAFT_CONFIG_DIR`,或直接传 `--session-dir`。 ## 哪些是自动的 [#哪些是自动的] 只要 source 和 guide 可用,Craft 就可以主动使用记忆工具;目前不需要为 Craft 单独发布 Nowledge npm 包。workspace source 负责 MCP 接入,`nmem t sync --from craft-agent` 负责真实 transcript 导入。 如果 Craft 后续提供稳定 lifecycle hook,Nowledge Mem 可以在同一个 `craft-agent` source 名称上增加实时捕获。在此之前,请把真实会话捕获视为显式 CLI 导入。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations) * [对话](/zh/docs/threads) * Craft Agent repo: [craft-ai-agents/craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss) # Cumora (/docs/zh/integrations/cumora) Cumora 是一个 AI teammate 工作区。它的 Agent 有 persona,可以主动开启对话,也可能有自己的内部记忆。 Nowledge Mem 不应该替代这些能力。它应该给每个 Cumora teammate 接入同一个跨工具、跨场景的长期知识层:Codex、Claude Code、Pi、OpenClaw、浏览器、笔记和 Library 都能共享的那一层。 关键规则:如果多个 Cumora teammate 共用同一个电脑级 daemon,不要给这个 daemon 设置一个统一的 `NMEM_AGENT_ID`。如果 Atlas、Iris、Bram、Nova 都继承同一个 daemon 身份,Mem 会把它们当成同一个 teammate。这比不设置身份更糟。 ## 当前最好的路径 [#当前最好的路径] 分两步设置: 1. 先连接 Cumora 启动的 AI coding tool。 2. 再给每个 Cumora Agent persona 加一小段 Mem 身份说明。 即使 Cumora 目前每台电脑只有一个本地 npx 或 daemon 命令,这个方式也能工作,因为身份由 Agent 的指令选择,而不是由共享 daemon 的环境变量选择。 ## 连接运行时 [#连接运行时] 在 Cumora 启动 AI 工具的那台电脑上安装并检查 Nowledge Mem: ```bash nmem status ``` 然后连接 Cumora 启动的工具,例如 Codex 或 Claude Code: * [Codex](/zh/docs/integrations/codex-cli) * [Claude Code](/zh/docs/integrations/claude-code) * [Pi](/zh/docs/integrations/pi) 这样这个工具就能用上 Mem 的工具、Context Bundle / Working Memory,以及它自己支持的会话同步 hooks。比如 Cumora 启动的是 Codex 或 Claude Code,且对应连接已经装好,那么这些工具里的会话就能通过 Nowledge Mem hooks 同步。 ## 添加 Persona Bridge [#添加-persona-bridge] 为每个长期存在的 Cumora teammate 创建一个 Mem 身份: ```bash nmem agents upsert atlas \ --name "Atlas" \ --default-space research \ --instructions "Research across the user's knowledge. Cite sources and separate facts from interpretation." ``` `Atlas` 是展示名称。`atlas` 是稳定 ID。这个命令只是创建身份记录;只有 Cumora persona 传入 `agent_id="atlas"`,或未来每 Agent 环境设置了 `NMEM_AGENT_ID=atlas` 时,才会使用这个身份。 然后把下面这段加入这个 Cumora Agent 的 persona 或 system prompt: ```text Nowledge Mem: - 每个任务开始时,用 agent_id="atlas" 读取 Context Bundle。 - 如果工具支持,也传入 host_agent_id="cumora:atlas"。 - source_app 保持为实际子运行时,例如 "codex" 或 "claude-code"。 - 后续 Nowledge Mem 调用继续传入 agent_id="atlas",这样 memory_search、thread_search、read_working_memory 和 memory_add 会使用同一个身份和默认 Space。 - 遇到跨对话仍然重要的决定、偏好和流程时,保存为长期记忆。 ``` 如果 Agent 只有 CLI 权限,对应命令是: ```bash nmem --json context --agent-id atlas --host-agent-id cumora:atlas --source-app codex ``` 后续命令使用返回的 active space: ```bash nmem --json m search "recent research decisions" --space research nmem --json m add "Atlas learned that ..." -t "Research note" --space research -s codex ``` 如果 Agent 有 MCP 权限,优先直接传入 `agent_id`: ```text read_context_bundle(agent_id="atlas", source_app="codex", host_agent_id="cumora:atlas") read_working_memory(agent_id="atlas", source_app="codex", host_agent_id="cumora:atlas") memory_search(query="recent research decisions", agent_id="atlas", source_app="codex") thread_search(query="last onboarding discussion", agent_id="atlas", source_app="codex") memory_add(content="Atlas learned that ...", title="Research note", agent_id="atlas", source_app="codex") ``` 在 Cumora 提供按 Agent 区分的运行时环境变量或官方集成点之前,这是最干净的兜底做法。 ## 如果 Cumora 支持每 Agent 环境变量 [#如果-cumora-支持每-agent-环境变量] 如果以后 Cumora 允许为每个 Agent 设置运行时环境变量,就把身份从 persona prompt 移到这个每 Agent 环境里: ```bash NMEM_AGENT_ID=atlas NMEM_HOST_AGENT_ID=cumora:atlas ``` 除非这个 daemon 只属于一个 Cumora teammate,否则不要在共享 daemon 上设置这些变量。 ## 哪些会同步 [#哪些会同步] 受支持的 AI 工具会话可以同步。如果 Cumora 启动的是 Codex、Claude Code、Pi、OpenClaw 或其他带 Nowledge Mem 连接的工具,就使用那个工具自己的同步路径。 Cumora 自己的历史是另一件事。除非 Cumora 暴露本地 API、导出、hook 或每 Agent 运行时集成点,Nowledge Mem 不能直接导入 Cumora 房间或 Cumora 内部 Agent memory。 在那之前,Cumora 自己的内部记忆仍然留在 Cumora 内部。Nowledge Mem 负责连接后的 AI 工具、用户保存的记忆、笔记和 Library,作为用户的跨工具、跨 Agent 长期知识层。 ## 下一步 [#下一步] * [自定义连接行为](/zh/docs/integrations/customize-behavior) * [Raft](/zh/docs/integrations/raft) * [Multica](/zh/docs/integrations/multica) # Cursor (/docs/zh/integrations/cursor) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Cursor 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` 现在最可靠的路径是把插件放到 `~/.cursor/plugins/local/nowledge-mem-cursor`。即使 Marketplace 还没通过,这条路也可以直接给用户使用。 如果将来 **Nowledge Mem** 出现在你的 Cursor Marketplace 账号里,你再切过去即可。下面这条本地安装路径才是现在面向用户的真实可用路径。 对用户来说,最重要的好处很直接:装一次,开一个新的智能体会话,规则、技能、启动钩子和 MCP 连线就一起到位了。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行([安装指南](/zh/docs/installation)),或你已经有可访问的远程 Mem 服务 * 已安装 Cursor IDE * 推荐:如果你希望在会话开始时自动带上 Working Memory,并在需要时创建可恢复交接摘要,请让 `nmem` 出现在 `PATH` 中 如果 Nowledge Mem 已经在同一台机器上的桌面应用中运行,最省事的方式仍然是 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**。这样 Cursor 就可以在会话开始时加载 Context Bundle 或 Working Memory,也能在需要时通过终端工具调用 `nmem`。 如果你要导入真实的 Cursor Agent 历史会话,Mem 会读取 Cursor 本地 `~/.cursor/projects` 里的 Agent transcript。桌面端在同一台机器上可以自动同步;如果你想手动补导历史,先预览: ```bash nmem t sync --from cursor --all-projects ``` 确认列表没问题后再导入: ```bash nmem t sync --from cursor --all-projects --apply ``` 只导入某一个项目时,也可以直接指定它的 transcript 目录: ```bash nmem t sync --from cursor --session-dir ~/.cursor/projects/Users-me-project/agent-transcripts --apply ``` ## 一分钟安装 [#一分钟安装]
### 克隆或进入插件仓库 [#克隆或进入插件仓库-step] ```bash git clone https://github.com/nowledge-co/community.git cd community ```
### 复制到 Cursor 的本地插件目录 [#复制到-cursor-的本地插件目录-step] ```bash mkdir -p ~/.cursor/plugins/local rm -rf ~/.cursor/plugins/local/nowledge-mem-cursor cp -R nowledge-mem-cursor-plugin ~/.cursor/plugins/local/nowledge-mem-cursor ``` 如果你为了本地迭代想试软链接,也可以: ```bash ln -s "$(pwd)/nowledge-mem-cursor-plugin" ~/.cursor/plugins/local/nowledge-mem-cursor ``` 但 Cursor 团队已经确认,本地插件的软链接解析现在实际还不稳定,所以面向用户时应优先用复制方案。
### 重新加载 Cursor [#重新加载-cursor-step] 重启 Cursor,或运行 **Developer: Reload Window**。 如果 Cursor 里看到的还是 Claude Code 风格文案、`save-thread`,或者 `beforeSubmitPrompt`、`stop` 这类钩子,先把旧的导入版 `nowledge-mem` 包从 Cursor 里移除。这个本地包正确加载后,只应该看到 `sessionStart` 和四个 Nowledge Mem skills。本地包专门使用 `nowledge-mem-cursor` 这个插件 id,就是为了避开这个导入包的命名冲突。
### 开启新的智能体会话 [#开启新的智能体会话-step] 打开一个新的智能体会话。 对于同机默认配置,插件内置的这些内容就是预期的零配置路径: * 插件清单 * 常驻规则 * 技能 * 启动钩子 * 本地 `mcp.json` 如果已经安装了 `nmem`,这个启动钩子会在新会话开始时把 Context Bundle 先带进上下文;旧版 CLI 会自动回退到 Working Memory。
### 仅在远程 Mem 时配置 MCP [#仅在远程-mem-时配置-mcp-step] 只有在你使用远程 Mem 时,才打开 **Settings**(`Cmd/Ctrl+Shift+J`)-> **Features** -> **Model Context Protocol**,然后更新 `nowledge-mem` 服务器的 URL 与 headers。 如果你还希望 `sessionStart` 启动钩子和 `save-handoff` 技能也连接到远程 Mem,就需要把当前机器上的 `nmem` 客户端也指向同一个远程服务: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` 这里有两个独立通道: * Cursor 的 MCP 设置负责插件里的记忆工具 * `nmem config client ...` 负责这台机器上终端侧的启动简报和交接摘要能力
## 更新 [#更新] 如果你走的是本地插件目录: * 推荐复制方式:用新的 `nowledge-mem-cursor-plugin` 覆盖 `~/.cursor/plugins/local/nowledge-mem-cursor`,然后重新加载 Cursor * 可选软链接方式:更新 `community` 仓库后重新加载 Cursor;如果 Cursor 又不识别插件,就切回复制方式 如果以后 Marketplace 可用了,再从本地版本切过去即可。 ## 安全地自定义 [#安全地自定义] 想调整行为时,优先使用 Cursor 自己的规则文件: * `.cursor/rules/*.mdc` * `.cursorrules` Nowledge Mem 插件自带的规则应继续作为默认值保留,不要直接去改 `~/.cursor/plugins/...` 里的已安装插件文件。完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 第一次成功应该看到什么 [#第一次成功应该看到什么] 当下面几件事成立时,就说明插件已经接通了: * 你已经把插件放进 `~/.cursor/plugins/local/nowledge-mem-cursor` * 你重新打开了一个新的 Cursor 智能体会话 * 如果装了 `nmem`,一开始就能看到 Working Memory 已经进了上下文 * 同机默认配置下,不需要手改 MCP 就能工作 * 远程模式下,只要改好 `nowledge-mem` MCP 服务器地址,就能恢复同样的行为 * Cursor 里不再出现旧的 Claude 风格包界面,比如 `save-thread`、`beforeSubmitPrompt` 或 `stop` ## 你会得到什么 [#你会得到什么] * 打包好的 `.cursor-plugin/plugin.json` * 用于启动时加载 Context Bundle 或 Working Memory 的 `hooks/hooks.json` * 用于本地 Nowledge Mem MCP 连接的 `mcp.json` * 一条常驻规则,用来约束工作记忆简报、路由式检索、提炼与交接摘要语义 * 四个技能:`read-working-memory`、`search-memory`、`distill-memory` 与 `save-handoff` * 通过桌面端自动同步或 `nmem t sync --from cursor` 导入真实 Cursor Agent transcript ## 新用户真正关心的事 [#新用户真正关心的事] 对第一次安装的用户,真正要记住的就这么几条: * 本地 Mem:装好插件后直接开新会话 * 远程 Mem:装好插件后,把 `nowledge-mem` MCP 服务器改到远程地址;如果还想保留启动简报和交接摘要,再把 `nmem` 也指向同一个远程服务 * 想把体验拉满:保留 `nmem` CLI,让 Cursor 能在新会话开始时先带上 Context Bundle 或 Working Memory,也能在需要时生成交接摘要 ## 重要约束 [#重要约束] 这个包故意 **不** 暴露 `save-thread`。 Cursor 的插件侧目前仍然没有直接暴露实时 transcript hook,所以摘要型保存必须继续叫 `save-handoff`,不能伪装成 `save-thread`。真实 Cursor Agent 会话由 Mem 桌面端或 `nmem t sync --from cursor` 导入:它会读取本地 `agent-transcripts` JSONL 文件,并把新增消息去重追加到 Mem 线程里。 ## 包结构 [#包结构] 这个包已经按 Cursor 插件格式组织好: ```text .cursor-plugin/plugin.json rules/nowledge-mem.mdc skills/*/SKILL.md hooks/hooks.json hooks/session-start.mjs mcp.json ``` Cursor 的本地插件目录要求 `.cursor-plugin/plugin.json` 位于插件根目录。这个包已经满足这个约定,所以前面的本地安装流程就是现在可以直接给用户使用的正式路径。 ## 以后如果上架 Marketplace [#以后如果上架-marketplace] 如果未来 Cursor Marketplace 接受了这个插件,再安装 Marketplace 版本即可。上架前,优先使用本地插件目录。 ## 相关内容 [#相关内容] * [连接总览](/zh/docs/integrations) * [Claude Code](/zh/docs/integrations/claude-code) * [Gemini CLI](/zh/docs/integrations/gemini-cli) * [远程访问](/zh/docs/remote-access) # 安全地自定义连接行为 (/docs/zh/integrations/customize-behavior) 如果你调整了连接行为,这个改动不应该在下次插件升级时消失。 最稳妥的规则很简单:优先使用宿主自己提供的指令文件或设置入口,不要直接去改安装目录里的插件文件。 先找到你正在使用的工具,把一条小规则写进下面对应的位置。之后正常升级一次插件,确认这条规则还在生效。 ## 改在哪里最合适 [#改在哪里最合适] | 工具 | 建议放在这里 | 适合什么场景 | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | | **Codex** | 项目里的 `AGENTS.md` | 桌面端和 CLI 共用的仓库级记忆行为 | | **Claude Code** | 个人规则放 `CLAUDE.local.md`,共享规则放 `CLAUDE.md` | 个人偏好或团队共享规则 | | **Copilot CLI** | 仓库共享规则放 `.github/copilot-instructions.md` 或 `.github/instructions/*.instructions.md`,个人规则放 `~/.copilot/copilot-instructions.md` | Copilot 的共享或个人行为 | | **Cursor** | `.cursor/rules/*.mdc` 或 `.cursorrules` | 项目级 Cursor 规则 | | **Gemini CLI** | 项目 `GEMINI.md`,可选 `~/.gemini/GEMINI.md` | 仓库规则或个人默认规则 | | **Hermes Agent** | 仓库规则放 `HERMES.md`,个人规则放 `~/.hermes/SOUL.md` | 项目级或全局 Hermes 行为 | | **OpenCode** | 项目 `AGENTS.md`、`~/.config/opencode/AGENTS.md`,或 `opencode.json` 里的 `instructions` 文件 | OpenCode 的共享或个人行为 | | **Pi** | 项目 `AGENTS.md` | 项目级 Pi 行为 | | **OpenClaw** | OpenClaw 插件设置,以及 OpenClaw 自己的提示词或 Agent 配置 | 行为开关和额外提示 | | **Alma** | Alma 插件设置,以及可选的原生 `nowledge-mem` Skill | 回忆、捕获策略和补充指令 | | **Bub** | Bub 自己的运行提示或配置,再配合共享的 `nmem` 配置 | Bub 的行为和连接方式 | | **Droid** | Droid 自己的提示词或指令入口,再配合共享的 `nmem` 配置 | Droid 的行为和连接方式 | | **Raycast** | Raycast 偏好设置 | 启动器层面的固定行为,比如服务器地址、密钥、space | ## 不要这样做 [#不要这样做] * 不要直接修改安装目录里的插件文件,比如 `~/.codex/...`、`~/.copilot/installed-plugins/...`、`~/.cursor/plugins/...` 这些缓存路径。 * 不要在原地修改插件自带的 skills,然后期待升级后还能保留。 * 如果宿主根本不会读取某个文件名,就不要自己发明一个新的“覆盖文件”名字。 ## 什么才算真正配好了 [#什么才算真正配好了] 满足下面三点,就说明这条路径是稳的: 1. 你的自定义规则放在宿主真正会读取的位置。 2. 插件或扩展正常升级后,连接本身还能工作。 3. 升级后不需要再去改安装目录,你的行为调整依然生效。 ## 很适合先加的一条小规则 [#很适合先加的一条小规则] * “遇到回归问题时,先搜索以前的发布或修复记录。” * “用户用中文工作时,更倾向保存中文记忆。” * “当用户问‘我们之前怎么决定的’时,更主动地搜索历史对话。” 规则越短越好。目标是轻轻地调整行为,而不是重写整套连接说明。 ## 多智能体编排工具 [#多智能体编排工具] 如果另一个应用负责启动你的 Agent,请给每个长期运行的 worker 一个稳定的 Mem 身份,而不是让所有子进程共用默认身份。 ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "帮助用户完成 onboarding。一次只解释一个步骤。" ``` 这会创建名为 Cindy 的 Mem AI Identity。命令和环境变量里使用的 ID 是 `cindy`。这个命令只是创建身份记录;它不会让所有 Codex 会话都变成 Cindy。 然后在这个 worker 的环境变量里只需要配置: ```bash NMEM_AGENT_ID="cindy" ``` 这个身份是可迁移的。你可以把 Cindy 从 Raft 换到其他编排工具,或者把子运行时从 Codex 换成 Pi;只要新的运行时已经连接 Mem,并继续收到同一个 `NMEM_AGENT_ID`。 如果这个身份已经有默认 Space,就不需要再设置 `NMEM_SPACE`。只有当这个运行时需要整体覆盖默认 Space 时,再加 `NMEM_SPACE="onboarding"`。`source_app` 仍然代表子运行时本身。比如由编排工具启动的 Codex worker,读取 Context Bundle 时仍然是 Codex。`NMEM_HOST_AGENT_ID` 是高级外部别名,不是第二个必填身份字段。 如果你想要同一个 persona 的变体,创建一个新身份,例如 `cindy-reviewer`,而不是在每个启动器里改来改去。这个新身份可以从 Cindy 的规则开始,再独立演化。 带截图的 Raft 设置步骤见 [Raft](/zh/docs/integrations/raft)。 ## 下一步 [#下一步] * [连接总览](/zh/docs/integrations) * [Codex](/zh/docs/integrations/codex-cli) * [Claude Code](/zh/docs/integrations/claude-code) * [Copilot CLI](/zh/docs/integrations/copilot-cli) # Droid (/docs/zh/integrations/droid) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Droid 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` 先把 Nowledge 社区 marketplace 加到 Droid,再安装 `nowledge-mem@nowledge-community`,运行一次 `nmem status`,然后开始新的 Droid 会话。 Droid 会获得原生连接入口:工作记忆简报、路由式检索、提炼、状态检查和可恢复交接摘要。它现在**不会**声称自己支持 `save-thread`。 对 Nowledge Mem 来说,Droid 是很合适的宿主。Factory 插件可以把 hooks、commands 和 skills 收敛成一个统一入口,而底层的记忆执行仍然交给 `nmem`。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行([安装指南](/zh/docs/installation)),或你已经有可访问的远程 Mem 服务 * 已安装 Factory Droid * `nmem` 在你的 `PATH` 中 如果你已经在同一台机器上运行 Nowledge Mem 桌面应用,最省事的方式仍然是 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**。这样 Droid 就能直接调用 `nmem`,本地和远程都走同一套路径。 你也可以单独安装 `nmem`: ```bash # 方式一:pip pip install nmem-cli # 方式二:uvx curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version ``` ## 一分钟安装 [#一分钟安装]
### 添加 Nowledge 社区 marketplace [#添加-nowledge-社区-marketplace-step] ```bash droid plugin marketplace add https://github.com/nowledge-co/community ```
### 安装插件 [#安装插件-step] ```bash droid plugin install nowledge-mem@nowledge-community ```
### 运行一次 `nmem status` [#运行一次-nmem-status-step] 对于同机默认配置,它应该指向 `http://127.0.0.1:14242`。
### 开始新的 Droid 会话 [#开始新的-droid-会话-step] 插件会在会话开始时加载工作记忆简报,并把命令和技能带进 Droid。
## 更新 [#更新] ```bash droid plugin marketplace update nowledge-community droid plugin update nowledge-mem@nowledge-community ``` ## 安全地自定义 [#安全地自定义] Droid 目前还没有给这个包提供单独的持久化指引文件。 * 如果你想调整记忆风格或保存行为,优先用 Droid 自己的 prompt / instruction 入口 * 保持安装好的插件包不被本地修改,这样 marketplace 升级才干净 完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 你会得到什么 [#你会得到什么] * 在会话开始、恢复、清空上下文和 compact 后自动加载工作记忆简报 * 在记忆与历史会话之间做路由式检索 * 把真正值得长期保留的内容提炼成记忆 * 在需要中断或交接时,显式创建可恢复交接摘要 * 本地与远程都复用同一套 `nmem` 连接方式 ## 命令 [#命令] * `/nowledge-read-working-memory` * `/nowledge-search-memory` * `/nowledge-distill-memory` * `/nowledge-save-handoff` * `/nowledge-status` ## 远程 Mem [#远程-mem] 推荐的远程配置方式是: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` 这会写入这台机器上的共享客户端配置。这样 Droid 会和 Gemini、Codex、CLI 等路径保持同一套本地/远程契约。 ## 重要约束 [#重要约束] 这个包刻意只暴露 `save-handoff`,不暴露 `save-thread`。 这里的边界必须保持清楚: * `save-thread` 应该表示导入真实录制下来的整段会话 * `save-handoff` 表示保存一个可恢复的交接摘要 Droid 现在还没有真正的 Nowledge transcript 导入器,所以这个插件不会把摘要伪装成完整会话保存。 ## 本地仓库回退路径 [#本地仓库回退路径] 如果你更想先从本地 checkout 验证: ```bash git clone https://github.com/nowledge-co/community.git cd community droid plugin marketplace add . droid plugin install nowledge-mem@nowledge-community ``` 之所以这样可行,是因为 `community` 仓库在根目录发布了 Factory marketplace 清单,而 Droid 插件则作为其中一个独立包存在。 ## 相关内容 [#相关内容] * [连接总览](/zh/docs/integrations) * [对话](/zh/docs/threads) * [Cursor](/zh/docs/integrations/cursor) * [Gemini CLI](/zh/docs/integrations/gemini-cli) * [远程访问](/zh/docs/remote-access) # Gemini CLI (/docs/zh/integrations/gemini-cli) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Gemini CLI 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` Google 已用 **Antigravity CLI**(`agy`)取代 Gemini CLI。Gemini CLI 已于 **2026 年 6 月 18 日**停止为个人版账号提供服务。如果你正在迁移,请查看 [Antigravity CLI 指南](/docs/integrations/antigravity-cli) —— Nowledge Mem 扩展可通过 `agy plugin import gemini` 一键转换。 最顺手的方式是直接在官方 Gemini Extensions Gallery 安装 `Nowledge Mem`,重启 Gemini CLI,同时获得内置 MCP 工具和 `nmem` 生命周期捕获。 页面底部依然保留了 GitHub 和本地目录安装方式,但对大多数用户来说,上面的官方扩展路径已经是默认推荐。 对大多数用户来说,心智模型可以很简单:先从官方 Gallery 安装扩展,确认一次 `nmem` 正常,再开一个新的 Gemini 会话。扩展内置本地 MCP 连接,用于检索和写入记忆;`nmem` 继续负责钩子、真实线程保存、状态检查和远程客户端配置。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行([安装指南](/zh/docs/installation)),或你已经有可访问的远程 Mem 服务 * 已安装 Gemini CLI * `nmem` 在你的 `PATH` 中 如果你已经在同一台机器上运行 Nowledge Mem 桌面应用,最省事的方式是打开 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**。这样会把随应用附带的 `nmem` 安装到 PATH,并直接连上默认的本地 Mem 服务。 你也可以单独安装 `nmem`: ```bash # 方式一:pip pip install nmem-cli # 方式二:uvx curl -LsSf https://astral.sh/uv/install.sh | sh uvx --from nmem-cli nmem --version ``` ## 一分钟安装 [#一分钟安装]
### 在扩展库中找到 Nowledge Mem [#在扩展库中找到-nowledge-mem-step] 打开 **Gemini CLI Extensions Gallery**,搜索 **Nowledge Mem**。
### 安装并重启 [#安装并重启-step] 安装扩展,然后重启 Gemini CLI。
### 运行一次 `nmem status` [#运行一次-nmem-status-step] 对于同机默认配置,它应该指向 `http://127.0.0.1:14242 (default)`。
### 打开新的 Gemini CLI 会话 [#打开新的-gemini-cli-会话-step] 扩展会自动加载 `GEMINI.md`、发现命令、暴露内置 MCP 工具,并让技能在需要时可用。
## 更新 [#更新] ```bash gemini extensions update nowledge-mem-gemini-cli ``` 如果你更习惯通过扩展库更新,也可以直接在 Gemini CLI 扩展库里更新 Nowledge Mem。更新后记得重新开启一个新的 Gemini 会话。 ## 导入旧会话 [#导入旧会话] 自动捕获会从扩展安装完成后开始。如果你想把更早的 Gemini CLI 会话也导入 Nowledge Mem,先预览: ```bash nmem t sync --from gemini-cli --all-projects --limit 20 ``` 确认无误后再导入: ```bash nmem t sync --from gemini-cli --all-projects --apply ``` 如果只想导入某个项目,用 `-p /path/to/project` 代替 `--all-projects`。这个命令会读取本机 Gemini CLI 会话文件,并写入 `nmem` 当前配置的 Mem 服务器。 ## 安全地自定义 [#安全地自定义] 想调整行为时,优先使用 Gemini 自己的上下文文件: * 项目里的 `GEMINI.md` * 如果你想做个人默认规则,可用 `~/.gemini/GEMINI.md` 如果规则变长,可以继续用 `@file.md` 拆分。不要直接去改已安装扩展里的文件。完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 第一次成功应该看到什么 [#第一次成功应该看到什么] 当下面几件事成立时,就说明 Gemini 已经接通: * 你已经从 Gallery 成功安装扩展 * `nmem status` 可以正常返回 * 新开的 Gemini 会话里可以看到 Nowledge 命令 * `save-thread` 导入的是真实 Gemini 会话,长会话也会在压缩前和会话结束时保存 ## 远程 Mem [#远程-mem] 推荐的远程配置方式是: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` 这会写入这台机器上的共享客户端配置。`nmem t save --from gemini-cli` 会在运行 Gemini 的那台机器上读取本地 Gemini 会话文件,再把规范化后的线程消息上传到 Mem。远程 Mem 服务器不需要直接访问 `~/.gemini`。 如果你希望 Gemini 的 MCP 工具也连接远程 Mem,请在 Gemini `settings.json` 里定义同名的 `nowledge-mem` 服务器。Gemini 会优先使用用户配置,覆盖扩展内置的本地 MCP 地址: ```bash nmem config mcp show --host gemini-cli ``` 把生成的 JSON 放进 Gemini 的 `settings.json`。直接 MCP 客户端不会自动读取 `~/.nowledge-mem/config.json`;这一步能确保 Gemini MCP 和 `nmem` 指向同一台 Mem 服务器。 ## 你会得到什么 [#你会得到什么] * Gemini 原生的上下文注入、生命周期钩子、命令和技能 * 内置本地 MCP 工具,用于检索和写入记忆 * 通过 `nmem t save --from gemini-cli` 捕获完整会话,包括上下文压缩前和会话结束时 * 当内置命令不够时,仍然可以直接调用 `nmem` * 本地与远程共用一套清晰的 `nmem` 认证方式 ## 命令 [#命令] * `/nowledge:read-working-memory` * `/nowledge:search-memory ` * `/nowledge:distill-memory` * `/nowledge:save-thread` * `/nowledge:save-handoff` * `/nowledge:status` ## 真实会话保存 与 交接摘要 [#真实会话保存-与-交接摘要] Gemini 有两条不同的保存路径,而且应该继续严格区分: * `save-thread` 会通过 `nmem t save --from gemini-cli` 导入 Gemini 的真实会话记录 * `save-handoff` 会保存一个适合中断后继续的交接摘要 扩展还会在 Gemini 压缩上下文前、以及会话结束时运行同一条真实会话导入路径。这样完整对话可以被检索回来,而交接摘要也不会被误当成完整会话记录。 ## 手动安装 [#手动安装] 如果你更喜欢从 GitHub 或本地目录安装,可以使用下面这条路径: ```bash git clone https://github.com/nowledge-co/nowledge-mem-gemini-cli.git cd nowledge-mem-gemini-cli gemini extensions link . ``` Gemini 官方文档也支持 `gemini extensions install `(GitHub 或本地 source),以及 `gemini extensions link `(本地开发)。对大多数用户来说,上面的已上架官方扩展安装流程仍然是最简单的选择。 ## 相关内容 [#相关内容] * [连接总览](/zh/docs/integrations) * [Claude Code](/zh/docs/integrations/claude-code) * [Codex](/zh/docs/integrations/codex-cli) * [远程访问](/zh/docs/remote-access) # Grok Build (/docs/zh/integrations/grok) 这篇是 **Grok Build** 的连接指南,也就是带插件、hooks、skills 和本地 `~/.grok/` 会话文件的编程智能体。它不是 grok.com 或 x.com 里普通 Grok 网页聊天的安装方式。网页 Grok 对话请用 [浏览器扩展指南](/zh/docs/integrations/browser-extension) 或 [Grok Web 连接](/zh/integrations/grok-web)。 Nowledge Mem 通过 Grok Build 的插件系统接入。安装一次、重启 Grok Build 后,新的编程智能体会话可以在开始时读到你的 Mem 上下文,并把真实对话记录保存回 Mem。 ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Grok Build 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` 如果你希望 Grok Build 自己完成设置,把上面这段粘给它即可。也可以按下面的命令手动安装。 ## 怎么确认已经生效 [#怎么确认已经生效] 安装后,打开一个新的 Grok Build 会话,问一句:“我最近在做什么?”它应该能拿到 Context Bundle 或 Working Memory。正常对话一轮后,用下面的命令应该能找到刚才的会话: ```bash nmem t search "刚才 Grok Build 回答里的某个短语" --source grok ``` ## 准备工作 [#准备工作] * 已安装并登录 Grok Build * 运行 Grok Build 的这台机器上能执行 `nmem` * Nowledge Mem 桌面端在本机运行,或这台机器上的 `nmem` 已经指向你的远程 Mem 如果 Grok Build 和 Mem 桌面端在同一台 Mac 上,最简单的方式是到 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**。如果 Grok Build 跑在另一台机器上,请在那台机器安装独立 CLI: ```bash python3 -m pip install --user nmem-cli # 或 pipx install nmem-cli ``` ## 安装 [#安装] ```bash grok plugin install nowledge-co/community#nowledge-mem-claude-code-plugin --trust ``` 安装后重启 Grok Build。 这个包和 Claude Code 连接共用同一份插件包,因为 Grok Build 可以加载 Claude 兼容的插件结构。Hook 会在运行时识别 Grok Build,所以保存到 Mem 里的来源会是 `grok`,不会混成 Claude Code。 ## 更新 [#更新] ```bash grok plugin update nowledge-mem ``` 更新后重启 Grok Build。 ## 导入旧 Grok Build 会话 [#导入旧-grok-build-会话] 插件安装后会开始捕获新的会话。要补导入之前的 Grok Build 会话,先预览: ```bash nmem t sync --from grok --all-projects --limit 20 ``` 确认后再导入: ```bash nmem t sync --from grok --all-projects --apply ``` 如果只想导入某个项目,用 `-p /path/to/project` 替代 `--all-projects`。这个命令会读取本机 Grok Build 的 `~/.grok/sessions`,再通过当前 `nmem` 配置写入本地或远程 Mem。 ## 远程 Mem [#远程-mem] 如果 Mem 在另一台机器或远程服务上,先在运行 Grok Build 的机器上配置一次: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` Grok Build hook 仍然在本机读取会话文件,然后通过 `nmem` 上传到 Mem。远程 Mem 服务器不需要访问你的 `~/.grok` 目录。 ## 自定义行为 [#自定义行为] 不要修改 `~/.grok/installed-plugins` 里的插件文件。需要调整行为时,放到 Grok Build 自己读取的项目规则或项目说明文件里。 如果 Grok Build 是被多 Agent 工具启动的,并且这个 worker 代表一个长期稳定的 AI 身份,请在启动前设置 `NMEM_AGENT_ID=`。只有整次运行都应该固定到某个 Mem 空间时,才设置 `NMEM_SPACE`。 ## 这个连接会带来什么 [#这个连接会带来什么] * 会话开始时注入 Context Bundle / Working Memory * 记忆搜索与提炼的技能引导 * `/save`、`/search`、`/sum`、`/status` 命令 * Stop 与 PreCompact hook,会调用 `nmem t save --from grok` * 通过 `nmem t sync --from grok` 补导入历史会话 ## 排障 [#排障] **找不到 `nmem`** 请在运行 Grok Build 的同一台机器安装 CLI,然后执行 `nmem status`。 **Mem 里看不到 Grok Build 会话** 安装或更新后先重启 Grok Build。然后手动跑一次: ```bash nmem --json t save --from grok -p . ``` 如果这条命令能保存,会话连接就是通的;之后 hook 会继续捕获新会话。 **包里有 Claude Code 字样** 少数文件名会保留共享包的历史命名,这是正常的。运行时行为已经区分 Grok Build:Context Bundle 会使用 `--source-app grok`,会话保存会使用 `nmem t save --from grok`。 ## 相关 [#相关] * [Claude Code](/zh/docs/integrations/claude-code) * [Codex](/zh/docs/integrations/codex-cli) * [Cursor](/zh/docs/integrations/cursor) * [连接总览](/zh/docs/integrations) # Hermes Agent × Nowledge Mem (/docs/zh/integrations/hermes) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Hermes Agent 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` ```bash title="一键安装(插件模式)" bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) ``` ```powershell title="Windows PowerShell" irm https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.ps1 | iex ``` Hermes v0.7.0+ 支持记忆提供者插件。安装一次后,Working Memory 会在会话开始时加载,相关记忆会在每轮对话前浮现,并且 Hermes 会在对话进行中把清洗后的轮次同步成 Mem 线程。无需配置 SOUL.md 行为指引。 Hermes 现在要求新的记忆提供者放在核心 `hermes-agent` 仓库之外。本页安装脚本就是 Nowledge Mem 的正式支持路径:它会把提供者安装到 `~/.hermes/plugins/nowledge-mem/`,Hermes 会通过同一套记忆提供者生命周期加载它。 跨工具的知识,在每次 Hermes 会话中都可用。在 Claude Code 中做的决策、在 Cursor 中设定的偏好、在 ChatGPT 中获得的洞察,汇聚成一个知识图谱,随时可以调用。 安装插件并重启 Hermes 后,开始一个新会话。发一条包含唯一短语的消息,然后正常退出、执行 `/new` 或执行 `/reset`。运行 `nmem t search "这条短语" --source hermes` 应能找到被捕获的 Hermes 对话。如果你的 Mem 里已经有记忆,再问一句"我最近做了哪些决策?",Hermes 应该直接搜索你的知识图谱,不需要你指定工具。 插件会自动捕获安装后的新会话。如果你想导入已经存在于 `~/.hermes/state.db` 里的旧对话,请在安装 Hermes 的那台机器上运行历史同步: ```bash nmem t sync --from hermes # 只预览,不写入 nmem t sync --from hermes --apply # 导入到 Mem ``` 远程 Mem 也应该这样做:由你的电脑读取本地 Hermes 数据库,再把标准化后的线程上传到 `nmem status` 当前指向的 Mem 服务。 ## 准备工作 [#准备工作] * **Nowledge Mem** 已在本地运行([安装指南](/zh/docs/installation))或可访问的远程服务器 * **Hermes Agent** v0.7.0+(v0.6.x 可使用 MCP 模式) * **`nmem` CLI** 已在 `PATH` 中。如果桌面应用就在这台机器上,使用 **Settings → Preferences → Developer Tools → Install CLI**。如果是纯远程机器,执行 `pip install nmem-cli`。 ```bash nmem status # 确认 Nowledge Mem 正在运行 hermes --version # 确认 Hermes 可用 ``` ## 安装 [#安装]
### 插件安装(推荐) [#插件安装推荐-step] ```bash bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) ``` 安装原生记忆提供者插件。运行后重启 Hermes。 Windows 用户直接使用原生 PowerShell 安装器,不再需要 Git Bash 或 WSL: ```powershell irm https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.ps1 | iex ``` 也可以手动安装: 1. 将插件文件复制到 `~/.hermes/plugins/nowledge-mem/`: ```bash mkdir -p ~/.hermes/plugins/nowledge-mem cd ~/.hermes/plugins/nowledge-mem for f in plugin.yaml __init__.py provider.py client.py; do curl -sLO "https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/$f" done ``` 2. 在 `~/.hermes/config.yaml` 中设置提供者: ```yaml memory: provider: "nowledge-mem" ``` 3. 重启 Hermes。
### MCP 模式(Hermes \< v0.7.0) [#mcp-模式hermes--v070-step] 如果你使用较早版本的 Hermes,或者偏好标准 MCP 连接: ```bash bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) --mcp ``` ```powershell title="Windows PowerShell" & ([scriptblock]::Create((irm https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.ps1))) -Mcp ``` 这会在 `config.yaml` 中添加 MCP 服务器配置,并将行为指引写入 `~/.hermes/SOUL.md`。工具名称带有 `mcp_nowledge_mem_` 前缀。 MCP 模式下,如果缺少行为指引,Hermes 虽然能访问工具,但不会主动使用。如果 Hermes 能检索记忆却从不主动保存,通常就是指引缺失。插件模式不需要额外的 SOUL 指引,因为这部分提示已经内置在提供者里。
### 验证 [#验证-step] 先用一个空库也能通过的检查验证对话捕获。请 Hermes 回复一条固定短语: ``` 请回复:hermes nmem smoke test ``` 然后正常退出 Hermes,或执行 `/new` / `/reset`,让 Hermes 做最后一次对话刷新。在终端里检查: ```bash nmem t search "hermes nmem smoke test" --source hermes ``` 你应该能看到来源为 Hermes 的对话。随后,如果你的 Mem 里已经有记忆,再问一个依赖过去工作的问题: ```text 我最近做了哪些决策? ``` 插件模式下,Hermes 应调用 `nmem_search`。MCP 模式下,应调用 `mcp_nowledge_mem_memory_search`。然后你可以让 Hermes 把结论存成记忆,或者观察它是否会在对话达到稳定结论时主动调用 `nmem_save`。
## 自动化行为 [#自动化行为] 插件接入了 Hermes 的记忆提供者生命周期,以下行为无需手动触发: * **Working Memory** 在每次会话开始时自动加载 * **相关记忆** 在每轮对话前自动浮现(主动召回) * **用户画像** 从 Hermes 内置记忆同步到跨工具知识图谱 * **会话记录** 会在轮次完成时同步成 Mem 线程,并在 Hermes 正常退出、开启新会话或重置会话时做最后一次增量刷新 * **压缩恢复提示** 会在当前 Hermes 版本实际消费 provider 压缩输出时生效 MCP 模式下,这些行为依赖 SOUL.md 中的行为指引,无法完全保证。 ## Hermes 记忆 vs Nowledge Mem [#hermes-记忆-vs-nowledge-mem] Hermes 自带的记忆系统存储 Hermes 会话中的特定信息。Nowledge Mem 是互补的:它存储跨工具的知识。两者配合使用: * **Hermes 记忆**:Hermes 特有的偏好、环境信息、工具习惯 * **Nowledge Mem**:决策、流程和经验,未来在任何工具中都应该知道的知识 插件会自动将 Hermes 中的用户画像同步到 Nowledge Mem,让跨工具知识保持一致。 ## 你能做什么 [#你能做什么] **在 Hermes 中查找其他工具的知识。** 问一句"数据库方案之前定了什么?",Hermes 会搜索你在 Claude Code、ChatGPT、Cursor 中积累的决策和洞察。 **保存知识,全局可用。** 在 Hermes 中得出结论后,你可以让它调用 `nmem_save` 保存到知识图谱;下次打开 Claude Code、Cursor 或 ChatGPT 时都能继续用。 **搜索历史对话。** 按关键词搜索所有工具中的历史对话,支持分页获取完整记录。 **让 Hermes 会话也可搜索。** 提供者会在对话进行中把清洗后的 `user` / `assistant` 轮次保存成 Mem 线程。正常退出、执行 `/new` 或 `/reset` 时,会再做一次最后的增量刷新。每个 Hermes `session_id` 第一次写入时导入线程,后续只追加新增轮次。 **补导入旧 Hermes 会话。** Hermes 的历史对话保存在 `~/.hermes/state.db`。先运行 `nmem t sync --from hermes` 预览,再加 `--apply` 导入。这个命令可以安全重复执行:它会复用 Hermes 的 `session_id` 作为 Mem 线程 ID,并在追加消息时去重。 MCP 模式下还可以使用图谱探索工具,追溯决策的演变过程和发现关联记忆。 ## 工具一览 [#工具一览] 插件模式使用简洁的 `nmem_` 前缀。MCP 模式使用 `mcp_nowledge_mem_` 前缀。 | 插件模式 | MCP 模式工具名 | 说明 | | ---------------------- | ---------------------------------------- | ------------- | | `nmem_search` | `mcp_nowledge_mem_memory_search` | 搜索记忆 | | `nmem_save` | `mcp_nowledge_mem_memory_add` | 保存或更新决策、洞察或经验 | | `nmem_update` | `mcp_nowledge_mem_memory_update` | 更新已有记忆 | | `nmem_delete` | `mcp_nowledge_mem_memory_delete` | 删除一条或多条记忆 | | `nmem_thread_search` | `mcp_nowledge_mem_thread_search` | 搜索历史对话 | | `nmem_thread_messages` | `mcp_nowledge_mem_thread_fetch_messages` | 获取对话消息 | MCP 模式还包含 `list_memory_labels`、`memory_neighbors` 和 `memory_evolves_chain`。待 `nmem` CLI 支持后会添加到插件中。 ## 配置 [#配置] 本地使用无需任何配置。插件使用共享的 `nmem` 客户端配置来读取服务器地址和 API 密钥。常规记忆操作走 `nmem`,较长的会话记录会直接发送到 Mem API。 如果 Nowledge Mem 桌面应用在同一台机器上,`nmem` 已经内置。远程环境下如果没有桌面应用,可以安装:`pip install nmem-cli`。 ### 远程访问 [#远程访问] 配置当前机器上的 `nmem` 客户端,让它指向远程服务器: ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` 这一步修改的是 Hermes 所在机器的客户端连接配置,不是 Mem 服务器端的 Access Anywhere 或局域网监听配置。 插件唯一的独立配置是请求超时,保存在 `~/.hermes/nowledge-mem.json`: ```json { "timeout": 60 } ``` ### Spaces [#spaces] Hermes 现在支持三种干净的 lane 设计: * `space`:当前 Hermes profile 固定使用一个 space * `space_by_identity`:把少量明确身份映射到命名好的 spaces * `space_template`:如果 Hermes 已经暴露稳定 identity,就按模板派生 space 如果这些都没配置,Hermes 仍然可以继承 `NMEM_SPACE`。 MCP 模式下,直接在 `config.yaml` 中更新地址: ```yaml title="~/.hermes/config.yaml" mcp_servers: nowledge-mem: url: "https://your-server/mcp" headers: Authorization: "Bearer your-key" timeout: 120 ``` 参见[随处访问 Mem](/zh/docs/remote-access)。 ## 更新 [#更新] 沿用你当前安装时选择的模式: * 插件模式,Hermes v0.7.0+ 的默认路径:不加参数重新运行 setup,然后重启 Hermes。 * MCP 模式,适合 Hermes v0.6.x 或你有意保留标准 MCP 接入:带 `--mcp` 重新运行 setup,然后重启 Hermes。 ```bash # 插件模式 bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) # MCP 模式 bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) --mcp ``` MCP 工具本身由 Nowledge Mem 提供,更新桌面应用后自动更新。Hermes 插件文件则通过这个 setup 脚本更新。 更新后,脚本会打印 Hermes 实际会加载的插件版本和线程导入端点: ```text Installed version: 0.5.18 Thread import endpoint: /threads/import ``` 如果这两行仍然显示旧版本或不同端点,说明 Hermes 正在读取另一个 `HERMES_HOME`。请把 `HERMES_HOME` 设为你启动 Hermes 时使用的 profile,再运行一次 setup,然后重启 Hermes。 ## 禁用或回退 [#禁用或回退] 修改文件前先退出 Hermes。 * 插件模式:把 `~/.hermes/config.yaml` 里的 `memory.provider` 改回你之前使用的 provider;如果你以前没有启用 Hermes memory,就删除这一行。然后删除 `~/.hermes/plugins/nowledge-mem`。如果旧版 Hermes 需要兼容副本,也删除 `~/.hermes/hermes-agent/plugins/memory/nowledge-mem`。 * MCP 模式:从 `~/.hermes/config.yaml` 删除 `mcp_servers.nowledge-mem` 配置块。如果你不再需要行为指引,也从 `~/.hermes/SOUL.md` 删除以 `# Nowledge Mem for Hermes` 开头的那段内容。 * 重启 Hermes,并运行 `hermes --version` 与 `nmem status`,确认 Hermes 和 Mem 客户端仍然正常。 ## 安全地自定义 [#安全地自定义] 优先使用 Hermes 自己的指引文件,而不是去改插件安装目录: * `~/.hermes/SOUL.md` 适合放个人默认习惯 * 项目根目录的 `HERMES.md` 适合放仓库级规则 不要直接修改 `~/.hermes/plugins/` 下已安装的 Nowledge Mem 插件文件。完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 常见问题 [#常见问题] **无法连接 Nowledge Mem。** 用 `nmem status` 确认服务器正在运行,检查地址是否匹配。 **Hermes 能检索但从不主动保存持久记忆(MCP 模式)。** 行为指引缺失。运行安装命令后重启 Hermes。指引需要在 `~/.hermes/SOUL.md`(每次会话都加载)或项目级 `HERMES.md`(在 git 根目录)中。插件模式下,检索和会话记录捕获都已经内置在提供者生命周期里,不需要额外指引。 **Hermes 线程没有出现在 Mem 里。** 提供者会在完整轮次结束后同步,并在真实会话边界再做一次刷新。请先完成一轮正常回复,再用正常退出、`/new` 或 `/reset` 验证。如果 Hermes 在一轮回复中途被强制杀掉,未完成的那一轮可能来不及进入提供者。 **Agent 说 `client.py` 和 community/main 不一致。** 通常是 Hermes 还在运行旧的本地插件副本。重新运行插件 setup,确认输出里有 `Thread import endpoint: /threads/import`,然后重启 Hermes。自定义行为请写到 `SOUL.md` 或 `HERMES.md`,不要改 `~/.hermes/plugins/nowledge-mem/` 里的插件文件。 **旧 Hermes 会话没有出现在 Mem 里。** 这是正常的,除非你运行过历史导入。桌面端 watcher 不会直接读取 Hermes 的 SQLite 数据库。先运行 `nmem t sync --from hermes` 预览 `~/.hermes/state.db` 中的旧会话,确认无误后再运行 `nmem t sync --from hermes --apply`。 **工具未出现(插件模式)。** 确认 `config.yaml` 中设置了 `memory.provider: "nowledge-mem"`,且插件文件存在于 `~/.hermes/plugins/nowledge-mem/`。重启 Hermes。 **工具未出现(MCP 模式)。** 确认 `config.yaml` 中有 `mcp_servers.nowledge-mem` 配置块。重启 Hermes。检查 YAML 格式是否正确。 **响应缓慢。** 默认超时为 30 秒。在 `nowledge-mem.json`(插件模式)或 `config.yaml`(MCP 模式)中调大超时值。如果问题持续,用 `nmem status` 检查服务器状态。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations) * [Claude Code](/zh/docs/integrations/claude-code) · [OpenCode](/zh/docs/integrations/opencode) · [Pi](/zh/docs/integrations/pi) · [OpenClaw](/zh/docs/integrations/openclaw) · [Alma](/zh/docs/integrations/alma) · [Bub](/zh/docs/integrations/bub) * 源码:[nowledge-mem-hermes](https://github.com/nowledge-co/community) # 连接 (/docs/zh/integrations) > API reference page. OpenAPI operation details could not be extracted from this page. # Kimi Code × Nowledge Mem (/docs/zh/integrations/kimi-code) 把这段发给 Kimi Code: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Kimi Code 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` Kimi Code 可以通过 Nowledge Mem 的 Kimi 原生插件读取上下文、搜索记忆、保存决策,并把 Kimi Code 对话同步到 Mem Threads。新版 Kimi Code 会直接读取插件 manifest 里的 hooks;安装、启用、`/reload` 之后,会话同步就会随 Kimi 的生命周期自动运行。 旧的 Kimi Code 会话仍然用同一条安全路径导入:先预览,再用 `nmem t sync --from kimi-code --apply` 写入。 这篇指南只针对 **Kimi Code**,也就是终端和 IDE 里的编码 Agent。Kimi 网页聊天请看[浏览器扩展](/zh/docs/integrations/browser-extension)。Kimi Work 是另一个桌面产品,并且使用独立的内置运行时;请按 [Kimi Work 指南](/zh/docs/integrations/kimi-work)进行设置。 ## 开始之前 [#开始之前] * Nowledge Mem 正在本机运行,或你有可访问的远程 Mem 服务 * 已安装 Kimi Code * Kimi Code 所在机器可以运行 `nmem` 0.9.19 或更新版本。Kimi Code 会话同步依赖 CLI 对 `--from kimi-code` 的支持。 ```bash nmem status nmem --version ``` 如果 `nmem` 已经存在,但不认识 `t sync --from kimi-code`、`config mcp show --host kimi-code`,或其它 Kimi 专用命令,请先更新同一个来源的 CLI,再排查 MCP 或会话同步: * 桌面端自带 CLI:打开 Mem,在 **设置 → 偏好设置 → 开发者工具 → 安装内置 CLI** 重新安装一次。 * PyPI CLI:`python3 -m pip install --user --upgrade nmem-cli` * pipx CLI:`pipx upgrade nmem-cli` 如果 Kimi Code 不在桌面端同一台机器上,先在那台机器安装独立 CLI: ```bash python3 -m pip install --user nmem-cli nmem --version nmem config client set url https://your-server nmem config client set api-key your-key ``` ## 安装插件 [#安装插件] 在 Kimi Code 里安装 Kimi Code 插件包: ```text /plugins install https://github.com/nowledge-co/community /plugins enable nowledge-mem /reload ``` community 仓库根目录有一个给 Kimi Code 用的 `kimi.plugin.json` shim,所以 GitHub 安装会直接加载 Kimi 插件包。Kimi 这里下载的是仓库 zip,不会 clone submodule。插件会带上 session-start skill,以及指向本机桌面端的 MCP 配置:`http://127.0.0.1:14242/mcp/`。 插件也会带上原生 lifecycle hooks:`Stop`、`SessionEnd`、`PreCompact`、`SubagentStop` 和 `Interrupt`。重新加载后,还可以直接使用这些命令: ```text /nowledge-mem:status /nowledge-mem:sync-now /nowledge-mem:import-history ``` 如果你使用远程 Mem,或本机 Mem 需要 API key,先生成 Kimi Code 的用户级 MCP 配置: ```bash nmem config mcp show --host kimi-code ``` 把生成的 `nowledge-mem` server 放进 `$KIMI_CODE_HOME/mcp.json` 或 `~/.kimi-code/mcp.json`。 如果你当前安装的 `nmem` 还不认识 `--host kimi-code`,先更新同一个来源的 CLI。临时处理时,也可以使用[连接概览](/zh/docs/integrations#direct-mcp)里的通用 streamable HTTP MCP 配置,并手动填入你的 Mem URL / API key。 ## 开启会话同步 [#开启会话同步] 新版 Kimi Code 会直接从 `kimi.plugin.json` 读取 Nowledge Mem 的 hook 声明。完成 `/reload` 后,Kimi Code 在一轮回复结束、会话退出、压缩上下文、subagent 完成任务,或本轮被中断时,都会尝试把本机会话同步进 Mem。 如果你用的是更早的 Kimi Code,插件 manifest 里的 hooks 没被加载,可以运行一次 fallback 安装脚本。它会把同样的 hook 规则写入你的 Kimi Code 配置,并保留原有设置: ```bash python3 ~/.cache/nowledge-community/nowledge-mem-kimi-code-plugin/scripts/install_hooks.py ``` ## 验证 [#验证] 重启 Kimi Code 后问: ```text Nowledge Mem 连上了吗?读取我当前的上下文。 ``` 只要 Kimi Code 能调用 Nowledge Mem MCP 工具,并返回 Context Bundle、Working Memory,或一个正常的空结果,就算成功。 再完成一段很短的 Kimi Code 对话,然后检查: ```bash nmem t list --source kimi-code -n 5 ``` hook 跑完后,你应该能看到最近的 Kimi Code 会话。如果这次工作用到了 Kimi subagent,subagent 的 wire log 也会进入同一个 thread,并保留来源标记。 ## 导入旧会话 [#导入旧会话] Kimi Code 会把本机会话存在 `~/.kimi-code/sessions`。导入命令是: ```bash nmem t sync --from kimi-code --limit 20 nmem t sync --from kimi-code --apply ``` 这条路径适用于本机 Mem,也适用于远程 Mem:`nmem` 在 Kimi Code 所在机器读取本机会话文件,再把标准化后的线程上传到你当前配置的 Mem 服务。重复执行也安全,Mem 会用稳定的 thread/message ID 去重。 ## 相关 [#相关] * [连接概览](/zh/docs/integrations) * [OpenCode](/zh/docs/integrations/opencode) · [Pi](/zh/docs/integrations/pi) · [ZCode](/zh/docs/integrations/zcode) * Kimi Code 源码:[MoonshotAI/kimi-code](https://github.com/MoonshotAI/kimi-code) # Kimi Work × Nowledge Mem (/docs/zh/integrations/kimi-work) 把这段发给 Kimi Work: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Kimi Work 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` Kimi Work 可以通过 Nowledge Mem 的 Kimi Work 连接器使用记忆。它会把 session-start skill 和本机 MCP 配置安装到 Kimi Work 内置的 Kimi Code 运行时里;这个运行时和你自己安装的 Kimi Code CLI 不是同一个目录。 Kimi Work 目前没有开放 lifecycle hook。所以 Mem 可以给 Kimi Work 提供上下文和记忆工具,但对话导入需要你主动执行:先预览,再用 `nmem t sync --from kimi-work --apply` 把 Kimi Work 历史写进 Mem Threads。 ## 开始之前 [#开始之前] * Nowledge Mem 正在本机运行,或你有可访问的远程 Mem 服务 * 已安装 Kimi Work Desktop * Kimi Work 所在机器可以运行 `nmem` 0.9.23 或更新版本 ```bash nmem status nmem --version ``` 如果 Kimi Work 不在桌面端同一台机器上,先在那台机器安装独立 CLI: ```bash python3 -m pip install --user nmem-cli nmem --version nmem config client set url https://your-server nmem config client set api-key your-key ``` ## 安装连接器 [#安装连接器] 如果你本机还没有 community 仓库,先取一份: ```bash git clone --depth 1 https://github.com/nowledge-co/community.git ~/.cache/nowledge-community ``` 安装到 Kimi Work 内置运行时: ```bash python3 ~/.cache/nowledge-community/nowledge-mem-kimi-work-connector/scripts/install_kimi_work_plugin.py ``` 脚本会优先使用 `KIMI_WORK_HOME`。如果没有设置,则使用 macOS 上 Kimi Work 的默认运行时目录: ```text ~/Library/Application Support/kimi-desktop/daimon-share/daimon/runtime/kimi-code/home ``` 安装后请重启 Kimi Work。 ## 远程 Mem 或带 API Key 的本机 Mem [#远程-mem-或带-api-key-的本机-mem] 连接器自带的 MCP 指向本机桌面端:`http://127.0.0.1:14242/mcp/`。 如果你使用远程 Mem,或本机 Mem 需要 API key,先生成 Kimi Work 的 MCP 配置: ```bash nmem config mcp show --host kimi-work ``` 把生成的 `nowledge-mem` server 放进 `$KIMI_WORK_HOME/mcp.json`,或放进上面默认运行时目录下的 `mcp.json`。 修改 MCP 配置后请重启 Kimi Work。 ## 验证 [#验证] 新开一段 Kimi Work 会话,问: ```text Nowledge Mem 连上了吗?读取我当前的上下文。 ``` 只要 Kimi Work 能调用 Nowledge Mem MCP 工具,并返回 Context Bundle、Working Memory,或一个正常的空结果,就算成功。 ## 导入 Kimi Work 会话 [#导入-kimi-work-会话] 先预览: ```bash nmem t sync --from kimi-work --limit 20 ``` 确认列表没问题后再导入: ```bash nmem t sync --from kimi-work --apply nmem t list --source kimi-work -n 5 ``` 这条路径适用于本机 Mem,也适用于远程 Mem:`nmem` 在 Kimi Work 所在机器读取本机会话文件,再把标准化后的对话上传到你当前配置的 Mem 服务。重复执行也安全,Mem 会用稳定的 thread/message ID 去重。 如果 Kimi Work 的会话目录不在默认位置,可以显式传入运行时 sessions 目录: ```bash nmem t sync --from kimi-work --session-dir "/path/to/kimi-work/home/sessions" --apply ``` ## Kimi Work 和 Kimi Code 的区别 [#kimi-work-和-kimi-code-的区别] Kimi Code CLI 和 Kimi Work 使用相近的底层会话格式,但它们不共享同一个 home 目录。 * 如果你用的是终端或 IDE 里的 Kimi Code,请看 [Kimi Code](/zh/docs/integrations/kimi-code)。它支持 hook 安装脚本,可以自动同步本机会话。 * 如果你用的是 Kimi Work Desktop,请按本页安装。它有 MCP 和启动指引,但没有 lifecycle hook,所以对话导入需要主动执行。 ## 相关 [#相关] * [连接概览](/zh/docs/integrations) * [导入已有对话](/zh/docs/import-existing-conversations) * [Kimi Code](/zh/docs/integrations/kimi-code) # Lody (/docs/zh/integrations/lody) Lody 通过 Agent Config 启动本地会话。这个配置会选择一个 AI 工具,例如 Claude Code 或 Codex,也可以把环境变量传给它。 这不等于一个长期在线的 teammate 身份。先把 Lody 当成会话和运行时的启动器。只有当你明确把某个 Lody Agent Config 用作稳定角色时,比如「reviewer」或「onboarding assistant」,才需要加 Mem AI Identity。 按这个规则处理: * 先连接 Lody 启动的 AI 工具,例如 Claude Code 或 Codex。 * 只有当这个 Lody Agent Config 代表稳定角色时,才添加 `NMEM_AGENT_ID`,例如 Cindy。 * 如果只是通用运行时 preset,就不要设置 `NMEM_AGENT_ID`。 ## 设置 [#设置] 先把 Lody 启动的 AI 工具连接到 Mem。例如安装 [Claude Code](/zh/docs/integrations/claude-code) 或 [Codex](/zh/docs/integrations/codex-cli) 连接。 如果这个 Agent Config 代表一个长期角色,再创建 Mem 身份: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "帮助用户完成 onboarding。一次只解释一个步骤。" ``` 这会创建名为 Cindy 的 Mem 身份。命令和环境变量里使用的 ID 是 `cindy`。这个命令不会让所有 Codex 会话都变成 Cindy;只有设置 `NMEM_AGENT_ID=cindy`,或明确传入 `agent_id="cindy"` 的地方,才会使用这个身份。 在这个 Lody Agent Config 里添加环境变量: ```bash NMEM_AGENT_ID=cindy ``` 如果这个 Lody config 只是一个通用 Codex 或 Claude 运行时 preset,就不要设置 `NMEM_AGENT_ID`。这样可以避免把每个 Lody 会话都误认为同一个长期的人。 如果你又创建了另一个 Lody config,但仍然代表同一个长期角色,就继续使用同一个 `NMEM_AGENT_ID`。如果运行时从 Codex 换成 Claude Code,更新运行时连接和 `--source-app`,不要改身份。 ## Space [#space] 默认不要设置 `NMEM_SPACE`。让身份自己的默认 Space 生效。只有当这个 Lody config 永远都应该读写同一个 Mem Space 时,才添加: ```bash NMEM_SPACE=onboarding ``` ## 高级宿主 ID [#高级宿主-id] 大多数用户不需要设置 `NMEM_HOST_AGENT_ID`。 只有当你需要把 Lody 内部稳定 ID(例如 `lody:`)映射到一个 Mem 身份时,才使用它。普通设置里,要么不设置身份,要么只在角色型 config 中使用 `NMEM_AGENT_ID=cindy`。 ## Fork [#fork] 如果同一个角色需要变成另一种工作方式,创建一个新的 Mem AI Identity,而不是把一个身份塞得太杂: ```bash nmem agents upsert cindy-reviewer \ --name "Cindy Reviewer" \ --instructions "Review code. Leave concise comments. Do not edit files unless asked." ``` 然后让对应的 Lody config 使用: ```bash NMEM_AGENT_ID=cindy-reviewer ``` ## 下一步 [#下一步] * [自定义连接行为](/zh/docs/integrations/customize-behavior) * [Raft](/zh/docs/integrations/raft) * [Multica](/zh/docs/integrations/multica) # MiMo Code × Nowledge Mem (/docs/zh/integrations/mimo-code) 把这段发给 MiMo Code: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 MiMo Code 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` MiMo Code 和 OpenCode 很接近,但包名、配置目录和生命周期 API 并不完全一样。实时记忆工具走 MCP;需要把 MiMo Code 的本地对话纳入 Mem 搜索时,使用 `nmem t sync --from mimo-code` 导入。 ## 开始之前 [#开始之前] * Nowledge Mem 正在本机运行,或你有可访问的远程 Mem 服务 * 已安装 MiMo Code * MiMo Code 所在机器可以运行 `nmem` ```bash nmem status ``` ## 设置 [#设置] 生成 MCP 配置: ```bash nmem config mcp show --host mimo-code ``` 把生成的 MCP server 加到 MiMo Code 的 MCP 配置或项目配置里。然后把 Nowledge Mem 指引加入项目说明,让 Agent 知道什么时候读取上下文、搜索记忆、保存决策。 ## 验证 [#验证] 重启 MiMo Code 后问: ```text Nowledge Mem 连上了吗?搜索这个项目相关的记忆。 ``` 只要 MiMo Code 能调用 Nowledge Mem MCP 工具并返回结果,或正常返回空结果,就算成功。 ## 会话捕获 [#会话捕获] MiMo Code 的本地对话保存在 `mimocode.db`。导入命令是: ```bash nmem t sync --from mimo-code --limit 20 nmem t sync --from mimo-code --apply ``` 这条路径适用于本机 Mem,也适用于远程 Mem:`nmem` 在 MiMo Code 所在机器读取本地数据库,再把标准化后的线程上传到你当前配置的 Mem 服务。 除非你是在做兼容性测试,否则不要直接把 OpenCode 插件包装到 MiMo Code。安全的实时连接需要遵守 MiMo Code 自己的插件和会话契约。原生包发布前,请使用这条导入路径;对话进行中如果需要马上可搜索的精简记录,再保存交接摘要。 ## 相关 [#相关] * [OpenCode](/zh/docs/integrations/opencode) * [Kimi Code](/zh/docs/integrations/kimi-code) · [ZCode](/zh/docs/integrations/zcode) · [OMP](/zh/docs/integrations/omp) * MiMo Code 源码:[XiaomiMiMo/MiMo-Code](https://github.com/XiaomiMiMo/MiMo-Code) # Multica (/docs/zh/integrations/multica) Multica 会启动本机的 AI 工具来运行命名 Agent,例如 Claude Code、Codex、Pi、OpenCode 或 OpenClaw。Nowledge Mem 应该接在这个被启动的 AI 工具上,然后再给每个长期存在的 Multica Agent 一个 Mem 身份。 这样一来: * 被启动的 AI 工具里的会话,可以通过该工具自己的 Nowledge Mem 连接和 hook 同步。 * MCP 要配置到 Multica Agent 上,不能只配在你当前打开的外层终端或另一个 Claude 会话里。 * 这个 Multica Agent 换 workspace、squad 或 AI 工具时,仍然沿用同一个 Mem 身份。 * Multica 自己的 workspace 历史是另一层。除非 Multica 提供导出、API 或 hook,否则 Mem 没法直接导入它。 ## 设置 [#设置] 先把 Multica 启动的 AI 工具连接到 Mem。例如在运行 Multica daemon 的机器上安装 [Codex](/zh/docs/integrations/codex-cli)、[Claude Code](/zh/docs/integrations/claude-code)、[Pi](/zh/docs/integrations/pi) 或 [OpenClaw](/zh/docs/integrations/openclaw) 连接。 如果这个 Multica Agent 使用 Claude Code,还要打开该 Agent 的 **MCP** 设置,把 Nowledge Mem 的 MCP 配置保存进去。Multica 启动 Claude Code 时,不会自动继承你外层终端或另一个 Claude 会话里的 MCP server。Multica 会把 Agent 里保存的 MCP 配置通过 `--mcp-config` 传给 Claude Code。 本机 Mem 可以使用这段配置: ```json { "mcpServers": { "nowledge-mem": { "url": "http://127.0.0.1:14242/mcp/", "type": "streamableHttp", "headers": { "APP": "Claude Code", "Authorization": "Bearer ", "X-NMEM-API-Key": "" } } } } ``` 你也可以直接生成当前机器的真实配置: ```bash nmem config mcp show --host claude-code --json ``` 如果使用远程 Mem,把 URL 换成你的 Access Anywhere MCP endpoint,并保留 Mem 配置里的 token headers。不要把 `--mcp-config` 写进 Multica custom args;当前 Multica 会从 Agent 的 MCP 配置生成这个参数。 创建 Mem 身份: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "帮助用户完成 onboarding。一次只解释一个步骤。" ``` 这会创建名为 Cindy 的 Mem 身份。命令和环境变量里使用的 ID 是 `cindy`。这个命令不会让所有 Codex 会话都变成 Cindy;只有设置 `NMEM_AGENT_ID=cindy`,或明确传入 `agent_id="cindy"` 的地方,才会使用这个身份。 然后把这个自定义环境变量添加到 Multica Agent: ```bash NMEM_AGENT_ID=cindy ``` 如果 Cindy 移动到另一个 Multica workspace、squad 或 AI 工具,继续保留她的 ID。只有当底层 AI 工具变化时,才更新对应连接。 ## 会同步什么 [#会同步什么] 只有被启动的 AI 工具有可用的 Nowledge Mem 连接或 hook 时,新会话才会自动同步。例如 Claude Code 和 Codex 使用各自的 Nowledge Mem 连接;Pi 使用 Pi package;OMP 使用 OMP 插件。 Multica 本身是编排层。它的 issue 评论、workspace 历史和任务时间线是另一类数据。只有当 Multica 以后提供消息级导出、API 或 hook 时,Mem 才能直接导入这些内容。 ## Space [#space] 除非分配给这个 Multica Agent 的每个任务都应该使用同一个 Mem Space,否则不要设置 `NMEM_SPACE`: ```bash NMEM_SPACE=onboarding ``` 如果这个 Agent 会跨多个 repo 或项目工作,让 Mem 身份自己的默认 Space 处理常见情况;只有明确需要时,再在具体任务里切换。 ## 安全 [#安全] 不要把高权限密钥放进 Multica Agent 的环境变量。`NMEM_AGENT_ID` 是安全的,因为它只是身份选择器。Mem API key、模型 provider key、生产 token 应该限制权限,并通过运行时或 Mem client config 管理。 ## 下一步 [#下一步] * [自定义连接行为](/zh/docs/integrations/customize-behavior) * [Lody](/zh/docs/integrations/lody) * [Cumora](/zh/docs/integrations/cumora) # OMP × Nowledge Mem (/docs/zh/integrations/omp) 把这段发给 OMP: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 OMP 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` 如果你希望 OMP 一启动就带上正确的 Mem 上下文,并在新对话完成后自动保存到 Mem,请安装 OMP 插件。 安装后,OMP 可以在启动时读取 Context Bundle 或 Working Memory,在任务中使用内置记忆技能,并把完成后的对话保存成 `source_app=omp` 的 Mem 线程。 不要给 OMP 安装 `nowledge-mem-pi`。OMP 来自 Pi 体系,但它有自己的插件命令、配置目录和来源标识。专用 OMP 插件会把 OMP 线程和 Pi 线程分开保存。 ## 开始之前 [#开始之前] * Nowledge Mem 正在本机运行,或你有可访问的远程 Mem 服务 * 已安装 OMP * OMP 所在机器可以运行 `nmem` ```bash nmem status ``` ## 设置 [#设置] ```bash omp plugin install nowledge-mem-omp ``` 安装或更新后重启 OMP,让扩展生命周期加载。 对大多数本机使用场景,这一步就是 OMP 侧唯一需要做的安装。 如果你还想让 OMP 直接调用 MCP 工具,或需要配置自定义远程 MCP endpoint,再生成可选的 OMP MCP 配置: ```bash nmem config mcp show --host omp ``` 把生成的 server 加到 OMP 的 MCP 配置。OMP 文档中常见位置包括项目 `.omp/mcp.json` 和用户级 `~/.omp/agent/mcp.json`。 ## 验证 [#验证] 重启 OMP 后问: ```text 读取我的 Nowledge Mem 上下文,并告诉我连接是否正常。 ``` 只要 OMP 能看到注入的 Context Bundle 或 Working Memory,就说明连接已经生效。完成一个正常 OMP 回合后,你还应该能在 Mem 里看到来源为 OMP 的线程。 ## 会话捕获 [#会话捕获] 新的 OMP 对话会由插件在 agent turn 完成后、压缩前、切换会话前和退出时自动捕获,保存为 `source_app=omp`。 只有在需要导入安装插件之前的旧 OMP 会话时,才需要运行同步命令。OMP 的旧会话默认保存在 `~/.omp/agent/sessions`: ```bash nmem t sync --from omp --limit 20 nmem t sync --from omp --apply ``` 这条路径适用于本机 Mem,也适用于远程 Mem:`nmem` 在 OMP 所在机器读取本地 JSONL 会话文件,再把标准化后的线程上传到你当前配置的 Mem 服务。 ## 相关 [#相关] * [Pi](/zh/docs/integrations/pi) * [OpenCode](/zh/docs/integrations/opencode) · [Kimi Code](/zh/docs/integrations/kimi-code) · [ZCode](/zh/docs/integrations/zcode) * OMP 文档:[omp.sh/docs](https://omp.sh/docs) # OpenClaw × Nowledge Mem (/docs/zh/integrations/openclaw) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 OpenClaw 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` ```bash title="一行安装" openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem ``` 配置好之后:你在 OpenClaw 里聊出来的内容会进 Mem,能搜得到;定时跑的那条线默认不会挤进「对话」列表。该留的重要时刻仍可提炼成带 `sourceThreadId` 的记忆,你在别的工具里存下来的知识也一样能被读到。 此外,Mem 不只是把文字堆在一起。相关知识会连成图谱,观点怎么变会有迹可循;开了后台处理后,工作记忆简报、冲突提示、多来源综合出的 crystals 也会回流到 OpenClaw。 最快的验证方式很简单:先记住一条事实,在新会话里把它问回来,再确认这段会话本身也已经成为可搜索的线程。 这个包现在已经发布在 ClawHub。想明确指定来源时,直接使用 `clawhub:` 前缀即可。若省略前缀,OpenClaw 也会优先从 ClawHub 解析,再回退到 npm。 ## 开始之前 [#开始之前] 需要准备: * **Nowledge Mem** 已在本地运行([安装](/zh/docs/installation)) * **OpenClaw 2026.5.3 或更高版本**([OpenClaw 入门](https://docs.openclaw.ai/start/openclaw))。旧的 2026.4.x 版本可能会在安装当前 ClawHub 包时先报 `archive integrity mismatch`,导致插件还没装上就被拒绝。 * **`nmem` CLI** 在你的 PATH 中。在 Nowledge Mem 中,打开 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**。或独立安装:`pip install nmem-cli` ```bash nmem status # 应显示 Nowledge Mem 正在运行 openclaw --version ``` ## 设置 [#设置]
### 安装插件 [#安装插件-step] ```bash openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem ``` 安装器会自动启用插件,并把 OpenClaw 的 `memory` slot 切换到 `openclaw-nowledge-mem`。在当前一些 OpenClaw 版本里,这个安装流程还可能把 `plugins.slots.contextEngine` 一起写成 `openclaw-nowledge-mem`。插件 `0.8.18+` 会把它当作兼容别名自动接受,所以安装后不需要再手改本地配置。如果你是手动维护配置,仍然建议使用规范的上下文引擎 id:`nowledge-mem`。 如果你之前从 ClawHub 安装时遇到 `dangerous code patterns detected`,请更新到 `0.8.17+`。这个版本会把测试文件排除在发布包之外,OpenClaw 安装时扫描到的就只 剩真正会运行的插件代码。 如果你更喜欢默认解析路径,这样写也可以: ```bash openclaw plugins install @nowledge/openclaw-nowledge-mem ``` 更新到最新版本: ```bash openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem --force ``` 这会从 ClawHub 重新拉取最新版并替换本地插件。如果你的 OpenClaw 本地记录曾经被固定 到某个具体版本,不要用 `openclaw plugins update openclaw-nowledge-mem`,直接用上面 这条命令。 如果安装时报 `archive integrity mismatch`,先升级 OpenClaw,再重新执行上面的 `--force` 安装命令。
## 安全地自定义 [#安全地自定义] OpenClaw 这条连接没有单独的项目级指引文件。 * 想做持久化行为调整,优先改插件设置和 OpenClaw 配置 * 想改变记忆风格、语言或回忆策略,优先走 agent / prompt 配置 * 不要直接去改 `~/.openclaw/extensions/` 下安装好的插件源码 完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。
### 可选但推荐:把非内置插件加入信任 allowlist [#可选但推荐把非内置插件加入信任-allowlist-step] 如果 OpenClaw 提示 `plugins.allow` 为空,可以加入: ```json { "plugins": { "allow": ["openclaw-nowledge-mem"] } } ``` 如果你还用了 `plugins.load.paths` 或 `openclaw plugins install --link` 的本地副本,也要一起检查。OpenClaw 的 allowlist 按插件 id 生效,不会固定来源路径。
### 重启 OpenClaw 并验证 [#重启-openclaw-并验证-step] ```bash openclaw nowledge-mem status ``` 看到 Nowledge Mem 可访问即配置成功。 如果你不是通过 `openclaw plugins install` 安装,而是手动维护配置,请确认 `plugins.slots.memory` 是 `openclaw-nowledge-mem`,并且 `plugins.entries.openclaw-nowledge-mem.enabled` 为 `true`。 本地模式不需要 API key。如果你要连接远程 Nowledge Mem 服务器,请设置 `apiUrl`;如果那台服务器开启了认证,再额外设置 `apiKey`。
## Spaces [#spaces] OpenClaw 比一般单 Agent 工具更适合做 lane 映射,但前提是宿主真的知道当前是谁在运行。 * 如果一个 OpenClaw profile 或进程本来就属于一个固定 lane,直接设置 `space` * 如果你的启动器已经提供可信的身份变量,再使用 `spaceTemplate` * 如果没有可靠的身份信号,就不要硬做自动路由。一个 profile 对应一个 space,往往比“看起来聪明”的猜测更稳 如果只是单 lane 使用,也可以直接用 `NMEM_SPACE="Research Agent"` 启动当前 OpenClaw 进程。 ## 验证配置(1 分钟) [#验证配置1-分钟] 在 OpenClaw 聊天中依次执行: 1. `/remember 我们为任务事件选择了 PostgreSQL` 2. `/recall PostgreSQL` - 应立即找到 3. `/new` - 开启新会话 4. 问:`任务事件的数据库我们选的什么?` - 跨会话记住了 5. 问:`这周我都做了什么?` - 按周浏览 6. 问:`2月17日我在忙什么?` - 精确到某一天 7. `/forget PostgreSQL 任务事件` - 删除干净 如果以上七步都顺利,记忆系统已完整运作。 ## 你能做什么 [#你能做什么] **对话留下,定时任务不塞进来** 你在窗口里亲自聊的内容会落成线程,以后搜得到。像 `cron-worker` 这种自动化会话,插件会直接跳过,不和你的手谈挤在同一张列表里。真有要留的东西,再提炼成结构化记忆,用 `sourceThreadId` 一键回到原文。 **用图谱记忆,而不是平铺的存档** 每条记忆都可以连到相关实体、同一主题更早或更新的版本,以及它来自的源对话。这样 OpenClaw 做的就不只是关键词检索,而是能追踪一个决策怎么变化、它和哪些主题相连、答案来自哪里。 **让知识在后台继续成长** 当你在 Nowledge Mem 里开启 Background Intelligence 后,系统会在会话结束后继续工作:去重重叠内容、找出矛盾、生成 Working Memory 简报,并在多条记忆逐渐收敛时形成知识结晶(crystals)。下次你使用 OpenClaw 时,这些结果就已经在那里了。 **记住任何事情** 告诉 AI `/remember 我们决定不用微服务,原因是团队太小`,下周换一个会话,直接问"微服务那个决定是怎么说的",它能找到。 **按日期找回工作内容** 问"上周二我在做什么",AI 会列出那天你保存的内容、添加的文档、生成的洞察。支持指定具体日期,不只是"最近 N 天"。 **把其他 AI 工具里的知识也带进 OpenClaw** 你在 Claude 里得到的结论、在 Cursor 里做的决定、在浏览器 AI 聊天里保存的内容,或者从旧线程导入的历史,都可以进入同一个记忆层。OpenClaw 不是孤立工作的,它接入的是一整套持续增长的上下文系统。 **追溯一个决策的来龙去脉** 问 AI "这条记忆是怎么来的、和什么有关",它会展示:这条知识的原始来源文档、哪些相关记忆被合成为了更高层的洞察、这个认识随时间怎么变化过。 **可选:让每次会话一开始就带着上下文** 开启 `sessionContext` 后,Nowledge Mem 会在第一轮回复前注入 Context Bundle / Working Memory 和相关记忆。这样 OpenClaw 从一开始就知道你的身份、分区、规则和当前重点。默认模式下不会自动注入这部分上下文,AI 仍然有完整的记忆工具和一条简短的系统提示,但它会自己判断什么时候搜索。 **保存时带上类型和时间** 你不只是在保存文字,你在记录结构化的知识。告诉 AI "记住这是一个决策,发生在 2026 年 2 月",它会以正确的类型和时间存进知识图谱。支持 8 种类型:事实、偏好、决策、计划、流程、学习、背景、事件。 **追溯记忆的来源对话** 当一条记忆是从对话中提炼出来的,它会包含 `sourceThreadId`。AI 可以用 `nowledge_mem_thread_fetch` 获取完整对话,查看当时说了什么、做了什么决定、结论是怎么得出的。 **直接搜索过去的对话** 问"找一下我们讨论 Redis 缓存的那次对话",AI 会用 `nowledge_mem_thread_search` 找到匹配的对话线程和消息片段。然后用 `nowledge_mem_thread_fetch` 逐页获取完整消息。 **斜杠命令快捷方式**:`/remember`、`/recall`、`/forget` ## 工作原理 [#工作原理] ### 每轮对话的工作流 [#每轮对话的工作流] 每次你发送消息,插件会在 AI 处理之前注入行为引导。AI 随后决定调用哪些工具。 行为技能和始终在线的引导提示 AI **回答前先搜索**、**做完决定后保存**。每个工具的触发时机: | 场景 | 工具 | 做什么 | | -------------------- | ---------------------------- | --------------------------------------------- | | 用户提问 | `memory_search` | 回答前搜索知识库,返回 `sourceThreadId` | | 做了决策、学到新东西 | `nowledge_mem_save` | 结构化保存:类型 + 标签 + 时间 | | "上周我在做什么?" | `nowledge_mem_timeline` | 按天分组的活动流,支持精确日期 | | "X 和 Y 有什么关联?" | `nowledge_mem_connections` | 图谱遍历:边、实体、演化链、来源 | | 需要启动上下文或今日重点 | `nowledge_mem_context` | 优先读取 Context Bundle,旧版 CLI 回退到 Working Memory | | 记忆有 `sourceThreadId` | `nowledge_mem_thread_fetch` | 获取完整来源对话,支持分页 | | "找一下我们讨论 X 的对话" | `nowledge_mem_thread_search` | 按关键词搜索过去的对话 | | "忘掉 X" | `nowledge_mem_forget` | 按 ID 或搜索词删除 | | "我的配置对吗?" | `nowledge_mem_status` | 显示配置、连接状态和版本 | ### 会话生命周期(自动捕获) [#会话生命周期自动捕获] 会话结束时,对话自动被捕获并可选地提炼为结构化记忆。无需用户操作。 要点: * 你在 OpenClaw 里正常聊出来的会话,会像其他已连接的助手一样自动进 Mem,搜得到。 * 定时任务、cron 那类隔离运行默认不同步。诊断里看到 `cron-worker` 不稀奇;对话列表刻意不收它们,是产品上的选择,不是漏了。 * 提炼跟着「对话真的变长了」走:`agent_end`,或者开了上下文引擎时的普通轮次。只有压缩检查点的那一瞬,不会单独再开一轮提炼。 * 如果你开启了上下文引擎,提示词组装会交给它;但线程捕获仍保留生命周期钩子做兜底。这样更稳,不会因为某一条运行路径漏掉一次回调,就把整段会话丢掉。 * 提炼结果带 `sourceThreadId`,要回原文一戳就行。 ### 渐进式检索(记忆 -> 线程 -> 消息) [#渐进式检索记忆---线程---消息] 从对话中提炼的记忆携带 `sourceThreadId`,形成检索链:搜索记忆 -> 追溯来源对话 -> 分页读取完整消息。 两个进入过去对话的入口: 1. **从记忆出发**: `memory_search` 或 `memory_get` 返回 `sourceThreadId`,然后获取来源对话 2. **直接搜索**: `nowledge_mem_thread_search` 按关键词查找对话,然后获取任意结果 ### 三种模式 [#三种模式] 插件支持三种运行模式。根据你想要多少保障、愿意花多少 token 预算来选择。 | 模式 | 配置 | 行为 | Token 开销 | | ---------- | ----------------------- | ---------------------------------------------------------------- | -------------------- | | **默认**(推荐) | `sessionContext: false` | AI 按需调用 10 个工具。会话结束时自动捕获 + 提炼。 | 开销最低,由 AI 自己判断何时搜索 | | **会话上下文** | `sessionContext: true` | 每次提示时自动注入 Context Bundle / Working Memory 和相关记忆,同时仍可使用全部 10 个工具。 | 每轮提示更大,但从第一轮开始就带着上下文 | | **最小模式** | `sessionDigest: false` | 仅工具调用,不自动捕获。 | 只保留那条简短系统提示的开销 | **选哪个模式?** * **大多数用户**:从默认模式开始。AI 每轮收到行为引导,提示它回答前先搜索、做完决定后保存。大多数对话场景下效果良好。 * **短会话或需要高准确性**:开启 `sessionContext`。这确保从第一轮开始就有相关记忆在上下文中,AI 不需要自行判断是否搜索。代价是每轮提示会更大。 * **完全手动控制**:设置 `sessionDigest: false`。你自己决定什么该保存(通过 `/remember` 或 `nowledge_mem_save`),不会自动捕获任何内容。 ### sessionContext - 会话上下文注入 [#sessioncontext---会话上下文注入] 开启后,插件在每次提示时自动注入上下文: 1. 优先读取 **Context Bundle**:用户身份、Agent 身份、当前分区、行为规则、Working Memory 和 KFS 路径;旧版 CLI 会回退到 Working Memory 2. 根据当前消息在知识图谱中**搜索相关记忆** 3. 将检索到的内容作为这次回答的上下文插入,同时把稳定的行为引导放在系统提示区域 开启 `sessionContext` 后,行为引导会自动调整,告诉 AI 上下文已经注入,`memory_search` 仅用于特定的后续查询,而非广泛的回忆。这样可以避免重复搜索相同的上下文。 适用于短会话和关键工作流,确保从第一轮开始就有完整的记忆上下文。 ### sessionDigest - 对话线程 + LLM 智能提炼(默认开启) [#sessiondigest---对话线程--llm-智能提炼默认开启] 在会话生命周期事件(`agent_end`、`after_compaction`、`before_reset`)时执行两步操作: **1. 对话线程保存(你亲自聊的才算)。** 整段对话会追加进 Mem 的持久线程,用 `nowledge_mem_thread_search` 能搜到。OpenClaw 给定时、cron 那类隔离运行发了另一套会话键,插件碰到就跳过,免得后台任务和你的手谈叠在同一条时间线上。 **2. LLM 智能提炼(有价值时才执行)。** 保存线程后,先用一次轻量级 LLM 筛选判断对话中是否有值得保存的内容(决策、洞察、偏好、事实)。如果有,执行完整的提炼流程,提取带有正确类型、标签和时间信息的结构化记忆。**支持任何语言**。 **上下文压缩**:当 OpenClaw 压缩长对话时,插件会先捕获对话记录,不会丢失任何内容。 **消息去重**:线程追加按消息 ID 幂等,不会出现重复内容。 ## 常见问题 [#常见问题] **AI 每次回答前都会搜索记忆吗?** 插件通过两层机制驱动记忆召回。第一层是行为技能(由 OpenClaw 自动发现),教会 AI 何时以及如何使用记忆工具。第二层是始终在线的系统提示,提醒 AI 在回答关于过去工作、决策或偏好的问题之前先搜索记忆。实际使用中,现代 LLM 会可靠地遵循这种指令式引导。对于不需要历史上下文的消息(比如「你好」「谢谢」),AI 会跳过搜索,这是正确的权衡。如果你需要确保每次都有完整的记忆上下文,开启 `sessionContext: true`,它会在 AI 处理消息之前就注入相关记忆。 **怎么防止 AI 重复保存同一件事?** 两层防护。第一,插件在每次保存前都会检查是否已有高度相似的记忆,如果相似度极高,保存会被跳过,返回已有记忆的信息。第二,Nowledge Mem 的后台智能在后台运行更深层的去重,它识别记忆之间的语义重叠,并通过 EVOLVES 链(替代、丰富、确认或挑战)建立关联。插件处理明显的重复;后台智能处理微妙的重复。 **没有主动保存的对话会怎样?** `sessionDigest` 默认开着:你在 OpenClaw 里的一次正常聊天,会落成 Mem 里的一条线程。边界跟着 OpenClaw 自己的会话生命周期走:当前这段聊天对应一条线程,执行 `/new` 或 `/reset` 会开始一条新线程,而 compaction 只是内部整理,不会把同一段聊天拆成第二条线程。Context Engine 路径和 hook 路径仍然会落到同一条对话上。像 `temp:*` 这样的内部辅助会话、subagent 会话会被过滤掉,最近线程列表里只保留真正的聊天。之后你可以用 `nowledge_mem_thread_search` 找回来。顺带还会跑一次轻量筛选,值得留的才提炼成结构化记忆,闲聊通常只保留在线程里。后台 cron 不走这条路径。 **记忆会过时吗?** 会,这是设计的一部分。Nowledge Mem 的 EVOLVES 链追踪认知如何变化:新的记忆可以替代、丰富或挑战旧的记忆。后台智能自动识别这些关系。搜索时,相关性评分会考虑时间因素,更新的记忆默认排名更高。 ## 配置 [#配置] 正常通过 npm 安装时,开箱即用。安装器已经帮你启用了插件并选好了 memory slot。 修改设置:打开 OpenClaw 控制面板,进入 **Automation > Plugins**。在 **Plugin Entries** 下展开 **Nowledge Mem**,再展开 **Nowledge Mem Config**。也可以在搜索栏输入"nowledge"直接定位。 OpenClaw Automation:Nowledge Mem 插件设置 修改后重启 OpenClaw 生效。 | 设置 | 默认值 | 说明 | | ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------ | | Session context injection | 关 | 每次提示时注入 Context Bundle / Working Memory 和相关记忆 | | Session digest at end | 开 | 会话结束时捕获对话 + 提炼关键记忆 | | Minimum digest interval | 300s | 会话提炼最短间隔秒数(0 = 无限制) | | Max context results | 5 | 注入的记忆数量(1-20) | | Min recall score | 0 | 仅注入相关性高于此阈值的记忆(0-100%),0 表示全部包含 | | Max thread message chars | 800 | 每条捕获线程消息保留的最大字符数(200-20000),长代码或技术对话可适当调高 | | Corpus supplement | 关 | 将你的知识接入 OpenClaw 的 dreaming 系统(详见下方) | | Corpus max results | 5 | 每次 dreaming 搜索返回的最大结果数(1-20) | | Corpus min score | 0 | dreaming 结果的最低分数(0-100%),0 表示全部包含 | | Dreaming | 由 OpenClaw 管理 | 可选的 OpenClaw dreaming 设置。当 Nowledge Mem 占用 memory slot 时,OpenClaw 可能会把原生 `dreaming` 对象写在这里。真正运行 dreaming 引擎的仍然是 `memory-core`。 | | Server URL | 空 | 远程服务器 URL(留空 = 本地) | | API key | 空 | 远程模式 API 密钥 | ### 远程访问 [#远程访问] 连接另一台机器上的 Nowledge Mem 服务器:先在这台机器上执行一次: ```bash nmem config client set url https:// nmem config client set api-key nmem_... ``` 这会写入这台机器上的共享客户端配置,`nmem`、OpenClaw、Bub、Claude Code 等连接都会复用它。也可以在 OpenClaw 仪表盘的插件设置中填写 **Server URL** 和 **API key**。插件内部无论走哪条路径,都会复用同一组解析后的凭据:基于 CLI 的记忆工具和基于 API 的线程同步都会使用同一个 `apiUrl` 与 `apiKey`。API 密钥不会出现在日志或命令行历史中。详见:[随处访问 Mem](/zh/docs/remote-access)。 ## 遇到问题? [#遇到问题] **插件装了,但 OpenClaw 好像没在用它** 检查 `plugins.slots.memory` 的值是否正好是 `openclaw-nowledge-mem`,确认修改配置后重启了 OpenClaw。 **`plugins.allow is empty` 警告** 这表示 OpenClaw 发现了一个非内置插件,但你还没有把它加入显式信任列表。如果这是你通过 npm 安装的插件,可以加入: ```json { "plugins": { "allow": ["openclaw-nowledge-mem"] } } ``` 如果你还配置了 `plugins.load.paths` 或本地 link 版本,也要一起检查。OpenClaw 的 allowlist 只按插件 id 生效,不会固定到某个来源路径。 **"Duplicate plugin id detected" 警告** 如果你之前本地安装过插件(例如使用 `--link`),之后又从 npm 安装, OpenClaw 会同时从两处加载。解决方法:删除配置中指向本地插件目录的 `plugins.load.paths` 条目。 打开 `~/.openclaw/openclaw.json`,删除指向本地插件目录的 `plugins.load.paths` 条目: ```json "load": { "paths": [] } ``` 然后重启 OpenClaw。警告会消失,只会加载 npm 安装的版本。 **status 显示无法连接** ```bash nmem status curl -sS http://127.0.0.1:14242/health ``` **记忆工具能用,但这段会话本身没有出现在 Threads 里** 在正常聊天会话里运行 `nowledge_mem_status`,重点确认: * `sessionDigest` 仍然开启 * 后端可达 * 当前走的是哪条捕获路径 * 最近有没有改过插件设置但还没重启 OpenClaw 如果你启用了 `plugins.slots.contextEngine: "nowledge-mem"`,那么插件 `0.8.6+` 会把生命周期钩子保留下来,作为线程同步的兜底。在当前一些 OpenClaw 安装器版本里,这个值也可能被自动写成 `openclaw-nowledge-mem`;插件 `0.8.18+` 会把它当作同一个引擎处理。若你还在 `0.8.5` 或更早版本,一个很有效的隔离方法是先临时移除 `contextEngine` slot,重启 OpenClaw,再看 hook-only 路径下线程捕获是否恢复。 如果是在升级 OpenClaw 后,线程突然不再更新,先升级 Nowledge Mem 插件,然后重启 OpenClaw。插件 `0.8.24+` 已经适配 OpenClaw Codex runtime 新的逐轮捕获事件。插件 `0.8.27+` 也适配了会报 `must declare contracts.tools before registering agent tools` 的新版 OpenClaw;这个报错表示 OpenClaw 在捕获钩子运行前就拒绝了插件工具注册。 要注意:OpenClaw 的插件设置是在重启后才真正生效的。如果你之前把 `sessionDigest` 关掉了,但当时还没重启,线程同步可能会暂时看起来还在继续;等到下一次重启后,才会真正停下来。 健康的 OpenClaw 线程同步,表现应该是这样: * 一段你看得见的当前聊天,只对应 Mem 里的一条线程 * 运行 `/new` 或 `/reset` 后,会开始一条新的 Mem 线程 * compaction 不会把同一段聊天拆出第二条线程 * `temp:slug-generator` 这种辅助会话不会出现在列表里 * `/new` 或 `/reset` 的启动提示,不会被保存成第一条用户消息 想直接看最近同步进来的 OpenClaw 线程,可以运行: ```bash nmem t list --source openclaw -n 20 ``` **只有 `memory_search` 和 `memory_get` 能用,保存的内容却写进了本地文件** 这通常是因为记忆插槽仍然指向 OpenClaw 内置的 `memory-core`,而不是 Nowledge Mem。OpenClaw 3.22 起,如果配置中没有显式指定记忆插槽,会默认使用 `memory-core`。如果你是手动安装插件、或在升级过程中配置被重置过,插槽可能需要重新设置。 确认配置中有显式的插槽声明: ```json { "plugins": { "slots": { "memory": "openclaw-nowledge-mem" } } } ``` 或者重新安装,安装命令会自动设置插槽: ```bash openclaw plugins install clawhub:@nowledge/openclaw-nowledge-mem ``` 改完后重启 OpenClaw。 **插件工具不可用** 插件工具在插件被允许加载后会自动注册。确保插件在 `plugins.allow` 中: ```json { "plugins": { "allow": ["openclaw-nowledge-mem"] } } ``` 不要在 `tools.allow` 中填入 `nowledge_mem_*` 工具名:OpenClaw 会静默丢弃只包含插件工具的允许列表。`tools.*` 这边什么都不用配。 **多个代理并发运行时搜索变慢** 同时运行很多代理(10 个以上)时,搜索性能可能下降,因为所有操作共用一条数据库连接。建议: * 升级到 Nowledge Mem v0.6.12+(后端):搜索响应不再被计分写入阻塞 * 如果代理走的是 CLI 通道,可以在插件配置中设置远程 API 地址,以减少子进程开销 **搜索只找到一两条结果** 把 `maxContextResults` 调高到 `8` 或 `12`。 ## 为什么用 Nowledge Mem 而不是其他方案? [#为什么用-nowledge-mem-而不是其他方案] 其他记忆工具把你说过的话存成一段段文字,靠语义相似度找回来。Nowledge Mem 不一样。 **知识是有结构的。** 你保存的每条记忆都知道自己是什么类型(决策、学习、计划还是偏好),知道它什么时候发生、指向哪些来源文档、和哪些其他记忆有关联。这让搜索更准、推理更靠谱。 **知识会演化。** 你今天写的理解,和三个月后更新过的认识,在系统里是连在一起的。你可以看到自己的想法怎么变化的,不会丢掉中间的过程。 **知识来自哪里是透明的。** 从 PDF、文档或网页提取的每条知识,都保留着指向原始文件的链接。AI 告诉你"根据你三月份的设计文档",你能直接验证。 **跨工具共享。** 在 Cursor 里学到的,在 Claude 里记下的,在 OpenClaw 里一样能用。你的知识不属于任何一个工具,它属于你。 **本地优先,无需云账户。** 你的知识存在本地。远程访问是可选的,不是必须的。 搜索怎么工作的?参见[搜索与相关性](/zh/docs/search-relevance)。 ## 与 memory-core 协同(v0.8.0+) [#与-memory-core-协同v080] 默认配置下,Nowledge Mem 接管 memory slot。你可以使用完整的工具集、跨工具知识图谱和结构化记忆类型。大多数用户应该保持这个配置。 有些用户更习惯保留 OpenClaw 内置的 memory-core 作为 memory slot,因为 memory-core 有自己的特色功能:`MEMORY.md` 管理、dreaming(实验性的记忆整合系统),以及和 OpenClaw 原生召回管线的深度整合。 插件同时支持两种路径。开启 `corpusSupplement` 后,memory-core 的召回管线可以直接搜索你的 Nowledge Mem 知识图谱。你在 Claude、Cursor、ChatGPT 或其他工具中保存的记忆,会出现在 memory-core 的搜索结果中,也会参与 dreaming。 这个组合请使用 `0.8.15` 或更高版本。更早的构建里,插件在 `memory-core` 旁边可能会实际失活,于是有些用户只能手动修改本地源文件,才能让 supplement 模式继续工作。 ### corpus supplement 做了什么 [#corpus-supplement-做了什么] 当 memory-core 执行搜索时,它也会同时查询 Nowledge Mem。你的知识图谱中的结果和 memory-core 自身的结果一起排序和评分: * memory-core 的召回会包含你的跨工具知识 * Dreaming(实验性)可以把高频召回的 Nowledge Mem 内容提升到 `MEMORY.md` * 每周模式提取可以发现知识图谱与 memory-core 数据之间的关联 ### 配置方式 [#配置方式] 保持 memory slot 为 memory-core(或不设置)。在插件设置中打开 `corpusSupplement: true`,或通过环境变量 `NMEM_CORPUS_SUPPLEMENT=true`。 插件会自动处理去重。当 Nowledge Mem 是 memory slot 时,它直接处理召回;当 memory-core 是 memory slot 且 corpus supplement 开启时,它接入 memory-core 的管线。同一条内容不会出现两次。 如果你在 Nowledge Mem 这个插件条目下看到顶层的 `dreaming` 对象,也不用担心,这属于正常现象。新版 OpenClaw 会把 dreaming 设置写到当前选中的 memory-slot 插件上。Nowledge Mem 只负责接受这份配置,不会自己实现 dreaming 引擎;真正运行 dreaming 的仍然是 memory-core。 ### 怎么选 [#怎么选] | 配置 | 适合场景 | | ------------------------------- | ----------------------------------------------------------- | | Nowledge Mem 作为 memory slot(默认) | 完整的 10 个工具、结构化记忆类型、对话溯源。一个系统管理一切。 | | memory-core + corpus supplement | 你在用 memory-core 的 `MEMORY.md` 工作流,或者想用 dreaming。跨工具知识仍然会接入。 | 两种配置下,对话捕获和蒸馏的效果是一样的。区别在于由哪个系统负责召回和长期整合。 ## 上下文引擎(v0.7.0+) [#上下文引擎v070] 从插件 v0.7.0 起,Nowledge Mem 可以作为 OpenClaw 的完整**上下文引擎**运行,而不仅仅是提示钩子。这让它能更深入地参与 OpenClaw 的生命周期: * **记忆感知的上下文压缩**:当 OpenClaw 压缩长对话时,你知识图谱中已保存的关键决策和经验会以引用方式保留,不会在摘要过程中丢失 * **子代理记忆继承**:当 OpenClaw 启动并行研究代理时,它们会自动继承你的记忆上下文 * **会话预热**:Context Bundle 或 Working Memory 在第一轮对话前就加载好,上下文从一开始就已就绪 * **逐轮捕获**:对话在每轮结束后都会被捕获,而不只在会话结束时 激活方式:在 OpenClaw 配置中添加: ```json { "plugins": { "slots": { "memory": "openclaw-nowledge-mem", "contextEngine": "nowledge-mem" } } } ``` 如果不激活上下文引擎,现有的钩子模式会继续正常工作。 如果激活了,上下文引擎负责提示词组装和逐轮捕获;生命周期钩子则继续留作线程同步的兜底路径。这样分工是刻意设计的:上下文注入不会重复,线程同步也不会把成败压在单一路径上。 ## 给进阶用户 [#给进阶用户] OpenClaw 的 `MEMORY.md` 工作区文件仍然有效,但记忆工具的实际调用全部由 Nowledge Mem 处理。两者可以共存。 插件内部使用同一套连接配置,但不强行走同一种传输方式。大多数记忆操作仍通过 `nmem` 完成;对话线程同步则直接请求 Mem 服务器,这样长会话会通过正常的请求体传输,而不是塞进一条很长的命令行参数。对用户来说不需要学两套配置:地址和密钥只配一次,本地模式和远程模式都按同样的方式工作。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations) - 原生连接、复用包、MCP 与浏览器捕获 * [Claude Code](/zh/docs/integrations/claude-code) · [Claude Desktop](/zh/docs/integrations/claude-desktop) · [Codex](/zh/docs/integrations/codex-cli) · [Alma](/zh/docs/integrations/alma) · [Raycast](/zh/docs/integrations/raycast) · [内置 Web 聊天](/zh/docs/integrations/other-chat-ai) ## 参考 [#参考] * 插件源码:[nowledge-mem-openclaw-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-openclaw-plugin) * OpenClaw 文档:[插件系统](https://docs.openclaw.ai/tools/plugin) * 更新日志:[CHANGELOG.md](https://github.com/nowledge-co/community/blob/main/nowledge-mem-openclaw-plugin/CHANGELOG.md) # OpenCode × Nowledge Mem (/docs/zh/integrations/opencode) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 OpenCode 安装或更新 Nowledge Mem。用 nmem status 和 Working Memory 检查验证结果,并总结你改了什么。 ``` ```bash title="安装" opencode plugin opencode-nowledge-mem -g ``` OpenCode 是一款强大的终端编程智能体。Nowledge Mem 为它补充跨工具知识:来自 Claude Code、Cursor、Codex 等工具的决策和经验,在 OpenCode 中即刻可用。新的 OpenCode 会话会在 OpenCode 进入 idle 后自动保存为 Mem 线程,所以 OpenCode 里的工作也能进入后续检索和知识结晶,不需要切换到别的工具触发。 ## 准备工作 [#准备工作] * **Nowledge Mem** 已在本地运行([安装指南](/zh/docs/installation)),或你已经有可访问的远程 Mem 服务 * **OpenCode** 已安装 * **`nmem` CLI** 已在 PATH 中。在 Nowledge Mem 中前往 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**,或执行 `pip install nmem-cli` ```bash nmem status # 确认 Nowledge Mem 正在运行 opencode --version # 确认 OpenCode 可用 ``` ## 安装 [#安装]
### 安装插件 [#安装插件-step] 安装 npm 插件,并让 OpenCode 自动更新配置: ```bash opencode plugin opencode-nowledge-mem -g ``` `-g` 表示全局启用,所有项目都可使用。如果只想在当前项目启用,可以去掉 `-g`。 如果你更习惯手动编辑配置,也可以自己加入插件名: ```json title="~/.config/opencode/opencode.json" { "plugin": ["opencode-nowledge-mem"] } ```
### 重启 OpenCode [#重启-opencode-step] 关闭并重新打开 OpenCode,让它加载新插件。
### 验证集成 [#验证集成-step] 让 OpenCode 检查与 Nowledge Mem 的连接: ``` 我最近在做什么? ``` 你应该会看到 OpenCode 调用 `nowledge_mem_context_bundle`(完整启动上下文)或 `nowledge_mem_working_memory`(轻量简报),并返回你的当前上下文。看到这些就说明已经接通了:OpenCode 现在可以访问你在其他工具中积累的知识。 要验证会话捕获,可以完成一个很短的 OpenCode 回合,等 OpenCode 进入 idle 后,在另一个终端搜索刚才说过的一句话: ```bash nmem t search "刚才那句话" --source opencode ``` 你应该能看到一个 `opencode-...` 线程。如果没有,先更新插件并重启 OpenCode,确保 event hook 已加载。
## 更新 [#更新] 刷新全局插件包,并替换已安装的副本: ```bash opencode plugin opencode-nowledge-mem -g --force ``` ## 安全地自定义 [#安全地自定义] 优先使用 OpenCode 自己的指引入口,而不是去改插件包文件: * 项目级规则放在仓库里的 `AGENTS.md` * 个人默认规则放在 `~/.config/opencode/AGENTS.md` * 如果你更偏好宿主配置,也可以用 `opencode.json` 里的 `instructions` 不要直接修改已安装的 Nowledge Mem 插件包。完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 你能做什么 [#你能做什么] **在 OpenCode 中查找其他工具的知识** 问一句"数据库方案之前定了什么?",OpenCode 会搜索你在 Claude Code 中做过的决策、ChatGPT 中获得的洞察、Cursor 中留下的笔记,而不仅仅是当前会话。 **保存知识,全局可用** 当你在 OpenCode 中得出结论,智能体会将其保存,你下一次打开 Claude Code、Cursor 或 ChatGPT 时都能找到。 **会话一开始就有上下文** 你的 Working Memory 简报和相关历史知识在你开口之前就已准备好,不用换个工具就把背景重新交代一遍。 **让完整会话可搜索** OpenCode 完成一轮并进入 idle 后,插件会把当前会话保存成 Mem 线程。长会话压缩前也会先 flush 一次,所以 transcript 会保留下来,供后续搜索、回顾和知识结晶使用。 **创建可恢复的交接** 在 OpenCode 中收尾后,到 Claude Code 或任何其他工具中可以接着继续。决策、计划和上下文会自动带过去。 ## 工具一览 [#工具一览] | 工具 | 说明 | | ----------------------------- | --------------------------------------------------- | | `nowledge_mem_context_bundle` | 读取启动上下文:主人身份、AI 身份、当前空间、规则、Working Memory 和 KFS 路径。 | | `nowledge_mem_working_memory` | 读取今日 Working Memory:关注领域、优先事项、近期动态。 | | `nowledge_mem_search` | 跨工具搜索知识,支持标签、日期和深度模式过滤。 | | `nowledge_mem_save` | 保存一个决策、洞察或偏好,让任何工具都能找到。 | | `nowledge_mem_update` | 更新已有记忆的内容或元数据。 | | `nowledge_mem_thread_search` | 搜索任何工具中的历史对话。 | | `nowledge_mem_save_thread` | 按需保存当前会话的完整对话记录。新工作通常由 idle 自动捕获处理。 | | `nowledge_mem_save_handoff` | 保存精简的交接摘要(由智能体撰写)。 | | `nowledge_mem_status` | 连接状态与配置诊断。 | ## 会话捕获机制 [#会话捕获机制] Nowledge Mem 通过四种互补方式捕获 OpenCode 会话: \*\*插件自动实时捕获。\*\*当 OpenCode 报告 `session.status=idle`(或旧版 `session.idle` 事件)时,插件会稍等片刻让消息落盘,然后通过 OpenCode SDK 读取当前会话,并写入对应的 `opencode-...` Mem 线程。新工作应优先依赖这条路径。 \*\*压缩前 flush。\*\*OpenCode 压缩长会话前,插件会通过同一条线程路径保存当前 transcript,然后提醒智能体在压缩后重新读取 Mem 上下文。 **手动完整会话捕获。**`nowledge_mem_save_thread` 通过 OpenCode SDK 读取当前会话的全部消息,以 HTTP 方式发送到 Nowledge Mem。它是幂等操作,可反复执行,适合作为显式兜底。 **插件主动知识保存。**`nowledge_mem_save` 在对话中实时捕获决策和洞察,并标记 `source=opencode`。`nowledge_mem_save_handoff` 在收尾时创建精简摘要。两者都是对完整会话记录的高信号补充。 桌面导入需要直接读取 OpenCode 的本地数据库,因此只能看到 Mem 所在机器上的会话。使用[远程模式](/zh/docs/remote-access)时,请依赖原生插件的实时捕获,或在运行 OpenCode 的客户端机器上执行 `nmem t sync`。 ### 导入旧会话 [#导入旧会话] 如果要回填更早的 OpenCode 会话,先预览: ```bash nmem t sync --from opencode --all-projects --limit 20 ``` 确认无误后再导入: ```bash nmem t sync --from opencode --all-projects --apply ``` 如果只想导入某个项目,用 `-p /path/to/project` 代替 `--all-projects`。这个命令会读取本机 OpenCode 会话数据库或旧版 JSON 存储,并写入 `nmem` 当前配置的 Mem 服务器。导入的历史会话会立刻可搜索;更深的提炼和结晶仍走显式复查路径。 ## 配置 [#配置] 本地使用无需配置。 | 环境变量 | 默认值 | 说明 | | -------------- | ------ | --------------------- | | `NMEM_API_URL` | *(本地)* | 远程 Nowledge Mem 服务器地址 | | `NMEM_API_KEY` | *(无)* | 远程访问的 API 密钥 | 如果你想用一套持久化的共享配置,先在这台机器上执行 `nmem config client ...`。如果只是临时覆盖,环境变量的优先级仍然更高。 ### 远程访问 [#远程访问] ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` OpenCode 的 `nmem` 命令工具、idle 自动捕获、手动会话捕获和历史同步,都会使用同一份共享配置。 参见 [随处访问 Mem](/zh/docs/remote-access)。 ## 常见问题 [#常见问题] \*\*找不到 nmem 命令。\*\*执行 `pip install nmem-cli`,然后运行 `nmem status` 确认连接正常。 \*\*服务器无响应。\*\*启动 Nowledge Mem 桌面应用,或用 `nmem status` 检查诊断信息。 \*\*插件未加载。\*\*重新执行 `opencode plugin opencode-nowledge-mem -g --force`,确认 `opencode.json` 的 `plugin` 数组中包含 `"opencode-nowledge-mem"`,然后重启 OpenCode。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations) * [Claude Code](/zh/docs/integrations/claude-code) · [Pi](/zh/docs/integrations/pi) · [Hermes Agent](/zh/docs/integrations/hermes) · [OpenClaw](/zh/docs/integrations/openclaw) · [Alma](/zh/docs/integrations/alma) * 插件源码:[nowledge-mem-opencode-plugin](https://github.com/nowledge-co/community/tree/main/nowledge-mem-opencode-plugin) # 其他桌面 AI (/docs/zh/integrations/other-chat-ai) DeepChat 和 LobeHub 都内置了 Nowledge Mem。不用配服务器,也不用手动设置 MCP,打开开关就能用。 ## DeepChat [#deepchat]
### 在 DeepChat 中启用 MCP [#在-deepchat-中启用-mcp-step] 在 设置 > MCP 设置 下打开开关。
### 启用 Nowledge Mem [#启用-nowledge-mem-step] 在 自定义服务器 下打开 nowledge-mem 开关。 DeepChat 切换高亮
## LobeHub [#lobehub] LobeHub(原 LobeChat)支持从插件市场一键安装。
### 一键安装 [#一键安装-step]
### 在安装对话框中确认 [#在安装对话框中确认-step] 在对话框中点击 安装 LobeHub 安装演示
## 相关 [#相关] * [连接总览](/zh/docs/integrations): 原生连接、复用包、MCP 与浏览器捕获 * [Claude Code](/zh/docs/integrations/claude-code) · [Claude Desktop](/zh/docs/integrations/claude-desktop) · [Codex](/zh/docs/integrations/codex-cli) · [Alma](/zh/docs/integrations/alma) · [OpenClaw](/zh/docs/integrations/openclaw) · [Raycast](/zh/docs/integrations/raycast) # Paseo (/docs/zh/integrations/paseo) Paseo 会在你的电脑上启动 Claude Code、Codex、Copilot、OpenCode、Pi、OMP 等编程 agent。 Nowledge Mem 应该接在这些被启动的 AI 工具上。Paseo 是编排层:它决定哪个 worker 运行;MCP、hook 和会话文件仍然属于被启动的工具。 Paseo 自己的 MCP 工具用于编排,比如创建 agent 或 worktree。你可以继续使用它们,但它们不能替代被启动 AI 工具里的 Nowledge Mem 连接,也不会自动把每段 transcript 都捕获进 Mem。 ## 你需要准备什么 [#你需要准备什么] 1. Nowledge Mem 已经在 Paseo 启动 agent 的那台机器上运行。 2. Paseo 会启动的 AI 工具已经连接到 Mem,例如 [Codex](/zh/docs/integrations/codex-cli)、[Claude Code](/zh/docs/integrations/claude-code)、[OpenCode](/zh/docs/integrations/opencode)、[Pi](/zh/docs/integrations/pi) 或 [OMP](/zh/docs/integrations/omp)。 3. 你知道哪些 Paseo agent 是长期角色,哪些只是一次性任务。 ## 第一步怎么做 [#第一步怎么做] 先连接被 Paseo 启动的 AI 工具。比如 Paseo 启动 Codex,就先安装并验证 Codex 连接;启动 Pi,就先安装并验证 Pi 包;启动 OMP,就先安装并验证 OMP 插件。 如果某个 Paseo agent 是稳定角色,先创建一个 Mem AI 身份: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "Help with onboarding. Explain one step at a time." ``` 然后把这个身份传给它启动的子运行时: ```bash NMEM_AGENT_ID=cindy ``` 一次性 advisor、短期实现 agent、通用 provider preset 不需要设置 `NMEM_AGENT_ID`。它们仍然可以通过子工具的 Mem 连接使用记忆,只是不需要一个长期身份。 ## 不要把来源写成 Paseo [#不要把来源写成-paseo] 不要把所有子会话都标成 `paseo`。 `source_app` 应该使用真正启动的 AI 工具: * Paseo 启动 Codex:`source_app=codex` * Paseo 启动 Claude Code:`source_app=claude-code` * Paseo 启动 OpenCode:`source_app=opencode` * Paseo 启动 Pi:`source_app=pi` * Paseo 启动 OMP:`source_app=omp` 这样,线程筛选、图标和捕获路径才是正确的。Mem AI 身份表示这个 worker 的长期角色;source app 表示实际产生会话的工具。 ## 哪些内容会同步 [#哪些内容会同步] 受支持的子工具会话有两种同步方式。 ### 使用过程中 [#使用过程中] 工作中新会话的自动捕获来自被启动 AI 工具里安装的连接。 如果 Paseo 启动 Codex,就安装 Codex 连接;如果启动 Claude Code,就安装 Claude Code 连接;如果启动 OpenCode、Pi 或 OMP,就安装对应包。Paseo 可以运行这些工具,但 Paseo 自己目前没有提供一个每次 child turn 结束后触发 Mem 的 hook。 ### 导入旧的 Paseo Agent [#导入旧的-paseo-agent] 旧的 Paseo 管理会话可以从 Paseo 本地 agent registry 导入: ```bash nmem t sync --from paseo --all-projects --apply ``` 这个命令会读取 Paseo 的 agent 记录,找到受支持的子工具会话,再导入真正的子工具 transcript。导入后的线程仍保留子工具来源,例如 `codex`、`claude-code`、`opencode`、`pi` 或 `omp`;不会被统一标成 `paseo`。 这个导入可以安全重复运行。Paseo-guided sync 使用和子工具直接同步一样的 child thread id,所以一个通过 Paseo 导入的 Codex 会话仍会进入同一个 `codex-*` 线程,而不是再创建一份 `paseo-*` 副本。 Paseo 的终端状态、定时任务和聊天室是另一层数据。只有当 Paseo 未来为这些表面提供消息级 transcript export、API 或 hook 时,Nowledge Mem 才能直接导入它们。 ## 怎么确认成功 [#怎么确认成功] 在 Paseo 启动的 AI 工具里运行: ```bash nmem --json context --source-app codex ``` 把 `codex` 换成实际被启动的工具。如果子运行时收到了 `NMEM_AGENT_ID=cindy`,Context Bundle 应该显示 Cindy 的身份和默认 Space。 如果你在普通终端里检查,就显式传入身份: ```bash nmem --json context --agent-id cindy --source-app codex ``` ## 下一步 [#下一步] * [Codex](/zh/docs/integrations/codex-cli) * [Claude Code](/zh/docs/integrations/claude-code) * [OpenCode](/zh/docs/integrations/opencode) * [Pi](/zh/docs/integrations/pi) * [OMP](/zh/docs/integrations/omp) * [自定义连接行为](/zh/docs/integrations/customize-behavior) # Pi × Nowledge Mem (/docs/zh/integrations/pi) 把这行交给你的智能体。它应该先使用统一安装指南;这一页保留为行为说明和排障参考: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Pi 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` ```bash title="一键安装" pi install npm:nowledge-mem-pi ``` Pi 是一款精简的终端编程智能体。Nowledge Mem 为它补充跨工具知识:来自 Claude Code、Cursor、Codex 等工具的决策和经验,在 Pi 中即刻可用。安装插件包之后,Pi 中完成的会话也会同步回 Nowledge Mem,之后你可以在其他工具里搜索到这些对话。 插件包现在有两条自动路径:Pi 会在会话启动时收到 Context Bundle 或 Working Memory,完成后的 Pi 对话也会同步成可搜索的 Threads。Skills 仍然用于会话中的检索、保存决策和显式交接。 ## 准备工作 [#准备工作] * **Nowledge Mem** 已在本地运行([安装指南](/zh/docs/installation)) * **Pi** 已安装 * **`nmem` CLI** 已在 PATH 中。在 Nowledge Mem 中前往 **设置 → 偏好设置 → 开发者工具 → 安装 CLI**,或执行 `pip install nmem-cli` ```bash nmem status # 确认 Nowledge Mem 正在运行 pi --version # 确认 Pi 可用 ``` ## 安装 [#安装]
### 安装插件包 [#安装插件包-step] ```bash pi install npm:nowledge-mem-pi ```
### 验证集成 [#验证集成-step] 让 Pi 检查与 Nowledge Mem 的连接: ``` Nowledge Mem 连上了吗?运行一下 status 技能。 ``` 你应该会看到连接信息,以及服务器可达的确认。看到这些就说明通了:Pi 现在能用上你在其他工具里积累的知识。 安装或更新后,重新开启一个 Pi 会话。Pi 应该已经在系统上下文里拿到 Nowledge Mem 的启动上下文,不需要再为了知道今日 Context Bundle 而主动运行 `read-working-memory` 技能。
## 更新 [#更新] ```bash pi update ``` 更新后请重启 Pi,让 Nowledge Mem 扩展重新加载。 ## 导入旧会话 [#导入旧会话] 自动同步会从安装插件包之后开始。如果你想把更早的 Pi 会话也导入 Nowledge Mem,可以运行一次历史导入。 先预览: ```bash nmem t sync --from pi --limit 20 ``` 确认无误后再导入: ```bash nmem t sync --from pi --apply ``` 这个命令会读取本机的 Pi 会话文件,并写入 CLI 或扩展当前配置的 Mem 服务器。它可以重复运行:Pi 会话 ID 会变成稳定的 Thread ID,重复消息会被自动去重。 常用过滤: ```bash nmem t sync --from pi --session-dir ~/.pi/agent/sessions --limit 20 nmem t sync --from pi --space work --apply ``` 传入 `--session-dir` 时,只扫描这个目录。不传时,命令会使用 Pi 的默认会话目录。 如果你安装的 `nmem` 还没有 `t sync`,可以先用插件包自带的备用命令: ```bash npx -p nowledge-mem-pi nowledge-mem-pi-sync --apply ``` ## 安全地自定义 [#安全地自定义] 优先使用项目自己的 `AGENTS.md`,而不是去改安装后的包缓存。 * 如果你希望 Pi 在这个仓库里更主动地检索或保存,就把包里的行为指引合并进项目 `AGENTS.md` * 把包文件保留为默认值,这样升级时不会把你的微调冲掉 Pi 目前没有单独的持久 override 文件,最稳妥的入口就是项目级行为指引。完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## 你能做什么 [#你能做什么] **让 Pi 对话自动进入 Threads** 插件包包含一个原生 Pi 扩展。安装之后,每轮对话完成后、切换会话、压缩上下文或退出时,它会把当前 Pi 会话分支同步成 Nowledge Mem 里的 `pi` 对话。 **在 Pi 中查找其他工具的知识** 问一句"数据库方案之前定了什么?",Pi 就可以去搜索你在 Claude Code 中做过的决策、在 ChatGPT 中获得的洞察、在 Cursor 中留下的笔记,而不仅仅是当前会话。 **保存知识,全局可用** 当你在 Pi 中得出结论时,可以让 `distill-memory` 把它存下来。这样你下次打开 Claude Code、Cursor 或 ChatGPT 时都还能找到。 **会话一开始就有上下文** 扩展会优先注入 Context Bundle,必要时回退到 Working Memory。只要你的 Mem 服务支持,Pi 启动时就会拿到 owner identity、AI Identity、当前 scope、Rules 和今日重点。 项目 `AGENTS.md` 仍然有价值,但它负责的是行为偏好,而不是启动上下文:你可以用它让 Pi 在某个仓库里更主动地检索和保存。 **创建可恢复的交接** 自动同步会保留对话本身。当你明确让 Pi 保存交接时,它还会额外生成一份结构化摘要,方便你到 Claude Code 或其他工具里继续接着做。 ## 技能一览 [#技能一览] | 技能 | 说明 | | --------------------- | ----------------------------------- | | `read-working-memory` | 读取今日 Working Memory:关注领域、优先事项、近期动态。 | | `search-memory` | 跨工具搜索知识,支持标签和日期过滤。 | | `distill-memory` | 保存一个决策、洞察或偏好,让任何工具都能找到。 | | `save-thread` | 在你明确需要时,额外生成一份结构化交接摘要。 | | `status` | 连接状态与配置诊断。 | ## 配置 [#配置] 本地使用无需配置。 | 环境变量 | 默认值 | 说明 | | -------------------- | -------- | -------------------------- | | `NMEM_API_URL` | *(本地)* | 远程 Nowledge Mem 服务器地址 | | `NMEM_API_KEY` | *(无)* | 远程访问的 API 密钥 | | `NMEM_SPACE` | *(默认空间)* | 这个 Pi 进程使用的可选记忆空间 | | `NMEM_AGENT_ID` | *(无)* | 多智能体编排时使用的 Mem AI Identity | | `NMEM_HOST_AGENT_ID` | *(无)* | 高级外部别名 | 如果你想用一套持久化的共享配置,先在这台机器上执行 `nmem config client ...`。Pi 扩展会读取与 CLI 相同的 `~/.nowledge-mem/config.json`。如果只是临时覆盖,环境变量的优先级仍然更高。 ### 远程访问 [#远程访问] ```bash nmem config client set url https://your-server nmem config client set api-key your-key ``` 参见 [随处访问 Mem](/zh/docs/remote-access)。 ## 常见问题 [#常见问题] \*\*找不到 nmem 命令。\*\*执行 `pip install nmem-cli`,然后运行 `nmem status` 确认连接正常。 \*\*服务器无响应。\*\*启动 Nowledge Mem 桌面应用,或用 `nmem status` 检查诊断信息。 \*\*技能未加载。\*\*用 `pi list` 确认插件已安装。如果看不到 `nowledge-mem-pi`,请重新安装:`pi install npm:nowledge-mem-pi`。 \*\*Pi 对话没有出现在 Threads。\*\*安装或更新后先重启 Pi,然后进行一次包含用户消息和助手回复的短对话,再检查: ```bash nmem t list --source pi -n 5 ``` 扩展会刻意跳过只有一条消息的会话,避免 `/new` 或空会话制造噪音。 \*\*旧 Pi 对话没有出现。\*\*自动同步无法看到安装插件包之前已经发生的会话。请用 `nmem t sync --from pi` 预览并导入历史 Pi 会话文件。 ## 相关 [#相关] * [连接总览](/zh/docs/integrations) * [Claude Code](/zh/docs/integrations/claude-code) · [OpenCode](/zh/docs/integrations/opencode) · [Hermes Agent](/zh/docs/integrations/hermes) · [OpenClaw](/zh/docs/integrations/openclaw) · [Alma](/zh/docs/integrations/alma) · [Bub](/zh/docs/integrations/bub) * 插件源码:[nowledge-mem-pi-package](https://github.com/nowledge-co/community/tree/main/nowledge-mem-pi-package) # Proma × Nowledge Mem (/docs/zh/integrations/proma) 如果你想让智能体帮你配置,可以把这句话交给它: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 Proma 安装或更新 Nowledge Mem。用 nmem status、启动上下文和 Proma 线程保存结果验证,并总结你改了什么。 ``` Proma 接入 Nowledge Mem 后,你会得到这些:Proma 可以在需要时搜索记忆、保存长期知识、浏览 Mem;通过生命周期 hooks,Proma 对话会自动存成 Mem 线程;每次新会话开始前,当前的 Mem 上下文会写进工作区 `CLAUDE.md`,让智能体一上来就知道重要背景。 Proma v0.13.0 及之后版本已经在「Memory」设置里加入 Nowledge Mem 卡片。第一次配置时,优先从那里复制配置提示词,贴到 Proma Agent 模式里执行。这页文档保留完整文件路径、更新方式和验证步骤,方便你检查或修复配置。 打开一个新的 Proma 会话,问 What was I working on?。然后发送一条带有独特短语的消息,等 Proma 回复完成后运行 nmem t search "那段短语" --source proma。你应该能在 Mem 里看到这条 Proma 线程。 ## 开始之前 [#开始之前] * Nowledge Mem 已在本地运行,或你有可访问的远程 Mem 服务。 * 已安装 Proma。 * 本机有 Python 3.9+,命令名为 `python3`。 * `nmem` 能在终端里正常运行。 ```bash nmem status ``` 如果找不到 `nmem`,可以从 Mem 桌面应用的开发者工具安装 CLI,或运行: ```bash pip install nmem-cli ``` ## 安装 [#安装] 如果你使用 Proma v0.13.0 或更新版本,可以先打开 **Proma 设置 → Memory → Nowledge Mem**,复制配置提示词并粘贴到 Proma Agent 模式。下面的手动步骤与这条提示词使用的是同一套配置,只是展开成了可检查的版本。 下面示例使用 Proma 的 `default` 工作区。如果你的工作区不是这个名字,把所有 `default` 替换成 `~/.proma/agent-workspaces/` 下面对应的目录名。 如果你的系统只有 `python` 命令,请把下面 hook 命令里的 `python3` 替换成 `python`。
### 下载插件文件 \[step] [#1-下载插件文件-step] ```bash rm -rf /tmp/nowledge-community git clone https://github.com/nowledge-co/community.git /tmp/nowledge-community mkdir -p ~/.proma/scripts ~/.proma/agent-workspaces/default/skills cp /tmp/nowledge-community/nowledge-mem-proma-plugin/hooks/save-to-nmem.py ~/.proma/scripts/ cp /tmp/nowledge-community/nowledge-mem-proma-plugin/hooks/read-working-memory.py ~/.proma/scripts/ chmod +x ~/.proma/scripts/save-to-nmem.py ~/.proma/scripts/read-working-memory.py cp -R /tmp/nowledge-community/nowledge-mem-proma-plugin/skills/{read-working-memory,search-memory,distill-memory,save-thread,status} ~/.proma/agent-workspaces/default/skills/ ```
### 添加 MCP 服务 \[step] [#2-添加-mcp-服务-step] 创建或编辑: ```text ~/.proma/agent-workspaces/default/mcp.json ``` 如果这个文件已经存在,把 `nowledge-mem` 合并到现有的 `servers` 对象里,不要覆盖其它服务。 ```json title="~/.proma/agent-workspaces/default/mcp.json" { "servers": { "nowledge-mem": { "url": "http://127.0.0.1:14242/mcp/", "type": "streamableHttp", "headers": { "APP": "Proma" } } } } ``` 如果使用远程 Mem,把 URL 换成远程地址,并加上 key: ```json title="~/.proma/agent-workspaces/default/mcp.json" { "servers": { "nowledge-mem": { "url": "https://mem.example.com/mcp/", "type": "streamableHttp", "headers": { "APP": "Proma", "Authorization": "Bearer nmem_your_key", "X-NMEM-API-Key": "nmem_your_key" } } } } ```
### 启用 hooks \[step] [#3-启用-hooks-step] 创建或编辑: ```text ~/.proma/sdk-config/.claude/settings.json ``` 把下面内容合并进 `hooks` 对象。若你的 Proma 版本不会展开 `$HOME`,请把命令改成绝对路径。 ```json title="~/.proma/sdk-config/.claude/settings.json" { "hooks": { "SessionStart": [ { "matcher": "startup|resume", "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/read-working-memory.py\"", "timeout": 15000 } ] } ], "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/save-to-nmem.py\" --event user-prompt-submit", "timeout": 30000 } ] } ], "Stop": [ { "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/save-to-nmem.py\" --event stop", "timeout": 30000 } ] }, { "hooks": [ { "type": "command", "command": "python3 \"$HOME/.proma/scripts/read-working-memory.py\" --rewake", "timeout": 15000, "async": true, "asyncRewake": true, "rewakeMessage": "Nowledge Mem context refreshed" } ] } ] } } ```
### 重启 Proma \[step] [#4-重启-proma-step] 修改 MCP、hooks 或 skills 后,都需要重启 Proma。
## 自动发生的事 [#自动发生的事] * `UserPromptSubmit` 会在下一轮用户输入前保存当前 Proma 线程。 * `Stop` 会在智能体回复结束后再保存一次,作为兜底。 * 保存脚本读取 `~/.proma/sdk-config/projects/**/.jsonl`,并以 `proma` 来源写入 Mem。 * `SessionStart` 会刷新 `~/.proma/agent-workspaces/default/CLAUDE.md` 里的 Nowledge Mem 区块。 * `Stop` 的 asyncRewake 可以在回复后推送一份简短 Working Memory 提醒。 当前 Proma 使用的 Claude Agent SDK 不能稳定把 SessionStart 的 stdout 注入模型上下文。因此这个连接器采用更可靠的方式:维护 `CLAUDE.md` 中的一个标记区块。 ```markdown ... ``` 你自己的 Proma 规则请写在这个区块外,或写进同目录的 `CLAUDE.md.template`。 ## 更新 [#更新] ```bash cd /tmp/nowledge-community git pull cp nowledge-mem-proma-plugin/hooks/save-to-nmem.py ~/.proma/scripts/ cp nowledge-mem-proma-plugin/hooks/read-working-memory.py ~/.proma/scripts/ chmod +x ~/.proma/scripts/save-to-nmem.py ~/.proma/scripts/read-working-memory.py cp -R nowledge-mem-proma-plugin/skills/{read-working-memory,search-memory,distill-memory,save-thread,status} ~/.proma/agent-workspaces/default/skills/ ``` 然后把最新的 `nowledge-mem-proma-plugin/hooks/hooks.json` 合并到 `~/.proma/sdk-config/.claude/settings.json`,并重启 Proma。 ## 远程模式 [#远程模式] MCP 使用 Proma 的 `mcp.json` 里的远程 URL 和 key。 hooks 与 CLI fallback 使用运行 Proma 这台机器上的 `nmem` 客户端配置: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` ## 常见问题 [#常见问题] **MCP 工具没有出现。** 确认 `mcp.json` 的顶层 key 是 `servers`,然后重启 Proma。 **新会话没有看到启动上下文。** 运行 `python ~/.proma/scripts/read-working-memory.py`,再检查 `~/.proma/agent-workspaces/default/CLAUDE.md` 里是否有 `nowledge-mem:start` 区块。 **Mem 里看不到 Proma 线程。** 等 Proma 完成一轮回复,再检查 `~/.proma/logs/nm-hooks.log`,并用 `nmem t search "短语" --source proma` 搜索。 **远程 MCP 能用,但 hooks 不工作。** MCP 使用 Proma 的 `mcp.json`;hooks 使用本机 `nmem` 客户端配置。两处需要指向同一个远程 Mem 服务。 ## 相关内容 [#相关内容] * [连接总览](/zh/docs/integrations) * [Claude Code](/zh/docs/integrations/claude-code) * [远程访问](/zh/docs/remote-access) # Raft (/docs/zh/integrations/raft) Raft 可以在同一台电脑上运行多个命名 Agent。Nowledge Mem 会把这些 Agent 识别成不同 worker,而不是把它们都当成同一个匿名 Codex 或 Claude 会话。 设置方式应该很轻:先连接 Raft 启动的 AI 工具,然后给每个 Raft Agent 设置一个环境变量。 ## 需要先准备好 [#需要先准备好] 1. Nowledge Mem 正在运行。 2. Raft 启动的 AI 工具已经连接到 Mem,例如 [Codex](/zh/docs/integrations/codex-cli) 或 [Claude Code](/zh/docs/integrations/claude-code)。 3. 每个 Raft worker 有稳定角色,例如 Cindy、Alice 或 Reviewer。 ## 最小设置 [#最小设置] 先为这个 Raft worker 创建一个 Mem AI Identity: ```bash nmem agents upsert cindy \ --name "Cindy" \ --default-space onboarding \ --instructions "帮助用户完成 onboarding。一次只解释一个步骤。" ``` 这会创建名为 Cindy 的 Mem 身份。命令和环境变量里使用的 ID 是 `cindy`。 这个命令只是创建身份记录。它不会让所有 Codex 会话都变成 Cindy。只有设置了 `NMEM_AGENT_ID=cindy`,或明确传入 `agent_id="cindy"` 的地方,才会使用这个身份。 然后打开 Raft 里这个 Agent 的 runtime config,只添加一个环境变量: ```bash NMEM_AGENT_ID=cindy ``` Raft runtime config 中的单个 Agent 环境变量 如果这个 Mem 身份已经设置了默认 Space,这样就够了。 ## 以后移动 Cindy [#以后移动-cindy] Cindy 这个身份属于 Mem,不属于 Raft。以后如果你把 Cindy 换到另一个编排工具,继续保留 `NMEM_AGENT_ID=cindy`,让新的启动器传入这个环境变量即可。 AI 工具也可以更换。Cindy 可以先跑在 Codex,之后改跑在 Pi 或 Claude Code。这个时候更新工具连接和 `--source-app`,但保留同一个 Mem 身份。 如果你需要一个相关但不同的 worker,创建一个新身份,例如 `cindy-reviewer`。这样 Cindy 保持稳定,新 worker 可以独立演化自己的规则。 ## 什么时候需要 Space [#什么时候需要-space] `NMEM_SPACE` 是可选项。它会作用于整个 Raft 运行时进程。 只有当这个 Raft Agent 在本次运行中所有 Mem 读取和写入都要覆盖默认 Space 时,才添加: ```bash NMEM_SPACE=onboarding ``` 如果这个 Agent 可能跨不同项目工作,不要设置 `NMEM_SPACE`。让它使用 Mem 身份的默认 Space,或者在具体命令里切换。 ## 默认不要添加第二个身份变量 [#默认不要添加第二个身份变量] 大多数用户不需要设置 `NMEM_HOST_AGENT_ID`。 `NMEM_HOST_AGENT_ID` 只适合高级场景:例如集成作者需要把 `raft:` 这类外部 worker ID 映射到 Mem 身份。普通 Raft 设置里,`NMEM_AGENT_ID=cindy` 更清楚,也已经足够;旧的 `slock:` 前缀仍然兼容。 ## 不要把执行轨迹写进 Threads [#不要把执行轨迹写进-threads] Raft 的 managed compute 会使用 Codex 执行任务,但真正的人类对话由 Raft 自己的 inbox 与消息通道管理。Codex rollout 里记录的是控制通知和工具执行;通过 Raft 消息工具发出的回复,并不会作为普通 Codex assistant 消息完整保存在 rollout 中。把它导入 Mem,会得到一条失真的 Thread。 因此,Nowledge Mem 会按每份 transcript 的结构化 session originator,跳过 `raft-daemon` 的 Codex rollout。旧的 `slock-daemon` originator 仍然兼容。这个判断只作用于对应 transcript,同一台电脑上的普通 Codex 会话仍然会自动捕获。 在 Raft worker 内,请通过 Mem skills 或 MCP 使用 Working Memory、检索和长期保存。完整同步 Raft 对话需要 Raft 原生 conversation connector;在该边界可用前,不要对 Raft 托管 worker 运行 `nmem t save --from codex`。 ## 成功是什么样 [#成功是什么样] 使用 `nmem` 0.9.0 或更新版本时,启动一个新的 Raft worker 会话,让它检查 Mem: ```bash nmem --json context --source-app codex ``` 在 Raft worker 内部,这个命令应该继承 `NMEM_AGENT_ID=cindy`,并返回你配置的 worker 身份。如果你是在普通终端里手动检查,请显式传入身份: ```bash nmem --json context --agent-id cindy --source-app codex ``` worker 内的记忆调用仍以 `codex`、`claude-code` 或 Raft 实际启动的运行时作为 source。未来的 Raft 原生 Thread connector 会以 `raft` 保存人类可见对话,并把子运行时保留为元数据。 ## 下一步 [#下一步] * [Codex](/zh/docs/integrations/codex-cli) * [Claude Code](/zh/docs/integrations/claude-code) * [自定义连接行为](/zh/docs/integrations/customize-behavior) # Raycast (/docs/zh/integrations/raycast) 来源:[community/nowledge-mem-raycast](https://github.com/nowledge-co/community/tree/main/nowledge-mem-raycast) 本文介绍的是 Nowledge Mem 的 Raycast 扩展,它走 API,让你在键盘上直接操作 Mem。Raycast AI 对话没有官方整包导出;要把历史迁入「对话」,请使用社区导出工具,再通过 Mem 批量导入。参见 [导入已有对话](/zh/docs/import-existing-conversations)、社区工具 [raycast-ai-exporter](https://github.com/daveonkels/raycast-ai-exporter),以及 [对话:批量导入](/zh/docs/threads#批量导入)。 ## 安装 [#安装] **Raycast Store:** 搜索「Nowledge Mem」或[直接打开链接](https://www.raycast.com/wey-gu/nowledge-mem)添加扩展。 **从源码安装**(用于开发或自定义): ```bash git clone https://github.com/nowledge-co/community.git cd community/nowledge-mem-raycast npm install && npm run dev ``` 你可以用两种方式连接: * **本地默认**:保持 `http://127.0.0.1:14242` * **远程 Mem**:可以直接在 Raycast 偏好设置中填写 **Server URL** 和 **API Key**。如果你想让 Raycast、CLI 和其他插件共用一套配置,也可以在这台机器上执行: ```bash nmem config client set url https://mem.example.com nmem config client set api-key nmem_your_key ``` Raycast 还有一个可选的 **Space** 偏好设置。如果这个 Raycast profile 天然就只对应一个命名好的 lane,比如 `Research Agent`,就可以填上。留空则继续用 **Default**。 大部分命令都同时支持本地和远程 Mem。只有 `编辑工作记忆简报` 是本地专用的便捷命令,因为它直接编辑你这台机器上的 **Default** Working Memory 文件。 Raycast - Nowledge Mem ## 命令列表 [#命令列表] | 命令 | 功能 | | ------------ | ----------------------------------------- | | **搜索记忆** | 语义搜索,显示相关度分数。搜索框为空时,会展示最近的记忆 | | **添加记忆** | 保存记忆,设置标题、内容和重要性 | | **读取工作记忆简报** | 通过 Mem API 读取你的每日简报 | | **编辑工作记忆简报** | 在本地 Raycast 中编辑 Default Working Memory 文件 | ## 安全地自定义 [#安全地自定义] Raycast 是启动器型连接,不像 agent runtime 那样自带项目级指引文件。 * 要做稳定的修改,就用 Raycast 偏好设置,比如 Server URL、API Key 和固定 Space * 除非你在开发这个扩展,否则别动扩展源码 完整对照表见 [安全地自定义连接行为](/zh/docs/integrations/customize-behavior)。 ## Spaces [#spaces] 对 Raycast 这种启动器型连接,最合适的就是「一个可选的固定 lane」: * **Space** 留空时,Raycast 跟着共享 `nmem` 客户端的 Space 走,通常就是 **Default** * 如果这个 Raycast profile 一直对应一个稳定的上下文,就设一个命名好的 **Space** * 别指望 Raycast 自己去判断「每个 agent 属于哪个 lane」 一旦设置了 Space,**搜索记忆**、**添加记忆**、**读取工作记忆简报**都会自动跟着这个 lane 走。`编辑工作记忆简报` 则仍然是本地、Default-only 的便捷入口。 ## 最推荐的用法 [#最推荐的用法] * 想最快找到答案时,用 **搜索记忆** * 想从键盘里顺手记下一条内容时,用 **添加记忆** * 想看今天的重点时,用 **读取工作记忆简报** Raycast 扩展目前还做不了图谱探索。需要图谱时,请用 Mem App,或者 Claude Code、Codex 这类支持图谱交互的连接。 搜索记忆 添加记忆 ## 相关 [#相关] * [连接总览](/zh/docs/integrations): 原生连接、复用包、MCP 与浏览器捕获 * [Claude Code](/zh/docs/integrations/claude-code) · [Claude Desktop](/zh/docs/integrations/claude-desktop) · [Codex](/zh/docs/integrations/codex-cli) · [Alma](/zh/docs/integrations/alma) · [OpenClaw](/zh/docs/integrations/openclaw) · [内置 Web 聊天](/zh/docs/integrations/other-chat-ai) # ZCode × Nowledge Mem (/docs/zh/integrations/zcode) 把这段发给 ZCode: ```text 读取 https://mem.nowledge.co/SKILL.md,按其中说明为 ZCode 安装或更新 Nowledge Mem。用 nmem status 和 Context Bundle 或 Working Memory 检查验证结果,并总结你改了什么。 ``` ZCode 支持 MCP servers 和 `SKILL.md` 技能。用它自己的设置入口连接 Nowledge Mem,不需要改 ZCode 内部文件。 ## 开始之前 [#开始之前] * Nowledge Mem 正在本机运行,或你有可访问的远程 Mem 服务 * 已安装 ZCode * ZCode 所在机器可以运行 `nmem` ```bash nmem status ``` ## 设置 [#设置] 生成 MCP 配置: ```bash nmem config mcp show --host zcode ``` 在 ZCode 中: 1. 打开 **Settings → MCP Servers**。 2. 添加生成的 `nowledge-mem` server。 3. 打开 **Settings → Skills**。 4. 导入或复制 Nowledge Mem 技能。 5. 重启或 reload ZCode Agent。 ## 验证 [#验证] 问 ZCode: ```text 搜索我的记忆,找最近和这个项目有关的决策。 ``` 只要 ZCode Agent 能调用 Nowledge Mem MCP 工具并返回结果,或正常返回空结果,就算成功。 ## 会话捕获 [#会话捕获] ZCode 的插件模型可以打包技能、MCP servers、hooks 和命令。但 Nowledge Mem 还没有发布 ZCode 原生 hook 包,所以这个连接不承诺自动同步完整对话。需要保留的对话,请先保存交接摘要。 ## 相关 [#相关] * [连接概览](/zh/docs/integrations) * [Kimi Code](/zh/docs/integrations/kimi-code) · [MiMo Code](/zh/docs/integrations/mimo-code) · [OMP](/zh/docs/integrations/omp) * ZCode 文档:[Plugin](https://zcode.z.ai/en/docs/plugin)、[MCP Servers](https://zcode.z.ai/en/docs/mcp-services)、[Skills](https://zcode.z.ai/en/docs/skill) # 自托管自动升级 (/docs/zh/self-host/auto-update) 自托管的 Docker 服务器可以直接在网页应用里检查 Nowledge Mem 新版本。真正从浏览器里安装更新需要你主动启用,因为这一步会改变服务器本身。 应用内自动升级依赖官方 `community/docker` 目录和里面的 `nmemctl` 工具。如果你是通过 NAS 应用商店、NAS Container Manager 模板、Portainer、Unraid,或者自己的 compose 文件安装的,应用仍然可以提示「有新版本」,但不能安全地替你改写那套部署。请从你当初安装 Mem 的地方升级,或者按你自己的 Docker 镜像拉取 / 重建流程处理。 如果设置页提示还没有配置自动升级,先 SSH 到服务器执行一次: ```bash cd community/docker ./nmemctl auto-update enable ``` 这条命令会生成当前部署专用的升级令牌,启动一个很小的伴随升级容器,并允许网页应用在之后下载和安装新的 Mem 镜像。如果服务器上没有 `community/docker` 或 `./nmemctl`,说明它不属于这条自动升级路径。 伴随升级容器需要访问 Docker,才能替换 Mem 容器。这也是为什么浏览器里的 Install 默认关闭,必须先在服务器主机上显式启用。 ## 应用里会出现什么 [#应用里会出现什么] 启用官方自动升级后: * 标题栏会在服务器镜像有新版本时显示更新提示。 * 设置页会显示当前服务器版本、最新版本,并提供发布说明链接。 * Download 会在后台拉取镜像,不会让 Mem 下线。 * Install 会先创建升级前快照,再重建容器,服务器恢复后页面会自动重连。 每次 Install 会在 `./cache` 中保留最近三份升级前快照。如果新镜像没有正常启动,设置页会显示快照路径,你可以回到服务器上恢复: ```bash ./nmemctl import <快照路径> --force ``` ## 常用命令 [#常用命令] ```bash ./nmemctl auto-update status ./nmemctl auto-update rotate ./nmemctl auto-update upgrade ./nmemctl auto-update disable ``` * `status` 查看自动升级状态和保留的快照。 * `rotate` 轮换升级令牌。 * `upgrade` 升级伴随升级容器自身。 * `disable` 移除伴随升级容器,但保留已有快照。 ## 远程安装 [#远程安装] 检查更新是只读操作,网页应用里一直可以使用。Download 和 Install 会改变服务器状态,所以受服务器的远程操作开关保护。 `./nmemctl auto-update enable` 会为正常的网页升级流程完成配置。如果你后来关闭了它,可以在可信的私有网络里从设置页打开 **Remote server upgrades**,或者继续通过 SSH 升级: ```bash ./nmemctl upgrade <版本> ``` ## 更多细节 [#更多细节] 完整的 Docker 部署指南,包括备份、内存配置、TLS 和迁移,请阅读 [Docker 部署](/zh/docs/docker)。 # 穿越时间搜索 (/docs/zh/use-cases/bi-temporal) ## 问题所在 [#问题所在] 董事会问:*"为什么你在第一季度选择了 React Native 而不是 Flutter?"* 那个决定你记得。可你记起来的样子,早就被后来发生的一切染过色了:转型、性能问题、推倒重写。 你要回答的其实是:当时的你,知道些什么? > "我可以搜索我的笔记中的'React Native'。但我不能搜索'我在三月份对 React Native 的看法'。" ## 解决方案 [#解决方案] Nowledge Mem 用的是双时态搜索:两条时间线,帮你精准定位要找的东西。 双时态搜索 事件时间:事情实际上是什么时候发生的? 记录时间:你什么时候捕获的? 可以单独搜索,也可以组合使用。 搜索查询详情 博客:[我们如何教会 Nowledge Mem 遗忘](https://nowledge-labs.ai/blog/memory-decay-temporal)。 关于[搜索与相关性](/zh/docs/search-relevance)的文档。 ## 工作原理 [#工作原理] ### 自然语言查询 [#自然语言查询] 想怎么问就怎么问。Nowledge Mem 能听懂里面的时间意思: > "我在 2024 年第一季度对 React Native 做了什么决定?" 系统会: 1. 认出里面的时间:"2024 年第一季度" 2. 找出事件发生在这段时间里的记忆 3. 连着原始上下文一起还给你 不用记什么特殊写法。 ### 显式时间过滤器 [#显式时间过滤器] 想精确控制,就用高级搜索: | 过滤器 | 含义 | 示例 | | --------- | -------- | ---------- | | **事件日期从** | 事件发生在此之后 | 2024-01-01 | | **事件日期到** | 事件发生在此之前 | 2024-03-31 | | **记录日期从** | 写下在此之后 | 2024-01-01 | | **记录日期到** | 写下在此之前 | 2024-12-31 | 举个有意思的查询: > 事件时间:2024 年 3 月 > 记录时间:不限 它会返回:*"所有讲 2024 年 3 月那些事的记忆,不管你是什么时候记下来的。"* ### 灵活的日期精度 [#灵活的日期精度] 日期可以写得很灵活,Nowledge Mem 都能认: * 只到年:"2024",匹配 2024 年里的任何内容 * 到月:"2024-03",匹配 2024 年 3 月 * 到日:"2024-03-15",匹配这一天 你写到哪一级,系统就记到哪一级,显示时也照这个精度来。 ## 知识演化 [#知识演化] 双时态搜索配上知识演化,威力更大。后台智能会自动发现你对某个话题想法上的变化: 周二:你存下"新服务用 PostgreSQL"。 周四:你提到打算迁到 CockroachDB。 周五:后台智能用 EVOLVES 关系把它们连起来,并标出其中的张力。 这时再搜"数据库决策",你拿到的就不是几条孤立的记忆,而是一整条演化链:最初的决策、后来的更新,以及它们之间的关系。你的想法是在什么时候、怎么变的,看得清清楚楚。 演化类型: * 替换:新信息使旧信息过时 * 丰富:新信息为旧信息添加细节 * 确认:来自不同来源的相同结论 * 挑战:矛盾的信息,标记待审查 ## 实际示例 [#实际示例] ### 董事会回顾 [#董事会回顾] > **查询**:"2024 年第一季度的架构决定" > > **结果**:带有第一季度上下文的原始决策备忘录,加上展示决策如何变化的演化链 ### 合规审计 [#合规审计] > **查询**:"事故前的安全策略" > > **结果**:违规前存在什么策略,带有证明何时记录的时间戳 ### 项目复盘 [#项目复盘] > **查询**:"项目启动时的 project-x 假设" > > **结果**:后来被证明错误的原始假设,链接到证明它们错误的后续洞察 ## 知识图谱 + 时间 [#知识图谱--时间] 图谱视图里有一个时间线滑块,可以按日期范围过滤节点和边。 把范围调到"2024 年 3 月",你会看到: * 只剩当时存在的实体 * 只剩当时已知的连接 * 那一刻你的知识全貌 往前拖滑块,看你的理解一点点长出来。按下播放,看知识随时间一层层累积。 ## 记忆衰减如何工作 [#记忆衰减如何工作] 记忆衰减按这几条规则来: * 默认让较近的记忆排在前面(半衰期 30 天) * 给经常访问的记忆加权(按对数缩放) * 看重重要性分数(重要性底线兜底,不让它彻底衰减掉) * 从你的行为里学(点击、停留时长) 平时搜索会把新鲜、相关的结果顶上来;而时间搜索会绕过衰减,精确返回你指定的那段时间。 时间意图检测需要**深度模式**搜索。在快速模式下,时间引用仅按关键词匹配。对于"最近在做"或"上季度的决定"等查询,启用深度模式。 查看[搜索与相关性](/zh/docs/search-relevance)了解评分、衰减和时间匹配如何工作的完整技术分解。 ## 两种时间 [#两种时间] 把这两者分清楚很要紧: | 问题 | 哪种时间? | | -------------- | ----- | | "我三月份做了什么决定?" | 事件时间 | | "我上周写了什么?" | 记录时间 | | "显示关于旧事件的最近笔记" | 两者 | | "转型前我知道什么?" | 事件时间 | 大多数搜索用的是事件时间,因为你问的是事情什么时候发生。 记录时间则适合用来: * 找最近刚存进来的内容 * 回看自己这阵子都记了些什么 * 查某条知识到底是什么时候记下的 ## 为什么这很重要 [#为什么这很重要] 普通搜索找的是内容,时间搜索找的是上下文,知识演化找的是来龙去脉。 > "我们用当时掌握的信息做了最好的决定。这就是证据。这里是我们的思维何时以及为何改变的完整记录。" 你的记忆都带着时间戳、有版本、历史可查。 ## 下一步 [#下一步] * [你的知识,你做主](/zh/docs/use-cases/shared-memory):自由切换工具,不丢失上下文 * [看见你的专长](/zh/docs/use-cases/expertise-graph):可视化你的知识 * [后台智能](/zh/docs/advanced-features):知识图谱能力 # 看见你的专长 (/docs/zh/use-cases/expertise-graph) ## 问题所在 [#问题所在] 你多年来积累了大量知识,但能看到它的全貌吗? > 我知道我擅长...某些东西。技术方面。但如果有人让我描述我的专长,我会很难说清楚。全凭直觉。没有具体的东西。 知识散落在记忆、笔记和对话里,其中的模式和连接你根本看不见。 ## 解决方案 [#解决方案] Nowledge Mem 把你的知识画成一张活的图谱。节点是你的记忆和实体,边是它们之间的关系。这张图不用你手动搭:后台智能在夜里自动从记忆里抽出实体和关系。 跑一次社区检测,就能看到你的专长集群一块块浮现出来: 专长图谱 ## 工作原理 [#工作原理]
### 图谱自动构建 [#图谱自动构建-step] 你不用手动给任何东西打标签或分类。后台智能读你的记忆,从中提取: * 实体:技术、人物、概念、项目 * 关系:它们之间怎么连接 * 演化链:你对某个话题的看法怎么变化 这些都是自动的。不管你从哪个渠道存记忆(自动同步、浏览器扩展、Timeline、`/sum`),图谱都会自己长大。 自动实体提取需要已配置的远程 LLM,以及你的当前版本所对应的许可能力。
### 运行社区检测 [#运行社区检测-step] 在右侧面板里找到「图算法」,点「聚类」下面的 计算。 Louvain 算法会分析你的知识结构,把自然形成的集群找出来: | 社区 | 大小 | 主题 | | ----- | ------ | ------- | | 分布式系统 | 87 条记忆 | 后端架构、扩展 | | 团队领导 | 45 条记忆 | 指导、沟通 | | 性能 | 62 条记忆 | 优化、分析 | | 个人项目 | 23 条记忆 | 创意实验 | 每个集群都会在自己的节点外面套一个彩色"气泡"。
### 穿越时间 [#穿越时间-step] 图谱底部有一个时间线滑块,可以按日期范围过滤。 拖到"2024 年 1 月",看看那时你的知识是什么样。往前拖,就能看到新集群冒出来、老集群变大、连接越来越多。 按下播放,看你的专长在几个月里怎么一步步长出来:新的兴趣什么时候出现,什么时候和已有知识接上,又是什么时候长成一整片集群。
### 探索和发现 [#探索和发现-step] 在图谱里走动: * 点击任意节点看它的详情 * 双击展开它的邻居 * Shift+拖动用套索框选多个节点 * 按 C 开关社区气泡 * 按 E 展开所选节点的邻居 找到你从来没留意过的模式: > 每条领导力记忆都链接回调试会话。我通过教调试来领导。
## 你将发现什么 [#你将发现什么] ### 专长集群 [#专长集群] 社区检测会把你的知识自然抱团的地方显出来: * 核心优势:又大又密的集群 * 新兴领域:还小、但正在长大的集群 * 桥梁:同时连着好几个集群的节点,往往就是你最独到的本事 ### 知识演化 [#知识演化] 后台智能会追踪你的想法怎么变: * 周二:"新服务用 PostgreSQL" * 周四:"考虑迁到 CockroachDB" * 周五简报:"你的数据库选型在变" 这些演化链在图谱里就是一串连起来的节点。你能清清楚楚看到自己的看法是在哪里转的弯,整个过程一目了然。 ### 隐藏模式 [#隐藏模式] 边逛边发现: * 那些反复出现、但你从没刻意记过的主题 * 看着八竿子打不着的项目之间,其实有联系 * 你自己独特的视角和做法 * 相邻主题之间还空着的那块 ## 向 AI 询问你的图谱 [#向-ai-询问你的图谱] 看着你的图谱,让 AI Now 替你讲讲它: > 基于我的知识图谱,什么职业道路最适合我? AI Now 把这些串起来: > 你的记忆里,深厚的系统功底和教学能力交汇在一起,这个组合并不常见。你最核心的几个概念(事件驱动架构、调试)正好把技术集群和领导力集群连了起来。可以考虑:Staff Engineer、Developer Advocate,或者偏技术的 Engineering Manager。 还可以这样问: * "我最强的专长领域是什么?" * "我的知识差距在哪里?" * "接下来我应该探索什么主题?" * "我的重点是如何随时间变化的?" ## 时间的积累 [#时间的积累] 记忆越多,图谱越满,看出来的东西也越深。 用了一个月: > 主要主题能看出来了,就是每个集群还很小。 用了半年: > 专长领域已经很清楚了。一些意想不到的连接开始冒出来,后台智能还帮我找到了一些自己没注意到的模式。 用满一年: > 我真能看见自己的思路是怎么变的了。之前搭起来的那些连接,成了后来的底子。 到了绩效评估的时候: > 评估前我先把自己的图谱过了一遍,每个维度都能拿出实打实的成长例子。 ## 下一步 [#下一步] * [后台智能](/zh/docs/advanced-features):图谱如何自动生长 * [你的知识,你做主](/zh/docs/use-cases/shared-memory):自由切换工具,不丢失上下文 * [穿越时间搜索](/zh/docs/use-cases/bi-temporal):时间查询和演化链 # 概述 (/docs/zh/use-cases) 你和 AI 一起干的活,Nowledge Mem 会一点点替你沉淀下来。它按各个工具最合适的方式抓取对话,让会话和记忆都能搜,还在后台不停地整理你的知识图谱。已连接的工具也就能带着更完整的上下文开工。 先挑一个你最想解决的问题看起。头一天,不用把 Mem 的本事全摸透。 告诉 Claude 一次,Cursor 也能接上。一个知识库,覆盖你连接到 Mem 的 AI 工具。 原生保存路径、连接器实时捕获、本地回填和浏览器捕获,让重要对话持续可搜索。 董事会问为什么选了 React Native。找到你当时相信的,而不是你现在知道的。 Obsidian、Notion、PDF、Word 文档。一次搜索覆盖所有知识源。 图谱从你的记忆中自动构建。社区检测揭示你不知道自己拥有的专长集群。 运行在本地的个人 AI 智能体。它可以使用你保存的知识、文件和已启用的插件来完成深度研究、文件分析和演示文稿。 ## Mem 改变了什么 [#mem-改变了什么] 浏览器扩展会从受支持的 Web AI 聊天平台抓取洞察和对话备份。支持 hook 的原生连接会捕获新的编程智能体工作,本地导入负责回填旧会话,Timeline 也随时能直接输入、保存。选对捕获路径,剩下的不用你操心。 你不动手整理的时候,Mem 也在替你整理。后台智能盯着你思路上的变化,把零散记忆收拢成参考内容,把矛盾标出来。每天早上的 Working Memory 简报,会在你开口之前先把重点递给 AI 工具。 原生连接、复用型工作流包和直接 MCP,连的都是同一套记忆。换工具,知识照旧。 ## 工作原理 [#工作原理] 1. 捕获:浏览器抓取、原生保存路径、连接器实时捕获、本地回填,或者直接在 Timeline 里敲进来 2. 连接:系统把它和你已有的所有知识关联起来 3. 生长:后台智能在夜里搭起演化链、知识结晶和各种标记 4. 使用:已连接的工具需要时就能找到它 知识攒在 Mem 里,不靠任何单个工具。 ## 开始 [#开始] 上面哪个问题正戳中你现在的痛点,就从那张卡片入手;要是还拿不准,先回到[从这里开始](/zh/docs/start-here)或[快速上手](/zh/docs/getting-started),先把一个小流程走通。 # 你的笔记,无处不在 (/docs/zh/use-cases/notes-everywhere) ## 问题所在 [#问题所在] 你记了好多年笔记,用 Obsidian,用 Notion,也许两个都用。 几千条记录,标签打得仔细,链接连得密。可是, > 我知道我写过这个,就是怎么都找不到。搜也搜不出来,标签也没用。 更糟的是,AI 助手压根不知道这些笔记的存在,笔记里早写过的东西,你每次还得重新跟它讲一遍。 ## 解决方案 [#解决方案] 不替换你的笔记应用,而是把它接进你的知识。 Obsidian、Notion、Apple Notes 或者一个 Markdown 文件夹,你原来怎么用还怎么用。Nowledge Mem 会把它们接进来,让你的笔记在 AI Now 里能搜到,也能配合其他接进 Mem 的 AI 工具一起用。 有了「资料库」,你还能把 PDF、Word 文档、演示文稿直接拖进来,所有东西在一个地方搜。 笔记无处不在 ## 工作原理 [#工作原理]
### 连接你的笔记 [#连接你的笔记-step] Obsidian: 1. 在 Nowledge Mem 里打开 AI Now 2. 进入 **插件**,开启 **Obsidian** 3. 填上你的知识库路径(比如 `/Users/you/Documents/ObsidianVault`) 4. 完成。AI Now 现在能搜你的知识库了 笔记无处不在 Notion: 1. 打开 AI Now,进入 **插件**,开启 **Notion** 2. 点 **连接 Notion** 3. 在弹出的浏览器窗口里授权 4. 你的工作区现在能访问了
### 将文档导入资料库 [#将文档导入资料库-step] 把文件直接拖进 Timeline 输入框,或者打开资料库视图: | 格式 | 扩展名 | 处理方式 | | ------------ | ----------- | ----------- | | **PDF** | .pdf | 提取文本,分段,索引 | | **Word** | .docx, .doc | 解析为文本,分段,索引 | | **演示文稿** | .pptx | 提取幻灯片内容并索引 | | **Markdown** | .md | 直接解析并索引 | 索引建好后,文档内容就能和你的记忆、笔记放在一起搜了。
### 跨所有内容搜索 [#跨所有内容搜索-step] 向 AI Now 提问任何问题: > 我的笔记关于量子计算说了什么? AI Now: 1. 搜索你的 Obsidian 知识库 2. 搜索你的 Notion 工作区 3. 搜索你的 Nowledge 记忆 4. 搜索你的资料库文档 5. 组合并综合结果 问一句,把所有知识源都搜了。
### 提炼成记忆 [#提炼成记忆-step] 翻到了有价值的笔记?把它们变成永久记忆: > 从这些量子计算笔记中提炼关键洞察 AI Now 创建: * **洞察**:"量子纠错需要 O(n^2) 量子比特" * **决定**:"近期研究专注于 NISQ 算法" * **事实**:"IBM 在 2023 年 12 月宣称量子优势" 这些记忆从此: * 能靠语义理解搜到 * 接进了知识图谱 * 接进 Mem 的各个 AI 工具都能一起用 * 相关的时候会出现在你的工作记忆简报里
## Obsidian 集成 [#obsidian-集成] ### 设置 [#设置]
#### 打开 Nowledge Mem [#打开-nowledge-mem-step] 打开 Nowledge Mem 应用。
#### 点击 AI Now 标签 [#点击-ai-now-标签-step] 在侧边栏中选择 **AI Now** 标签。
#### 前往插件 [#前往插件-step] 在侧边栏中打开 **插件**。
#### 启用 Obsidian [#启用-obsidian-step] 找到 **Obsidian** 并切换开启。
#### 输入知识库路径 [#输入知识库路径-step] 示例:`/Users/yourname/Documents/ObsidianVault`
### 你可以做什么 [#你可以做什么] 连接后: * 按内容搜索笔记:*"找到我关于机器学习的笔记"* * 阅读特定笔记:*"显示我关于项目启动的笔记"* * 在上下文中引用:*"基于我关于 X 的 Obsidian 笔记,帮我..."* 你的知识库在本地读取。笔记永远不会上传到任何地方。Nowledge Mem 只是读取你机器上的文件。 ## Notion 集成 [#notion-集成] ### 设置 [#设置-1]
#### 打开 AI Now 插件 [#打开-ai-now-插件-step] 打开 AI Now → **插件**。
#### 连接 Notion [#连接-notion-step] 找到 **Notion** 并点击 **连接**。
#### 在浏览器中授权 [#在浏览器中授权-step] 在浏览器弹出窗口中完成授权。
#### 选择工作区 [#选择工作区-step] 选择你想连接的工作区。
### 你可以做什么 [#你可以做什么-1] * 搜索你的工作区:*"找到关于季度规划的页面"* * 阅读页面内容:*"我的产品路线图页面里有什么?"* * 交叉引用:*"比较我的 Notion 笔记与我关于 X 的记忆"* * 结合公开信息和私人知识进行深度研究:*"量子计算的最新进展是什么?"* Notion 使用安全的 OAuth。你完全控制 Nowledge Mem 可以访问哪些页面。随时从 Notion 设置中撤销。 ## 内置集成 [#内置集成] 部分工具已内置 Nowledge Mem: * **DeepChat**:在设置中开启 Nowledge Mem。你的记忆在每次对话中可用。 * **LobeHub**:从市场安装。完整 MCP 集成。 * **Apple Notes(macOS)**:启用 AI Now 内置插件后即可搜索你的 Apple Notes。 加入[社区](/zh/docs/community)请求集成。 ## 下一步 [#下一步] * [AI Now](/zh/docs/ai-now):了解 AI Now 还能做什么 * [资料库](/zh/docs/library):导入和搜索文档 * [看见你的专长](/zh/docs/use-cases/expertise-graph):可视化你的知识图谱 * [连接](/zh/docs/integrations):完整设置指南 # 永不丢失会话 (/docs/zh/use-cases/session-backup) ## 问题所在 [#问题所在] 你刚跟 Claude Code 鏖战了三个小时调试。揪出一个竞态条件,翻遍了 15 个文件,写出一个带测试、干净利落的修复。 可惜 AI 对话留不住。上下文被压缩,token 用到了上限,会话也过期了。一条两百条消息的对话,早先那些内容早就没影了。 > "我以前解决过这个完全相同的问题。我只是不记得怎么解决的了。或者在哪里。或者什么时候。" ## 解决方案 [#解决方案] 你的会话会按各个工具最合适的路径进到 Mem。宿主支持的话,原生连接会把真实会话记录存下来;本地导入用来回填旧的编程智能体会话;ChatGPT、Claude、Gemini 的浏览器对话则由扩展直接抓取。只有当你手上本来就有导出文件时,才需要走导入这条路。 准备好之后,把对话提炼成永久、可搜索、连进图谱的记忆。 选一段你本来就在意的对话,让它进到 Threads,再从里面提炼出一条真正有用的记忆。之后你既能翻回原始对话,又能搜到那条提炼出来的记忆,这一趟就跑通了。 ## 工作原理 [#工作原理]
### 会话会通过不同路径进入 Mem [#会话会通过不同路径进入-mem-step] 原生实时捕获(Claude Code、Codex、Gemini CLI、OpenCode)。专属连接会在智能体运行的那台机器上保存真实 transcript。OpenCode 会在宿主报告 idle 后自动捕获,并在压缩前 flush 一次。 本地回填(Claude Code、Cursor、Codex、OpenCode)。当你想把旧历史放进 Threads,Nowledge Mem 可以从本机磁盘扫描这些编程会话。使用导入视图,或在保存会话的机器上执行 `nmem t sync --from `。 以交接摘要为主的原生路径(Droid、Cursor)。有些工具已经有了原生包,但在真正的 transcript 导入器出现之前,它们刻意只给一份能续上的交接摘要。这样既保住了跨会话的连续性,也不会把摘要硬说成完整的会话保存。 浏览器捕获(ChatGPT、Gemini、Claude Web)。Exchange v2 扩展会从受支持的 Web AI 聊天平台抓取对话。你聊着天,洞察和对话备份就一并进了 Mem。 手动提炼或交接摘要: ``` /sum -> 将长期有价值的洞察提炼成记忆 /save -> 根据集成能力创建交接摘要,或触发该工具自己的保存路径 ```
### 提炼成永久知识 [#提炼成永久知识-step] 打开保存好的对话,点「提炼」。AI 会把整段对话读一遍,从里面挑出: * **决定**:"选择滑动窗口而不是令牌桶因为..." * **洞察**:"异步回调中的竞态条件需要互斥锁" * **模式**:"测试基于时间的 bug 需要模拟时钟" * **事实**:"Redis SETNX 提供原子锁获取" 每一条都会变成一条独立、可搜索的记忆,并打上合适的标签。
### 后台智能自动连接 [#后台智能自动连接-step] 新存的记忆不会孤零零地待着。后台智能会: * 把它们和同一个代码库里以前的工作接上 * 看它们有没有更新或推翻早先的决定 * 把它们连到知识图谱里相关的实体上 * 在第二天早上的工作记忆简报里冒出来 三个月后,同事撞上同一个 bug。还没等他开口,你的简报就先把它点出来了。
### 随时搜索 [#随时搜索-step] 三个月后,类似的 bug 出现: > 搜索:"支付竞态条件" Nowledge Mem 把完整上下文还给你:问题、调试步骤、解决方案、测试方法。 已经解过的问题,不用再解第二遍。
## 捕获来源 [#捕获来源] | 来源 | 方式 | 捕获内容 | | ---------------------- | ----------------------------- | ------------------------------- | | **Claude Code** | 原生连接保存或本地自动同步 | 带代码上下文的完整会话 | | **Gemini CLI** | 原生扩展 `save-thread` | 真实录制的 Gemini 会话 | | **Droid** | 原生连接 `save-handoff` | Droid 内的可恢复交接摘要,并明确不把它包装成完整会话导入 | | **Codex** | 原生连接 Stop hook 或本地自动同步 | 带代码上下文的完整会话 | | **Cursor** | 插件 `save-handoff`、本地自动同步或手动导入 | 插件中的可恢复交接摘要,以及你机器上的本地对话导入 | | **OpenCode** | 原生插件 idle 捕获;CLI/导入回填旧会话 | 新会话实时进入 Mem,旧历史导入后可搜索 | | **ChatGPT** | 浏览器扩展(自动捕获) | 网页聊天中的洞察与完整对话备份 | | **Claude Web** | 浏览器扩展(自动捕获) | 网页聊天中的洞察与完整对话备份 | | **Gemini** | 浏览器扩展(自动捕获) | 网页聊天中的洞察与完整对话备份 | | **更多受支持的 Web AI 聊天平台** | 浏览器扩展 | 在受支持的网站上使用同样的捕获模型 | ## 提取的内容 [#提取的内容] 当你提炼对话线程时,AI 按类型创建记忆: | 类型 | 示例 | 标签 | | ------ | ------------------ | -------- | | **决定** | "使用 Redis 进行分布式锁" | 决定、架构 | | **洞察** | "异步回调需要仔细排序" | 洞察、调试 | | **过程** | "重现竞态条件的步骤" | 过程、测试 | | **事实** | "SETNX 如果键被设置返回 1" | 事实、redis | | **经验** | "支付服务的调试会话" | 经验、项目 | ## 时间的积累 [#时间的积累] 一条对话顶用,十条就成了知识库,一百条就是你的团队记忆。 > "今天初级开发者遇到了同样的 bug。发给他们我的记忆。他们20分钟修复了,而不是3小时。" 一次调试会话不只是一段对话,更是留给以后的自己、随时能再用的知识。 ## 专业提示 [#专业提示] 你不需要提炼每个对话线程。保存重要的会话:突破、架构决定、来之不易的解决方案。 对于敏感代码库,审查你正在保存的内容。对话线程可能包含专有代码或凭据。 ## 下一步 [#下一步] * [你的知识,你做主](/zh/docs/use-cases/shared-memory):自由切换工具,不丢失上下文 * [穿越时间搜索](/zh/docs/use-cases/bi-temporal):从特定时间段找到记忆 * [连接](/zh/docs/integrations):每个工具的设置指南 # 你的知识,你做主 (/docs/zh/use-cases/shared-memory) ## 问题所在 [#问题所在] 上周你把项目架构跟 Claude Code 讲了一遍。今天换 Cursor,又得从头讲一遍。明天想试试大家都在聊的新工具,结果还是从零开始。 问题不在你记不住,而在于知识被锁死在了上一个工具里。 > "我已经解释过了。为什么换个工具就得重来?" ## 解决方案 [#解决方案] Nowledge Mem 夹在你和各个 AI 工具中间,是一层共用的知识系统。它会自动把你的洞察记下来,把会话和记忆都收进同一个能搜索的地方,再生成每日简报,让支持的工具一上来就带着更完整的上下文。 重点不在于所有工具都用同一种装法,而在于它们最后都连到同一套记忆上。 如果你现在最头疼的就是「换个工具又得重讲一遍」,那就先小试一把:在 Mem 里存一条决策,接上你最常用的工具,过一会儿换第二个工具来问同一个主题。只要它能把那条决策找回来,这事就成了。 共享记忆 ## 工作原理 [#工作原理]
### 为你的工具选择合适的连接方式 [#为你的工具选择合适的连接方式-step] * 专属集成:Claude Code、Grok Build、Codex、Gemini CLI、OpenClaw、Hermes Agent、Alma、Cursor、Droid、OpenCode 和 Copilot CLI 用这个,上手体验最好。 * 复用型工作流包:还没有专属包的智能体环境用它。 * 直接 MCP:没有专属包、但支持 MCP 的客户端用它。 很多编程智能体最快的复用方式,还是这一条: ```bash npx skills add nowledge-co/community/nowledge-mem-npx-skills ``` 装好之后,智能体一开会话就能读到简报,干活时随手搜你的知识,遇到值得长期留下的东西也会顺手存上。
### 捕获会自然发生 [#捕获会自然发生-step] 你不用专门记着去保存,Mem 会从好几个渠道把内容收进来: 浏览器扩展(Exchange v2)会盯着你在受支持的 Web AI 聊天平台上的对话,你忙你的,洞察自动就存下来了。 会话捕获与同步:本地编程会话能实时自动同步;宿主支持的话,原生连接还会给一条专门保存真实会话的路径。 Timeline 输入:敲一个想法、贴一个 URL、拖一个文件进来,想单独留点什么的时候用它。 手动命令: ``` /sum -> 将此对话总结成记忆 /save -> 根据当前集成执行对应的保存或交接摘要动作 ```
### 已连接的工具知情启动 [#已连接的工具知情启动-step] 每天早上,后台智能都会写一份 Working Memory 简报。已连接的工具一开会话,就会按各自的接入方式读到当前分区对应的那份。 这时你的智能体已经知道: * 你正在忙什么 * 你最近做了哪些决策 * 还悬着的问题和矛盾 * 你的想法是怎么变的 不用再从头解释。早上九点打开 Claude Code,它接着你上次停下的地方往下做。
### 自由切换工具 [#自由切换工具-step] 来了个新工具?按它支持的最好方式接上 Mem,它就能用上同一套共享上下文。 比如: 你存过:*"架构决定:会话管理用 Redis,因为……"* 后来在 Cursor 里:*"帮我加上会话处理"* Cursor 搜了你的知识,翻到那条 Redis 决定,照着同样的套路来。不用你再解释一遍。
## 实际示例 [#实际示例] **没有 Nowledge Mem:** > 你:"帮我实现限流" > > Claude:"什么类型?令牌桶?滑动窗口?你的用例是什么?" > > 你:*\[这个月第5次解释]* **有 Nowledge Mem:** > 你:"帮我实现限流" > > Claude:*\[读取工作记忆简报,搜索你的记忆]* "根据你上个月对支付服务使用滑动窗口限流的决定,这是一个匹配你 Redis 模式的实现..." ## 连接方式 [#连接方式] | 渠道 | 如何工作 | 捕获什么 | | ------------------ | ------------- | ------------------------------------ | | **原生连接** | 工具专属包 | 工作记忆简报、检索、提炼,以及该工具对应的保存路径 | | **复用型工作流包** | 共享提示词或技能 | 工作记忆简报、搜索、保存、提炼 | | **浏览器扩展** | 自动捕获 AI 对话 | 来自受支持的 Web AI 聊天平台的洞察 | | **会话捕获与回填** | 原生 hook 加本地导入 | Claude Code、Cursor、Codex、OpenCode 会话 | | **MCP** | 直接协议连接 | 任何兼容 MCP 的工具 | | **Claude Desktop** | 一键扩展 | 完整集成 | | **内置支持** | 在设置中切换 | DeepChat、LobeHub | ## 用得越久,切换越轻松 [#用得越久切换越轻松] 用上几周,新接进来的工具很快就摸清了你做事的路数。偏好在工具之间延续,决策一点点攒下来,存过的洞察以后换什么工具都能搜得到。 价值是攒在 Mem 里的,不挂在任何一个工具上。 ## 下一步 [#下一步] * [永不丢失会话](/zh/docs/use-cases/session-backup):自动同步和备份 AI 对话 * [穿越时间搜索](/zh/docs/use-cases/bi-temporal):找到你当时知道的 * [连接](/zh/docs/integrations):连接所有工具 # Get Evolves Edges (/docs/api/agent/evolves/get) ## GET /agent/evolves **Summary:** Get Evolves Edges Get memory evolution chains. Shows how memories have been updated, enriched, or superseded over time. Filter by a specific `memory_id` to see its full version history. Use `offset` to paginate; `total` in the response reflects the count under the same filters. ### OpenAPI Operation ```json { "/agent/evolves": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Get Evolves Edges", "description": "Get memory evolution chains.\n\nShows how memories have been updated, enriched, or superseded over time. Filter by a specific `memory_id` to see its full version history. Use `offset` to paginate; `total` in the response reflects the count under the same filters.", "operationId": "get_evolves_edges_agent_evolves_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "default": 50, "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset" } }, { "name": "content_relation", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Content Relation" } }, { "name": "unreviewed_only", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Unreviewed Only" } }, { "name": "memory_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to EVOLVES edges where this memory appears as older or newer node.", "title": "Memory Id" }, "description": "Filter to EVOLVES edges where this memory appears as older or newer node." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Evolves Edges Agent Evolves Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Agent Status (/docs/api/agent/status/get) ## GET /agent/status **Summary:** Get Agent Status Get the Knowledge Agent's current status. ### OpenAPI Operation ```json { "/agent/status": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Get Agent Status", "description": "Get the Knowledge Agent's current status.", "operationId": "get_agent_status_agent_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Get Agent Status Agent Status Get" } } } } } } } } ``` # Get Token Usage Summary (/docs/api/agent/token-usage/get) ## GET /agent/token-usage **Summary:** Get Token Usage Summary Return the local model-usage ledger for UI and enterprise integrations. ### OpenAPI Operation ```json { "/agent/token-usage": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Get Token Usage Summary", "description": "Return the local model-usage ledger for UI and enterprise integrations.", "operationId": "get_token_usage_summary_agent_token_usage_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Get Token Usage Summary Agent Token Usage Get" } } } } } } } } ``` # Get Working Memory (/docs/api/agent/working-memory/get) ## GET /agent/working-memory **Summary:** Get Working Memory Read the agent's working memory. Returns today's working memory by default. Pass a `date` (YYYY-MM-DD) to read an archived day instead. ### OpenAPI Operation ```json { "/agent/working-memory": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Get Working Memory", "description": "Read the agent's working memory.\n\nReturns today's working memory by default. Pass a `date` (YYYY-MM-DD) to read an archived day instead.", "operationId": "get_working_memory_agent_working_memory_get", "parameters": [ { "name": "date", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "YYYY-MM-DD for archived WM", "title": "Date" }, "description": "YYYY-MM-DD for archived WM" }, { "name": "space_id", "in": "query", "required": false, "schema": { "type": "string", "description": "Isolation space to read", "default": "default", "title": "Space Id" }, "description": "Isolation space to read" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Working Memory Agent Working Memory Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Working Memory (/docs/api/agent/working-memory/put) ## PUT /agent/working-memory **Summary:** Update Working Memory Save changes to the agent's working memory. Content must include at least a Focus Areas or Briefing section. Maximum 4 KB. ### OpenAPI Operation ```json { "/agent/working-memory": { "put": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Update Working Memory", "description": "Save changes to the agent's working memory.\n\nContent must include at least a Focus Areas or Briefing section. Maximum 4 KB.", "operationId": "update_working_memory_agent_working_memory_put", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateWorkingMemoryRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Update Working Memory Agent Working Memory Put" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Community Details (/docs/api/communities/community_id/get) ## GET /communities/{community_id} **Summary:** Get Community Details Get community details including entities and sample memories. ### OpenAPI Operation ```json { "/communities/{community_id}": { "get": { "tags": [ "analytics" ], "summary": "Get Community Details", "description": "Get community details including entities and sample memories.", "operationId": "get_community_details_communities__community_id__get", "parameters": [ { "name": "community_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Community Id" } }, { "name": "entity_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 50, "minimum": 1, "default": 20, "title": "Entity Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Context Bundle (/docs/api/context/bundle/get) ## GET /context/bundle **Summary:** Get Context Bundle Return the owner/profile/policy/scope context bundle for agents. ### OpenAPI Operation ```json { "/context/bundle": { "get": { "tags": [ "context", "context" ], "summary": "Get Context Bundle", "description": "Return the owner/profile/policy/scope context bundle for agents.", "operationId": "get_context_bundle_context_bundle_get", "parameters": [ { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Nowledge agent profile id/slug to resolve.", "title": "Agent Id" }, "description": "Nowledge agent profile id/slug to resolve." }, { "name": "source_app", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Calling app/source hint, e.g. codex or hermes.", "title": "Source App" }, "description": "Calling app/source hint, e.g. codex or hermes." }, { "name": "host_agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Host-local long-running agent identity, if known.", "title": "Host Agent Id" }, "description": "Host-local long-running agent identity, if known." }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Memory space id/name to use as the active lane.", "title": "Space Id" }, "description": "Memory space id/name to use as the active lane." }, { "name": "include_working_memory", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include the current Working Memory preview.", "default": true, "title": "Include Working Memory" }, "description": "Include the current Working Memory preview." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Checkpoint Data (/docs/api/data/checkpoint/post) ## POST /data/checkpoint **Summary:** Checkpoint Data Flush pending changes to disk. Ensures all recent writes are safely persisted. Called automatically before app updates, but can be triggered manually. ### OpenAPI Operation ```json { "/data/checkpoint": { "post": { "tags": [ "data-transfer" ], "operationId": "checkpoint_data_data_checkpoint_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataTransferCheckpointResponse" } } } } }, "summary": "Checkpoint Data", "description": "Flush pending changes to disk.\n\nEnsures all recent writes are safely persisted. Called automatically before app updates, but can be triggered manually." } } } ``` # Export Data (/docs/api/data/export/post) ## POST /data/export **Summary:** Export Data Export your data to a portable archive. Creates a .zip (or folder) containing memories, threads, entities, labels, sources, managed skills, and working memory. Use this for backups or migrating to another device. By default this endpoint is synchronous for REST and CLI compatibility. Set `async` to `true` to start a background export job and poll `/data/export/status/{job_id}` until the job is completed or reports an error. ### OpenAPI Operation ```json { "/data/export": { "post": { "tags": [ "data-transfer" ], "operationId": "export_data_data_export_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataExportRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataExportResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "summary": "Export Data", "description": "Export your data to a portable archive.\n\nCreates a .zip (or folder) containing memories, threads, entities, labels,\nsources, managed skills, and working memory. Use this for backups or\nmigrating to another device.\n\nBy default this endpoint is synchronous for REST and CLI compatibility.\nSet `async` to `true` to start a background export job and poll\n`/data/export/status/{job_id}` until the job is completed or reports an error." } } } ``` # Import Data (/docs/api/data/import/post) ## POST /data/import **Summary:** Import Data Import data from a previous export. Runs in the background. Poll `/data/import/status/{job_id}` to check progress. Supports merge (combine with existing), skip (keep existing), or overwrite modes. ### OpenAPI Operation ```json { "/data/import": { "post": { "tags": [ "data-transfer" ], "operationId": "import_data_data_import_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataImportRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataImportStartResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "summary": "Import Data", "description": "Import data from a previous export.\n\nRuns in the background. Poll `/data/import/status/{job_id}` to check progress. Supports merge (combine with existing), skip (keep existing), or overwrite modes." } } } ``` # Delete an entity (/docs/api/entities/entity_id/delete) ## DELETE /entities/{entity_id} **Summary:** Delete an entity Delete one Entity and its incident graph links without deleting any Memory, Source, Label, or Community. Requires an exact entity-id confirmation. ### OpenAPI Operation ```json { "/entities/{entity_id}": { "delete": { "tags": [ "entities" ], "summary": "Delete an entity", "description": "Delete one Entity and its incident graph links without deleting any Memory, Source, Label, or Community. Requires an exact entity-id confirmation.", "operationId": "delete_entity_handler", "parameters": [ { "name": "entity_id", "in": "path", "description": "Entity id", "required": true, "schema": { "type": "string" } }, { "name": "confirm_entity_id", "in": "query", "description": "Must exactly match the entity id in the path.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Entity deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EntityMutationResponse" } } } }, "404": { "description": "Entity not found" }, "422": { "description": "Confirmation does not match the entity id" } } } } } ``` # Event Stream (/docs/api/events/stream/get) ## GET /events/stream **Summary:** Event Stream Server-Sent Events stream for real-time updates. Emits data-change, progress, and stage events as they occur. Connect using the browser EventSource API or any SSE client. ### OpenAPI Operation ```json { "/events/stream": { "get": { "tags": [ "events", "events" ], "summary": "Event Stream", "description": "Server-Sent Events stream for real-time updates.\n\nEmits data-change, progress, and stage events as they occur.\nConnect using the browser EventSource API or any SSE client.", "operationId": "event_stream_events_stream_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } } } ``` # Get Favorite Memories (/docs/api/favorites/memories/get) ## GET /favorites/memories **Summary:** Get Favorite Memories Get all favorite memories. ### OpenAPI Operation ```json { "/favorites/memories": { "get": { "tags": [ "memories" ], "summary": "Get Favorite Memories", "description": "Get all favorite memories.", "operationId": "get_favorite_memories_favorites_memories_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 50, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/MemoryPublic" }, "title": "Response Get Favorite Memories Favorites Memories Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Favorite Threads (/docs/api/favorites/threads/get) ## GET /favorites/threads **Summary:** Get Favorite Threads Get all favorite threads. ### OpenAPI Operation ```json { "/favorites/threads": { "get": { "tags": [ "memories" ], "summary": "Get Favorite Threads", "description": "Get all favorite threads.", "operationId": "get_favorite_threads_favorites_threads_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 50, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/nowledge_graph_server__models__memories_api__ThreadPublic" }, "title": "Response Get Favorite Threads Favorites Threads Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Capabilities (/docs/api/fs/capabilities/get) ## GET /fs/capabilities **Summary:** Fs Capabilities Return the machine-readable Nowledge FS contract. ### OpenAPI Operation ```json { "/fs/capabilities": { "get": { "tags": [ "files", "files" ], "summary": "Fs Capabilities", "description": "Return the machine-readable Nowledge FS contract.", "operationId": "fs_capabilities_fs_capabilities_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } } } ``` # Fs Cat (/docs/api/fs/cat/get) ## GET /fs/cat **Summary:** Fs Cat Return the rendered body of a Nowledge FS file. For ``.md`` files this returns YAML-frontmatter markdown. For ``messages.jsonl`` it returns one JSON object per line. Fragment selectors (``:page/N``, ``:section/``, etc.) are documented in the design doc but land in Phase 2; passing one returns ENOTSUP for now. ``line`` / ``lines`` are Phase 1 progressive-read controls for agents: they work for every rendered text body, including thread ``messages.jsonl`` where one line is one message. ### OpenAPI Operation ```json { "/fs/cat": { "get": { "tags": [ "files", "files" ], "summary": "Fs Cat", "description": "Return the rendered body of a Nowledge FS file.\n\nFor ``.md`` files this returns YAML-frontmatter markdown. For\n``messages.jsonl`` it returns one JSON object per line. Fragment\nselectors (``:page/N``, ``:section/``, etc.) are documented in\nthe design doc but land in Phase 2; passing one returns\nENOTSUP for now. ``line`` / ``lines`` are Phase 1 progressive-read\ncontrols for agents: they work for every rendered text body, including\nthread ``messages.jsonl`` where one line is one message.", "operationId": "fs_cat_fs_cat_get", "parameters": [ { "name": "path", "in": "query", "required": true, "schema": { "type": "string", "description": "Nowledge FS file path", "title": "Path" }, "description": "Nowledge FS file path" }, { "name": "line", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "minimum": 1 }, { "type": "null" } ], "description": "One-based line to start reading from", "title": "Line" }, "description": "One-based line to start reading from" }, { "name": "lines", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 1000, "minimum": 1 }, { "type": "null" } ], "description": "Number of lines to return", "title": "Lines" }, "description": "Number of lines to return" }, { "name": "fragment", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Fragment selector (page|section|sheet|slide|chunk) — Phase 2", "title": "Fragment" }, "description": "Fragment selector (page|section|sheet|slide|chunk) — Phase 2" }, { "name": "raw", "in": "query", "required": false, "schema": { "type": "boolean", "description": "For .source.* files: return original bytes (501 in Phase 1)", "default": false, "title": "Raw" }, "description": "For .source.* files: return original bytes (501 in Phase 1)" }, { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Agent identity id/slug for /context/* files", "title": "Agent Id" }, "description": "Agent identity id/slug for /context/* files" }, { "name": "source_app", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Calling app provenance hint for /context/* files", "title": "Source App" }, "description": "Calling app provenance hint for /context/* files" }, { "name": "host_agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Host-local long-running agent id for /context/* files", "title": "Host Agent Id" }, "description": "Host-local long-running agent id for /context/* files" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Active space override for /context/* files", "title": "Space Id" }, "description": "Active space override for /context/* files" }, { "name": "include_working_memory", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include Working Memory preview in /context/* files", "default": true, "title": "Include Working Memory" }, "description": "Include Working Memory preview in /context/* files" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Delete (/docs/api/fs/delete/post) ## POST /fs/delete **Summary:** Fs Delete Delete/archive a canonical Nowledge FS file. Memory delete delegates to the existing Memories delete path, preserving the object's concrete space. Working Memory delete has no safe helper in this slice and returns ``ENOTSUP``. ### OpenAPI Operation ```json { "/fs/delete": { "post": { "tags": [ "files", "files" ], "summary": "Fs Delete", "description": "Delete/archive a canonical Nowledge FS file.\n\nMemory delete delegates to the existing Memories delete path, preserving\nthe object's concrete space. Working Memory delete has no safe helper in\nthis slice and returns ``ENOTSUP``.", "operationId": "fs_delete_fs_delete_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FSDeleteRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Find (/docs/api/fs/find/get) ## GET /fs/find **Summary:** Fs Find Structural / metadata search. Returns paths. Phase 1 covers ``type``, ``unit_type``, ``label``, ``since``, ``until``, and ``mentions`` over ``/memories``. ``unit_type`` is also inferred from ``/memories/by-type/``. Other roots return an empty result so callers can compose without errors. ### OpenAPI Operation ```json { "/fs/find": { "get": { "tags": [ "files", "files" ], "summary": "Fs Find", "description": "Structural / metadata search. Returns paths.\n\nPhase 1 covers ``type``, ``unit_type``, ``label``, ``since``, ``until``,\nand ``mentions`` over ``/memories``. ``unit_type`` is also inferred from\n``/memories/by-type/``. Other roots return an empty result so\ncallers can compose without errors.", "operationId": "fs_find_fs_find_get", "parameters": [ { "name": "path", "in": "query", "required": false, "schema": { "type": "string", "description": "Nowledge FS path scope (e.g. '/memories')", "default": "/memories", "title": "Path" }, "description": "Nowledge FS path scope (e.g. '/memories')" }, { "name": "type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by file type: memory | crystal", "title": "Type" }, "description": "Filter by file type: memory | crystal" }, { "name": "unit_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter memories by unit type; also inferred from /memories/by-type/ paths", "title": "Unit Type" }, "description": "Filter memories by unit type; also inferred from /memories/by-type/ paths" }, { "name": "label", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by label name", "title": "Label" }, "description": "Filter by label name" }, { "name": "since", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Lower record-time bound (YYYY-MM-DD or ISO8601)", "title": "Since" }, "description": "Lower record-time bound (YYYY-MM-DD or ISO8601)" }, { "name": "until", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Upper record-time bound (YYYY-MM-DD or ISO8601)", "title": "Until" }, "description": "Upper record-time bound (YYYY-MM-DD or ISO8601)" }, { "name": "mentions", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter memories that MENTION this entity name", "title": "Mentions" }, "description": "Filter memories that MENTION this entity name" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 200, "title": "Limit" } }, { "name": "cursor", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Opaque pagination cursor", "title": "Cursor" }, "description": "Opaque pagination cursor" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Grep (/docs/api/fs/grep/get) ## GET /fs/grep **Summary:** Fs Grep Content search. Returns ``path:line:match`` shaped hits. Preview space contract: graph-wide projection. Phase 1 covers memory/crystal bodies, thread messages, and parsed Library documents. Memory grep can be narrowed with ``unit_type`` or a ``/memories/by-type/`` path. ### OpenAPI Operation ```json { "/fs/grep": { "get": { "tags": [ "files", "files" ], "summary": "Fs Grep", "description": "Content search. Returns ``path:line:match`` shaped hits.\n\nPreview space contract: graph-wide projection. Phase 1 covers\nmemory/crystal bodies, thread messages, and parsed Library documents.\nMemory grep can be narrowed with ``unit_type`` or a\n``/memories/by-type/`` path.", "operationId": "fs_grep_fs_grep_get", "parameters": [ { "name": "q", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "description": "Fixed string or regex pattern to find", "title": "Q" }, "description": "Fixed string or regex pattern to find" }, { "name": "path", "in": "query", "required": false, "schema": { "type": "string", "description": "Nowledge FS path scope. Supports /memories, /threads, and /sources in this preview.", "default": "/memories", "title": "Path" }, "description": "Nowledge FS path scope. Supports /memories, /threads, and /sources in this preview." }, { "name": "unit_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter memory grep by unit type; also inferred from /memories/by-type/ paths", "title": "Unit Type" }, "description": "Filter memory grep by unit type; also inferred from /memories/by-type/ paths" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 200, "title": "Limit" } }, { "name": "cursor", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Opaque pagination cursor", "title": "Cursor" }, "description": "Opaque pagination cursor" }, { "name": "literal", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "description": "When false, treat q as a regular expression", "title": "Literal" }, "description": "When false, treat q as a regular expression" }, { "name": "regex", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Treat q as a regular expression", "default": false, "title": "Regex" }, "description": "Treat q as a regular expression" }, { "name": "ignore_case", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Match without regard to case; true by default", "default": true, "title": "Ignore Case" }, "description": "Match without regard to case; true by default" }, { "name": "case_sensitive", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Force case-sensitive matching", "default": false, "title": "Case Sensitive" }, "description": "Force case-sensitive matching" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Ls (/docs/api/fs/ls/get) ## GET /fs/ls **Summary:** Fs Ls List a directory in Nowledge FS. Preview space contract: graph-wide projection. Pass ``cursor`` to fetch the next page; agents should not peek inside the cursor payload (it's an opaque base64-JSON). The explicit ``/spaces/...`` lens is deferred. ### OpenAPI Operation ```json { "/fs/ls": { "get": { "tags": [ "files", "files" ], "summary": "Fs Ls", "description": "List a directory in Nowledge FS.\n\nPreview space contract: graph-wide projection. Pass ``cursor`` to fetch\nthe next page; agents should not peek inside the cursor payload (it's an\nopaque base64-JSON). The explicit ``/spaces/...`` lens is deferred.", "operationId": "fs_ls_fs_ls_get", "parameters": [ { "name": "path", "in": "query", "required": false, "schema": { "type": "string", "description": "Nowledge FS path (e.g. '/memories/by-label/decisions')", "default": "/", "title": "Path" }, "description": "Nowledge FS path (e.g. '/memories/by-label/decisions')" }, { "name": "cursor", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Opaque pagination cursor", "title": "Cursor" }, "description": "Opaque pagination cursor" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 200, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Recall (/docs/api/fs/recall/get) ## GET /fs/recall **Summary:** Fs Recall Semantic memory search. Returns paths, not search hits. Reuses the existing hybrid search pipeline (the one AI Now and Library already drive) so there's no second index. Preview recall is memory-backed; use ``grep`` for exact search in threads and sources. Memory recall can be narrowed with ``unit_type`` or a ``/memories/by-type/`` path. Results are materialised as canonical Nowledge FS paths so the caller can pipe them straight into ``cat``. ### OpenAPI Operation ```json { "/fs/recall": { "get": { "tags": [ "files", "files" ], "summary": "Fs Recall", "description": "Semantic memory search. Returns paths, not search hits.\n\nReuses the existing hybrid search pipeline (the one AI Now and\nLibrary already drive) so there's no second index. Preview recall is\nmemory-backed; use ``grep`` for exact search in threads and sources.\nMemory recall can be narrowed with ``unit_type`` or a\n``/memories/by-type/`` path.\nResults are\nmaterialised as canonical Nowledge FS paths so the caller can pipe them\nstraight into ``cat``.", "operationId": "fs_recall_fs_recall_get", "parameters": [ { "name": "query", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "description": "Semantic query text", "title": "Query" }, "description": "Semantic query text" }, { "name": "path", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Memory subtree to search; non-memory roots return no hits in preview", "title": "Path" }, "description": "Memory subtree to search; non-memory roots return no hits in preview" }, { "name": "unit_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter semantic recall by memory unit type; also inferred from /memories/by-type/ paths", "title": "Unit Type" }, "description": "Filter semantic recall by memory unit type; also inferred from /memories/by-type/ paths" }, { "name": "k", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "description": "How many results to return", "default": 20, "title": "K" }, "description": "How many results to return" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Stat (/docs/api/fs/stat/get) ## GET /fs/stat **Summary:** Fs Stat Return metadata for a Nowledge FS path. Mirrors ``stat(2)`` shape with Mem extras: labels, mention count, back-reference count, importance. Preview space contract: graph-wide projection, with each file returning its concrete ``space_id`` metadata. ### OpenAPI Operation ```json { "/fs/stat": { "get": { "tags": [ "files", "files" ], "summary": "Fs Stat", "description": "Return metadata for a Nowledge FS path.\n\nMirrors ``stat(2)`` shape with Mem extras: labels, mention count,\nback-reference count, importance. Preview space contract: graph-wide\nprojection, with each file returning its concrete ``space_id`` metadata.", "operationId": "fs_stat_fs_stat_get", "parameters": [ { "name": "path", "in": "query", "required": true, "schema": { "type": "string", "description": "Nowledge FS path", "title": "Path" }, "description": "Nowledge FS path" }, { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Agent identity id/slug for /context/* files", "title": "Agent Id" }, "description": "Agent identity id/slug for /context/* files" }, { "name": "source_app", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Calling app provenance hint for /context/* files", "title": "Source App" }, "description": "Calling app provenance hint for /context/* files" }, { "name": "host_agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Host-local long-running agent id for /context/* files", "title": "Host Agent Id" }, "description": "Host-local long-running agent id for /context/* files" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Active space override for /context/* files", "title": "Space Id" }, "description": "Active space override for /context/* files" }, { "name": "include_working_memory", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include Working Memory preview in /context/* files", "default": true, "title": "Include Working Memory" }, "description": "Include Working Memory preview in /context/* files" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Fs Write (/docs/api/fs/write/post) ## POST /fs/write **Summary:** Fs Write Write a canonical Nowledge FS file. Writes through the same concrete-space APIs as the underlying surface. This bounded Phase 2 slice supports canonical memory files under ``/memories/by-id/`` and ``/working-memory/today.md``. Alias paths return ``EXDEV`` and derived paths return ``EROFS``. ### OpenAPI Operation ```json { "/fs/write": { "post": { "tags": [ "files", "files" ], "summary": "Fs Write", "description": "Write a canonical Nowledge FS file.\n\nWrites through the same concrete-space APIs as the underlying surface.\nThis bounded Phase 2 slice supports canonical\nmemory files under ``/memories/by-id/`` and\n``/working-memory/today.md``. Alias paths return ``EXDEV`` and\nderived paths return ``EROFS``.", "operationId": "fs_write_fs_write_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FSWriteRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Graph Analysis (/docs/api/graph/analysis/get) ## GET /graph/analysis **Summary:** Get Graph Analysis Get comprehensive graph analysis including community and centrality metrics. This endpoint provides a complete overview of the graph structure, communities, and centrality measures without triggering new calculations. ### OpenAPI Operation ```json { "/graph/analysis": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Graph Analysis", "description": "Get comprehensive graph analysis including community and centrality metrics.\n\nThis endpoint provides a complete overview of the graph structure, communities,\nand centrality measures without triggering new calculations.", "operationId": "get_graph_analysis_graph_analysis_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphAnalysisResponseModel" } } } } } } } } ``` # Explore Graph (/docs/api/graph/explore/get) ## GET /graph/explore **Summary:** Explore Graph Build a visualization-ready graph neighborhood around one or more memory IDs. ### OpenAPI Operation ```json { "/graph/explore": { "get": { "tags": [ "graph-analysis" ], "summary": "Explore Graph", "description": "Build a visualization-ready graph neighborhood around one or more memory IDs.", "operationId": "explore_graph_graph_explore_get", "parameters": [ { "name": "memory_ids", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "description": "Comma-separated memory IDs to explore as graph seeds", "title": "Memory Ids" }, "description": "Comma-separated memory IDs to explore as graph seeds" }, { "name": "depth", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5, "minimum": 1, "description": "Traversal depth for graph expansion around the seed memories", "default": 1, "title": "Depth" }, "description": "Traversal depth for graph expansion around the seed memories" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 300, "minimum": 1, "description": "Maximum path rows to inspect when building the graph neighborhood", "default": 100, "title": "Limit" }, "description": "Maximum path rows to inspect when building the graph neighborhood" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional memory space lens for the graph", "title": "Space Id" }, "description": "Optional memory space lens for the graph" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphDataResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Graph Analysis Health (/docs/api/graph/health/get) ## GET /graph/health **Summary:** Graph Analysis Health Health check for graph analysis. Returns whether graph analysis features (community detection, importance scoring) are available. ### OpenAPI Operation ```json { "/graph/health": { "get": { "tags": [ "graph-analysis" ], "summary": "Graph Analysis Health", "description": "Health check for graph analysis.\n\nReturns whether graph analysis features (community detection, importance scoring) are available.", "operationId": "graph_analysis_health_graph_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphAnalysisHealthCheckModel" } } } } } } } } ``` # Get Live Preview Graph (/docs/api/graph/live-preview/get) ## GET /graph/live-preview **Summary:** Get Live Preview Graph Get a compact merged 1-hop graph for feed/live preview surfaces. ### OpenAPI Operation ```json { "/graph/live-preview": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Live Preview Graph", "description": "Get a compact merged 1-hop graph for feed/live preview surfaces.", "operationId": "get_live_preview_graph_graph_live_preview_get", "parameters": [ { "name": "node_ids", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "description": "Comma-separated memory IDs to preview as graph seeds", "title": "Node Ids" }, "description": "Comma-separated memory IDs to preview as graph seeds" }, { "name": "limit_per_seed", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 20, "minimum": 1, "description": "Maximum direct neighbors to include for each seed node", "default": 5, "title": "Limit Per Seed" }, "description": "Maximum direct neighbors to include for each seed node" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional memory space lens for the graph", "title": "Space Id" }, "description": "Optional memory space lens for the graph" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphDataResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Cleanup Orphaned Entities (/docs/api/graph/orphans/delete) ## DELETE /graph/orphans **Summary:** Cleanup Orphaned Entities Remove all unconnected entities. Deletes entities that have no relationships to memories or other entities. Only affects isolated entities; your memories, labels, and communities are never touched. ### OpenAPI Operation ```json { "/graph/orphans": { "delete": { "tags": [ "graph-analysis" ], "summary": "Cleanup Orphaned Entities", "description": "Remove all unconnected entities.\n\nDeletes entities that have no relationships to memories or other entities. Only affects isolated entities; your memories, labels, and communities are never touched.", "operationId": "cleanup_orphaned_entities_graph_orphans_delete", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CleanupOrphansResponse" } } } } } } } } ``` # Find Orphaned Entities (/docs/api/graph/orphans/get) ## GET /graph/orphans **Summary:** Find Orphaned Entities Find entities with no connections. Lists entities that aren't linked to any memory or other entity. These are safe to clean up without losing meaningful knowledge. ### OpenAPI Operation ```json { "/graph/orphans": { "get": { "tags": [ "graph-analysis" ], "summary": "Find Orphaned Entities", "description": "Find entities with no connections.\n\nLists entities that aren't linked to any memory or other entity. These are safe to clean up without losing meaningful knowledge.", "operationId": "find_orphaned_entities_graph_orphans_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OrphanedEntitiesResponse" } } } } } } } } ``` # Get Graph Overview (/docs/api/graph/overview/get) ## GET /graph/overview **Summary:** Get Graph Overview Lightweight full-graph endpoint for overview visualization. Returns all graph-overview node types (Entity, Memory, Source, Thread, Skill) with minimal data (no content, no metadata, no messages) for fast full-graph rendering. ### OpenAPI Operation ```json { "/graph/overview": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Graph Overview", "description": "Lightweight full-graph endpoint for overview visualization.\n\nReturns all graph-overview node types (Entity, Memory, Source, Thread, Skill)\nwith minimal data (no content, no metadata, no messages) for fast full-graph\nrendering.", "operationId": "get_graph_overview_graph_overview_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 2000, "minimum": 10, "default": 500, "title": "Limit" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional memory space lens for the graph", "title": "Space Id" }, "description": "Optional memory space lens for the graph" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Graph Data (/docs/api/graph/sample/get) ## GET /graph/sample **Summary:** Get Graph Data Get a sample of the knowledge graph. Returns a representative subset of nodes and edges for visualization. Useful for exploring the graph without a specific query. ### OpenAPI Operation ```json { "/graph/sample": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Graph Data", "description": "Get a sample of the knowledge graph.\n\nReturns a representative subset of nodes and edges for visualization. Useful for exploring the graph without a specific query.", "operationId": "get_graph_data_graph_sample_get", "parameters": [ { "name": "filter_type", "in": "query", "required": false, "schema": { "type": "string", "title": "Filter Type" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 10, "default": 50, "title": "Limit" } }, { "name": "depth", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5, "minimum": 1, "description": "Traversal depth for relationships", "default": 1, "title": "Depth" }, "description": "Traversal depth for relationships" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional memory space lens for the graph", "title": "Space Id" }, "description": "Optional memory space lens for the graph" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphDataResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Search Graph (/docs/api/graph/search/get) ## GET /graph/search **Summary:** Search Graph Search the knowledge graph. Finds memories matching your query and returns them with their connections as visualization-ready graph data. ### OpenAPI Operation ```json { "/graph/search": { "get": { "tags": [ "graph-analysis" ], "summary": "Search Graph", "description": "Search the knowledge graph.\n\nFinds memories matching your query and returns them with their connections as visualization-ready graph data.", "operationId": "search_graph_graph_search_get", "parameters": [ { "name": "query", "in": "query", "required": true, "schema": { "type": "string", "description": "Search query", "title": "Query" }, "description": "Search query" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 30, "title": "Limit" } }, { "name": "depth", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5, "minimum": 1, "description": "Traversal depth for graph search", "default": 2, "title": "Depth" }, "description": "Traversal depth for graph search" }, { "name": "node_types", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Filter by node types", "title": "Node Types" }, "description": "Filter by node types" }, { "name": "edge_types", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Filter by edge types", "title": "Edge Types" }, "description": "Filter by edge types" }, { "name": "include_metadata", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include metadata in results", "default": true, "title": "Include Metadata" }, "description": "Include metadata in results" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional memory space lens for the graph", "title": "Space Id" }, "description": "Optional memory space lens for the graph" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphSearchResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Shortest Path (/docs/api/graph/shortest-path/get) ## GET /graph/shortest-path **Summary:** Get Shortest Path Find all shortest paths between two nodes using KuzuDB ALL SHORTEST. Note: KuzuDB does not support parameter binding in recursive relationship bounds, so max_depth is interpolated as a validated literal (ge=2, le=20). Returns all shortest paths (same hop count, different routes) so the frontend can render every connection between the two nodes. The overview graph may not contain all intermediate nodes, so paths are drawn between visible positions. ### OpenAPI Operation ```json { "/graph/shortest-path": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Shortest Path", "description": "Find all shortest paths between two nodes using KuzuDB ALL SHORTEST.\n\nNote: KuzuDB does not support parameter binding in recursive relationship\nbounds, so max_depth is interpolated as a validated literal (ge=2, le=20).\n\nReturns all shortest paths (same hop count, different routes) so the\nfrontend can render every connection between the two nodes. The overview\ngraph may not contain all intermediate nodes, so paths are drawn between\nvisible positions.", "operationId": "get_shortest_path_graph_shortest_path_get", "parameters": [ { "name": "from_id", "in": "query", "required": true, "schema": { "type": "string", "description": "Source node ID", "title": "From Id" }, "description": "Source node ID" }, { "name": "to_id", "in": "query", "required": true, "schema": { "type": "string", "description": "Target node ID", "title": "To Id" }, "description": "Target node ID" }, { "name": "max_depth", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 20, "minimum": 2, "default": 10, "title": "Max Depth" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Graph Vis (/docs/api/graph/vis/get) ## GET /graph/vis **Summary:** Graph Vis Embeddable interactive graph explorer. Returns a self-contained HTML page with an interactive knowledge graph visualization. The page fetches data from the REST API on load, so it works standalone in any browser or embedded in your application via an iframe. **Modes** (pick one, or omit all for a random sample): - `?query=React` search for memories matching "React" and visualize their connections. - `?memory_ids=abc,def` explore the neighborhood around specific memories. - *(no params)* show a random sample of the graph. **Embedding:** set `search_bar=false` to hide the top search bar for a cleaner look when embedding in an iframe or dashboard. ### OpenAPI Operation ```json { "/graph/vis": { "get": { "tags": [ "graph-analysis" ], "summary": "Graph Vis", "description": "Embeddable interactive graph explorer.\n\nReturns a self-contained HTML page with an interactive knowledge graph\nvisualization. The page fetches data from the REST API on load, so it\nworks standalone in any browser or embedded in your application via an\niframe.\n\n**Modes** (pick one, or omit all for a random sample):\n\n- `?query=React` search for memories matching \"React\" and visualize their connections.\n- `?memory_ids=abc,def` explore the neighborhood around specific memories.\n- *(no params)* show a random sample of the graph.\n\n**Embedding:** set `search_bar=false` to hide the top search bar for\na cleaner look when embedding in an iframe or dashboard.", "operationId": "graph_vis_graph_vis_get", "parameters": [ { "name": "query", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Search query to filter memories and show their connections.", "title": "Query" }, "description": "Search query to filter memories and show their connections." }, { "name": "memory_ids", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Comma-separated memory IDs to explore their neighborhood.", "title": "Memory Ids" }, "description": "Comma-separated memory IDs to explore their neighborhood." }, { "name": "depth", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5, "minimum": 1, "description": "How many hops to traverse from each seed node.", "default": 2, "title": "Depth" }, "description": "How many hops to traverse from each seed node." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 300, "minimum": 10, "description": "Maximum number of nodes to return.", "default": 50, "title": "Limit" }, "description": "Maximum number of nodes to return." }, { "name": "search_bar", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Show the search bar. Set to false for clean embedding (e.g. iframe).", "default": true, "title": "Search Bar" }, "description": "Show the search bar. Set to false for clean embedding (e.g. iframe)." } ], "responses": { "200": { "description": "Successful Response", "content": { "text/html": { "schema": { "type": "string" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Force Checkpoint (/docs/api/health/checkpoint/post) ## POST /health/checkpoint **Summary:** Force Checkpoint Force a database checkpoint. Flushes pending writes before app updates. ### OpenAPI Operation ```json { "/health/checkpoint": { "post": { "tags": [ "health" ], "operationId": "force_checkpoint_health_checkpoint_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataTransferCheckpointResponse" } } } } }, "summary": "Force Checkpoint", "description": "Force a database checkpoint.\n\nFlushes pending writes before app updates." } } } ``` # Consolidate Labels (/docs/api/labels/consolidate/post) ## POST /labels/consolidate **Summary:** Consolidate Labels Consolidate exact-canonical label forks into their highest-usage survivor. Cross-space (graph aggregation): operates on the global label graph. Deterministic and safe (same canonical token = same concept). Defaults to ``dry_run=true`` so callers preview the plan before mutating. Semantic and cross-language consolidation is the separate agent-judged pass. ### OpenAPI Operation ```json { "/labels/consolidate": { "post": { "tags": [ "labels" ], "summary": "Consolidate Labels", "description": "Consolidate exact-canonical label forks into their highest-usage survivor.\n\nCross-space (graph aggregation): operates on the global label graph.\nDeterministic and safe (same canonical token = same concept). Defaults to\n``dry_run=true`` so callers preview the plan before mutating. Semantic and\ncross-language consolidation is the separate agent-judged pass.", "operationId": "consolidate_labels_labels_consolidate_post", "parameters": [ { "name": "dry_run", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Preview without merging", "default": true, "title": "Dry Run" }, "description": "Preview without merging" }, { "name": "max_groups", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5000, "minimum": 1, "default": 200, "title": "Max Groups" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Consolidate Labels Labels Consolidate Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Label Consolidation (/docs/api/labels/consolidation-preview/post) ## POST /labels/consolidation-preview **Summary:** Preview Label Consolidation Preview the full label-consolidation task without applying merges. This is the same dry-run path as the scheduled task: deterministic canonical-fork planning plus model-judged semantic/cross-language pairs. It can spend model tokens, but it never mutates graph state. ### OpenAPI Operation ```json { "/labels/consolidation-preview": { "post": { "tags": [ "labels" ], "summary": "Preview Label Consolidation", "description": "Preview the full label-consolidation task without applying merges.\n\nThis is the same dry-run path as the scheduled task: deterministic\ncanonical-fork planning plus model-judged semantic/cross-language pairs.\nIt can spend model tokens, but it never mutates graph state.", "operationId": "preview_label_consolidation_labels_consolidation_preview_post", "parameters": [ { "name": "sim_floor", "in": "query", "required": false, "schema": { "type": "number", "maximum": 1, "minimum": 0, "default": 0.82, "title": "Sim Floor" } }, { "name": "max_labels", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5000, "minimum": 2, "default": 2000, "title": "Max Labels" } }, { "name": "max_pairs", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "default": 40, "title": "Max Pairs" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Preview Label Consolidation Labels Consolidation Preview Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Label Health (/docs/api/labels/health/get) ## GET /labels/health **Summary:** Label Health Label vocabulary health report. Cross-space (graph aggregation): reads the global label graph regardless of active space lens. Quantifies size, labels-per-memory, coverage, singleton rate, and the exact-canonical fork backlog so consolidation progress is measurable. ### OpenAPI Operation ```json { "/labels/health": { "get": { "tags": [ "labels" ], "summary": "Label Health", "description": "Label vocabulary health report.\n\nCross-space (graph aggregation): reads the global label graph regardless of\nactive space lens. Quantifies size, labels-per-memory, coverage, singleton\nrate, and the exact-canonical fork backlog so consolidation progress is\nmeasurable.", "operationId": "label_health_labels_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Label Health Labels Health Get" } } } } } } } } ``` # Delete Label (/docs/api/labels/label_id/delete) ## DELETE /labels/{label_id} **Summary:** Delete Label Delete a label and all its relationships. ### OpenAPI Operation ```json { "/labels/{label_id}": { "delete": { "tags": [ "labels" ], "summary": "Delete Label", "description": "Delete a label and all its relationships.", "operationId": "delete_label_labels__label_id__delete", "parameters": [ { "name": "label_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Label Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteLabelResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Label (/docs/api/labels/label_id/get) ## GET /labels/{label_id} **Summary:** Get Label Get a specific label by ID. ### OpenAPI Operation ```json { "/labels/{label_id}": { "get": { "tags": [ "labels" ], "summary": "Get Label", "description": "Get a specific label by ID.", "operationId": "get_label_labels__label_id__get", "parameters": [ { "name": "label_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Label Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Label (/docs/api/labels/label_id/put) ## PUT /labels/{label_id} **Summary:** Update Label Update an existing label. ### OpenAPI Operation ```json { "/labels/{label_id}": { "put": { "tags": [ "labels" ], "summary": "Update Label", "description": "Update an existing label.", "operationId": "update_label_labels__label_id__put", "parameters": [ { "name": "label_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Label Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateLabelRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Merge Labels Endpoint (/docs/api/labels/merge/post) ## POST /labels/merge **Summary:** Merge Labels Endpoint Merge one label into another: re-point every HAS_LABEL edge from source to target, record the merge for reversal, delete the source. Cross-space (graph aggregation): operates on the global label graph. Used by the manual "merge labels" affordance and the agentic consolidation pass. ### OpenAPI Operation ```json { "/labels/merge": { "post": { "tags": [ "labels" ], "summary": "Merge Labels Endpoint", "description": "Merge one label into another: re-point every HAS_LABEL edge from source\nto target, record the merge for reversal, delete the source.\n\nCross-space (graph aggregation): operates on the global label graph. Used by\nthe manual \"merge labels\" affordance and the agentic consolidation pass.", "operationId": "merge_labels_endpoint_labels_merge_post", "parameters": [ { "name": "source_id", "in": "query", "required": true, "schema": { "type": "string", "description": "Label id to merge away (deleted)", "title": "Source Id" }, "description": "Label id to merge away (deleted)" }, { "name": "target_id", "in": "query", "required": true, "schema": { "type": "string", "description": "Label id to keep (survivor)", "title": "Target Id" }, "description": "Label id to keep (survivor)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Merge Labels Endpoint Labels Merge Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Label Merge Candidates (/docs/api/labels/merge-candidates/get) ## GET /labels/merge-candidates **Summary:** Label Merge Candidates Semantically-near label pairs (candidates for merge), read-only. Cross-space (graph aggregation). Surfaces near-synonym and cross-language pairs (the embedding model is multilingual) for human/agent review. A cosine score is a candidate signal, not a verdict: nothing is merged here. Exact- canonical forks are excluded (handled by /labels/consolidate). Apply a chosen merge via POST /labels/merge. ### OpenAPI Operation ```json { "/labels/merge-candidates": { "get": { "tags": [ "labels" ], "summary": "Label Merge Candidates", "description": "Semantically-near label pairs (candidates for merge), read-only.\n\nCross-space (graph aggregation). Surfaces near-synonym and cross-language\npairs (the embedding model is multilingual) for human/agent review. A cosine\nscore is a candidate signal, not a verdict: nothing is merged here. Exact-\ncanonical forks are excluded (handled by /labels/consolidate). Apply a\nchosen merge via POST /labels/merge.", "operationId": "label_merge_candidates_labels_merge_candidates_get", "parameters": [ { "name": "sim_floor", "in": "query", "required": false, "schema": { "type": "number", "maximum": 1, "minimum": 0, "default": 0.82, "title": "Sim Floor" } }, { "name": "max_labels", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5000, "minimum": 2, "default": 2000, "title": "Max Labels" } }, { "name": "max_pairs", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 100, "title": "Max Pairs" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Label Merge Candidates Labels Merge Candidates Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Library Okf Export (/docs/api/library/okf-export/get) ## GET /library/okf-export **Summary:** Get Library Okf Export Build an Open Knowledge Format (OKF) bundle ZIP. Cross-space (graph aggregation): reads the global graph regardless of the active space lens, same as `/library/wiki-export`. Returns an OKF-conformant bundle (markdown + frontmatter, bundle-relative links, per-directory index.md). See `docs/design/OKF_INTEROP.md`. ### OpenAPI Operation ```json { "/library/okf-export": { "get": { "tags": [ "library-wiki" ], "summary": "Get Library Okf Export", "description": "Build an Open Knowledge Format (OKF) bundle ZIP.\n\nCross-space (graph aggregation): reads the global graph regardless of\nthe active space lens, same as `/library/wiki-export`. Returns an\nOKF-conformant bundle (markdown + frontmatter, bundle-relative links,\nper-directory index.md). See `docs/design/OKF_INTEROP.md`.", "operationId": "get_library_okf_export_library_okf_export_get", "parameters": [ { "name": "entity_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 2000, "minimum": 1, "default": 500, "title": "Entity Limit" } }, { "name": "top_per_community", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 30, "minimum": 1, "default": 12, "title": "Top Per Community" } }, { "name": "max_mentions_per_entity", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 30, "title": "Max Mentions Per Entity" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Library Wiki Export (/docs/api/library/wiki-export/get) ## GET /library/wiki-export **Summary:** Get Library Wiki Export Build the markdown wiki ZIP. ### OpenAPI Operation ```json { "/library/wiki-export": { "get": { "tags": [ "library-wiki" ], "summary": "Get Library Wiki Export", "description": "Build the markdown wiki ZIP.", "operationId": "get_library_wiki_export_library_wiki_export_get", "parameters": [ { "name": "entity_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 2000, "minimum": 1, "default": 500, "title": "Entity Limit" } }, { "name": "top_per_community", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 30, "minimum": 1, "default": 12, "title": "Top Per Community" } }, { "name": "max_mentions_per_entity", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 30, "title": "Max Mentions Per Entity" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Library Wiki Export Summary (/docs/api/library/wiki-export-summary/get) ## GET /library/wiki-export-summary **Summary:** Get Library Wiki Export Summary Return cheap export counts before building the ZIP. ### OpenAPI Operation ```json { "/library/wiki-export-summary": { "get": { "tags": [ "library-wiki" ], "summary": "Get Library Wiki Export Summary", "description": "Return cheap export counts before building the ZIP.", "operationId": "get_library_wiki_export_summary_library_wiki_export_summary_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } } } ``` # Get Library Wiki Index (/docs/api/library/wiki-index/get) ## GET /library/wiki-index **Summary:** Get Library Wiki Index Return Library topic cards for the All tab. The response is deliberately flat: one row per community with its surfaced entities and crystals, so the client can render the index in one round-trip. ### OpenAPI Operation ```json { "/library/wiki-index": { "get": { "tags": [ "library-wiki" ], "summary": "Get Library Wiki Index", "description": "Return Library topic cards for the All tab.\n\nThe response is deliberately flat: one row per community with its surfaced\nentities and crystals, so the client can render the index in one round-trip.", "operationId": "get_library_wiki_index_library_wiki_index_get", "parameters": [ { "name": "community_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "default": 20, "title": "Community Limit" } }, { "name": "top_per_community", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10, "minimum": 1, "default": 5, "title": "Top Per Community" } }, { "name": "include_top_memories", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 8, "minimum": 0 }, { "type": "null" } ], "title": "Include Top Memories" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Distill Memories From Thread (/docs/api/memories/distill/post) ## POST /memories/distill **Summary:** Distill Memories From Thread Create memories from a conversation thread. ### OpenAPI Operation ```json { "/memories/distill": { "post": { "tags": [ "distillation" ], "summary": "Distill Memories From Thread", "description": "Create memories from a conversation thread.", "operationId": "distill_memories_from_thread_memories_distill_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DistillationRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryCreateResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Delete Memory (/docs/api/memories/memory_id/delete) ## DELETE /memories/{memory_id} **Summary:** Delete Memory Delete a memory and optionally its relationships. ### OpenAPI Operation ```json { "/memories/{memory_id}": { "delete": { "tags": [ "memories" ], "summary": "Delete Memory", "description": "Delete a memory and optionally its relationships.", "operationId": "delete_memory_memories__memory_id__delete", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } }, { "name": "cascade_delete", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Delete related entities", "default": true, "title": "Cascade Delete" }, "description": "Delete related entities" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteMemoryResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Memory (/docs/api/memories/memory_id/get) ## GET /memories/{memory_id} **Summary:** Get Memory Get a specific memory by ID with associated labels. ### OpenAPI Operation ```json { "/memories/{memory_id}": { "get": { "tags": [ "memories" ], "summary": "Get Memory", "description": "Get a specific memory by ID with associated labels.", "operationId": "get_memory_memories__memory_id__get", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryPublic" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Memory (/docs/api/memories/memory_id/patch) ## PATCH /memories/{memory_id} **Summary:** Update Memory Update memory properties like importance, title, and content. ### OpenAPI Operation ```json { "/memories/{memory_id}": { "patch": { "tags": [ "memories" ], "summary": "Update Memory", "description": "Update memory properties like importance, title, and content.", "operationId": "update_memory_memories__memory_id__patch", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Request" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryPublic" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Reindex Memories Bulk (/docs/api/memories/reindex/post) ## POST /memories/reindex **Summary:** Reindex Memories Bulk Reindex multiple memories or all memories needing reindex. This endpoint can work for both single and bulk reindexing: - If memory_ids is provided: reindex those specific memories - If memory_ids is None/empty: reindex all memories with reindex_needed=True ### OpenAPI Operation ```json { "/memories/reindex": { "post": { "tags": [ "memories" ], "summary": "Reindex Memories Bulk", "description": "Reindex multiple memories or all memories needing reindex.\n\nThis endpoint can work for both single and bulk reindexing:\n- If memory_ids is provided: reindex those specific memories\n- If memory_ids is None/empty: reindex all memories with reindex_needed=True", "operationId": "reindex_memories_bulk_memories_reindex_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10, "minimum": 1, "description": "Batch size for concurrent processing", "default": 3, "title": "Batch Size" }, "description": "Batch size for concurrent processing" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryReindexRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReindexResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Search Memories (/docs/api/memories/search/post) ## POST /memories/search **Summary:** Search Memories Memory search with filtering, metadata, and reasoning support. ### OpenAPI Operation ```json { "/memories/search": { "post": { "tags": [ "memories" ], "summary": "Search Memories", "description": "Memory search with filtering, metadata, and reasoning support.", "operationId": "search_memories_memories_search_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySearchRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/MemorySearchResult" }, "type": "array", "title": "Response Search Memories Memories Search Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Model Memory Status (/docs/api/models/memory-status/get) ## GET /models/memory-status **Summary:** Get Model Memory Status Return which local model weights are currently resident in RAM. ### OpenAPI Operation ```json { "/models/memory-status": { "get": { "tags": [ "models" ], "summary": "Get Model Memory Status", "description": "Return which local model weights are currently resident in RAM.", "operationId": "get_model_memory_status_models_memory_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ModelMemoryStatusResponse" } } } } } } } } ``` # Resolve a Nowledge resource URI (/docs/api/resources/resolve/get) ## GET /resources/resolve **Summary:** Resolve a Nowledge resource URI Resolve one capability-free nowledgemem:// reference against the authenticated backend and workspace. This endpoint never fetches HTTP(S) or file URLs. ### OpenAPI Operation ```json { "/resources/resolve": { "get": { "tags": [ "resources" ], "summary": "Resolve a Nowledge resource URI", "description": "Resolve one capability-free nowledgemem:// reference against the authenticated backend and workspace. This endpoint never fetches HTTP(S) or file URLs.", "operationId": "resolve_resource_handler", "parameters": [ { "name": "uri", "in": "query", "description": "Capability-free `nowledgemem://` URI to resolve.", "required": true, "schema": { "type": "string" } }, { "name": "agent_id", "in": "query", "description": "Optional agent identity used only by Context KFS renderers.", "required": false, "schema": { "type": "string" } }, { "name": "source_app", "in": "query", "description": "Optional calling application identity used only by Context renderers.", "required": false, "schema": { "type": "string" } }, { "name": "host_agent_id", "in": "query", "description": "Optional host-agent identity used only by Context renderers.", "required": false, "schema": { "type": "string" } }, { "name": "space_id", "in": "query", "description": "Optional Space lens used only by Context renderers.", "required": false, "schema": { "type": "string" } }, { "name": "include_working_memory", "in": "query", "description": "Include Working Memory in a resolved Context Bundle.", "required": false, "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "Rendered resource", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResolvedResourceResponse" } } } }, "400": { "description": "Invalid or unsupported resource URI" }, "404": { "description": "Resource not found" } } } } } ``` # Reindex Search Index (/docs/api/search-index/reindex/post) ## POST /search-index/reindex **Summary:** Reindex Search Index Refresh the search projection from authoritative storage. Most calls perform a full semantic rebuild of: - All memories (with search embeddings) - All thread messages - All Library sources and source chunks - All communities - All entities If the only pending marker is the 0.8.4 Content Store thread-message migration and semantic index metadata already matches the active embedding backend, this endpoint only copies/verifies messages, rebuilds the FTS-only messages_index, and skips embedding initialization. The embedding model is platform-specific: - macOS Apple Silicon: Qwen3-Embedding via mlx-embeddings - non-Apple-Silicon (Windows/Linux/macOS Intel): BGE-M3 via FastEmbed/ONNX This is a heavy operation and should only be triggered: - After first downloading the search embedding model - After a data migration - When explicitly requested by the user ### OpenAPI Operation ```json { "/search-index/reindex": { "post": { "tags": [ "memories" ], "summary": "Reindex Search Index", "description": "Refresh the search projection from authoritative storage.\n\nMost calls perform a full semantic rebuild of:\n- All memories (with search embeddings)\n- All thread messages\n- All Library sources and source chunks\n- All communities\n- All entities\n\nIf the only pending marker is the 0.8.4 Content Store thread-message\nmigration and semantic index metadata already matches the active embedding\nbackend, this endpoint only copies/verifies messages, rebuilds the FTS-only\nmessages_index, and skips embedding initialization.\n\nThe embedding model is platform-specific:\n- macOS Apple Silicon: Qwen3-Embedding via mlx-embeddings\n- non-Apple-Silicon (Windows/Linux/macOS Intel): BGE-M3 via FastEmbed/ONNX\n\nThis is a heavy operation and should only be triggered:\n- After first downloading the search embedding model\n- After a data migration\n- When explicitly requested by the user", "operationId": "reindex_search_index_search_index_reindex_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchIndexReindexResponse" } } } } } } } } ``` # Get Search Index Status (/docs/api/search-index/status/get) ## GET /search-index/status **Summary:** Get Search Index Status Get status of the search index (LanceDB + hybrid search). The embedding model is platform-specific: - macOS Apple Silicon: Qwen3-Embedding via mlx-embeddings - non-Apple-Silicon (Windows/Linux/macOS Intel): BGE-M3 via FastEmbed/ONNX This endpoint checks: - Whether the active search embedding backend is available - Whether the search index service is initialized ### OpenAPI Operation ```json { "/search-index/status": { "get": { "tags": [ "memories" ], "summary": "Get Search Index Status", "description": "Get status of the search index (LanceDB + hybrid search).\n\nThe embedding model is platform-specific:\n- macOS Apple Silicon: Qwen3-Embedding via mlx-embeddings\n- non-Apple-Silicon (Windows/Linux/macOS Intel): BGE-M3 via FastEmbed/ONNX\n\nThis endpoint checks:\n- Whether the active search embedding backend is available\n- Whether the search index service is initialized", "operationId": "get_search_index_status_search_index_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchIndexStatusResponse" } } } } } } } } ``` # Get Agent Profiles (/docs/api/settings/agent-profiles/get) ## GET /settings/agent-profiles **Summary:** Get Agent Profiles List owner-configured long-running agent identities. ### OpenAPI Operation ```json { "/settings/agent-profiles": { "get": { "tags": [ "settings", "settings" ], "summary": "Get Agent Profiles", "description": "List owner-configured long-running agent identities.", "operationId": "get_agent_profiles_settings_agent_profiles_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentProfilesResponse" } } } } } } } } ``` # Create Agent Profile (/docs/api/settings/agent-profiles/post) ## POST /settings/agent-profiles **Summary:** Create Agent Profile Create a named agent identity consumed by Context Bundle. ### OpenAPI Operation ```json { "/settings/agent-profiles": { "post": { "tags": [ "settings", "settings" ], "summary": "Create Agent Profile", "description": "Create a named agent identity consumed by Context Bundle.", "operationId": "create_agent_profile_settings_agent_profiles_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentProfilePayload" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentProfileResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Export portable settings (/docs/api/settings/backup/get) ## GET /settings/backup **Summary:** Export portable settings Export profile, Spaces, knowledge-processing preferences, and provider routing without API keys, sign-in sessions, licenses, Access Anywhere keys, or device paths. ### OpenAPI Operation ```json { "/settings/backup": { "get": { "tags": [ "settings" ], "summary": "Export portable settings", "description": "Export profile, Spaces, knowledge-processing preferences, and provider routing without API keys, sign-in sessions, licenses, Access Anywhere keys, or device paths.", "operationId": "export_settings_backup_handler", "responses": { "200": { "description": "Portable settings artifact", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SettingsBackupArtifact" } } } } } } } } ``` # Get User Profile (/docs/api/settings/profile/get) ## GET /settings/profile **Summary:** Get User Profile Get user profile (name, aliases, context, preferred language). Used by the browser extension and CLI to inject user identity and language preference into agent prompts. ### OpenAPI Operation ```json { "/settings/profile": { "get": { "tags": [ "settings", "settings" ], "summary": "Get User Profile", "description": "Get user profile (name, aliases, context, preferred language).\n\nUsed by the browser extension and CLI to inject user identity\nand language preference into agent prompts.", "operationId": "get_user_profile_settings_profile_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserProfileResponse" } } } } } } } } ``` # Restore portable settings (/docs/api/settings/restore/post) ## POST /settings/restore **Summary:** Restore portable settings Merge portable settings into this installation. Existing credentials survive only for an unchanged non-OAuth provider identity; secrets are never read from the artifact. ### OpenAPI Operation ```json { "/settings/restore": { "post": { "tags": [ "settings" ], "summary": "Restore portable settings", "description": "Merge portable settings into this installation. Existing credentials survive only for an unchanged non-OAuth provider identity; secrets are never read from the artifact.", "operationId": "restore_settings_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SettingsBackupArtifact" } } }, "required": true }, "responses": { "200": { "description": "Settings restored", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SettingsRestoreResponse" } } } }, "422": { "description": "Invalid, unsafe, or unsupported settings artifact" } } } } } ``` # Get Guidance Rules (/docs/api/settings/rules/get) ## GET /settings/rules **Summary:** Get Guidance Rules List owner-managed AI Context rules consumed by Context Bundle. ### OpenAPI Operation ```json { "/settings/rules": { "get": { "tags": [ "settings", "settings" ], "summary": "Get Guidance Rules", "description": "List owner-managed AI Context rules consumed by Context Bundle.", "operationId": "get_guidance_rules_settings_rules_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RulesResponse" } } } } } } } } ``` # Create Guidance Rule (/docs/api/settings/rules/post) ## POST /settings/rules **Summary:** Create Guidance Rule Create an AI Context rule for the Context Bundle control plane. ### OpenAPI Operation ```json { "/settings/rules": { "post": { "tags": [ "settings", "settings" ], "summary": "Create Guidance Rule", "description": "Create an AI Context rule for the Context Bundle control plane.", "operationId": "create_guidance_rule_settings_rules_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GuidanceRulePayload" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GuidanceRuleResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Skill Activity (/docs/api/skills/activity/get) ## GET /skills/activity **Summary:** Get Skill Activity Recent skill-use moments, newest-first — the usage proof feed. Reads each skill's metadata use/outcome logs and merges them (see SKILL_USAGE_PROOF_FEED.md). Registered BEFORE ``/{skill_id}`` so this static path is not shadowed. ``skill_id`` limits to one skill (the detail-page strip); else cross-skill, scoped to the active space when ``space_id`` is given. ### OpenAPI Operation ```json { "/skills/activity": { "get": { "tags": [ "skills", "skills" ], "summary": "Get Skill Activity", "description": "Recent skill-use moments, newest-first — the usage proof feed.\n\nReads each skill's metadata use/outcome logs and merges them (see\nSKILL_USAGE_PROOF_FEED.md). Registered BEFORE ``/{skill_id}`` so this static path\nis not shadowed. ``skill_id`` limits to one skill (the detail-page strip); else\ncross-skill, scoped to the active space when ``space_id`` is given.", "operationId": "get_skill_activity_skills_activity_get", "parameters": [ { "name": "skill_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Limit to one skill (else all)", "title": "Skill Id" }, "description": "Limit to one skill (else all)" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Scope to a space (else all)", "title": "Space Id" }, "description": "Scope to a space (else all)" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Skill Activity Skills Activity Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Author Skill (/docs/api/skills/author/post) ## POST /skills/author **Summary:** Author Skill Create a skill the user authored deliberately (top-down), from a name plus optional sources (memories and/or threads) and a free-text intent note. Threads are resolved to their source memories via the ``COMPACTS_TO`` edge so they flow through the same ``SYNTHESIZED_FROM`` provenance and compile context as auto-detected evidence. The skill is created at stage ``promotable`` (ready to compile); the caller then runs the normal compile to produce a reviewable draft. A note-only skill (no memories/threads) is allowed: the note carries the intent. Scoped to the personal lane (skills list cross-space). See docs/design/SKILL_BUILDER_AND_PURPOSE.md §4.2. ### OpenAPI Operation ```json { "/skills/author": { "post": { "tags": [ "skills", "skills" ], "summary": "Author Skill", "description": "Create a skill the user authored deliberately (top-down), from a name plus\noptional sources (memories and/or threads) and a free-text intent note.\n\nThreads are resolved to their source memories via the ``COMPACTS_TO`` edge so\nthey flow through the same ``SYNTHESIZED_FROM`` provenance and compile context\nas auto-detected evidence. The skill is created at stage ``promotable`` (ready\nto compile); the caller then runs the normal compile to produce a reviewable\ndraft. A note-only skill (no memories/threads) is allowed: the note carries\nthe intent. Scoped to the personal lane (skills list cross-space).\nSee docs/design/SKILL_BUILDER_AND_PURPOSE.md §4.2.", "operationId": "author_skill_skills_author_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthorSkillRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Author Skill Skills Author Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Match Skills Endpoint (/docs/api/skills/match/get) ## GET /skills/match **Summary:** Match Skills Endpoint Rank active Skills against a task through the same semantic hybrid router used by MCP Skill discovery and routing benchmarks. When semantic embeddings are unavailable, interactive discovery remains usable through deterministic trigger matching; the response reports semantic or keyword_fallback in its routing field. ### OpenAPI Operation ```json { "/skills/match": { "get": { "tags": [ "skills", "skills" ], "summary": "Match Skills Endpoint", "description": "Rank active Skills against a task through the same semantic hybrid router used by MCP Skill discovery and routing benchmarks. When semantic embeddings are unavailable, interactive discovery remains usable through deterministic trigger matching; the response reports semantic or keyword_fallback in its routing field.", "operationId": "match_skills_endpoint_skills_match_get", "parameters": [ { "name": "q", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "description": "Task/query to rank skills against", "title": "Q" }, "description": "Task/query to rank skills against" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 20, "minimum": 1, "default": 5, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Match Skills Endpoint Skills Match Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Host Registration Status (/docs/api/skills/registration/get) ## GET /skills/registration **Summary:** Skill Host Registration Status Per-host registration status (installed? registered? where?). Read-only. ### OpenAPI Operation ```json { "/skills/registration": { "get": { "tags": [ "skills", "skills", "skills" ], "summary": "Skill Host Registration Status", "description": "Per-host registration status (installed? registered? where?). Read-only.", "operationId": "skill_host_registration_status_skills_registration_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Skill Host Registration Status Skills Registration Get" } } } } } } } } ``` # Get a Skill (/docs/api/skills/skill_id/get) ## GET /skills/{skill_id} **Summary:** Get a Skill Get one Skill and optionally its procedure body or bounded portable bundle. Bundle files are returned only when explicitly requested; binary files use base64. ### OpenAPI Operation ```json { "/skills/{skill_id}": { "get": { "tags": [ "skills" ], "summary": "Get a Skill", "description": "Get one Skill and optionally its procedure body or bounded portable bundle. Bundle files are returned only when explicitly requested; binary files use base64.", "operationId": "get_skill_skills__skill_id__get", "parameters": [ { "name": "skill_id", "in": "path", "description": "Stable Skill ID", "required": true, "schema": { "type": "string", "title": "Skill Id" } }, { "name": "include_body", "in": "query", "description": "Include the SKILL.md body", "required": false, "schema": { "type": "boolean", "description": "Include the SKILL.md body", "default": false, "title": "Include Body" } }, { "name": "include_files", "in": "query", "description": "Explicit opt-in for remote native-host projection. Normal UI detail\nrequests stay small and keep binary assets off the wire.", "required": false, "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Skill Skills Skill Id Get" } } } }, "404": { "description": "Skill not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Search Sources (/docs/api/sources/search/get) ## GET /sources/search **Summary:** Search Sources Full-text search across source names and content. ### OpenAPI Operation ```json { "/sources/search": { "get": { "tags": [ "sources" ], "summary": "Search Sources", "description": "Full-text search across source names and content.", "operationId": "search_sources_sources_search_get", "parameters": [ { "name": "q", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "description": "Search query", "title": "Q" }, "description": "Search query" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Limit" } }, { "name": "labels", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Filter by source label name or label_id. Repeat for AND semantics.", "title": "Labels" }, "description": "Filter by source label name or label_id. Repeat for AND semantics." }, { "name": "label", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Alias for labels. Repeat for AND semantics.", "title": "Label" }, "description": "Alias for labels. Repeat for AND semantics." }, { "name": "metadata", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "description": "Filter by source metadata equality, e.g. metadata=customer=acme. Repeat for AND semantics; repeat the same key for OR values.", "title": "Metadata" }, "description": "Filter by source metadata equality, e.g. metadata=customer=acme. Repeat for AND semantics; repeat the same key for OR values." }, { "name": "space_id", "in": "query", "required": false, "schema": { "type": "string", "description": "Isolation space to search", "default": "default", "title": "Space Id" }, "description": "Isolation space to search" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SourceSearchResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Delete Source (/docs/api/sources/source_id/delete) ## DELETE /sources/{source_id} **Summary:** Delete Source Delete a source and its search index records. ### OpenAPI Operation ```json { "/sources/{source_id}": { "delete": { "tags": [ "sources" ], "summary": "Delete Source", "description": "Delete a source and its search index records.", "operationId": "delete_source_sources__source_id__delete", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Delete Source Sources Source Id Delete" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Source Detail (/docs/api/sources/source_id/get) ## GET /sources/{source_id} **Summary:** Get Source Detail Get source detail with related memories and revision chain. ### OpenAPI Operation ```json { "/sources/{source_id}": { "get": { "tags": [ "sources" ], "summary": "Get Source Detail", "description": "Get source detail with related memories and revision chain.", "operationId": "get_source_detail_sources__source_id__get", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SourceDetailResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Source (/docs/api/sources/source_id/patch) ## PATCH /sources/{source_id} **Summary:** Update Source Update a source's processing state. Supported actions: - **reparse** re-extract and re-index the content. - **ocr_reparse** run or retry vision OCR for deterministic candidate PDF pages. - **mark_stale** flag the source as needing re-processing. ### OpenAPI Operation ```json { "/sources/{source_id}": { "patch": { "tags": [ "sources" ], "summary": "Update Source", "description": "Update a source's processing state.\n\nSupported actions:\n\n- **reparse** re-extract and re-index the content.\n- **ocr_reparse** run or retry vision OCR for deterministic candidate PDF pages.\n- **mark_stale** flag the source as needing re-processing.", "operationId": "update_source_sources__source_id__patch", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSourceRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SourceResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Space Settings (/docs/api/spaces/config/post) ## POST /spaces/config **Summary:** Update Space Settings ### OpenAPI Operation ```json { "/spaces/config": { "post": { "tags": [ "spaces", "spaces" ], "summary": "Update Space Settings", "operationId": "update_space_settings_spaces_config_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceSettingsUpdate" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceSettingsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Space Roster (/docs/api/spaces/roster/get) ## GET /spaces/roster **Summary:** Get Space Roster ### OpenAPI Operation ```json { "/spaces/roster": { "get": { "tags": [ "spaces", "spaces" ], "summary": "Get Space Roster", "operationId": "get_space_roster_spaces_roster_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceSettingsResponse" } } } } } } } } ``` # Delete Space (/docs/api/spaces/space_ref/delete) ## DELETE /spaces/{space_ref} **Summary:** Delete Space ### OpenAPI Operation ```json { "/spaces/{space_ref}": { "delete": { "tags": [ "spaces", "spaces" ], "summary": "Delete Space", "operationId": "delete_space_spaces__space_ref__delete", "parameters": [ { "name": "space_ref", "in": "path", "required": true, "schema": { "type": "string", "title": "Space Ref" } }, { "name": "purge_working_memory", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Purge Working Memory" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceSettingsResponse" } } } }, "409": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceDeleteConflictResponse" } } }, "description": "Conflict" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Space (/docs/api/spaces/space_ref/get) ## GET /spaces/{space_ref} **Summary:** Get Space ### OpenAPI Operation ```json { "/spaces/{space_ref}": { "get": { "tags": [ "spaces", "spaces" ], "summary": "Get Space", "operationId": "get_space_spaces__space_ref__get", "parameters": [ { "name": "space_ref", "in": "path", "required": true, "schema": { "type": "string", "title": "Space Ref" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Space (/docs/api/spaces/space_ref/patch) ## PATCH /spaces/{space_ref} **Summary:** Update Space ### OpenAPI Operation ```json { "/spaces/{space_ref}": { "patch": { "tags": [ "spaces", "spaces" ], "summary": "Update Space", "operationId": "update_space_spaces__space_ref__patch", "parameters": [ { "name": "space_ref", "in": "path", "required": true, "schema": { "type": "string", "title": "Space Ref" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceUpdatePayload" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemorySpaceSettingsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Storage Info (/docs/api/storage/info/get) ## GET /storage/info **Summary:** Get Storage Info Return on-disk sizes for graph, message store, and search projection. ### OpenAPI Operation ```json { "/storage/info": { "get": { "tags": [ "memories" ], "summary": "Get Storage Info", "description": "Return on-disk sizes for graph, message store, and search projection.", "operationId": "get_storage_info_storage_info_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StorageInfoResponse" } } } } } } } } ``` # Optimize Storage (/docs/api/storage/optimize/post) ## POST /storage/optimize **Summary:** Optimize Storage Compact search index and flush database changes. Prunes old LanceDB versions and runs a KuzuDB checkpoint. ### OpenAPI Operation ```json { "/storage/optimize": { "post": { "tags": [ "memories" ], "summary": "Optimize Storage", "description": "Compact search index and flush database changes.\n\nPrunes old LanceDB versions and runs a KuzuDB checkpoint.", "operationId": "optimize_storage_storage_optimize_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OptimizeStorageResponse" } } } } } } } } ``` # Bulk Delete Threads (/docs/api/threads/bulk/delete) ## DELETE /threads/bulk **Summary:** Bulk Delete Threads Delete multiple threads and optionally their extracted memories. ### OpenAPI Operation ```json { "/threads/bulk": { "delete": { "tags": [ "threads" ], "summary": "Bulk Delete Threads", "description": "Delete multiple threads and optionally their extracted memories.", "operationId": "bulk_delete_threads_threads_bulk_delete", "parameters": [ { "name": "cascade_delete_memories", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Delete extracted memories", "default": false, "title": "Cascade Delete Memories" }, "description": "Delete extracted memories" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkDeleteThreadsRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkDeleteThreadsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Import threads (/docs/api/threads/import/post) ## POST /threads/import **Summary:** Import threads Import one or more conversation threads from JSON messages or conversation markdown. **Single mode** set fields directly: ```json { "title": "My Conversation", "messages": [ {"role": "user", "content": "Hello!"}, {"role": "assistant", "content": "Hi there!"} ] } ``` **Markdown mode**pass conversation markdown: ```json { "markdown_content": "## User\n\nHello!\n\n## Assistant\n\nHi there!" } ``` **Batch mode** import multiple threads at once: ```json { "threads": [ {"title": "Thread 1", "messages": [...]}, {"title": "Thread 2", "markdown_content": "## User\n\n..."} ] } ``` Thread IDs are auto-generated when omitted. Titles are inferred from markdown frontmatter when available. See the [Conversation Markdown format reference](https://github.com/nowledge-co/community/blob/main/examples/conversation-markdown.md) for the full `.md` format specification. ### OpenAPI Operation ```json { "/threads/import": { "post": { "tags": [ "threads" ], "summary": "Import threads", "description": "Import one or more conversation threads from JSON messages or conversation markdown.\n\n**Single mode** set fields directly:\n\n```json\n{\n \"title\": \"My Conversation\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Hello!\"},\n {\"role\": \"assistant\", \"content\": \"Hi there!\"}\n ]\n}\n```\n\n**Markdown mode**pass conversation markdown:\n\n```json\n{\n \"markdown_content\": \"## User\\n\\nHello!\\n\\n## Assistant\\n\\nHi there!\"\n}\n```\n\n**Batch mode** import multiple threads at once:\n\n```json\n{\n \"threads\": [\n {\"title\": \"Thread 1\", \"messages\": [...]},\n {\"title\": \"Thread 2\", \"markdown_content\": \"## User\\n\\n...\"}\n ]\n}\n```\n\nThread IDs are auto-generated when omitted. Titles are inferred from markdown frontmatter when available.\n\nSee the [Conversation Markdown format reference](https://github.com/nowledge-co/community/blob/main/examples/conversation-markdown.md) for the full `.md` format specification.", "operationId": "import_threads_threads_import_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadImportRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadImportResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Import Config (/docs/api/threads/import-config/get) ## GET /threads/import-config **Summary:** Get Import Config Get the current import configuration. ### OpenAPI Operation ```json { "/threads/import-config": { "get": { "tags": [ "threads" ], "summary": "Get Import Config", "description": "Get the current import configuration.", "operationId": "get_import_config_threads_import_config_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportConfigModel" } } } } } } } } ``` # Update Import Config (/docs/api/threads/import-config/put) ## PUT /threads/import-config **Summary:** Update Import Config Update import configuration. ### OpenAPI Operation ```json { "/threads/import-config": { "put": { "tags": [ "threads" ], "summary": "Update Import Config", "description": "Update import configuration.", "operationId": "update_import_config_threads_import_config_put", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportConfigUpdateRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportConfigModel" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Parse Thread Content (/docs/api/threads/parse/post) ## POST /threads/parse **Summary:** Parse Thread Content Parse thread content from various formats. ### OpenAPI Operation ```json { "/threads/parse": { "post": { "tags": [ "distillation" ], "summary": "Parse Thread Content", "description": "Parse thread content from various formats.", "operationId": "parse_thread_content_threads_parse_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadParseRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadParseResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Search Threads Full (/docs/api/threads/search/get) ## GET /threads/search **Summary:** Search Threads Full Full thread search with message matching. ### OpenAPI Operation ```json { "/threads/search": { "get": { "tags": [ "threads" ], "summary": "Search Threads Full", "description": "Full thread search with message matching.", "operationId": "search_threads_full_threads_search_get", "parameters": [ { "name": "query", "in": "query", "required": true, "schema": { "type": "string", "description": "Search query", "title": "Query" }, "description": "Search query" }, { "name": "mode", "in": "query", "required": false, "schema": { "type": "string", "description": "Search mode: 'suggestions' or 'full'", "default": "full", "title": "Mode" }, "description": "Search mode: 'suggestions' or 'full'" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "default": 20, "title": "Limit" } }, { "name": "source", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by source (e.g. 'openclaw', 'claude-code')", "title": "Source" }, "description": "Filter by source (e.g. 'openclaw', 'claude-code')" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space to search", "title": "Space Id" }, "description": "Optional isolation space to search" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadSearchResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Thread Sources (/docs/api/threads/sources/get) ## GET /threads/sources **Summary:** Get Thread Sources Get thread source filters across the full thread set. ### OpenAPI Operation ```json { "/threads/sources": { "get": { "tags": [ "threads" ], "summary": "Get Thread Sources", "description": "Get thread source filters across the full thread set.", "operationId": "get_thread_sources_threads_sources_get", "parameters": [ { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space to inspect", "title": "Space Id" }, "description": "Optional isolation space to inspect" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadSourceListResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Thread Summaries (/docs/api/threads/summaries/get) ## GET /threads/summaries **Summary:** Get Thread Summaries Get all thread titles/summaries. ### OpenAPI Operation ```json { "/threads/summaries": { "get": { "tags": [ "threads" ], "summary": "Get Thread Summaries", "description": "Get all thread titles/summaries.", "operationId": "get_thread_summaries_threads_summaries_get", "parameters": [ { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space to list", "title": "Space Id" }, "description": "Optional isolation space to list" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadSummariesResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Delete Thread (/docs/api/threads/thread_id/delete) ## DELETE /threads/{thread_id} **Summary:** Delete Thread Delete a thread and optionally its extracted memories. ### OpenAPI Operation ```json { "/threads/{thread_id}": { "delete": { "tags": [ "threads" ], "summary": "Delete Thread", "description": "Delete a thread and optionally its extracted memories.", "operationId": "delete_thread_threads__thread_id__delete", "parameters": [ { "name": "thread_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Thread Id" } }, { "name": "cascade_delete_memories", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Delete extracted memories", "default": false, "title": "Cascade Delete Memories" }, "description": "Delete extracted memories" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteThreadResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Thread (/docs/api/threads/thread_id/get) ## GET /threads/{thread_id} **Summary:** Get Thread Get a thread with messages. Supports pagination via limit/offset. ### OpenAPI Operation ```json { "/threads/{thread_id}": { "get": { "tags": [ "threads" ], "summary": "Get Thread", "description": "Get a thread with messages. Supports pagination via limit/offset.", "operationId": "get_thread_threads__thread_id__get", "parameters": [ { "name": "thread_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Thread Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 500, "minimum": 1 }, { "type": "null" } ], "description": "Max messages to return", "title": "Limit" }, "description": "Max messages to return" }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "description": "Skip first N messages", "default": 0, "title": "Offset" }, "description": "Skip first N messages" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadFetchResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Create embeddings (/docs/api/v1/embeddings/post) ## POST /v1/embeddings **Summary:** Create embeddings Generate embeddings with the active search model on this local or self-hosted server. Supports OpenAI-compatible float and base64 responses plus the optional Nowledge input_type extension. The endpoint is not available on Nowledge Cloud. If a remote embedding provider is active, calls are forwarded by this server and count toward that provider's usage. ### OpenAPI Operation ```json { "/v1/embeddings": { "post": { "tags": [ "openai-compatible" ], "summary": "Create embeddings", "description": "Generate embeddings with the active search model on this local or self-hosted server. Supports OpenAI-compatible float and base64 responses plus the optional Nowledge input_type extension. The endpoint is not available on Nowledge Cloud. If a remote embedding provider is active, calls are forwarded by this server and count toward that provider's usage.", "operationId": "create_embeddings_v1_embeddings_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OpenAIEmbeddingRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OpenAIEmbeddingResponse" } } } }, "400": { "description": "Invalid request or model mismatch" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } }, "500": { "description": "Embedding generation failed" }, "503": { "description": "No real embedding model is active" } } } } } ``` # List the active embedding model (/docs/api/v1/models/get) ## GET /v1/models **Summary:** List the active embedding model List the active search embedding model on this local or self-hosted server. The endpoint is not available on Nowledge Cloud. If a remote embedding provider is selected in Settings, requests are forwarded by this server and count toward that provider's usage. ### OpenAPI Operation ```json { "/v1/models": { "get": { "tags": [ "openai-compatible" ], "summary": "List the active embedding model", "description": "List the active search embedding model on this local or self-hosted server. The endpoint is not available on Nowledge Cloud. If a remote embedding provider is selected in Settings, requests are forwarded by this server and count toward that provider's usage.", "operationId": "list_models_v1_models_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OpenAIModelListResponse" } } } }, "503": { "description": "No real embedding model is active" } } } } } ``` # List recurring AI Now tasks (/docs/api/agent/ai-now/schedules/get) ## GET /agent/ai-now/schedules **Summary:** List recurring AI Now tasks ### OpenAPI Operation ```json { "/agent/ai-now/schedules": { "get": { "tags": [ "ai-now" ], "summary": "List recurring AI Now tasks", "operationId": "openapi_list_schedules", "parameters": [ { "name": "include_deleted", "in": "path", "required": true, "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleListResponse" } } } } } } } } ``` # Create a recurring AI Now task draft (/docs/api/agent/ai-now/schedules/post) ## POST /agent/ai-now/schedules **Summary:** Create a recurring AI Now task draft Creates a draft only. The task cannot run unattended until it is explicitly confirmed. ### OpenAPI Operation ```json { "/agent/ai-now/schedules": { "post": { "tags": [ "ai-now" ], "summary": "Create a recurring AI Now task draft", "description": "Creates a draft only. The task cannot run unattended until it is explicitly confirmed.", "operationId": "openapi_create_schedule", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateScheduleRequest" } } }, "required": true }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResponse" } } } }, "400": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } } } } } } ``` # List Ai Now Sessions (/docs/api/agent/ai-now/sessions/get) ## GET /agent/ai-now/sessions **Summary:** List Ai Now Sessions List AI Now sessions. By-id-direct. Includes backend sessions plus read-only legacy ACP sessions so upgrades preserve existing user conversations. ### OpenAPI Operation ```json { "/agent/ai-now/sessions": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "List Ai Now Sessions", "description": "List AI Now sessions.\n\nBy-id-direct. Includes backend sessions plus read-only legacy ACP sessions\nso upgrades preserve existing user conversations.", "operationId": "list_ai_now_sessions_agent_ai_now_sessions_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response List Ai Now Sessions Agent Ai Now Sessions Get" } } } } } } } } ``` # Create Ai Now Session (/docs/api/agent/ai-now/sessions/post) ## POST /agent/ai-now/sessions **Summary:** Create Ai Now Session Create a backend-owned AI Now session. Space-scoped through ``activeSpaceId`` for Nowledge Mem MCP retrieval. ### OpenAPI Operation ```json { "/agent/ai-now/sessions": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Create Ai Now Session", "description": "Create a backend-owned AI Now session.\n\nSpace-scoped through ``activeSpaceId`` for Nowledge Mem MCP retrieval.", "operationId": "create_ai_now_session_agent_ai_now_sessions_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowSessionCreateRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Create Ai Now Session Agent Ai Now Sessions Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Sync Ai Now Skill Prompts (/docs/api/agent/ai-now/skill-prompts/post) ## POST /agent/ai-now/skill-prompts **Summary:** Sync Ai Now Skill Prompts Update the server-side AI Now skill prompt injection file. Backend-owned AI Now sessions read this file when preparing their agent spec, so web/mobile/remote clients must sync it to the backend, not only to a client-local Tauri filesystem. ### OpenAPI Operation ```json { "/agent/ai-now/skill-prompts": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Sync Ai Now Skill Prompts", "description": "Update the server-side AI Now skill prompt injection file.\n\nBackend-owned AI Now sessions read this file when preparing their agent spec,\nso web/mobile/remote clients must sync it to the backend, not only to a\nclient-local Tauri filesystem.", "operationId": "sync_ai_now_skill_prompts_agent_ai_now_skill_prompts_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowSkillPromptsRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Sync Ai Now Skill Prompts Agent Ai Now Skill Prompts Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Feed Events (/docs/api/agent/feed/events/get) ## GET /agent/feed/events **Summary:** Get Feed Events Read immutable Timeline events with bounded pagination and filters. Set review_only with unresolved_only to project the pending Memory Review Inbox; membership is determined by event type rather than presentation severity. Each pending review advertises allowed_actions, the conservative recommended_action for explicit approval, automatic_resolution=expired_no_change, and its absolute expires_at timestamp. ### OpenAPI Operation ```json { "/agent/feed/events": { "get": { "tags": [ "knowledge-agent" ], "summary": "Get Feed Events", "description": "Read immutable Timeline events with bounded pagination and filters. Set review_only with unresolved_only to project the pending Memory Review Inbox; membership is determined by event type rather than presentation severity. Each pending review advertises allowed_actions, the conservative recommended_action for explicit approval, automatic_resolution=expired_no_change, and its absolute expires_at timestamp.", "operationId": "get_feed_events_agent_feed_events_get", "parameters": [ { "name": "limit", "in": "query", "description": "Maximum events returned on this page.", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 50, "title": "Limit", "format": "int64" } }, { "name": "offset", "in": "query", "description": "Zero-based result offset.", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset", "format": "int64" } }, { "name": "severity", "in": "query", "description": "Filter by presentation severity.", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Severity", "type": "string" } }, { "name": "event_type", "in": "query", "description": "Filter by one exact event type.", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Event Type", "type": "string" } }, { "name": "unresolved_only", "in": "query", "description": "Return only events that have not been resolved.", "required": false, "schema": { "type": "boolean", "default": false, "title": "Unresolved Only" } }, { "name": "review_only", "in": "query", "description": "Project only actionable Timeline review families. Event type, not\npresentation severity, defines membership (Cloud/local parity).", "required": false, "schema": { "type": "boolean", "default": false } }, { "name": "last_n_days", "in": "query", "description": "Number of recent date partitions to scan when no explicit range is supplied.", "required": false, "schema": { "type": "integer", "maximum": 365, "minimum": 1, "default": 90, "title": "Last N Days", "format": "int64" } }, { "name": "date_from", "in": "query", "description": "Start of date range (YYYY-MM-DD). Overrides last_n_days lower bound.", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Start of date range (YYYY-MM-DD). Overrides last_n_days lower bound.", "title": "Date From", "type": "string" } }, { "name": "date_to", "in": "query", "description": "End of date range (YYYY-MM-DD, inclusive). Defaults to today.", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "End of date range (YYYY-MM-DD, inclusive). Defaults to today.", "title": "Date To", "type": "string" } }, { "name": "source", "in": "query", "description": "Filter by metadata.source value (e.g. 'library:source_id').", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by metadata.source value (e.g. 'library:source_id').", "title": "Source", "type": "string" } }, { "name": "space_id", "in": "query", "description": "Filter by memory space. Feed storage stays global; matching is based on event metadata or related memories.", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by memory space. Feed storage stays global; matching is based on event metadata or related memories.", "title": "Space Id", "type": "string" } }, { "name": "include_total", "in": "query", "description": "Return an exact total count. Set false for faster first-page loading when only page data and has_more are needed.", "required": false, "schema": { "type": "boolean", "description": "Return an exact total count. Set false for faster first-page loading when only page data and has_more are needed.", "default": true, "title": "Include Total" } }, { "name": "tz", "in": "query", "description": "Client IANA timezone so `date_from`/`date_to` (local day strings from the\ncalendar/timeline) compare against each event's LOCAL day, not its UTC day.\nAbsent/unknown → UTC (prior behavior).", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FeedEventsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Send Message (/docs/api/agent/graph-intelligence/message/post) ## POST /agent/graph-intelligence/message **Summary:** Send Message Send a message to the Graph Intelligence Agent with frozen graph context. Returns an SSE stream with text, tool_call, tool_result, canvas_command, and done events. The graphContext is injected into the agent prompt and stored as user message metadata. ### OpenAPI Operation ```json { "/agent/graph-intelligence/message": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "graph-intelligence" ], "summary": "Send Message", "description": "Send a message to the Graph Intelligence Agent with frozen graph context.\n\nReturns an SSE stream with text, tool_call, tool_result, canvas_command,\nand done events. The graphContext is injected into the agent prompt and\nstored as user message metadata.", "operationId": "send_message_agent_graph_intelligence_message_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphIntelligenceMessageRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Load Session (/docs/api/agent/graph-intelligence/session/get) ## GET /agent/graph-intelligence/session **Summary:** Load Session Load the last chat session from disk. ### OpenAPI Operation ```json { "/agent/graph-intelligence/session": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "graph-intelligence" ], "summary": "Load Session", "description": "Load the last chat session from disk.", "operationId": "load_session_agent_graph_intelligence_session_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } } } ``` # Save Session (/docs/api/agent/graph-intelligence/session/post) ## POST /agent/graph-intelligence/session **Summary:** Save Session Save chat session to disk (atomic write, size-capped). ### OpenAPI Operation ```json { "/agent/graph-intelligence/session": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "graph-intelligence" ], "summary": "Save Session", "description": "Save chat session to disk (atomic write, size-capped).", "operationId": "save_session_agent_graph_intelligence_session_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SaveSessionRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Status (/docs/api/agent/graph-intelligence/status/get) ## GET /agent/graph-intelligence/status **Summary:** Get Status Check if the Graph Intelligence Agent is running. ### OpenAPI Operation ```json { "/agent/graph-intelligence/status": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "graph-intelligence" ], "summary": "Get Status", "description": "Check if the Graph Intelligence Agent is running.", "operationId": "get_status_agent_graph_intelligence_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } } } ``` # Get Knowledge Processing Status (/docs/api/agent/knowledge-processing/status/get) ## GET /agent/knowledge-processing/status **Summary:** Get Knowledge Processing Status Get knowledge processing settings and status. Returns current configuration, task status history, and token budget usage. ### OpenAPI Operation ```json { "/agent/knowledge-processing/status": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Get Knowledge Processing Status", "description": "Get knowledge processing settings and status.\n\nReturns current configuration, task status history, and token budget usage.", "operationId": "get_knowledge_processing_status_agent_knowledge_processing_status_get", "parameters": [ { "name": "include_settings", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Include Settings" } }, { "name": "include_ledgers", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Include Ledgers" } }, { "name": "include_dedup", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Include Dedup" } }, { "name": "include_usage", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Include Usage" } }, { "name": "include_history", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Include History" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Knowledge Processing Status Agent Knowledge Processing Status Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Builder Chat (/docs/api/agent/skill-builder/chat/post) ## POST /agent/skill-builder/chat **Summary:** Skill Builder Chat The Skills copilot turn (SSE). Reads the screen context, routes intent, and answers, drafts a new skill, or emits one UI action. Events: ``routing`` -> ``message`` (the reply) -> then EITHER ``action`` (a UI command the frontend applies) OR the draft sub-stream (``searching`` -> ``knowledge`` -> ``drafting`` -> ``proposal``) -> ``done`` (or ``error``). Cross-space when ``space_id`` is omitted. ### OpenAPI Operation ```json { "/agent/skill-builder/chat": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Chat", "description": "The Skills copilot turn (SSE). Reads the screen context, routes intent, and\nanswers, drafts a new skill, or emits one UI action.\n\nEvents: ``routing`` -> ``message`` (the reply) -> then EITHER ``action`` (a UI\ncommand the frontend applies) OR the draft sub-stream (``searching`` ->\n``knowledge`` -> ``drafting`` -> ``proposal``) -> ``done`` (or ``error``).\nCross-space when ``space_id`` is omitted.", "operationId": "skill_builder_chat_agent_skill_builder_chat_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillBuilderChatRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Builder Discover Importable (/docs/api/agent/skill-builder/discover-importable/get) ## GET /agent/skill-builder/discover-importable **Summary:** Skill Builder Discover Importable Hand-written skills found in the user's connected host dirs that Mem does not manage — the discovery half of enroll. Read-only scan; the user selects which to import. Reads local disk directly (local-only, enforced). ### OpenAPI Operation ```json { "/agent/skill-builder/discover-importable": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Discover Importable", "description": "Hand-written skills found in the user's connected host dirs that Mem does not\nmanage — the discovery half of enroll. Read-only scan; the user selects which to\nimport. Reads local disk directly (local-only, enforced).", "operationId": "skill_builder_discover_importable_agent_skill_builder_discover_importable_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Skill Builder Discover Importable Agent Skill Builder Discover Importable Get" } } } } } } } } ``` # Skill Builder Edit Body (/docs/api/agent/skill-builder/edit-body/post) ## POST /agent/skill-builder/edit-body **Summary:** Skill Builder Edit Body Stage a user-authored body as a pending version (the user as a third author of ``pending_version``, beside refine-AI and the curator). Stages INSTANTLY (validate + compose + secret-scan), then computes the A/B transparency proof in the BACKGROUND so the save isn't blocked on running the benchmark through the model (that was the 20-second "Saving…"). The edit is INTENT (D4): the proof never refuses it, only shows it, and the user can apply via ``POST /skills/{id}/apply-version`` without waiting for it. ### OpenAPI Operation ```json { "/agent/skill-builder/edit-body": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Edit Body", "description": "Stage a user-authored body as a pending version (the user as a third author\nof ``pending_version``, beside refine-AI and the curator).\n\nStages INSTANTLY (validate + compose + secret-scan), then computes the A/B\ntransparency proof in the BACKGROUND so the save isn't blocked on running the\nbenchmark through the model (that was the 20-second \"Saving…\"). The edit is\nINTENT (D4): the proof never refuses it, only shows it, and the user can apply\nvia ``POST /skills/{id}/apply-version`` without waiting for it.", "operationId": "skill_builder_edit_body_agent_skill_builder_edit_body_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillEditBodyRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Skill Builder Edit Body Agent Skill Builder Edit Body Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Builder Import (/docs/api/agent/skill-builder/import/post) ## POST /agent/skill-builder/import **Summary:** Skill Builder Import Import a hand-written skill as a managed draft (body verbatim, no compile). The third way a skill is born (beside suggested + authored-from-scratch): it flows through the same review -> activate -> materialize -> evolve loop, gaining verification, self-improvement, cross-tool sync, and versioning. A folder import keeps the whole tree (nested folders + binary assets) verbatim. Returns the created draft, or — when it looks like an existing active skill and ``force`` is false — the duplicate it matched, so the user can strengthen that one instead. Looks up by content; space-agnostic (skills list cross-space). ### OpenAPI Operation ```json { "/agent/skill-builder/import": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Import", "description": "Import a hand-written skill as a managed draft (body verbatim, no compile).\n\nThe third way a skill is born (beside suggested + authored-from-scratch): it\nflows through the same review -> activate -> materialize -> evolve loop, gaining\nverification, self-improvement, cross-tool sync, and versioning. A folder import\nkeeps the whole tree (nested folders + binary assets) verbatim. Returns the\ncreated draft, or — when it looks like an existing active skill and ``force`` is\nfalse — the duplicate it matched, so the user can strengthen that one instead.\nLooks up by content; space-agnostic (skills list cross-space).", "operationId": "skill_builder_import_agent_skill_builder_import_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillImportRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Skill Builder Import Agent Skill Builder Import Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Builder Preview Importable (/docs/api/agent/skill-builder/preview-importable/get) ## GET /agent/skill-builder/preview-importable **Summary:** Skill Builder Preview Importable The SKILL.md + file list for one discoverable skill, for the enroll preview pane (read what you're bringing in before you commit). Path-validated to a host skills dir. Reads local disk directly (local-only, enforced). ### OpenAPI Operation ```json { "/agent/skill-builder/preview-importable": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Preview Importable", "description": "The SKILL.md + file list for one discoverable skill, for the enroll preview\npane (read what you're bringing in before you commit). Path-validated to a host\nskills dir. Reads local disk directly (local-only, enforced).", "operationId": "skill_builder_preview_importable_agent_skill_builder_preview_importable_get", "parameters": [ { "name": "path", "in": "query", "required": true, "schema": { "type": "string", "title": "Path" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Skill Builder Preview Importable Agent Skill Builder Preview Importable Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Builder Propose (/docs/api/agent/skill-builder/propose/post) ## POST /agent/skill-builder/propose **Summary:** Skill Builder Propose Propose a skill draft from intent, streaming the work as it happens (SSE). Events (``data: {json}``): ``searching`` -> ``knowledge`` (the threads + notes it found, shown before the draft) -> ``drafting`` -> ``proposal`` (the draft + which sources it chose) -> ``done`` (or ``error``). The UI renders this as a live process timeline so the agent shows its work. Cross-space when ``space_id`` is omitted. The proposal is the builder form's pre-fill; the user reviews and creates. ### OpenAPI Operation ```json { "/agent/skill-builder/propose": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Propose", "description": "Propose a skill draft from intent, streaming the work as it happens (SSE).\n\nEvents (``data: {json}``): ``searching`` -> ``knowledge`` (the threads + notes\nit found, shown before the draft) -> ``drafting`` -> ``proposal`` (the draft +\nwhich sources it chose) -> ``done`` (or ``error``). The UI renders this as a\nlive process timeline so the agent shows its work. Cross-space when\n``space_id`` is omitted. The proposal is the builder form's pre-fill; the user\nreviews and creates.", "operationId": "skill_builder_propose_agent_skill_builder_propose_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillBuilderProposeRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Builder Refine (/docs/api/agent/skill-builder/refine/post) ## POST /agent/skill-builder/refine **Summary:** Skill Builder Refine Propose a sharper version of a compiled skill from how it has performed (plus optional guidance). Records it as a ``pending_version`` the user reviews and applies via apply-version; never auto-commits. Mirrors ProposeSkillVersion. Non-streaming; ``/refine/stream`` shows the work as it happens. ### OpenAPI Operation ```json { "/agent/skill-builder/refine": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Refine", "description": "Propose a sharper version of a compiled skill from how it has performed\n(plus optional guidance). Records it as a ``pending_version`` the user reviews\nand applies via apply-version; never auto-commits. Mirrors ProposeSkillVersion.\nNon-streaming; ``/refine/stream`` shows the work as it happens.", "operationId": "skill_builder_refine_agent_skill_builder_refine_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillRefineRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Skill Builder Refine Agent Skill Builder Refine Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Trigger Community Detection (/docs/api/agent/trigger/community-detection/post) ## POST /agent/trigger/community-detection **Summary:** Trigger Community Detection Detect topic clusters in the knowledge graph. Groups related entities into communities and generates AI summaries for each cluster. ### OpenAPI Operation ```json { "/agent/trigger/community-detection": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Community Detection", "description": "Detect topic clusters in the knowledge graph.\n\nGroups related entities into communities and generates AI summaries for each cluster.", "operationId": "trigger_community_detection_agent_trigger_community_detection_post", "parameters": [ { "name": "resolution", "in": "query", "required": false, "schema": { "type": "number", "default": 1, "title": "Resolution" } }, { "name": "generate_ai_summary", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Generate Ai Summary" } }, { "name": "summary_limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 200, "minimum": 1 }, { "type": "null" } ], "title": "Summary Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Trigger Community Detection Agent Trigger Community Detection Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Trigger Crystallization (/docs/api/agent/trigger/crystallization/post) ## POST /agent/trigger/crystallization **Summary:** Trigger Crystallization Trigger a crystallization review. The agent analyzes recent memories and synthesizes higher-level insights: patterns, recurring themes, and emerging conclusions. ### OpenAPI Operation ```json { "/agent/trigger/crystallization": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Crystallization", "description": "Trigger a crystallization review.\n\nThe agent analyzes recent memories and synthesizes higher-level insights: patterns, recurring themes, and emerging conclusions.", "operationId": "trigger_crystallization_agent_trigger_crystallization_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Trigger Crystallization Agent Trigger Crystallization Post" } } } } } } } } ``` # Trigger Daily Briefing (/docs/api/agent/trigger/daily-briefing/post) ## POST /agent/trigger/daily-briefing **Summary:** Trigger Daily Briefing Manually trigger a daily briefing. ### OpenAPI Operation ```json { "/agent/trigger/daily-briefing": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Daily Briefing", "description": "Manually trigger a daily briefing.", "operationId": "trigger_daily_briefing_agent_trigger_daily_briefing_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Trigger Daily Briefing Agent Trigger Daily Briefing Post" } } } } } } } } ``` # Trigger Decay Refresh (/docs/api/agent/trigger/decay-refresh/post) ## POST /agent/trigger/decay-refresh **Summary:** Trigger Decay Refresh Recalculate memory relevance scores. Refreshes the time-based relevance ranking so frequently accessed and recently updated memories surface higher in search results. ### OpenAPI Operation ```json { "/agent/trigger/decay-refresh": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Decay Refresh", "description": "Recalculate memory relevance scores.\n\nRefreshes the time-based relevance ranking so frequently accessed and recently updated memories surface higher in search results.", "operationId": "trigger_decay_refresh_agent_trigger_decay_refresh_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Trigger Decay Refresh Agent Trigger Decay Refresh Post" } } } } } } } } ``` # Trigger Insight Detection (/docs/api/agent/trigger/insight-detection/post) ## POST /agent/trigger/insight-detection **Summary:** Trigger Insight Detection Manually trigger proactive insight detection. ### OpenAPI Operation ```json { "/agent/trigger/insight-detection": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Insight Detection", "description": "Manually trigger proactive insight detection.", "operationId": "trigger_insight_detection_agent_trigger_insight_detection_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Trigger Insight Detection Agent Trigger Insight Detection Post" } } } } } } } } ``` # Trigger Kg Extraction (/docs/api/agent/trigger/kg-extraction/post) ## POST /agent/trigger/kg-extraction **Summary:** Trigger Kg Extraction Extract entities and relationships from memories. Builds the knowledge graph by analyzing memory content. Use `backfill=true` to queue the next bounded backfill wave for unprocessed memories, or pass specific `memory_ids` to target individual ones. ### OpenAPI Operation ```json { "/agent/trigger/kg-extraction": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Kg Extraction", "description": "Extract entities and relationships from memories.\n\nBuilds the knowledge graph by analyzing memory content. Use `backfill=true`\nto queue the next bounded backfill wave for unprocessed memories, or pass\nspecific `memory_ids` to target individual ones.", "operationId": "trigger_kg_extraction_agent_trigger_kg_extraction_post", "parameters": [ { "name": "backfill", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Backfill" } }, { "name": "memory_ids", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Comma-separated memory IDs for scoped extraction", "title": "Memory Ids" }, "description": "Comma-separated memory IDs for scoped extraction" }, { "name": "scan_limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 2000, "minimum": 1 }, { "type": "null" } ], "title": "Scan Limit" } }, { "name": "batch_size", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 10, "minimum": 1 }, { "type": "null" } ], "title": "Batch Size" } }, { "name": "repair_empty", "in": "query", "required": false, "schema": { "type": "boolean", "description": "When backfill=true, process a bounded repair wave for memories previously marked extracted but carrying no graph facts.", "default": false, "title": "Repair Empty" }, "description": "When backfill=true, process a bounded repair wave for memories previously marked extracted but carrying no graph facts." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Trigger Kg Extraction Agent Trigger Kg Extraction Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Trigger Label Consolidation (/docs/api/agent/trigger/label-consolidation/post) ## POST /agent/trigger/label-consolidation **Summary:** Trigger Label Consolidation Consolidate duplicate labels across the knowledge graph. Embedding finds semantically-similar label pairs (including cross-language), an LLM judges which are the same concept, and confirmed duplicates are merged into one (reversible). Pass dry_run=true to preview the LLM's proposed merges in the feed event without changing anything. ### OpenAPI Operation ```json { "/agent/trigger/label-consolidation": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Label Consolidation", "description": "Consolidate duplicate labels across the knowledge graph.\n\nEmbedding finds semantically-similar label pairs (including cross-language),\nan LLM judges which are the same concept, and confirmed duplicates are\nmerged into one (reversible). Pass dry_run=true to preview the LLM's\nproposed merges in the feed event without changing anything.", "operationId": "trigger_label_consolidation_agent_trigger_label_consolidation_post", "parameters": [ { "name": "dry_run", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Preview proposed merges without applying them", "default": false, "title": "Dry Run" }, "description": "Preview proposed merges without applying them" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Trigger Label Consolidation Agent Trigger Label Consolidation Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Trigger Memory Compaction (/docs/api/agent/trigger/memory-compaction/post) ## POST /agent/trigger/memory-compaction **Summary:** Trigger Memory Compaction Review and merge similar memories. The agent scans for memories that cover the same topic and suggests merging duplicates or linking related ones. ### OpenAPI Operation ```json { "/agent/trigger/memory-compaction": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Memory Compaction", "description": "Review and merge similar memories.\n\nThe agent scans for memories that cover the same topic and suggests merging duplicates or linking related ones.", "operationId": "trigger_memory_compaction_agent_trigger_memory_compaction_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Trigger Memory Compaction Agent Trigger Memory Compaction Post" } } } } } } } } ``` # Trigger Guidance Review (/docs/api/agent/trigger/rule-review/post) ## POST /agent/trigger/rule-review **Summary:** Trigger Guidance Review Manually trigger learned rule candidate review. Detection only: suggests draft always-on rules from repeated memory evidence. Drafts are not injected into Context Bundle until the user enables them. ### OpenAPI Operation ```json { "/agent/trigger/rule-review": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Guidance Review", "description": "Manually trigger learned rule candidate review.\n\nDetection only: suggests draft always-on rules from repeated memory\nevidence. Drafts are not injected into Context Bundle until the user enables\nthem.", "operationId": "trigger_guidance_review_agent_trigger_rule_review_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Trigger Guidance Review Agent Trigger Rule Review Post" } } } } } } } } ``` # Trigger Skill Compile (/docs/api/agent/trigger/skill-compile/post) ## POST /agent/trigger/skill-compile **Summary:** Trigger Skill Compile Compile one promoted candidate into a draft skill. Reads the candidate's evidence and writes a SKILL.md bundle, moving the candidate to 'draft' for review. Triggered after the user promotes a candidate. ### OpenAPI Operation ```json { "/agent/trigger/skill-compile": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Skill Compile", "description": "Compile one promoted candidate into a draft skill.\n\nReads the candidate's evidence and writes a SKILL.md bundle, moving the\ncandidate to 'draft' for review. Triggered after the user promotes a candidate.", "operationId": "trigger_skill_compile_agent_trigger_skill_compile_post", "parameters": [ { "name": "skill_id", "in": "query", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Trigger Skill Compile Agent Trigger Skill Compile Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Trigger Skill Review (/docs/api/agent/trigger/skill-review/post) ## POST /agent/trigger/skill-review **Summary:** Trigger Skill Review Manually trigger a skill target review. Surfaces reusable procedural capabilities from recurring EVOLVES chains as skill candidates. Detection only: proposes candidates, never compiles skills. ### OpenAPI Operation ```json { "/agent/trigger/skill-review": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Skill Review", "description": "Manually trigger a skill target review.\n\nSurfaces reusable procedural capabilities from recurring EVOLVES chains as\nskill candidates. Detection only: proposes candidates, never compiles skills.", "operationId": "trigger_skill_review_agent_trigger_skill_review_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Trigger Skill Review Agent Trigger Skill Review Post" } } } } } } } } ``` # Trigger Unit Type Reclassification (/docs/api/agent/trigger/unit-type-reclassification/post) ## POST /agent/trigger/unit-type-reclassification **Summary:** Trigger Unit Type Reclassification Review weak Memory unit_type metadata. This on-demand maintenance task never changes content or embeddings. Apply mode updates Kuzu metadata and patches LanceDB filter metadata in place. ### OpenAPI Operation ```json { "/agent/trigger/unit-type-reclassification": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Unit Type Reclassification", "description": "Review weak Memory unit_type metadata.\n\nThis on-demand maintenance task never changes content or embeddings. Apply\nmode updates Kuzu metadata and patches LanceDB filter metadata in place.", "operationId": "trigger_unit_type_reclassification_agent_trigger_unit_type_reclassification_post", "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/UnitTypeReclassificationRequest" }, { "type": "null" } ], "title": "Request" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Trigger Unit Type Reclassification Agent Trigger Unit Type Reclassification Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Trigger Wm Refresh (/docs/api/agent/trigger/wm-refresh/post) ## POST /agent/trigger/wm-refresh **Summary:** Trigger Wm Refresh Queue a bounded Working Memory refresh. With memory IDs, this reviews only those memories plus the current Working Memory. Without IDs, it is a cheap dispatch/proof run that records the current direct path without opening a tool-using agent session. ### OpenAPI Operation ```json { "/agent/trigger/wm-refresh": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Trigger Wm Refresh", "description": "Queue a bounded Working Memory refresh.\n\nWith memory IDs, this reviews only those memories plus the current Working\nMemory. Without IDs, it is a cheap dispatch/proof run that records the\ncurrent direct path without opening a tool-using agent session.", "operationId": "trigger_wm_refresh_agent_trigger_wm_refresh_post", "parameters": [ { "name": "memory_ids", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional comma-separated memory IDs to consider.", "title": "Memory Ids" }, "description": "Optional comma-separated memory IDs to consider." }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Space Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Trigger Wm Refresh Agent Trigger Wm Refresh Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Working Memory History (/docs/api/agent/working-memory/history/get) ## GET /agent/working-memory/history **Summary:** Get Working Memory History List dates with archived working memory. Returns available dates newest-first. Use a specific date with the GET endpoint to read that day's content. ### OpenAPI Operation ```json { "/agent/working-memory/history": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Get Working Memory History", "description": "List dates with archived working memory.\n\nReturns available dates newest-first. Use a specific date with the GET endpoint to read that day's content.", "operationId": "get_working_memory_history_agent_working_memory_history_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 365, "minimum": 1, "default": 30, "title": "Limit" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "type": "string", "description": "Isolation space to inspect", "default": "default", "title": "Space Id" }, "description": "Isolation space to inspect" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Working Memory History Agent Working Memory History Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Check (/docs/api/admin/upgrade/check/get) ## GET /admin/upgrade/check **Summary:** Check Aggregated check: current vs latest, sidecar reachability, pulled status. Safe to call from any same-origin client; respects the origin guard. ### OpenAPI Operation ```json { "/admin/upgrade/check": { "get": { "tags": [ "admin-upgrade", "admin", "upgrade" ], "summary": "Check", "description": "Aggregated check: current vs latest, sidecar reachability, pulled status.\n\nSafe to call from any same-origin client; respects the origin guard.", "operationId": "check_admin_upgrade_check_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpgradeCheckResponse" } } } } } } } } ``` # Download (/docs/api/admin/upgrade/download/post) ## POST /admin/upgrade/download **Summary:** Download Pre-pull a target tag into the local docker cache. Idempotent. Returns 412 if the sidecar is unreachable — the actual `docker pull` runs inside the sidecar, which is the only piece holding docker.sock. ### OpenAPI Operation ```json { "/admin/upgrade/download": { "post": { "tags": [ "admin-upgrade", "admin", "upgrade" ], "summary": "Download", "description": "Pre-pull a target tag into the local docker cache. Idempotent.\n\nReturns 412 if the sidecar is unreachable — the actual `docker pull`\nruns inside the sidecar, which is the only piece holding docker.sock.", "operationId": "download_admin_upgrade_download_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpgradeActionRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Download Admin Upgrade Download Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Install (/docs/api/admin/upgrade/install/post) ## POST /admin/upgrade/install **Summary:** Install Snapshot + recreate the mem container on a new tag. Strict checks BEFORE forwarding to the sidecar: - Origin guard (default-closed). - Stable semver tag. - `confirm` matches `tag` (the type-to-confirm contract). - Reject downgrades and same-version applies (catch operator misclicks). The sidecar runs free-space precheck + lock acquisition + snapshot + recreate detached and returns 202 immediately. The UI polls /check to learn when the new tag is live. ### OpenAPI Operation ```json { "/admin/upgrade/install": { "post": { "tags": [ "admin-upgrade", "admin", "upgrade" ], "summary": "Install", "description": "Snapshot + recreate the mem container on a new tag.\n\nStrict checks BEFORE forwarding to the sidecar:\n - Origin guard (default-closed).\n - Stable semver tag.\n - `confirm` matches `tag` (the type-to-confirm contract).\n - Reject downgrades and same-version applies (catch operator misclicks).\n\nThe sidecar runs free-space precheck + lock acquisition + snapshot +\nrecreate detached and returns 202 immediately. The UI polls /check\nto learn when the new tag is live.", "operationId": "install_admin_upgrade_install_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpgradeApplyRequest" } } }, "required": true }, "responses": { "202": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Install Admin Upgrade Install Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Content Store Migration Status (/docs/api/content-store/migration/status/get) ## GET /content-store/migration/status **Summary:** Get Content Store Migration Status Return the truthful Content Store ownership and migration state. ### OpenAPI Operation ```json { "/content-store/migration/status": { "get": { "tags": [ "content-store" ], "summary": "Get Content Store Migration Status", "description": "Return the truthful Content Store ownership and migration state.", "operationId": "get_content_store_migration_status_content_store_migration_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Get Content Store Migration Status Content Store Migration Status Get" } } } } } } } } ``` # Cleanup Legacy Thread Message Graph (/docs/api/content-store/thread-messages/cleanup-legacy-graph/post) ## POST /content-store/thread-messages/cleanup-legacy-graph **Summary:** Cleanup Legacy Thread Message Graph Preview or run bounded deletion of legacy Kuzu Message graph rows. ### OpenAPI Operation ```json { "/content-store/thread-messages/cleanup-legacy-graph": { "post": { "tags": [ "content-store" ], "summary": "Cleanup Legacy Thread Message Graph", "description": "Preview or run bounded deletion of legacy Kuzu Message graph rows.", "operationId": "cleanup_legacy_thread_message_graph_content_store_thread_messages_cleanup_legacy_graph_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 500, "title": "Batch Size" } }, { "name": "max_batches", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10000, "minimum": 1, "default": 100, "title": "Max Batches" } }, { "name": "dry_run", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Dry Run" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Cleanup Legacy Thread Message Graph Content Store Thread Messages Cleanup Legacy Graph Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Copy Thread Messages Until Finished (/docs/api/content-store/thread-messages/copy-all/post) ## POST /content-store/thread-messages/copy-all **Summary:** Copy Thread Messages Until Finished Copy legacy messages in bounded batches without cutting over ownership. ### OpenAPI Operation ```json { "/content-store/thread-messages/copy-all": { "post": { "tags": [ "content-store" ], "summary": "Copy Thread Messages Until Finished", "description": "Copy legacy messages in bounded batches without cutting over ownership.", "operationId": "copy_thread_messages_until_finished_content_store_thread_messages_copy_all_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 500, "title": "Batch Size" } }, { "name": "max_batches", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10000, "minimum": 1, "default": 1000, "title": "Max Batches" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Copy Thread Messages Until Finished Content Store Thread Messages Copy All Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Copy Thread Messages Batch (/docs/api/content-store/thread-messages/copy-batch/post) ## POST /content-store/thread-messages/copy-batch **Summary:** Copy Thread Messages Batch Copy one bounded legacy Kuzu Message page into SQLite. ### OpenAPI Operation ```json { "/content-store/thread-messages/copy-batch": { "post": { "tags": [ "content-store" ], "summary": "Copy Thread Messages Batch", "description": "Copy one bounded legacy Kuzu Message page into SQLite.", "operationId": "copy_thread_messages_batch_content_store_thread_messages_copy_batch_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 500, "title": "Batch Size" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Copy Thread Messages Batch Content Store Thread Messages Copy Batch Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Cut Over Thread Messages (/docs/api/content-store/thread-messages/cutover/post) ## POST /content-store/thread-messages/cutover **Summary:** Cut Over Thread Messages Make SQLite the runtime owner after verification has marked it ready. ### OpenAPI Operation ```json { "/content-store/thread-messages/cutover": { "post": { "tags": [ "content-store" ], "summary": "Cut Over Thread Messages", "description": "Make SQLite the runtime owner after verification has marked it ready.", "operationId": "cut_over_thread_messages_content_store_thread_messages_cutover_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 500, "title": "Batch Size" } }, { "name": "max_batches", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10000, "minimum": 1, "default": 1000, "title": "Max Batches" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Cut Over Thread Messages Content Store Thread Messages Cutover Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Migrate Thread Message Anchors (/docs/api/content-store/thread-messages/migrate-anchors/post) ## POST /content-store/thread-messages/migrate-anchors **Summary:** Migrate Thread Message Anchors Backfill legacy Memory->Message links into SQLite content anchors. ### OpenAPI Operation ```json { "/content-store/thread-messages/migrate-anchors": { "post": { "tags": [ "content-store" ], "summary": "Migrate Thread Message Anchors", "description": "Backfill legacy Memory->Message links into SQLite content anchors.", "operationId": "migrate_thread_message_anchors_content_store_thread_messages_migrate_anchors_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 500, "title": "Batch Size" } }, { "name": "max_batches", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10000, "minimum": 1, "default": 1000, "title": "Max Batches" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Migrate Thread Message Anchors Content Store Thread Messages Migrate Anchors Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Migrate Thread Messages Through Cutover (/docs/api/content-store/thread-messages/migrate-through-cutover/post) ## POST /content-store/thread-messages/migrate-through-cutover **Summary:** Migrate Thread Messages Through Cutover Run copy, verification, anchor backfill, and non-destructive cutover. ### OpenAPI Operation ```json { "/content-store/thread-messages/migrate-through-cutover": { "post": { "tags": [ "content-store" ], "summary": "Migrate Thread Messages Through Cutover", "description": "Run copy, verification, anchor backfill, and non-destructive cutover.", "operationId": "migrate_thread_messages_through_cutover_content_store_thread_messages_migrate_through_cutover_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 500, "title": "Batch Size" } }, { "name": "max_batches", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10000, "minimum": 1, "default": 1000, "title": "Max Batches" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Migrate Thread Messages Through Cutover Content Store Thread Messages Migrate Through Cutover Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Verify Thread Message Copy (/docs/api/content-store/thread-messages/verify/post) ## POST /content-store/thread-messages/verify **Summary:** Verify Thread Message Copy Verify SQLite contains every legacy message and no orphan thread rows. ### OpenAPI Operation ```json { "/content-store/thread-messages/verify": { "post": { "tags": [ "content-store" ], "summary": "Verify Thread Message Copy", "description": "Verify SQLite contains every legacy message and no orphan thread rows.", "operationId": "verify_thread_message_copy_content_store_thread_messages_verify_post", "parameters": [ { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 500, "title": "Batch Size" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Verify Thread Message Copy Content Store Thread Messages Verify Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Export Data Download (/docs/api/data/export/download/post) ## POST /data/export/download **Summary:** Export Data Download Export data as a downloadable zip file. Streams the zip archive directly to the client. Use this from remote or web clients that cannot write to the server filesystem. ### OpenAPI Operation ```json { "/data/export/download": { "post": { "tags": [ "data-transfer" ], "operationId": "export_data_download_data_export_download_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataExportDownloadRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} }, "application/zip": { "schema": { "type": "string" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "summary": "Export Data Download", "description": "Export data as a downloadable zip file.\n\nStreams the zip archive directly to the client. Use this from remote\nor web clients that cannot write to the server filesystem." } } } ``` # Import Data Upload (/docs/api/data/import/upload/post) ## POST /data/import/upload **Summary:** Import Data Upload Import data from an uploaded zip file. Accepts a multipart file upload and runs the import in the background. Poll `/data/import/status/{job_id}` to check progress. Use this from remote or web clients that cannot access the server filesystem. ### OpenAPI Operation ```json { "/data/import/upload": { "post": { "tags": [ "data-transfer" ], "operationId": "import_data_upload_data_import_upload_post", "requestBody": { "content": { "multipart/form-data": { "schema": { "type": "object", "title": "Body_import_data_upload_data_import_upload_post", "description": "Multipart body for POST /data/import/upload.", "required": [ "file" ], "properties": { "file": { "type": "string", "contentMediaType": "application/octet-stream" }, "include_communities": { "type": "boolean", "default": true }, "include_edges": { "type": "boolean", "default": true }, "include_entities": { "type": "boolean", "default": true }, "include_feed_events": { "type": "boolean", "description": "Include durable Timeline history from feed_events/*.jsonl.", "default": true }, "include_labels": { "type": "boolean", "default": true }, "include_memories": { "type": "boolean", "default": true }, "include_messages": { "type": "boolean", "default": true }, "include_skills": { "type": "boolean", "default": true }, "include_source_files": { "type": "boolean", "default": true }, "include_sources": { "type": "boolean", "default": true }, "include_threads": { "type": "boolean", "default": true }, "include_working_memory": { "type": "boolean", "default": true }, "include_working_memory_archive": { "type": "boolean", "default": true }, "mode": { "$ref": "#/components/schemas/DataImportMode" } } } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataImportStartResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "summary": "Import Data Upload", "description": "Import data from an uploaded zip file.\n\nAccepts a multipart file upload and runs the import in the background.\nPoll `/data/import/status/{job_id}` to check progress. Use this from\nremote or web clients that cannot access the server filesystem." } } } ``` # Merge entities (/docs/api/entities/entity_id/merge/post) ## POST /entities/{entity_id}/merge **Summary:** Merge entities Atomically move the source Entity's mentions, aliases, labels, topics, and custom relations to the target, then remove the source. Requires an exact source-id confirmation. ### OpenAPI Operation ```json { "/entities/{entity_id}/merge": { "post": { "tags": [ "entities" ], "summary": "Merge entities", "description": "Atomically move the source Entity's mentions, aliases, labels, topics, and custom relations to the target, then remove the source. Requires an exact source-id confirmation.", "operationId": "merge_entity_handler", "parameters": [ { "name": "entity_id", "in": "path", "description": "Source entity id", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EntityMergeRequest" } } }, "required": true }, "responses": { "200": { "description": "Entities merged", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EntityMutationResponse" } } } }, "404": { "description": "Source or target Entity not found" }, "422": { "description": "Source, target, or confirmation is invalid" } } } } } ``` # Get Entity Relationships (/docs/api/entities/entity_id/relationships/get) ## GET /entities/{entity_id}/relationships **Summary:** Get Entity Relationships Get relationships for a specific entity. Returns all connected entities and the memories where this entity is mentioned. Use `depth` to control how many hops to traverse. ### OpenAPI Operation ```json { "/entities/{entity_id}/relationships": { "get": { "tags": [ "entities" ], "summary": "Get Entity Relationships", "description": "Get relationships for a specific entity.\n\nReturns all connected entities and the memories where this entity is mentioned. Use `depth` to control how many hops to traverse.", "operationId": "get_entity_relationships_entities__entity_id__relationships_get", "parameters": [ { "name": "entity_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Entity Id" } }, { "name": "depth", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 3, "minimum": 1, "description": "Traversal depth for relationships", "default": 1, "title": "Depth" }, "description": "Traversal depth for relationships" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "description": "Maximum relationships to return", "default": 50, "title": "Limit" }, "description": "Maximum relationships to return" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EntityRelationshipsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Augmentation Jobs (/docs/api/graph/augmentation/jobs/get) ## GET /graph/augmentation/jobs **Summary:** List Augmentation Jobs List recent augmentation jobs. Optionally filter by status (pending, running, completed, failed). ### OpenAPI Operation ```json { "/graph/augmentation/jobs": { "get": { "tags": [ "graph-analysis" ], "summary": "List Augmentation Jobs", "description": "List recent augmentation jobs.\n\nOptionally filter by status (pending, running, completed, failed).", "operationId": "list_augmentation_jobs_graph_augmentation_jobs_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "default": 10, "title": "Limit" } }, { "name": "status_filter", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status Filter" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AugmentationJobListResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Start Augmentation Job (/docs/api/graph/augmentation/start/post) ## POST /graph/augmentation/start **Summary:** Start Augmentation Job Start a background graph analysis job. Supported job types: - **community_detection** group related entities into topic clusters. - **community_summary_enrichment** write missing topic summaries without rebuilding topic structure. - **pagerank_calculation** calculate entity importance scores. - **undo_community_detection** / **undo_pagerank_calculation** remove previous analysis results. ### OpenAPI Operation ```json { "/graph/augmentation/start": { "post": { "tags": [ "graph-analysis" ], "summary": "Start Augmentation Job", "description": "Start a background graph analysis job.\n\nSupported job types:\n- **community_detection** group related entities into topic clusters.\n- **community_summary_enrichment** write missing topic summaries without\n rebuilding topic structure.\n- **pagerank_calculation** calculate entity importance scores.\n- **undo_community_detection** / **undo_pagerank_calculation** remove previous analysis results.", "operationId": "start_augmentation_job_graph_augmentation_start_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AugmentationStartRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AugmentationJobStartResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Augmentation State (/docs/api/graph/augmentation/state/get) ## GET /graph/augmentation/state **Summary:** Get Augmentation State Get the current graph augmentation state. Returns information about which augmentations are currently applied, their parameters, and the last augmentation timestamp. ### OpenAPI Operation ```json { "/graph/augmentation/state": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Augmentation State", "description": "Get the current graph augmentation state.\n\nReturns information about which augmentations are currently applied,\ntheir parameters, and the last augmentation timestamp.", "operationId": "get_augmentation_state_graph_augmentation_state_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AugmentationStateModel" } } } } } } } } ``` # Get Community Members (/docs/api/graph/community-members/community_id/get) ## GET /graph/community-members/{community_id} **Summary:** Get Community Members Get all nodes belonging to a community. ### OpenAPI Operation ```json { "/graph/community-members/{community_id}": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Community Members", "description": "Get all nodes belonging to a community.", "operationId": "get_community_members_graph_community_members__community_id__get", "parameters": [ { "name": "community_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Community Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Expand Neighbors (/docs/api/graph/expand/node_id/get) ## GET /graph/expand/{node_id} **Summary:** Expand Neighbors Expand neighbors of a specific node to get connected nodes and edges with depth-based traversal. ### OpenAPI Operation ```json { "/graph/expand/{node_id}": { "get": { "tags": [ "graph-analysis" ], "summary": "Expand Neighbors", "description": "Expand neighbors of a specific node to get connected nodes and edges with depth-based traversal.", "operationId": "expand_neighbors_graph_expand__node_id__get", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } }, { "name": "depth", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5, "minimum": 1, "description": "Expansion depth", "default": 1, "title": "Depth" }, "description": "Expansion depth" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "description": "Maximum neighbors to return", "default": 50, "title": "Limit" }, "description": "Maximum neighbors to return" }, { "name": "include_metadata", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include metadata in results", "default": true, "title": "Include Metadata" }, "description": "Include metadata in results" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional memory space lens for the graph", "title": "Space Id" }, "description": "Optional memory space lens for the graph" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExpandNeighborsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Live Preview Neighbors (/docs/api/graph/live-preview/node_id/get) ## GET /graph/live-preview/{node_id} **Summary:** Get Live Preview Neighbors Get a compact 1-hop neighborhood for feed/live preview surfaces. Unlike `expand_neighbors`, this path intentionally avoids path materialization and returns only direct neighbor rows plus connecting edges. ### OpenAPI Operation ```json { "/graph/live-preview/{node_id}": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Live Preview Neighbors", "description": "Get a compact 1-hop neighborhood for feed/live preview surfaces.\n\nUnlike `expand_neighbors`, this path intentionally avoids path\nmaterialization and returns only direct neighbor rows plus connecting edges.", "operationId": "get_live_preview_neighbors_graph_live_preview__node_id__get", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 50, "minimum": 1, "description": "Maximum direct neighbors to return", "default": 20, "title": "Limit" }, "description": "Maximum direct neighbors to return" }, { "name": "include_metadata", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include metadata in results", "default": true, "title": "Include Metadata" }, "description": "Include metadata in results" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional memory space lens for the graph", "title": "Space Id" }, "description": "Optional memory space lens for the graph" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExpandNeighborsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Node Details (/docs/api/graph/node-details/node_id/get) ## GET /graph/node-details/{node_id} **Summary:** Get Node Details Lazy-load full node details (properties, neighbors). ### OpenAPI Operation ```json { "/graph/node-details/{node_id}": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Node Details", "description": "Lazy-load full node details (properties, neighbors).", "operationId": "get_node_details_graph_node_details__node_id__get", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Bulk Delete Memories (/docs/api/memories/bulk/delete/post) ## POST /memories/bulk/delete **Summary:** Bulk Delete Memories Delete a bounded memory selection inside one source space. ### OpenAPI Operation ```json { "/memories/bulk/delete": { "post": { "tags": [ "memories" ], "summary": "Bulk Delete Memories", "description": "Delete a bounded memory selection inside one source space.", "operationId": "bulk_delete_memories_memories_bulk_delete_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkDeleteMemoriesRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkDeleteMemoriesResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Bulk Move Memories (/docs/api/memories/bulk/move/post) ## POST /memories/bulk/move **Summary:** Bulk Move Memories Move a bounded selection of memories into another space. ### OpenAPI Operation ```json { "/memories/bulk/move": { "post": { "tags": [ "memories" ], "summary": "Bulk Move Memories", "description": "Move a bounded selection of memories into another space.", "operationId": "bulk_move_memories_memories_bulk_move_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMoveMemoriesRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMoveMemoriesResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Thread Distillation Batch (/docs/api/memories/distill/batch-plan/post) ## POST /memories/distill/batch-plan **Summary:** Plan Thread Distillation Batch Build a bounded, read-only plan for bulk thread distillation. ### OpenAPI Operation ```json { "/memories/distill/batch-plan": { "post": { "tags": [ "distillation" ], "summary": "Plan Thread Distillation Batch", "description": "Build a bounded, read-only plan for bulk thread distillation.", "operationId": "plan_thread_distillation_batch_memories_distill_batch_plan_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadDistillationBatchPlanRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadDistillationBatchPlanResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Distillation Plan (/docs/api/memories/distill/plan/post) ## POST /memories/distill/plan **Summary:** Get Distillation Plan Decide whether this thread should use direct or background distillation. ### OpenAPI Operation ```json { "/memories/distill/plan": { "post": { "tags": [ "distillation" ], "summary": "Get Distillation Plan", "description": "Decide whether this thread should use direct or background distillation.", "operationId": "get_distillation_plan_memories_distill_plan_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DistillationRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DistillationPlanResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Distillation (/docs/api/memories/distill/preview/post) ## POST /memories/distill/preview **Summary:** Preview Distillation Preview what memories would be created from a thread. ### OpenAPI Operation ```json { "/memories/distill/preview": { "post": { "tags": [ "distillation" ], "summary": "Preview Distillation", "description": "Preview what memories would be created from a thread.", "operationId": "preview_distillation_memories_distill_preview_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DistillationRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DistillationPreviewResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Schedule Distillation (/docs/api/memories/distill/schedule/post) ## POST /memories/distill/schedule **Summary:** Schedule Distillation Schedule agent-backed thread distillation for a large or deferred thread. ### OpenAPI Operation ```json { "/memories/distill/schedule": { "post": { "tags": [ "distillation" ], "summary": "Schedule Distillation", "description": "Schedule agent-backed thread distillation for a large or deferred thread.", "operationId": "schedule_distillation_memories_distill_schedule_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DistillationScheduleRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DistillationScheduleResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Triage Conversation (/docs/api/memories/distill/triage/post) ## POST /memories/distill/triage **Summary:** Triage Conversation Quick check: is this conversation worth saving? ### OpenAPI Operation ```json { "/memories/distill/triage": { "post": { "tags": [ "distillation" ], "summary": "Triage Conversation", "description": "Quick check: is this conversation worth saving?", "operationId": "triage_conversation_memories_distill_triage_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TriageRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Triage Conversation Memories Distill Triage Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Memory Kg Extraction Content (/docs/api/memories/extract-kg/preview-content/post) ## POST /memories/extract-kg/preview-content **Summary:** Preview Memory Kg Extraction Content Preview KG extraction for explicit content without writing a Memory. ### OpenAPI Operation ```json { "/memories/extract-kg/preview-content": { "post": { "tags": [ "memories" ], "summary": "Preview Memory Kg Extraction Content", "description": "Preview KG extraction for explicit content without writing a Memory.", "operationId": "preview_memory_kg_extraction_content_memories_extract_kg_preview_content_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryKGContentExtractionRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryKGExtractionResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Archive Memory (/docs/api/memories/memory_id/archive/post) ## POST /memories/{memory_id}/archive **Summary:** Archive Memory Hide a memory from everyday recall while keeping it explicitly readable. ### OpenAPI Operation ```json { "/memories/{memory_id}/archive": { "post": { "tags": [ "memories" ], "summary": "Archive Memory", "description": "Hide a memory from everyday recall while keeping it explicitly readable.", "operationId": "archive_memory_memories__memory_id__archive_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryStateRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Archive Memory Memories Memory Id Archive Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Deprecate Memory (/docs/api/memories/memory_id/deprecate/post) ## POST /memories/{memory_id}/deprecate **Summary:** Deprecate Memory Mark a memory as deprecated while preserving it for graph history. ### OpenAPI Operation ```json { "/memories/{memory_id}/deprecate": { "post": { "tags": [ "memories" ], "summary": "Deprecate Memory", "description": "Mark a memory as deprecated while preserving it for graph history.", "operationId": "deprecate_memory_memories__memory_id__deprecate_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeprecateMemoryRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Deprecate Memory Memories Memory Id Deprecate Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Export Memory (/docs/api/memories/memory_id/export/get) ## GET /memories/{memory_id}/export **Summary:** Export Memory Export a memory in various formats. ### OpenAPI Operation ```json { "/memories/{memory_id}/export": { "get": { "tags": [ "memories" ], "summary": "Export Memory", "description": "Export a memory in various formats.", "operationId": "export_memory_memories__memory_id__export_get", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } }, { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "description": "Export format: json, markdown, html", "default": "json", "title": "Format" }, "description": "Export format: json, markdown, html" }, { "name": "include_metadata", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include memory metadata", "default": true, "title": "Include Metadata" }, "description": "Include memory metadata" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Toggle Memory Favorite (/docs/api/memories/memory_id/favorite/post) ## POST /memories/{memory_id}/favorite **Summary:** Toggle Memory Favorite Toggle memory favorite status. ### OpenAPI Operation ```json { "/memories/{memory_id}/favorite": { "post": { "tags": [ "memories" ], "summary": "Toggle Memory Favorite", "description": "Toggle memory favorite status.", "operationId": "toggle_memory_favorite_memories__memory_id__favorite_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } }, { "name": "is_favorite", "in": "query", "required": true, "schema": { "type": "boolean", "description": "Set favorite status", "title": "Is Favorite" }, "description": "Set favorite status" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Forget Memory (/docs/api/memories/memory_id/forget/post) ## POST /memories/{memory_id}/forget **Summary:** Forget Memory Remove a memory from recall and explicit by-id reads without hard-deleting graph rows. ### OpenAPI Operation ```json { "/memories/{memory_id}/forget": { "post": { "tags": [ "memories" ], "summary": "Forget Memory", "description": "Remove a memory from recall and explicit by-id reads without hard-deleting graph rows.", "operationId": "forget_memory_memories__memory_id__forget_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryStateRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Forget Memory Memories Memory Id Forget Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Memory Labels (/docs/api/memories/memory_id/labels/get) ## GET /memories/{memory_id}/labels **Summary:** Get Memory Labels Get labels assigned to a memory. ### OpenAPI Operation ```json { "/memories/{memory_id}/labels": { "get": { "tags": [ "memories" ], "summary": "Get Memory Labels", "description": "Get labels assigned to a memory.", "operationId": "get_memory_labels_memories__memory_id__labels_get", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Memory Relations (/docs/api/memories/memory_id/relations/get) ## GET /memories/{memory_id}/relations **Summary:** List Memory Relations List semantic relations around a memory. ### OpenAPI Operation ```json { "/memories/{memory_id}/relations": { "get": { "tags": [ "memories" ], "summary": "List Memory Relations", "description": "List semantic relations around a memory.", "operationId": "list_memory_relations_memories__memory_id__relations_get", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } }, { "name": "direction", "in": "query", "required": false, "schema": { "enum": [ "out", "in", "both" ], "type": "string", "default": "both", "title": "Direction" } }, { "name": "types", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Comma-separated relation_type filter", "title": "Types" }, "description": "Comma-separated relation_type filter" }, { "name": "status", "in": "query", "required": false, "schema": { "type": "string", "description": "Comma-separated status filter, default active", "default": "active", "title": "Status" }, "description": "Comma-separated status filter, default active" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "default": 50, "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Offset" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Space Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationListResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Create Memory Relation (/docs/api/memories/memory_id/relations/post) ## POST /memories/{memory_id}/relations **Summary:** Create Memory Relation Create or update a semantic relation from one memory to another. ### OpenAPI Operation ```json { "/memories/{memory_id}/relations": { "post": { "tags": [ "memories" ], "summary": "Create Memory Relation", "description": "Create or update a semantic relation from one memory to another.", "operationId": "create_memory_relation_memories__memory_id__relations_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationCreateRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationPublic" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Supersede Memory (/docs/api/memories/memory_id/supersede/post) ## POST /memories/{memory_id}/supersede **Summary:** Supersede Memory Mark a memory as replaced by a newer memory. ### OpenAPI Operation ```json { "/memories/{memory_id}/supersede": { "post": { "tags": [ "memories" ], "summary": "Supersede Memory", "description": "Mark a memory as replaced by a newer memory.", "operationId": "supersede_memory_memories__memory_id__supersede_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupersedeMemoryRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Supersede Memory Memories Memory Id Supersede Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Reindex Status (/docs/api/memories/reindex/status/get) ## GET /memories/reindex/status **Summary:** Get Reindex Status Get status of memories needing reindex. ### OpenAPI Operation ```json { "/memories/reindex/status": { "get": { "tags": [ "memories" ], "summary": "Get Reindex Status", "description": "Get status of memories needing reindex.", "operationId": "get_reindex_status_memories_reindex_status_get", "parameters": [ { "name": "include_ids", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include all memory IDs needing reindex", "default": false, "title": "Include Ids" }, "description": "Include all memory IDs needing reindex" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReindexStatusResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Delete Memory Relation (/docs/api/memories/relations/relation_id/delete) ## DELETE /memories/relations/{relation_id} **Summary:** Delete Memory Relation Soft-delete a semantic memory relation. ### OpenAPI Operation ```json { "/memories/relations/{relation_id}": { "delete": { "tags": [ "memories" ], "summary": "Delete Memory Relation", "description": "Soft-delete a semantic memory relation.", "operationId": "delete_memory_relation_memories_relations__relation_id__delete", "parameters": [ { "name": "relation_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Relation Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationPublic" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Memory Relation (/docs/api/memories/relations/relation_id/patch) ## PATCH /memories/relations/{relation_id} **Summary:** Update Memory Relation Update a semantic memory relation. ### OpenAPI Operation ```json { "/memories/relations/{relation_id}": { "patch": { "tags": [ "memories" ], "summary": "Update Memory Relation", "description": "Update a semantic memory relation.", "operationId": "update_memory_relation_memories_relations__relation_id__patch", "parameters": [ { "name": "relation_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Relation Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationUpdateRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationPublic" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Install Bge M3 (/docs/api/models/bge-m3/install/post) ## POST /models/bge-m3/install **Summary:** Install Bge M3 Download and install the search embedding model. The right model for your platform is selected automatically. When the response includes `reindex_required=true`, run `/search-index/reindex` to refresh existing searchable content. ### OpenAPI Operation ```json { "/models/bge-m3/install": { "post": { "tags": [ "models" ], "summary": "Install Bge M3", "description": "Download and install the search embedding model.\n\nThe right model for your platform is selected automatically. When the\nresponse includes `reindex_required=true`, run `/search-index/reindex` to\nrefresh existing searchable content.", "operationId": "install_bge_m3_models_bge_m3_install_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BGEM3InstallRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BGEM3InstallResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Bge M3 Status (/docs/api/models/bge-m3/status/get) ## GET /models/bge-m3/status **Summary:** Get Bge M3 Status Check the status of the search embedding model. The embedding model powers hybrid search (combining keyword and semantic matching). The specific model is selected automatically based on your platform for best performance. ### OpenAPI Operation ```json { "/models/bge-m3/status": { "get": { "tags": [ "models" ], "summary": "Get Bge M3 Status", "description": "Check the status of the search embedding model.\n\nThe embedding model powers hybrid search (combining keyword and semantic matching). The specific model is selected automatically based on your platform for best performance.", "operationId": "get_bge_m3_status_models_bge_m3_status_get", "parameters": [ { "name": "full_verify", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Full Verify" } }, { "name": "force_refresh", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Force Refresh" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BGEM3StatusResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Unload Model (/docs/api/models/unload/model_type/post) ## POST /models/unload/{model_type} **Summary:** Unload Model Manually unload a model from memory. The model will reload automatically on next use. ### OpenAPI Operation ```json { "/models/unload/{model_type}": { "post": { "tags": [ "models" ], "summary": "Unload Model", "description": "Manually unload a model from memory.\n\nThe model will reload automatically on next use.", "operationId": "unload_model_models_unload__model_type__post", "parameters": [ { "name": "model_type", "in": "path", "required": true, "schema": { "enum": [ "embedding", "llm" ], "type": "string", "title": "Model Type" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ModelUnloadResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Search Index Reindex Status (/docs/api/search-index/reindex/status/get) ## GET /search-index/reindex/status **Summary:** Get Search Index Reindex Status Get the current or last-known full search rebuild runtime state. ### OpenAPI Operation ```json { "/search-index/reindex/status": { "get": { "tags": [ "memories" ], "summary": "Get Search Index Reindex Status", "description": "Get the current or last-known full search rebuild runtime state.", "operationId": "get_search_index_reindex_status_search_index_reindex_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchIndexReindexRuntimeStatusResponse" } } } } } } } } ``` # Delete Agent Profile (/docs/api/settings/agent-profiles/agent_id/delete) ## DELETE /settings/agent-profiles/{agent_id} **Summary:** Delete Agent Profile Delete a named agent identity. ### OpenAPI Operation ```json { "/settings/agent-profiles/{agent_id}": { "delete": { "tags": [ "settings", "settings" ], "summary": "Delete Agent Profile", "description": "Delete a named agent identity.", "operationId": "delete_agent_profile_settings_agent_profiles__agent_id__delete", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentProfilesResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Agent Profile (/docs/api/settings/agent-profiles/agent_id/put) ## PUT /settings/agent-profiles/{agent_id} **Summary:** Update Agent Profile Update an existing named agent identity. ### OpenAPI Operation ```json { "/settings/agent-profiles/{agent_id}": { "put": { "tags": [ "settings", "settings" ], "summary": "Update Agent Profile", "description": "Update an existing named agent identity.", "operationId": "update_agent_profile_settings_agent_profiles__agent_id__put", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentProfilePayload" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentProfileResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview a settings restore (/docs/api/settings/restore/preview/post) ## POST /settings/restore/preview **Summary:** Preview a settings restore Validate a settings artifact and report its portable sections before any write. ### OpenAPI Operation ```json { "/settings/restore/preview": { "post": { "tags": [ "settings" ], "summary": "Preview a settings restore", "description": "Validate a settings artifact and report its portable sections before any write.", "operationId": "preview_settings_restore_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SettingsBackupArtifact" } } }, "required": true }, "responses": { "200": { "description": "Valid restore preview", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SettingsRestorePreview" } } } }, "422": { "description": "Invalid, unsafe, or unsupported settings artifact" } } } } } ``` # Delete Guidance Rule (/docs/api/settings/rules/rule_id/delete) ## DELETE /settings/rules/{rule_id} **Summary:** Delete Guidance Rule Delete an AI Context rule. ### OpenAPI Operation ```json { "/settings/rules/{rule_id}": { "delete": { "tags": [ "settings", "settings" ], "summary": "Delete Guidance Rule", "description": "Delete an AI Context rule.", "operationId": "delete_guidance_rule_settings_rules__rule_id__delete", "parameters": [ { "name": "rule_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Rule Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RulesResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Guidance Rule (/docs/api/settings/rules/rule_id/put) ## PUT /settings/rules/{rule_id} **Summary:** Update Guidance Rule Update an existing AI Context rule. ### OpenAPI Operation ```json { "/settings/rules/{rule_id}": { "put": { "tags": [ "settings", "settings" ], "summary": "Update Guidance Rule", "description": "Update an existing AI Context rule.", "operationId": "update_guidance_rule_settings_rules__rule_id__put", "parameters": [ { "name": "rule_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Rule Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GuidanceRulePayload" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GuidanceRuleResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Curator Dry Run (/docs/api/skills/curator/dry-run/get) ## GET /skills/curator/dry-run **Summary:** Curator Dry Run Preview the scheduled skill-curator pass without staging proposals. This runs the same read-only detection surfaces as the scheduled curator: rot selection for bounded hardening and staleness detection from superseded evidence. It does not run hardening, stage pending versions, write pending enrichments, emit feed events, or queue background work. ### OpenAPI Operation ```json { "/skills/curator/dry-run": { "get": { "tags": [ "skills", "skills" ], "summary": "Curator Dry Run", "description": "Preview the scheduled skill-curator pass without staging proposals.\n\nThis runs the same read-only detection surfaces as the scheduled curator:\nrot selection for bounded hardening and staleness detection from superseded\nevidence. It does not run hardening, stage pending versions, write pending\nenrichments, emit feed events, or queue background work.", "operationId": "curator_dry_run_skills_curator_dry_run_get", "parameters": [ { "name": "budget", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 20, "minimum": 0, "default": 3, "title": "Budget" } }, { "name": "include_merges", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Include Merges" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Curator Dry Run Skills Curator Dry Run Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Curator Proposals (/docs/api/skills/curator/proposals/get) ## GET /skills/curator/proposals **Summary:** Curator Proposals What the curator would propose right now: rotting skills (failing in real use, no fix staged) and near-duplicate pairs worth merging. ### OpenAPI Operation ```json { "/skills/curator/proposals": { "get": { "tags": [ "skills", "skills" ], "summary": "Curator Proposals", "description": "What the curator would propose right now: rotting skills (failing in real\nuse, no fix staged) and near-duplicate pairs worth merging.", "operationId": "curator_proposals_skills_curator_proposals_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Curator Proposals Skills Curator Proposals Get" } } } } } } } } ``` # Curator Run (/docs/api/skills/curator/run/post) ## POST /skills/curator/run **Summary:** Curator Run Run one budgeted curator cycle now: stage proven refines for the worst rotting skills. The work happens in the background (model-heavy); the proposals appear as pending updates the user reviews. Manual trigger today; the scheduler calls this on a cadence later (default-off for managed tiers). ### OpenAPI Operation ```json { "/skills/curator/run": { "post": { "tags": [ "skills", "skills" ], "summary": "Curator Run", "description": "Run one budgeted curator cycle now: stage proven refines for the worst\nrotting skills. The work happens in the background (model-heavy); the proposals\nappear as pending updates the user reviews. Manual trigger today; the scheduler\ncalls this on a cadence later (default-off for managed tiers).", "operationId": "curator_run_skills_curator_run_post", "parameters": [ { "name": "budget", "in": "query", "required": false, "schema": { "type": "integer", "default": 3, "title": "Budget" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Curator Run Skills Curator Run Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Unregister Skill Host (/docs/api/skills/registration/host/delete) ## DELETE /skills/registration/{host} **Summary:** Unregister Skill Host Remove our entries for one host. Leaves foreign files/links untouched. ### OpenAPI Operation ```json { "/skills/registration/{host}": { "delete": { "tags": [ "skills", "skills", "skills" ], "summary": "Unregister Skill Host", "description": "Remove our entries for one host. Leaves foreign files/links untouched.", "operationId": "unregister_skill_host_skills_registration__host__delete", "parameters": [ { "name": "host", "in": "path", "required": true, "schema": { "type": "string", "title": "Host" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Unregister Skill Host Skills Registration Host Delete" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Register Skill Host (/docs/api/skills/registration/host/post) ## POST /skills/registration/{host} **Summary:** Register Skill Host Register one host, or ``all`` for every detected host. Idempotent. ### OpenAPI Operation ```json { "/skills/registration/{host}": { "post": { "tags": [ "skills", "skills", "skills" ], "summary": "Register Skill Host", "description": "Register one host, or ``all`` for every detected host. Idempotent.", "operationId": "register_skill_host_skills_registration__host__post", "parameters": [ { "name": "host", "in": "path", "required": true, "schema": { "type": "string", "title": "Host" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Register Skill Host Skills Registration Host Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Activate Skill (/docs/api/skills/skill_id/activate/post) ## POST /skills/{skill_id}/activate **Summary:** Activate Skill Publish a reviewed draft skill to active (the consumable surface). A manual publish: the user reviewed the SKILL.md and chose to publish. The moment it goes live we fire a background verification (the entry gate), so an active skill earns its trust verdict automatically rather than waiting for a manual eval click — that is what makes the home a Verified Library. ### OpenAPI Operation ```json { "/skills/{skill_id}/activate": { "post": { "tags": [ "skills", "skills" ], "summary": "Activate Skill", "description": "Publish a reviewed draft skill to active (the consumable surface).\n\nA manual publish: the user reviewed the SKILL.md and chose to publish. The\nmoment it goes live we fire a background verification (the entry gate), so an\nactive skill earns its trust verdict automatically rather than waiting for a\nmanual eval click — that is what makes the home a Verified Library.", "operationId": "activate_skill_skills__skill_id__activate_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Activate Skill Skills Skill Id Activate Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Apply Skill Enrichment (/docs/api/skills/skill_id/apply-enrichment/post) ## POST /skills/{skill_id}/apply-enrichment **Summary:** Apply Skill Enrichment Apply the skill's pending enrichments: link the fresh evidence the background agent found, then recompile so the body incorporates it. Clears the applied enrichments. The recompile runs async; the body updates shortly. Looks up by id directly; cross-space when space_id is omitted. ### OpenAPI Operation ```json { "/skills/{skill_id}/apply-enrichment": { "post": { "tags": [ "skills", "skills" ], "summary": "Apply Skill Enrichment", "description": "Apply the skill's pending enrichments: link the fresh evidence the\nbackground agent found, then recompile so the body incorporates it. Clears\nthe applied enrichments. The recompile runs async; the body updates shortly.\n\nLooks up by id directly; cross-space when space_id is omitted.", "operationId": "apply_skill_enrichment_skills__skill_id__apply_enrichment_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Apply Skill Enrichment Skills Skill Id Apply Enrichment Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Apply Skill Version (/docs/api/skills/skill_id/apply-version/post) ## POST /skills/{skill_id}/apply-version **Summary:** Apply Skill Version Commit a proposed new version (the evolve half of the human-approval gate). ``ProposeSkillVersion`` only records ``metadata.pending_version`` (body + rationale); the live bundle is never touched until a human reviews and calls this. Applying swaps the SKILL.md body, preserves the existing assets, bumps the version, and clears the proposal. Stage is unchanged: applying to an active skill republishes it live (the call itself is the approval); a draft/stale skill still needs a separate ``activate``. Reject-on-drift: if the live bundle changed since the proposal was made (``base_content_hash`` no longer matches), the proposal is stale — 409, so the agent re-proposes against the current body rather than silently clobbering an intervening recompile. Filesystem and graph are not transactional, so a failed graph write restores the prior bundle. ### OpenAPI Operation ```json { "/skills/{skill_id}/apply-version": { "post": { "tags": [ "skills", "skills" ], "summary": "Apply Skill Version", "description": "Commit a proposed new version (the evolve half of the human-approval gate).\n\n``ProposeSkillVersion`` only records ``metadata.pending_version`` (body +\nrationale); the live bundle is never touched until a human reviews and calls\nthis. Applying swaps the SKILL.md body, preserves the existing assets, bumps\nthe version, and clears the proposal. Stage is unchanged: applying to an\nactive skill republishes it live (the call itself is the approval); a\ndraft/stale skill still needs a separate ``activate``.\n\nReject-on-drift: if the live bundle changed since the proposal was made\n(``base_content_hash`` no longer matches), the proposal is stale — 409, so\nthe agent re-proposes against the current body rather than silently clobbering\nan intervening recompile. Filesystem and graph are not transactional, so a\nfailed graph write restores the prior bundle.", "operationId": "apply_skill_version_skills__skill_id__apply_version_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Apply Skill Version Skills Skill Id Apply Version Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Archive Skill (/docs/api/skills/skill_id/archive/post) ## POST /skills/{skill_id}/archive **Summary:** Archive Skill Archive a compiled skill (recoverable; the bundle is retained). ### OpenAPI Operation ```json { "/skills/{skill_id}/archive": { "post": { "tags": [ "skills", "skills" ], "summary": "Archive Skill", "description": "Archive a compiled skill (recoverable; the bundle is retained).", "operationId": "archive_skill_skills__skill_id__archive_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Archive Skill Skills Skill Id Archive Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Deactivate Skill (/docs/api/skills/skill_id/deactivate/post) ## POST /skills/{skill_id}/deactivate **Summary:** Deactivate Skill Turn an active skill OFF: keep it (body, versions, outcomes) but stop your agents using it. The non-destructive half of the on/off toggle. We move active -> draft (the compiled-but-not-live stage) and un-materialize from host skill dirs, so agents stop seeing it. Nothing is lost: turning it back on is the existing ``activate`` (draft -> active), instant and lossless. This is deliberately NOT ``archive`` (a removal end-state) and NOT a revert to a suggestion (that would discard the compiled bundle and its history). A toggle must be reversible; discarding is a separate, explicit gesture. Scoped by id; the active set is global, so the materializer reconciles all hosts. ### OpenAPI Operation ```json { "/skills/{skill_id}/deactivate": { "post": { "tags": [ "skills", "skills" ], "summary": "Deactivate Skill", "description": "Turn an active skill OFF: keep it (body, versions, outcomes) but stop your\nagents using it.\n\nThe non-destructive half of the on/off toggle. We move active -> draft (the\ncompiled-but-not-live stage) and un-materialize from host skill dirs, so agents\nstop seeing it. Nothing is lost: turning it back on is the existing ``activate``\n(draft -> active), instant and lossless. This is deliberately NOT ``archive``\n(a removal end-state) and NOT a revert to a suggestion (that would discard the\ncompiled bundle and its history). A toggle must be reversible; discarding is a\nseparate, explicit gesture.\n\nScoped by id; the active set is global, so the materializer reconciles all hosts.", "operationId": "deactivate_skill_skills__skill_id__deactivate_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Deactivate Skill Skills Skill Id Deactivate Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Dismiss Skill (/docs/api/skills/skill_id/dismiss/post) ## POST /skills/{skill_id}/dismiss **Summary:** Dismiss Skill Dismiss a candidate (stamps rejected_at via the repository), recording WHY. The reason + resurface rule are persisted in metadata so the background reviewer doesn't keep re-suggesting the same bad idea (audit §3 P0). A default is applied when the caller passes none. By-id-direct; cross-space. ### OpenAPI Operation ```json { "/skills/{skill_id}/dismiss": { "post": { "tags": [ "skills", "skills" ], "summary": "Dismiss Skill", "description": "Dismiss a candidate (stamps rejected_at via the repository), recording WHY.\n\nThe reason + resurface rule are persisted in metadata so the background\nreviewer doesn't keep re-suggesting the same bad idea (audit §3 P0). A default\nis applied when the caller passes none. By-id-direct; cross-space.", "operationId": "dismiss_skill_skills__skill_id__dismiss_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/DismissSkillRequest" }, { "type": "null" } ], "title": "Req" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Dismiss Skill Skills Skill Id Dismiss Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Dismiss Skill Enrichment (/docs/api/skills/skill_id/dismiss-enrichment/post) ## POST /skills/{skill_id}/dismiss-enrichment **Summary:** Dismiss Skill Enrichment Dismiss the skill's pending enrichments without applying them (the evidence stays in the graph; it just won't strengthen this skill). Looks up by id. ### OpenAPI Operation ```json { "/skills/{skill_id}/dismiss-enrichment": { "post": { "tags": [ "skills", "skills" ], "summary": "Dismiss Skill Enrichment", "description": "Dismiss the skill's pending enrichments without applying them (the evidence\nstays in the graph; it just won't strengthen this skill). Looks up by id.", "operationId": "dismiss_skill_enrichment_skills__skill_id__dismiss_enrichment_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Dismiss Skill Enrichment Skills Skill Id Dismiss Enrichment Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Duplicate Of (/docs/api/skills/skill_id/duplicate-of/get) ## GET /skills/{skill_id}/duplicate-of **Summary:** Skill Duplicate Of The active skill this one looks like a duplicate of, or null. Computed lazily, OFF the detail hot path: it needs embeddings (which can cold-start slowly), so the UI fetches it separately after opening a skill — the same non-blocking pattern as the benchmark — keeping skill-open instant. For a SUGGESTION the UI offers "strengthen that one instead"; for an OFF compiled skill (draft/stale) a read-only "you may already have this" hint + merge. Active skills ARE the catalog, so they're never checked against themselves. Best-effort (no embeddings -> null). By-id-direct; cross-space. ### OpenAPI Operation ```json { "/skills/{skill_id}/duplicate-of": { "get": { "tags": [ "skills", "skills" ], "summary": "Skill Duplicate Of", "description": "The active skill this one looks like a duplicate of, or null.\n\nComputed lazily, OFF the detail hot path: it needs embeddings (which can\ncold-start slowly), so the UI fetches it separately after opening a skill — the\nsame non-blocking pattern as the benchmark — keeping skill-open instant. For a\nSUGGESTION the UI offers \"strengthen that one instead\"; for an OFF compiled skill\n(draft/stale) a read-only \"you may already have this\" hint + merge. Active skills\nARE the catalog, so they're never checked against themselves. Best-effort\n(no embeddings -> null). By-id-direct; cross-space.", "operationId": "skill_duplicate_of_skills__skill_id__duplicate_of_get", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Skill Duplicate Of Skills Skill Id Duplicate Of Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Edit Skill File (/docs/api/skills/skill_id/edit-file/post) ## POST /skills/{skill_id}/edit-file **Summary:** Edit Skill File Write one of a skill's own asset files (scripts/references) directly — the answer to "4 files but I can only edit SKILL.md". Asset files are opt-gated, so the edit commits straight away (no proof gate, unlike edit-body), bumps the version, and re-syncs tools. SKILL.md/evals refused. By id; cross-space. ### OpenAPI Operation ```json { "/skills/{skill_id}/edit-file": { "post": { "tags": [ "skills", "skills" ], "summary": "Edit Skill File", "description": "Write one of a skill's own asset files (scripts/references) directly — the\nanswer to \"4 files but I can only edit SKILL.md\". Asset files are opt-gated, so\nthe edit commits straight away (no proof gate, unlike edit-body), bumps the\nversion, and re-syncs tools. SKILL.md/evals refused. By id; cross-space.", "operationId": "edit_skill_file_skills__skill_id__edit_file_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillEditFileRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Edit Skill File Skills Skill Id Edit File Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Skill Eval (/docs/api/skills/skill_id/eval/get) ## GET /skills/{skill_id}/eval **Summary:** Get Skill Eval The skill's behavioral benchmark (§16): the cases it's proven on, by status. v1 returns the case inventory; the with/without run verdict is the v2 model-runner. See docs/implementation/SKILL_EVAL_IMPLEMENTATION.md. ### OpenAPI Operation ```json { "/skills/{skill_id}/eval": { "get": { "tags": [ "skills", "skills" ], "summary": "Get Skill Eval", "description": "The skill's behavioral benchmark (§16): the cases it's proven on, by status.\n\nv1 returns the case inventory; the with/without run verdict is the v2\nmodel-runner. See docs/implementation/SKILL_EVAL_IMPLEMENTATION.md.", "operationId": "get_skill_eval_skills__skill_id__eval_get", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Skill Eval Skills Skill Id Eval Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Harden Skill Endpoint (/docs/api/skills/skill_id/harden/post) ## POST /skills/{skill_id}/harden **Summary:** Harden Skill Endpoint Run the autonomous skill-hardening loop once: build/grow the harness, then each round propose -> prove on the held-out slice -> keep ONLY if strictly better (compounding), and stage ONE pending_version for the user's Apply. By-id-direct; cross-space. See docs/design/SKILL_AUTONOMOUS_HARDENING_LOOP.md. ### OpenAPI Operation ```json { "/skills/{skill_id}/harden": { "post": { "tags": [ "skills", "skills" ], "summary": "Harden Skill Endpoint", "description": "Run the autonomous skill-hardening loop once: build/grow the harness, then each\nround propose -> prove on the held-out slice -> keep ONLY if strictly better\n(compounding), and stage ONE pending_version for the user's Apply. By-id-direct;\ncross-space. See docs/design/SKILL_AUTONOMOUS_HARDENING_LOOP.md.", "operationId": "harden_skill_endpoint_skills__skill_id__harden_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } }, { "name": "max_rounds", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 8, "minimum": 1, "default": 4, "title": "Max Rounds" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Harden Skill Endpoint Skills Skill Id Harden Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Merge Into (/docs/api/skills/skill_id/merge-into/post) ## POST /skills/{skill_id}/merge-into **Summary:** Merge Into Merge a compiled skill INTO another, leaving one canonical skill. The generalization of strengthen-instead for two COMPILED skills (the curator's near-duplicate pair, or an off draft overlapping an active one): the absorbed skill's evidence moves onto the kept skill as a pending enrichment (the user reviews + applies it; the kept body is never silently rewritten), and the absorbed skill is ARCHIVED with ``merged_into`` provenance — recoverable, and un-materialized from hosts by the shared transition. Outcomes do NOT transfer (they were measured against a different body); the kept skill records ``merged_from`` for honest provenance. A suggestion still uses strengthen-instead (its end-state is reject, not archive). See docs/design/SKILL_MERGE_PRIMITIVE.md. By-id-direct; cross-space. ### OpenAPI Operation ```json { "/skills/{skill_id}/merge-into": { "post": { "tags": [ "skills", "skills" ], "summary": "Merge Into", "description": "Merge a compiled skill INTO another, leaving one canonical skill.\n\nThe generalization of strengthen-instead for two COMPILED skills (the curator's\nnear-duplicate pair, or an off draft overlapping an active one): the absorbed\nskill's evidence moves onto the kept skill as a pending enrichment (the user\nreviews + applies it; the kept body is never silently rewritten), and the\nabsorbed skill is ARCHIVED with ``merged_into`` provenance — recoverable, and\nun-materialized from hosts by the shared transition. Outcomes do NOT transfer\n(they were measured against a different body); the kept skill records\n``merged_from`` for honest provenance. A suggestion still uses strengthen-instead\n(its end-state is reject, not archive). See docs/design/SKILL_MERGE_PRIMITIVE.md.\nBy-id-direct; cross-space.", "operationId": "merge_into_skills__skill_id__merge_into_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MergeIntoRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Merge Into Skills Skill Id Merge Into Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Report Skill Outcome (/docs/api/skills/skill_id/outcome/post) ## POST /skills/{skill_id}/outcome **Summary:** Report Skill Outcome Record how a skill actually performed in use (G1 Tier 2 feedback). Version-anchored and content-bearing: the structured deviation/missing/failure text is recompile + eval evidence, not a vanity rating. Updates use_count and a current-version success_rate. A real failure also grows the skill's eval (G4), in the background. See SKILL_CRYSTALLIZATION.md §3.8. ### OpenAPI Operation ```json { "/skills/{skill_id}/outcome": { "post": { "tags": [ "skills", "skills" ], "summary": "Report Skill Outcome", "description": "Record how a skill actually performed in use (G1 Tier 2 feedback).\n\nVersion-anchored and content-bearing: the structured deviation/missing/failure\ntext is recompile + eval evidence, not a vanity rating. Updates use_count and a\ncurrent-version success_rate. A real failure also grows the skill's eval (G4),\nin the background. See SKILL_CRYSTALLIZATION.md §3.8.", "operationId": "report_skill_outcome_skills__skill_id__outcome_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillOutcomeRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Report Skill Outcome Skills Skill Id Outcome Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Discard a pending Skill version (/docs/api/skills/skill_id/pending-version/delete) ## DELETE /skills/{skill_id}/pending-version **Summary:** Discard a pending Skill version Remove only the reviewable pending proposal. The live Skill body and version remain unchanged. ### OpenAPI Operation ```json { "/skills/{skill_id}/pending-version": { "delete": { "tags": [ "skills" ], "summary": "Discard a pending Skill version", "description": "Remove only the reviewable pending proposal. The live Skill body and version remain unchanged.", "operationId": "discard_pending_version_handler", "parameters": [ { "name": "skill_id", "in": "path", "description": "Skill id", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Pending version discarded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DiscardPendingVersionResponse" } } } }, "404": { "description": "Skill not found" }, "409": { "description": "The Skill has no pending version" } } } } } ``` # Strengthen Instead (/docs/api/skills/skill_id/strengthen-instead/post) ## POST /skills/{skill_id}/strengthen-instead **Summary:** Strengthen Instead Resolve a duplicate suggestion: move its evidence onto the existing active skill as a pending enrichment, then dismiss the suggestion. The product's one-tap answer to "this is a skill I already have": the evidence is preserved — it strengthens the real skill via the same pending-enrichment path as SuggestSkillEnrichment — instead of being lost to a blunt dismiss. The candidate is a suggestion (``_DISMISSABLE``); the target must be an active skill. By-id-direct; cross-space. ### OpenAPI Operation ```json { "/skills/{skill_id}/strengthen-instead": { "post": { "tags": [ "skills", "skills" ], "summary": "Strengthen Instead", "description": "Resolve a duplicate suggestion: move its evidence onto the existing active\nskill as a pending enrichment, then dismiss the suggestion.\n\nThe product's one-tap answer to \"this is a skill I already have\": the evidence\nis preserved — it strengthens the real skill via the same pending-enrichment\npath as SuggestSkillEnrichment — instead of being lost to a blunt dismiss. The\ncandidate is a suggestion (``_DISMISSABLE``); the target must be an active skill.\nBy-id-direct; cross-space.", "operationId": "strengthen_instead_skills__skill_id__strengthen_instead_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StrengthenInsteadRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Strengthen Instead Skills Skill Id Strengthen Instead Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Ingest Batch (/docs/api/sources/ingest/batch/post) ## POST /sources/ingest/batch **Summary:** Ingest Batch Ingest a batch of files at once. ### OpenAPI Operation ```json { "/sources/ingest/batch": { "post": { "tags": [ "sources" ], "summary": "Ingest Batch", "description": "Ingest a batch of files at once.", "operationId": "ingest_batch_sources_ingest_batch_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchIngestRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchIngestResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Ingest Content (/docs/api/sources/ingest/content/post) ## POST /sources/ingest/content **Summary:** Ingest Content Ingest raw text content (a paste, or a text file the client read) as a Library source. JSON-only so it works in every transport without multipart/file-path plumbing. The text is written to a temp file and run through the same ingest_file pipeline, so it gets the identical Source lifecycle (parse, index, background extraction). Used by Deep Create's 'bring in material'. ### OpenAPI Operation ```json { "/sources/ingest/content": { "post": { "tags": [ "sources" ], "summary": "Ingest Content", "description": "Ingest raw text content (a paste, or a text file the client read) as a Library\nsource. JSON-only so it works in every transport without multipart/file-path\nplumbing. The text is written to a temp file and run through the same ingest_file\npipeline, so it gets the identical Source lifecycle (parse, index, background\nextraction). Used by Deep Create's 'bring in material'.", "operationId": "ingest_content_sources_ingest_content_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IngestContentRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IngestResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Ingest File (/docs/api/sources/ingest/file/post) ## POST /sources/ingest/file **Summary:** Ingest File Ingest a file into the library. ### OpenAPI Operation ```json { "/sources/ingest/file": { "post": { "tags": [ "sources" ], "summary": "Ingest File", "description": "Ingest a file into the library.", "operationId": "ingest_file_sources_ingest_file_post", "requestBody": { "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/Body_ingest_file_sources_ingest_file_post" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IngestResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Ingest File Path (/docs/api/sources/ingest/file-path/post) ## POST /sources/ingest/file-path **Summary:** Ingest File Path Ingest a file by its local path. ### OpenAPI Operation ```json { "/sources/ingest/file-path": { "post": { "tags": [ "sources" ], "summary": "Ingest File Path", "description": "Ingest a file by its local path.", "operationId": "ingest_file_path_sources_ingest_file_path_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IngestFilePathRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IngestResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Ingest Folder Summary (/docs/api/sources/ingest/folder-summary/post) ## POST /sources/ingest/folder-summary **Summary:** Ingest Folder Summary Emit a folder import summary event for remote/web chunked uploads. ### OpenAPI Operation ```json { "/sources/ingest/folder-summary": { "post": { "tags": [ "sources" ], "summary": "Ingest Folder Summary", "description": "Emit a folder import summary event for remote/web chunked uploads.", "operationId": "ingest_folder_summary_sources_ingest_folder_summary_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FolderIngestSummaryRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchIngestResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Ingest Folder Upload (/docs/api/sources/ingest/folder-upload/post) ## POST /sources/ingest/folder-upload **Summary:** Ingest Folder Upload Ingest client-uploaded folder files via multipart. This is the remote/web-safe folder API. The server never reads a client filesystem path; clients upload file bytes and provide folder-relative paths in ``file_manifest``. Space-scoped: writes sources to ``space_id``, defaulting to the canonical default space when omitted. ### OpenAPI Operation ```json { "/sources/ingest/folder-upload": { "post": { "tags": [ "sources" ], "summary": "Ingest Folder Upload", "description": "Ingest client-uploaded folder files via multipart.\n\nThis is the remote/web-safe folder API. The server never reads a client\nfilesystem path; clients upload file bytes and provide folder-relative\npaths in ``file_manifest``.\n\nSpace-scoped: writes sources to ``space_id``, defaulting to the canonical\ndefault space when omitted.", "operationId": "ingest_folder_upload_sources_ingest_folder_upload_post", "requestBody": { "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/Body_ingest_folder_upload_sources_ingest_folder_upload_post" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchIngestResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Ingest Url (/docs/api/sources/ingest/url/post) ## POST /sources/ingest/url **Summary:** Ingest Url Ingest a web page into the library. ### OpenAPI Operation ```json { "/sources/ingest/url": { "post": { "tags": [ "sources" ], "summary": "Ingest Url", "description": "Ingest a web page into the library.", "operationId": "ingest_url_sources_ingest_url_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IngestUrlRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IngestResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Source Content (/docs/api/sources/source_id/content/get) ## GET /sources/{source_id}/content **Summary:** Get Source Content Read the parsed text content of a source. ### OpenAPI Operation ```json { "/sources/{source_id}/content": { "get": { "tags": [ "sources" ], "summary": "Get Source Content", "description": "Read the parsed text content of a source.", "operationId": "get_source_content_sources__source_id__content_get", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "description": "Character offset for pagination", "default": 0, "title": "Offset" }, "description": "Character offset for pagination" }, { "name": "limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 50000, "minimum": 100 }, { "type": "null" } ], "description": "Maximum characters to return. Omit to read the full parsed content.", "title": "Limit" }, "description": "Maximum characters to return. Omit to read the full parsed content." }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SourceContentResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Source Content (/docs/api/sources/source_id/content/put) ## PUT /sources/{source_id}/content **Summary:** Update Source Content Replace the markdown body of an editable source artifact. Used by the Library inline editor for agent-generated artifacts (reports, blog drafts) and any other markdown source where editing in place makes sense. Re-runs chunk + index so search stays fresh. ### OpenAPI Operation ```json { "/sources/{source_id}/content": { "put": { "tags": [ "sources" ], "summary": "Update Source Content", "description": "Replace the markdown body of an editable source artifact.\n\nUsed by the Library inline editor for agent-generated artifacts (reports,\nblog drafts) and any other markdown source where editing in place makes\nsense. Re-runs chunk + index so search stays fresh.", "operationId": "update_source_content_sources__source_id__content_put", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSourceContentRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SourceResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Trigger Source Extraction (/docs/api/sources/source_id/extract/post) ## POST /sources/{source_id}/extract **Summary:** Trigger Source Extraction Queue knowledge extraction for a source. Returns 202 when the extraction task is queued or already queued; 5xx is reserved for genuine rejection. ### OpenAPI Operation ```json { "/sources/{source_id}/extract": { "post": { "tags": [ "sources" ], "summary": "Trigger Source Extraction", "description": "Queue knowledge extraction for a source. Returns 202 when the extraction task is queued or already queued; 5xx is reserved for genuine rejection.", "operationId": "trigger_source_extraction_sources__source_id__extract_post", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "202": { "description": "Extraction queued", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "SourceExtractionQueuedResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } }, "503": { "description": "Knowledge Agent is not running", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "SourceExtractionErrorResponse" } } } } } } } } ``` # Get Source Labels (/docs/api/sources/source_id/labels/get) ## GET /sources/{source_id}/labels **Summary:** Get Source Labels Get labels assigned to a source. ### OpenAPI Operation ```json { "/sources/{source_id}/labels": { "get": { "tags": [ "sources" ], "summary": "Get Source Labels", "description": "Get labels assigned to a source.", "operationId": "get_source_labels_sources__source_id__labels_get", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Source Raw (/docs/api/sources/source_id/raw/get) ## GET /sources/{source_id}/raw **Summary:** Get Source Raw Serve the raw source file for native preview (PDF, DOCX, etc). ### OpenAPI Operation ```json { "/sources/{source_id}/raw": { "get": { "tags": [ "sources" ], "summary": "Get Source Raw", "description": "Serve the raw source file for native preview (PDF, DOCX, etc).", "operationId": "get_source_raw_sources__source_id__raw_get", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "title": "Response Get Source Raw Sources Source Id Raw Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Refetch Source (/docs/api/sources/source_id/refetch/post) ## POST /sources/{source_id}/refetch **Summary:** Refetch Source Re-fetch and re-parse a URL source. ### OpenAPI Operation ```json { "/sources/{source_id}/refetch": { "post": { "tags": [ "sources" ], "summary": "Refetch Source", "description": "Re-fetch and re-parse a URL source.", "operationId": "refetch_source_sources__source_id__refetch_post", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Refetch Source Sources Source Id Refetch Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Merge Spaces (/docs/api/spaces/space_ref/merge/post) ## POST /spaces/{space_ref}/merge **Summary:** Merge Spaces Move Memories, Threads, Library sources, and Working Memory into the target Space, retire the source profile, and preserve its references as target aliases. Apply is rejected when preview reports conflicts. ### OpenAPI Operation ```json { "/spaces/{space_ref}/merge": { "post": { "tags": [ "spaces" ], "summary": "Merge Spaces", "description": "Move Memories, Threads, Library sources, and Working Memory into the target Space, retire the source profile, and preserve its references as target aliases. Apply is rejected when preview reports conflicts.", "operationId": "merge_space_spaces__space_ref__merge_post", "parameters": [ { "name": "space_ref", "in": "path", "required": true, "schema": { "type": "string", "title": "Space Ref" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SpaceMergeRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SpaceMergeResult" } } } }, "409": { "description": "Merge Conflict", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Bulk Delete Threads By Selection (/docs/api/threads/bulk/delete/post) ## POST /threads/bulk/delete **Summary:** Bulk Delete Threads By Selection Delete a bounded thread selection inside one source space. ### OpenAPI Operation ```json { "/threads/bulk/delete": { "post": { "tags": [ "threads" ], "summary": "Bulk Delete Threads By Selection", "description": "Delete a bounded thread selection inside one source space.", "operationId": "bulk_delete_threads_by_selection_threads_bulk_delete_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkDeleteThreadsBySelectionRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkDeleteThreadsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Bulk Move Threads (/docs/api/threads/bulk/move/post) ## POST /threads/bulk/move **Summary:** Bulk Move Threads Move a bounded selection of threads into another space. ### OpenAPI Operation ```json { "/threads/bulk/move": { "post": { "tags": [ "threads" ], "summary": "Bulk Move Threads", "description": "Move a bounded selection of threads into another space.", "operationId": "bulk_move_threads_threads_bulk_move_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMoveThreadsRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMoveThreadsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Discover Conversations (/docs/api/threads/conversations/discover/get) ## GET /threads/conversations/discover **Summary:** Discover Conversations Discover conversation files from AI coding assistants. Scans file system for conversation files from Claude Code, Codex, Cursor, and OpenCode. ### OpenAPI Operation ```json { "/threads/conversations/discover": { "get": { "tags": [ "threads" ], "summary": "Discover Conversations", "description": "Discover conversation files from AI coding assistants.\n\nScans file system for conversation files from Claude Code, Codex, Cursor, and OpenCode.", "operationId": "discover_conversations_threads_conversations_discover_get", "parameters": [ { "name": "source", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by source: claude, codex, cursor, opencode, or None for all", "title": "Source" }, "description": "Filter by source: claude, codex, cursor, opencode, or None for all" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConversationDiscoveryResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Export Conversation Raw (/docs/api/threads/conversations/export-raw/post) ## POST /threads/conversations/export-raw **Summary:** Export Conversation Raw Export a raw conversation file as markdown or JSON without importing. Parses the session file using the same parsers as import, but returns formatted content directly instead of creating a thread. ### OpenAPI Operation ```json { "/threads/conversations/export-raw": { "post": { "tags": [ "threads" ], "summary": "Export Conversation Raw", "description": "Export a raw conversation file as markdown or JSON without importing.\n\nParses the session file using the same parsers as import, but returns\nformatted content directly instead of creating a thread.", "operationId": "export_conversation_raw_threads_conversations_export_raw_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConversationExportRawRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Import Conversation (/docs/api/threads/conversations/import/post) ## POST /threads/conversations/import **Summary:** Import Conversation Import a conversation file into Nowledge Mem. Converts external conversation formats (Claude Code, Codex, Cursor, OpenCode) into threads. ### OpenAPI Operation ```json { "/threads/conversations/import": { "post": { "tags": [ "threads" ], "summary": "Import Conversation", "description": "Import a conversation file into Nowledge Mem.\n\nConverts external conversation formats (Claude Code, Codex, Cursor, OpenCode) into threads.", "operationId": "import_conversation_threads_conversations_import_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConversationImportRequestModel" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConversationImportResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Conversation (/docs/api/threads/conversations/preview/post) ## POST /threads/conversations/preview **Summary:** Preview Conversation Load a richer preview for one selected discovered conversation. ### OpenAPI Operation ```json { "/threads/conversations/preview": { "post": { "tags": [ "threads" ], "summary": "Preview Conversation", "description": "Load a richer preview for one selected discovered conversation.", "operationId": "preview_conversation_threads_conversations_preview_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConversationPreviewRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConversationPreviewResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Mark Thread History Sync Completed (/docs/api/threads/history-sync/completed/post) ## POST /threads/history-sync/completed **Summary:** Mark Thread History Sync Completed Record a single Timeline card for a completed CLI history sync. ### OpenAPI Operation ```json { "/threads/history-sync/completed": { "post": { "tags": [ "threads" ], "summary": "Mark Thread History Sync Completed", "description": "Record a single Timeline card for a completed CLI history sync.", "operationId": "mark_thread_history_sync_completed_threads_history_sync_completed_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadHistorySyncCompletedRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Mark Thread History Sync Completed Threads History Sync Completed Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Hide Project (/docs/api/threads/import-config/hide-project/post) ## POST /threads/import-config/hide-project **Summary:** Hide Project Hide a project from the browse view. ### OpenAPI Operation ```json { "/threads/import-config/hide-project": { "post": { "tags": [ "threads" ], "summary": "Hide Project", "description": "Hide a project from the browse view.", "operationId": "hide_project_threads_import_config_hide_project_post", "parameters": [ { "name": "project_encoded", "in": "query", "required": true, "schema": { "type": "string", "description": "Encoded project path", "title": "Project Encoded" }, "description": "Encoded project path" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Hide Project Threads Import Config Hide Project Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Hide Session (/docs/api/threads/import-config/hide-session/post) ## POST /threads/import-config/hide-session **Summary:** Hide Session Hide a session from the browse view. ### OpenAPI Operation ```json { "/threads/import-config/hide-session": { "post": { "tags": [ "threads" ], "summary": "Hide Session", "description": "Hide a session from the browse view.", "operationId": "hide_session_threads_import_config_hide_session_post", "parameters": [ { "name": "session_id", "in": "query", "required": true, "schema": { "type": "string", "description": "Session ID", "title": "Session Id" }, "description": "Session ID" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Hide Session Threads Import Config Hide Session Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Unhide Project (/docs/api/threads/import-config/unhide-project/post) ## POST /threads/import-config/unhide-project **Summary:** Unhide Project Unhide a project. ### OpenAPI Operation ```json { "/threads/import-config/unhide-project": { "post": { "tags": [ "threads" ], "summary": "Unhide Project", "description": "Unhide a project.", "operationId": "unhide_project_threads_import_config_unhide_project_post", "parameters": [ { "name": "project_encoded", "in": "query", "required": true, "schema": { "type": "string", "description": "Encoded project path", "title": "Project Encoded" }, "description": "Encoded project path" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Unhide Project Threads Import Config Unhide Project Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Unhide Session (/docs/api/threads/import-config/unhide-session/post) ## POST /threads/import-config/unhide-session **Summary:** Unhide Session Unhide a session. ### OpenAPI Operation ```json { "/threads/import-config/unhide-session": { "post": { "tags": [ "threads" ], "summary": "Unhide Session", "description": "Unhide a session.", "operationId": "unhide_session_threads_import_config_unhide_session_post", "parameters": [ { "name": "session_id", "in": "query", "required": true, "schema": { "type": "string", "description": "Session ID", "title": "Session Id" }, "description": "Session ID" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Unhide Session Threads Import Config Unhide Session Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Save Session (/docs/api/threads/sessions/save/post) ## POST /threads/sessions/save **Summary:** Save Session Save coding session(s) as conversation thread(s). Auto-detects sessions from project_path. Creates new thread or appends to existing (with deduplication). Supports Claude Code, Codex, and Gemini CLI. This endpoint assumes the backend machine can read the session files directly, so it is a local-host import surface. Remote-safe capture should use ``nmem t save --from ...`` from the client machine instead. Args: request: Session save request with client, project_path, and options Returns: SessionSaveResponse with results for each processed session ### OpenAPI Operation ```json { "/threads/sessions/save": { "post": { "tags": [ "threads" ], "summary": "Save Session", "description": "Save coding session(s) as conversation thread(s).\n\nAuto-detects sessions from project_path. Creates new thread or appends to existing\n(with deduplication). Supports Claude Code, Codex, and Gemini CLI.\n\nThis endpoint assumes the backend machine can read the session files\ndirectly, so it is a local-host import surface. Remote-safe capture should\nuse ``nmem t save --from ...`` from the client machine instead.\n\nArgs:\n request: Session save request with client, project_path, and options\n\nReturns:\n SessionSaveResponse with results for each processed session", "operationId": "save_session_threads_sessions_save_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SessionSaveRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SessionSaveResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Append Messages To Thread (/docs/api/threads/thread_id/append/post) ## POST /threads/{thread_id}/append **Summary:** Append Messages To Thread Append messages to existing thread (for MCP integration). Supports two modes: 1. Direct messages: `{"messages": [...]}` 2. File-based: `{"file_path": "...", "format": "auto"}` Optional controls: - `deduplicate` (default: true) - `idempotency_key` (string; used to derive stable external_ids) - `space_id` (optional; guards appends to a specific Mem space) ### OpenAPI Operation ```json { "/threads/{thread_id}/append": { "post": { "tags": [ "threads" ], "summary": "Append Messages To Thread", "description": "Append messages to existing thread (for MCP integration).\n\nSupports two modes:\n1. Direct messages: `{\"messages\": [...]}`\n2. File-based: `{\"file_path\": \"...\", \"format\": \"auto\"}`\n\nOptional controls:\n- `deduplicate` (default: true)\n- `idempotency_key` (string; used to derive stable external_ids)\n- `space_id` (optional; guards appends to a specific Mem space)", "operationId": "append_messages_to_thread_threads__thread_id__append_post", "parameters": [ { "name": "thread_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Thread Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Request" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AppendMessagesResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Thread Coverage (/docs/api/threads/thread_id/coverage/get) ## GET /threads/{thread_id}/coverage **Summary:** Get Thread Coverage Read-only coverage report for debugging progress issues. ### OpenAPI Operation ```json { "/threads/{thread_id}/coverage": { "get": { "tags": [ "threads" ], "summary": "Get Thread Coverage", "description": "Read-only coverage report for debugging progress issues.", "operationId": "get_thread_coverage_threads__thread_id__coverage_get", "parameters": [ { "name": "thread_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Thread Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThreadCoverageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Export Thread (/docs/api/threads/thread_id/export/get) ## GET /threads/{thread_id}/export **Summary:** Export Thread Export a thread in various formats. ### OpenAPI Operation ```json { "/threads/{thread_id}/export": { "get": { "tags": [ "threads" ], "summary": "Export Thread", "description": "Export a thread in various formats.", "operationId": "export_thread_threads__thread_id__export_get", "parameters": [ { "name": "thread_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Thread Id" } }, { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "description": "Export format: json, markdown, html", "default": "json", "title": "Format" }, "description": "Export format: json, markdown, html" }, { "name": "include_metadata", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Include thread metadata", "default": true, "title": "Include Metadata" }, "description": "Include thread metadata" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Toggle Thread Favorite (/docs/api/threads/thread_id/favorite/post) ## POST /threads/{thread_id}/favorite **Summary:** Toggle Thread Favorite Toggle favorite status for a thread. ### OpenAPI Operation ```json { "/threads/{thread_id}/favorite": { "post": { "tags": [ "memories" ], "summary": "Toggle Thread Favorite", "description": "Toggle favorite status for a thread.", "operationId": "toggle_thread_favorite_threads__thread_id__favorite_post", "parameters": [ { "name": "thread_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Thread Id" } }, { "name": "is_favorite", "in": "query", "required": true, "schema": { "type": "boolean", "description": "Set favorite status", "title": "Is Favorite" }, "description": "Set favorite status" }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space for disambiguating duplicate thread IDs", "title": "Space Id" }, "description": "Optional isolation space for disambiguating duplicate thread IDs" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Reconcile Thread Tail (/docs/api/threads/thread_id/reconcile-tail/post) ## POST /threads/{thread_id}/reconcile-tail **Summary:** Reconcile Thread Tail Safely replace the tail of a thread without changing append semantics. Optional request fields: - `matched_count` (required int): Number of leading messages that still match - `messages` (required array): Replacement tail messages - `expected_tail_ids` (optional string[]): Current remote tail message IDs for optimistic concurrency ### OpenAPI Operation ```json { "/threads/{thread_id}/reconcile-tail": { "post": { "tags": [ "threads" ], "summary": "Reconcile Thread Tail", "description": "Safely replace the tail of a thread without changing append semantics.\n\nOptional request fields:\n- `matched_count` (required int): Number of leading messages that still match\n- `messages` (required array): Replacement tail messages\n- `expected_tail_ids` (optional string[]): Current remote tail message IDs for optimistic concurrency", "operationId": "reconcile_thread_tail_threads__thread_id__reconcile_tail_post", "parameters": [ { "name": "thread_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Thread Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Request" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReconcileTailResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Start Watcher (/docs/api/threads/watcher/start/post) ## POST /threads/watcher/start **Summary:** Start Watcher Start the session watcher for auto-importing sessions. ### OpenAPI Operation ```json { "/threads/watcher/start": { "post": { "tags": [ "threads" ], "summary": "Start Watcher", "description": "Start the session watcher for auto-importing sessions.", "operationId": "start_watcher_threads_watcher_start_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WatcherStatusModel" } } } } } } } } ``` # Get Watcher Status (/docs/api/threads/watcher/status/get) ## GET /threads/watcher/status **Summary:** Get Watcher Status Get the current status of the session watcher. ### OpenAPI Operation ```json { "/threads/watcher/status": { "get": { "tags": [ "threads" ], "summary": "Get Watcher Status", "description": "Get the current status of the session watcher.", "operationId": "get_watcher_status_threads_watcher_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WatcherStatusModel" } } } } } } } } ``` # Stop Watcher (/docs/api/threads/watcher/stop/post) ## POST /threads/watcher/stop **Summary:** Stop Watcher Stop the session watcher. ### OpenAPI Operation ```json { "/threads/watcher/stop": { "post": { "tags": [ "threads" ], "summary": "Stop Watcher", "description": "Stop the session watcher.", "operationId": "stop_watcher_threads_watcher_stop_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WatcherStatusModel" } } } } } } } } ``` # Preview recurring task occurrences (/docs/api/agent/ai-now/schedules/preview/post) ## POST /agent/ai-now/schedules/preview **Summary:** Preview recurring task occurrences ### OpenAPI Operation ```json { "/agent/ai-now/schedules/preview": { "post": { "tags": [ "ai-now" ], "summary": "Preview recurring task occurrences", "operationId": "openapi_preview_schedule", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PreviewScheduleRequest" } } }, "required": true }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SchedulePreviewResponse" } } } }, "400": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } } } } } } ``` # Delete a recurring AI Now task (/docs/api/agent/ai-now/schedules/schedule_id/delete) ## DELETE /agent/ai-now/schedules/{schedule_id} **Summary:** Delete a recurring AI Now task ### OpenAPI Operation ```json { "/agent/ai-now/schedules/{schedule_id}": { "delete": { "tags": [ "ai-now" ], "summary": "Delete a recurring AI Now task", "operationId": "openapi_delete_schedule", "parameters": [ { "name": "schedule_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleDeleteResponse" } } } }, "404": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } } } } } } ``` # Get a recurring AI Now task (/docs/api/agent/ai-now/schedules/schedule_id/get) ## GET /agent/ai-now/schedules/{schedule_id} **Summary:** Get a recurring AI Now task ### OpenAPI Operation ```json { "/agent/ai-now/schedules/{schedule_id}": { "get": { "tags": [ "ai-now" ], "summary": "Get a recurring AI Now task", "operationId": "openapi_get_schedule", "parameters": [ { "name": "schedule_id", "in": "path", "description": "Stable recurring task ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResponse" } } } }, "404": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } } } } } } ``` # Edit a recurring AI Now task (/docs/api/agent/ai-now/schedules/schedule_id/patch) ## PATCH /agent/ai-now/schedules/{schedule_id} **Summary:** Edit a recurring AI Now task Permission-sensitive changes pause an active task until it is reviewed and confirmed again. ### OpenAPI Operation ```json { "/agent/ai-now/schedules/{schedule_id}": { "patch": { "tags": [ "ai-now" ], "summary": "Edit a recurring AI Now task", "description": "Permission-sensitive changes pause an active task until it is reviewed and confirmed again.", "operationId": "openapi_update_schedule", "parameters": [ { "name": "schedule_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateScheduleRequest" } } }, "required": true }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResponse" } } } }, "400": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } }, "409": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } } } } } } ``` # Delete Ai Now Session (/docs/api/agent/ai-now/sessions/session_id/delete) ## DELETE /agent/ai-now/sessions/{session_id} **Summary:** Delete Ai Now Session ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}": { "delete": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Delete Ai Now Session", "operationId": "delete_ai_now_session_agent_ai_now_sessions__session_id__delete", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Delete Ai Now Session Agent Ai Now Sessions Session Id Delete" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Ai Now Session (/docs/api/agent/ai-now/sessions/session_id/get) ## GET /agent/ai-now/sessions/{session_id} **Summary:** Get Ai Now Session ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Get Ai Now Session", "operationId": "get_ai_now_session_agent_ai_now_sessions__session_id__get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Ai Now Session Agent Ai Now Sessions Session Id Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Ai Now Session (/docs/api/agent/ai-now/sessions/session_id/patch) ## PATCH /agent/ai-now/sessions/{session_id} **Summary:** Update Ai Now Session ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}": { "patch": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Update Ai Now Session", "operationId": "update_ai_now_session_agent_ai_now_sessions__session_id__patch", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowSessionUpdateRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Update Ai Now Session Agent Ai Now Sessions Session Id Patch" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Hide Feed Event (/docs/api/agent/feed/events/event_id/delete) ## DELETE /agent/feed/events/{event_id} **Summary:** Hide Feed Event Compatibility endpoint that hides an immutable Timeline event from the current viewer. It does not delete the event or its evidence. Use PUT /agent/feed/events/{event_id}/visibility to hide or restore explicitly. ### OpenAPI Operation ```json { "/agent/feed/events/{event_id}": { "delete": { "tags": [ "knowledge-agent" ], "summary": "Hide Feed Event", "description": "Compatibility endpoint that hides an immutable Timeline event from the current viewer. It does not delete the event or its evidence. Use PUT /agent/feed/events/{event_id}/visibility to hide or restore explicitly.", "operationId": "delete_feed_event_agent_feed_events__event_id__delete", "parameters": [ { "name": "event_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Event Id" } } ], "responses": { "200": { "description": "Event hidden for the current viewer", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FeedEventVisibilityResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Persist Question (/docs/api/agent/feed/input/persist-question/post) ## POST /agent/feed/input/persist-question **Summary:** Persist Question Save a question and its response as a feed event. Called after agent streaming completes to persist the Q&A in the feed timeline. Does not create memories, only stores the conversation. ### OpenAPI Operation ```json { "/agent/feed/input/persist-question": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "knowledge-agent" ], "summary": "Persist Question", "description": "Save a question and its response as a feed event.\n\nCalled after agent streaming completes to persist the Q&A in the feed timeline. Does not create memories, only stores the conversation.", "operationId": "persist_question_agent_feed_input_persist_question_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersistQuestionRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Persist Question Agent Feed Input Persist Question Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Submit Feed Input Stream (/docs/api/agent/feed/input/stream/post) ## POST /agent/feed/input/stream **Summary:** Submit Feed Input Stream Stream agent processing of feed input. The agent classifies your input, searches the knowledge base for context, and streams back a response. Captures are saved as memories automatically. ### OpenAPI Operation ```json { "/agent/feed/input/stream": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "knowledge-agent" ], "summary": "Submit Feed Input Stream", "description": "Stream agent processing of feed input.\n\nThe agent classifies your input, searches the knowledge base for context, and streams back a response. Captures are saved as memories automatically.", "operationId": "submit_feed_input_stream_agent_feed_input_stream_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FeedInputRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Cancel Knowledge Processing Task (/docs/api/agent/knowledge-processing/tasks/cancel/post) ## POST /agent/knowledge-processing/tasks/cancel **Summary:** Cancel Knowledge Processing Task Cancel a queued or running Knowledge Processing task. ### OpenAPI Operation ```json { "/agent/knowledge-processing/tasks/cancel": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Cancel Knowledge Processing Task", "description": "Cancel a queued or running Knowledge Processing task.", "operationId": "cancel_knowledge_processing_task_agent_knowledge_processing_tasks_cancel_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CancelKnowledgeProcessingTaskRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Cancel Knowledge Processing Task Agent Knowledge Processing Tasks Cancel Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Skill Builder Refine Stream (/docs/api/agent/skill-builder/refine/stream/post) ## POST /agent/skill-builder/refine/stream **Summary:** Skill Builder Refine Stream Stream the refine work (SSE): ``reading`` -> ``outcomes`` -> ``drafting`` -> ``revision`` -> ``done`` (or ``error``). The UI renders the optimize loop as a live process, the same way create does. ### OpenAPI Operation ```json { "/agent/skill-builder/refine/stream": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "skill-builder" ], "summary": "Skill Builder Refine Stream", "description": "Stream the refine work (SSE): ``reading`` -> ``outcomes`` -> ``drafting`` ->\n``revision`` -> ``done`` (or ``error``). The UI renders the optimize loop as a\nlive process, the same way create does.", "operationId": "skill_builder_refine_stream_agent_skill_builder_refine_stream_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillRefineRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Community Detection (/docs/api/agent/trigger/community-detection/plan/get) ## GET /agent/trigger/community-detection/plan **Summary:** Plan Community Detection Preview a community detection refresh without scheduling work. ### OpenAPI Operation ```json { "/agent/trigger/community-detection/plan": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Plan Community Detection", "description": "Preview a community detection refresh without scheduling work.", "operationId": "plan_community_detection_agent_trigger_community_detection_plan_get", "parameters": [ { "name": "resolution", "in": "query", "required": false, "schema": { "type": "number", "maximum": 5, "minimum": 0.1, "default": 1, "title": "Resolution" } }, { "name": "generate_ai_summary", "in": "query", "required": false, "schema": { "type": "boolean", "default": true, "title": "Generate Ai Summary" } }, { "name": "scan_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 2000, "minimum": 1, "default": 500, "title": "Scan Limit" } }, { "name": "summary_limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 200, "minimum": 1 }, { "type": "null" } ], "title": "Summary Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Plan Community Detection Agent Trigger Community Detection Plan Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Kg Extraction Backfill (/docs/api/agent/trigger/kg-extraction/plan/get) ## GET /agent/trigger/kg-extraction/plan **Summary:** Plan Kg Extraction Backfill Preview a bounded KG backfill batch without scheduling work. ### OpenAPI Operation ```json { "/agent/trigger/kg-extraction/plan": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Plan Kg Extraction Backfill", "description": "Preview a bounded KG backfill batch without scheduling work.", "operationId": "plan_kg_extraction_backfill_agent_trigger_kg_extraction_plan_get", "parameters": [ { "name": "scan_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 2000, "minimum": 1, "default": 500, "title": "Scan Limit" } }, { "name": "batch_size", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 10, "minimum": 1, "default": 5, "title": "Batch Size" } }, { "name": "repair_empty", "in": "query", "required": false, "schema": { "type": "boolean", "description": "When true, preview a bounded repair wave for memories previously marked extracted but carrying no graph facts.", "default": false, "title": "Repair Empty" }, "description": "When true, preview a bounded repair wave for memories previously marked extracted but carrying no graph facts." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Plan Kg Extraction Backfill Agent Trigger Kg Extraction Plan Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Archive Memory Cleanup Candidates (/docs/api/agent/trigger/memory-cleanup/archive/post) ## POST /agent/trigger/memory-cleanup/archive **Summary:** Archive Memory Cleanup Candidates Archive user-reviewed cleanup candidates after server-side revalidation. The client only submits ids from the visible review. The server re-reads the source-of-truth rows and re-runs the cleanup classifier so stale UI state can never archive a memory that was visited, pinned, or otherwise protected after the review was rendered. ### OpenAPI Operation ```json { "/agent/trigger/memory-cleanup/archive": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Archive Memory Cleanup Candidates", "description": "Archive user-reviewed cleanup candidates after server-side revalidation.\n\nThe client only submits ids from the visible review. The server re-reads the\nsource-of-truth rows and re-runs the cleanup classifier so stale UI state can\nnever archive a memory that was visited, pinned, or otherwise protected after\nthe review was rendered.", "operationId": "archive_memory_cleanup_candidates_agent_trigger_memory_cleanup_archive_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryCleanupArchiveRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Archive Memory Cleanup Candidates Agent Trigger Memory Cleanup Archive Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Queue Memory Cleanup Compaction (/docs/api/agent/trigger/memory-cleanup/compaction/post) ## POST /agent/trigger/memory-cleanup/compaction **Summary:** Queue Memory Cleanup Compaction Queue semantic compaction for user-reviewed cleanup candidates. This is deliberately not an automatic merge. It re-reads each submitted memory id, re-runs the cleanup classifier, and only queues the bounded Memory Compaction task for rows still in the semantic-review lane. ### OpenAPI Operation ```json { "/agent/trigger/memory-cleanup/compaction": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Queue Memory Cleanup Compaction", "description": "Queue semantic compaction for user-reviewed cleanup candidates.\n\nThis is deliberately not an automatic merge. It re-reads each submitted\nmemory id, re-runs the cleanup classifier, and only queues the bounded\nMemory Compaction task for rows still in the semantic-review lane.", "operationId": "queue_memory_cleanup_compaction_agent_trigger_memory_cleanup_compaction_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryCleanupCompactionRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Queue Memory Cleanup Compaction Agent Trigger Memory Cleanup Compaction Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Keep Memory Cleanup Candidates (/docs/api/agent/trigger/memory-cleanup/keep/post) ## POST /agent/trigger/memory-cleanup/keep **Summary:** Keep Memory Cleanup Candidates Mark user-reviewed cleanup candidates as intentionally kept. This is the negative-feedback side of cleanup governance. Dismissing a Timeline card should not make Mem ask about the same rows again next week; it should become an explicit retention signal on the Memory itself. The server still revalidates each id so changed or hidden rows are skipped. ### OpenAPI Operation ```json { "/agent/trigger/memory-cleanup/keep": { "post": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Keep Memory Cleanup Candidates", "description": "Mark user-reviewed cleanup candidates as intentionally kept.\n\nThis is the negative-feedback side of cleanup governance. Dismissing a\nTimeline card should not make Mem ask about the same rows again next week;\nit should become an explicit retention signal on the Memory itself. The\nserver still revalidates each id so changed or hidden rows are skipped.", "operationId": "keep_memory_cleanup_candidates_agent_trigger_memory_cleanup_keep_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryCleanupKeepRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Keep Memory Cleanup Candidates Agent Trigger Memory Cleanup Keep Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Memory Cleanup (/docs/api/agent/trigger/memory-cleanup/plan/get) ## GET /agent/trigger/memory-cleanup/plan **Summary:** Plan Memory Cleanup Preview Memory cleanup lanes without queueing or mutating anything. ### OpenAPI Operation ```json { "/agent/trigger/memory-cleanup/plan": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Plan Memory Cleanup", "description": "Preview Memory cleanup lanes without queueing or mutating anything.", "operationId": "plan_memory_cleanup_agent_trigger_memory_cleanup_plan_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 30, "title": "Limit" } }, { "name": "scan_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 5000, "minimum": 1, "default": 500, "title": "Scan Limit" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Space Id" } }, { "name": "emit_event", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Emit Event" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Plan Memory Cleanup Agent Trigger Memory Cleanup Plan Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Memory Compaction (/docs/api/agent/trigger/memory-compaction/plan/get) ## GET /agent/trigger/memory-compaction/plan **Summary:** Plan Memory Compaction Preview the exact compaction candidate context without queueing work. This endpoint does not ask the agent to decide, does not create EVOLVES edges, does not create crystals, and does not enqueue the compaction task. It exposes the same pre-computed candidate context the scheduled task would inject into the Knowledge Agent so evals can measure the real input surface. ### OpenAPI Operation ```json { "/agent/trigger/memory-compaction/plan": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Plan Memory Compaction", "description": "Preview the exact compaction candidate context without queueing work.\n\nThis endpoint does not ask the agent to decide, does not create EVOLVES\nedges, does not create crystals, and does not enqueue the compaction task.\nIt exposes the same pre-computed candidate context the scheduled task would\ninject into the Knowledge Agent so evals can measure the real input surface.", "operationId": "plan_memory_compaction_agent_trigger_memory_compaction_plan_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 30, "title": "Limit" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Space Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Plan Memory Compaction Agent Trigger Memory Compaction Plan Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Memory Created Events (/docs/api/agent/trigger/memory-created/plan/get) ## GET /agent/trigger/memory-created/plan **Summary:** Plan Memory Created Events Preview the next memory-created flush without mutating scheduler state. ### OpenAPI Operation ```json { "/agent/trigger/memory-created/plan": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Plan Memory Created Events", "description": "Preview the next memory-created flush without mutating scheduler state.", "operationId": "plan_memory_created_events_agent_trigger_memory_created_plan_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Plan Memory Created Events Agent Trigger Memory Created Plan Get" } } } } } } } } ``` # Dry Run Guidance Rule Review (/docs/api/agent/trigger/rule-review/dry-run/get) ## GET /agent/trigger/rule-review/dry-run **Summary:** Dry Run Guidance Rule Review Preview learned Rule suggestions without writing draft Rules. This may call the configured model to judge harvested evidence, but it does not archive stale drafts, write new drafts, enqueue work, or mutate graph state. ### OpenAPI Operation ```json { "/agent/trigger/rule-review/dry-run": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Dry Run Guidance Rule Review", "description": "Preview learned Rule suggestions without writing draft Rules.\n\nThis may call the configured model to judge harvested evidence, but it does\nnot archive stale drafts, write new drafts, enqueue work, or mutate graph\nstate.", "operationId": "dry_run_guidance_rule_review_agent_trigger_rule_review_dry_run_get", "parameters": [ { "name": "queries", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "title": "Queries" } }, { "name": "memory_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Memory Id" } }, { "name": "memory_ids", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ], "title": "Memory Ids" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Space Id" } }, { "name": "max_evidence_results", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 40, "minimum": 2, "default": 40, "title": "Max Evidence Results" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Dry Run Guidance Rule Review Agent Trigger Rule Review Dry Run Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Scheduled Agent Context (/docs/api/agent/trigger/task_type/context-plan/get) ## GET /agent/trigger/{task_type}/context-plan **Summary:** Plan Scheduled Agent Context Preview the context injected into supported scheduled agent tasks. This endpoint does not enqueue work, does not run the agent, and does not ask an LLM to decide. It exposes the actual context prefix produced by the runtime injector so evals can audit the live input surface before any prompt or cadence changes are claimed as improvements. ### OpenAPI Operation ```json { "/agent/trigger/{task_type}/context-plan": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Plan Scheduled Agent Context", "description": "Preview the context injected into supported scheduled agent tasks.\n\nThis endpoint does not enqueue work, does not run the agent, and does not\nask an LLM to decide. It exposes the actual context prefix produced by the\nruntime injector so evals can audit the live input surface before any prompt\nor cadence changes are claimed as improvements.", "operationId": "plan_scheduled_agent_context_agent_trigger__task_type__context_plan_get", "parameters": [ { "name": "task_type", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Type" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Space Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Plan Scheduled Agent Context Agent Trigger Task Type Context Plan Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Plan Thread Synced Events (/docs/api/agent/trigger/thread-synced/plan/get) ## GET /agent/trigger/thread-synced/plan **Summary:** Plan Thread Synced Events Preview the next thread-sync flush without mutating scheduler state. ### OpenAPI Operation ```json { "/agent/trigger/thread-synced/plan": { "get": { "tags": [ "knowledge-agent", "knowledge-agent" ], "summary": "Plan Thread Synced Events", "description": "Preview the next thread-sync flush without mutating scheduler state.", "operationId": "plan_thread_synced_events_agent_trigger_thread_synced_plan_get", "parameters": [ { "name": "max_tasks", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 100, "minimum": 0 }, { "type": "null" } ], "title": "Max Tasks" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Plan Thread Synced Events Agent Trigger Thread Synced Plan Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Export Status (/docs/api/data/export/status/job_id/get) ## GET /data/export/status/{job_id} **Summary:** Get Export Status Check the progress of a background data export job started with `POST /data/export` and `async: true`. ### OpenAPI Operation ```json { "/data/export/status/{job_id}": { "get": { "tags": [ "data-transfer" ], "operationId": "get_export_status_data_export_status__job_id__get", "parameters": [ { "name": "job_id", "in": "path", "description": "Data transfer job id", "required": true, "schema": { "type": "string", "title": "Job Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataImportStatusResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "summary": "Get Export Status", "description": "Check the progress of a background data export job started with `POST /data/export` and `async: true`." } } } ``` # Get Import Status (/docs/api/data/import/status/job_id/get) ## GET /data/import/status/{job_id} **Summary:** Get Import Status Check the progress of a data import job. ### OpenAPI Operation ```json { "/data/import/status/{job_id}": { "get": { "tags": [ "data-transfer" ], "operationId": "get_import_status_data_import_status__job_id__get", "parameters": [ { "name": "job_id", "in": "path", "description": "Data transfer job id", "required": true, "schema": { "type": "string", "title": "Job Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataImportStatusResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "summary": "Get Import Status", "description": "Check the progress of a data import job." } } } ``` # Preview entity deletion (/docs/api/entities/entity_id/delete/preview/get) ## GET /entities/{entity_id}/delete/preview **Summary:** Preview entity deletion Count the graph links that would be detached. Referencing memories are always preserved. ### OpenAPI Operation ```json { "/entities/{entity_id}/delete/preview": { "get": { "tags": [ "entities" ], "summary": "Preview entity deletion", "description": "Count the graph links that would be detached. Referencing memories are always preserved.", "operationId": "preview_entity_delete_handler", "parameters": [ { "name": "entity_id", "in": "path", "description": "Entity id", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Deletion impact preview", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EntityDeletePlanResponse" } } } }, "404": { "description": "Entity not found" } } } } } ``` # Preview an entity merge (/docs/api/entities/entity_id/merge/preview/post) ## POST /entities/{entity_id}/merge/preview **Summary:** Preview an entity merge Preview moving a duplicate Entity into a canonical target, including mention and custom-relation consolidation. ### OpenAPI Operation ```json { "/entities/{entity_id}/merge/preview": { "post": { "tags": [ "entities" ], "summary": "Preview an entity merge", "description": "Preview moving a duplicate Entity into a canonical target, including mention and custom-relation consolidation.", "operationId": "preview_entity_merge_handler", "parameters": [ { "name": "entity_id", "in": "path", "description": "Source entity id", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EntityMergeRequest" } } }, "required": true }, "responses": { "200": { "description": "Merge impact preview", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EntityMergePlanResponse" } } } }, "404": { "description": "Source or target Entity not found" }, "422": { "description": "Source and target are invalid" } } } } } ``` # Plan Pagerank Refresh (/docs/api/graph/augmentation/pagerank/plan/get) ## GET /graph/augmentation/pagerank/plan **Summary:** Plan Pagerank Refresh Preview a PageRank refresh without scheduling graph augmentation work. ### OpenAPI Operation ```json { "/graph/augmentation/pagerank/plan": { "get": { "tags": [ "graph-analysis" ], "summary": "Plan Pagerank Refresh", "description": "Preview a PageRank refresh without scheduling graph augmentation work.", "operationId": "plan_pagerank_refresh_graph_augmentation_pagerank_plan_get", "parameters": [ { "name": "force", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Force" } }, { "name": "min_nodes", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000, "minimum": 1, "default": 2, "title": "Min Nodes" } }, { "name": "min_edges", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 1000000, "minimum": 0, "default": 1, "title": "Min Edges" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Plan Pagerank Refresh Graph Augmentation Pagerank Plan Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Job Status (/docs/api/graph/augmentation/status/job_id/get) ## GET /graph/augmentation/status/{job_id} **Summary:** Get Job Status Get the status of a specific augmentation job. Returns job progress, status, and any error messages. ### OpenAPI Operation ```json { "/graph/augmentation/status/{job_id}": { "get": { "tags": [ "graph-analysis" ], "summary": "Get Job Status", "description": "Get the status of a specific augmentation job.\n\nReturns job progress, status, and any error messages.", "operationId": "get_job_status_graph_augmentation_status__job_id__get", "parameters": [ { "name": "job_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Job Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AugmentationJobStatusResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Apply label deletion (/docs/api/labels/label_id/delete/apply/post) ## POST /labels/{label_id}/delete/apply **Summary:** Apply label deletion Atomically delete a label only if its current state still matches the supplied preview plan. ### OpenAPI Operation ```json { "/labels/{label_id}/delete/apply": { "post": { "tags": [ "labels" ], "summary": "Apply label deletion", "description": "Atomically delete a label only if its current state still matches the supplied preview plan.", "operationId": "apply_label_delete_handler", "parameters": [ { "name": "label_id", "in": "path", "description": "Label id", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelApplyRequest" } } }, "required": true }, "responses": { "200": { "description": "Label deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelMutationResponse" } } } }, "404": { "description": "Label not found" }, "409": { "description": "Label changed after preview" } } } } } ``` # Preview label deletion (/docs/api/labels/label_id/delete/preview/post) ## POST /labels/{label_id}/delete/preview **Summary:** Preview label deletion Return the exact resources whose label assignment would be detached. Memories and resources are preserved. ### OpenAPI Operation ```json { "/labels/{label_id}/delete/preview": { "post": { "tags": [ "labels" ], "summary": "Preview label deletion", "description": "Return the exact resources whose label assignment would be detached. Memories and resources are preserved.", "operationId": "preview_label_delete_handler", "parameters": [ { "name": "label_id", "in": "path", "description": "Label id", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Deletion plan", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelLifecyclePlanResponse" } } } }, "404": { "description": "Label not found" } } } } } ``` # Apply a label merge (/docs/api/labels/label_id/merge/apply/post) ## POST /labels/{label_id}/merge/apply **Summary:** Apply a label merge Atomically move assignments and remove the source label only if both labels still match the supplied preview plan. ### OpenAPI Operation ```json { "/labels/{label_id}/merge/apply": { "post": { "tags": [ "labels" ], "summary": "Apply a label merge", "description": "Atomically move assignments and remove the source label only if both labels still match the supplied preview plan.", "operationId": "apply_label_merge_handler", "parameters": [ { "name": "label_id", "in": "path", "description": "Source label id", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelMergeApplyRequest" } } }, "required": true }, "responses": { "200": { "description": "Labels merged", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelMutationResponse" } } } }, "404": { "description": "Source or target label not found" }, "409": { "description": "Labels changed after preview" }, "422": { "description": "Missing plan id or invalid labels" } } } } } ``` # Preview a label merge (/docs/api/labels/label_id/merge/preview/post) ## POST /labels/{label_id}/merge/preview **Summary:** Preview a label merge Preview moving every assignment from a duplicate label to a canonical label. ### OpenAPI Operation ```json { "/labels/{label_id}/merge/preview": { "post": { "tags": [ "labels" ], "summary": "Preview a label merge", "description": "Preview moving every assignment from a duplicate label to a canonical label.", "operationId": "preview_label_merge_handler", "parameters": [ { "name": "label_id", "in": "path", "description": "Source label id", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelMergePreviewRequest" } } }, "required": true }, "responses": { "200": { "description": "Merge plan", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LabelLifecyclePlanResponse" } } } }, "404": { "description": "Source or target label not found" }, "422": { "description": "Source and target are invalid" } } } } } ``` # Get Community Recent Memories (/docs/api/library/community/community_id/recent-memories/get) ## GET /library/community/{community_id}/recent-memories **Summary:** Get Community Recent Memories Most recent memories mentioning any entity in this community. Cross-space; reads the global graph regardless of active space lens (Louvain ids are global). Powers the "Recent on this topic" rail on the Library wiki community panel — closes the loop between "what this topic is" (top entities + crystals) and "what's happening on it lately" (recent memories that touch it). ### OpenAPI Operation ```json { "/library/community/{community_id}/recent-memories": { "get": { "tags": [ "library-wiki" ], "summary": "Get Community Recent Memories", "description": "Most recent memories mentioning any entity in this community.\n\nCross-space; reads the global graph regardless of active space lens\n(Louvain ids are global). Powers the \"Recent on this topic\" rail\non the Library wiki community panel — closes the loop between\n\"what this topic is\" (top entities + crystals) and \"what's\nhappening on it lately\" (recent memories that touch it).", "operationId": "get_community_recent_memories_library_community__community_id__recent_memories_get", "parameters": [ { "name": "community_id", "in": "path", "required": true, "schema": { "type": "integer", "title": "Community Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 20, "minimum": 1, "default": 8, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Related Communities (/docs/api/library/community/community_id/related/get) ## GET /library/community/{community_id}/related **Summary:** Get Related Communities Return other communities sharing entity-to-entity edges with this one. Cross-space; reads the global graph regardless of active space lens. Communities are computed by Louvain over the global Entity projection, so the related-communities lens is meaningless when scoped to a single space. The "shared edge count" is how many RELATES_TO edges run between an entity in this community and an entity in the other community: the strongest available signal that two topic clusters touch each other in the user's mind. ### OpenAPI Operation ```json { "/library/community/{community_id}/related": { "get": { "tags": [ "library-wiki" ], "summary": "Get Related Communities", "description": "Return other communities sharing entity-to-entity edges with this one.\n\nCross-space; reads the global graph regardless of active space lens.\nCommunities are computed by Louvain over the global Entity projection,\nso the related-communities lens is meaningless when scoped to a single\nspace. The \"shared edge count\" is how many RELATES_TO edges run\nbetween an entity in this community and an entity in the other\ncommunity: the strongest available signal that two topic clusters\ntouch each other in the user's mind.", "operationId": "get_related_communities_library_community__community_id__related_get", "parameters": [ { "name": "community_id", "in": "path", "required": true, "schema": { "type": "integer", "title": "Community Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 20, "minimum": 1, "default": 6, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Community Subgraph (/docs/api/library/community/community_id/subgraph/get) ## GET /library/community/{community_id}/subgraph **Summary:** Get Community Subgraph Return the actual subgraph for a community. Cross-space; reads the global graph regardless of active space lens (Louvain ids are global). Returns the entities in this community plus their RELATES_TO edges to each other, and optionally the highest-mentioned memories that touch any of these entities, so the Library wiki community panel can render the cluster's true shape — not a 30-node live-preview sample. Output shape matches `GraphData` (`nodes` carry `node_type` and `metadata`; `edges` carry `edge_type`) so the same MiniGraph component used in the Feed Timeline can render it without an extra adapter. ### OpenAPI Operation ```json { "/library/community/{community_id}/subgraph": { "get": { "tags": [ "library-wiki" ], "summary": "Get Community Subgraph", "description": "Return the actual subgraph for a community.\n\nCross-space; reads the global graph regardless of active space lens\n(Louvain ids are global). Returns the entities in this community\nplus their RELATES_TO edges to each other, and optionally the\nhighest-mentioned memories that touch any of these entities, so\nthe Library wiki community panel can render the cluster's true\nshape — not a 30-node live-preview sample.\n\nOutput shape matches `GraphData` (`nodes` carry `node_type` and\n`metadata`; `edges` carry `edge_type`) so the same MiniGraph\ncomponent used in the Feed Timeline can render it without an\nextra adapter.", "operationId": "get_community_subgraph_library_community__community_id__subgraph_get", "parameters": [ { "name": "community_id", "in": "path", "required": true, "schema": { "type": "integer", "title": "Community Id" } }, { "name": "max_entities", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 10, "default": 80, "title": "Max Entities" } }, { "name": "include_top_memories", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 40, "minimum": 0, "default": 12, "title": "Include Top Memories" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Crystal Source Memories (/docs/api/library/crystal/crystal_id/source-memories/get) ## GET /library/crystal/{crystal_id}/source-memories **Summary:** Get Crystal Source Memories Return the source memories a crystal was synthesized from. Powers the "Built from N memories" section on the Crystal page in the Library wiki. Follows the CRYSTALLIZED_FROM edge that CreateCrystal writes during synthesis (one edge per source memory, with a contribution_weight property). Sorted by weight descending so the most-contributing memories surface first. ### OpenAPI Operation ```json { "/library/crystal/{crystal_id}/source-memories": { "get": { "tags": [ "library-wiki" ], "summary": "Get Crystal Source Memories", "description": "Return the source memories a crystal was synthesized from.\n\nPowers the \"Built from N memories\" section on the Crystal page in the\nLibrary wiki. Follows the CRYSTALLIZED_FROM edge that CreateCrystal\nwrites during synthesis (one edge per source memory, with a\ncontribution_weight property). Sorted by weight descending so the\nmost-contributing memories surface first.", "operationId": "get_crystal_source_memories_library_crystal__crystal_id__source_memories_get", "parameters": [ { "name": "crystal_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Crystal Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "default": 50, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Wiki Page Crystal (/docs/api/library/wiki-page/crystal/crystal_id/get) ## GET /library/wiki-page/crystal/{crystal_id} **Summary:** Get Wiki Page Crystal Render a single crystal's wiki page as markdown. By-id-direct. ### OpenAPI Operation ```json { "/library/wiki-page/crystal/{crystal_id}": { "get": { "tags": [ "library-wiki" ], "summary": "Get Wiki Page Crystal", "description": "Render a single crystal's wiki page as markdown. By-id-direct.", "operationId": "get_wiki_page_crystal_library_wiki_page_crystal__crystal_id__get", "parameters": [ { "name": "crystal_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Crystal Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Wiki Page Entity (/docs/api/library/wiki-page/entity/id_or_name/get) ## GET /library/wiki-page/entity/{id_or_name} **Summary:** Get Wiki Page Entity Render a single entity's wiki page as markdown. Cross-space (graph aggregation): looks up by id, with a case-insensitive name fallback. Pass either the entity UUID or its canonical name. ### OpenAPI Operation ```json { "/library/wiki-page/entity/{id_or_name}": { "get": { "tags": [ "library-wiki" ], "summary": "Get Wiki Page Entity", "description": "Render a single entity's wiki page as markdown.\n\nCross-space (graph aggregation): looks up by id, with a case-insensitive\nname fallback. Pass either the entity UUID or its canonical name.", "operationId": "get_wiki_page_entity_library_wiki_page_entity__id_or_name__get", "parameters": [ { "name": "id_or_name", "in": "path", "required": true, "schema": { "type": "string", "title": "Id Or Name" } }, { "name": "mention_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "default": 30, "title": "Mention Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Wiki Page Topic (/docs/api/library/wiki-page/topic/community_id/get) ## GET /library/wiki-page/topic/{community_id} **Summary:** Get Wiki Page Topic Render a single topic (community) wiki page as markdown. Cross-space (graph aggregation). The community id is the Louvain integer assigned by community detection. ### OpenAPI Operation ```json { "/library/wiki-page/topic/{community_id}": { "get": { "tags": [ "library-wiki" ], "summary": "Get Wiki Page Topic", "description": "Render a single topic (community) wiki page as markdown.\n\nCross-space (graph aggregation). The community id is the Louvain\ninteger assigned by community detection.", "operationId": "get_wiki_page_topic_library_wiki_page_topic__community_id__get", "parameters": [ { "name": "community_id", "in": "path", "required": true, "schema": { "type": "integer", "title": "Community Id" } }, { "name": "top_per_community", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 30, "minimum": 1, "default": 12, "title": "Top Per Community" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Bulk Move Memories (/docs/api/memories/bulk/move/preview/post) ## POST /memories/bulk/move/preview **Summary:** Preview Bulk Move Memories Preview a bounded bulk memory move before mutating data. ### OpenAPI Operation ```json { "/memories/bulk/move/preview": { "post": { "tags": [ "memories" ], "summary": "Preview Bulk Move Memories", "description": "Preview a bounded bulk memory move before mutating data.", "operationId": "preview_bulk_move_memories_memories_bulk_move_preview_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMoveMemoriesRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMovePreviewResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Apply a Memory history correction (/docs/api/memories/evolves/revision/apply/post) ## POST /memories/evolves/revision/apply **Summary:** Apply a Memory history correction Atomically reconcile the pair's direct EVOLVES edge, recompute visibility from the remaining replacement graph, and write an idempotent governance receipt. ### OpenAPI Operation ```json { "/memories/evolves/revision/apply": { "post": { "tags": [ "memories" ], "summary": "Apply a Memory history correction", "description": "Atomically reconcile the pair's direct EVOLVES edge, recompute visibility from the remaining replacement graph, and write an idempotent governance receipt.", "operationId": "apply_evolves_revision_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EvolvesRevisionApplyRequest" } } }, "required": true }, "responses": { "200": { "description": "Correction applied", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EvolvesRevisionResultResponse" } } } }, "409": { "description": "Pair changed after preview" }, "422": { "description": "Invalid correction" } } } } } ``` # Preview a Memory history correction (/docs/api/memories/evolves/revision/preview/post) ## POST /memories/evolves/revision/preview **Summary:** Preview a Memory history correction Inspect the exact EVOLVES pair and bind a desired semantic state to its current topology. This never mutates raw edges or Memory visibility fields. ### OpenAPI Operation ```json { "/memories/evolves/revision/preview": { "post": { "tags": [ "memories" ], "summary": "Preview a Memory history correction", "description": "Inspect the exact EVOLVES pair and bind a desired semantic state to its current topology. This never mutates raw edges or Memory visibility fields.", "operationId": "preview_evolves_revision_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EvolvesRevisionPreviewRequest" } } }, "required": true }, "responses": { "200": { "description": "State-bound correction plan", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EvolvesRevisionPlanResponse" } } } }, "404": { "description": "Memory pair not found" }, "422": { "description": "Invalid correction" } } } } } ``` # Apply Memory Kg Extraction (/docs/api/memories/memory_id/extract-kg/apply/post) ## POST /memories/{memory_id}/extract-kg/apply **Summary:** Apply Memory Kg Extraction Apply knowledge graph extraction results to a memory. This endpoint saves the extracted entities and relationships to the graph database and updates the memory's metadata to track the extraction. ### OpenAPI Operation ```json { "/memories/{memory_id}/extract-kg/apply": { "post": { "tags": [ "memories" ], "summary": "Apply Memory Kg Extraction", "description": "Apply knowledge graph extraction results to a memory.\n\nThis endpoint saves the extracted entities and relationships to the graph database\nand updates the memory's metadata to track the extraction.", "operationId": "apply_memory_kg_extraction_memories__memory_id__extract_kg_apply_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryKGApplyRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryKGApplyResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Memory Kg Extraction (/docs/api/memories/memory_id/extract-kg/preview/post) ## POST /memories/{memory_id}/extract-kg/preview **Summary:** Preview Memory Kg Extraction Preview knowledge graph extraction for a memory. This endpoint extracts entities and relationships from a memory's content using the local LLM, providing a preview without saving to the database. ### OpenAPI Operation ```json { "/memories/{memory_id}/extract-kg/preview": { "post": { "tags": [ "memories" ], "summary": "Preview Memory Kg Extraction", "description": "Preview knowledge graph extraction for a memory.\n\nThis endpoint extracts entities and relationships from a memory's content\nusing the local LLM, providing a preview without saving to the database.", "operationId": "preview_memory_kg_extraction_memories__memory_id__extract_kg_preview_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryKGExtractionRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryKGExtractionResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Remove Label From Memory (/docs/api/memories/memory_id/labels/label_id/delete) ## DELETE /memories/{memory_id}/labels/{label_id} **Summary:** Remove Label From Memory Remove a label from a memory. ### OpenAPI Operation ```json { "/memories/{memory_id}/labels/{label_id}": { "delete": { "tags": [ "memories" ], "summary": "Remove Label From Memory", "description": "Remove a label from a memory.", "operationId": "remove_label_from_memory_memories__memory_id__labels__label_id__delete", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } }, { "name": "label_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Label Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Assign Label To Memory (/docs/api/memories/memory_id/labels/label_id/post) ## POST /memories/{memory_id}/labels/{label_id} **Summary:** Assign Label To Memory Assign a label to a memory. ### OpenAPI Operation ```json { "/memories/{memory_id}/labels/{label_id}": { "post": { "tags": [ "memories" ], "summary": "Assign Label To Memory", "description": "Assign a label to a memory.", "operationId": "assign_label_to_memory_memories__memory_id__labels__label_id__post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } }, { "name": "label_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Label Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Suggest Memory Relation (/docs/api/memories/memory_id/relations/suggest/post) ## POST /memories/{memory_id}/relations/suggest **Summary:** Suggest Memory Relation Suggest a semantic relation for two memories without writing it. ### OpenAPI Operation ```json { "/memories/{memory_id}/relations/suggest": { "post": { "tags": [ "memories" ], "summary": "Suggest Memory Relation", "description": "Suggest a semantic relation for two memories without writing it.", "operationId": "suggest_memory_relation_memories__memory_id__relations_suggest_post", "parameters": [ { "name": "memory_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Memory Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationSuggestRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemoryRelationSuggestionPublic" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Set Skill Host Config Dir (/docs/api/skills/registration/host/config-dir/put) ## PUT /skills/registration/{host}/config-dir **Summary:** Set Skill Host Config Dir Point one host at a custom config dir, then re-sync if it is connected. ### OpenAPI Operation ```json { "/skills/registration/{host}/config-dir": { "put": { "tags": [ "skills", "skills", "skills" ], "summary": "Set Skill Host Config Dir", "description": "Point one host at a custom config dir, then re-sync if it is connected.", "operationId": "set_skill_host_config_dir_skills_registration__host__config_dir_put", "parameters": [ { "name": "host", "in": "path", "required": true, "schema": { "type": "string", "title": "Host" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HostConfigDir" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Set Skill Host Config Dir Skills Registration Host Config Dir Put" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # List Eval Cases (/docs/api/skills/skill_id/eval/cases/get) ## GET /skills/{skill_id}/eval/cases **Summary:** List Eval Cases List the editable benchmark inventory, including each case task, expectation, deterministic checks, review status, and source. Output cases use expectation output; routing negatives use should_not_trigger and carry no output checks. ### OpenAPI Operation ```json { "/skills/{skill_id}/eval/cases": { "get": { "tags": [ "skills", "skills" ], "summary": "List Eval Cases", "description": "List the editable benchmark inventory, including each case task, expectation, deterministic checks, review status, and source. Output cases use expectation output; routing negatives use should_not_trigger and carry no output checks.", "operationId": "list_eval_cases_skills__skill_id__eval_cases_get", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response List Eval Cases Skills Skill Id Eval Cases Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Add Eval Case (/docs/api/skills/skill_id/eval/cases/post) ## POST /skills/{skill_id}/eval/cases **Summary:** Add Eval Case Add a human-authored benchmark case. Use {task, checks:[{op, arg}], status?} for an output case, or {task, expectation:"should_not_trigger"} for a semantic routing negative. Routing negatives assert that production Skill discovery must leave this Skill silent for the near-miss task. ### OpenAPI Operation ```json { "/skills/{skill_id}/eval/cases": { "post": { "tags": [ "skills", "skills" ], "summary": "Add Eval Case", "description": "Add a human-authored benchmark case. Use {task, checks:[{op, arg}], status?} for an output case, or {task, expectation:\"should_not_trigger\"} for a semantic routing negative. Routing negatives assert that production Skill discovery must leave this Skill silent for the near-miss task.", "operationId": "add_eval_case_skills__skill_id__eval_cases_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Add Eval Case Skills Skill Id Eval Cases Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Run Skill Eval (/docs/api/skills/skill_id/eval/run/post) ## POST /skills/{skill_id}/eval/run **Summary:** Run Skill Eval Run the Skill benchmark and return its verdict. Output cases grade generated behavior; should_not_trigger cases use the production semantic Skill router and become inconclusive when semantic evidence is unavailable rather than falling back to lexical matching. A passing routing negative is a safety gate and cannot by itself prove that a Skill helps on intended work. strict=true runs the output cases through the median-of-3 with/without gate; the streaming variant is /eval/stream. ### OpenAPI Operation ```json { "/skills/{skill_id}/eval/run": { "post": { "tags": [ "skills", "skills" ], "summary": "Run Skill Eval", "description": "Run the Skill benchmark and return its verdict. Output cases grade generated behavior; should_not_trigger cases use the production semantic Skill router and become inconclusive when semantic evidence is unavailable rather than falling back to lexical matching. A passing routing negative is a safety gate and cannot by itself prove that a Skill helps on intended work. strict=true runs the output cases through the median-of-3 with/without gate; the streaming variant is /eval/stream.", "operationId": "run_skill_eval_skills__skill_id__eval_run_post", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } }, { "name": "strict", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Strict" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Run Skill Eval Skills Skill Id Eval Run Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Stream Skill Eval (/docs/api/skills/skill_id/eval/stream/get) ## GET /skills/{skill_id}/eval/stream **Summary:** Stream Skill Eval Run the benchmark, streaming per-case progress (SSE): ``bootstrapping`` -> ``start`` -> ``case_started`` / ``case_done`` (per case) -> ``summary``. Feeds the 'Proven on' surface case by case. ``strict=true`` runs the Phase 2 gate. ### OpenAPI Operation ```json { "/skills/{skill_id}/eval/stream": { "get": { "tags": [ "skills", "skills" ], "summary": "Stream Skill Eval", "description": "Run the benchmark, streaming per-case progress (SSE): ``bootstrapping`` ->\n``start`` -> ``case_started`` / ``case_done`` (per case) -> ``summary``. Feeds\nthe 'Proven on' surface case by case. ``strict=true`` runs the Phase 2 gate.", "operationId": "stream_skill_eval_skills__skill_id__eval_stream_get", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } }, { "name": "strict", "in": "query", "required": false, "schema": { "type": "boolean", "default": false, "title": "Strict" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Get Source Image (/docs/api/sources/source_id/images/filename/get) ## GET /sources/{source_id}/images/{filename} **Summary:** Get Source Image Serve an extracted image from a source's images/ directory. ### OpenAPI Operation ```json { "/sources/{source_id}/images/{filename}": { "get": { "tags": [ "sources" ], "summary": "Get Source Image", "description": "Serve an extracted image from a source's images/ directory.", "operationId": "get_source_image_sources__source_id__images__filename__get", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string", "title": "Filename" } }, { "name": "space_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional isolation space guard", "title": "Space Id" }, "description": "Optional isolation space guard" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "title": "Response Get Source Image Sources Source Id Images Filename Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Remove Label From Source (/docs/api/sources/source_id/labels/label_id/delete) ## DELETE /sources/{source_id}/labels/{label_id} **Summary:** Remove Label From Source Remove a label from a source. ### OpenAPI Operation ```json { "/sources/{source_id}/labels/{label_id}": { "delete": { "tags": [ "sources" ], "summary": "Remove Label From Source", "description": "Remove a label from a source.", "operationId": "remove_label_from_source_sources__source_id__labels__label_id__delete", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "label_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Label Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Assign Label To Source (/docs/api/sources/source_id/labels/label_id/post) ## POST /sources/{source_id}/labels/{label_id} **Summary:** Assign Label To Source Assign a label to a source. ### OpenAPI Operation ```json { "/sources/{source_id}/labels/{label_id}": { "post": { "tags": [ "sources" ], "summary": "Assign Label To Source", "description": "Assign a label to a source.", "operationId": "assign_label_to_source_sources__source_id__labels__label_id__post", "parameters": [ { "name": "source_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Source Id" } }, { "name": "label_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Label Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Space Merge (/docs/api/spaces/space_ref/merge/preview/post) ## POST /spaces/{space_ref}/merge/preview **Summary:** Preview Space Merge Preview an exact, server-owned Space merge plan without changing data. Returns entity counts, Working Memory disposition, and any conflicts that must be resolved before apply. ### OpenAPI Operation ```json { "/spaces/{space_ref}/merge/preview": { "post": { "tags": [ "spaces" ], "summary": "Preview Space Merge", "description": "Preview an exact, server-owned Space merge plan without changing data. Returns entity counts, Working Memory disposition, and any conflicts that must be resolved before apply.", "operationId": "preview_space_merge_spaces__space_ref__merge_preview_post", "parameters": [ { "name": "space_ref", "in": "path", "required": true, "schema": { "type": "string", "title": "Space Ref" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SpaceMergeRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SpaceMergePlan" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Preview Bulk Move Threads (/docs/api/threads/bulk/move/preview/post) ## POST /threads/bulk/move/preview **Summary:** Preview Bulk Move Threads Preview a bounded bulk thread move before mutating data. ### OpenAPI Operation ```json { "/threads/bulk/move/preview": { "post": { "tags": [ "threads" ], "summary": "Preview Bulk Move Threads", "description": "Preview a bounded bulk thread move before mutating data.", "operationId": "preview_bulk_move_threads_threads_bulk_move_preview_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMoveThreadsRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkMoveThreadsPreviewResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Confirm and activate a recurring AI Now task (/docs/api/agent/ai-now/schedules/schedule_id/confirm/post) ## POST /agent/ai-now/schedules/{schedule_id}/confirm **Summary:** Confirm and activate a recurring AI Now task Activates only when the capability grant matches the current instruction and connector configuration. ### OpenAPI Operation ```json { "/agent/ai-now/schedules/{schedule_id}/confirm": { "post": { "tags": [ "ai-now" ], "summary": "Confirm and activate a recurring AI Now task", "description": "Activates only when the capability grant matches the current instruction and connector configuration.", "operationId": "openapi_confirm_schedule", "parameters": [ { "name": "schedule_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConfirmScheduleRequest" } } }, "required": true }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResponse" } } } }, "400": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } }, "409": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } } } } } } ``` # Resume a recurring AI Now task (/docs/api/agent/ai-now/schedules/schedule_id/resume/post) ## POST /agent/ai-now/schedules/{schedule_id}/resume **Summary:** Resume a recurring AI Now task Tasks with changed authority or uncertain external side effects must be confirmed instead. ### OpenAPI Operation ```json { "/agent/ai-now/schedules/{schedule_id}/resume": { "post": { "tags": [ "ai-now" ], "summary": "Resume a recurring AI Now task", "description": "Tasks with changed authority or uncertain external side effects must be confirmed instead.", "operationId": "openapi_resume_schedule", "parameters": [ { "name": "schedule_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResponse" } } } }, "400": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } }, "409": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleErrorResponse" } } } } } } } } ``` # Pause future recurring task occurrences (/docs/api/agent/ai-now/schedules/schedule_id/pause/post) ## POST /agent/ai-now/schedules/{schedule_id}/pause **Summary:** Pause future recurring task occurrences ### OpenAPI Operation ```json { "/agent/ai-now/schedules/{schedule_id}/pause": { "post": { "tags": [ "ai-now" ], "summary": "Pause future recurring task occurrences", "operationId": "openapi_pause_schedule", "parameters": [ { "name": "schedule_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResponse" } } } } } } } } ``` # List recurring task run history (/docs/api/agent/ai-now/schedules/schedule_id/runs/get) ## GET /agent/ai-now/schedules/{schedule_id}/runs **Summary:** List recurring task run history ### OpenAPI Operation ```json { "/agent/ai-now/schedules/{schedule_id}/runs": { "get": { "tags": [ "ai-now" ], "summary": "List recurring task run history", "operationId": "openapi_schedule_runs", "parameters": [ { "name": "schedule_id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "limit", "in": "path", "required": true, "schema": { "type": "integer", "minimum": 0 } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleRunsResponse" } } } } } } } } ``` # Get Ai Now Auto Approve (/docs/api/agent/ai-now/sessions/session_id/auto-approve/get) ## GET /agent/ai-now/sessions/{session_id}/auto-approve **Summary:** Get Ai Now Auto Approve ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/auto-approve": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Get Ai Now Auto Approve", "operationId": "get_ai_now_auto_approve_agent_ai_now_sessions__session_id__auto_approve_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Ai Now Auto Approve Agent Ai Now Sessions Session Id Auto Approve Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Set Ai Now Auto Approve (/docs/api/agent/ai-now/sessions/session_id/auto-approve/post) ## POST /agent/ai-now/sessions/{session_id}/auto-approve **Summary:** Set Ai Now Auto Approve ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/auto-approve": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Set Ai Now Auto Approve", "operationId": "set_ai_now_auto_approve_agent_ai_now_sessions__session_id__auto_approve_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowAutoApproveRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Set Ai Now Auto Approve Agent Ai Now Sessions Session Id Auto Approve Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Cancel Ai Now Prompt (/docs/api/agent/ai-now/sessions/session_id/cancel/post) ## POST /agent/ai-now/sessions/{session_id}/cancel **Summary:** Cancel Ai Now Prompt ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/cancel": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Cancel Ai Now Prompt", "operationId": "cancel_ai_now_prompt_agent_ai_now_sessions__session_id__cancel_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Cancel Ai Now Prompt Agent Ai Now Sessions Session Id Cancel Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Close Ai Now Session (/docs/api/agent/ai-now/sessions/session_id/close/post) ## POST /agent/ai-now/sessions/{session_id}/close **Summary:** Close Ai Now Session ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/close": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Close Ai Now Session", "operationId": "close_ai_now_session_agent_ai_now_sessions__session_id__close_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Close Ai Now Session Agent Ai Now Sessions Session Id Close Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Stream Ai Now Session Events (/docs/api/agent/ai-now/sessions/session_id/events/get) ## GET /agent/ai-now/sessions/{session_id}/events **Summary:** Stream Ai Now Session Events Attach to a live prompt stream without starting a new turn. ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/events": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Stream Ai Now Session Events", "description": "Attach to a live prompt stream without starting a new turn.", "operationId": "stream_ai_now_session_events_agent_ai_now_sessions__session_id__events_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Load Ai Now Messages (/docs/api/agent/ai-now/sessions/session_id/messages/get) ## GET /agent/ai-now/sessions/{session_id}/messages **Summary:** Load Ai Now Messages ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/messages": { "get": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Load Ai Now Messages", "operationId": "load_ai_now_messages_agent_ai_now_sessions__session_id__messages_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Load Ai Now Messages Agent Ai Now Sessions Session Id Messages Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Save Ai Now Messages (/docs/api/agent/ai-now/sessions/session_id/messages/post) ## POST /agent/ai-now/sessions/{session_id}/messages **Summary:** Save Ai Now Messages ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/messages": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Save Ai Now Messages", "operationId": "save_ai_now_messages_agent_ai_now_sessions__session_id__messages_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowMessagesRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Save Ai Now Messages Agent Ai Now Sessions Session Id Messages Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Prompt Ai Now Session (/docs/api/agent/ai-now/sessions/session_id/prompt/post) ## POST /agent/ai-now/sessions/{session_id}/prompt **Summary:** Prompt Ai Now Session Stream a prompt turn. Returns SSE events in the existing AI Now UI event contract. ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/prompt": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Prompt Ai Now Session", "description": "Stream a prompt turn.\n\nReturns SSE events in the existing AI Now UI event contract.", "operationId": "prompt_ai_now_session_agent_ai_now_sessions__session_id__prompt_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowPromptRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Resolve Timeline Review (/docs/api/agent/feed/events/event_id/resolve/post) ## POST /agent/feed/events/{event_id}/resolve **Summary:** Resolve Timeline Review Resolve one pending Memory review through the server's audited executor. Prefer review_action: the server validates the action against the stored event and performs any graph mutation before marking the event resolved. A failed action leaves the review pending. Replays are idempotent and return the persisted decision with already_resolved=true. ### OpenAPI Operation ```json { "/agent/feed/events/{event_id}/resolve": { "post": { "tags": [ "knowledge-agent" ], "summary": "Resolve Timeline Review", "description": "Resolve one pending Memory review through the server's audited executor. Prefer review_action: the server validates the action against the stored event and performs any graph mutation before marking the event resolved. A failed action leaves the review pending. Replays are idempotent and return the persisted decision with already_resolved=true.", "operationId": "resolve_event_agent_feed_events__event_id__resolve_post", "parameters": [ { "name": "event_id", "in": "path", "description": "Timeline review event id", "required": true, "schema": { "type": "string", "title": "Event Id" } }, { "name": "review_action", "in": "query", "description": "Semantic review action; JSON body is preferred", "required": false, "schema": { "$ref": "#/components/schemas/TimelineReviewAction" } }, { "name": "resolution", "in": "query", "description": "Resolution type: accepted|dismissed|merged", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Resolution type: accepted|dismissed|merged", "title": "Resolution", "type": "string" } }, { "name": "action", "in": "query", "description": "Graph action: delete_memory|keep_newer|keep_both", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Graph action: delete_memory|keep_newer|keep_both", "title": "Action", "type": "string" } }, { "name": "memory_ids", "in": "query", "description": "Comma-separated memory IDs to act on", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Comma-separated memory IDs to act on", "title": "Memory Ids", "type": "string" } }, { "name": "resolution_note", "in": "query", "description": "Optional human/agent note explaining a custom resolution", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional human/agent note explaining a custom resolution", "title": "Resolution Note", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/TimelineReviewResolveRequest" } ] } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimelineReviewResolveResponse" } } } }, "404": { "description": "Pending review not found" }, "409": { "description": "Review already resolved" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Retry Event (/docs/api/agent/feed/events/event_id/retry/post) ## POST /agent/feed/events/{event_id}/retry **Summary:** Retry Event Retry a failed background task. Re-submits the task with high priority. The original event is marked as retried. ### OpenAPI Operation ```json { "/agent/feed/events/{event_id}/retry": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "knowledge-agent" ], "summary": "Retry Event", "description": "Retry a failed background task.\n\nRe-submits the task with high priority. The original event is marked as retried.", "operationId": "retry_event_agent_feed_events__event_id__retry_post", "parameters": [ { "name": "event_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Event Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Retry Event Agent Feed Events Event Id Retry Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Set Feed Event Visibility (/docs/api/agent/feed/events/event_id/visibility/put) ## PUT /agent/feed/events/{event_id}/visibility **Summary:** Set Feed Event Visibility Hide or restore an immutable Timeline event for the current viewer. This changes personal presentation only; it does not delete the event or its evidence. ### OpenAPI Operation ```json { "/agent/feed/events/{event_id}/visibility": { "put": { "tags": [ "knowledge-agent" ], "summary": "Set Feed Event Visibility", "description": "Hide or restore an immutable Timeline event for the current viewer. This changes personal presentation only; it does not delete the event or its evidence.", "operationId": "openapi_set_feed_event_visibility", "parameters": [ { "name": "event_id", "in": "path", "description": "Timeline event id", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FeedEventVisibilityRequest" } } }, "required": true }, "responses": { "200": { "description": "Visibility updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FeedEventVisibilityResponse" } } } } } } } } ``` # Delete Eval Case (/docs/api/skills/skill_id/eval/cases/task_id/delete) ## DELETE /skills/{skill_id}/eval/cases/{task_id} **Summary:** Delete Eval Case Remove a case from the benchmark. ### OpenAPI Operation ```json { "/skills/{skill_id}/eval/cases/{task_id}": { "delete": { "tags": [ "skills", "skills" ], "summary": "Delete Eval Case", "description": "Remove a case from the benchmark.", "operationId": "delete_eval_case_skills__skill_id__eval_cases__task_id__delete", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Delete Eval Case Skills Skill Id Eval Cases Task Id Delete" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Update Eval Case (/docs/api/skills/skill_id/eval/cases/task_id/patch) ## PATCH /skills/{skill_id}/eval/cases/{task_id} **Summary:** Update Eval Case Edit one case: any of ``{task, checks, status}``. Approving a bootstrapped case is just ``{status: "green"}``. The task_id is preserved so a prior run's coverage mapping stays stable. ### OpenAPI Operation ```json { "/skills/{skill_id}/eval/cases/{task_id}": { "patch": { "tags": [ "skills", "skills" ], "summary": "Update Eval Case", "description": "Edit one case: any of ``{task, checks, status}``. Approving a bootstrapped\ncase is just ``{status: \"green\"}``. The task_id is preserved so a prior run's\ncoverage mapping stays stable.", "operationId": "update_eval_case_skills__skill_id__eval_cases__task_id__patch", "parameters": [ { "name": "skill_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Skill Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Update Eval Case Skills Skill Id Eval Cases Task Id Patch" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Read Ai Now Session File (/docs/api/agent/ai-now/sessions/session_id/files/read/post) ## POST /agent/ai-now/sessions/{session_id}/files/read **Summary:** Read Ai Now Session File Read a text artifact generated inside an AI Now session workdir. By-id-direct. The requested path must resolve inside the session working directory, so web/remote renderers can load generated cards without exposing arbitrary backend files. ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/files/read": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Read Ai Now Session File", "description": "Read a text artifact generated inside an AI Now session workdir.\n\nBy-id-direct. The requested path must resolve inside the session working\ndirectory, so web/remote renderers can load generated cards without\nexposing arbitrary backend files.", "operationId": "read_ai_now_session_file_agent_ai_now_sessions__session_id__files_read_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowFileReadRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Read Ai Now Session File Agent Ai Now Sessions Session Id Files Read Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ``` # Respond Ai Now Permission (/docs/api/agent/ai-now/sessions/session_id/permissions/request_id/post) ## POST /agent/ai-now/sessions/{session_id}/permissions/{request_id} **Summary:** Respond Ai Now Permission ### OpenAPI Operation ```json { "/agent/ai-now/sessions/{session_id}/permissions/{request_id}": { "post": { "tags": [ "knowledge-agent", "knowledge-agent", "ai-now" ], "summary": "Respond Ai Now Permission", "operationId": "respond_ai_now_permission_agent_ai_now_sessions__session_id__permissions__request_id__post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } }, { "name": "request_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Request Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AINowPermissionResponseRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Respond Ai Now Permission Agent Ai Now Sessions Session Id Permissions Request Id Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } } ```