* restart: Match Docker Compose semantics
Change `cf restart` from doing `down + up` to using `docker compose
restart`, matching the Docker Compose command behavior.
This provides command naming parity with Docker Compose. Users who want
the old behavior can use `cf down mystack && cf up mystack`.
- Update restart implementation to use `docker compose restart`
- Remove traefik regeneration from restart (no longer recreates containers)
- Update all documentation and help text
- Remove restart from self-update SSH handling (no longer involves down)
* web: Clarify Update tooltip uses 'recreate' not 'restart'
Avoid confusion now that 'restart' means something different.
* web: Fix Update All tooltip to use 'recreates'
* update: Only restart containers when images change
Use `up -d --pull always --build` instead of separate pull/build/down/up
steps. This avoids unnecessary container restarts when images haven't
changed.
* Update README.md
* docs: Update update command description across all docs
Reflect new behavior: only recreates containers if images changed.
* Update README.md
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- Enable `-n auto` for all test commands in justfile (parallel execution)
- Add redis stack to test fixtures (missing stack was causing test failure)
- Replace hardcoded timeouts with constants: `TIMEOUT` (10s) and `SHORT_TIMEOUT` (5s)
- Rename `test-unit` → `test-cli` and `test-browser` → `test-web`
- Skip CLI startup test when running in parallel mode (`-n auto`)
- Update test assertions for 5 stacks (was 4)
- Adds a justfile with common development commands for easier workflow
- Commands: `install`, `test`, `test-unit`, `test-browser`, `lint`, `web`, `kill-web`, `doc`, `kill-doc`, `clean`
Adds `cf compose <stack> <command> [args...]` to run any docker compose
command on a stack without needing dedicated wrappers. Useful for
commands like top, images, exec, run, config, etc.
Multi-host stacks require --host to specify which host to run on.
Add support for targeting specific services within a stack:
CLI:
- New `stop` command for stopping services without removing containers
- Add `--service` / `-s` flag to: up, pull, restart, update, stop, logs, ps
- Service flag requires exactly one stack to be specified
Web API:
- Add `stop` to allowed stack commands
- New endpoint: POST /api/stack/{name}/service/{service}/{command}
- Supports: logs, pull, restart, up, stop
Web UI:
- Add action buttons to container rows: logs, restart, stop, shell
- Add rotate_ccw and scroll_text icons for new buttons
* fix(web): Ensure URL updates after HTMX navigation in command palette
Use history.pushState() after HTMX swap completes to ensure
window.location.pathname is correct when rebuilding commands.
* docs: Add rule about unchecked checklists in PR descriptions
Use run_parallel_with_progress for visual feedback during host checks.
Results are now sorted alphabetically for consistent output.
Also adds code style rule to CLAUDE.md about keeping imports at top level.
Simplifies CLI by having one clear reconciliation command:
- cf up <service> = start specific services (auto-migrates if needed)
- cf apply = full reconcile (stop orphans + migrate + start missing)
The --migrate flag was redundant with 'apply --no-orphans'.
Separate "read state from reality" from "write config to reality":
- Rename `sync` to `refresh` (updates local state from running services)
- Add `apply` command (makes reality match config: migrate + stop orphans)
- Add `down --orphaned` flag (stops services removed from config)
- Modify `up --migrate` to only handle migrations (not orphans)
The new mental model:
- `refresh` = Reality → State (discover what's running)
- `apply` = Config → Reality (reconcile: migrate services + stop orphans)
Also extract private helper functions for reporting to match codebase style.
Shows hosts table (address, configured/running services) and summary
(total hosts, services, compose files on disk, pending migrations).
Use --live to query Docker for actual container counts.
- Extract compose.py from traefik.py for generic compose parsing
(env loading, interpolation, ports, volumes, networks)
- Rename ssh.py to executor.py for clarity
- Extract operations.py from cli.py for business logic
(up_services, discover_running_services, preflight checks)
- Update CLAUDE.md with new architecture diagram
- Add docs/dev/future-improvements.md for low-priority items
CLI is now a thin layer that delegates to operations module.
All 70 tests pass.
- check: Validates external networks exist on configured hosts
- up: Pre-flight check blocks if networks missing on target host
- init-network: Creates Docker network with consistent subnet/gateway
across hosts (default: mynetwork 172.20.0.0/16)
Networks defined as `external: true` in compose files are now
checked before starting or migrating services.
Merged check-mounts into check command. Now provides:
- Config validation (compose files exist)
- Traefik label validation
- Mount path validation (SSH-based)
- Host compatibility matrix when checking specific services
Usage:
cf check # Full validation of all services
cf check --local # Skip SSH mount checks (fast)
cf check jellyfin # Check service + show which hosts can run it
Removed standalone check-mounts command (merged into check).
New command to verify volume mount paths exist on target hosts before
migration. Parses bind mounts from compose files and SSHs to hosts to
check each path exists.
- check_paths_exist() in ssh.py: batch check multiple paths efficiently
- parse_host_volumes() in traefik.py: extract bind mount paths from compose
- check-mounts command in cli.py: groups by host, reports missing paths
Usage: cf check-mounts plex jellyfin
cf check-mounts --all