Nyx is a personal desktop AI chat client.
The repository is now organized as a workspace, but the current product scope remains intentionally narrow: v1 min chat. The goal of this phase is still a minimal, real, streaming desktop chat loop, not a general AI workbench.
Nyx is split into two first-class subprojects:
apps/desktop: the current Electron desktop app.runtime/ocaml: an independent OCaml runtime core skeleton.
The desktop app is the only user-facing product surface right now. The OCaml runtime exists as a foundation for later typed Agent/runtime work, but it is not connected to Electron yet.
Current architecture notes:
The active source of truth is docs/v1-min-chat-implementation-plan.md.
If PRD.md, DESIGN.md, or older background docs disagree with the min-chat plan, follow the min-chat plan.
In scope:
- single-page desktop chat UI
- plain text messages
- real model traffic through the Electron main process
- real streaming output
- temporary in-memory multi-turn conversation
StopRetryNew chat- environment-based provider configuration
- provider secrets kept in Electron main only
Out of scope for this phase:
- persistent conversation history
- settings UI
- model picker UI
- Markdown or code highlighting
- tools
- agents
- plugins
- artifacts
- cloud sync
- multimodal features
apps/desktop owns:
- Electron main, preload, and renderer
- desktop UI
- current provider integration
- environment variables and provider credentials
- OS-facing side effects
- current
v1 min chatbehavior
runtime/ocaml owns:
- runtime domain types
- runtime event model
- future state transitions
- future tool scheduling semantics
- future policy and capability model
- replayable runtime tests
Electron and OCaml do not communicate yet. When that work starts later, Electron main is expected to own the OCaml child process lifecycle over stdio/NDJSON. The renderer must never talk to the OCaml runtime directly.
Root tooling is managed through mise tasks. mise currently manages Node for the workspace; pnpm and opam are expected to be available on the machine.
Initial setup:
mise install
pnpm install
mise run runtime:setupThe runtime setup creates a local opam switch under:
runtime/ocaml/_opam
Do not commit generated directories such as node_modules, out, dist, _build, or _opam.
Workspace:
mise run check
mise run build
mise run format
mise run format-checkDesktop:
mise run desktop:dev
mise run desktop:build
mise run desktop:typecheck
mise run desktop:typecheck:compat
mise run desktop:lint
mise run desktop:format
mise run desktop:format-check
mise run desktop:checkOCaml runtime:
mise run runtime:setup
mise run runtime:build
mise run runtime:test
mise run runtime:format
mise run runtime:format-check
mise run runtime:ping
mise run runtime:checkRoot pnpm scripts are compatibility aliases for the same mise tasks:
pnpm dev
pnpm build
pnpm check
pnpm format
pnpm format:check
pnpm lint
pnpm typecheck
pnpm typecheck:compatFor desktop-only changes:
mise run desktop:typecheck
mise run desktop:typecheck:compat
mise run desktop:lintFor runtime-only changes:
mise run runtime:build
mise run runtime:test
mise run runtime:format-checkFor cross-boundary, tooling, or structural changes:
mise run check
mise run build- Keep the product inside
v1 min chatunless a task explicitly changes scope. - Do not implement Electron <-> OCaml communication as part of structural docs or setup work.
- Renderer code must not read environment variables or provider credentials.
- Provider calls and cancellation handles belong in Electron main.
- Runtime code should stay pure and tiny until a concrete runtime behavior requires more.
- Do not add tools, agents, plugin UI, persistence, or settings UI during this phase.