dsh-use-codex 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +400 -0
- package/README.md +404 -2
- package/SECURITY.md +30 -0
- package/cordis.patch.yml +19 -0
- package/lib/index.js +506 -0
- package/package.json +54 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-use-codex contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# DSH Use Codex
|
|
2
|
+
|
|
3
|
+
> Delegate a task from DeepSeek Harness to your local Codex CLI with one natural-language request, then bring the result back to the conversation.
|
|
4
|
+
|
|
5
|
+
English | [简体中文](README.md)
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
`dsh-use-codex` adds a small set of tools to [DeepSeek Harness (DSH)](https://github.com/deepseek-ai) for delegating one-shot tasks to the local [OpenAI Codex CLI](https://github.com/openai/codex). It is designed for code changes, debugging, repository analysis, and batch file processing while keeping execution inside explicitly authorized workspaces.
|
|
13
|
+
|
|
14
|
+
## Contents
|
|
15
|
+
|
|
16
|
+
- [Features](#features)
|
|
17
|
+
- [Requirements](#requirements)
|
|
18
|
+
- [Installation](#installation)
|
|
19
|
+
- [Configuration](#configuration)
|
|
20
|
+
- [Usage](#usage)
|
|
21
|
+
- [Tool reference](#tool-reference)
|
|
22
|
+
- [How it works](#how-it-works)
|
|
23
|
+
- [Security model](#security-model)
|
|
24
|
+
- [Development and testing](#development-and-testing)
|
|
25
|
+
- [FAQ](#faq)
|
|
26
|
+
- [Project status](#project-status)
|
|
27
|
+
- [License](#license)
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- **Natural-language delegation**: ask DSH to "let Codex do..." or "hand this to Codex".
|
|
32
|
+
- **Three built-in tools**: run a task, inspect status, and toggle the plugin.
|
|
33
|
+
- **Workspace allowlist**: Codex can only run in explicitly authorized, real directories.
|
|
34
|
+
- **Symlink escape protection**: both the requested directory and configured roots are resolved to real paths.
|
|
35
|
+
- **Safe sandbox default**: `workspace-write` is used unless the caller requests otherwise.
|
|
36
|
+
- **Two-step dangerous-mode approval**: `danger-full-access` also requires explicit host configuration.
|
|
37
|
+
- **No shell interpolation**: the task is passed as a single argv value.
|
|
38
|
+
- **Process-group cleanup**: the complete Codex process group is terminated on timeout or cancellation.
|
|
39
|
+
- **Bounded output**: stdout and stderr are capped before being returned to the conversation.
|
|
40
|
+
- **Minimal state**: only the runtime toggle and update timestamp are persisted.
|
|
41
|
+
- **Zero runtime dependencies**: the plugin itself needs no additional npm packages.
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
| Component | Requirement |
|
|
46
|
+
|---|---|
|
|
47
|
+
| Node.js | `>= 20` |
|
|
48
|
+
| DSH | A version supporting Cordis bundle patches and tool registration |
|
|
49
|
+
| Codex CLI | Supports `codex exec`, `-C`, `-s`, and `--ephemeral` |
|
|
50
|
+
| Operating system | macOS or Linux; Windows has not been validated |
|
|
51
|
+
|
|
52
|
+
Validated combination:
|
|
53
|
+
|
|
54
|
+
- DeepSeek Harness `0.2.1-rc.2`
|
|
55
|
+
- Node.js `22.x`
|
|
56
|
+
- Codex CLI `0.166.0`
|
|
57
|
+
|
|
58
|
+
Verify the Codex CLI first:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
codex --version
|
|
62
|
+
codex login status
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
> When using a custom OpenAI-compatible provider, a logged-out result from `codex login status` may not indicate a problem. The authoritative check is whether `codex exec` can complete a task.
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
### Install through the DSH plugin market index
|
|
70
|
+
|
|
71
|
+
In DSH, open **Discover → Plugin Market → Add index source** and add:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
https://raw.githubusercontent.com/chaorenzeng/dsh-use-codex/main/market/index.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Search for **DSH Use Codex** and install it. The market index pins an immutable Git commit; the actual installation source remains this repository.
|
|
78
|
+
|
|
79
|
+
### 1. Get the source
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone git@github.com:chaorenzeng/dsh-use-codex.git "$HOME/Projects/dsh-use-codex"
|
|
83
|
+
cd "$HOME/Projects/dsh-use-codex"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Register the dependency and bundle in a DSH profile
|
|
87
|
+
|
|
88
|
+
Edit the target DSH profile's `package.json`, for example `~/.dsh/profiles/web/package.json`:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"dependencies": {
|
|
93
|
+
"dsh-use-codex": "file:/absolute/path/to/dsh-use-codex"
|
|
94
|
+
},
|
|
95
|
+
"dsh": {
|
|
96
|
+
"profile": {
|
|
97
|
+
"bundles": [
|
|
98
|
+
"dsh-use-codex"
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Keep the existing dependencies and bundles in that file. Then install the profile dependencies:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cd ~/.dsh/profiles/web
|
|
109
|
+
pnpm install
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
If the profile uses another package manager, use the equivalent install command.
|
|
113
|
+
|
|
114
|
+
### 3. Add local configuration
|
|
115
|
+
|
|
116
|
+
Override the plugin configuration in the target DSH profile's `cordis.patch.yml`:
|
|
117
|
+
|
|
118
|
+
```yaml
|
|
119
|
+
- id: use-codex
|
|
120
|
+
name: dsh-use-codex
|
|
121
|
+
config:
|
|
122
|
+
enabled: true
|
|
123
|
+
bin: /absolute/path/to/codex
|
|
124
|
+
defaultCwd: /absolute/path/to/workspace
|
|
125
|
+
allowedRoots:
|
|
126
|
+
- /absolute/path/to/workspace
|
|
127
|
+
allowDangerFullAccess: false
|
|
128
|
+
timeoutSec: 900
|
|
129
|
+
maxOutputChars: 20000
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
> Local paths, Codex credentials, and provider settings belong in machine-local configuration and must not be committed to a public repository.
|
|
133
|
+
|
|
134
|
+
### 4. Restart DSH
|
|
135
|
+
|
|
136
|
+
Restart the DSH host so the profile loads the plugin for the first time. If it is managed by a macOS LaunchAgent:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
launchctl kickstart -k "gui/$(id -u)/<YOUR_DSH_LAUNCHD_LABEL>"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
After restarting, **create a new DSH conversation**. Existing conversations do not automatically receive newly registered tools.
|
|
143
|
+
|
|
144
|
+
### 5. Verify the integration
|
|
145
|
+
|
|
146
|
+
Send this in a new conversation:
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
Let Codex do: reply only with USE_CODEX_OK. Do not read or modify any files.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
A `USE_CODEX_OK` response confirms that the plugin, Codex CLI, and tool-call path are working.
|
|
153
|
+
|
|
154
|
+
## Configuration
|
|
155
|
+
|
|
156
|
+
### Plugin options
|
|
157
|
+
|
|
158
|
+
| Option | Default | Description |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `enabled` | `false` | Register tools when DSH starts; when disabled, no tools are registered |
|
|
161
|
+
| `bin` | `codex` | Codex CLI executable path; supports `~` expansion |
|
|
162
|
+
| `defaultCwd` | DSH process working directory | Used when `cwd` is omitted; must be an absolute directory inside the allowlist |
|
|
163
|
+
| `allowedRoots` | `[defaultCwd]` | Real directories in which Codex may run |
|
|
164
|
+
| `allowDangerFullAccess` | `false` | Allow an individual call to request `danger-full-access` |
|
|
165
|
+
| `timeoutSec` | `900` | Maximum run timeout, from `1` to `3600` seconds |
|
|
166
|
+
| `maxOutputChars` | `20000` | Maximum retained characters for stdout and stderr separately, from `1000` to `200000` |
|
|
167
|
+
|
|
168
|
+
The public [`cordis.patch.yml`](cordis.patch.yml) uses `/tmp` as a safe placeholder and sets `enabled: false`. Production settings should be kept in the machine-local profile patch.
|
|
169
|
+
|
|
170
|
+
### Environment variables
|
|
171
|
+
|
|
172
|
+
| Variable | Description |
|
|
173
|
+
|---|---|
|
|
174
|
+
| `CODEX_BIN` | Codex CLI path used when `bin` is not configured |
|
|
175
|
+
| `USE_CODEX_STATE` | Overrides the runtime toggle state-file path |
|
|
176
|
+
| `DSH_HOME` | DSH data directory; state defaults to `use-codex.json` under this directory |
|
|
177
|
+
|
|
178
|
+
The runtime toggle state file defaults to:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
${DSH_HOME:-~/.dsh}/use-codex.json
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
It is created with mode `0600` and contains only:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"enabled": true,
|
|
189
|
+
"updatedAt": "2026-01-01T00:00:00.000Z"
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Usage
|
|
194
|
+
|
|
195
|
+
### Natural-language delegation
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
Let Codex do: inspect why the tests are failing, identify the root cause, and fix it. Do not commit.
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
Hand this to Codex: analyze duplicated code under src and propose a plan before changing anything.
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
DSH decides when to call `codex_run`. Give Codex a clear objective, scope, constraints, and acceptance criteria so it can complete the task independently.
|
|
206
|
+
|
|
207
|
+
### Specify a workspace and sandbox
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
Ask Codex to summarize the architecture of /absolute/path/to/repo using the read-only sandbox.
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Check status
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
Check the status of Use Codex.
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Disable immediately
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
Disable Use Codex.
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
New `codex_run` calls are rejected immediately. Re-enabling the plugin does not require a DSH restart.
|
|
226
|
+
|
|
227
|
+
### Raw tool arguments
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"task": "Run the relevant tests and fix the failures. Do not commit.",
|
|
232
|
+
"cwd": "/absolute/path/to/repository",
|
|
233
|
+
"sandbox": "workspace-write",
|
|
234
|
+
"timeoutSec": 600
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Tool reference
|
|
239
|
+
|
|
240
|
+
### `codex_run`
|
|
241
|
+
|
|
242
|
+
Starts one non-interactive `codex exec` task in the requested workspace.
|
|
243
|
+
|
|
244
|
+
| Argument | Type | Required | Description |
|
|
245
|
+
|---|---|---|---|
|
|
246
|
+
| `task` | `string` | Yes | Complete task instructions; up to `100000` characters |
|
|
247
|
+
| `cwd` | `string` | No | Absolute workspace path that resolves inside `allowedRoots` |
|
|
248
|
+
| `sandbox` | `string` | No | `read-only`, `workspace-write`, or `danger-full-access` |
|
|
249
|
+
| `timeoutSec` | `number` | No | Per-call timeout, capped by the plugin's configured `timeoutSec` |
|
|
250
|
+
|
|
251
|
+
The default sandbox is `workspace-write`. `danger-full-access` is rejected unless the host sets `allowDangerFullAccess: true`.
|
|
252
|
+
|
|
253
|
+
### `codex_status`
|
|
254
|
+
|
|
255
|
+
Reports:
|
|
256
|
+
|
|
257
|
+
- current runtime toggle state
|
|
258
|
+
- `codex --version`
|
|
259
|
+
- `codex login status`
|
|
260
|
+
- effective workspace allowlist
|
|
261
|
+
- whether dangerous mode is allowed
|
|
262
|
+
- timeout and output limits
|
|
263
|
+
- a summary of the most recent run in the current DSH process
|
|
264
|
+
|
|
265
|
+
### `codex_danger`
|
|
266
|
+
|
|
267
|
+
Runtime toggle for `danger-full-access` (effective when the host config sets `allowDangerFullAccess: true`).
|
|
268
|
+
|
|
269
|
+
| Param | Type | Required | Description |
|
|
270
|
+
|---|---|---|---|
|
|
271
|
+
| `enabled` | `boolean` | yes | `true` enables danger mode (default sandbox becomes `danger-full-access`), `false` disables it (back to `workspace-write`) |
|
|
272
|
+
|
|
273
|
+
When enabled, the **next** `codex_run` defaults to `danger-full-access` (no sandbox: unrestricted read/write, network access, arbitrary commands). This only changes the default; an explicit `sandbox` argument is untouched. The state persists across DSH restarts.
|
|
274
|
+
|
|
275
|
+
### `codex_switch`
|
|
276
|
+
|
|
277
|
+
| Argument | Type | Required | Description |
|
|
278
|
+
|---|---|---|---|
|
|
279
|
+
| `enabled` | `boolean` | Yes | `true` enables the plugin; `false` disables it |
|
|
280
|
+
|
|
281
|
+
The runtime toggle is persisted separately and does not affect other DSH plugins.
|
|
282
|
+
|
|
283
|
+
## How it works
|
|
284
|
+
|
|
285
|
+
```mermaid
|
|
286
|
+
flowchart LR
|
|
287
|
+
U[DSH user] --> A[DSH agent]
|
|
288
|
+
A -->|codex_run| B[dsh-use-codex]
|
|
289
|
+
B --> C{Validate workspace<br/>and security policy}
|
|
290
|
+
C -->|allowed| D[Codex CLI<br/>codex exec]
|
|
291
|
+
D --> W[Authorized workspace]
|
|
292
|
+
D --> B
|
|
293
|
+
B --> A
|
|
294
|
+
A --> U
|
|
295
|
+
C -->|rejected| A
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The effective command is equivalent to:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
codex exec \
|
|
302
|
+
-C /absolute/path/to/workspace \
|
|
303
|
+
-s workspace-write \
|
|
304
|
+
--skip-git-repo-check \
|
|
305
|
+
--ephemeral \
|
|
306
|
+
--color never \
|
|
307
|
+
-- "task text"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
`--ephemeral` disables Codex session reuse; it does not make the run read-only. With `workspace-write`, Codex may modify files inside the authorized workspace.
|
|
311
|
+
|
|
312
|
+
## Security model
|
|
313
|
+
|
|
314
|
+
This plugin allows DSH to start the local Codex CLI. Treat any DSH conversation that can access the plugin as having controlled local execution capability.
|
|
315
|
+
|
|
316
|
+
### Built-in protections
|
|
317
|
+
|
|
318
|
+
- The workspace must exist, be absolute, and resolve to a real filesystem path.
|
|
319
|
+
- The resolved workspace must remain inside `allowedRoots`.
|
|
320
|
+
- Symlinks cannot be used to escape an allowed root.
|
|
321
|
+
- The task is passed as one argv value without a shell.
|
|
322
|
+
- Timeout and cancellation terminate the Codex process group.
|
|
323
|
+
- stdout and stderr are bounded.
|
|
324
|
+
- Task text, working directories, and outputs are not written to plugin state.
|
|
325
|
+
- The public bundle disables dangerous mode by default.
|
|
326
|
+
|
|
327
|
+
### Deployment guidance
|
|
328
|
+
|
|
329
|
+
- Install only in a trusted local DSH instance; never expose it to untrusted users.
|
|
330
|
+
- Keep `allowedRoots` as narrow as practical.
|
|
331
|
+
- Do not enable `allowDangerFullAccess` without additional host-level isolation.
|
|
332
|
+
- The Codex child inherits the DSH environment, which may contain credentials.
|
|
333
|
+
- `workspace-write` can still modify allowed files; do not allowlist sensitive directories.
|
|
334
|
+
- Although task text is not stored in plugin state, it may appear in DSH conversation history, host logs, or Codex logs.
|
|
335
|
+
- Keep DSH, Codex CLI, and dependencies up to date.
|
|
336
|
+
|
|
337
|
+
See [SECURITY.md](SECURITY.md) for the full security policy.
|
|
338
|
+
|
|
339
|
+
## Development and testing
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
git clone https://github.com/chaorenzeng/dsh-use-codex.git
|
|
343
|
+
cd dsh-use-codex
|
|
344
|
+
npm test
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Tests use temporary directories and a fake Codex executable. They do not call a network service, model, or private workspace. Coverage includes:
|
|
348
|
+
|
|
349
|
+
- plugin metadata and registration of all three tools
|
|
350
|
+
- empty tasks, missing paths, and paths outside the allowlist
|
|
351
|
+
- symlink escapes
|
|
352
|
+
- dangerous-mode rejection by default
|
|
353
|
+
- runtime toggling
|
|
354
|
+
- `workspace-write` and `--ephemeral` arguments
|
|
355
|
+
- process-group termination on timeout
|
|
356
|
+
- minimal state persistence
|
|
357
|
+
|
|
358
|
+
Inspect the actual npm package contents before publishing:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
npm pack --dry-run
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Issues and pull requests are welcome. Do not include credentials, private paths, full logs, or other sensitive information in public issues. Report security problems through the private process described in [SECURITY.md](SECURITY.md).
|
|
365
|
+
|
|
366
|
+
## FAQ
|
|
367
|
+
|
|
368
|
+
### Why are the tools missing in a new conversation?
|
|
369
|
+
|
|
370
|
+
Confirm that `dsh.profile.bundles` in `package.json` includes `dsh-use-codex`, `enabled` is `true` in the profile patch, and DSH was restarted. Then create a new conversation.
|
|
371
|
+
|
|
372
|
+
### Why is the working directory rejected?
|
|
373
|
+
|
|
374
|
+
`cwd` must be absolute, exist, and resolve inside `allowedRoots`. Invalid allowlist entries are ignored during startup.
|
|
375
|
+
|
|
376
|
+
### Why does a call fail when `cwd` is omitted?
|
|
377
|
+
|
|
378
|
+
`defaultCwd` must exist and be inside the allowlist. Set both `defaultCwd` and the corresponding `allowedRoots` entry explicitly.
|
|
379
|
+
|
|
380
|
+
### Why does `codex_status` report a logged-out state?
|
|
381
|
+
|
|
382
|
+
With a custom OpenAI-compatible provider, `codex login status` may not reflect actual availability. Verify by running a real `codex exec` task instead.
|
|
383
|
+
|
|
384
|
+
### Why does a task take so long?
|
|
385
|
+
|
|
386
|
+
One run may wait up to `900` seconds by default. Set `timeoutSec` within the configured maximum when a shorter or longer limit is required.
|
|
387
|
+
|
|
388
|
+
### Is a restart required after disabling the plugin?
|
|
389
|
+
|
|
390
|
+
No. `codex_switch` takes effect immediately. A restart is only required when changing registration-time settings such as `enabled` in the profile configuration.
|
|
391
|
+
|
|
392
|
+
## Project status
|
|
393
|
+
|
|
394
|
+
The project is experimental at the `0.x` stage. Tool arguments, configuration fields, and response formats may change as DSH and Codex CLI evolve. Pin validated DSH and Codex CLI versions and rerun the end-to-end check after upgrades.
|
|
395
|
+
|
|
396
|
+
This is an independent community plugin, not affiliated with or endorsed by DeepSeek or OpenAI. DeepSeek Harness, Codex, and related names and trademarks belong to their respective owners.
|
|
397
|
+
|
|
398
|
+
## License
|
|
399
|
+
|
|
400
|
+
[MIT](LICENSE) © 2026 dsh-use-codex contributors
|