# left4me

`left4me` is a local L4D2 server management platform with two planned components:

1. `l4d2host` + `l4d2ctl` (host library + CLI)
2. `l4d2-web-app` (Flask web app for users, blueprints, servers, jobs, and logs)

## Status

Implementation plans remain the source of truth for architecture and task sequencing:

- `docs/superpowers/plans/2026-04-22-l4d2-host-lib-v1.md`
- `docs/superpowers/plans/2026-04-23-l4d2-web-app-v1.md`

## Locked v1 Decisions

- Naming is strictly `l4d2` (not `l4d`).
- Host library and web app are separate components.
- Host CLI write commands are fixed to:
  - `install`
  - `initialize <name> -f <spec.yaml>`
  - `start <name>`
  - `stop <name>`
  - `delete <name>`
- Host CLI read commands are available for the web/host boundary:
  - `status <name> --json`
  - `logs <name> --lines <n> --follow/--no-follow`
- The web app calls host operations through `l4d2ctl`, not direct `l4d2host` imports.
- Deployment uses `/var/lib/left4me` for runtime state, `/opt/left4me` for repository contents and the virtualenv, `/etc/left4me` for environment files, and global units under `/usr/local/lib/systemd/system`.
- Overlay handling is directory-based; the web app populates each overlay (workshop downloads, managed-global refresh).
- No lock manager, no rollback, no preflight checks in host library.
- CLI propagates subprocess failures via stderr and return code.
- `delete` on missing instance is no-op success.
- Blueprint model (web app):
  - user-private in v1
  - servers are live-linked to blueprint
  - no per-server overrides
  - delete blueprint blocked when linked servers exist
  - blueprint changes apply on next action
  - server can reassign blueprint anytime

## Planned Repository Layout

- `l4d2host/`
- `l4d2web/`
- `deploy/`
- `docs/superpowers/plans/`

## Deployment

See `deploy/README.md` for the Linux test deployment contract, including the runtime user, target filesystem layout, systemd units, privileged helpers, sudoers rules, admin bootstrap, and overlay reference rules.

## Local development

This repo is a [uv](https://docs.astral.sh/uv/) workspace (`l4d2host` + `l4d2web` as members) with a committed `uv.lock` and a `.python-version` pinning Python 3.13 (matching the Debian Trixie production target).

One-time prereq: install `uv` (macOS: `brew install uv`; Linux: `curl -LsSf https://astral.sh/uv/install.sh | sh` — `uv` is not yet in Debian stable's apt).

1. `direnv allow` once per fresh checkout (and after any `.envrc` change). `.envrc` uses `use uv`, which runs `uv sync` and activates `.venv/` on `cd`.
2. Without direnv: `uv sync` at the repo root creates `.venv/`, installs both workspace members editable, and pulls in dev deps (pytest) from the lockfile.
3. Tests: `uv run pytest` (or just `pytest` once the venv is on PATH).

## Tech Stack (planned)

- Python 3.13+ (workspace uses uv + hatchling)
- Typer, PyYAML, pytest
- Flask, SQLAlchemy, Alembic
- HTMX (vendored locally), custom CSS, SSE
- systemd units, kernel overlayfs (mounted via the `left4me-overlay` privileged helper), steamcmd

## Recommended Implementation Order

1. Implement `l4d2host` plan first.
2. Implement `l4d2web` plan second.
3. Keep tests green task-by-task (TDD flow from plans).
4. Keep commits small and aligned with plan tasks.

## Contributing Notes

- Follow plan task order unless explicitly re-planned.
- Keep contracts above unchanged unless the user asks to change them.
- Update plan docs when scope or behavior changes.
