Toolkit of small, single-purpose GUI applications for software development on macOS and Linux
  • Rust 60.7%
  • TypeScript 12.5%
  • Svelte 9.9%
  • Shell 6.1%
  • Nix 6%
  • Other 4.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Allison Bentley cb404acc7c
feat: spigot Linux build + themed GTK header bar chrome
Wire up the Linux side of spigot, which was macOS-only in practice.

flake.nix devShell (Linux):
- Add Tauri's GTK/WebKit build deps (pkg-config, webkitgtk_4_1, gtk3,
  libsoup_3, librsvg) plus PKG_CONFIG_PATH so pnpm tauri build resolves.
- Add gsettings-desktop-schemas and point XDG_DATA_DIRS at the compiled
  schema dirs so GtkFileChooser stops aborting with GLib-GIO-ERROR.

Window chrome (Linux):
- New linux_chrome module installs a gtk::HeaderBar on the main window in
  place of the native menubar: native min/max/close controls plus a single
  menu button exposing Open and Save, wired to the existing pick_and_open
  and MenuSave paths.
- The header title tracks the current file and its edited state by reusing
  the string the frontend already sends to set_window_title.
- The Tauri menu and its handler are now non-Linux only; build_menu and the
  tauri::menu imports are cfg-gated to match.

Keyboard shortcuts (regression guard for the dropped menu):
- Editor.svelte registers a Monaco Ctrl/Cmd+S command for save.
- +page.svelte handles Ctrl/Cmd+O at the window level for open.

macOS chrome (proxy icon, edited dot, Tahoe traffic lights) is untouched;
all new code is cfg-gated to Linux.
2026-06-29 21:45:28 +01:00
.forgejo/workflows feat: spigot macOS release pipeline + decoupled Nix .app wiring 2026-05-17 17:02:47 +01:00
conduitctl feat: conduitd workspace registry + lifecycle (conduitctl) 2026-05-17 16:42:28 +01:00
conduitd feat: conduitd workspace registry + lifecycle (conduitctl) 2026-05-17 16:42:28 +01:00
nix feat: spigot macOS release pipeline + decoupled Nix .app wiring 2026-05-17 17:02:47 +01:00
protocol feat: conduitd workspace registry + lifecycle (conduitctl) 2026-05-17 16:42:28 +01:00
scripts feat: spigot macOS release pipeline + decoupled Nix .app wiring 2026-05-17 17:02:47 +01:00
spigot feat: spigot Linux build + themed GTK header bar chrome 2026-06-29 21:45:28 +01:00
.envrc initial commit: spigot editor scaffold 2026-05-15 18:38:00 +01:00
.gitignore feat: spigot macOS release pipeline + decoupled Nix .app wiring 2026-05-17 17:02:47 +01:00
Cargo.lock feat: spigot Linux build + themed GTK header bar chrome 2026-06-29 21:45:28 +01:00
Cargo.toml feat: conduitd workspace registry + lifecycle (conduitctl) 2026-05-17 16:42:28 +01:00
flake.lock initial commit: spigot editor scaffold 2026-05-15 18:38:00 +01:00
flake.nix feat: spigot Linux build + themed GTK header bar chrome 2026-06-29 21:45:28 +01:00
README.md feat: spigot macOS release pipeline + decoupled Nix .app wiring 2026-05-17 17:02:47 +01:00

conduit - unix pipe your GUIs

A toolkit of small, single-purpose GUI applications for software development on macOS and Linux. Inspired by the Unix philosophy and Plan 9's plumber: instead of one monolithic IDE, conduit is a set of focused windowed tools (editor, filesystem tree, git viewer, etc.) that communicate over a shared IPC protocol.

Programs

Spigot - editor

An editor based on the Monaco editor used in VSCode.

Trunk - git manager

View how repository state has changed over time.

Canopy - file manager

See current filesystem state.

Daemon

Although conduit's composability objectives keeps programs broadly stateless, conduitd exists as a broker to:

  • Share resources for connections to shared services (LSP integration)
  • Expose a network service (for piping from programs across the network - bring your GUI to SSH sessions)
  • Expose an MCP surface (to enable agents like Claude Code to spawn ephemeral GUI applications.)

conduitd runs as a persistent per-user service (Nix-managed). It keeps a registry of workspaces; each registered repo gets its own Claude Code /ide endpoint (lockfile + WebSocket MCP) and drives spigot to render deferred openDiff reviews — accept writes the change, reject discards it. Resources stay warm ~10 min after the last session so they're reused, not respawned.

conduitctl is the control client:

conduitctl add <dir> [--session ID]   register a workspace (root = git toplevel)
conduitctl release <dir> [--session]  drop a session reference (warm-idle GC)
conduitctl list | status              show registered workspaces
conduitctl stop                       stop the daemon
conduitctl hook                       stdin-JSON bridge for Claude hooks
conduitctl install-hooks [--user|--project]

conduitctl install-hooks wires Claude Code SessionStart/SessionEnd to conduitctl hook, so every repo you Claude in auto-registers (and releases on exit) — no manual add.

Service (Nix)

The flake exposes packages.conduitd, nixosModules.conduitd, and darwinModules.conduitd. In your nix-config:

imports = [ conduit.nixosModules.conduitd ];   # or darwinModules.conduitd
services.conduitd.enable = true;

This installs conduitd/conduitctl and runs the daemon as a systemd user unit (NixOS/home-manager) or launchd agent (nix-darwin).

Spigot (macOS .app)

Spigot is a Tauri app — not built in the Nix sandbox (codesign + notarization can't run sandboxed). Instead CI builds it under nix develop, signs + notarizes on a self-hosted aarch64-darwin Forgejo runner, and publishes a release; the flake fetchurls the pinned, signed artifact.

Cutting a release (rolling, CalVer):

git tag spigot-$(date +%Y.%m.%d.%H%M) && git push origin --tags

.forgejo/workflows/release-spigot-macos.yml runs build → sign → notarize → package → upload spigot-<ver>-arm64.app.zip (+ .sha256) to the release for that tag. Then bump version + sha256 in flake.nix packages.spigot.

One-time prerequisites (Forgejo, manual):

  • Repo/org secrets on allison/conduit: APPLE_ID, TEAM_ID, NOTARY_PASSWORD (app-specific password), optional SIGNING_IDENTITY. GITHUB_TOKEN is injected by Forgejo Actions (must have release scope; else add a PAT secret).
  • The self-hosted aarch64-darwin runner (shared with HopNet) scoped to this repo, with a Developer ID Application cert in its login keychain.

Install — spigot is standalone, decoupled from the daemon:

# the app alone (Spotlight/Dock-launchable via mac-app-util):
environment.systemPackages = [ conduit.packages.${pkgs.system}.spigot ];

# optional: let an enabled daemon spawn it for /ide diffs:
services.conduitd.enable = true;
services.conduitd.spigotPackage = conduit.packages.${pkgs.system}.spigot;

Either works without the other. The daemon needs only the binary ($CONDUIT_SPIGOT); the app needs no daemon.

A global throttling Governor (debounce, cross-project fairness, resource caps) and shared LSP servers per workspace plug into the same registry/seam in later slices.