nodwyn as an app
nodwyn app is the whole product in one program (ADR 30): a window with the
console, and — when no daemon is already running — the daemon itself, in the
same process. Nobody has to start nodwyn daemon, copy a pairing code or unlock
a keychain at a terminal.
nodwyn app # a window (webview build) or the default browser
nodwyn app --browser # the default browser even in the webview build
nodwyn app --no-open # print the launch address instead of opening it
It also takes --socket PATH (the daemon socket to attach to or serve on),
and the remote-device flags of nodwyn ui: --listen ADDR, --name
HOST:PORT and --tls-cert/--tls-key (browser.md, "Other devices").
- A daemon is running (your usual
nodwyn daemon): the app attaches to it. Closing the app leaves its tasks running, as closingnodwyn uidoes. - No daemon is running: the app serves tasks itself on the standard
socket, so
nodwyn tuiornodwyn uican attach to it meanwhile.nodwyn tuiand line mode (nodwyn chat) do the same when they find no daemon running (the TUI, the clients). Closing the app closes those tasks; their conversations are kept and resume later like after any daemon shutdown.
The page the app opens pairs itself with a one-time launch ticket carried in
the address's fragment (never sent to a server, removed from the address bar
at once, valid for a minute). The browser is started with that address, so
another user of the same computer can read the ticket in the process list for
the moment it starts and spend it first; on a computer other people log in to,
pair with the code the app prints to its log instead (nodwyn ui --no-open).
Another browser on the same computer can pair with that code too.
First run
With no model configured (no [control] in config.toml), Home draws the
forms of Settings › Models, one after the other (ADR 41), and no task starts
until they are done. First the provider, from the presets Settings has
(Ollama, OpenAI, Anthropic, Baseten, OpenRouter, Cerebras, or another server),
started on Ollama, on this computer or another one on the network, which needs
no key. Then the model, on the provider just saved: the models it lists are
offered as buttons (a long list is typed to), and Save and use it saves
the model and makes it the default for new tasks. The efforts it takes (the
provider's own, as published, when it says), what it is for and the effort it
starts at wait under a closed More fold, as the provider's name does in
the provider form; neither form asks for anything that does not have to be
answered before a task works. Its context length, prices and the rest of its settings are
what its provider publishes, and Settings › Models changes them, adds more
providers and models, and chooses another default (the manual, "Choosing
models"). The provider is written to a [servers.NAME] table of config.toml,
the model to a [models.NAME] table and the choice to [control]; every other
line of an existing file is kept. An API key is never written there: it goes into
the encrypted keychain, and a binding row allows it only for that server's
host, POST (and GET for its model list), as a bearer Authorization header
(Anthropic's: its x-api-key header). A model with a key must be
reached over HTTPS, unless it runs on this computer. A provider that wants a key
is not saved until there is a keychain to hold it, so the provider form shows the
keychain form beside it: a passphrase (at least 8 characters, not recoverable),
or, if you tick "Don't protect it with a passphrase", none (not recommended:
see below). What was typed in the provider form is kept while the keychain is
made. Settings makes one too, and sets or changes its passphrase.
When a keychain with a passphrase exists, a new app starts with it locked; Home offers to unlock it. While the model's own key is in a locked keychain, no task can be opened, resumed or run: the app asks you to unlock first, so no task starts without the key it needs. Tasks opened after unlocking can use every key in it. A keychain without a passphrase is opened as the app starts, and nothing asks. It is still an encrypted file, but its key comes from the empty passphrase, so it protects nothing its file permissions (0600, your user) do not: anyone who can read the file, or a backup of it, can use every key in it. Settings says so while it has none, and sets, changes or removes the passphrase (changing or removing one asks for the current one first).
Connections › Credentials manages the keys themselves: what the keychain holds, where each may be sent and what uses it; adding a key and allowing it for a host, replacing a rotated one, connecting an OAuth2 account, and removing or revoking one (browser.md, "Credentials"). Settings, keychain and credential changes are available to a console on this computer, and to another device only when the person signed it in with a passkey and touches it (browser.md, "Other devices").
The macOS app
make app # bin/Nodwyn.app — universal (Apple silicon and Intel), ad-hoc signed
It needs Xcode's command line tools (for cgo and WebKit). The bundle is the
same nodwyn binary built with the webview tag and Wails v3; started from Finder or the
Dock it runs nodwyn app, takes the login shell's PATH (so tools installed
with Homebrew are found), and writes its diagnostics to
~/.local/share/nodwyn/app.log. Everything else — configuration, keychain,
sessions — lives where the command-line nodwyn keeps it (nodwyn paths), per user.
Sharing it with family
make app, then zipbin/Nodwyn.app(Finder: Compress) and send it.- They move
Nodwyn.appto Applications. The first time, macOS says it is from an unidentified developer: right-click → Open → Open (once). The app is signed only ad hoc; signing with a Developer ID and notarizing is what would remove that step. - On first launch they choose a provider and a model (see First run). For a model
running on your machine, give its address on your network (for example
http://workshop:11434, over Tailscale); nothing leaves their computer until they do.
Each person's tasks, keys and settings stay in their own account.
Linux and other systems
make build-webview # bin/nodwyn with the webview tag
On Linux it needs cgo and WebKitGTK (libwebkit2gtk-4.1-dev on Debian and
Ubuntu, webkit2gtk4.1-devel on Fedora), or GTK4 with WebKitGTK 6.0.
Wails supports WebView2 on Windows, but Nodwyn's host still requires a Windows
port of its Unix process, locking and local IPC code; no Windows package is
published yet.
Without the tag, nodwyn app opens the default browser instead and works the
same; started from a desktop launcher, with no terminal for its messages, it
has no window of its own and is easy to take for an app that did not start.
So make promote builds nodwyn-stable with the tag on Linux and macOS, and
refuses to install one whose go version -m does not show -tags=webview.
On a Linux system without WebKitGTK it builds without the tag and says so,
before the acceptance run and again at the end.
scripts/webview-env.sh tags selects webview for GTK4 or macOS, and
webview,gtk3 for GTK3. make build-webview uses that selection. Wails
uses the real WebKitGTK package; no pkg-config alias is needed.
The desktop dependency is pinned to Wails v3.0.0-beta.28. Version 3 is
still beta; its direct window URL API lets the app keep the existing
loopback console, pairing tickets, cookies, CSP and WebSocket origin checks.
We do not serve the console through Wails' asset server or expose task
methods as Wails services. ADR 44 records the choice.
To run the native window check in a desktop session:
NODWYN_TEST_DESKTOP=1 go test -tags "$(scripts/webview-env.sh tags)" ./cmd/nodwyn -run '^TestWailsWindowRoundTrip$' -count=1
What the window adds
The page gets three functions from the window and nothing else: a native folder chooser (for adding a folder on Home or Workspaces), system notifications (the same generic "nodwyn needs your answer", opt-in in Settings), and opening a link in the default browser. None of them reads or writes a file the page names.
The native bridge accepts only the loopback window's origin and a random per-window capability injected into its top frame. GTK reports a top-level URI without a frame identity; the capability covers that missing metadata. Other platforms' frame metadata is checked when present. Replies also check the current origin so navigating elsewhere cannot receive a selected path. Notifications carry only the fixed attention notice, and external links must be HTTP(S). The browser version receives no desktop capability.
The daemon has notices of its own (ADR 53 §11), for when no window is open:
with Settings › General › While you're away › Desktop notices from
the daemon on, it shows
"nodwyn needs your answer" when a task comes to need one and no window of
this computer watches, and "nodwyn can't run a scheduled task" once when a
locked keychain stops a run. A daemon nodwyn app starts closes with its
window; Settings › General › While you're away › Start at login
(nodwyn startup on) has one
start at login instead, which the app then uses and leaves running.
Application icon and Linux shortcuts
The native window carries the console's cream n and blue dot on a dark
background. The macOS bundle includes Nodwyn.icns; move Nodwyn.app to
Applications and pin that bundle in the Dock.
On Linux, after building or installing nodwyn, install its application-menu entry and hicolor icons for your account:
python3 scripts/install-desktop.py /absolute/path/to/nodwyn
# Or, after promotion:
python3 scripts/install-desktop.py ~/.local/bin/nodwyn-stable
The installer uses XDG_DATA_HOME (normally ~/.local/share), or
--data-dir PATH. It points the shortcut at that exact executable and runs
app without a terminal. Pin nodwyn from the application menu; replace an
older pinned shortcut if it still shows a generic icon. Paths with spaces
are supported; executable paths containing percent signs or newlines are
refused. The binary must stay at the installed path.
An existing per-user nodwyn.desktop is updated too, as a hidden alias for
old pins, so the application menu shows only the new entry.
Distribution packages can install packaging/linux/com.nodwyn.app.desktop
in share/applications, and the console's icons/icon.svg and
icons/icon-512.png as com.nodwyn.app.svg and com.nodwyn.app.png under
share/icons/hicolor/scalable/apps and share/icons/hicolor/512x512/apps.
The native GTK application id and launcher id are both com.nodwyn.app, so
Wayland can associate the window with the shortcut's icon.