Skip to content

Commit c8bd5e2

Browse files
authored
feat: streamline desktop local dev workflow (#640)
* feat: add local dev supervisor workflow * feat: refine local dev workflow and desktop runtime scaffolding * docs: add dev workflow faq * fix: remove nested controller tsx watcher * refactor: share ensure guards across dev process helpers * chore: remove stale task notes * refactor: centralize local dev path resolution * refactor: move dev orchestration into scripts/dev Keep @nexu/dev-utils focused on atomic helpers so service-level controller and web flows stay easier to reason about and recover. Add lightweight session tracing so leaked dev processes can be correlated and cleaned up without heavy self-healing. * refactor: clarify scripts dev module boundaries * feat: externalize dev runtime ownership * feat: split local dev into explicit service controls * refactor: remove legacy desktop dev launchers * fix: run desktop local dev through the Vite supervisor * fix: harden local dev stack flow * chore: sync workspace lockfiles * fix: restore desktop dev auth session
1 parent 2890ae1 commit c8bd5e2

File tree

92 files changed

+5036
-1879
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+5036
-1879
lines changed

AGENTS.md

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Nexu is a desktop-first OpenClaw platform. Users create AI bots, connect them to
1212
- `apps/web` — React + Ant Design + Vite
1313
- `openclaw-runtime` — Repo-local packaged OpenClaw runtime for local dev and desktop packaging; replaces global `openclaw` CLI
1414
- `packages/shared` — Shared Zod schemas
15+
- `packages/dev-utils` — TS-first reusable utilities for local script tooling
1516

1617
## Project overview
1718

@@ -23,13 +24,16 @@ All commands use pnpm. Target a single app with `pnpm --filter <package>`.
2324

2425
```bash
2526
pnpm install # Install
26-
pnpm dev # Local controller-first web stack (Controller + Web)
27-
pnpm dev:controller # Controller only
28-
pnpm start # Build and launch the desktop local runtime stack
29-
pnpm stop # Stop the desktop local runtime stack
30-
pnpm restart # Restart the desktop local runtime stack
31-
pnpm reset-state # Stop desktop runtime and delete repo-local desktop state
32-
pnpm status # Show desktop local runtime status
27+
pnpm --filter @nexu/shared build # Build shared dist required by cold-start dev flows
28+
pnpm dev start # Start the lightweight local stack: openclaw -> controller -> web -> desktop
29+
pnpm dev start <service> # Start one local-dev service: desktop|openclaw|controller|web
30+
pnpm dev restart # Restart the lightweight local stack
31+
pnpm dev stop # Stop the lightweight local stack in reverse order
32+
pnpm dev stop <service> # Stop one local-dev service
33+
pnpm dev restart <service> # Restart one local-dev service
34+
pnpm dev status <service> # Show status for one local-dev service
35+
pnpm dev logs <service> # Show active-session log tail (max 200 lines) for one local-dev service
36+
pnpm dev:controller # Legacy controller-only direct dev entrypoint
3337
pnpm dist:mac # Build signed macOS desktop distributables
3438
pnpm dist:mac:arm64 # Build signed Apple Silicon macOS desktop distributables
3539
pnpm dist:mac:x64 # Build signed Intel macOS desktop distributables
@@ -67,15 +71,16 @@ This repo is desktop-first. Prefer the controller-first path and remove or ignor
6771

6872
## Desktop local development
6973

70-
- Use `pnpm install` first, then `pnpm start` / `pnpm stop` / `pnpm restart` / `pnpm status` as the standard local desktop workflow.
71-
- `pnpm start` is the canonical local desktop entrypoint and now applies safe startup optimizations by default: it reuses existing build artifacts when present and reuses the prepared OpenClaw sidecar cache when its inputs have not changed.
72-
- Temporary escape hatches exist for debugging or suspicious cache behavior: `NEXU_DESKTOP_FORCE_FULL_START=1` disables the optimized start path, `NEXU_DESKTOP_DISABLE_BUILD_REUSE=1` disables build artifact reuse only, and `NEXU_DESKTOP_DISABLE_OPENCLAW_SIDECAR_CACHE=1` disables the OpenClaw sidecar cache only.
73-
- `pnpm reset-state` is the reset button for the optimized path too: it stops the desktop runtime and clears repo-local runtime state plus cached sidecars under `.tmp/sidecars/`.
74+
- Minimal cold-start setup on a fresh machine is: `pnpm install` -> `pnpm --filter @nexu/shared build` -> copy `scripts/dev/.env.example` to `scripts/dev/.env` only if you need dev-only overrides.
75+
- Default daily flow is: `pnpm dev start` -> `pnpm dev status <service>` / `pnpm dev logs <service>` as needed -> `pnpm dev stop`.
76+
- Use `pnpm dev restart` for a clean full-stack recycle; use `pnpm dev restart <service>` only when you are intentionally touching one service.
77+
- Explicit single-service control remains available through `pnpm dev start <desktop|openclaw|controller|web>`, `pnpm dev stop <service>`, `pnpm dev restart <service>`, `pnpm dev status <service>`, and `pnpm dev logs <service>`.
78+
- `pnpm dev` intentionally does not support `all`; the full local stack order remains `openclaw` -> `controller` -> `web` -> `desktop`.
79+
- `pnpm dev logs <service>` is session-scoped, prints a fixed header, and tails at most the last 200 lines from the active service session.
80+
- `scripts/dev/.env.example` is the source-of-truth template for dev-only overrides. Copy it to `scripts/dev/.env` only when you need to override ports, URLs, state paths, or the shared OpenClaw gateway token for local development.
7481
- Keep the detailed startup optimization rules, cache invalidation behavior, and troubleshooting notes in `specs/guides/desktop-runtime-guide.md`; keep only the core workflow expectations here.
7582
- The repo also includes a local Slack reply smoke probe at `scripts/probe/slack-reply-probe.mjs` (`pnpm probe:slack prepare` / `pnpm probe:slack run`) for verifying the end-to-end Slack DM reply path after local runtime or OpenClaw changes.
7683
- The Slack smoke probe is not zero-setup: install Chrome Canary first, then manually log into Slack in the opened Canary window before running `pnpm probe:slack run`.
77-
- The desktop dev launcher is `apps/desktop/scripts/dev-cli.mjs`; `apps/desktop/dev.sh` is only a thin compatibility wrapper.
78-
- Treat `pnpm start` as the canonical cold-start entrypoint for the full local desktop runtime.
7984
- The active desktop runtime path is controller-first: desktop launches `controller + web + openclaw` and no longer starts local `api`, `gateway`, or `pglite` sidecars.
8085
- Desktop local runtime should not depend on PostgreSQL. In dev mode, all state (config, OpenClaw state, logs) lives under `.tmp/desktop/nexu-home/`, fully isolated from the packaged app. Launchd plists go to `.tmp/launchd/`, runtime-ports.json also lives there.
8186
- In packaged mode, data is split across two directories (see table below). Launchd plists go to `~/Library/LaunchAgents/`.
@@ -90,21 +95,18 @@ This repo is desktop-first. Prefer the controller-first path and remove or ignor
9095

9196
The split is intentional: `NEXU_HOME` holds lightweight user preferences that should persist across reinstalls; Electron `userData` holds heavy runtime state tied to the app lifecycle. `OPENCLAW_STATE_DIR` is explicitly set by the desktop launcher to point to the `userData` path — do not rely on the controller's default fallback.
9297
- `tmux` is no longer required for the desktop local-dev workflow; process state is tracked by the platform-aware launcher entrypoints.
93-
- For startup troubleshooting, use `pnpm logs` and `node apps/desktop/scripts/dev-cli.mjs devlog` when you need the raw dev-cli timeline.
94-
- `pnpm reset-state` is a dev-only cleanup shortcut; it stops the stack and removes repo-local desktop runtime state under `.tmp/desktop/`, but it does not delete packaged app state.
9598
- To fully reset local desktop + controller state, stop the stack, remove `.tmp/desktop/`, then remove `~/.nexu/` and `~/Library/Application Support/@nexu/desktop/`.
96-
- If `pnpm start` exits immediately because `electron/cli.js` cannot be resolved from `apps/desktop`, validate `pnpm -C apps/desktop exec electron --version` and consult `specs/guides/desktop-runtime-guide.md` before changing the launcher flow.
9799
- Desktop already exposes an agent-friendly runtime observability surface; prefer subscribing/querying before adding temporary UI or ad hoc debug logging.
98100
- For deeper desktop runtime inspection, use the existing event/query path (`onRuntimeEvent(...)`, `runtime:query-events`, `queryRuntimeEvents(...)`) instead of rebuilding one-off diagnostics.
99101
- Use `actionId`, `reasonCode`, and `cursor` / `nextCursor` as the primary correlation and incremental-fetch primitives for desktop runtime debugging.
100-
- To fully clear local desktop runtime state, use `node apps/desktop/scripts/dev-cli.mjs reset-state`.
101102
- Desktop runtime guide: `specs/guides/desktop-runtime-guide.md`.
102103
- The controller sidecar is packaged by `apps/desktop/scripts/prepare-controller-sidecar.mjs` which deep-copies all controller `dependencies` and their transitive deps into `.dist-runtime/controller/node_modules/`. Keep controller deps minimal to avoid bloating the desktop distributable.
103104
- SkillHub (catalog, install, uninstall) runs in the controller via HTTP — not in the Electron main process via IPC. The web app always uses HTTP SDK for skill operations.
104105
- Desktop auto-update is channel-specific. Packaged builds should embed `NEXU_DESKTOP_UPDATE_CHANNEL` (`stable` / `beta` / `nightly`) so the updater checks the matching feed, and update diagnostics should always log the effective feed URL plus remote `version` / `releaseDate` when available.
105106

106107
## Hard rules
107108

109+
- **Debugging first principle: binary isolate, don't guess.** For UI/runtime regressions, start with overall bisection and add tiny reversible `quick return` / `quick fail` probes at key boundaries. Prefer changes that create obvious UI/log differences, narrow the fault domain quickly, and can be reverted immediately after verification. Do not start by rewriting route guards, state flows, or core logic based on intuition.
108110
- **Never use `any`.** Use `unknown` with narrowing or `z.infer<typeof schema>`.
109111
- No foreign keys in Drizzle schema — application-level joins only.
110112
- Credentials (bot tokens, signing secrets) must never appear in logs or errors.
@@ -168,6 +170,7 @@ See `ARCHITECTURE.md` for the full bird's-eye view. Key points:
168170
| Workspace templates | `specs/guides/workspace-templates.md` |
169171
| Local Slack testing | `specs/references/local-slack-testing.md` |
170172
| Local Slack smoke probe | `scripts/probe/README.md`, `scripts/probe/slack-reply-probe.mjs` |
173+
| Local dev CLI guidance | `scripts/dev/AGENTS.md` |
171174
| Frontend conventions | `specs/FRONTEND.md` |
172175
| Desktop runtime guide | `specs/guides/desktop-runtime-guide.md` |
173176
| Security posture | `specs/SECURITY.md` |
@@ -258,9 +261,12 @@ This note should track:
258261
## Local quick reference
259262

260263
- Controller env path: `apps/controller/.env`
264+
- Fresh local-dev cold start: `pnpm install` -> `pnpm --filter @nexu/shared build` -> optional `copy scripts/dev/.env.example scripts/dev/.env` (Windows) or `cp scripts/dev/.env.example scripts/dev/.env` (POSIX) -> `pnpm dev start`
265+
- Daily local-dev flow: `pnpm dev start` -> `pnpm dev logs <service>` / `pnpm dev status <service>` when needed -> `pnpm dev restart` for a clean recycle -> `pnpm dev stop`
261266
- OpenClaw managed skills dir (expected default): `~/.openclaw/skills/`
262267
- Slack smoke probe setup: install Chrome Canary, set `PROBE_SLACK_URL`, run `pnpm probe:slack prepare`, then manually log into Slack in Canary before `pnpm probe:slack run`
263268
- `openclaw-runtime` is installed implicitly by `pnpm install`; local development should normally not use a global `openclaw` CLI
269+
- Full-stack startup order is `openclaw` -> `controller` -> `web` -> `desktop`; shutdown order is the reverse
264270
- Prefer `./openclaw-wrapper` over global `openclaw` in local development; it executes `openclaw-runtime/node_modules/openclaw/openclaw.mjs`
265271
- When OpenClaw is started manually, set `RUNTIME_MANAGE_OPENCLAW_PROCESS=false` for `@nexu/controller` to avoid launching a second OpenClaw process
266272
- If behavior differs, verify effective `OPENCLAW_STATE_DIR` / `OPENCLAW_CONFIG_PATH` used by the running controller process.

0 commit comments

Comments
 (0)