feat: add onboarding CLI and Leptos chat UI#5
Merged
Conversation
Implement two user stories for the 002-onboard-chat-ui feature:
US1 - Onboarding: `exoclaw onboard` guides first-time setup with secure
API key storage (~/.exoclaw/credentials/{provider}.key, mode 0600).
Config file never contains the key — resolved at runtime from env var
or credential file. Re-onboard preserves unrelated config sections.
US2 - Chat UI: Leptos 0.7 CSR web interface served at / via rust-embed.
WebSocket client connects to /ws with JSON-RPC protocol. Markdown
rendering (pulldown-cmark), streaming token display, auto-scroll,
auth prompt for non-loopback, connection status indicator. Dark theme.
Infrastructure:
- Convert to Cargo workspace (root server + ui/ Leptos crate)
- trunk builds WASM bundle, rust-embed serves it from the binary
- 14 new onboard tests (permissions, resolution, preservation)
- 134 total tests passing, 0 clippy warnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Owner
Author
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
- Prevent XSS by converting raw HTML events to escaped text in pulldown-cmark renderer (ui/src/markdown.rs) - Remove unused tower-http "fs" feature from Cargo.toml - Fix CLAUDE.md: correct Leptos version (0.7, not 0.8), remove nonexistent leptos_axum reference, add secrets.rs and update main.rs/AppState module descriptions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Owner
Author
Code reviewFound 1 issue:
Lines 13 to 25 in 8e5c11e
exoclaw/ui/src/components/status.rs Lines 24 to 41 in 8e5c11e 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Update is_connected signal in message handler: set true on successful connect, set false on connect failure or stream error. The initial probe in app.rs sets the starting state; message sends keep it current. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract set_secure_dir_permissions() and set_secure_file_permissions() into shared src/fs_util.rs module to eliminate duplication between config.rs and secrets.rs - Add home_dir() helper that returns Result instead of silently falling back to "." when HOME is unset - Update specs/002-onboard-chat-ui/research.md to reflect actual implementation: Leptos 0.7 CSR + trunk + rust-embed (not 0.8 SSR with leptos_axum) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
exoclaw onboard): Guided first-time setup with secure API key storage. Keys stored in~/.exoclaw/credentials/{provider}.key(mode 0600), never in config. Resolution chain: env var → credential file → None.http://localhost:7200with WebSocket streaming, markdown rendering, auth prompt for non-loopback binds, and connection status indicator. Built as WASM via trunk, embedded in server binary via rust-embed.ui/frontend crate sharingCargo.lockandtarget/.Changes
ui/crate: Leptos 0.7 CSR app (app, state, ws, markdown, 5 components)src/secrets.rs: Credential file read/write with filesystem permissionstests/onboard_test.rs: 14 integration testssrc/gateway/server.rs: rust-embed UI serving + no-API-key warningsrc/main.rs,src/config.rs: Onboarding CLI commandspecs/002-onboard-chat-ui/Test plan
cargo testpasses (134 tests)cargo clippyclean (0 warnings excluding dead_code)cargo fmt --checkcleancargo check -p exoclaw-ui --target wasm32-unknown-unknownpassestrunk buildproduces WASM bundle inui/dist/cargo run -- onboard→ enter provider + key → verify credential file created with 0600 permissionscargo run -- gateway→ open browser to localhost:7200 → verify chat UI loads🤖 Generated with Claude Code