Skip to content

Sign in to Claude from the app - #13

Merged
httpsphl merged 5 commits into
mainfrom
feat/claude-sign-in
Sep 29, 2026
Merged

httpsphl merged 5 commits into
mainfrom
feat/claude-sign-in

Conversation

@httpsphl

Copy link
Copy Markdown
Owner

Adds a "Sign in to Claude" button, so a first-time user never has to open a terminal to sign in. Stacked on #12: the first commit here is #12's until it merges.

Service

  • Checks the sign-in with claude auth status. The docs say it prints JSON with loggedIn and exits 0 when signed in, 1 when not; I confirmed both with 2.1.284, using an empty CLAUDE_CONFIG_DIR for the signed-out case. It checks when Claude Code is found, every 30 s while signed out, right away when a bot hits a sign-in error, and when the app calls the new system.refresh.
  • system.status now includes claudeSignedIn and claudePath.
  • When the sign-in comes back, bots stopped by a sign-in error restart by themselves. An account problem with a valid sign-in (billing, blocked organization) leaves the answer at "signed in", so those bots stay stopped instead of looping.
  • To prepare for translations: notices carry a code (signed_out, usage_limit, turn_failed) alongside the English text. The sidebar preview carries a kind and no wording of its own; the app adds "You:" and "Waiting for approval".

App

  • "Sign in to Claude" opens claude auth login in its own window. The app launches it, not the service, so the window comes to the front. Once it finishes, the app calls system.refresh and re-reads the status every second for up to 20 s.
  • The button appears in three places: a "Claude account" row on the welcome screen, a "Sign in to Claude" banner when signed out, and the bot view when a bot is stopped by a sign-in error.
  • The Tauri command only runs an absolute path to an existing claude.exe. It strips CLAUDECODE and CLAUDE_CODE_* from the environment, because an app started from inside a Claude Code session would otherwise pass them on.
  • Also fixes a pre-existing race between two port tests in the Tauri crate.

Tested

  • New Rust tests: status reporting, checks while signed out, automatic restart after signing in, an immediate check after system.refresh, and no loop on account errors. Full workspace tests and clippy pass.
  • 57 app tests pass, including sign-in success, a window closed early, the banner, and the bot view.

Manual test

On a machine signed out of Claude Code (claude auth logout): open Botloft and click "Sign in to Claude". A window opens and the browser asks you to sign in. When you finish, the window closes, the welcome screen shows "Signed in." within a few seconds, and any bot that was waiting starts. I didn't run the real claude auth login, because it would have opened a sign-in page in your browser and I wasn't going to log you out; the app only relies on its exit code.

The app checks the latest published GitHub release (latest.json) when it
opens and every six hours. A newer version shows "Update available" in
the title bar; one click downloads it with progress, runs the installer
passively and reopens Botloft, and the reopened app updates the daemon
because it is now outdated. Failures keep the current version, with the
error under "Details". Dev builds never offer to replace themselves.

Updates are signed with the Tauri updater key (public key in
tauri.conf.json, private key in the TAURI_SIGNING_PRIVATE_KEY secret),
and requireSignedVersion keeps a tampered feed from pushing an older
signed release back.

Pushing a tag vX.Y.Z runs release.yml: it checks the tag against the
workspace version, builds the signed installer and opens a draft release
with the installer, its signature and latest.json. The updater sees it
once the owner publishes it. The version now lives only in Cargo.toml.
… for the app

The daemon runs `claude auth status` (documented: JSON with loggedIn,
exit 0 when signed in, 1 when not; checked with 2.1.284) once Claude Code
is found, every 30 s while signed out, at once when a bot hits a sign-in
error, and when the app calls the new `system.refresh`. `system.status`
reports `claudeSignedIn` and `claudePath`. When the answer turns from
signed out to signed in, the bots a sign-in error stopped start again by
themselves. An account problem with a valid sign-in (billing, a blocked
organization) does not change the answer, so it cannot loop.

So the app can speak the owner's language, notices carry a code
(signed_out, usage_limit, turn_failed) next to the English text, and the
conversation-list line carries its kind with no wording of its own: the
app adds "You:" and "Waiting for approval".
Both pick a free port; run in parallel, one could take the port the other
had just freed and read it as taken.
"Sign in to Claude" opens Claude Code's own sign-in (`claude auth login`)
in a window of its own, launched by the app so it comes to the front,
then asks the daemon to check again and watches for the result. It shows
on the welcome screen as a "Claude account" check, as a banner when
signed out, and on a bot stopped by a sign-in error. The Tauri command
only runs an absolute path to an existing claude.exe, and strips the
Claude Code session variables an app started from a session would pass
on.
@httpsphl
httpsphl merged commit 99b1898 into main Sep 29, 2026
3 checks passed
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.

1 participant