Files
humanlayer/humanlayer-wui/README.md
Allison Durham 877ec27b0a Allison/eng 1784 bundle daemon and cli with wui for single installation (#385)
* feat(daemon): add dynamic port allocation support

- Always create HTTP server regardless of port configuration
- Support port 0 for dynamic allocation
- Output actual port to stdout when using dynamic allocation
- Enable WUI to start daemon on any available port

* feat(wui): add daemon process management infrastructure

- Add Tauri shell and store plugins for process and state management
- Implement Rust daemon manager with automatic startup on app launch
- Add branch-based daemon isolation for development environments
- Create TypeScript services and hooks for daemon lifecycle management
- Add debug panel UI for manual daemon control in dev mode
- Support automatic daemon connection with managed port discovery
- Handle graceful daemon shutdown on app close
- Implement retry logic for daemon connection during startup

* feat(wui): add daemon process management infrastructure

* chore(wui): update gitignore for daemon artifacts

* build(wui): update Tauri bundle configuration

* build: add homebrew formula and update CI for daemon bundling

* formatting

* makefile to build daemon too (when run wui on dev)

* refactor: improve daemon management in WUI with async/await and better error handling

- Convert daemon start/stop operations to async/await pattern
- Switch HTTP host from 127.0.0.1 to localhost for better compatibility
- Add debug URL override support for development
- Improve error handling and startup behavior
- Fix path resolution for development mode when running from src-tauri

* daemon no longer randomly crashes
Needed to do weird stdout things

* Parse daemon log levels to improve dev logging output

Previously all daemon stderr output was logged as ERROR level, causing confusion
and double timestamps. Now we parse slog format to extract actual log levels
(INFO, WARN, ERROR, etc.) and route them to appropriate tracing levels.

* Integrate debug panel into status bar with theme-aware colors

- Move debug panel button from floating bottom-left to status bar bottom-right
- Replace Settings icon with Bug icon and match styling of other status controls
- Update connection status colors to use CSS variables for theme consistency
- Refactor DebugPanel to accept open/onOpenChange props for controlled state

* Remove local homebrew tap files - moved to separate repository

The homebrew tap is now properly maintained in its own repository
at humanlayer/homebrew-humanlayer for public distribution.

* Migrate WUI backend from tracing to log crate with tauri-plugin-log

- Replace tracing with log crate for consistency
- Add tauri-plugin-log with file rotation (50MB) and proper formatting
- Configure LogDir, Stdout (dev), and Webview targets
- Add proper prefixes: [Tauri] for WUI logs, [Daemon] for daemon logs
- Add log:default permission to capabilities

* Add frontend logging infrastructure for WUI

- Install @tauri-apps/plugin-log and @tauri-apps/api dependencies
- Create logging service with JSON serialization for objects
- Add log location notification for production builds
- Initialize attachConsole to display Rust logs in browser console
- All frontend logs will use [Console] prefix

* Migrate all console calls to use logger throughout WUI

- Replace 94 console.* calls with logger.* across 24 files
- Ensures all frontend logs are captured in production log file
- Maintains browser console output in development mode
- High-traffic files: NotificationService (22), AppStore (21), useSubscriptions (10)

* git ignore of compiled things

* fix it to not be annoyed

* Implement branch-based logging for WUI

- Extract branch detection logic (get_git_branch, extract_ticket_id, get_branch_id)
  into shared functions in lib.rs
- Configure tauri-plugin-log to use branch-based folders in development:
  ~/.humanlayer/logs/wui-{branch-id}/codelayer.log
- Update daemon.rs to use shared branch detection functions
- Add get_log_directory Tauri command to expose log paths to frontend
- Update log notification service to handle branch-based directories
- All log sources (WUI backend, daemon stderr, frontend console) now write
  to a single rotated log file per branch with clear source prefixes

* Update documentation and simplify Makefile for new logging structure

- Remove tee command from wui-dev target in Makefile since logging is now
  handled by tauri-plugin-log
- Update DEVELOPMENT.md to show new WUI log paths in environment overview
- Update CLAUDE.md files to document branch-based log locations:
  - Dev: ~/.humanlayer/logs/wui-{branch}/codelayer.log
  - Prod: Platform-specific directories
- Document that logs include all sources with prefixes: [Tauri], [Daemon], [Console]

* formatting

* add touch to bins

* ci: align GitHub Actions workflows with local development setup

- Simplify main.yml workflow to use unified setup process
- Add CI detection to setup_repo.sh for conditional tool installation
- Install CI-specific tools (Claude Code CLI, UV, golangci-lint) only in CI
- Add setup-ci and ci-tools targets to Makefile for explicit CI setup
- Parallelize npm and bun dependency installations for faster setup
- Add Go and Rust tool caching to improve CI performance
- Create platform-specific dependency script for future expansion

This change reduces workflow complexity from 75+ to ~50 lines per job while
maintaining all functionality. CI and local development now share the same
setup process, improving maintainability and consistency.

* sdk needs to build in order for wui to check
2025-07-31 12:10:26 -07:00

3.3 KiB

humanlayer-wui

Web/desktop UI for the HumanLayer daemon (hld) built with Tauri and React.

Development

Running in Development Mode

  1. Build the daemon (required for auto-launch):

    make daemon-dev-build
    
  2. Start CodeLayer in development mode:

    make codelayer-dev
    

The daemon starts automatically and invisibly when the app launches. No manual daemon management needed.

Disabling Auto-Launch (Advanced Users)

If you prefer to manage the daemon manually:

export HUMANLAYER_WUI_AUTOLAUNCH_DAEMON=false
make codelayer-dev

Using an External Daemon

To connect to a daemon running on a specific port:

export HUMANLAYER_DAEMON_HTTP_PORT=7777
make codelayer-dev

Building for Production

To build CodeLayer with bundled daemon:

make codelayer-bundle

This will:

  1. Build the daemon for macOS ARM64
  2. Build the humanlayer CLI for macOS ARM64
  3. Copy both to the Tauri resources
  4. Build CodeLayer with the bundled binaries

The resulting DMG will include both binaries and automatically manage their lifecycle.

Daemon Management

The daemon lifecycle is completely automatic:

In development mode:

  • Daemon starts invisibly when CodeLayer launches
  • Each git branch gets its own daemon instance
  • Database is copied from daemon-dev.db to daemon-{branch}.db
  • Socket and port are isolated per branch
  • Use debug panel (bottom-left settings icon) for manual control if needed

In production mode:

  • Daemon starts invisibly when CodeLayer launches
  • Uses default paths (~/.humanlayer/daemon.db)
  • Stops automatically when the app exits
  • No user interaction or awareness required

Error Handling:

  • If daemon fails to start, app continues normally
  • Connection can be established later via debug panel (dev) or automatically on retry
  • All errors are logged but never interrupt the user experience

MCP Testing

To test MCP functionality:

In development:

  • Ensure you have humanlayer installed globally: npm install -g humanlayer
  • Start CodeLayer: make codelayer-dev
  • Configure Claude Code to use humanlayer mcp claude_approvals
  • The MCP server will connect to your running daemon

In production (after Homebrew installation):

  • Claude Code can directly execute humanlayer mcp claude_approvals
  • No npm or npx required - Homebrew automatically created symlinks in PATH
  • The MCP server connects to the daemon started by CodeLayer
  • Verify PATH setup is working: which humanlayer should show /usr/local/bin/humanlayer

Troubleshooting MCP connection:

  • If MCP can't find humanlayer, restart Claude Code after installation
  • If launched from Dock, Claude Code may have limited PATH - launch from Terminal instead
  • Check daemon is running: ps aux | grep hld
  • Check MCP logs in Claude Code for connection errors

Quick Start for Frontend Development

Always use React hooks, never the daemon client directly:

import { useApprovals } from '@/hooks'

function MyComponent() {
  const { approvals, loading, error, approve } = useApprovals()
  // ... render UI
}

Documentation

Status

⚠️ Experimental - APIs may change