* fix(cc-plugin): drop --scope from plugin commands, add legacy-mode install path
- Removed `--scope user` from `claude plugin marketplace add` and
`claude plugin install` everywhere (install.sh + READMEs + docs).
These commands default to user scope already, and older 2.0.x builds
(e.g. 2.0.76) reject the flag outright. Kept `--scope user` on
`claude mcp add` because its default is `local` (current-project only)
and the flag has been supported since MCP first shipped.
- install.sh now probes for `claude plugin` subcommand existence rather
than parsing version strings. If absent, prompts the user to enable
legacy compatibility mode, which wires the same functionality through
`claude mcp add` + a JSON-merge into ~/.claude/settings.json. The
modern path also falls back to legacy on plugin-install failure.
- Legacy mode keeps `${VAR}` placeholders single-quoted so Claude Code
expands them at MCP launch time (the rc wrapper injects the values),
rather than letting the shell expand them to empty strings at install
time. Settings.json is backed up with a timestamp before the merge,
and the merged JSON is validated before overwriting.
- Documented the legacy path in both READMEs and the agent-integration
docs (EN + CN), with a pointer from the docs back to the README.
* fix(cc-plugin): highlight 'source rc' final step in installer
The script runs in a subshell (bash <(curl ...)), so it can't source
the rc back into the user's interactive shell. Make the manual
follow-up step visually unmissable with bold + color, and explain why
auto-source isn't possible in a comment.
* fix(cc-plugin): address copilot review on legacy install path
- mktemp + XXXXXX for tmp files (was $$ — predictable, symlink-race
on shared /tmp).
- Replace sed substitution with jq walk + gsub. $plugin_dir comes from
OPENVIKING_REPO_DIR (user-configurable) and may contain &, |, \
which would corrupt sed. jq with --arg is byte-safe.
- Wrap the merge jq in an explicit if-branch so 'set -e' can't kill the
script before cleanup runs. Drop the now-redundant post-validation
jq -e (a successful jq run already guarantees valid JSON output).
- README EN/CN: clarify that the 'plugin enable --scope user' tip only
applies on newer builds that accept --scope, removing the apparent
contradiction with the surrounding 'older builds reject --scope'.
## feat(cc-memory-plugin): implement persistent sessions, native MCP, and async write path
This update transitions the Claude Code memory plugin from a one-shot capture model to a persistent, per-session integration with OpenViking. It introduces native MCP support directly from the FastAPI server, significantly expands the tool surface, and optimizes performance via detached async write hooks.
### Core Engineering & Capabilities
* **Persistent Sessions:** Reworked lifecycle hooks (SessionStart, PreCompact, SessionEnd) to maintain stable session IDs across the entire Claude Code conversation.
* **Native MCP Endpoint:** Replaced the Node.js MCP subprocess with a native `/mcp` endpoint on the OpenViking server.
* Expands to 9 specialized tools: `search`, `read`, `list`, `store`, `add_resource`, `forget`, `grep`, `glob`, and `health`.
* Propagates identity headers (`X-OpenViking-Account`, `X-OpenViking-User`) through the MCP transport.
* **Async Write Path:** Introduced a detached worker pattern for `auto-capture`, `session-end`, and `subagent-stop` hooks. Claude Code no longer blocks on network round-trips to the OpenViking server.
* **Multi-Source Recall:** Enhanced `auto-recall` to search across memories, resources, and skills with URI-deduplication and score-based filtering.
### Configuration & Integration
* **Unified Auth:** Standardized on `Authorization: Bearer` tokens.
* **Config Resolution:** Established a clear priority chain: **Env Vars → ovcli.conf → ov.conf → Defaults**.
* Added comprehensive environment variable coverage for all tuning fields (e.g., `OPENVIKING_SCORE_THRESHOLD`, `OPENVIKING_COMMIT_TOKEN_THRESHOLD`).
* **One-Line Installer:** Added an interactive bash installer (`install.sh`) that handles dependencies, `ovcli.conf` setup, and marketplace registration, with support for both self-hosted and Volcengine Cloud options.
### Bug Fixes & Refinement
* **Self-Injection Prevention:** Implemented block-stripping logic in `auto-capture` to prevent the plugin from re-storing its own injected context blocks into the memory pool.
* **Session Bypass:** Fixed a bug where `session-start` and `subagent-start` ignored bypass patterns.
* **Subagent Isolation:** Implemented `SubagentStart/Stop` hooks with isolated session IDs and specialized agent headers for memory segregation.
* **Docs & Maintenance:** Bumped version to `0.2.2`; added comprehensive agent integration guides; fixed Vue interpolation and markdown fence issues in documentation.
The default host (127.0.0.1) made the server unreachable from outside
the container. Now the entrypoint passes --host 0.0.0.0, which requires
root_api_key in ov.conf (enforced by existing validate_server_config).
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "Official OAuth Support (Planned)" subsection describing three
approaches under evaluation: OTP authorization, Console quick-auth,
and third-party IdP login
- Reframe MCP-Key2OAuth as a community workaround with strengthened
disclaimer (no security/availability guarantee)
- Replace hosted demo URL with self-deployment instruction
- Both zh and en docs updated symmetrically
* docs: add CHANGELOG.md generated from GitHub Releases
- Import all 32 releases into CHANGELOG.md
- Add GitHub Action to auto-update CHANGELOG on each new release
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: generate changelog from GitHub Releases with auto-update Action
- Replace placeholder changelog in docs/en and docs/zh with all 32 releases
- Remove root CHANGELOG.md (changelogs live in docs site)
- Add GitHub Action that on each release:
- Uses Claude API to categorize changes into Keep a Changelog format
- Generates both EN and ZH entries
- Incrementally prepends to both changelog files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: compact changelogs and remove auto-update workflow
- Remove changelog.yml GitHub Action (per user request)
- Compact EN and ZH changelogs: strip PR links, authors, contributor
sections, code examples; keep gist only (<50 lines per release)
- ZH uses Chinese summaries where available, EN uses English summaries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: fix code-doc inconsistencies in English documentation
- Fix default server host: docs claimed 0.0.0.0 but code defaults to 127.0.0.1
- Fix GLOBAL_SEARCH_TOPK: docs said 3 but code uses 10
- Fix VLM model name: docs had doubao-seed-2-0-code-preview-260215, code uses doubao-seed-2-0-pro-260215
- Fix metrics file reference: pointed to nonexistent .vscode/.workdir/metric/METRIC_res.md
- Fix build prerequisite: Go replaced by Rust/Cargo (no .go files remain in repo)
- Fix embedding provider list: README listed 7 providers, code supports 13
- Fix CLI command inconsistency: two ov commands in sessions doc should be openviking
- Add missing session archive endpoint to API overview table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: revert ov→openviking CLI rename in sessions doc
Both `ov` and `openviking` are registered entry points for the same
Rust CLI binary (pyproject.toml). The short `ov` alias is intentional
and valid — reverting the previous rename.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: sync same fixes to Chinese docs, README_CN, and README_JA
Apply the same consistency fixes from the English docs to:
- docs/zh/ (Chinese documentation)
- README_CN.md (Chinese README)
- README_JA.md (Japanese README)
Changes mirror the English fixes: server host default, GLOBAL_SEARCH_TOPK,
VLM model name, build prerequisites (Go→Rust), embedding provider list,
metrics file reference, and missing session archive endpoint.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(server): add native MCP endpoint at /mcp
Serve 5 MCP tools (search, read, store, forget, health) directly from
the OV FastAPI server via streamable HTTP transport. This eliminates the
need for the Node.js MCP subprocess — the plugin's .mcp.json now points
to the server URL instead of spawning a process.
Identity headers (X-OpenViking-Account/User/Agent) are propagated to
service-layer calls via contextvars ASGI middleware.
* fix(mcp): disable DNS rebinding protection for reverse proxy compatibility
MCP SDK auto-enables host validation for localhost, rejecting requests
with external Host headers (e.g. from Cloudflare/Nginx reverse proxy).
* fix(mcp): reuse auth.resolve_identity for MCP endpoint authentication
MCP endpoint previously had no authentication — requests fell through
with default/default identity. Now delegates to the same resolve_identity
used by all REST routes, so auth_mode, API key validation, and identity
resolution are handled identically.
* fix(mcp): fix import path for TextPart in store tool
openviking.session.parts does not exist; the correct module is
openviking.message.part.
* fix(mcp): store tool now creates a new session and commits immediately
Each store call creates a unique session, adds the message, and commits
right away so memories are extracted and searchable without waiting for
a token threshold.
* chore: add mcp>=1.27.0 dependency for native MCP endpoint
* fix(mcp): align search/forget tools with REST API, fix forget crash
- Remove SEARCH_TARGETS and per-scope loop; use single
service.search.find(target_uri="") call matching REST API behavior
- Fix forget crash: FSService has no delete(), use rm() instead
- Replace fragile _is_memory_uri() substring check with ContextType
- search tool: replace scope param with target_uri for direct passthrough
- Work directly with FindResult/MatchedContext objects instead of
dict-munging via to_dict()
* fix(mcp): fail-closed on missing identity, remove unused Role import
- _get_ctx() now raises UnauthenticatedError instead of defaulting to
ROOT when identity contextvar is not set
- Remove unused Role import
- Clean up comments in create_mcp_app
* test(mcp): add unit tests for MCP endpoint tools
17 tests covering all 5 MCP tools and identity propagation:
- _get_ctx: returns context when set, raises UnauthenticatedError when not
- health: healthy/unhealthy responses
- search: no results, with resource, with target_uri
- read: nonexistent URI, directory listing, batch reads
- store: user and assistant roles
- forget: input validation, non-memory guard, URI deletion, query fallback
- Route registration: /mcp route exists in app
* docs(mcp): update integration guide with verified platforms and correct tools
- Add verified platforms table (Claude Code, ChatGPT/Codex, Claude.ai,
Manus, Trae)
- Document authentication (X-Api-Key / Bearer token)
- Add Claude.ai OAuth proxy (MCP-Key2OAuth) instructions
- Update tool table to match actual implementation (search, read, store,
forget, health) — remove stale tool names
- Reorganize client config: generic first, then platform-specific
* feat(mcp): expand to 7 tools aligned with vikingbot, split read/list
Align MCP tool surface with vikingbot/agent/tools/ov_file.py:
- Split read/list: read is file-only with semaphore(10) concurrency;
list is directory-only with recursive support
- store: accept batch messages[] (was single text), matching
VikingMemoryCommitTool
- search: add min_score parameter (default 0.35), matching
VikingSearchTool
- add_resource: new tool for adding files/URLs to resources
- Use @mcp.tool(name="list") to avoid shadowing Python builtin
7 tools: search, read, list, store, add_resource, forget, health
* feat(mcp): add grep and glob tools, update docs to 9 tools
Add grep (multi-pattern regex search) and glob (file pattern matching)
MCP tools to align with VikingBot's full tool surface. Update EN/ZH
integration docs to reflect all 9 tools with correct parameters.
* fix(mcp): store schema, forget safety, remove memories-only restriction
- store: use Pydantic StoreMessage model so MCP schema includes
required role/content field definitions (was bare dict[str, str])
- forget: remove query parameter entirely — deletion requires exact URI,
use search tool first to find candidates
- forget: remove /memories/ path restriction, allow deleting any URI
* docs(mcp): update forget tool description — exact URI only, no query
* fix(mcp): rename list_dir to ls, add forget safeguard, use Bearer in docs
- Rename list_dir → ls (MCP tool name stays "list") to avoid confusion
with "only lists directories"
- Add safeguard to forget tool description: irreversible, requires user
confirmation
- Docs: use Authorization: Bearer in all examples (standard, consistent
with OAuth proxy flow)
- Fix ruff format on mcp_endpoint.py and test_mcp_endpoint.py
* docs(config): document encryption.api_key_hashing.enabled in EN reference
* docs(config): document encryption.api_key_hashing.enabled in ZH reference
* docs(api): add memory_diff.json to archive directory tree (EN)
Document the memory_diff.json artifact added to history/archive_N/ in #1710 (chenjw). The file is written by Phase 2 memory extraction whenever the update produces non-empty adds/updates/deletes (see openviking/session/compressor_v2.py guard 'if archive_uri and result.has_changes()').
* docs(api): add memory_diff.json to archive directory tree (ZH)
Mirror EN counterpart for #1710 memory_diff.json artifact, ZH 全角标点对齐既有 'Phase 2 写入(后台)' convention.
* fix(docker): collapse persistent state into /app/.openviking
The Docker image previously crashed on startup when ov.conf was missing,
making it impossible to docker exec in to fix the configuration. This
also forced two separate volume mounts (config + data), which is awkward
on managed platforms that only offer one persistent volume.
Changes:
- Set HOME=/app and put all persistent state under /app/.openviking, so
the in-container layout mirrors the host's ~/.openviking.
- docker-compose.yml mounts ~/.openviking -> /app/.openviking as a single
volume that captures ov.conf, ovcli.conf, and the workspace.
- Entrypoint bootstraps ov.conf from OPENVIKING_CONF_CONTENT when set;
otherwise prints a fix-it message and sleeps until the file exists, so
the container stays up for docker exec.
- openviking-server init honors OPENVIKING_CONFIG_FILE and derives the
workspace from its parent directory, so a single env var places init
output where the server will read it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(docker): describe single-mount layout and no-mount fallbacks
Switch all Docker examples to the new single-volume layout
(~/.openviking -> /app/.openviking) and document the two ways to
configure when bind mounts aren't available: pass the full ov.conf JSON
through OPENVIKING_CONF_CONTENT, or docker exec in and run
openviking-server init while the entrypoint waits for the file.
Updates docs/{en,zh}/getting-started/02-quickstart.md and
docs/{en,zh}/guides/03-deployment.md, including the macOS socat block.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: link
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(docs): add Copy Markdown button, per-page llms.txt, and llms-full.txt
- Add "Copy markdown" dropdown button (top-right of each doc page) with
Open in GitHub / ChatGPT / Claude actions
- Generate per-page llms.txt at /{page-path}/llms.txt serving raw Markdown,
plus site-wide /llms.txt index and /llms-full.txt full-content dump
- Add Vite dev middleware so per-page llms.txt works in dev mode without a build step
- Add llms.txt footer link on each doc page pointing to the current page's llms.txt
- Fix dark mode background: replace green-tinted colors with neutral dark palette
* fix(docs): use llms.txt URL pattern for Open in ChatGPT/Claude links
* ci: add manual docs deployment workflow
* Revert "ci: add manual docs deployment workflow"
This reverts commit 6123acaf26.