Skip to content

Windows: source-checkout setup is unusable — CLI build fails on chmod, and dapi never completes the handshake (named pipes) #82

Description

@alvarovegaromero

Summary

Two independent defects make the source-checkout + dapi setup unusable on Windows. Both have to be fixed before dapi can talk to the app at all.

  • OS: Windows 11
  • Node: v22.21.0 · npm: 11.6.1
  • dapi: 0.201.0, built from a source checkout (dapi on PATH is a junction into apps/cli)
  • Setup: git clone → npm install → cp apps/web/.env.example apps/web/.env → npm run dev:desktop

Bug 1 — the CLI build script fails on Windows (chmod)

apps/cli/package.json ends its build with:

"build": "esbuild ... --outfile=dist/index.js && chmod +x dist/index.js"

On Windows that is:

'chmod' is not recognized as an internal or external command,
operable program or batch file.
npm error Lifecycle script `build` failed with error:
npm error code 1

npm run dev:desktop builds the CLI as its first step, so the whole dev stack aborts before Vite or Electron ever start.

chmod is only needed for the macOS/Homebrew symlink and should be a no-op where it does not apply:

"build": "esbuild ... --outfile=dist/index.js && node -e \"if(process.platform!=='win32')require('fs').chmodSync('dist/index.js',0o755)\""

Bug 2 — the CLI handshake never gets a reply on Windows named pipes

With the app running and the named pipe present (\\.\pipe\diffusion-studio), every command fails:

$ dapi context
Unexpected end of JSON input

apps/cli/src/cli-client.ts (requestConnection) does:

sock.on("connect", () => sock.end(JSON.stringify(handshake)));

and apps/desktop/src/cli-server.ts answers on the socket's end event.

On Windows named pipes a half-close does not survive: the pipe goes down as soon as the client ends its side, so the app's 'end' handler races a torn-down socket and sock.end(JSON.stringify(reply)) writes to a dead pipe. The CLI sees EOF with an empty buffer, hence JSON.parse("").

Minimal repro (no Diffusion Studio involved, Windows only)

import { createServer, connect } from "node:net";

const PIPE = "\\\\.\\pipe\\ds-halftest";

const srv = createServer({ allowHalfOpen: true }, (sock) => {
  let buf = "";
  sock.setEncoding("utf8");
  sock.on("data", (c) => (buf += c));
  sock.on("end", async () => {
    await new Promise((r) => setTimeout(r, 50)); // any async work
    if (!sock.destroyed) sock.end(JSON.stringify({ ok: true }));
  });
  sock.on("error", () => {});
});

srv.listen(PIPE, () => {
  const c = connect(PIPE);
  let got = "";
  c.setEncoding("utf8");
  c.on("data", (d) => (got += d));
  c.on("end", () => { console.log("reply:", JSON.stringify(got)); process.exit(0); });
  c.on("connect", () => c.end(JSON.stringify({ port: 1, token: "x" })));
});

Result on Windows: reply: "", and the server's 'end' handler never runs.

If the client writes without half-closing (c.write(...)) and the server processes the handshake on the first complete data chunk, the reply arrives correctly.

Suggested fix (works on all platforms)

  • cli-client.ts: sock.write(...) instead of sock.end(...), letting the app close the socket after replying.
  • cli-server.ts: parse the handshake from accumulated data as soon as it is complete, keeping the end handler as a fallback for peers that do half-close (macOS/Linux).

Also worth documenting

openProject only calls launchApp() when process.platform === "darwin", so on Windows dapi open cannot start the app — the user has to launch Diffusion Studio manually first. That is easy to miss when following the source-setup instructions.

Workaround for anyone hitting this today

npm run dev:desktop          # after patching the chmod line
# then, with the app running:
dapi context

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions