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
11 changes: 11 additions & 0 deletions .codex/environments/environment.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY
version = 1
name = "microbridge"

[setup]
script = ""

[[actions]]
name = "Run"
icon = "run"
command = "./script/build_and_run.sh"
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,12 @@ jobs:
npm ci
# Bundle the daemon inside direct-download apps so the device twin
# always has a real local source of truth without a separate install.
cargo build --manifest-path ../../Cargo.toml --release -p microbridged --target ${{ matrix.target }}
cargo build --manifest-path ../../Cargo.toml --release -p microbridged -p microbridgectl --target ${{ matrix.target }}
mkdir -p src-tauri/binaries
cp "../../target/${{ matrix.target }}/release/microbridged" \
"src-tauri/binaries/microbridged-${{ matrix.target }}"
cp "../../target/${{ matrix.target }}/release/microbridgectl" \
"src-tauri/binaries/microbridgectl-${{ matrix.target }}"
# createUpdaterArtifacts (tauri.conf.json) requires the updater signing
# key. Forks without the secret still build — just without in-app
# updater artifacts (they can use the DMG / Homebrew).
Expand Down
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ members = [
]

[workspace.package]
version = "0.2.4"
version = "0.3.0"
edition = "2021"
license = "MIT"
repository = "https://github.com/DevVig/microbridge"

[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "io-util", "sync", "time", "fs", "signal"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "io-util", "sync", "time", "fs", "signal", "process"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
toml = "0.8"
Expand Down
15 changes: 15 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ Cursor's supported local-plugin directory after that explicit consent. Reload
Cursor once if it is already open. **Remove** disables the adapter and removes
only Microbridge's local integration. No Marketplace download is required.

### Factory integration

Factory support ships inside Microbridge. Open **Settings → Adapters** and
click **Enable Factory**. Microbridge copies its signed `microbridgectl` helper
to `~/.microbridge/integrations/factory/` and merges only its own entries into
Factory's supported `~/.factory/hooks.json`; existing hooks are preserved.
**Remove** deletes the Microbridge-owned hook entries and helper. Droid must be
installed and signed in for interrupt and reasoning-effort controls.

Synara and Conductor do not need an installer: their Codex/Claude sessions are
named by the built-in journal watchers. T3 Code controls require the one-time
pairing flow shown in **Settings → Adapters**.

**Note:** Homebrew installs **prebuilt** release binaries (not a from-source
Tauri build). The formula checksums are refreshed by CI after each `v*` tag.

Expand All @@ -132,6 +145,8 @@ Tauri build). The formula checksums are refreshed by CI after each `v*` tag.
| `~/.microbridge/config.toml` | Key source, lighting, appearance |
| `~/.microbridge/daemon.log` | launchd / service logs |
| `~/.cursor/plugins/local/microbridge` | Bundled Cursor lifecycle integration (only after consent) |
| `~/.factory/hooks.json` | Existing Factory hooks plus Microbridge-owned lifecycle entries (only after consent) |
| `~/.microbridge/integrations/factory/microbridgectl` | Signed Factory hook helper (only after consent) |
| `~/Library/LaunchAgents/ai.microbridge.ui.plist` | Login item (only if you enable launch at login) |

## Launch at login
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

**An open-source control plane for the Codex Micro — one macropad, every coding agent.**

Microbridge is a tiny local daemon that bridges AI coding agents — Codex CLI, Claude Code, Cursor, T3 Code, and anything else with an adapter — to the [Work Louder Codex Micro](https://worklouder.cc/). Per-key RGB mirrors live agent state; keys route only the actions each adapter explicitly advertises, so unsupported controls never report false success. No vendor desktop app is required for Microbridge itself.
Microbridge is a tiny local daemon that bridges AI coding agents — Codex CLI, Claude Code, Cursor, T3 Code, Synara, Conductor, Factory, and anything else with an adapter — to the [Work Louder Codex Micro](https://worklouder.cc/). Per-key RGB mirrors live agent state; keys route only the actions each adapter explicitly advertises, so unsupported controls never report false success. No vendor desktop app is required for Microbridge itself.

> **Status: early public alpha (`v0.2.x`).** Menu bar UI, local daemon, in-process Codex/Claude watchers, and signed macOS packages are shipping. Cursor lifecycle reception and paired T3 Code control are opt-in and capability-gated. **HID protocol (VID/PID, framing, `v.oai.thstatus`) is implemented from ChatGPT’s Work Louder kit**; hardware control stays off until enabled in Device settings (or `MICROBRIDGE_HID_CLAIM=1` is set for diagnostics) while physical validation is completed. See [docs/device-hid.md](docs/device-hid.md).
> **Status: early public alpha (`v0.3.x`).** Menu bar UI, local daemon, in-process Codex/Claude host attribution, and signed macOS packages are shipping. Cursor and Factory lifecycle reception and paired T3 Code control are opt-in and capability-gated. **HID protocol (VID/PID, framing, `v.oai.thstatus`) is implemented from ChatGPT’s Work Louder kit**; hardware control stays off until enabled in Device settings (or `MICROBRIDGE_HID_CLAIM=1` is set for diagnostics) while physical validation is completed. See [docs/device-hid.md](docs/device-hid.md).

## Screenshots

Expand Down Expand Up @@ -41,7 +41,7 @@ The Micro's best feature — bidirectional Agent Keys — currently works throug
## Design principles

1. **Invisible footprint.** Local watchers are event-driven; device input and an explicitly paired T3 connection use bounded polling and backoff. Idle CPU and RSS remain part of the [footprint budget](docs/architecture.md#footprint-budget).
2. **Local-first and explicit network access.** There is no telemetry or cloud relay. The app checks for updates only when requested or enabled, and the daemon contacts a T3 environment only after the user enables the adapter and supplies a one-time pairing link.
2. **Local-first and explicit network access.** There is no telemetry or Microbridge cloud relay. The app checks for updates only when requested or enabled, and the daemon contacts a T3 environment only after the user enables the adapter and supplies a one-time pairing link. Factory controls invoke the user-installed `droid` CLI only when a hardware action is requested.
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 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.

Expand All @@ -50,6 +50,13 @@ once in **Settings → Adapters**; Microbridge installs its bundled lifecycle
integration into Cursor's supported local-plugin directory. There is no
separate Marketplace download or second product to maintain.

Factory support is also bundled. Enabling it merges Microbridge-owned entries
into Factory's official user hooks without replacing existing hooks; the knob
uses Factory's public JSON-RPC session settings and only cycles levels the
active model advertises. Synara and Conductor sessions are attributed through
the built-in Codex/Claude watchers, so they need no pairing code or extra
background adapter.

## Architecture

```
Expand Down
9 changes: 6 additions & 3 deletions adapters/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ checklist, and [docs/protocol.md](../docs/protocol.md) for the wire format.
| Adapter | Status | Language |
|---|---|---|
| [`reference-echo`](reference-echo/) | working example | Node (no deps) |
| [`cursor`](cursor/) | scaffold — awaiting session source | Node |
| [`t3code`](t3code/) | scaffold — awaiting session source | Node |
| [`cursor`](cursor/) | bundled managed hooks | Node |
| [`t3code`](t3code/) | daemon-owned paired HTTP | Rust |
| [`factory`](factory/) | bundled official hooks + JSON-RPC controls | Rust helper |
| [`synara`](synara/) | built-in host attribution | Rust |
| [`conductor`](conductor/) | built-in host attribution | Rust |

First-party adapters (Codex CLI, Claude Code) are compiled into the daemon
First-party watchers (Codex CLI, Claude Code, including their embedding hosts) are compiled into the daemon
(`crates/mb-adapters`) — see [docs/architecture.md](../docs/architecture.md).
11 changes: 11 additions & 0 deletions adapters/conductor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Conductor integration

Conductor needs no pairing code for lifecycle detection. Codex and Claude
sessions running under `~/conductor/workspaces` are attributed to **Conductor**
by Microbridge's existing journal watchers, with no new poller or network call.

Conductor's public API exposes session creation, status, cancellation, and deep
links, but does not expose a reliable mapping from an underlying Codex/Claude
journal id to the Conductor session id or an active-session effort update.
Microbridge therefore advertises lifecycle only instead of guessing with local
database reads or keyboard automation.
21 changes: 21 additions & 0 deletions adapters/factory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Factory integration

Enable Factory in **Microbridge Settings → Adapters**. The app transactionally
merges Microbridge-owned commands into Factory's official user hooks at
`~/.factory/hooks.json` and installs a signed helper at
`~/.microbridge/integrations/factory/microbridgectl`. Existing hooks are
preserved; **Remove** deletes only Microbridge-owned entries and the helper.

## Supported behavior

- Lifecycle: `SessionStart`, `UserPromptSubmit`, `Notification`, `PreToolUse`,
`PostToolUse`, `Stop`, and `SessionEnd`.
- Interrupt: Factory's public `droid.interrupt_session` JSON-RPC method.
- Knob: Factory's public `droid.update_session_settings` method. Microbridge
reads the active session's documented settings and cycles only the reasoning
levels advertised by the installed Droid model catalogue.

There is no resident Factory bridge process and no polling. Hooks run on state
transitions; control starts `droid` only for the requested hardware action.
Microbridge finds Droid in Factory.app, `~/.local/bin`, or common Homebrew
locations; custom installations can set `FACTORY_DROID_PATH` for the daemon.
10 changes: 10 additions & 0 deletions adapters/synara/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Synara integration

Synara needs no separate adapter process or pairing code. Its Codex and Claude
Agent SDK sessions use the standard agent journals, and Microbridge's built-in
watchers attribute them to **Synara** from the journal's official host metadata
or Synara worktree path.

Lifecycle LEDs and Agent Key assignment work automatically. Commands remain
limited to capabilities exposed by the underlying Codex or Claude contract;
Microbridge does not inspect Synara private state or synthesize keystrokes.
11 changes: 8 additions & 3 deletions adapters/t3code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ its host contract and replaces the former idle Node scaffold.
## Pairing

1. Enable T3 Code in **Microbridge Settings → Adapters**.
2. In T3 Code, open **Settings → Connections** and create a one-time pairing link.
2. In T3 Code, open **Settings → Connections**, enable **Network access**, then
create a one-time link under **Authorized clients**.
3. Paste the link into Microbridge. The one-time token is exchanged immediately.
4. The resulting bearer credential is stored in macOS Keychain under
`ai.microbridge.t3code` and is removed by **Remove**.
Expand All @@ -16,14 +17,18 @@ Microbridge uses T3 Code's authenticated public endpoints:
- `GET /api/orchestration/shell` for lifecycle snapshots.
- `GET /api/orchestration/threads/:threadId` for pending approval identity.
- `POST /api/orchestration/dispatch` for approval and interrupt commands.
- `t3code://threads/:environmentId/:threadId` to open the owning thread.

It never reads T3 Code databases, bootstrap credentials, or desktop internals.

The compatibility suite is pinned to T3 server `0.0.28` and upstream contract
commit `ebe8afb1df357423a0e036b388af3e739d640205`. Other server versions are
reported as **Incompatible** until Microbridge verifies and ships their contract.
The adapter reports **Limited** when the paired HTTP contract does not advertise
focus/open or provider option descriptors for reasoning-effort adjustment.
The adapter opens threads with T3 Code's semantic deep link. Reasoning effort
stays disabled because the current paired HTTP snapshot includes the selected
value but not the provider/model option descriptors needed to choose the next
valid level safely. Microbridge does not fake this with key presses or private
desktop state.

The compatibility target is the contract present in `pingdotgg/t3code` as of
July 18, 2026. Authentication failures return to **Needs setup**; transport
Expand Down
4 changes: 2 additions & 2 deletions apps/microbridge-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/microbridge-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "microbridge-ui",
"private": true,
"version": "0.2.4",
"version": "0.3.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
4 changes: 2 additions & 2 deletions apps/microbridge-ui/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/microbridge-ui/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "microbridge-ui"
version = "0.2.4"
version = "0.3.0"
description = "Microbridge menu bar app (primary UI)"
authors = ["Microbridge contributors"]
edition = "2021"
Expand Down
Loading
Loading