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 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: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
+ ![Node.js](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&logoColor=white)
9
+ ![DSH Plugin](https://img.shields.io/badge/DeepSeek%20Harness-plugin-4B6BFB)
10
+ ![Status](https://img.shields.io/badge/status-experimental-orange)
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