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
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ End-user install paths are documented in [INSTALL.md](INSTALL.md)
cargo fmt --all
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
# optional UI:
# menu bar app:
cd apps/microbridge-ui && npm ci && npm run build
```

Expand Down
22 changes: 7 additions & 15 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Installing Microbridge

Microbridge is a local daemon plus an optional companion UI. There is **no
cloud account** — install puts binaries on your machine and runs a user-level
service.
Microbridge installs a **menu bar app** (primary UI for the keyboard) plus a
local daemon that drives the Micro. There is **no cloud account** — everything
runs on your machine.

## Recommended on macOS: Homebrew (with updates)

Expand Down Expand Up @@ -51,30 +51,22 @@ Governance / why this path: [docs/governance.md](docs/governance.md).
| Piece | Need |
|---|---|
| Daemon (Homebrew) | Homebrew; Rust pulled in as a build dependency |
| Daemon (from source) | Rust stable (`rustup`), macOS 13+ or Linux |
| Companion UI (optional) | Node ≥ 20; full `.app` also needs Xcode CLT |
| Full install (from source) | Rust stable, Node ≥ 20; macOS also needs Xcode CLT for the `.app` |
| Hardware LEDs | Codex Micro over USB (HID packing still landing — mock works without hardware) |

## From source (developers)

```sh
git clone https://github.com/DevVig/microbridge.git
cd microbridge
./scripts/install.sh # macOS: binaries + launchd
# ./scripts/install.sh --with-ui
./scripts/install.sh # macOS: daemon + menu bar app + launchd
# ./scripts/install.sh --no-ui # daemon/CLI only (headless)
# ./scripts/install-linux-systemd.sh
microbridgectl status
```

Uninstall: `./scripts/uninstall.sh` (add `--purge` to remove `~/.microbridge`).

### Optional companion UI

```sh
./scripts/install.sh --with-ui
# or during development:
cd apps/microbridge-ui && npm install && npm run dev
```
During UI development: `cd apps/microbridge-ui && npm install && npm run tauri dev`.

## Linux

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ The Micro's best feature — bidirectional Agent Keys — currently works throug
1. **Invisible footprint.** Event-driven end to end: no polling loops, no heartbeat timers. Idle CPU is 0.0% and idle RSS targets single-digit megabytes. If Microbridge is noticeable in Activity Monitor, that is a bug — the [footprint budget](docs/architecture.md#footprint-budget) is a spec, not an aspiration.
2. **Zero network.** No telemetry, no update pings, no cloud. The daemon's only I/O is a local Unix socket and the USB device. It links no HTTP client — auditable in `Cargo.lock`.
3. **Rust core, any-language adapters.** The always-resident part is a single static Rust binary. First-party adapters compile into it (in-process, ~zero overhead). Community adapters are separate processes speaking [newline-delimited JSON](docs/protocol.md) — write one in whatever you like.
4. **The UI is optional.** A menu bar companion shows connection status and opens Settings for key remapping; you can quit it and the daemon keeps working.
4. **The menu bar app is the product UI.** Configure keys, lighting, and adapters there. The daemon keeps the hardware alive underneath; `microbridgectl` is a support/debug escape hatch.

## Architecture

Expand All @@ -61,7 +61,7 @@ The Micro's best feature — bidirectional Agent Keys — currently works throug
└──────────────────────┬───────────────────────────┘
│ same socket (status + commands)
┌─────────┴─────────┐
│ menu bar app │ optional, quit-able (Tauri)
│ menu bar app │ primary UI (Tauri)
└───────────────────┘
```

Expand All @@ -74,8 +74,8 @@ crates/mb-protocol wire types (serde) — the protocol's source of truth
crates/mb-device device abstraction; mock today, HID packing TBD
crates/mb-adapters first-party Codex CLI + Claude Code watchers
crates/microbridged the daemon: socket server, registry, focus, key source
crates/microbridgectl inspect a live bus (`status`)
apps/microbridge-ui optional Tauri companion (MagicPath-faithful)
crates/microbridgectl support/debug CLI (`status`)
apps/microbridge-ui menu bar app — primary UI (MagicPath-faithful)
adapters/ out-of-process community adapters + reference impl
docs/ protocol, architecture, adapter guide, design, HID notes
```
Expand Down
5 changes: 3 additions & 2 deletions apps/microbridge-ui/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# microbridge-ui

Optional Tauri 2 companion for Microbridge. **Status + setup only** — agent
actions stay on the physical Codex Micro.
Primary Microbridge UI (Tauri 2 menu bar app). **Status + setup** for the
keyboard — agent actions (approve / reject / interrupt) stay on the physical
Codex Micro.

MagicPath mockups remain the visual go-to:

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
| `microbridged` | resident daemon (launchd agent) | Rust | yes |
| First-party adapters (Codex CLI, Claude Code) | in-process modules of the daemon | Rust | bundled |
| Community adapters | separate processes on the socket | any | optional |
| Menu bar app | tray app talking to the same socket | Tauri 2 + React (`apps/microbridge-ui`) | optional, quit-able |
| Menu bar app | primary UI (tray + settings + focus HUD) | Tauri 2 + React (`apps/microbridge-ui`) | yes (default install) |

The daemon owns three things: the **status bus** (session registry fed by
adapters), the **focus policy** (which session owns the deck), and the
Expand Down
25 changes: 16 additions & 9 deletions docs/design/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# UI design

The interface direction for Microbridge's optional UI surfaces. **MagicPath
interactive mockups are the go-to reference** for M3 implementation; this
document describes what they show and why.
The menu bar app is the **primary** way people deal with the keyboard.
**MagicPath interactive mockups are the go-to reference**; this document
describes what they show and why.

## Lean companion principle

Expand Down Expand Up @@ -138,10 +138,17 @@ Keyboard setup. Four sections in a left rail:

### 3. Focus HUD — [interactive mockup](https://api.magicpath.ai/v1/sunnily-shadow-8075)

A transient, **non-interactive** frosted overlay confirming deck ownership
when focus changes: app badge, app name, thread title, state chip, a
six-key echo of miniature frosted caps with the focused key lit,
press-behavior hint, and a 2px drain bar (~2.5s). No buttons on the HUD card.
A transient, **non-interactive** frosted overlay confirming **deck focus** —
which single thread currently owns Approve / Reject / dial / command keys.

**When it appears (you don’t open it):** whenever the daemon’s focused
session changes, for about 2.5 seconds — for example after you press an
Agent Key, an approval preempts another thread, or auto-follow moves the
deck to another app. It is a glanceable confirmation, not a settings
screen. No buttons on the HUD card.

Contents: app badge, app name, thread title, state chip, a six-key echo
with the focused key lit, press-behavior hint, and a 2px drain bar.

## Interaction rules

Expand All @@ -157,8 +164,8 @@ press-behavior hint, and a 2px drain bar (~2.5s). No buttons on the HUD card.
- **Approvals are privileged on the deck**, not in the popover. An
`awaiting_approval` thread may temporarily claim the approve/reject keys
(user-toggleable in Settings → Agent Keys).
- The UI processes are optional; quitting them changes nothing about the
daemon's behavior.
- Quitting the menu bar app does not stop the daemon or LEDs; you lose
status/setup chrome until you reopen it.

## Assets

Expand Down
60 changes: 49 additions & 11 deletions scripts/install.sh
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
#!/usr/bin/env bash
# Unified Microbridge installer (daemon + optional UI).
# Unified Microbridge installer daemon + menu bar app (default).
set -euo pipefail

ROOT="$(cd "$(dirname "$0")/.." && pwd)"
BIN_DIR="${MICROBRIDGE_BIN:-$HOME/.local/bin}"
WITH_UI=0
WITH_UI=1
WITH_LAUNCHD=1
LABEL="ai.microbridge.daemon"
UI_LABEL="ai.microbridge.ui"

usage() {
cat <<EOF
Usage: ./scripts/install.sh [options]

--with-ui Also set up apps/microbridge-ui (npm; Tauri build if available)
--no-launchd Skip macOS launchd agent (Linux default behavior unless Darwin)
--no-ui Skip the menu bar companion (daemon/CLI only)
--no-launchd Skip macOS launchd agents
--bin-dir DIR Install binaries here (default: ~/.local/bin)
-h, --help Show this help
EOF
}

while [[ $# -gt 0 ]]; do
case "$1" in
--with-ui) WITH_UI=1; shift ;;
--no-ui) WITH_UI=0; shift ;;
--with-ui) WITH_UI=1; shift ;; # back-compat; UI is already default
--no-launchd) WITH_LAUNCHD=0; shift ;;
--bin-dir) BIN_DIR="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
Expand Down Expand Up @@ -128,25 +130,61 @@ else
fi

if [[ "$WITH_UI" -eq 1 ]]; then
echo "==> Companion UI"
echo "==> Menu bar app (primary UI)"
need npm
(
cd "$ROOT/apps/microbridge-ui"
npm ci
npm run build
if command -v cargo >/dev/null && [[ -d src-tauri ]]; then
if npm run tauri build; then
echo " Tauri app built under apps/microbridge-ui/src-tauri/target/release/bundle/"
if npm run tauri build; then
APP_SRC="$(find "$ROOT/apps/microbridge-ui/src-tauri/target/release/bundle" -name 'Microbridge.app' -type d 2>/dev/null | head -n1 || true)"
if [[ -n "$APP_SRC" && "$(uname -s)" == "Darwin" ]]; then
rm -rf "$HOME/Applications/Microbridge.app"
mkdir -p "$HOME/Applications"
cp -R "$APP_SRC" "$HOME/Applications/Microbridge.app"
echo " installed ~/Applications/Microbridge.app"
if [[ "$WITH_LAUNCHD" -eq 1 ]]; then
UI_PLIST="$HOME/Library/LaunchAgents/${UI_LABEL}.plist"
cat >"$UI_PLIST" <<EOF
Comment on lines +147 to +148
<?xml version="1.0" encoding="UTF-8"?>
<!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>${UI_LABEL}</string>
<key>ProgramArguments</key>
<array>
<string>${HOME}/Applications/Microbridge.app/Contents/MacOS/microbridge-ui</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
</dict>
</plist>
EOF
launchctl bootout "gui/$(id -u)/${UI_LABEL}" 2>/dev/null || true
launchctl bootstrap "gui/$(id -u)" "$UI_PLIST"
launchctl enable "gui/$(id -u)/${UI_LABEL}"
launchctl kickstart -k "gui/$(id -u)/${UI_LABEL}" 2>/dev/null || open "$HOME/Applications/Microbridge.app"
echo " menu bar app set to launch at login"
else
open "$HOME/Applications/Microbridge.app" 2>/dev/null || true
fi
else
echo " note: Tauri bundle skipped/failed — web build is in apps/microbridge-ui/dist"
echo " run: cd apps/microbridge-ui && npm run dev"
echo " note: .app bundle not found — web build is in apps/microbridge-ui/dist"
echo " run: cd apps/microbridge-ui && npm run tauri dev"
fi
else
echo " note: Tauri bundle failed — web build is in apps/microbridge-ui/dist"
echo " run: cd apps/microbridge-ui && npm run tauri dev"
fi
)
fi

echo ""
echo "Microbridge installed."
echo " UI: ~/Applications/Microbridge.app (menu bar)"
echo " status: $BIN_DIR/microbridgectl status"
echo " logs: ~/.microbridge/daemon.log"
echo " config: ~/.microbridge/config.toml"
Comment on lines 185 to 190
Expand Down
9 changes: 8 additions & 1 deletion scripts/uninstall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set -euo pipefail

BIN_DIR="${MICROBRIDGE_BIN:-$HOME/.local/bin}"
LABEL="ai.microbridge.daemon"
UI_LABEL="ai.microbridge.ui"
PURGE=0

usage() {
Expand All @@ -23,9 +24,15 @@ while [[ $# -gt 0 ]]; do
done

if [[ "$(uname -s)" == "Darwin" ]]; then
echo "==> Stopping launchd agent"
echo "==> Stopping launchd agents"
launchctl bootout "gui/$(id -u)/${LABEL}" 2>/dev/null || true
launchctl bootout "gui/$(id -u)/${UI_LABEL}" 2>/dev/null || true
rm -f "$HOME/Library/LaunchAgents/${LABEL}.plist"
rm -f "$HOME/Library/LaunchAgents/${UI_LABEL}.plist"
if [[ -d "$HOME/Applications/Microbridge.app" ]]; then
echo "==> Removing menu bar app"
rm -rf "$HOME/Applications/Microbridge.app"
fi
fi

if [[ -f "$HOME/.config/systemd/user/microbridge.service" ]]; then
Expand Down
Loading