Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Cross-platform background-service install path so launching Burble no
longer pops a terminal window. New `scripts/install-service.sh install`
detects the OS and installs:
- Linux/WSL: systemd `--user` units (`assets/services/burble.service`,
`burble-ai-bridge.service`) — Bolt's `udp/9` privileged bind handled
via `AmbientCapabilities=CAP_NET_BIND_SERVICE` instead of root.
- macOS: launchd LaunchAgents
(`assets/services/com.hyperpolymath.burble.plist`,
`…ai-bridge.plist`) in `~/Library/LaunchAgents/`.
- Windows host (WSL2 NAT): `scripts/wsl-bolt-udp-forward.ps1 -Install`
now installs a **true Windows Service** registered with `sc.exe`
(replaces the previous scheduled-task-at-logon path). A minimal C#
service host is compiled in-place from an embedded source using the
in-box .NET Framework `csc.exe` — no NSSM, srvany, or external
tooling required. The service runs under the installing user's
account (prompted once via `Get-Credential`, password stored by the
SCM via LSA Secrets) because WSL distros are per-user — a
LocalSystem service can launch `wsl.exe` but won't see the user's
distro. Configured for auto-restart on crash (5s/5s/30s). Install
+ uninstall must be run from an elevated PowerShell.
Justfile recipes: `service-install`, `service-uninstall`,
`service-start`, `service-stop`, `service-restart`, `service-status`,
`service-logs`. Relay logs land in `C:\ProgramData\BurbleBoltFwd\relay.log`
on Windows / `journalctl --user -u burble` on Linux /
`/tmp/burble.{out,err}.log` on macOS.
- `Burble.TestSupport.SingletonWatcher` in `test/test_helper.exs` — `Process.monitor`s each of 20 app-owned singletons (PubSub, Presence, RoomRegistry/Supervisor, PeerRegistry/Supervisor, CoprocessorRegistry/Supervisor, MessageStore, NNTPSBackend, Media.Engine, Timing.{PTP,ClockCorrelator,Alignment}, Groove + HealthMesh + Feedback, Transport.RTSP, Bolt.Listener, Endpoint), reports any mid-run death (name + pid + reason + ms-since-start) to stderr at suite end, freezes via `ExUnit.after_suite/1` before BEAM shutdown so the normal app-teardown `:DOWN` cascade is not mistaken for instability. Diagnostic for #62 Bucket B; advisory (does not fail CI).

### Changed
Expand Down
19 changes: 19 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,25 @@ full:
server:
cd server && mix phx.server

# ─── Background-service install (cross-platform, no terminal window) ──────
# systemd --user on Linux/WSL, launchd LaunchAgent on macOS. Windows host
# users should also run scripts\wsl-bolt-udp-forward.ps1 -Install from a
# Windows PowerShell to forward Bolt udp/7373+9 into WSL — windowless.

# Install Burble as a background service (no terminal window pops up)
service-install:
scripts/install-service.sh install

# Remove the Burble background service
service-uninstall:
scripts/install-service.sh uninstall

service-start: ; scripts/install-service.sh start
service-stop: ; scripts/install-service.sh stop
service-restart: ; scripts/install-service.sh restart
service-status: ; scripts/install-service.sh status
service-logs: ; scripts/install-service.sh logs

# Start the web client dev server
client:
cd client/web && deno task dev
Expand Down
28 changes: 28 additions & 0 deletions assets/services/burble-ai-bridge.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: MPL-2.0
#
# Burble AI bridge — Deno HTTP/WS shim on tcp/6474 + tcp/6475 that lets
# Claude Code talk to the in-browser P2P data channel. Installed as a
# systemd *user* unit by scripts/install-service.sh.
#
# Logs: journalctl --user -u burble-ai-bridge -f

[Unit]
Description=Burble Claude<->browser bridge (Deno, http :6474 / ws :6475)
Documentation=https://github.com/hyperpolymath/burble
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=@REPO_DIR@
Environment=LANG=C.UTF-8
ExecStart=/usr/bin/env deno run --allow-net --allow-env client/web/burble-ai-bridge.js
Restart=on-failure
RestartSec=3
TimeoutStopSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=burble-ai-bridge

[Install]
WantedBy=default.target
39 changes: 39 additions & 0 deletions assets/services/burble.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: MPL-2.0
#
# Burble Elixir/Phoenix control-plane service (Bolt udp/7373 + udp/9, voice
# signalling on tcp/4020). Installed as a systemd *user* unit by
# scripts/install-service.sh — the @REPO_DIR@ token is rewritten at install
# time. To install by hand:
#
# sed "s|@REPO_DIR@|$PWD|g" assets/services/burble.service \
# > ~/.config/systemd/user/burble.service
# systemctl --user daemon-reload
# systemctl --user enable --now burble.service
#
# Logs: journalctl --user -u burble -f

[Unit]
Description=Burble voice/media control plane (Elixir, Bolt udp/7373+9, http :4020)
Documentation=https://github.com/hyperpolymath/burble
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=@REPO_DIR@/server
Environment=MIX_ENV=dev
Environment=LANG=C.UTF-8
ExecStart=/usr/bin/env mix phx.server
Restart=on-failure
RestartSec=5
TimeoutStopSec=15
KillMode=mixed
# Bolt binds udp/9 (WoL-compat poke port) which is privileged. Grant just
# the capability instead of running as root.
AmbientCapabilities=CAP_NET_BIND_SERVICE
StandardOutput=journal
StandardError=journal
SyslogIdentifier=burble

[Install]
WantedBy=default.target
43 changes: 43 additions & 0 deletions assets/services/com.hyperpolymath.burble.ai-bridge.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-License-Identifier: MPL-2.0

Burble AI bridge LaunchAgent. Installed by scripts/install-service.sh.
-->
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.hyperpolymath.burble.ai-bridge</string>

<key>ProgramArguments</key>
<array>
<string>/usr/bin/env</string>
<string>deno</string>
<string>run</string>
<string>--allow-net</string>
<string>--allow-env</string>
<string>client/web/burble-ai-bridge.js</string>
</array>

<key>WorkingDirectory</key>
<string>@REPO_DIR@</string>

<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>

<key>StandardOutPath</key>
<string>/tmp/burble-ai-bridge.out.log</string>
<key>StandardErrorPath</key>
<string>/tmp/burble-ai-bridge.err.log</string>

<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
55 changes: 55 additions & 0 deletions assets/services/com.hyperpolymath.burble.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-License-Identifier: MPL-2.0

Burble Elixir/Phoenix control-plane LaunchAgent. Installed by
scripts/install-service.sh into ~/Library/LaunchAgents/. The
@REPO_DIR@ token is rewritten at install time.

Manage:
launchctl load ~/Library/LaunchAgents/com.hyperpolymath.burble.plist
launchctl unload ~/Library/LaunchAgents/com.hyperpolymath.burble.plist
tail -F /tmp/burble.out.log /tmp/burble.err.log
-->
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.hyperpolymath.burble</string>

<key>ProgramArguments</key>
<array>
<string>/usr/bin/env</string>
<string>mix</string>
<string>phx.server</string>
</array>

<key>EnvironmentVariables</key>
<dict>
<key>MIX_ENV</key>
<string>dev</string>
<key>LANG</key>
<string>C.UTF-8</string>
</dict>

<key>WorkingDirectory</key>
<string>@REPO_DIR@/server</string>

<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>

<key>StandardOutPath</key>
<string>/tmp/burble.out.log</string>
<key>StandardErrorPath</key>
<string>/tmp/burble.err.log</string>

<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
35 changes: 30 additions & 5 deletions docs/developer/wsl-mirrored-networking.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,40 @@ changes and none of the mirrored-mode instability.

[source,powershell]
----
# One-time: register a logon scheduled task (optionally add firewall rules
# from an elevated shell):
# One-time: install as a true Windows Service (elevated shell required).
# A minimal C# service host is compiled in-place using the in-box
# .NET Framework csc.exe — no NSSM, no external tooling. New-Service
# prompts via Get-Credential for your password so the service runs
# under YOUR account (WSL distros are per-user; LocalSystem can't see
# them). The password is stored by the SCM via LSA Secrets.
.\scripts\wsl-bolt-udp-forward.ps1 -Install
.\scripts\wsl-bolt-udp-forward.ps1 -Install -Firewall # elevated
.\scripts\wsl-bolt-udp-forward.ps1 -Install -Firewall # also adds inbound rules

# Inspect / run in foreground / remove:
.\scripts\wsl-bolt-udp-forward.ps1 -Status
.\scripts\wsl-bolt-udp-forward.ps1 -Run
.\scripts\wsl-bolt-udp-forward.ps1 -Uninstall
.\scripts\wsl-bolt-udp-forward.ps1 -Run # console, debugging only
.\scripts\wsl-bolt-udp-forward.ps1 -Uninstall # elevated

# Standard service-management surface:
sc.exe query BurbleBoltUdpForward
sc.exe stop BurbleBoltUdpForward
sc.exe start BurbleBoltUdpForward
Get-Service BurbleBoltUdpForward | Format-List *
----

The relay appends to `C:\ProgramData\BurbleBoltFwd\relay.log` so logs
survive across logoffs and reboots. The service is configured for
auto-restart on crash (5s, 5s, 30s).

Inside WSL itself, install Burble's Elixir control plane as a systemd
`--user` service so launching the project never pops a terminal either:

[source,bash]
----
scripts/install-service.sh install # systemd --user (Linux/WSL) or
# launchd LaunchAgent (macOS)
scripts/install-service.sh status
journalctl --user -u burble -f
----

The relay is bidirectional (per-client ephemeral upstream socket, 30 s
Expand Down
Loading
Loading