daisy-sdk 0.2.0
Daisy SDK CLI for auth and image fetch
License: MIT
Requires Python: >=3.11
Keywords: daisy, cli, sdk

# daisy-sdk

## Quickstart (for Daisy users)

1) Prereqs: Docker running; Python 3.11+.  
2) Install CLI: `pip install daisy-sdk`  
3) Enable `host.docker.internal` (required by the app in the container):  
   - macOS/Linux: `sudo sh -c "echo '127.0.0.1 host.docker.internal' >> /etc/hosts"`  
   - Windows (Admin PowerShell): `Add-Content -Path "C:\Windows\System32\drivers\etc\hosts" -Value "`r`n127.0.0.1 host.docker.internal"`  
4) Run Daisy: `daisy run` (UI at http://localhost:8080, control at http://127.0.0.1:3282).  
5) Stop Daisy: `daisy stop` (or Ctrl+C if in foreground).

## Contributing

### Setup

```bash
mise install
uv sync --dev
```

If `uv` is not installed, you can install it with mise or pipx:

```bash
# with mise
mise use -g uv@0.2

# or with pipx
pipx install uv
```

### Usage (dev)

```bash
PYTHONPATH=src uv run python -m daisy_sdk.cli run
```

Tokens must be stored in `~/.daisy/config.toml`:

```toml
access_token = "..."
refresh_token = "..."
```

On each run, the CLI validates the access token with Supabase; if it is invalid or expired, it refreshes and writes the new tokens back to the same file.

### Control server and hot restarts

`daisy run` now launches a lightweight control server (default bind `0.0.0.0:3282`, reachable at `http://127.0.0.1:3282` on the host) and starts the Daisy Docker container in the background (container name `daisy-local` by default). The Daisy image expects to reach the host API at `http://host.docker.internal:3282/`; changing the port requires rebuilding the main image with a new `VITE_HOST_API_BASE`.

- Health: `GET /health` returns container status and the active image tag.
- Restart with updated mounts: `POST /restart` (body: `{"project_path": "/path/just/added"}`) restarts the container after re-reading `~/.daisy/projects.toml` and broadcasts a refresh event to connected clients.
- Events: `GET /events` streams server-sent events; refresh events include `activeProject` when provided in the restart request.

Flags:
- `--port` host port for the Daisy UI (default `8080`).
- `--control-host` to choose how the CLI talks to the control server (default `127.0.0.1`); `--control-bind` to choose what the server binds to (default `0.0.0.0`); `--control-port` defaults to `3282` and should stay in sync with `VITE_HOST_API_BASE`.
- `--platform` to override the docker platform; leave unset to use Docker's default for the host.
- `--project-config-path` to point at a non-default `projects.toml`.
- If a Daisy container with the default name is already running, `daisy run` will just point you to the mapped port instead of restarting it.
- `--image` lets you force a specific local image tag; no pull will be attempted (docker run uses `--pull=never`).
- Advanced: run the control server directly via `python -m daisy_sdk.server --image <tag> [--detach]`; it now uses FastAPI + uvicorn. Default keeps it foreground (stops the container when terminated). `daisy run` also defaults to foreground; pass `--detach-control` to background it. In foreground mode, `Ctrl+C` stops both server and container.

Host control API (used by the frontend inside the container, via `host.docker.internal:3282`):
- `POST /projects` with `{"name": "...", "path": "/abs/path", "bi_paths": [...]}` registers/updates a project, validates the host path, writes `projects.toml`, and restarts the container with new mounts.
- `PATCH /projects/{name}` updates an existing project entry with the same validation/restart behavior.
- `POST /restart` forces a restart and emits a refresh event; `GET /events` streams refresh events; `GET /health` reports status.
- Container logs are forwarded to stdout with prefix `[daisy-container]` while the control server is running.
- CORS: control server responds with `Access-Control-Allow-Origin: *` and handles `OPTIONS` so the web app at `http://localhost:8080` can reach it.

Stopping:

- `daisy stop` sends `/shutdown` to the control server and also force-removes the container (`docker rm -f daisy-local` by default).