Files
humanlayer/DEVELOPMENT.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

7.0 KiB

Development Guide

This guide covers development workflows and tools for the HumanLayer repository.

Parallel Development Environments

Why parallel environments? When developing daemon (hld) or WUI features, restarting the daemon breaks active Claude sessions. This feature lets you maintain a stable "nightly" environment for regular work while testing changes in an isolated "dev" environment.

How It Works

┌─────────────────────┐     ┌─────────────────────┐
│   Nightly (Stable)  │     │   Dev (Testing)     │
├─────────────────────┤     ├─────────────────────┤
│ daemon.sock         │     │ daemon-dev.sock     │
│ daemon.db           │     │ daemon-{timestamp}.db│
│ Production WUI      │     │ Dev WUI             │
└─────────────────────┘     └─────────────────────┘
         │                           │
         └──── Your Work ────────────┘

The development setup provides complete isolation between environments, allowing you to:

  • Keep Claude sessions running in "nightly" while developing in "dev"
  • Test breaking changes without fear
  • Maintain different database states for testing

Quick Start

# Start nightly (stable) environment
make daemon-nightly
make wui-nightly

# Start dev environment (in another terminal)
make daemon-dev
make wui-dev

# Launch Claude Code with specific daemon
npx humanlayer launch "implement feature X" --daemon-socket ~/.humanlayer/daemon-dev.sock

Environment Overview

Component Nightly (Stable) Dev (Testing)
Daemon Binary hld/hld-nightly hld/hld-dev
Socket Path ~/.humanlayer/daemon.sock ~/.humanlayer/daemon-dev.sock
Database ~/.humanlayer/daemon.db ~/.humanlayer/dev/daemon-TIMESTAMP.db
Daemon Logs daemon-nightly-*.log daemon-dev-*.log
WUI Logs Platform-specific ~/.humanlayer/logs/wui-{branch}/codelayer.log
WUI Installed in ~/Applications Running in dev mode

Available Commands

Nightly (Stable) Environment

make daemon-nightly-build  # Build nightly daemon binary
make daemon-nightly        # Build and run nightly daemon
make wui-nightly-build     # Build nightly WUI
make wui-nightly          # Build, install, and open nightly WUI

Dev Environment

make daemon-dev-build     # Build dev daemon binary
make daemon-dev          # Build and run dev daemon with fresh DB copy
make daemon              # Alias for make daemon-dev
make wui-dev            # Run WUI in dev mode connected to dev daemon
make wui                # Alias for make wui-dev
make copy-db-to-dev     # Manually copy production DB to timestamped dev DB
make cleanup-dev        # Clean up dev DBs and logs older than 10 days

Status and Utilities

make dev-status         # Show current dev environment status

Claude Code Integration

MCP servers launched by Claude Code sessions automatically connect to the correct daemon instance. The daemon passes the HUMANLAYER_DAEMON_SOCKET environment variable to MCP servers, ensuring they connect to the same daemon that launched them.

The npx humanlayer launch command supports custom daemon sockets through multiple methods:

1. Command-line Flag

npx humanlayer launch "test my implementation" --daemon-socket ~/.humanlayer/daemon-dev.sock

2. Environment Variable

HUMANLAYER_DAEMON_SOCKET=~/.humanlayer/daemon-dev.sock npx humanlayer launch "test feature"

3. Configuration File

Add to your humanlayer.json:

{
  "daemon_socket": "~/.humanlayer/daemon-dev.sock"
}

Typical Development Workflow

  1. Morning setup - Start your stable environment:

    make daemon-nightly  # Runs in background
    make wui-nightly     # Opens installed WUI
    

    This is your "production" environment for regular Claude work.

  2. Development time - Work on daemon/WUI features:

    git checkout -b feature/my-feature
    # Make your changes to hld/ or humanlayer-wui/
    
  3. Testing - Use dev environment without disrupting your work:

    # Terminal 1: Start dev daemon (auto-copies current DB)
    make daemon-dev
    
    # Terminal 2: Test with Claude Code using dev daemon
    npx humanlayer launch "test my feature" --daemon-socket ~/.humanlayer/daemon-dev.sock
    
    # Or test with dev WUI
    make wui-dev
    

    Your nightly Claude sessions remain unaffected!

  4. Maintenance - Clean up old dev artifacts (weekly):

    make cleanup-dev  # Removes DBs and logs >10 days old
    

Key Benefits

  • Zero Disruption: Keep working in nightly while testing in dev
  • Fresh State: Each make daemon-dev starts with a clean database copy
  • Clear Separation: Different sockets prevent accidental cross-connections
  • Easy Identification: Dev daemon shows "dev" version in WUI
  • Automatic Cleanup: Old dev databases cleaned up with one command

Environment Variables

Both daemon and WUI respect these environment variables:

  • HUMANLAYER_DAEMON_SOCKET: Path to daemon socket (default: ~/.humanlayer/daemon.sock)
    • This variable is automatically passed to MCP servers launched by Claude Code sessions
  • HUMANLAYER_DATABASE_PATH: Path to SQLite database (daemon only)
  • HUMANLAYER_DAEMON_VERSION_OVERRIDE: Custom version string (daemon only)

Troubleshooting

Q: Both daemons won't start Check for existing processes:

ps aux | grep hld | grep -v grep
# Kill if needed: kill <PID>

Q: WUI shows "connection failed" Verify socket paths match:

ls -la ~/.humanlayer/*.sock
# Should see daemon.sock and/or daemon-dev.sock

Q: Want to use a specific dev database

# List available dev databases
ls -la ~/.humanlayer/dev/
# Run daemon with specific DB
HUMANLAYER_DATABASE_PATH=~/.humanlayer/dev/daemon-20240717-143022.db make daemon-dev

Q: How do I know which environment I'm in?

  • Check WUI title bar: shows "dev" for dev daemon
  • Check daemon logs: tail -f ~/.humanlayer/logs/daemon-*.log
  • Check WUI logs: tail -f ~/.humanlayer/logs/wui-*/codelayer.log

Other Development Commands

Building and Testing

make setup              # Resolve dependencies across monorepo
make check-test        # Run all checks and tests
make check             # Run linting and type checking
make test              # Run all test suites

Python Development

make check-py          # Python linting and type checking
make test-py           # Python tests

TypeScript Development

Check individual package.json files for specific commands, as package managers and test frameworks vary across projects.

Go Development

Check go.mod for Go version requirements and look for Makefile in each Go project directory.