name: dev-installation description: Capsem native CLI installer -- setup wizard, service registration, self-update, background asset download, corp config provisioning, and the Docker-based install test harness. Use when working on capsem setup/update/uninstall commands, service install/uninstall, asset management, corp config, install test infrastructure, or the installed layout (~/.capsem/).
Native CLI Installer
Installed layout
~/.capsem/
bin/capsem, capsem-service, capsem-process, capsem-mcp, capsem-gateway, capsem-tray
assets/manifest.json, v{ver}/
run/service.sock, service.pid, instances/, persistent/
setup-state.json
update-check.json
user.toml
corp.toml (CLI-provisioned corp config)
corp-source.json (corp config source metadata)
CLI commands (no service required)
These commands dispatch before UdsClient creation -- they work without the service running:
| Command | Module | What |
|---|---|---|
capsem version | main.rs | Print version + build hash |
capsem setup | setup.rs | First-time setup wizard |
capsem update | update.rs | Self-update from GitHub |
capsem service install|uninstall|status | service_install.rs | Service registration |
capsem completions bash|zsh|fish | completions.rs | Shell completions |
capsem uninstall --yes | uninstall.rs | Full removal |
Path discovery (paths.rs)
discover_paths() finds sibling binaries and assets:
current_exe().parent()-> bin_dir -> capsem-service, capsem-process- Assets:
~/.capsem/assets/(the only layout -- no dev fallback, usejust installor symlink)
Auto-launch (main.rs UdsClient)
try_ensure_service() runs on every service-dependent command:
- Check socket connectivity
- Try systemd/LaunchAgent if unit installed (via
try_start_via_service_manager()) - Fall back to direct spawn with
--foreground --assets-dir --process-binary - Poll socket for 5s
The request() method wraps all HTTP calls with retry-on-connect-fail.
Service registration (service_install.rs)
Pure generators (unit-testable on all platforms):
generate_plist()-> macOS LaunchAgent XMLgenerate_systemd_unit()-> systemd user unit
Side-effecting:
install_service()-> write +launchctl bootstrap/systemctl --user enable --nowuninstall_service()->launchctl bootout/systemctl --user disable --now+ deleteservice_status()-> installed + running + pid + unit_path
Setup wizard (setup.rs)
6 steps, corp-aware, state persisted to setup-state.json:
- Corp config provisioning (if
--corp-config) - Welcome
- (Doctor -- deferred)
- Security preset (skips corp-locked)
- AI providers (auto-detect credentials)
- Repositories (detect git/SSH/GitHub)
- Summary + PATH check + service install
Flags: --non-interactive, --preset, --force, --accept-detected, --corp-config
Self-update (update.rs)
read_cached_update_notice()-> sync file read on every commandrefresh_update_cache_if_stale()-> background 24h-cached GitHub checkrun_update()-> fetch manifest, download assets, cleanup old versions- Layout detection: MacosPkg, UserDir, Development (bails with "build from source")
Corp config provisioning (capsem-core: corp_provision.rs)
fetch_corp_config(url)-> GET + validate + return content + ETagvalidate_corp_toml(content)-> parse as SettingsFileinstall_corp_config(dir, content, source)-> write corp.toml + corp-source.jsonrefresh_corp_config_if_stale(dir)-> background conditional GET with ETag
Loader changes: corp_config_paths() returns [/etc, ~/.capsem/] with first-wins merge.
Remote manifest + background download (capsem-core: asset_manager.rs)
fetch_remote_manifest(client, version)-> GET release manifest.jsonfetch_latest_manifest(client)-> GitHub API latest release -> manifeststart_background_download(manifest, version, dir, arch)-> tokio task + mpsc progress
Test harness
Docker-based e2e tests in tests/capsem-install/:
| File | Tests |
|---|---|
| test_smoke.py | Harness works (systemd, binaries, build hash) |
| test_auto_launch.py | Auto-launch, path discovery, asset resolution, error cases |
| test_service_install.py | Install/uninstall/status, idempotent, systemd integration |
| test_setup_wizard.py | Non-interactive, rerun skip, --force, user.toml |
| test_corp_config.py | Provisioning, validation, precedence |
| test_update.py | Dev build bail, layout detection, cache, preserve-on-fail |
| test_completions.py | bash/zsh/fish output |
| test_uninstall.py | Full cleanup |
| test_lifecycle.py | End-to-end user journey |
| test_reinstall.py | Binary replacement verification |
| test_error_paths.py | Failure scenarios with actionable errors |
Run: just test-install (Docker with systemd PID 1)
Key files
crates/capsem/src/
main.rs CLI entry, command dispatch, UdsClient with auto-launch
paths.rs Binary + asset path discovery
platform.rs Install layout detection
setup.rs Setup wizard orchestrator
update.rs Self-update + cache
service_install.rs LaunchAgent + systemd unit generation + registration
completions.rs Shell completions via clap_complete
uninstall.rs Full removal
build.rs Build hash embedding (CAPSEM_BUILD_HASH)
crates/capsem-core/src/
asset_manager.rs Remote manifest, background download, cleanup
net/policy_config/
corp_provision.rs Corp config fetch, validate, install, refresh
loader.rs corp_config_paths() with merge