Bundle
dsh-claude-code-local
Local Claude Code provider for DeepSeek Harness: a configurable 'claude-code' LLM route that runs your locally installed `claude` CLI and streams its output into the harness
- Source
- NGdust
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 13 days ago
Readme
# dsh-claude-code-local
[](https://www.npmjs.com/package/dsh-claude-code-local)
[](LICENSE)
Use your **locally installed Claude Code** as an LLM provider in [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH).
The plugin registers a `claude-code` provider route. Each model request spawns your local `claude` CLI in streaming JSON mode; Claude Code runs its own agentic loop (its built-in tools, permission mode, max turns) and the streamed text is translated into the harness chat in real time.
- Pick the provider in the composer's model selector — group **Claude Code (local)**.
- No API key in DSH: the CLI uses its own stored credentials (`~/.claude`, `ANTHROPIC_API_KEY`, OAuth, Bedrock/Vertex, ...).
- Your existing Claude Code setup keeps working: skills, commands, MCP servers, permission modes.
- macOS/Linux only.
## Requirements
- DeepSeek Harness `0.1.0-rc.7` or newer (web, headless, or the DSH Desktop app).
- The Claude Code CLI installed and authenticated:
```sh
claude --version
```
## Installation
### Option 1: DSH Desktop community market
1. Open the **Market** page in DSH Desktop.
2. **Sources** → add a source with this manifest URL:
```
https://raw.githubusercontent.com/NGdust/dsh-claude-code-local/main/catalog/manifest.json
```
3. Select the source, open **Discover**, find **Claude Code (local)**, and install it. Restart the app when prompted.
### Option 2: dsh CLI
```sh
dsh plugin --profile web add dsh-claude-code-local
dsh --profile web
```
For a headless profile, replace `web` with the profile name. Restart the server after installing.
### Option 3: manual (offline / air-gapped)
Copy this package into the profile module farm and register the plugin row in the profile patch layer:
```sh
cp -R dsh-claude-code-local ~/.dsh/profiles/node_modules/
```
Then add to `~/.dsh/profiles/web/cordis.patch.yml`:
```yaml
- insert:
- id: llm-claude-code
name: dsh-claude-code-local
```
A running web app picks the row up without a restart (the patch is hot-watched); the DSH Desktop app applies it on the next launch.
## Verify
Open the composer's model selector (or the Models page) and look for the **Claude Code (local)** group with the model lineup (`claude-opus-5`, `claude-sonnet-5`, `claude-haiku-4-5`, `claude-fable-5`). Select any of them and send a message — the reply streams from your local CLI.
## Configuration
Settings live in the `llm-claude-code:` section of `$DSH_HOME/settings.yaml` (default `~/.dsh/settings.yaml`) and are hot-reloaded — no restart needed:
```yaml
llm-claude-code:
permissionMode: auto # auto | acceptEdits | bypassPermissions | manual | dontAsk | plan
maxTurns: 10 # internal agent steps per request
streamIdleTimeoutMs: 300000 # kill the request if the CLI is silent this long (ms)
```
### All options
| Key | Default | Description |
| --- | --- | --- |
| `executable` | `claude` | Path or name of the Claude Code CLI. Set an absolute path (see `which claude`) if the CLI is not on the harness PATH. |
| `model` | `""` | Model passed to `claude --model`. Empty: use the picker selection. `default`: omit the flag and let the CLI pick. |
| `permissionMode` | `auto` | Claude Code permission mode. `bypassPermissions` is dangerous. |
| `allowedTools` | `[]` | `claude --allowedTools` list, e.g. `["Bash(git *)", "Read"]`. |
| `disallowedTools` | `[]` | `claude --disallowedTools` list. |
| `tools` | unset | Raw `claude --tools` override. `""`: disable Claude's built-in tools (pure text). `default`: restore them. |
| `maxTurns` | `10` | Max internal agent steps per request. |
| `appendSystemPrompt` | `true` | Append the harness system prompt to Claude Code's own. |
| `cwd` | unset | Working directory for the CLI; unset inherits the harness cwd. |
| `noSessionPersistence` | `true` | Don't write Claude Code session files to disk. |
| `extraArgs` | `[]` | Extra raw CLI arguments (advanced). |
| `streamIdleTimeoutMs` | `300000` | Idle watchdog between streamed events, in milliseconds. |
| `models` | current lineup | Advisory catalog shown in the picker (see below). |
| `retryPolicy` | harness default | LLM retry policy. |
### Model catalog
The `models` list controls what the picker offers. The default lineup is what the installed CLI resolves today (`opus` → `claude-opus-5`, `sonnet` → `claude-sonnet-5`, `haiku` → `claude-haiku-4-5`, `fable` → `claude-fable-5`). Override it to pin or extend the list:
```yaml
llm-claude-code:
models:
- id: claude-opus-5
name: Claude Opus 5
contextWindow: 200000
- id: claude-sonnet-5
name: Claude Sonnet 5
contextWindow: 200000
- id: claude-haiku-4-5
name: Claude Haiku 4.5
contextWindow: 200000
- id: claude-fable-5
name: Claude Fable 5
contextWindow: 200000
```
The list is advisory: the CLI decides which models your account can actually serve, and a model that is not in the list is still served if it is selected.
### Make it the default provider
New sessions default to the profile's `agent-default-model` (DeepSeek). To default every new session to local Claude Code:
```yaml
agent-default-model:
provider: claude-code
model: claude-sonnet-5
```
Or just pick the provider per session with the composer's model selector.
### Permission modes
- `auto` (default): Claude Code's auto-mode classifier — safe actions run, risky ones are denied in non-interactive mode.
- `acceptEdits`: file edits are auto-approved.
- `bypassPermissions`: **dangerous** — Claude Code can do anything its tools allow (equivalent to `--dangerously-skip-permissions`).
- `manual` / `dontAsk` / `plan`: see the Claude Code CLI docs.
## Troubleshooting
| Symptom | Fix |
| --- | --- |
| Provider not in the model picker | The plugin is not loaded. Re-check the install step; restart the server (DSH Desktop applies changes on the next launch). |
| `spawn claude ENOENT` / `claude: command not found` | Set `executable` to the full path: `llm-claude-code: { executable: /path/to/claude }` (see `which claude`). |
| Auth / account errors on first message | Log in once: run `claude` interactively, or check `~/.claude` / `ANTHROPIC_API_KEY`. The plugin never asks DSH for an API key. |
| Long agentic runs get cut off mid-stream | Raise `streamIdleTimeoutMs` (e.g. `600000`) — the request is aborted when the CLI stays silent longer than the timeout. |
| File edits are blocked | Use `permissionMode: acceptEdits`. Note: DSH's sandbox does not gate Claude Code's actions — the CLI's permission mode does. |
| Nothing happens on Windows | Not supported. Use macOS, Linux, or WSL. |
## How it works
1. `apply()` registers the `claude-code` route with a `ClaudeCodeAdapter` and declares it in the configurable-provider directory, so the model picker and Models page know it.
2. Each request spawns `claude -p --output-format stream-json --include-partial-messages --verbose <flags>` with the rendered conversation piped over stdin (long histories never hit OS argument-length limits).
3. `stream_event`/`result` JSON events are translated into harness chunks: text deltas → chat text, thinking deltas → reasoning, tool use → a liveness line (`Claude Code tool: ...`), usage → token counts.
4. The child is killed on caller abort or idle timeout.
## Limitations
- Each request is a fresh stateless CLI invocation; the full conversation is re-rendered every turn (no cross-request prompt-cache reuse).
- The harness's own tools are not used through this provider: Claude Code owns its loop, so DSH's sandbox/permission service does not gate Claude Code's actions — the CLI's `permissionMode` does.
- `maxTokens` / `temperature` / `stop` from the harness request are ignored; the CLI controls sampling.
## Contributing
Found a bug or missing a feature? Open an issue or a pull request in this repository.
## License
MIT
Install
dsh plugin --profile web add github:NGdust/dsh-claude-code-local
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-claude-code-local from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.