diff --git a/.env.example b/.env.example index e42f2130..089160c2 100644 --- a/.env.example +++ b/.env.example @@ -1,38 +1,48 @@ +# Persistent product configuration belongs in ~/.devspace/config.jsonc. +# Environment values are useful for bootstrap, secrets, deployment overrides, +# and compatibility with pre-v1.1 setups. + HOST=127.0.0.1 PORT=7676 + +# Locate an alternate config.jsonc/auth.json directory. +# DEVSPACE_CONFIG_DIR=/path/to/devspace-config + # Owner password generated by `devspace init` in ~/.devspace/auth.json. Set this # only for non-interactive or fully env-driven deployments. # DEVSPACE_OAUTH_OWNER_TOKEN=change-me-to-a-long-random-secret -# Optional OAuth tuning. -# DEVSPACE_OAUTH_ACCESS_TOKEN_TTL_SECONDS=3600 -# DEVSPACE_OAUTH_REFRESH_TOKEN_TTL_SECONDS=2592000 -# DEVSPACE_OAUTH_SCOPES=devspace -# DEVSPACE_OAUTH_ALLOWED_REDIRECT_HOSTS=chatgpt.com,localhost,127.0.0.1 -DEVSPACE_ALLOWED_ROOTS=/home/waishnav/personal,/home/waishnav/work -# For temporary tunnels, prefer setting this per run. DevSpace derives the -# inbound Host allowlist from this URL. + +# Common deployment overrides. +# DEVSPACE_ALLOWED_ROOTS=/home/me/personal,/home/me/work # DEVSPACE_PUBLIC_BASE_URL=https://your-public-host.example.com -# Advanced escape hatch. `*` disables Host header allowlist protection. # DEVSPACE_ALLOWED_HOSTS=localhost,127.0.0.1,your-public-host.example.com -DEVSPACE_TOOL_MODE=full -# off | changes | full. Defaults to changes. -# changes creates one aggregate review widget via review_changes instead of per-tool iframes. -DEVSPACE_WIDGETS=changes -DEVSPACE_LOG_LEVEL=info -DEVSPACE_LOG_FORMAT=json -DEVSPACE_LOG_REQUESTS=1 -DEVSPACE_LOG_ASSETS=0 -DEVSPACE_LOG_TOOL_CALLS=1 -DEVSPACE_LOG_SHELL_COMMANDS=0 -# DEVSPACE_TRUST_PROXY=1 -# DEVSPACE_STATE_DIR=/home/waishnav/.local/share/devspace -# DEVSPACE_WORKTREE_ROOT=/home/waishnav/.devspace/worktrees -# Native-file download is opt-in. Files stream to a model-selected relative -# path inside an already-open workspace without overwriting existing files. +# DEVSPACE_STATE_DIR=/home/me/.local/share/devspace +# DEVSPACE_WORKTREE_ROOT=/home/me/.devspace/worktrees + +# Legacy harness/presentation overrides. Prefer config.jsonc for persistent use. +# DEVSPACE_TOOL_MODE=minimal +# DEVSPACE_MINIMAL_TOOLS=1 +# DEVSPACE_WIDGETS=full + +# Optional feature overrides. # DEVSPACE_ARTIFACTS=1 # DEVSPACE_ARTIFACT_MAX_FILE_BYTES=104857600 -# DEVSPACE_AUTO_LOAD_AGENTS_MD=1 -# Skills are enabled by default. Set DEVSPACE_SKILLS=0 to hide them. # DEVSPACE_SKILLS=0 -# DEVSPACE_AGENT_DIR=/home/waishnav/.codex -# DEVSPACE_SKILL_PATHS=/home/waishnav/.codex/skills,/home/waishnav/.claude/skills +# DEVSPACE_AGENT_DIR=/home/me/.codex +# DEVSPACE_SKILL_PATHS=/home/me/.claude/skills,/home/me/company/skills +# DEVSPACE_SUBAGENTS=1 + +# OAuth policy overrides. +# DEVSPACE_OAUTH_ACCESS_TOKEN_TTL_SECONDS=3600 +# DEVSPACE_OAUTH_REFRESH_TOKEN_TTL_SECONDS=2592000 +# DEVSPACE_OAUTH_SCOPES=devspace +# DEVSPACE_OAUTH_ALLOWED_REDIRECT_HOSTS=chatgpt.com,localhost,127.0.0.1 + +# Logging overrides. +# DEVSPACE_LOG_LEVEL=info +# DEVSPACE_LOG_FORMAT=json +# DEVSPACE_LOG_REQUESTS=1 +# DEVSPACE_LOG_ASSETS=0 +# DEVSPACE_LOG_TOOL_CALLS=1 +# DEVSPACE_LOG_SHELL_COMMANDS=0 +# DEVSPACE_TRUST_PROXY=1 diff --git a/AGENTS.md b/AGENTS.md index fa13d508..73da3468 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,7 +26,8 @@ These ideas should stay true as the project evolves: - **Allowed root** — a configured filesystem boundary within which a workspace may be opened. It is not itself necessarily a workspace. - **Checkout mode** — operating on an existing checkout supplied by the user. - **Worktree mode** — operating in an isolated Git worktree. -- **Tool surface** — the tools exposed by a configured mode, such as minimal, full, or Codex-compatible. +- **Coding harness** — the model-facing coding tool contract. DevSpace currently composes a Claude Code-style harness or a Codex-style harness. +- **Presentation profile** — the host-rendered UI/review behavior: inline tool UI, aggregate change review, or off. - **Process session** — a long-running command tracked for later input, output, or termination. - **Instruction file** — an `AGENTS.md` or `CLAUDE.md` discovered while navigating a workspace. - **Subagent** — a bounded model invocation delegated and coordinated by the host. @@ -62,8 +63,8 @@ Determine how the user will consume the change and verify that path. Behavior ma - a fresh process and a server or host that needs restarting; - checkout mode and worktree mode; - Linux, macOS, and Windows Bash environments; -- minimal, full, and Codex-compatible tool surfaces; -- widgets enabled, disabled, or limited to change review. +- Claude Code shell-inspection, Claude Code dedicated-inspection, and Codex harnesses; +- inline, change-review, and off presentation profiles. State clearly when only a narrower proxy was verified. For model-facing schemas, inspect what the host receives. For UI and artifacts, inspect the rendered result rather than inferring success from the producing command. @@ -115,4 +116,4 @@ Start at the boundary named by the problem and follow the data. Keep policy in D - Preserve host and provider data unless DevSpace has a concrete reason to normalize it. - Add compatibility behavior only for an identified consumer with a real upgrade path. - Reuse glossary terms in schemas, types, documentation, and errors. -- Keep the execution layer small, reliable, and unsurprising. \ No newline at end of file +- Keep the execution layer small, reliable, and unsurprising. diff --git a/docs/chatgpt-coding-workflow.md b/docs/chatgpt-coding-workflow.md index d7a5d13c..e71a4a7d 100644 --- a/docs/chatgpt-coding-workflow.md +++ b/docs/chatgpt-coding-workflow.md @@ -148,9 +148,9 @@ configuration. The bundled `subagents` skill teaches the minimal comes from `open_workspace`; `devspace agents ls` lists existing subagent sessions for that workspace. -## Tool Names +## Coding Harness -DevSpace exposes these tool names: +The default `claude-code` harness with `inspection: "shell"` exposes: - `open_workspace` - `read` @@ -158,14 +158,23 @@ DevSpace exposes these tool names: - `edit` - `bash` -By default, DevSpace also runs in `DEVSPACE_TOOL_MODE=minimal`, so dedicated -`grep`, `glob`, and `ls` tools are hidden. Use `bash` with command-line tools -such as `rg`, `find`, and `ls` for search and directory inspection. +Dedicated `grep`, `glob`, and `ls` tools are hidden in that configuration. Use +`bash` with command-line tools such as `rg`, `find`, and `ls` for search and +directory inspection. -Use `DEVSPACE_TOOL_MODE=full` to restore dedicated search and directory tools. +Set `harness.inspection` to `"dedicated"` in `~/.devspace/config.jsonc` to expose +the dedicated inspection tools. -The experimental Codex-style surface is enabled with -`DEVSPACE_TOOL_MODE=codex`. It exposes: +The Codex harness is selected with: + +```jsonc +{ + "version": 1, + "harness": { "kind": "codex" } +} +``` + +It exposes: - `open_workspace` - `read` @@ -173,20 +182,22 @@ The experimental Codex-style surface is enabled with - `exec_command` - `write_stdin` -In this mode, `write`, `edit`, `bash`, `grep`, `glob`, and `ls` are not +In this harness, `write`, `edit`, `bash`, `grep`, `glob`, and `ls` are not registered. `exec_command` returns a process session ID when a command is still running after its yield window. Use `write_stdin` to poll it, send input, resize a PTY, or send Ctrl-C. Set `tty: true` only for commands that need a terminal. -## Show Changes +`DEVSPACE_TOOL_MODE=minimal|full|codex` remains a compatibility override for +older deployments. -By default, `DEVSPACE_WIDGETS=full`. +## Show Changes -In that mode, DevSpace attaches widget UI to the exposed workspace, file, edit, -and shell tools. The aggregate `show_changes` tool is not exposed by default. +By default, `presentation.mode` is `"inline"`, which attaches widget UI to the +normal exposed tools without registering the aggregate review tool. -Use `DEVSPACE_WIDGETS=off` to disable widget UI, or `DEVSPACE_WIDGETS=changes` -to expose the aggregate show-changes flow. +Use `presentation.mode: "off"` to disable widget UI, or +`presentation.mode: "change-review"` to expose the aggregate `show_changes` +flow. `DEVSPACE_WIDGETS=off|changes|full` remains a compatibility override. When `show_changes` is exposed, call it exactly once after the final file modification in any turn that changes files. It shows the combined changes for diff --git a/docs/configuration.md b/docs/configuration.md index 93a3d4fa..d640c082 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,16 +1,19 @@ # Configuration Reference -DevSpace can be configured through `devspace init`, persisted config files, or -environment variables. - -The default files are: +DevSpace v1.1 uses a versioned JSONC configuration file as its primary product +configuration: ```text -~/.devspace/config.json +~/.devspace/config.jsonc ~/.devspace/auth.json ``` -Use another config directory with: +`config.jsonc` is human-editable, supports comments and trailing commas, and can +reference the checked-in JSON Schema for editor completion and validation. +`auth.json` remains separate so the OAuth owner password is not mixed into normal +product configuration. + +Use another configuration directory with: ```bash DEVSPACE_CONFIG_DIR=/path/to/config npx @waishnav/devspace serve @@ -26,234 +29,249 @@ npx @waishnav/devspace config get npx @waishnav/devspace config set publicBaseUrl https://devspace.example.com ``` -## Core Environment Variables +## JSONC configuration -| Variable | Purpose | -| --- | --- | -| `HOST` | Local bind host. Defaults to `127.0.0.1`. | -| `PORT` | Local port. Defaults to `7676`. | -| `DEVSPACE_ALLOWED_ROOTS` | Comma-separated local roots that workspaces may open. | -| `DEVSPACE_PUBLIC_BASE_URL` | Public origin for the server, without `/mcp`. | -| `DEVSPACE_ALLOWED_HOSTS` | Optional Host header allowlist override. | -| `DEVSPACE_OAUTH_OWNER_TOKEN` | Owner password for OAuth approval. Must be at least 16 characters. | -| `DEVSPACE_WORKTREE_ROOT` | Directory for managed Git worktrees. Defaults to `~/.devspace/worktrees`. | -| `DEVSPACE_STATE_DIR` | Directory for SQLite state. Defaults to `~/.local/share/devspace`. | +`devspace init` writes the canonical v1 shape. Keep only values you intentionally +want to configure; omitted values use DevSpace defaults. -## Native Artifact Download +```jsonc +{ + "$schema": "https://raw.githubusercontent.com/Waishnav/devspace/refs/tags/v1.1.0/schema/devspace-config.schema.json", + "version": 1, + + "server": { + "host": "127.0.0.1", + "port": 7676, + "allowedRoots": [ + "~/personal", + "~/work" + ], + "publicBaseUrl": "https://devspace.example.com" + }, + + "harness": { + "kind": "claude-code", + "inspection": "shell" + }, + + "presentation": { + "mode": "inline" + }, + + "skills": { + "enabled": true, + "paths": [] + }, -Native-file download is disabled by default. Enable it when ChatGPT needs to hand -an attached or generated file into an already-open workspace: + "artifacts": { + "enabled": false, + "maxFileBytes": 104857600 + }, -```bash -DEVSPACE_ARTIFACTS=1 npx @waishnav/devspace serve + "subagents": { + "enabled": true, + "providers": [ + { + "id": "codex", + "enabled": true, + "model": "gpt-5.4", + "effort": "high" + } + ] + }, + + "logging": { + "level": "info", + "format": "json" + } +} ``` -This feature currently supports Linux. It is not registered on macOS, Windows, -or BSD because the secure publication path depends on traversable, -descriptor-anchored directory paths provided by Linux procfs. +The published schema is generated from the same Zod codec used at runtime. A +test keeps the checked-in schema synchronized with that codec. -| Variable | Default | Purpose | -| --- | --- | --- | -| `DEVSPACE_ARTIFACTS` | `0` | Expose `download_artifact` for trusted native files. | -| `DEVSPACE_ARTIFACT_MAX_FILE_BYTES` | `104857600` | Maximum streamed size of one file (100 MiB). | +### Precedence + +Configuration resolves in this order: -The same settings may be persisted in `~/.devspace/config.json` as -`artifactsEnabled` and `artifactMaxFileBytes`. +1. Environment overrides, when supplied. +2. `~/.devspace/config.jsonc`. +3. Legacy `~/.devspace/config.json`, when no JSONC file exists. +4. DevSpace defaults. -`download_artifact` accepts the native file object supplied by the MCP connector, -a `workspaceId` returned by `open_workspace`, and a relative workspace `path`. -DevSpace safely creates missing parent directories, refuses to overwrite an -existing destination, and returns only the normalized workspace-relative path. -It does not accept conflict modes, expected hashes, arbitrary URL strings, local -paths, embedded credentials, or extra object fields. +If both persisted files exist, `config.jsonc` is authoritative. DevSpace does +not rewrite configuration during `serve`. An intentional write such as +`devspace init --force` or `devspace config set ...` writes the canonical JSONC +file. Existing JSONC comments, formatting, and unknown future keys are preserved +where the edited value does not require replacing them. -There is no artifact root, total quota, TTL, pinning, persistent database record, -or background artifact cleanup service. See [Native File Download](artifact-exchange.md) -for the supported connector shape and security boundaries. +Legacy `config.json` remains readable in v1.1. Its old flat fields are migrated +to the v1 model in memory. The legacy file is left untouched so merely starting +DevSpace never mutates user state. -## OAuth +## Coding harness -DevSpace uses a single-user OAuth approval flow. +The harness controls the model-facing coding tool contract. -| Variable | Default | +| Configuration | Exposed tools | | --- | --- | -| `DEVSPACE_OAUTH_ACCESS_TOKEN_TTL_SECONDS` | `3600` | -| `DEVSPACE_OAUTH_REFRESH_TOKEN_TTL_SECONDS` | `2592000` | -| `DEVSPACE_OAUTH_SCOPES` | `devspace` | -| `DEVSPACE_OAUTH_ALLOWED_REDIRECT_HOSTS` | `chatgpt.com,localhost,127.0.0.1` | +| `{ "kind": "claude-code", "inspection": "shell" }` | `open_workspace`, `read`, `write`, `edit`, `bash` | +| `{ "kind": "claude-code", "inspection": "dedicated" }` | Above plus `grep`, `glob`, `ls` | +| `{ "kind": "codex" }` | `open_workspace`, `read`, `apply_patch`, `exec_command`, `write_stdin` | -MCP clients discover metadata from: +The Claude Code harness uses the same mutation/shell contract as the previous +`minimal` and `full` tool modes. `inspection: "shell"` keeps inspection inside +`bash`; `inspection: "dedicated"` exposes dedicated search and directory tools. -```text -/.well-known/oauth-protected-resource/mcp -/.well-known/oauth-authorization-server -``` +The Codex harness uses process sessions. Commands run without a PTY by default; +set `tty: true` on `exec_command` for interactive terminal programs. + +For compatibility, `DEVSPACE_TOOL_MODE=minimal|full|codex` still overrides the +persisted harness. `DEVSPACE_MINIMAL_TOOLS` remains an older alias when +`DEVSPACE_TOOL_MODE` is unset. -## Tool Modes +## Presentation and change review -`DEVSPACE_TOOL_MODE` controls the tool surface. +`presentation.mode` controls host-rendered UI and the aggregate review workflow. | Value | Behavior | | --- | --- | -| `minimal` | Default. Exposes `open_workspace`, `read`, `write`, `edit`, and `bash`. Clients use `bash` with tools such as `rg`, `find`, and `ls` for inspection. | -| `full` | Exposes the minimal tools plus dedicated `grep`, `glob`, and `ls` tools. | -| `codex` | Experimental. Exposes `open_workspace`, `read`, `apply_patch`, `exec_command`, and `write_stdin`. Existing mutation and shell tools are hidden. | +| `inline` | Default. Attach widget UI to normal exposed tools. | +| `change-review` | Expose `show_changes`, attach UI to `open_workspace` and `show_changes`, and track review checkpoints. | +| `off` | Do not attach widget UI. | -`DEVSPACE_MINIMAL_TOOLS` remains a backward-compatible alias when -`DEVSPACE_TOOL_MODE` is unset: `1` selects `minimal` and `0` selects `full`. -The `codex` mode must be selected through `DEVSPACE_TOOL_MODE` and always uses -its fixed short tool names regardless of `DEVSPACE_TOOL_NAMING`. +`DEVSPACE_WIDGETS=full|changes|off` remains a compatibility override mapping to +`inline|change-review|off` respectively. -Codex-mode commands run without a PTY by default. Set `tty: true` on -`exec_command` for interactive terminal programs. PTY support uses the optional -`node-pty` dependency; `write_stdin` can send input, poll output, and resize PTY -sessions. +## Server -## Widgets +The `server` object supports: -`DEVSPACE_WIDGETS` controls ChatGPT Apps iframe usage. - -| Value | Behavior | -| --- | --- | -| `full` | Default. Widget UI is attached to exposed workspace, file, edit, and shell tools. | -| `changes` | Enables the aggregate `show_changes` tool and attaches widget UI to `open_workspace` and `show_changes`. | -| `off` | Disables widget UI. | +| Key | Default | Purpose | +| --- | --- | --- | +| `host` | `127.0.0.1` | Local bind host. | +| `port` | `7676` | Local MCP port. | +| `allowedRoots` | current directory | Local roots workspaces may open. | +| `publicBaseUrl` | local server URL | Public origin, without `/mcp`. Use `null` to fall back to the local URL. | +| `allowedHosts` | derived | Optional Host header allowlist. | +| `worktreeRoot` | `~/.devspace/worktrees` | Managed Git worktree directory. | +| `stateDir` | `~/.local/share/devspace` | SQLite state directory. | -## Skills +`HOST`, `PORT`, `DEVSPACE_ALLOWED_ROOTS`, `DEVSPACE_PUBLIC_BASE_URL`, +`DEVSPACE_ALLOWED_HOSTS`, `DEVSPACE_WORKTREE_ROOT`, and `DEVSPACE_STATE_DIR` +remain deployment overrides. -| Variable | Purpose | -| --- | --- | -| `DEVSPACE_SKILLS` | Set to `0` to hide skills. Enabled by default. | -| `DEVSPACE_SUBAGENTS` | Optional master override for the persisted Subagents configuration. | -| `DEVSPACE_AGENT_DIR` | Defaults to `~/.codex`; its `skills` child is loaded for compatibility. | -| `DEVSPACE_SKILL_PATHS` | Optional comma-separated additional skill directories. | +## Native artifact download -DevSpace discovers standard Agent Skills from: +Native-file download is disabled by default: -- `~/.agents/skills` -- project `.agents/skills` -- `~/.devspace/skills` - -It also keeps compatibility with: +```jsonc +{ + "version": 1, + "artifacts": { + "enabled": true, + "maxFileBytes": 104857600 + } +} +``` -- the bundled `subagents` skill when Subagents are enabled, unless `~/.devspace/skills/subagents/SKILL.md` exists -- `DEVSPACE_AGENT_DIR/skills`, defaulting to `~/.codex/skills` -- additional paths from `DEVSPACE_SKILL_PATHS` +This feature currently supports Linux. It is not registered on unsupported +platforms even when requested in configuration. Runtime compilation resolves +that availability once so tool registration, model instructions, and startup +status agree. -When Subagents are enabled, DevSpace discovers agent profiles -from: +`DEVSPACE_ARTIFACTS` and `DEVSPACE_ARTIFACT_MAX_FILE_BYTES` remain environment +overrides. See [Native File Download](artifact-exchange.md) for the connector and +security contract. -- `~/.devspace/agents/*.md` -- project `.devspace/agents/*.md` +## Skills and subagents -Enable providers and set their defaults in `~/.devspace/config.json`: +Skills are enabled by default. Additional paths and the compatibility agent +directory can be persisted under `skills`: -```json +```jsonc { - "subagents": { + "version": 1, + "skills": { "enabled": true, - "providers": [ - { - "id": "codex", - "enabled": true, - "model": "gpt-5.4", - "effort": "high" - }, - { - "id": "claude", - "enabled": true, - "model": "sonnet" - }, - { - "id": "grok", - "enabled": true, - "model": "grok-4.5", - "effort": "low" - } - ] + "paths": ["~/.claude/skills", "~/company/skills"], + "agentDir": "~/.codex" } } ``` -Each entry controls one provider. Providers omitted from the array are disabled. -`model` and `effort` are optional defaults; an invocation override wins over a -profile value, which wins over the provider default. The legacy boolean -`"subagents": true` remains readable and enables every provider, but new -configuration should use the explicit object form. - -`devspace agents targets` shows usable providers and profiles for the current -workspace. Add `--json` for a compact list of exact target names and their -selection metadata. Disabled, unavailable, and unconfigured providers are -omitted. Provider availability is runtime state and never rewrites the -configuration. - -Grok Build is discovered from the `grok` executable. Authenticate it with -`grok login` or `XAI_API_KEY`; DevSpace does not read or store Grok credentials. -Grok supports `grok-build` by default and validates explicit model and effort -values against the ACP session metadata when available. Set `GROK_COMMAND` when -the executable is not on the normal PATH. If your Grok installation selects a -custom agent profile, set `GROK_AGENT_PROFILE` to that profile's path; DevSpace -passes it to `grok agent stdio` without writing to Grok's configuration. - -`open_workspace` returns a compact catalog containing profile names, -descriptions, providers, and optional models/effort levels so the host model can choose an -agent without reading provider-specific launch details. Disabled or unavailable -providers and their profiles are omitted from this model-facing catalog. `devspace agents ls` -lists existing subagent sessions for the current workspace, scoped by the -workspace environment injected into shell commands. The `subagents` -skill teaches the model to use only the minimal `devspace agents ls`, -`devspace agents targets`, `devspace agents run`, `devspace agents continue`, -and `devspace agents show` workflow. - -For Codex, Claude Code, OpenCode, Pi, or another supported Coding Agent, use -the Skills CLI to install the same skill. DevSpace setup prints this command but -does not run it or write into agent skill directories: +DevSpace discovers standard Agent Skills from `~/.agents/skills`, project +`.agents/skills`, `~/.devspace/skills`, the compatibility agent directory, and +the configured additional paths. -```bash -npx skills add Waishnav/devspace --skill subagents --global -``` +When Subagents are enabled, agent profiles are discovered from +`~/.devspace/agents/*.md` and project `.devspace/agents/*.md`. Each provider entry +controls enablement plus optional `model` and `effort` defaults. Invocation +overrides win over profile values, which win over provider defaults. -Starter profile templates are available under `examples/agents/`. Copy or adapt -them into one of the active profile directories before use. +The legacy boolean `"subagents": true` in `config.json` remains readable and is +migrated in memory to the explicit provider configuration. New JSONC config uses +the object form. -Legacy project paths such as `.pi/skills` can be added through `DEVSPACE_SKILL_PATHS` when needed. +Provider availability is runtime state and never rewrites configuration. +Credentials remain owned by provider CLIs. For example, Grok Build uses +`grok login` or `XAI_API_KEY`; command-location variables such as `GROK_COMMAND` +and `CODEX_COMMAND` remain process/provider overrides rather than DevSpace +credentials. -Example: +`DEVSPACE_SKILLS`, `DEVSPACE_SKILL_PATHS`, `DEVSPACE_AGENT_DIR`, and +`DEVSPACE_SUBAGENTS` remain compatibility overrides. -```bash -DEVSPACE_SKILL_PATHS="$HOME/.claude/skills,$HOME/company/skills" \ -npx @waishnav/devspace serve -``` +## OAuth and secrets -## Logging +The OAuth owner password stays in `~/.devspace/auth.json` or +`DEVSPACE_OAUTH_OWNER_TOKEN`; it is intentionally not part of `config.jsonc`. -| Variable | Default | -| --- | --- | -| `DEVSPACE_LOG_LEVEL` | `info` | -| `DEVSPACE_LOG_FORMAT` | `json` | -| `DEVSPACE_LOG_REQUESTS` | `1` | -| `DEVSPACE_LOG_ASSETS` | `0` | -| `DEVSPACE_LOG_TOOL_CALLS` | `1` | -| `DEVSPACE_LOG_SHELL_COMMANDS` | `0` | -| `DEVSPACE_TRUST_PROXY` | `0` | +Non-secret OAuth policy can be persisted: -Set `DEVSPACE_LOG_FORMAT=pretty` for local debugging. +```jsonc +{ + "version": 1, + "oauth": { + "accessTokenTtlSeconds": 3600, + "refreshTokenTtlSeconds": 2592000, + "scopes": ["devspace"], + "allowedRedirectHosts": ["chatgpt.com", "localhost", "127.0.0.1"] + } +} +``` -Set `DEVSPACE_LOG_SHELL_COMMANDS=1` only when you intentionally want command -previews in logs. +The matching `DEVSPACE_OAUTH_*` variables remain environment overrides. -## Env-Only Example +MCP clients discover metadata from: -```bash -DEVSPACE_OAUTH_OWNER_TOKEN="$(openssl rand -base64 32)" \ -DEVSPACE_ALLOWED_ROOTS="$HOME/personal,$HOME/work" \ -DEVSPACE_PUBLIC_BASE_URL="https://devspace.example.com" \ -DEVSPACE_WORKTREE_ROOT="$HOME/.devspace/worktrees" \ -DEVSPACE_ARTIFACTS="1" \ -DEVSPACE_TOOL_MODE="minimal" \ -DEVSPACE_WIDGETS="full" \ -npx @waishnav/devspace serve +```text +/.well-known/oauth-protected-resource/mcp +/.well-known/oauth-authorization-server ``` -The environment assignments must be part of the same command invocation, or -exported first. +## Logging + +Logging can be persisted under `logging`; environment variables continue to +override individual values. + +| Key / override | Default | +| --- | --- | +| `level` / `DEVSPACE_LOG_LEVEL` | `info` | +| `format` / `DEVSPACE_LOG_FORMAT` | `json` | +| `requests` / `DEVSPACE_LOG_REQUESTS` | `true` | +| `assets` / `DEVSPACE_LOG_ASSETS` | `false` | +| `toolCalls` / `DEVSPACE_LOG_TOOL_CALLS` | `true` | +| `shellCommands` / `DEVSPACE_LOG_SHELL_COMMANDS` | `false` | +| `trustProxy` / `DEVSPACE_TRUST_PROXY` | `false` | + +Enable shell command logging only when command previews are intentionally safe +to retain. + +## Environment-only deployment + +JSONC is the normal persistent interface, but fully environment-driven +deployments remain supported. `DEVSPACE_CONFIG_DIR` is always environment-only +because it locates the configuration itself. Secrets, child-process workspace +context (`DEVSPACE_WORKSPACE_ID`, `DEVSPACE_WORKSPACE_ROOT`), and internal daemon +controls also remain outside the persisted product config. diff --git a/docs/gotchas.md b/docs/gotchas.md index 495243bb..18b40152 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -253,12 +253,16 @@ If a skill appears in `open_workspace`, the model must read that skill's ## Review Card Does Not Appear -Per-tool widget cards are enabled by default with: +Per-tool widget cards are enabled by default through the inline presentation: -```bash -DEVSPACE_WIDGETS=full +```jsonc +{ + "version": 1, + "presentation": { "mode": "inline" } +} ``` The aggregate `show_changes` tool is only exposed with -`DEVSPACE_WIDGETS=changes`. Plain MCP clients may ignore ChatGPT Apps widget -metadata and only show text results. +`presentation.mode: "change-review"`. `DEVSPACE_WIDGETS=changes` remains a +compatibility override. Plain MCP clients may ignore ChatGPT Apps widget metadata +and only show text results. diff --git a/docs/setup.md b/docs/setup.md index 934b0b8c..6feaebae 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -56,7 +56,7 @@ remain limited to the roots configured for ChatGPT. Setup detects supported Coding Agents and asks which ones DevSpace may use. These choices are stored as provider objects under `subagents` in -`~/.devspace/config.json`. +`~/.devspace/config.jsonc`. If you selected Coding Agents, setup prints: @@ -120,7 +120,7 @@ password approval page. Enter the Owner password printed during setup. The default config files are: ```text -~/.devspace/config.json +~/.devspace/config.jsonc ~/.devspace/auth.json ``` diff --git a/package-lock.json b/package-lock.json index e8d69ce2..5def9f34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@waishnav/devspace", - "version": "1.0.7", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@waishnav/devspace", - "version": "1.0.7", + "version": "1.1.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c3209e95..598e3740 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@waishnav/devspace", - "version": "1.0.7", + "version": "1.1.0", "description": "Expose a secure local coding workspace through an MCP server.", "type": "module", "main": "dist/server.js", diff --git a/src/cli.ts b/src/cli.ts index 13b4e3ce..5d0f958e 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -392,7 +392,7 @@ function printHelp(): void { "Usage:", " devspace Run first-time setup if needed, then start the server", " devspace serve Start the server", - " devspace init Create or update ~/.devspace/config.json and auth.json", + " devspace init Create or update ~/.devspace/config.jsonc and auth.json", " devspace doctor Show config, runtime, and native dependency status", " devspace config get Print persisted config", " devspace config set publicBaseUrl ", diff --git a/src/local-agent-acp.ts b/src/local-agent-acp.ts index a5d9c369..043939cf 100644 --- a/src/local-agent-acp.ts +++ b/src/local-agent-acp.ts @@ -10,6 +10,7 @@ import { isProgrammerDefect, } from "./local-agent-errors.js"; import { terminateProcessTree } from "./process-platform.js"; +import { DEVSPACE_VERSION } from "./version.js"; import { GrokPromptCompletionRegistry, GROK_DEFAULT_MODEL, @@ -36,7 +37,6 @@ const ACP_INITIALIZE_TIMEOUT_MS = 10_000; const ACP_GROK_PROMPT_COMPLETION_TIMEOUT_MS = 10 * 60_000; const require = createRequire(import.meta.url); const spawn = require("cross-spawn") as typeof import("node:child_process").spawn; -const DEVSPACE_VERSION = readDevspaceVersion(); const observeChildError = (): void => {}; @@ -851,14 +851,6 @@ async function withTimeout(promise: Promise, timeoutMs: number, message: s } } -function readDevspaceVersion(): string { - const packageJson = require("../package.json") as { version?: unknown }; - if (typeof packageJson.version !== "string" || !packageJson.version) { - throw new Error("Unable to read DevSpace package version."); - } - return packageJson.version; -} - function readArray(value: unknown, key: string): unknown[] | undefined { const result = asRecord(value)?.[key]; return Array.isArray(result) ? result : undefined; diff --git a/src/local-agent-codex.ts b/src/local-agent-codex.ts index dac27cc3..3d73c530 100644 --- a/src/local-agent-codex.ts +++ b/src/local-agent-codex.ts @@ -10,6 +10,7 @@ import { } from "./local-agent-errors.js"; import { removeDevspaceNodeModulesBinFromPath } from "./local-agent-path.js"; import { terminateProcessTree } from "./process-platform.js"; +import { DEVSPACE_VERSION } from "./version.js"; import type { LocalAgentDriver, LocalAgentRunCallbacks, @@ -109,7 +110,7 @@ export class CodexAppServerRuntime implements LocalAgentRuntime { async initialize(): Promise { await this.rpc.request("initialize", { - clientInfo: { name: "devspace", title: "DevSpace", version: "1.0.7" }, + clientInfo: { name: "devspace", title: "DevSpace", version: DEVSPACE_VERSION }, capabilities: {}, }); this.rpc.notify("initialized"); diff --git a/src/server.ts b/src/server.ts index aa78563e..9ad7ab85 100644 --- a/src/server.ts +++ b/src/server.ts @@ -62,6 +62,7 @@ import { shutdownHttpServer } from "./server-shutdown.js"; import { formatPathForPrompt } from "./skills.js"; import { createWorkspaceStore } from "./workspace-store.js"; import { formatAgentsPath, WorkspaceRegistry } from "./workspaces.js"; +import { DEVSPACE_VERSION } from "./version.js"; import { getLocalAgentProviderAvailabilitySnapshot, } from "./local-agent-availability.js"; @@ -683,7 +684,7 @@ export function createMcpServer( { name: "devspace", title: "DevSpace", - version: "0.1.0", + version: DEVSPACE_VERSION, description: "Coding tools for project workspaces. Open each project or worktree once, then reuse its workspaceId.", }, diff --git a/src/version.ts b/src/version.ts new file mode 100644 index 00000000..d5dd91a3 --- /dev/null +++ b/src/version.ts @@ -0,0 +1,10 @@ +import { createRequire } from "node:module"; + +const require = createRequire(import.meta.url); +const packageJson = require("../package.json") as { version?: unknown }; + +if (typeof packageJson.version !== "string" || !packageJson.version) { + throw new Error("DevSpace package version is missing."); +} + +export const DEVSPACE_VERSION = packageJson.version;