DSH Plugins Marketplace

DSH Plugins

Plugins

/

Tools & Capabilities

/

dsh-plugin-codegraph-project

d

dsh-plugin-codegraph-project

Manifest valid

A CodeGraph tool scoped to the session's own indexed project, resolved from its workspace directory. One MCP server is launched through npx per project root and shared by every session working there;

hasBundlePatch

dsh-plugin-codegraph-project

English | 中文 | Changelog (中文)

npm CI license

Project-scoped CodeGraph for DeepSeek Harness. One CodeGraph MCP server per project, launched through npx, shared by every session working in that project, and visible only to sessions whose workspace actually has an index.

Summary

CodeGraph is excellent and its MCP server has one structural limitation: it resolves "the project" from its own process working directory. Every existing DSH integration therefore has to answer "which project?" globally — one managed MCP row with one cwd, rewritten and hot-reloaded as you move between projects.

This plugin answers it per session instead:

ConcernHow it is decided here
Which project is this session in?The session's own workspace directory (agent.session.header.cwd), resolved upward to the first .codegraph/ that holds a database — the same rule the CLI uses.
Which CodeGraph version?Your choice, in this row's configuration (and overridable in DSH settings).
How many servers?One per project root, reference-counted across every session in it. Two sessions in one repo share a single process; two repos get one each.
When may a session use the tools?Only once its project has a real index. A project with no .codegraph/ cannot call CodeGraph: the call is refused with a reason that states there is no index and gives the init command.
What if I index the project mid-session?The tools are injected into that running session within a few seconds. No restart, no new session.
What happens to the processes?They are launched through the harness's managed-subprocess service, so they belong to DSH: closing a session releases its share, and harness shutdown terminates what is left.

Install

DSH desktop app — install it from the app's own Plugins page (sidebar → Plugins): paste the package name to pull it from npm, or an absolute path to install a local checkout.

dsh-plugin-codegraph-project
# or a local checkout
/path/to/dsh-plugin-codegraph-project

The desktop profile belongs to the application — dsh plugin --profile desktop … is refused on purpose (profile "desktop" is managed exclusively by the Electron application) — so the Plugins page is the supported channel there. It installs the package, appends the bundle to the profile, and the row then appears in the Settings inventory. Host-side rows load immediately; a client-side surface needs one page refresh before it shows up.

CLI profiles (dsh web, TUI, headless) — install into that profile by name, or link a checkout:

# from npm
dsh plugin --profile web add dsh-plugin-codegraph-project

# or a local checkout
dsh plugin --profile web add link:/path/to/dsh-plugin-codegraph-project

Restart the profile afterwards (dsh web). The package ships a bundle patch, so it inserts its own row without any composition edit. Requires Node.js 20 or newer, together with a DSH deployment that provides @deepseek-ai/dsh-subprocess and @deepseek-ai/dsh-tools.

Both dependency lines are supported: on the 0.1.5 line a host settings namespace layers a user override over this row, while on the 0.2.0 line that namespace cannot be registered at all — 0.2.0 removed plugin-registered settings namespaces — so the row's config is the only settings channel (the plugin logs one line saying so; see Configuration).

Nothing else is needed: the server is fetched through npx into a plugin-owned cache, so there is no global CodeGraph install to manage.

Quick start

Indexing is your decision, exactly as upstream intends — this plugin never runs init by itself. For a project you want CodeGraph on:

npx -y @colbymchenry/codegraph@1.6.0 init -y -- /path/to/project

That creates .codegraph/codegraph.db (and nothing else in your source tree). Do it while a session is open and the session picks the tools up within a few seconds; do it before and the session simply starts with them. (This live pickup holds with the default pollMaxMs: 0; if you set a positive pollMaxMs, an index created after that limit needs the session reopened.)

codegraph uninit -- /path/to/project removes it again.

Configuration

Set these on the plugin row in your profile's cordis.patch.yml (or wherever the row lives):

- id: codegraph-project
  config:
    version: '1.6.0'
FieldDefaultMeaning
enabledtrueMaster switch. When false, nothing is spawned and no tool is registered.
version'1.6.0'The global CodeGraph version, passed to npx as @colbymchenry/codegraph@<version>. The default is the release this plugin was verified against.
packageSpec''Escape hatch: a complete package spec that wins over version (mirror, private registry, file: tarball). npx loads and executes whatever this points at, so a local file:/git+file: spec must be an absolute path.
cacheDir'' → ~/.dsh/codegraph/npm-cachenpm cache used by npx, created if missing. Set it if DSH's ~/.npm is not writable.
serverName'codegraph'MCP namespace; the model-facing name is mcp__<serverName>__codegraph_explore.
toolCallTimeoutMs60000Per-call timeout for one CodeGraph query.
pollIntervalMs3000How often an unindexed workspace is re-checked for a new index.
pollMaxMs0Stop watching an unindexed workspace after this long. 0 watches for the session's life.
telemetryunsetForward an explicit preference as CODEGRAPH_TELEMETRY (true → 1, false → 0). Unset injects nothing, so CodeGraph reads your own environment; the plugin never switches telemetry on or off on its own.
cliProbefalseRun npx … version once at startup and log the outcome; it also warms the npx cache. Off by default: it runs on every app start even when CodeGraph is never used, and with a cold cache it downloads the bundle while the first session's own launch races for the same cache. Opt in when the diagnostic is worth that cost.
usageGuidancetrueAdd a short CodeGraph section to the prompt of mounted sessions only.
diagnosticToolfalseRegister a codegraph_project_status tool reporting this session's state.
allowHomeProjectfalseServe an index that is the home directory (or the filesystem root). The plugin's equivalent of the CLI's --force; an index nested in a home directory is always served.

The same subset is exposed as the DSH settings namespace codegraph-project (version, packageSpec, cacheDir, toolCallTimeoutMs, allowHomeProject), where the user layer wins over the row configuration. Everything is validated before it is used: an invalid settings edit is refused and the row configuration stays in force. enabled is deliberately not part of that layer: the row configuration's enabled is honored by the loader before the plugin runs, while a settings-layer switch could only ever be read once at activation — it could not turn a running plugin off.

DSH 0.2.0 and later no longer serve plugin-registered settings namespaces. When a build still exposes a settings service but it has no register(), the plugin logs one line saying so instead of ignoring the layer silently. (If a build serves no settings service at all, neither the namespace nor that line appears.) Configure the row instead — the same keys, in the profile's cordis.patch.yml, which is the channel 0.2.0 uses for every plugin's settings.

Changing the version

version applies to the next project connection. Sessions already connected keep the version they started with — swapping the server under a live session would remove tools that are in use. Reopen the session (or the project's last session) to move it to the new version.

What the model sees

One tool per project connection, named exactly as the MCP bridge would name it:

mcp__codegraph__codegraph_explore

CodeGraph 1.6.0 advertises only codegraph_explore by default. To expose more of its tools, set its own allowlist in the environment; this plugin passes through whatever the server advertises and never renames or filters it:

# Child environments are scrubbed and rebuilt from the harness environment, so export it
# where the harness is started (its own row config has no `env` field):
export CODEGRAPH_MCP_TOOLS=explore,node,search,callers

When a session is mounted, usageGuidance also injects a short section naming the project root and the available tools, and tells the model to reach for codegraph_explore instead of a grep/read loop. A session without an index gets no such section.

How it works

  • No index, no CodeGraph. The gate is a *.db inside .codegraph/, not the directory's existence: CodeGraph keeps runtime files (daemon.sock, codegraph.lock, telemetry*.json) in ~/.codegraph, and a directory holding only those is not a project. Before any project is live the tool is not registered at all; once one is, a session whose own workspace has no index still cannot call it — the guard refuses, and the refusal names the workspace and the exact init command.
  • The home directory and the filesystem root are never projects, even when they contain a real index. ~/.codegraph is both the CLI's runtime directory and the place codegraph init --force -- ~ writes its database, so without this rule a single ~/.codegraph/codegraph.db would become the project of every session under $HOME — and the tool would be offered for a codebase nobody indexed. This mirrors the CLI, which refuses to initialize the home directory without --force ("it looks like your home directory"). A real project nested under $HOME (~/work/api) still gets served by its own index. Set allowHomeProject: true for the plugin's equivalent of that --force.
  • One request may precede the connection. A session's tool list is assembled when a model request starts, and connecting a project takes about two seconds (faster when the optional cliProbe has warmed the cache). In an interactive session that means the tool is there before you have finished typing; a session driven programmatically may need to wait for the mount before its first prompt. The plugin logs one line per project mount naming the pid and tools.
  • Upward resolution. A monorepo session in packages/app is served by the repository root's index, and the server runs with that root as its cwd.
  • One process per project. The second session in the same project attaches to the existing server; the process is stopped when the last session releases it.
  • Live injection. An index that appears later is detected by polling the workspace and the tools are registered into the live session's scope.
  • Connection loss heals. If the server dies, the next tool call transparently reconnects; a failure during that reconnect is reported as a tool error rather than a silent success.
  • Cold start. The first use of a version downloads the platform bundle (tens of megabytes). Sessions are never blocked by it — the tools appear when the connection is ready. Set cliProbe: true to warm the same cache at startup; it is off by default so a fresh app start does not pay for (or race the first session over) a download nobody asked for.

Per-session tool lists (a platform limitation)

This plugin registers its tool definitions on the root tool registry and enforces per-session access with a guard, rather than registering per session. That is deliberate, and it is the honest shape of the constraint: DSH's tool registry accepts agent-scoped registrations, but the model's tool list is assembled with scope: agent — the Agent object, not the scope key the registry keys its layers by — so an agent-scoped definition never reaches the model. Measured, in the shipped 0.1.5-rc.2: with a tool registered through agent.ctx, the session's own schemas(scopeKey) view contains it while systemPrompt.assemble({ agent, scope: agent }) — the call the agent loop makes — returns an empty list. restrict() is evaluated against the scope key as well, so it cannot hide a tool per session either.

What that means in practice: while at least one project is live, the CodeGraph tools are listed for every session in the process, and the guard is what keeps a session without an index from using them. If DSH later assembles the model's tool list from the agent's scope key, the registration can move back to agent.ctx and the list becomes exactly per session.

Process ownership (no orphans)

Every CodeGraph child is spawned through ctx.subprocess (the harness's managed-subprocess service) rather than a bare child_process, which buys four layers of cleanup:

  1. Closing a project sends SIGTERM and then SIGKILL after a grace period, and waits for the process group to be gone.
  2. The plugin's own teardown (unload, reload, profile shutdown) closes every live project.
  3. Disposing the subprocess service terminates and awaits every managed process — this is what runs during harness shutdown.
  4. CODEGRAPH_HOST_PPID is set to the harness pid, so CodeGraph's own orphan watchdog exits the server even if the harness is killed without any chance to clean up.

Closing stdin is tried first, because CodeGraph exits within milliseconds of stdin EOF; the signals are the backstop for a wedged server.

Diagnostics

SymptomCause and fix
No codegraph tool, log says not-a-project.codegraph/ exists without a database. Run the init command above.
No codegraph tool, log says missingNo .codegraph/ at or above the workspace, or the walk reached the repository root. Index the project.
Log: could not resolve an npm launchernpx is not on the harness's PATH. Start DSH from a shell that has Node, or set packageSpec to a spec npx can still reach.
Log: could not create the npx cache directorycacheDir is not writable. Point it somewhere writable.
Log: a manifest/download errornpm could not fetch the bundle (offline, mirror without platform packages, private registry). Set packageSpec to a reachable spec.
Log: cannot read <root>/.codegraphA .codegraph entry exists but is not a readable directory: EACCES/EIO on it, a broken symlink (ENOENT), a symlink to a non-directory, or a plain file (ENOTDIR). The plugin stops the upward walk rather than serving an ancestor project's index. Fix the permissions or the link and the watcher picks it up.
Log: could not register mcp__<serverName>__…Usually another MCP server already owns that namespace (an invalid serverName can also fail registration), so this plugin would silently lose all its tools. Give the codegraph-project row a distinct serverName (or remove the conflicting server) and restart the session.
Tool call: "the MCP server is not responding"The server crashed and the reconnect attempt failed. The log carries the captured stderr tail.
Session still on an old versionSessions keep the version they connected with. Reopen the session.
A private registry needs credentialsThe harness scrubs credentials out of child environments. Use a cache directory pre-populated with the package, or a file:/tarball packageSpec.

Set diagnosticTool: true to get a codegraph_project_status tool that reports the resolved project root, why tools are or are not present, the live server pid per project, and the exact init command for the current version.

Development

npm test          # unit + integration, all against a stub MCP server (no network)
npm run lint      # node --check on every source file

# Manual checks against the REAL CodeGraph server (need a warm npx cache or network):
node scripts/real-codegraph-e2e.mjs --version 1.6.0
                  # share one process across sessions, index a project mid-flight, reap it
node scripts/stdio-probe.mjs /path/to/indexed/project 1.6.0
                  # raw NDJSON framing, concurrent calls, stdin-EOF teardown

The runtime lives in lib/: locate.js (project index resolution), config.js (row options and the settings namespace), transport.js (managed stdio transport), pool.js (per-project sharing and tool sync), agent-tools.js (tool registration and the session guard), poll.js (index watcher), and index.js (plugin wiring).

The test suite substitutes a stub MCP server for the real one, so it is deterministic and offline; scripts/real-codegraph-e2e.mjs is the script that verifies the real protocol, a real query, process sharing, and process reaping, and needs a warm npx cache or network.

CI runs npm run lint and npm test on Node.js 20, 22, and 24.

Releasing

  1. Add a ## [<version>] entry to CHANGELOG.md (written in Chinese). The publish workflow refuses to ship a version the changelog does not document.
  2. npm version <patch|minor|major> commits the bump and creates the tag; push the commit and the tag.
  3. .github/workflows/publish.yml then runs the tests, checks that the tag matches package.json, checks the changelog entry, and publishes through npm trusted publishing (OIDC) with a provenance attestation, so no long-lived token is stored in the repository.

The very first release is manual

The one precondition is a working npm login for the account that owns the package: trusted publishing authorizes the workflow, but nothing can create the package until a human with npm credentials has published it once. npm whoami must answer with the account's name; a token that has expired makes that fail with 401 Unauthorized while every read-only npm command still works, which is worth checking before assuming the package name is the problem.

Trusted publishing cannot create a package that does not exist yet — the trusted-publisher entry lives on the package's own settings page, so the package has to exist before the workflow can be authorized to publish it. The first version is therefore published once by hand, from a clean main checkout:

# 1. publish 0.1.0 from the laptop. `--provenance=false` is required: provenance is generated
#    by CI, and `npm publish` refuses to attest from a local environment.
npm publish --provenance=false --access public

# 2. register the workflow as a trusted publisher (npm 11.15+; prompts for 2FA).
#    The four values must match the workflow exactly.
npm trust github dsh-plugin-codegraph-project \
  --file publish.yml \
  --repo troytse/dsh-plugin-codegraph-project \
  --allow-publish -y

Every later release is fully automated by the workflow, with provenance. If a publish run fails after the tag was pushed, fix the commit, move the tag, and push it again:

git tag -f v<version> && git push --force origin refs/tags/v<version>

If GitHub does not start a run for a tag-object-only update, delete and recreate the remote tag (git push origin :refs/tags/v<version> then push it again).

Run these from a normal terminal. A sandboxed shell that denies writes outside the project (such as an agent session with workspace-write file policy) makes npm login and npm publish fail with EPERM on ~/.npm/_cacache — that is the file policy refusing the write, not a broken npm cache, and no chown is needed.

License

MIT

Comments

Loading…

Similar plugins

dsh-codegraph

Indexes the current workspace into a relation graph and exposes one agent tool, codegraph_explore, for reachability, callers, and impact, plus a Web sidebar graph pane.

Tools & CapabilitiesManifest valid

★ 0

dsh plugin --profile web add @meteor-system/dsh-codegraph

by JohnXu22786

Code knowledge graph plugin for agent harnesses (dsh): indexes symbols, call sites and imports into SQLite, answers call/dependency questions via CLI or stdio MCP tool server

Tools & CapabilitiesDevelopment & InfrastructureManifest valid

★ 3

↓ 70/wk

MIT

Python

Sep 29, 2026

dsh plugin --profile web add dsh-codegraph

by jiangzhenguo

DSH bundle that registers 13 native codegraph_* tools wrapping the codegraph CLI, so agents bootstrap, maintain, and query a pre-indexed code knowledge graph (symbol query, explore, node trail, caller

Tools & CapabilitiesManifest valid

★ 11

↓ 105/wk

MIT

JavaScript

Sep 30, 2026

dsh plugin --profile web add dsh-codegraph

Multi-workspace manager: bind a docs anchor plus ordered code-project repositories into one session, injecting their absolute paths, a recursive file index, a server/client endpoint index and optional

UI & ExperienceManifest valid

★ 1

NOASSERTION

TypeScript

dsh plugin --profile web add dsh-workspace-combiner

by lifeopsgo

Adds session, project, and global controls in the DSH WebUI for skills, MCP servers, tools, prompt injections, approval escalation, and safety guards; enforcement is scoped to the current agent.

Tools & CapabilitiesSecurity & AuditManifest valid

★ 3

MIT

TypeScript

Sep 29, 2026

dsh plugin --profile web add dsh-capability-toggle-plugin

by moon16u

A pouch of practical micro-plugins for DSH: per-turn wall-clock time injection, safe restart, session ID header badge, Tavily search provider, configurable LLM request-header routes, and an MCP server

Tools & CapabilitiesModels & ProvidersManifest valid

★ 1

↓ 70/wk

MIT

JavaScript

Sep 10, 2026

dsh plugin --profile web add @moon16u/dsh-pouch