Skip to content

Conversation

@thruflo
Copy link
Owner

@thruflo thruflo commented Jan 18, 2026

Summary

Enable developers to monitor and interact with active wisp sessions from any device (phone, tablet, another computer) while away from the machine running wisp. This adds a web-based interface that provides full TUI parity - you can check progress, see Claude's output, and respond to NEEDS_INPUT prompts without physical access to the terminal.

Key Changes

  • Web server mode (--server flag) for start and resume commands with password authentication
  • Real-time state streaming via Durable Streams to sync sessions, tasks, and Claude output to the browser
  • React/TanStack DB web client with dashboard, session view, task list, live output log, and input prompt UI
  • Browser notifications when a session needs input while the tab is backgrounded
  • Remote input handling - first response wins when both TUI and web respond concurrently
Tasks completed (22/22)
  • Add server configuration to config types
  • Add --server, --port, and --password flags to start command
  • Add --server, --port, and --password flags to resume command
  • Create internal/server package with core server struct
  • Implement Durable Streams integration
  • Implement HTTP endpoints for web server
  • Implement asset embedding for web client
  • Integrate server with loop for state broadcasting
  • Handle user input from web client
  • Set up web client project structure
  • Implement TanStack DB schema and store setup
  • Implement authentication UI
  • Implement Dashboard view
  • Implement Session view with task list
  • Implement Claude output stream display
  • Implement input prompt UI
  • Implement browser notifications
  • Add CSS styling for web client
  • Implement disconnection handling
  • Add server unit tests
  • Add server integration tests
  • Update CLI help text and README

🤖 Generated with wisp

@thruflo thruflo changed the title Create internal/server package with core server struct feat: add remote web UI for monitoring and interacting with wisp sessions Jan 18, 2026
@thruflo thruflo changed the title feat: add remote web UI for monitoring and interacting with wisp sessions feat: add web UI to monitor and drive wisp sessions Jan 18, 2026
thruflo and others added 17 commits January 19, 2026 14:26
Add ServerConfig struct with port and password_hash fields for web server
configuration. The server config is optional and validates port range.

- Add ServerConfig struct to types.go
- Add Server field to Config struct (optional, pointer)
- Add DefaultServerPort constant (8374)
- Add DefaultServerConfig() helper function
- Add ValidateServerConfig() validation function
- Add comprehensive tests for loading and validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements server mode flags for the start command:
- --server: enables web server alongside TUI for remote access
- --port: overrides default server port (8374)
- --password: prompts to set/change the server password

Adds password handling with argon2id hashing:
- Prompts for password when --server is used and no password is configured
- Prompts for new password when --password flag is explicitly set
- Stores password hash in .wisp/config.yaml

Also adds:
- internal/auth package with HashPassword, VerifyPassword, and PromptPassword
- SaveConfig function to persist config changes
- Tests for password hashing and config saving

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the same server-related flags to the resume command that are
available on the start command, enabling remote web access when
resuming sessions.

- Add --server flag to enable web server alongside TUI
- Add --port flag to configure server port (default: 8374)
- Add --password flag to prompt for password change
- Add handleResumeServerPassword function for password handling
- Add comprehensive tests for flag registration and password logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement the foundational server package for remote wisp access:
- Server struct with Start(ctx) and Stop() methods for lifecycle management
- Password verification using argon2 (delegated to auth package)
- Token generation using crypto/rand (256-bit random tokens)
- Token validation and revocation with expiry-based cleanup
- POST /auth endpoint for password authentication returning session token
- Comprehensive unit tests for all auth flow components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add StreamManager wrapping durable-streams MemoryStore for real-time state
streaming to web clients. Includes:

- Message types for session, task, claude_event, input_request, and delete
- Broadcast methods for each message type with state tracking
- Integration with Server struct for lifecycle management
- Comprehensive tests for message serialization and stream operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds the following HTTP endpoints:
- /auth POST: password authentication (existing, now with integration tests)
- /stream GET: Durable Streams endpoint with catch-up, long-poll, and SSE modes
- /input POST: user input submission for NEEDS_INPUT handling
- / GET: static file serving (placeholder for web assets)

Also adds:
- Auth middleware for protected endpoints using Bearer token
- GetPendingInput() method for retrieving web client responses
- Comprehensive integration tests for all endpoints

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add web package with go:embed directive for web/dist/* assets. Create
getAssets() function with development mode fallback (checks filesystem
before using embedded assets). Update server to serve static files from
the assets filesystem with proper MIME types, caching headers, and SPA
support for client-side routing.

- Add web/assets.go with //go:embed directive and GetAssets() function
- Add web/dist/index.html placeholder for initial build
- Update Server struct to include assets fs.FS field
- Implement handleStatic to serve files from embedded/dev assets
- Add getContentType() for MIME type detection
- Add isImmutableAsset() for cache control of hashed assets
- Add comprehensive tests for asset serving

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add optional server parameter to Loop struct and implement real-time
state broadcasting to web clients:

- Add Server field to Loop and LoopOptions for optional web server
- Broadcast session state after each sync (status, iteration, tasks)
- Broadcast Claude output lines as ClaudeEvents in real-time
- Broadcast InputRequest on NEEDS_INPUT with polling for web responses
- Map internal state statuses to server.SessionStatus types
- Track event sequence numbers per iteration for ClaudeEvents
- First-response-wins concurrency handling for TUI/web input

Tests:
- TestBroadcastState: verifies session and task state broadcasting
- TestBroadcastStateNeedsInput/Blocked/Done: status mapping tests
- TestBroadcastStateNoServer: graceful no-op without server
- TestBroadcastClaudeEvent: verifies JSON event broadcasting
- TestBroadcastClaudeEventSkipsInvalidJSON: filters invalid lines
- TestBroadcastInputRequest: verifies input request broadcasting
- TestBroadcastInputResponded: verifies response updates
- TestLoopWithServerOption: verifies server option storage

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create React + TypeScript web client with Vite for wisp remote access:
- Add package.json with dependencies (react, zod, @durable-streams/state, @tanstack/react-db)
- Configure Vite build with React plugin and dev proxy
- Set up TypeScript config
- Create db/ with schema, store, and optimistic actions
- Create components: Login, Dashboard, Session, TaskList, OutputLog, InputPrompt
- Add CSS styles for all components
- Build produces dist/ for Go embedding

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add detection and UI for stream disconnection:
- Create Disconnected component with reconnect button
- Track connection state in App (disconnected/connecting/connected/error)
- Use onError callback in createDb to detect stream errors
- Show disconnected page when connection is lost after being connected
- Add CSS styling for disconnected state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add proper handling for concurrent TUI and web client input:
- Add inputMu mutex for input-specific synchronization
- Track responded inputs in respondedInputs map
- Return 409 Conflict if input already responded
- Add MarkInputResponded() for TUI to mark inputs as responded
- Add IsInputResponded() to check response status
- Broadcast input request updates when responded
- Update loop to mark inputs as responded when TUI provides input

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive integration tests with //go:build integration tag covering:
- Auth flow (correct/incorrect password, token validation)
- State sync on connect (initial sync, incremental updates)
- Real-time updates via stream (long-poll, rapid updates, Claude events)
- Input submission (store and broadcast, validation)
- Concurrent TUI/web input handling (first-response-wins)
- SSE streaming mode
- Server lifecycle (start, stop, graceful shutdown)
- End-to-end flow test

Run with: go test -tags=integration ./internal/server/...

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add remote access section to start and resume command help text,
documenting the --server, --port, and --password flags.

Add comprehensive remote access section to README.md with usage
examples for starting the web server and exposing via ngrok.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The --server flag was handling password setup but never actually
starting the web server. Now both start and resume commands create,
start, and wire up the server to the loop for state broadcasting.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The web client sends JSON for authentication but the server was
expecting form-urlencoded data, causing a 400 error on login.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use absolute URL for stream endpoint (fixes "Invalid URL" error)
- Fix import from @tanstack/db to @tanstack/react-db (fixes build)
- Don't reset token on connection error (show error screen instead of
  silently redirecting to login)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Starts a minimal server on port 8375 for debugging the web client
auth flow without running a full wisp session.

Usage: go run ./cmd/debug-server [password]

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@thruflo thruflo merged commit 9d02ff2 into main Jan 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants