login: default command is claude auth login
This commit is contained in:
parent
e777576528
commit
d81a845dbe
6 changed files with 10 additions and 10 deletions
|
|
@ -271,7 +271,7 @@ See PLAN.md → "Phase 8" for the full design. Summary:
|
||||||
login` badge in the container list. "Valid session" today is a heuristic
|
login` badge in the container list. "Valid session" today is a heuristic
|
||||||
(any regular file inside `/root/.claude/`); we may refine once the
|
(any regular file inside `/root/.claude/`); we may refine once the
|
||||||
filename layout claude writes is locked in.
|
filename layout claude writes is locked in.
|
||||||
- **Login from the per-agent web UI.** Spawn `claude /login` with plain
|
- **Login from the per-agent web UI.** Spawn `claude auth login` with plain
|
||||||
stdio pipes (no PTY initially), surface the OAuth URL from stdout on the
|
stdio pipes (no PTY initially), surface the OAuth URL from stdout on the
|
||||||
page, accept the resulting code via a paste field, write it to the process
|
page, accept the resulting code via a paste field, write it to the process
|
||||||
stdin. Once `~/.claude/` populates, the existing needs-login polling loop
|
stdin. Once `~/.claude/` populates, the existing needs-login polling loop
|
||||||
|
|
|
||||||
2
PLAN.md
2
PLAN.md
|
|
@ -263,7 +263,7 @@ knows where to click.
|
||||||
|
|
||||||
**Login over the per-agent web UI.** No more `nixos-container root-login` for
|
**Login over the per-agent web UI.** No more `nixos-container root-login` for
|
||||||
the common case. The agent's web UI exposes a "log in" action that:
|
the common case. The agent's web UI exposes a "log in" action that:
|
||||||
1. Spawns `claude /login` (or equivalent) inside the container with plain
|
1. Spawns `claude auth login` (or equivalent) inside the container with plain
|
||||||
stdio pipes — no PTY unless we discover we need one.
|
stdio pipes — no PTY unless we discover we need one.
|
||||||
2. Reads the OAuth URL from the process stdout and shows it on the page.
|
2. Reads the OAuth URL from the process stdout and shows it on the page.
|
||||||
3. Provides a paste field for the resulting code; writes it to the process
|
3. Provides a paste field for the resulting code; writes it to the process
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ async fn main() -> Result<()> {
|
||||||
// stays bound) but don't drive the turn loop. Poll the
|
// stays bound) but don't drive the turn loop. Poll the
|
||||||
// claude dir periodically so a successful login (whether
|
// claude dir periodically so a successful login (whether
|
||||||
// from the dashboard PTY path in step 4 or via
|
// from the dashboard PTY path in step 4 or via
|
||||||
// `root-login` + `claude /login` in the meantime)
|
// `root-login` + `claude auth login` in the meantime)
|
||||||
// transitions us into the turn loop without a restart.
|
// transitions us into the turn loop without a restart.
|
||||||
needs_login_loop(&cli.socket, &claude_dir, login_state, poll_ms).await
|
needs_login_loop(&cli.socket, &claude_dir, login_state, poll_ms).await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
//! destroy/recreate so OAuth tokens survive.
|
//! destroy/recreate so OAuth tokens survive.
|
||||||
//!
|
//!
|
||||||
//! "Has session" today means "the dir contains at least one regular file."
|
//! "Has session" today means "the dir contains at least one regular file."
|
||||||
//! That's a heuristic: a fresh bind-mount starts empty, and `claude /login`
|
//! That's a heuristic: a fresh bind-mount starts empty, and `claude auth login`
|
||||||
//! writes credentials into the dir. We may refine later (probe for the
|
//! writes credentials into the dir. We may refine later (probe for the
|
||||||
//! specific credentials filename, or run a no-op `claude` call) once the
|
//! specific credentials filename, or run a no-op `claude` call) once the
|
||||||
//! exact layout is locked in.
|
//! exact layout is locked in.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//! `claude /login` driver. Spawns the login command under plain stdio pipes,
|
//! `claude auth login` driver. Spawns the login command under plain stdio pipes,
|
||||||
//! accumulates stdout+stderr in a shared buffer (so the web UI can show
|
//! accumulates stdout+stderr in a shared buffer (so the web UI can show
|
||||||
//! whatever URL/prompt claude emits), and writes paste-back codes from the
|
//! whatever URL/prompt claude emits), and writes paste-back codes from the
|
||||||
//! UI into the child's stdin.
|
//! UI into the child's stdin.
|
||||||
|
|
@ -16,7 +16,7 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||||
use tokio::process::{Child, ChildStdin, Command};
|
use tokio::process::{Child, ChildStdin, Command};
|
||||||
|
|
||||||
const DEFAULT_CMD: &str = "claude";
|
const DEFAULT_CMD: &str = "claude";
|
||||||
const DEFAULT_ARGS: &[&str] = &["/login"];
|
const DEFAULT_ARGS: &[&str] = &["auth", "login"];
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct State {
|
struct State {
|
||||||
|
|
@ -33,7 +33,7 @@ struct State {
|
||||||
exit_note: Option<String>,
|
exit_note: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A running `claude /login` subprocess.
|
/// A running `claude auth login` subprocess.
|
||||||
pub struct LoginSession {
|
pub struct LoginSession {
|
||||||
child: Mutex<Child>,
|
child: Mutex<Child>,
|
||||||
/// Tokio mutex because we hold the guard across the `write_all().await`
|
/// Tokio mutex because we hold the guard across the `write_all().await`
|
||||||
|
|
@ -46,7 +46,7 @@ pub struct LoginSession {
|
||||||
impl LoginSession {
|
impl LoginSession {
|
||||||
/// Spawn the login command. The exact binary/args are configurable via
|
/// Spawn the login command. The exact binary/args are configurable via
|
||||||
/// `HYPERHIVE_LOGIN_CMD` (single string, shell-split into argv); by
|
/// `HYPERHIVE_LOGIN_CMD` (single string, shell-split into argv); by
|
||||||
/// default we run `claude /login`. Failing to spawn returns an error
|
/// default we run `claude auth login`. Failing to spawn returns an error
|
||||||
/// before any state is registered.
|
/// before any state is registered.
|
||||||
pub fn start() -> Result<Self> {
|
pub fn start() -> Result<Self> {
|
||||||
let (cmd, args) = resolve_command();
|
let (cmd, args) = resolve_command();
|
||||||
|
|
@ -146,7 +146,7 @@ impl LoginSession {
|
||||||
|
|
||||||
fn resolve_command() -> (String, Vec<String>) {
|
fn resolve_command() -> (String, Vec<String>) {
|
||||||
if let Ok(raw) = std::env::var("HYPERHIVE_LOGIN_CMD") {
|
if let Ok(raw) = std::env::var("HYPERHIVE_LOGIN_CMD") {
|
||||||
// Whitespace-only split — no quote handling. Fine for "claude /login"
|
// Whitespace-only split — no quote handling. Fine for "claude auth login"
|
||||||
// style overrides; if we need anything with embedded spaces we'll
|
// style overrides; if we need anything with embedded spaces we'll
|
||||||
// switch to shell-words.
|
// switch to shell-words.
|
||||||
let mut parts = raw.split_whitespace().map(str::to_owned);
|
let mut parts = raw.split_whitespace().map(str::to_owned);
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ fn render_online() -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_needs_login_idle() -> String {
|
fn render_needs_login_idle() -> String {
|
||||||
"<p class=\"status-needs-login\">▓█▓▒░ NEEDS L0G1N ▓█▓▒░</p>\n<p>No Claude session in <code>~/.claude/</code>. The harness is up but the turn loop is paused until you log in.</p>\n<form method=\"POST\" action=\"/login/start\">\n <button type=\"submit\" class=\"btn btn-login\">◆ ST4RT L0G1N</button>\n</form>\n<p class=\"meta\">Spawns <code>claude /login</code> over plain stdio pipes. The OAuth URL will appear here when claude emits it; paste the resulting code back into the form below.</p>".into()
|
"<p class=\"status-needs-login\">▓█▓▒░ NEEDS L0G1N ▓█▓▒░</p>\n<p>No Claude session in <code>~/.claude/</code>. The harness is up but the turn loop is paused until you log in.</p>\n<form method=\"POST\" action=\"/login/start\">\n <button type=\"submit\" class=\"btn btn-login\">◆ ST4RT L0G1N</button>\n</form>\n<p class=\"meta\">Spawns <code>claude auth login</code> over plain stdio pipes. The OAuth URL will appear here when claude emits it; paste the resulting code back into the form below.</p>".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_login_in_progress(session: &Arc<LoginSession>) -> String {
|
fn render_login_in_progress(session: &Arc<LoginSession>) -> String {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue