You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Telegram token currently lives in launchctl setenv, which dies on reboot — launch would be nominal-only if the channel silently breaks on the first restart. Decide the durable mechanism (e.g. launchd plist EnvironmentVariables, an env file the engine loads, Keychain), consistent with the project's secrets-via-environment convention and never hard-coded. Resolution records the chosen mechanism and where the follow-up implementation lands (repair scope amendment vs. a small standalone change).
Mechanism: the shell owns the token; the engine is unchanged. A menu-bar panel row ("Telegram bot token: set / not set → Set…", write-only SecureField) writes a KEY=VALUE file, mode 0600, under the shell's Application Support base; at engine spawn (ProcessLauncher.swift:63) the shell injects it into the engine's environment under the variable config.tomltoken_env names, read via MinimalTOML so no constant is duplicated across languages. A pre-spawn preflight replaces today's empty Retry panel with "token not set → Set…". Saving restarts the engine. Headless checkout runs keep export.
Ruled out, with reasons on record:
Keychain — Simon: the system authorisation dialog reads like credential theft to an open-source user; ad-hoc signing would re-raise it every build.
launchd plist EnvironmentVariables — does not apply: the engine is spawned by the login-item shell (SMAppService.mainApp), not by a LaunchAgent. The com.gpt-voicecoding.bridge plist on the reference machine is gen-1 debris (unloaded; bridge-serve) → Dispose of the gen-1 bridge remnants #54.
Importing from the login-shell profile — already ruled out by LoginShellPath.swift ("a second, invisible configuration file").
A LaunchAgent that runs launchctl setenv at login — the same invisible-file shape, outside the repo.
Evidence that made it urgent:launchctl getenv GPT_VOICECODING_TELEGRAM_TOKEN is already empty on the reference machine after a restart; the next engine start would refuse after log adoption (the acceptance step-0 failure).
Where it lands: repair charter order 11, ticket #55, committed to main at 94d60ad (docs/repair-charter.md) — delivered before the bundle rebuild so the manual acceptance run uses the shipped mechanism. Precedent for the gen-1 shape: config.local.plist's credentialsFile (~/.claude/channels/telegram/.env).
Activity
Add #55 (menu-bar Telegram token) to the repair charter as order 11
Simon-AI-coding commentedon Aug 24, 2026
Resolved (Simon, 2026-08-25, grilled in-session).
Mechanism: the shell owns the token; the engine is unchanged. A menu-bar panel row ("Telegram bot token: set / not set → Set…", write-only
SecureField) writes aKEY=VALUEfile, mode 0600, under the shell's Application Support base; at engine spawn (ProcessLauncher.swift:63) the shell injects it into the engine's environment under the variableconfig.tomltoken_envnames, read viaMinimalTOMLso no constant is duplicated across languages. A pre-spawn preflight replaces today's empty Retry panel with "token not set → Set…". Saving restarts the engine. Headless checkout runs keepexport.Ruled out, with reasons on record:
EnvironmentVariables— does not apply: the engine is spawned by the login-item shell (SMAppService.mainApp), not by a LaunchAgent. Thecom.gpt-voicecoding.bridgeplist on the reference machine is gen-1 debris (unloaded;bridge-serve) → Dispose of the gen-1 bridge remnants #54.LoginShellPath.swift("a second, invisible configuration file").launchctl setenvat login — the same invisible-file shape, outside the repo.Evidence that made it urgent:
launchctl getenv GPT_VOICECODING_TELEGRAM_TOKENis already empty on the reference machine after a restart; the next engine start would refuse after log adoption (the acceptance step-0 failure).Where it lands: repair charter order 11, ticket #55, committed to
mainat94d60ad(docs/repair-charter.md) — delivered before the bundle rebuild so the manual acceptance run uses the shipped mechanism. Precedent for the gen-1 shape:config.local.plist'scredentialsFile(~/.claude/channels/telegram/.env).