Skip to content

Add agent-friendly Beeper install script; fix README platform support#15

Open
Miyamura80 wants to merge 16 commits into
mainfrom
claude/relaxed-planck-dtn99w
Open

Add agent-friendly Beeper install script; fix README platform support#15
Miyamura80 wants to merge 16 commits into
mainfrom
claude/relaxed-planck-dtn99w

Conversation

@Miyamura80

@Miyamura80 Miyamura80 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What

Adds scripts/install-beeper.sh, a one-command installer that wires Beeper into the Edison Watch MCP gateway, and corrects a stale "macOS only" claim in the README.

The install script

Thin orchestrator over the beeper and edison-stdiod CLIs plus two REST calls. install runs the full flow idempotently:

deps -> headless Beeper Server -> stdiod login+install -> register beeper child -> bind token -> print MCP URL

End-to-end path it sets up:

AI client --MCP--> Edison Gateway --WS tunnel--> edison-stdiod --stdio--> npx @beeper/desktop-mcp --HTTP :23373--> Beeper Server --> WhatsApp / Telegram / LinkedIn

Built to be driven by an agent or a human:

  • Non-interactive by default; every input is a flag or an UPPER_SNAKE env var. Prompts only run behind --interactive.
  • --dry-run, --yes, --json, --verbose, --install-deps.
  • resource+verb subcommands: install, doctor, status, network add|list, mcp-url, uninstall.
  • Every --help carries runnable examples; missing inputs fail fast with the exact fix.
  • Returns data on success (mcp_url, auth header, ready-to-paste claude mcp add ...).

Example:

./scripts/install-beeper.sh install --install-deps --yes \
  --ew-api-key ew_live_abc --beeper-token bpr_xyz \
  --networks whatsapp,telegram,linkedin

Validated by actually running it

Exercised on Linux against the real edison-stdiod binary (built from this checkout) plus a stubbed beeper. Confirmed every flag the script calls matches the binary's --help (login, install, server add/list/remove), and that login writes a correct config.toml. Running it surfaced and fixed several defects: an IFS leak that mangled dry-run logging, a token-bind curl printing http 000000 with no timeout, a dry-run abort when no token was supplied, and a raw daemon backtrace plus mid-flow set -e abort on install failure (now a clean actionable message).

Known seams (need a live backend / Mac to verify)

Three integration points are wrapped defensively and marked, not faked:

  1. Headless Beeper token minting (documented path is the GUI; --beeper-token overrides).
  2. Edison Watch account bootstrap (currently requires --ew-api-key).
  3. The token-to-child bind route POST /api/v1/servers/<name>/env is a best guess (overridable via EW_SERVER_ENV_PATH); non-fatal with a manual fallback if it 404s. The clean alternative is a small edison-stdiod server env subcommand.

README fix

The WARNING claimed the daemon is "macOS only," but src/platform/ implements supervisor integration for macOS (LaunchAgent), Linux (systemd --user), and Windows (Scheduled Task); only other OSes hit the runtime stub. Updated the WARNING, the quickstart install comment, and the CLI table to match the code, while noting macOS is the most exercised target.

Test plan

  • bash -n + repo AI-writing hook pass
  • edison-stdiod builds; script flags match its --help
  • dry-run, --json, fail-fast, and clean-failure paths exercised on Linux
  • End-to-end on macOS with the real beeper CLI and a live Edison backend

🤖 Generated with Claude Code


Generated by Claude Code


Summary by cubic

Adds a one-command, agent-friendly installer to wire Beeper into the Edison Watch MCP gateway, and updates the README for macOS, Linux, and Windows support. Headless setup reuses the Beeper CLI token, validates the Desktop API, and cleanly handles conflicts and step-up reauth when registering the tunnel child.

  • New Features

    • scripts/install-beeper.sh: installs deps, starts headless beeper, logs in and installs edison-stdiod, registers npx @beeper/desktop-mcp (uses --arg=-y), binds the Beeper token, and prints the MCP URL or --json.
    • Headless token reuse: pulls accessToken from ~/.beeper/targets/*.json, small JSON files, and macOS Keychain; validates via the local OAuth userinfo; probes 127.0.0.1, [::1], and localhost on ports 23373–23378; adds a token subcommand.
    • Agent-friendly and idempotent: flags/env for all inputs; --dry-run, --yes, --json, --verbose, --install-deps; subcommands: install, doctor, status, network add|list, mcp-url, token, uninstall; TTY-aware colors auto-disable; Linux allowed with a warning.
    • README: fixes platform note to macOS (LaunchAgent), Linux (systemd --user), and Windows (Scheduled Task).
  • Bug Fixes

    • Reliable Beeper detection via a real Desktop API probe (handles IPv6-only binds).
    • Dependency installs: require consent + confirm; validate installer presence and that tools land on PATH; quiet Homebrew with HOMEBREW_NO_AUTO_UPDATE=1, HOMEBREW_NO_ENV_HINTS=1, --quiet.
    • Early Edison key check: validates GET /api/v1/servers; clear 401/403 and demo-backend hint; warns on unreachable backends.
    • server add hardening: use --arg=-y; don’t abort on non-zero so conflict handler runs; self-heal 409 by remove+re-add; detect and explain STEP_UP_REQUIRED with dashboard unblock guidance; suppress Rust backtraces on failure.
    • Token bind: confirmed POST /api/v1/servers/{name}/env, 30s timeout; clear 401/403 vs 000; non-fatal with dashboard fallback; passes BEEPER_API_URL/BEEPER_DESKTOP_BASE_URL.
    • Runtime: fix IFS leak in network adds; honor --dry-run in probes and token step.

Written for commit 97cb8ff. Summary will update on new commits.

Review in cubic

claude added 3 commits July 14, 2026 16:17
Prototype one-command installer that wires Beeper into the Edison Watch
MCP gateway on macOS: installs prerequisites, brings up a headless Beeper
Server, supervises the stdiod tunnel daemon, registers Beeper's stdio MCP
proxy (npx @beeper/desktop-mcp) as a tunnel child, binds the Beeper access
token, and prints the Edison MCP URL.

Built to be driven by an agent or a human: every input is a flag or env
var, missing inputs fail fast with the exact fix, subcommands follow a
resource+verb pattern, --help carries examples, and --dry-run/--yes/--json
are supported. Interactive prompts only run behind --interactive.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
Ran the script on Linux against the real edison-stdiod binary (built from
this checkout) plus stubbed beeper, which surfaced several defects:

- add_networks leaked IFS=',' into run()'s "$*" logging, so --dry-run
  previewed 'beeper accounts add' calls with commas instead of spaces.
  Split on commas via tr without mutating IFS.
- Token-bind curl printed 'http 000000' (its own 000 plus a '|| echo 000'
  fallback) and had no timeout. Use '|| true' with an empty-check and add
  --connect-timeout/-m so it fails fast.
- --dry-run without --beeper-token aborted at the token step instead of
  previewing. Add a dry-run branch that reports the intent and continues.
- edison-stdiod install failures spilled a raw anyhow backtrace and aborted
  mid-flow via set -e. Export RUST_BACKTRACE/RUST_LIB_BACKTRACE=0 and wrap
  each edison-stdiod step so failures produce an actionable message.
- Skip the live 'server list' idempotency probe under --dry-run.
- The real binary carries a Linux (systemd --user) path, so the hard
  macOS-only guard was stricter than the daemon. Warn on Linux and let the
  daemon report capability, block only truly unsupported platforms.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
The daemon's supervisor integration is implemented for macOS (LaunchAgent),
Linux (systemd --user), and Windows (Scheduled Task); only genuinely other
OSes hit the runtime stub. Update the WARNING, the quickstart install
comment, and the CLI table so the README matches the code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="README.md">

<violation number="1" location="README.md:116">
P3: The README now advertises Linux and Windows supervisors, but `edison-stdiod install --help` still describes `install` as a macOS LaunchAgent command. Updating the CLI help with this documentation change would keep the advertised interface and the runnable help output consistent.</violation>
</file>

<file name="scripts/install-beeper.sh">

<violation number="1" location="scripts/install-beeper.sh:84">
P2: `uninstall --dry-run` fails with the non-interactive confirmation error instead of previewing the uninstall. Treating dry-run as an automatic confirmation would preserve the documented “change nothing” preview behavior.</violation>

<violation number="2" location="scripts/install-beeper.sh:289">
P2: `install --networks ...` can block in the default agent/non-interactive mode because `beeper accounts add` is invoked without checking `--interactive`. Gating this flow behind `--interactive` or wiring the documented non-browser auth flow would prevent an unattended installer from hanging.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread scripts/install-beeper.sh
for net in $nets; do
[ -z "$net" ] && continue
log "network: adding '$net' (follow the QR / code prompt in this terminal)"
run beeper accounts add "$net"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: install --networks ... can block in the default agent/non-interactive mode because beeper accounts add is invoked without checking --interactive. Gating this flow behind --interactive or wiring the documented non-browser auth flow would prevent an unattended installer from hanging.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/install-beeper.sh, line 289:

<comment>`install --networks ...` can block in the default agent/non-interactive mode because `beeper accounts add` is invoked without checking `--interactive`. Gating this flow behind `--interactive` or wiring the documented non-browser auth flow would prevent an unattended installer from hanging.</comment>

<file context>
@@ -0,0 +1,452 @@
+  for net in $nets; do
+    [ -z "$net" ] && continue
+    log "network: adding '$net' (follow the QR / code prompt in this terminal)"
+    run beeper accounts add "$net"
+  done
+}
</file context>

Comment thread scripts/install-beeper.sh

confirm() {
[ "$ASSUME_YES" -eq 1 ] && return 0
[ "$INTERACTIVE" -eq 0 ] && die "refusing to run a confirming action non-interactively: $1" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: uninstall --dry-run fails with the non-interactive confirmation error instead of previewing the uninstall. Treating dry-run as an automatic confirmation would preserve the documented “change nothing” preview behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/install-beeper.sh, line 84:

<comment>`uninstall --dry-run` fails with the non-interactive confirmation error instead of previewing the uninstall. Treating dry-run as an automatic confirmation would preserve the documented “change nothing” preview behavior.</comment>

<file context>
@@ -0,0 +1,452 @@
+
+confirm() {
+  [ "$ASSUME_YES" -eq 1 ] && return 0
+  [ "$INTERACTIVE" -eq 0 ] && die "refusing to run a confirming action non-interactively: $1" \
+    "pass --yes to proceed, or --dry-run to preview"
+  printf '%s [y/N] ' "$1" >&2; read -r ans; [ "$ans" = "y" ] || [ "$ans" = "Y" ]
</file context>

Comment thread README.md
| --- | --- |
| `login` | Persist credentials + backend URL to `~/.config/edison-stdiod/config.toml` (mode `0600`). Merges on re-run, so you can rotate the API key without re-supplying the backend URL. |
| `install` | Register the OS supervisor unit (macOS LaunchAgent) so the daemon starts at login and restarts on crash. Requires `login` first. |
| `install` | Register the OS supervisor unit (LaunchAgent on macOS, systemd `--user` unit on Linux, Scheduled Task on Windows) so the daemon starts at login and restarts on crash. Requires `login` first. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The README now advertises Linux and Windows supervisors, but edison-stdiod install --help still describes install as a macOS LaunchAgent command. Updating the CLI help with this documentation change would keep the advertised interface and the runnable help output consistent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 116:

<comment>The README now advertises Linux and Windows supervisors, but `edison-stdiod install --help` still describes `install` as a macOS LaunchAgent command. Updating the CLI help with this documentation change would keep the advertised interface and the runnable help output consistent.</comment>

<file context>
@@ -112,7 +113,7 @@ TLDR: `edison-stdiod --help` (and `edison-stdiod <command> --help` for any subco
 | --- | --- |
 | `login` | Persist credentials + backend URL to `~/.config/edison-stdiod/config.toml` (mode `0600`). Merges on re-run, so you can rotate the API key without re-supplying the backend URL. |
-| `install` | Register the OS supervisor unit (macOS LaunchAgent) so the daemon starts at login and restarts on crash. Requires `login` first. |
+| `install` | Register the OS supervisor unit (LaunchAgent on macOS, systemd `--user` unit on Linux, Scheduled Task on Windows) so the daemon starts at login and restarts on crash. Requires `login` first. |
 | `uninstall` | Stop and remove the supervisor unit. Pass `--purge` to also delete the persisted config and logs. |
 | `run` | Run the daemon in the foreground (normally invoked by the service unit). Reads config or accepts `--backend` / `--api-key` / `--device-id` / `--label` flags (also via `EDISON_*` env vars). |
</file context>

claude added 7 commits July 15, 2026 16:15
Reported: 'install --dry-run' died on a missing 'beeper' CLI instead of
previewing. Rework dependency handling around a single ensure_tool helper:

- --dry-run previews the install command for each missing dep and never
  fails, so you can inspect the whole plan before installing anything.
- Auto-install now requires consent (--install-deps or --interactive) AND
  a confirmation (auto-passed by --yes, prompted under --interactive,
  refused non-interactively without --yes).
- After running an installer, validate the command actually landed on PATH;
  validate the installer itself (brew/cargo) exists before invoking it.
- No consent still fails fast with the exact manual command.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
…tics

Traced the real backend route: POST /api/v1/servers/{name}/env
(UpdateServerEnvRequest) stages the value in the device env_store and
respawns the child. The script's guessed path/body were already correct.

- Drop the 'guessed route' hedging; document the confirmed endpoint.
- The endpoint is admin-only, so surface a clear 401/403 message telling
  the user --ew-api-key must belong to an org admin.
- Distinguish 000 (unreachable / daemon not yet connected) from other codes,
  each with an actionable next step; keep the failure non-fatal.
- Bump the bind timeout to 30s since the call blocks on a child respawn.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
Add a TTY-aware color layer with semantic helpers (step/ok/warn/info) so
both dry-run and real runs read as grouped phases instead of a wall of
white text:

- Colors auto-disable when stderr is not a TTY, when NO_COLOR is set, or
  with the new --no-color flag, so piped and agent output stays a clean,
  parseable ASCII stream (verified: no escape codes leak when piped).
- Phase headers (>>), success (+), info (-), warn (!), and error (x) markers.
- Result block on stdout is gated separately on stdout being a TTY, and the
  copy-paste 'claude mcp add' line stays uncolored so it pastes cleanly.
- --json output is unchanged and never colorized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
From a real macOS run:
- brew install dumped its full auto-update 'New Formulae' wall. Export
  HOMEBREW_NO_AUTO_UPDATE=1 and HOMEBREW_NO_ENV_HINTS=1 and pass --quiet so
  dependency installs are calm.
- The token step optimistically tried a nonexistent mint endpoint and then
  pointed at a GUI-only path. Beeper exposes no headless token mint, so state
  that plainly: guide the user to create a token once in the app UI and
  re-run with --beeper-token, noting the re-run is fast because deps and the
  Beeper Server are already set up and every step is idempotent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
Beeper has no headless token mint (OAuth is authorization_code + PKCE), but
the CLI already holds a valid Desktop API bearer after 'beeper setup'. Add
format-agnostic discovery that reuses it so no GUI 'Approved connections'
step is needed:

- discover_beeper_token gathers candidate strings from 'beeper config path'
  and the macOS Keychain, then keeps the first that authenticates against the
  local OAuth userinfo endpoint (discovered from the well-known metadata).
- ensure_beeper_token tries discovery before failing; on success it reuses the
  token silently (only a masked fingerprint is shown, never the secret).
- New 'token' subcommand runs discovery standalone for quick verification.
- All probes are timeout-bounded so a missing server fails fast instead of
  hanging.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
Field findings: 'beeper config path' returns a single file (~/.beeper/
config.json), and the Desktop API did not answer on IPv4, suggesting an
IPv6-only bind. Make token discovery robust:

- Probe the well-known metadata on 127.0.0.1, [::1], and localhost (and
  BEEPER_API_URL if set), using the first that answers as the validation base.
- Scan the whole config directory (dirname of the config file) plus ~/.beeper,
  not just the single config file.
- Report clearly when the Desktop API is unreachable so the cause is obvious.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
…tatus'

Root cause of the empty ~/.beeper and dead 23373: 'beeper status' exits 0
even when no server is configured, so ensure_beeper_server printed 'already
running' and SKIPPED 'beeper setup --server --install'. The server was never
authorized and the Desktop API never started.

- Add beeper_api_base(): probe the well-known metadata across ports
  23373-23378 on 127.0.0.1/localhost/[::1] (honor BEEPER_API_URL), echo the
  first reachable base URL.
- ensure_beeper_server now runs setup when the API is unreachable and
  re-probes after, failing with a clear 'finish the browser authorization'
  message if it still is not up.
- discover_beeper_token reuses beeper_api_base for the same port range.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/install-beeper.sh">

<violation number="1" location="scripts/install-beeper.sh:281">
P2: Token discovery exits silently when a config directory has no token-shaped strings, so the intended Keychain and manual-token fallbacks never run. Make the candidate-extraction pipeline non-fatal when it finds no matches.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/install-beeper.sh Outdated
for d in $dirs; do
[ -d "$d" ] || continue
cands="$cands
$(find "$d" -type f -exec cat {} + 2>/dev/null | grep -oE '[A-Za-z0-9._-]{24,}' | sort -u | head -n 80)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Token discovery exits silently when a config directory has no token-shaped strings, so the intended Keychain and manual-token fallbacks never run. Make the candidate-extraction pipeline non-fatal when it finds no matches.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/install-beeper.sh, line 281:

<comment>Token discovery exits silently when a config directory has no token-shaped strings, so the intended Keychain and manual-token fallbacks never run. Make the candidate-extraction pipeline non-fatal when it finds no matches.</comment>

<file context>
@@ -246,19 +246,40 @@ mask_token() {
+  for d in $dirs; do
+    [ -d "$d" ] || continue
+    cands="$cands
+$(find "$d" -type f -exec cat {} + 2>/dev/null | grep -oE '[A-Za-z0-9._-]{24,}' | sort -u | head -n 80)"
+  done
   if command -v security >/dev/null 2>&1; then
</file context>
Suggested change
$(find "$d" -type f -exec cat {} + 2>/dev/null | grep -oE '[A-Za-z0-9._-]{24,}' | sort -u | head -n 80)"
$(find "$d" -type f -exec cat {} + 2>/dev/null | grep -oE '[A-Za-z0-9._-]{24,}' | sort -u | head -n 80 || true)"

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/install-beeper.sh">

<violation number="1" location="scripts/install-beeper.sh:227">
P2: A non-Beeper HTTP listener is treated as a running Desktop API, so install can skip server setup and fail later during token discovery. Require successful OAuth metadata (for example HTTP 200) in both probe branches rather than accepting every non-`000` response.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/install-beeper.sh
local wk="/.well-known/oauth-authorization-server" code h p url
if [ -n "${BEEPER_API_URL:-}" ]; then
code="$(curl -s -m 3 -o /dev/null -w '%{http_code}' "${BEEPER_API_URL}${wk}" 2>/dev/null || true)"
[ -n "$code" ] && [ "$code" != "000" ] && { printf '%s' "$BEEPER_API_URL"; return 0; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A non-Beeper HTTP listener is treated as a running Desktop API, so install can skip server setup and fail later during token discovery. Require successful OAuth metadata (for example HTTP 200) in both probe branches rather than accepting every non-000 response.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/install-beeper.sh, line 227:

<comment>A non-Beeper HTTP listener is treated as a running Desktop API, so install can skip server setup and fail later during token discovery. Require successful OAuth metadata (for example HTTP 200) in both probe branches rather than accepting every non-`000` response.</comment>

<file context>
@@ -217,15 +217,47 @@ ensure_deps() {
+  local wk="/.well-known/oauth-authorization-server" code h p url
+  if [ -n "${BEEPER_API_URL:-}" ]; then
+    code="$(curl -s -m 3 -o /dev/null -w '%{http_code}' "${BEEPER_API_URL}${wk}" 2>/dev/null || true)"
+    [ -n "$code" ] && [ "$code" != "000" ] && { printf '%s' "$BEEPER_API_URL"; return 0; }
+  fi
+  for h in 127.0.0.1 localhost "[::1]"; do
</file context>

claude added 4 commits July 15, 2026 17:56
Field finding: the CLI stores the bearer verbatim as "accessToken" in
~/.beeper/targets/<name>.json. The previous discovery cat'd the entire
~/.beeper tree (including the 100MB server binary and sqlite DBs), so the real
token was crowded out past the candidate cutoff.

- Extract "accessToken" straight from targets/*.json and try those first,
  remembering the first as the canonical token.
- Limit the broad fallback scan to JSON files under 1M (skip binaries/DBs/logs).
- If no candidate passes the live userinfo check, fall back to the explicit
  accessToken rather than failing (userinfo can be strict about scopes; a truly
  wrong token surfaces as a real child auth error later).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
… child

Real macOS run got all the way through headless token discovery and daemon
install, then failed at 'edison-stdiod server add ... --arg -y': clap reads a
hyphen-leading value in the space form as an unknown flag. Use the --arg=-y
equals form (verified: parses where the space form errors).

Also pass the discovered Desktop API base URL to the child as BEEPER_API_URL
and BEEPER_DESKTOP_BASE_URL, because the server may bind a non-default port
(23374 here) while @beeper/desktop-mcp defaults to 23373.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
A real run reached the daemon and then failed inside 'server add' with a raw
'HTTP 401 Invalid or inactive API key'. Pre-validate the key against
GET /api/v1/servers in ensure_ew_api_key so a bad or wrong-environment key
fails early with an actionable message (including the demo backend hint),
before login/install/server-add run. Non-401 responses proceed; unreachable
backend warns and continues.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
A stale 'beeper' registered under an old device_id caused a 409 (names are
unique per org, so the this-device 'server list' check missed it). On a
conflict, remove the org-level server (admin-only) and re-add it on this
device. If it still fails (e.g. non-admin key), fail with guidance to use
--server-name or delete it in the dashboard. Also skip the live probe cleanly
under --dry-run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/install-beeper.sh Outdated
claude added 2 commits July 15, 2026 20:50
The 409 self-heal never ran: 'out=$(edison-stdiod server add ...)' as a bare
assignment fails under set -e when the command returns non-zero, so bash exited
silently right after the daemon install (output was captured, nothing printed).
Guard both add captures with '&& rc=0 || rc=$?' so the failure is recorded and
the conflict handler runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
Adding a stdio_tunnel server is gated behind interactive step-up re-auth
(backend _require_recent_supabase_login). Detect the STEP_UP_REQUIRED response
and explain the real cause and unblock (add once in the dashboard, or set
STEP_UP_BYPASS_EMAIL_DOMAINS on a non-release backend) instead of the generic
admin-key message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CRjwx1BeWkTiS97Acyjvx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants