The SSH key multiselect (@clack/prompts) creates and destroys its own
readline interface on stdin. Due to Bun #1707, subsequent Node readline
interfaces silently receive an immediate "close" event — causing the
model selection prompt to exit the process without reading input.
Fix: replace the readline-based prompt() with p.text() from @clack/prompts,
so all stdin interactions use the same library and never trigger the bug.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: clean up SPA code — extract helpers, use isString, DRY Slack calls
helpers.ts:
- Extract parseAssistantEvent/parseUserEvent/formatToolHint from parseStreamEvent
- Eliminate redundant second scans for toolName and isError (captured during loop)
- Use isString() from @openrouter/spawn-shared instead of typeof checks
- Split long node:fs import across multiple lines
main.ts:
- Extract postOrUpdate() to DRY the post-vs-update pattern (was 3 copy-paste blocks)
- Add SlackClient type alias (replaces 4x InstanceType<typeof App>["client"])
- Remove unused Mapping import
- Inline REQUIRED_VARS into for loop
- Rename currentMsgTs → msgTs
- Tighten formatting throughout
spa.test.ts:
- Remove unused beforeEach import
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add biome config to SPA, fix all lint/format, add PostToolUse hook
- Add biome.json extending lint/biome.json (2-space indent, 120 line width,
useBlockStatements, expand:always, etc.)
- Fix all 36 useBlockStatements violations (braceless if/continue/return)
- Fix all format issues (line width, expand, trailing commas)
- Add biome lint+format to PostToolUse hook — runs automatically on any
.ts file edit when a biome.json is found in the file's directory
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: enforce separated type imports via biome useImportType
Add `style: "separatedType"` to the base biome config's useImportType
rule. This enforces `import type { T }` on its own line instead of
mixing `type` into value imports (`import { type T, foo }`).
Auto-fixed 21 violations across CLI (18) and SPA (3).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When an agent process dies on a cloud VM (SIGTERM, OOM, crash), it now
automatically restarts after 5 seconds, up to 10 times. Clean exits
(code 0) break out immediately. Local execution is unaffected.
Fixes#1860
Agent: code-health
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: add swap space before ZeroClaw install to prevent OOM on nano instances
ZeroClaw's Rust compilation gets OOM-killed on nano_3_0 (512 MB) — build
fails at a random dependency each run. Add ensureSwapSpace() that creates
a 1 GB swap file before running the installer:
- Idempotent: skips silently if swap already exists
- Non-fatal: logs a warning if sudo fails (larger instances won't need it)
- Timeout bumped from 5 min to 10 min (swap-backed builds are slower)
- Defense-in-depth: --prefer-prebuilt avoids compilation in the common
case, but fallback source builds still need memory
Fixes#1840
Agent: issue-fixer
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: add input validation to ensureSwapSpace() to prevent command injection
Validate sizeMb is a positive integer before interpolating into shell
commands, as requested in security review.
Agent: pr-maintainer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* refactor: split SPA into helpers + main, add build script and tests
Split slack-bot.ts into helpers.ts (pure functions) and main.ts (entry
point) for testability. Add build.ts to bundle SPA into spa.js. Add
spa.test.ts with 19 tests covering stream parsing and text helpers.
Improved streaming: tool_use and tool_result events get their own Slack
messages instead of concatenating everything into one. Prompt is passed
via stdin to avoid CLI flag parsing issues with user content.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: drop build.ts — run main.ts directly via bun
Bun runs TypeScript natively, no bundling step needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: move Result monad to shared, add Claude Code fixtures, use Result in SPA
- Move Result type/Ok/Err from packages/cli/src/shared/result.ts to
packages/shared/src/result.ts and re-export from @openrouter/spawn-shared
- Update CLI imports (ui.ts) to use the shared package
- Add fixtures/claude-code/ with realistic stream-json events covering
all event types (assistant text, tool_use, user tool_result, result)
- Refactor SPA helpers to return Result<T> instead of throwing/returning null:
loadState() → Result<State>, saveState() → Result<void>,
downloadSlackFile() → Result<string>, addMapping() → Result<void>
- Update main.ts call sites to handle Result returns
- Update SPA tests to import events from fixtures and test Result returns
- Bump CLI version 0.10.0 → 0.10.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: biome format issues in aws.test.ts, aws.ts, daytona.ts
Expand inline objects/arrays to multi-line format to satisfy biome
formatter rules. No logic changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure the repo as a Bun workspace monorepo:
- Move cli/ → packages/cli/
- Create packages/shared/ (@openrouter/spawn-shared) with type-guards and parse utilities
- Add root package.json with workspace configuration
- Update all CLI imports to use @openrouter/spawn-shared
- Deduplicate toRecord/toObjectArray helpers from 4 cloud modules
- Update SPA (slack-bot) to use shared package instead of local toObj()
- Update 48 agent shell scripts for new packages/cli/ path
- Update install.sh, install.ps1, e2e, and test scripts
- Update all GitHub workflows, .gitignore, pre-commit hooks
- Update CLAUDE.md, README.md, and skill prompt references
- Pin all dependency versions (no ^ ranges)
- Bump CLI version 0.9.1 → 0.10.0
All 1908 tests pass. Lint clean. All 8 cloud bundles build.
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>