Commit Graph

1266 Commits

Author SHA1 Message Date
gavrielc
3e7fea0fde Merge pull request #2142 from mnolet/fix/schedule-task-routing
fix(scheduling): include routing in schedule_task content JSON
2026-05-01 00:31:04 +03:00
gavrielc
d418f830db Merge branch 'main' into fix/schedule-task-routing 2026-05-01 00:30:11 +03:00
gavrielc
524ac221e1 Merge pull request #2111 from qwibitai/setup-scratch-agent-cleanup
feat(setup): delete scratch agent after ping-pong, simplify flow
2026-04-30 23:20:54 +03:00
gavrielc
69b4225916 Merge branch 'main' into setup-scratch-agent-cleanup 2026-04-30 23:20:32 +03:00
gavrielc
3d6a9b74f3 review: surface ping-test cleanup failures + restore copy
Routes the post-ping `_ping-test` cleanup through `spawnQuiet` +
`setupLog.step` so a non-zero exit from `delete-cli-agent.ts` lands
in `logs/setup-steps/cleanup-cli-agent.log` and the progression log,
and prints a one-line warn to the user. Previously the spawnSync was
fire-and-forget with `stdio: 'ignore'`, leaving an orphan agent group
silently if cleanup failed.

Restores the original copy on the cli-agent step labels, the ping
explainer paragraph, and the post-ping spinner stop line — those
copy changes are out of scope for this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 23:16:34 +03:00
gavrielc
dcc625f2b8 Merge pull request #2155 from qwibitai/setup-root-warning-v2
Add root user warning gate to Linux setup
2026-04-30 23:09:36 +03:00
gavrielc
99a8559b14 Merge remote-tracking branch 'origin/main' into setup-root-warning-v2
# Conflicts:
#	setup/auto.ts
2026-04-30 23:07:38 +03:00
gavrielc
3dc772cca0 Merge branch 'main' into setup-scratch-agent-cleanup 2026-04-30 23:05:09 +03:00
gavrielc
5ebad280ce Merge pull request #1502 from Koshkoshinsk/docs/pr-hygiene-check
Add PR hygiene check to CLAUDE.md and contributing guidelines
2026-04-30 23:00:43 +03:00
gavrielc
d73b9e14ad Merge branch 'main' into docs/pr-hygiene-check 2026-04-30 23:00:10 +03:00
gavrielc
681a5b51c8 Merge pull request #2157 from qwibitai/setup-lazy-env-reuse
refactor(setup): per-step env var reuse instead of upfront all-or-nothing
2026-04-30 22:59:03 +03:00
gavrielc
8e45f4e964 Merge branch 'main' into setup-lazy-env-reuse 2026-04-30 22:58:53 +03:00
gavrielc
eb9a5d706d Merge branch 'main' into setup-scratch-agent-cleanup 2026-04-30 22:54:48 +03:00
github-actions[bot]
46cd91c306 docs: update token count to 138k tokens · 69% of context window 2026-04-30 19:54:27 +00:00
github-actions[bot]
0218159ef0 chore: bump version to 2.0.20 2026-04-30 19:54:21 +00:00
gavrielc
3ee07effea Merge pull request #2105 from qwibitai/feat/channel-approval-flow
feat: richer channel-approval flow with agent selection and free-text naming
2026-04-30 22:54:08 +03:00
gavrielc
462b9581b2 Merge branch 'main' into feat/channel-approval-flow 2026-04-30 22:54:00 +03:00
gavrielc
a359f2555f Merge pull request #2158 from alipgoldberg/setup-splash-screen
feat(setup): show under-the-sea lobster splash at boot
2026-04-30 22:51:35 +03:00
gavrielc
6525926ca9 Merge branch 'main' into setup-splash-screen 2026-04-30 22:51:01 +03:00
gavrielc
35d35fefc3 Merge pull request #2154 from alipgoldberg/setup-fallback-url-in-prompt
feat(setup): move URL fallback into the open-browser prompt
2026-04-30 22:50:44 +03:00
gavrielc
eab9110232 Merge branch 'main' into setup-fallback-url-in-prompt 2026-04-30 22:48:47 +03:00
gavrielc
2c0d0e9d44 Merge pull request #2146 from alipgoldberg/setup-headless-link-copy
feat(setup): label headless URL fallback with "Get started:"
2026-04-30 22:48:26 +03:00
gavrielc
17823dffae Merge branch 'main' into setup-headless-link-copy 2026-04-30 17:14:25 +03:00
gavrielc
941a75f65d Merge pull request #2145 from alipgoldberg/setup-headless-skip-browser
feat(setup): skip browser-open prompts on headless devices
2026-04-30 17:13:57 +03:00
gavrielc
c2ee2b7c91 Merge branch 'main' into setup-headless-skip-browser 2026-04-30 17:11:35 +03:00
gavrielc
ef62f57326 Merge pull request #2108 from alipgoldberg/setup-fmt-duration
feat(setup): switch elapsed-time suffixes to "Xm Ys" past 60s
2026-04-30 17:10:40 +03:00
exe.dev user
e51f6e0c41 feat(setup): show under-the-sea lobster splash at boot
Replaces the single-line `NanoClaw` wordmark printed by
nanoclaw.sh with a multi-line splash frame: the lobster mascot
rendered as truecolor braille, drifting bubbles on either side,
the figlet wordmark below (Nano in bold, Claw in cyan bold),
three taglines — "Small.", "Runs on your machine.", "Yours to
modify." — and a navy seafloor line.

The frame is pre-rendered into `assets/setup-splash.txt` (built
from `assets/nanoclaw-icon.png` via chafa for the lobster +
figlet for the wordmark). nanoclaw.sh just streams the literal
bytes — no runtime dependency on chafa, figlet, or
ImageMagick.

Total height: 30 lines. Visible width: ~40 columns (fits any
terminal). Truecolor ANSI codes are used directly; terminals
without truecolor support will see a degraded but still
readable frame.

Also removes the standalone "Small. Runs on your machine.
Yours to modify." tagline line that nanoclaw.sh used to print
above the bootstrap spinner — those taglines now appear inside
the splash, so showing them again would duplicate.

The wordmark-suppression flow downstream (`setup:auto` honoring
`NANOCLAW_BOOTSTRAPPED=1`) is unchanged: the splash prints once
in nanoclaw.sh, setup:auto's `printIntro()` sees the flag and
keeps the clack `p.intro` line clean ("Let's get you set up.").
2026-04-30 16:46:43 +03:00
exe.dev user
cb15e606c3 feat(setup): move URL fallback into the open-browser prompt
On GUI devices the URL was previously rendered dim inside the
instructional `note(...)` card, then `confirmThenOpen` printed
its prompt below: read the card, see the URL, then a separate
"Press Enter to open the X" prompt with no link near it. Two
visual moments for what's really one decision.

This PR pulls the URL out of the card on GUI devices and
relocates it directly under the action line of the confirm
prompt, separated only by a dim "If browser does not appear,
please visit: <url>" line:

    │
    ◆  Press Enter to open the Developer Portal
    │  If browser does not appear, please visit: …  (dim)
    │  ● Yes / ○ No
    │

Action and fallback live as one prompt block — the user sees
both at the same time, no need to scroll back up to grab the
URL if the auto-open misses.

Headless behavior is unchanged: `formatNoteLink` still emits
"Get started: <url>" inside the card on headless devices (per
#2146), and `confirmThenOpen` still no-ops on headless (per
#2145). The only thing that changed for headless is the leading
`\n` in the helper output, which acts as a visual separator from
the steps above.

Five call sites adjusted (Discord ×3, Slack ×1, Telegram ×1) to
use `.filter((line) => line !== null)` so the now-nullable
`formatNoteLink` cleanly drops out of GUI-rendered cards.
2026-04-30 16:46:29 +03:00
exe.dev user
6863e0f63b feat(setup): label headless URL fallback with "Get started:"
When a card's auto-open is gated on `confirmThenOpen`, the URL also
appears inside the surrounding `note(...)` as a copy-paste fallback —
rendered dim because on a GUI device the auto-open is doing the
heavy lifting and the printed URL is just an incidental backup.

On headless devices the auto-open doesn't run (per #2145), so the
URL inside the note is the user's *only* path forward. A dim URL
reads as "incidental reference" exactly when it should be reading
as "this is the action."

Adds `formatNoteLink(url)` to setup/lib/browser.ts:
  - GUI device → `k.dim(url)` (unchanged from today)
  - Headless device → `Get started: <url>` at full strength

Replaces five call sites (Discord ×3, Slack ×1, Telegram ×1).
Single helper, atomic switch via the same `isHeadless()` plumbing
introduced in #2145, so the headless behavior across all five
flows stays in sync.
2026-04-30 16:46:16 +03:00
exe.dev user
4d42bb95fb feat(setup): skip browser-open prompts on headless devices
Wires the existing `isHeadless()` from setup/platform.ts into
`confirmThenOpen`. When the helper detects a headless device
(Linux without `DISPLAY`/`WAYLAND_DISPLAY`), both the
"Press Enter to open your browser" prompt and the actual
`openUrl(...)` call are skipped — there's no browser to launch
and the user can't usefully press Enter to summon one.

Why this is enough — the surrounding flow already supports the
headless path implicitly:

  - Every `confirmThenOpen` call site sits beneath a `note(...)`
    that prints the URL and the steps the user needs to take.
    The URL is already visible to copy-paste onto another
    device.

  - Every site is followed by an explicit confirmation prompt
    ("Got your bot token?", "Done with the X?", etc.) that
    naturally serves as the headless user's "I finished the
    thing on my other device" signal.

So the headless branch becomes: read the note, do the thing,
answer the next prompt — without a useless "Press Enter to
open your browser" detour in between.

Coverage rationale (~95% accurate for the cases that actually
cause user confusion today):

  - Linux + no `DISPLAY`/`WAYLAND_DISPLAY` → headless. Catches:
      • Raspberry Pi headless installs
      • Bare-metal Linux servers
      • SSH'd into Linux without X11 forwarding
      • CI environments on Linux
      • Linux containers (which have no display)
  - macOS → never headless. Even SSH'd Macs can usually still
    open URLs through the local user's session, so treating
    them as GUI-capable is the right default.
  - Windows → never headless (effectively always GUI in
    practice).

The remaining ~5% are edge cases (someone manually unset
`DISPLAY` on a desktop Linux session, etc.) that almost never
happen accidentally and recover gracefully — the URL is still
visible in the surrounding note.

Six call sites in channel adapters (Discord ×3, Slack ×1,
Telegram ×1, Teams ×1) all change behavior atomically through
the single helper. No per-site copy changes needed; consistency
is enforced by the central wiring.
2026-04-30 16:45:59 +03:00
exe.dev user
a66cd545d5 feat(setup): switch elapsed-time suffixes to "Xm Ys" past 60s
Adds a `fmtDuration(ms)` helper in `setup/lib/theme.ts` that returns
`47s` under a minute and `1m 34s` from 60s onward, then routes every
elapsed-time spinner suffix in the setup flow through it. Replaces
the inline `Math.round((Date.now() - start) / 1000)` + `(${elapsed}s)`
pattern at every site.

Format is consistent past 60s — `1m 0s` over `1m` — so the live
spinner doesn't change shape at every whole-minute crossing.

Sites updated: setup/auto.ts, setup/lib/{runner,tz-from-claude,
claude-assist}.ts, and setup/channels/{signal,whatsapp,telegram,
discord,slack}.ts. Pre-allocated suffix budgets in `fitToWidth`
calls bumped from `' (999s)'` to `' (99m 59s)'` so long-running
steps don't blow past the reserved width.
2026-04-30 16:45:21 +03:00
Gabi Simons
cfb737d681 Merge branch 'main' into feat/channel-approval-flow 2026-04-30 15:54:55 +03:00
Gabi
1db98ee614 refactor(setup): check env vars per-step instead of upfront all-or-nothing
Remove the grouped detectExistingEnv() block that asked "reuse all or
start fresh" at the top of setup. Each channel step now reads credentials
directly from .env on disk via readEnvKey() and offers to reuse them
individually at the point of use.

- Add readEnvKey() helper in setup/environment.ts
- Remove ENV_KEY_GROUPS, ExistingEnvGroup, detectExistingEnv from auto.ts
- Move detectRegisteredGroups skip to right before cli-agent step
- Switch all channel files (telegram, discord, slack, teams, imessage)
  from process.env to readEnvKey()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 12:36:25 +00:00
gavrielc
bb1b41800c Merge pull request #2156 from qwibitai/fix/telegram-spinner-overflow
fix: prevent telegram pairing spinner from flooding terminal
2026-04-30 15:30:54 +03:00
gabi-simons
5be15be139 fix: prevent telegram pairing spinner from flooding the terminal
The spinner label exceeded terminal width, breaking clack's cursor-up
redraw and causing each animation tick to print a new line instead of
updating in-place. Wrap with fitToWidth() like other setup spinners.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 12:07:53 +00:00
Koshkoshinsk
e56132d04a Remove SSH key copy step from root warning instructions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 11:33:25 +00:00
Gabi Simons
5cf5840426 Merge branch 'main' into feat/channel-approval-flow 2026-04-30 14:11:21 +03:00
Koshkoshinsk
35f8e9d2f5 Move SSH hint above user-creation steps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:40:45 +00:00
Koshkoshinsk
d5388a168b Replace web terminal instructions with SSH setup hint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:37:42 +00:00
Koshkoshinsk
23a3fea868 Add passwordless sudo step to root warning instructions
Setup steps like install-node.sh and install-docker.sh run sudo
non-interactively. Without NOPASSWD, password prompts can silently
hang when piped through the setup runner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:51 +00:00
Koshkoshinsk
72837c1643 Fix sg docker re-exec restarting setup from scratch
When maybeReexecUnderSg() re-launches setup:auto under `sg docker`,
the new process had no memory of completed steps — it re-prompted the
welcome menu, re-ran environment and container checks, and then failed
on onecli because the earlier run's state was lost.

Pass NANOCLAW_SKIP with completedStepNames() so the re-exec'd process
skips already-finished steps, suppress the welcome menu and existing-env
prompts on re-exec since the user already answered them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
Koshkoshinsk
d07cd7afa0 Remove redundant root login step from user-creation instructions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
Koshkoshinsk
3d29965413 Update root warning instructions: add SSH key copy, remove extra step
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
Koshkoshinsk
0a18c1d21a Ensure user is in docker group before sg docker, revert workarounds
The root cause of broken keyboard navigation was sg docker prompting
for the (unset) group password when the user wasn't in the docker
group. Fix by running sudo usermod -aG docker before sg docker.

This makes the stty sane calls and p.confirm workaround unnecessary,
so revert those. Also remove the manual docker group instruction from
nanoclaw.sh since container.ts handles it automatically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
Koshkoshinsk
dec1be6adc Add clone step to root warning user-creation instructions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
Koshkoshinsk
030ee8a46f Update root warning instructions: add root login step, fix ssh user
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
Koshkoshinsk
c4f654083d Change root warning from y/N prompt to numbered menu options
Clearer UX: option 1 shows user creation instructions,
option 2 explicitly continues as root (not recommended).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
Koshkoshinsk
7755082a4c Add root user warning gate to Linux setup pre-flight
Users running setup as root hit permission issues with containers,
services, and file ownership. Warn early with an interactive prompt
and provide step-by-step instructions to create a regular user.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 10:31:30 +00:00
gabi-simons
8a205808e0 fix(setup): wrap scratch agent cleanup in transaction, remove session data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 08:19:18 +00:00
Gabi Simons
d7c76ac12b Merge branch 'main' into setup-scratch-agent-cleanup 2026-04-30 11:07:01 +03:00