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 .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ body:
attributes:
label: Louder Bridge version
description: Run `npm run status` for a source install, or use the version from the release filename.
placeholder: 0.3.2 or commit SHA
placeholder: 0.3.3 or commit SHA
validations:
required: true
- type: textarea
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ have not shipped appear under "Unreleased."

There are no unreleased changes.

## 0.3.3 - 2026-08-09

### Fixed

- Hermes plugin setup now installs beside the active profile instead of always
using the default profile.
- Every command in a Hermes setup transaction stays pinned to the profile that
was active when setup began.
- Uninstall removes Louder Bridge's managed plugin and settings from the
default profile and every named profile without changing unrelated plugins.
- Hermes setup, upgrade, removal, and rollback recheck plugin ownership and
managed settings before cleanup continues.
- Indexed Hermes plugin-list cleanup rereads the current list before each
removal so a reordered list cannot delete a different plugin.

## 0.3.2 - 2026-08-08

### Fixed
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ separate panes. Agent Keys switched between the correct panes, lifecycle and
exterior lighting followed each session, both voice routes inserted speech,
and send submitted each prompt once.

Two locally signed development builds containing the v0.3.2 Hermes changes
passed in Ghostty. MIC used Hermes's `Control+B` voice toggle, the Agent Key
focused the correct pane, and the session lighting worked. Releasing MIC after
moving to another pane returned to the original Hermes pane and stopped
recording there. The GitHub-built v0.3.2 candidate still needs its hardware
check before release.
The GitHub-built v0.3.2 archive passed its focused Hermes-in-Ghostty test over
USB. MIC used Hermes's `Control+B` voice toggle, the Agent Key focused the
correct pane, and the session lighting followed the active session. Releasing
MIC after moving to another pane returned to the original Hermes pane and
stopped recording there. The downloaded archive's checksum and app signature
were verified before installation.

The visible Cowork composer route, double-tap latching, approval prompts, wired
restart and power-cycle cases, and the remaining recovery checks still need
Expand Down
27 changes: 18 additions & 9 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,24 @@ The GitHub-built v0.3.1 archive passed the automated release checks and a
downloaded checksum and archive check. The hardware run used the local
candidate, not the published ZIP.

An unreleased locally signed build, revision `809cde7`, passed a focused
Hermes-in-Ghostty test on August 8, 2026. Pressing MIC started Hermes voice
input with `Control+B`, and releasing MIC stopped it with the same shortcut.
The Hermes Agent Key focused the correct pane, and the session lighting worked
as expected.
The v0.3.2 archive downloaded from GitHub passed a focused Hermes-in-Ghostty
test over USB on August 8, 2026:

Follow-up build `b00c76a` passed the focused pane-switch test. When focus moved
to another pane while MIC was held, releasing MIC returned to the original
Hermes pane and stopped recording there.
| Component | Version or result |
|---|---|
| macOS | 26.5.2 (25F84) |
| Ghostty | 1.3.1 |
| Hermes Agent | 0.19.0 (2026.7.20), upstream `a4973c3f` |
| Louder Bridge | 0.3.2, GitHub release archive |
| Embedded Node.js | 22.23.1 |
| Codex Micro firmware | v0.4.1 |
| Connection | USB |
| Voice | MIC started and stopped Hermes recording with `Control+B` |
| Pane switch | MIC release returned to the pane where recording began |
| Navigation | The Hermes Agent Key focused the correct pane |
| Lighting | Session and exterior lighting followed the active session |

The archive checksum and app signature were verified before installation.

## Latest Hermes candidate qualification

Expand Down Expand Up @@ -85,7 +94,7 @@ lifecycle event. The bridge received no audio or transcript text.
This test used the locally generated ad-hoc archive, not an asset downloaded
from GitHub.

## Latest downloaded-release hardware qualification
## Earlier Claude Desktop package qualification

The v0.1.2 archive downloaded from GitHub passed a physical test on August 4,
2026:
Expand Down
2 changes: 1 addition & 1 deletion docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ Returns bridge status and the six current slot states:
"activeSurface": "claude",
"inputMonitoring": "granted",
"accessibility": "granted",
"version": "0.3.2",
"version": "0.3.3",
"buildRevision": "0123456789abcdef0123456789abcdef01234567",
"nodeVersion": "v24.8.0",
"navigator": {
Expand Down
14 changes: 7 additions & 7 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,13 @@ A locally built v0.3.1 candidate passed a mixed-pane USB test on August 8,
| Agent Keys | Switched to the correct pane |
| Lifecycle response | Key and exterior lighting followed both sessions |

Hermes-in-Ghostty controls passed a physical test with build `809cde7` on
August 8, 2026. The bridge recorded a matching voice start and stop, Hermes
voice input worked, the Agent Key focused the correct pane, and the session
lighting behaved as expected.

Follow-up build `b00c76a` passed the pane-switch check. Releasing MIC after
moving focus returned to the original Hermes pane and stopped recording there.
The v0.3.2 archive downloaded from GitHub passed the focused Hermes-in-Ghostty
check over USB on August 8, 2026. MIC started and stopped Hermes recording with
`Control+B`, the Agent Key focused the correct pane, and the session and
exterior lighting followed the active session. The pane-switch check also
passed: releasing MIC after moving focus returned to the pane where recording
began and stopped it there. The archive checksum and app signature were
verified before installation.

## Latest Hermes candidate result

Expand Down
4 changes: 2 additions & 2 deletions 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 package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "louder-bridge",
"version": "0.3.2",
"version": "0.3.3",
"private": true,
"license": "MIT",
"description": "Use a Work Louder Codex Micro with Claude, Hermes, and terminal agents in Ghostty",
Expand Down
18 changes: 8 additions & 10 deletions release-notes/v0.3.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ macOS Dictation.

## Hardware result

The Hermes changes passed in locally signed development builds over USB on
August 8, 2026. MIC started and stopped Hermes voice input, the Agent Key
focused the correct pane, and the session lighting worked as expected. A
follow-up build covered moving focus to another pane while MIC was held;
releasing MIC returned to the original Hermes pane and stopped recording
there. The GitHub-built v0.3.2 candidate has not yet completed its hardware
check.
The GitHub-built v0.3.2 archive passed its focused Hermes-in-Ghostty hardware
check over USB on August 8, 2026. MIC started and stopped Hermes voice input,
the Agent Key focused the correct pane, and the session lighting followed the
active session. The pane-switch test also passed: after focus moved while MIC
was held, releasing MIC returned to the original Hermes pane and stopped
recording there.

The archive checksum and app signature were verified before installation.

| Component | Version or result |
|---|---|
Expand All @@ -37,9 +38,6 @@ check.
| Connection | USB |
| Automated tests | 360 passed |

The GitHub-built ZIP still needs the release checklist before this draft is
published.

## Install

Download the Apple Silicon ZIP, move **Louder Bridge.app** to **Applications**,
Expand Down
48 changes: 48 additions & 0 deletions release-notes/v0.3.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Louder Bridge 0.3.3

This prerelease fixes Hermes setup when a named profile is active.

## What changed

- Louder Bridge now asks Hermes which profile is active and installs its plugin
beside that profile's config file.
- Every command in the setup transaction stays pinned to the same profile,
even if the active Hermes profile changes before setup finishes.
- Uninstall checks the default profile and every named profile for managed
copies of the plugin.
- Setup, upgrades, removal, and rollback preserve unrelated Hermes settings
and refuse to delete a plugin directory Louder Bridge does not own.
- Plugin-list cleanup rereads the current list before each removal instead of
reusing an old numeric index.

Voice input, Agent Key navigation, send, and lighting behavior are unchanged.

## Validation

The source passed 385 automated tests, including the Node.js 22, 24, and 26
matrix and the package smoke test. Setup and rollback also passed a real Hermes
CLI smoke test with an isolated named profile.

The exact ZIP built by GitHub still needs the focused Hermes hardware check
before this draft can be published. Record the tested versions and connection
type here after that run.

## Install

Download the Apple Silicon ZIP, move **Louder Bridge.app** to **Applications**,
and open it once. If macOS blocks it, open **System Settings → Privacy &
Security** and choose **Open Anyway**. Approve Input Monitoring and
Accessibility for Louder Bridge. Ghostty may also ask for Automation permission
the first time an Agent Key selects a terminal.

The GitHub build uses an ad-hoc signature, so macOS may ask for permissions
again after an upgrade.

## Privacy

Louder Bridge runs locally. It collects no telemetry, audio, transcripts,
prompt content, project names, or session identifiers. Local diagnostics
require a private authentication token.

This remains a prerelease. Ghostty labels its AppleScript API as a preview, and
the device driver uses an independently documented protocol.
2 changes: 1 addition & 1 deletion src/hermes/plugin/plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: louder-bridge
version: "0.3.2"
version: "0.3.3"
description: Send Hermes session state to a locally installed Louder Bridge
provides_hooks:
- on_session_start
Expand Down
2 changes: 1 addition & 1 deletion src/setup/application-bundle.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export function applicationBundlePathsForCli(cliPath) {
return applicationBundlePathsForApp(app);
}

export function applicationInfoPlist({ version = "0.3.2" } = {}) {
export function applicationInfoPlist({ version = "0.3.3" } = {}) {
return `<?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">
Expand Down
2 changes: 1 addition & 1 deletion test/cli.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ test("prints CLI help without starting the bridge", () => {
test("prints the package version", () => {
const result = run(["--version"]);
assert.equal(result.status, 0);
assert.equal(result.stdout.trim(), "0.3.2");
assert.equal(result.stdout.trim(), "0.3.3");
});

test("checks source build tools before the native driver is installed", (context) => {
Expand Down
8 changes: 4 additions & 4 deletions test/release-check.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,26 @@ function run(refName, { branchRef = "HEAD" } = {}) {
}

test("requires the release tag to match the package version", () => {
const matching = run("v0.3.2");
const matching = run("v0.3.3");
assert.equal(matching.status, 0, matching.stderr);

const mismatched = run("v0.1.0");
assert.equal(mismatched.status, 1);
assert.match(
mismatched.stderr,
/Release tag v0\.1\.0 does not match package version 0\.3\.2/,
/Release tag v0\.1\.0 does not match package version 0\.3\.3/,
);
});

test("requires the release tag commit to belong to the protected branch", () => {
const outsideBranch = run("v0.3.2", { branchRef: "HEAD^" });
const outsideBranch = run("v0.3.3", { branchRef: "HEAD^" });
assert.equal(outsideBranch.status, 1);
assert.match(
outsideBranch.stderr,
/release tag commit is not part of HEAD\^/,
);

const missingBranch = run("v0.3.2", { branchRef: null });
const missingBranch = run("v0.3.3", { branchRef: null });
assert.equal(missingBranch.status, 1);
assert.match(
missingBranch.stderr,
Expand Down
2 changes: 1 addition & 1 deletion test/server.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ test("reports service and device health", async (context) => {
inputMonitoring: "unknown",
accessibility: "unknown",
activeSurface: "claude",
version: "0.3.2",
version: "0.3.3",
buildRevision: null,
nodeVersion: process.version,
navigator: {
Expand Down
4 changes: 2 additions & 2 deletions test/service-readiness.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ test("accepts the real authenticated bridge health endpoint", async (context) =>

const health = await waitForBridgeReady({
authToken,
expectedVersion: "0.3.2",
expectedVersion: "0.3.3",
url: `http://127.0.0.1:${address.port}`,
attempts: 1,
});

assert.equal(health.ok, true);
assert.equal(health.service.mode, "service");
assert.equal(health.service.version, "0.3.2");
assert.equal(health.service.version, "0.3.3");
});

test("waits for the authenticated background agent health response", async () => {
Expand Down