Two coupled bugs surfaced when the daemon resolved an older `claude`
binary on PATH:
1. Spawn crashed with "unknown option '--include-partial-messages'"
because that flag landed in 1.0.86 and we passed it unconditionally.
2. Even after dropping the flag, the assistant bubble rendered empty —
the stream parser only extracted text from `stream_event` deltas
(only emitted under --include-partial-messages). Without those
events, the full text in the `assistant` wrapper went unread.
Fix:
- Probe `claude --help` once during agent detection and cache which
flags the installed CLI advertises (`agentCapabilities` map).
- `buildArgs` reads the cache and only emits `--include-partial-messages`
/ `--add-dir` when supported; safe baseline when probing fails.
- Warm the cache on server startup (`detectAgents()`) so the first
/api/chat doesn't race ahead of the frontend's /api/agents call.
- Parse text (and thinking) blocks out of the `assistant` wrapper as a
fallback, deduped via a per-message-id `textStreamed` set so newer
builds streaming deltas never double-emit.
Co-authored-by: lukebaze <lukebaze@users.noreply.github.com>
Co-authored-by: lefarcen <20859779+lefarcen@users.noreply.github.com>
* feat(agents): add GitHub Copilot CLI as a code-agent option
Wire `copilot -p "..." --allow-all-tools` into AGENT_DEFS so the daemon
can spawn it alongside the other CLIs. `--allow-all-tools` is required
in non-interactive mode (same tradeoff as Claude's `-p` and Codex's
`exec`). Add a matching GitHub-dark icon with the Copilot two-eye mark.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(copilot-stream): treat result.success as completed when exitCode missing
Strict `obj.exitCode === 0 ? 'completed' : 'error'` mis-flags turns
where Copilot emits a `result` event with `success: true` but no numeric
exitCode. Switch to `obj.success === true || obj.exitCode === 0`. The
asymmetry argument that applies to other defensive ideas in this file
(raw fallback, stringifyResult cap) doesn't apply here — Claude's
`result` event uses a string `stop_reason`, not exitCode, so this is a
Copilot-specific schema-variance fix rather than a one-sided hardening.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(agent-adapters): list Copilot CLI auth paths in §5.7
Adds a one-line note: detection assumes Copilot is already
authenticated, via either `copilot login` (subcommand, OAuth device
flow) or the interactive `/login` slash command inside `copilot` with
no args. Surfaces the assumption so anyone hitting an undetected /
unversioned Copilot install can trace it back.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Adds design-systems/xiaohongshu/DESIGN.md. Lands under Media & Consumer.
- Color, typography, layout, component, and dark-mode tokens sampled
from production CSS at https://www.xiaohongshu.com/explore — the
inline :root,.force-light and :root[dark],.force-dark blocks.
- Brand primary captured as two values: #FF2442 (the --primary token)
and #FF2E4D (hard-coded on .reds-button-new.primary and .active-bar).
Both ship in the live UI.
- Danger / error reuses --primary; no independent error token in source.
- Bookmark / collect star (#FDBC5F) sampled from the inline
<symbol id="collected"> SVG path fill. Digits use the custom RED
Number family (Regular / Medium / Bold).
- Narrative copy in English per CONTRIBUTING.md; real product strings
(brand name, slogan, font name, follow-button labels, profile tab
labels) kept verbatim with English glosses, mirroring
pinterest/DESIGN.md preserving its Japanese font fallback names.
- Upstream VoltAgent/awesome-design-md does not currently include any
Chinese-internet brand, so this lands directly in the OD bundled set
rather than going to upstream first.
* fix: spawn agents via resolved absolute path on Windows (#10)
Detection in `/api/agents` resolves each agent's full executable path,
but `/api/chat` was spawning the bare `def.bin` ("claude"). On Windows
the child process's PATH often doesn't include the user's npm-global
shim directory, so spawn() failed with ENOENT despite the picker
showing the agent as available.
Use the resolved path at spawn time, and pass `shell: true` when the
resolved bin is a `.cmd`/`.bat` shim so Node ≥21 doesn't refuse to
execute it (CVE-2024-27980).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: address PR #13 review — friendlier ENOENT, document shell:true caveats
- When `resolveAgentBin` returns null we now emit a friendly SSE `error`
pointing at /api/agents and end the stream, instead of silently falling
back to spawn(def.bin) — which would re-introduce the exact issue #10
symptom this PR is meant to prevent.
- Strengthen the comment around `shell: true` on Windows: call out that
the only thing keeping user-controlled prompt text safe today is Node's
CVE-2024-27980 escaper, that the proper fix is to route the composed
prompt through child stdin (not a new `-p $prompt`-style flag), and
that cmd.exe's ~8191-char command-line cap reintroduces an
ENAMETOOLONG-class failure for long prompts under shell:true.
- Document why the `.cmd`/`.bat` regex is the right gate: those are the
only PATHEXT extensions that strictly need cmd.exe; `.exe`/`.com`
launch directly and `.ps1`/`.vbs` would need a different host that
shell:true (=cmd.exe) wouldn't help with.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(guizang-ppt): sync host slide counter on transform-paginated decks
go() previously only mutated #deck.style.transform on the parent track,
leaving .slide attributes untouched — so the iframe-host bridge in
src/runtime/srcdoc.ts couldn't detect which slide was active and the
host counter froze at 1/N. Toggle .active on the current .slide so
findActiveByClass returns the right index and the existing
MutationObserver fires a re-report.
* docs(guizang-ppt): mark .slide.active toggle as load-bearing for OD host counter
* fix(daemon): non-interactive permissions for agent CLIs in web UI
Claude Code and other CLIs prompt for tool approval; OD has no terminal
in the browser, so prompts stall the stream. Align spawn args with cwd
sandboxing: Claude bypassPermissions, Codex --full-auto, Gemini/Qwen
--yolo, Cursor --force.
Fixes https://github.com/nexu-io/open-design/issues/25
* fix(daemon): pass --force before -p for cursor-agent
---------
Co-authored-by: zhengyuanqing.zyq <zhengyuanqing.zyq@alibaba-inc.com>
* feat: per-CLI model picker for local agents (closes#8)
Each agent CLI declares its selectable models (and reasoning effort, for
Codex) on the daemon side; the frontend renders a model dropdown in the
avatar menu and the Settings dialog scoped to the currently picked CLI,
persists the choice per-agent in the AppConfig, and threads it through
/api/chat to the spawn argv. "Default" leaves the flag off so the CLI's
own config wins.
* feat(models): fetch live model lists from CLIs, allow custom ids
Each agent definition now declares an optional `listModels` spec; the
daemon runs the CLI's own list-models command (e.g. `opencode models`,
`cursor-agent models`) during agent detection and uses the result as
the dropdown options. Hardcoded entries shrink to a `fallbackModels`
hint that only kicks in when the CLI has no listing command (Claude,
Codex, Gemini, Qwen) or when the listing fails (e.g. unauth'd
cursor-agent).
UI groups `provider/model` ids by provider via <optgroup> so opencode's
~175 live models stay navigable, and the Settings dialog gains a
"Custom…" entry that opens a free-text input for any model id the
listing didn't surface yet. Daemon validates picks against the live
cache + fallback, with a permissive sanitizer for custom ids.
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* Add contributing guidelines in English and Chinese
- Introduced CONTRIBUTING.md and CONTRIBUTING.zh-CN.md to provide clear instructions for contributors.
- Outlined contribution types, local setup instructions, and merging criteria for skills and design systems.
- Enhanced README files to reference the new contributing guidelines.
* Update README and documentation for deck framework directives
- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.
* Update README and documentation for deck framework directives
- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.
* Enhance README and add star promotion assets
- Added a "Star us" section in both English and Chinese README files to encourage users to star the project on GitHub.
- Included a new image asset for the star promotion.
- Introduced a new HTML file for a dedicated star promotion page.
- Updated .gitignore to exclude new cursor-related files.
* feat(dev): auto-switch ports on dev:all when defaults are busy
Adds a small launcher (scripts/dev-all.mjs) that probes free ports
for the daemon (OD_PORT, default 7456) and Vite (VITE_PORT, default
5173) before invoking concurrently, so a stray process holding
either port no longer breaks the boot. The resolved ports are
exported into the child env; vite.config.ts now reads VITE_PORT to
keep its dev server and /api proxy aligned with the daemon's actual
port.
Made-with: Cursor
* Allow Claude Code to read skill seeds and design-system specs (#6)
The skill body's preamble points the agent at absolute paths like
`<repo>/skills/guizang-ppt/assets/template.html`, but the agent's cwd
is `.od/projects/<id>/`. Without an explicit allowlist Claude Code
blocks Read on those paths and the user sees a permission error
mid-conversation.
Pass `SKILLS_DIR` and `DESIGN_SYSTEMS_DIR` through `buildArgs` and emit
them as `--add-dir` for Claude so the seed template, references, and
design-system DESIGN.md are all readable. Other agents ignore the
extra dirs (no equivalent flag).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs: add verification screenshot for issue #6 fix
Captures the agent successfully Read-ing skills/guizang-ppt/ side files
through the new --add-dir allowlist, confirming the permission error
from issue #6 is gone.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* Add contributing guidelines in English and Chinese
- Introduced CONTRIBUTING.md and CONTRIBUTING.zh-CN.md to provide clear instructions for contributors.
- Outlined contribution types, local setup instructions, and merging criteria for skills and design systems.
- Enhanced README files to reference the new contributing guidelines.
* Update README and documentation for deck framework directives
- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.
* Update README and documentation for deck framework directives
- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.
* Enhance README and add star promotion assets
- Added a "Star us" section in both English and Chinese README files to encourage users to star the project on GitHub.
- Included a new image asset for the star promotion.
- Introduced a new HTML file for a dedicated star promotion page.
- Updated .gitignore to exclude new cursor-related files.
The Save button fired both onSave and onClose. onClose's closed-over
`config` still held the bootstrap default (agentId: 'claude'), so it
re-ran setConfig with the stale value right after onSave wrote the
user's choice — leaving the user with Claude Code even when they had
clicked Codex on first run.
Split the responsibilities: Save now owns close (handleConfigSave
calls setSettingsOpen(false)); onClose stays scoped to dismiss flows
(Skip / backdrop) where the stale-config write is harmless.
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* Add contributing guidelines in English and Chinese
- Introduced CONTRIBUTING.md and CONTRIBUTING.zh-CN.md to provide clear instructions for contributors.
- Outlined contribution types, local setup instructions, and merging criteria for skills and design systems.
- Enhanced README files to reference the new contributing guidelines.
* Update README and documentation for deck framework directives
- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.
* Update README and documentation for deck framework directives
- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* Add contributing guidelines in English and Chinese
- Introduced CONTRIBUTING.md and CONTRIBUTING.zh-CN.md to provide clear instructions for contributors.
- Outlined contribution types, local setup instructions, and merging criteria for skills and design systems.
- Enhanced README files to reference the new contributing guidelines.
- Created .gitignore to exclude build artifacts and dependencies.
- Added index.html as the main entry point for the application.
- Included LICENSE file with Apache 2.0 terms.
- Initialized package.json and package-lock.json for project dependencies.
- Added pnpm-lock.yaml for package management.
- Created QUICKSTART.md for setup instructions.
- Added README.md and README.zh-CN.md for project documentation in English and Chinese.