Commit Graph
2 Commits
Author SHA1 Message Date
iris 2a1bc84c1e Expand a leading ~, and say what the failing command said
Three things, two of which are the same failure seen from opposite ends.

**A working directory of `~/repos/ai-app` never worked.** Everything
crossing to the remote side is single-quoted, which is right for paths,
model names and prompts alike -- unquoted they would be shell syntax
rather than data. It is wrong for exactly one character: `~` means "expand
me", and quoting is what stops expansion. So the remote shell was handed
the literal four-character directory `~` and correctly said it did not
exist, which reads as the path being wrong rather than the quoting.

Paths now go through `quote_path`, which emits `"$HOME"` for a leading
`~/` and single-quotes the rest. The variable expands, the expansion is
not re-split or globbed because it is double-quoted, and nothing after it
gains a meaning -- there is a test that pushes a quote-and-semicolon
injection through the tilde branch and gets back one absurd path rather
than three commands. `$HOME` is set by every shell this can land in, so
this does not depend on the remote side being POSIX; verified by running
the generated script under both sh and fish, which is what the dev VM
actually uses.

**The phone could not have told you any of that.** The exit report kept
the last line of stderr, and a shell's error message ends with a blank
line -- so the last line was empty, the report was a bare exit status, and
the seven lines of fish complaining sat in the server's log where nobody
holding a phone is looking. It now keeps the last 50 lines in a ring and
reports them with blank lines trimmed from both ends. The tests use the
real fish `cd` failure as their fixture.

**The status bar was unreadable.** `isAppearanceLightStatusBars` was
hardcoded to `true` -- dark icons -- which was right against the default
light surface and wrong the moment the app wore Mocha. It now asks the
scheme's own background for its luminance, so changing the palette cannot
reintroduce it.

**And the address field takes `user@host:port`.** One field rather than
two, because that is how an address is written everywhere else and a port
that is nearly always 22 does not deserve its own box on a phone keyboard.
Absent means absent rather than 22: the backend already decides that
default, and writing it here would be a second answer in a second place.
A colon only means "port" when it can -- brackets for IPv6 as ssh writes
them, otherwise exactly one colon followed by digits.

Looked at on the emulator: the status bar, and the form, whose label I
then shortened because it wrapped onto a second line and made that field
taller than the two beside it.
2026-08-28 21:05:17 -04:00
irisandClaude Opus 5 3c144f8070 A screen for the machines, and failures a phone can act on
The other half of making setups editable: add, rename, rediscover and
remove, with a Test that tries a machine before anything is saved.

The screen cannot name a program, which is the point rather than an
omission -- providers are what the server found when it asked, so this app
has no way to introduce something to run. The dialog says so, because
"what it can run is discovered, not typed" is the answer to the question a
person will otherwise ask when they look for a command field.

Two things running it changed. The card showed "this machine / this
machine", because the seeded setup is *called* that and my fallback line
for a local setup said the same -- the line now says something the name
cannot also be. And the header row absorbed a fifth action without
complaint, which is the earlier title-and-actions split paying off exactly
as its comment predicted.

**Host key verification is the failure that would have made this look
broken.** Every machine fails it the first time, because its key is not in
known_hosts yet, and ssh's own words -- "Host key verification failed." --
are written for somebody at a terminal on the backend, which is exactly who
is not reading a phone. It now says what to do: ssh to it once from the
backend and try again. Permission denied gets the same treatment.

Deliberately *not* fixed by relaxing StrictHostKeyChecking. Accepting a new
key is a decision somebody should make with the key in front of them, not
something this app does quietly on their behalf while adding a machine.

Verified on the emulator against a running server: the seeded setup renders
with what was discovered on it, the add dialog explains itself, and Test
against an untrusted machine produces the full explanation rather than
ssh's four words.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017xn8nHw1tw1R6PtiY1eEtw
2026-08-28 13:17:08 -04:00