diff --git a/.kilo/plans/1776548369772-nimble-planet.md b/.kilo/plans/1776548369772-nimble-planet.md new file mode 100644 index 0000000..c8d7e4d --- /dev/null +++ b/.kilo/plans/1776548369772-nimble-planet.md @@ -0,0 +1,110 @@ +# Plan: Add Snacks app to zima-apps + +## Context + +`apps.md` lists "Snacks" (https://github.com/derekshreds/snacks) as a pending app. It is an automated video library encoder with hardware acceleration (NVENC, QSV, VAAPI, AMF). + +This plan has two parts: +1. Create the Snacks app definition +2. Update `apps.md` with agent instructions for future additions + +--- + +## Part 1: Create `Apps/snacks/` + +### Steps + +1. **Create `Apps/snacks/` directory** from `_template` + +2. **`docker-compose.yaml`** — adapt upstream `deploy-compose.yml`: + + | Field | Upstream value | ZimaOS target | + |---|---|---| + | `name` | n/a | `snacks` | + | `image` | `derekshreds/snacks-docker:latest` | **Pinned version** — fetch latest release tag from GitHub, verify manifest exists | + | `network_mode` | `host` | Keep `host` — required for cluster UDP broadcast discovery | + | `privileged` | `true` | Keep `true` — required for `/dev/dri` access on QNAP/ZimaOS | + | `devices` | `/dev/dri:/dev/dri` | Keep — VAAPI/QSV hardware acceleration | + | `ports` | none (host mode) | Add `6767:6767` for web UI | + | `volumes` | QNAP-specific paths | Parameterize as `/DATA/AppData/$AppID/...` | + | `environment` | QNAP-specific ffmpeg path | Use default ffmpeg path; make jellyfin-ffmpeg path configurable | + + Security baseline (MUST): + - `security_opt: ["no-new-privileges:true"]` + - `cap_drop: ["ALL"]` + - `deploy.resources.reservations` set to appropriate value + + High-risk settings that MUST be documented in README: + - `network_mode: host` — required for cluster UDP broadcast + - `privileged: true` — required for `/dev/dri` access + - Device mount `/dev/dri` — GPU acceleration + +3. **`README.md`** — document: + - Purpose: automated video library encoder with hardware acceleration + - Port: 6767 (web UI) + - Volumes: media library, logs, config + - High-risk settings with justification, alternatives evaluated, and risks + - Hardware acceleration options (VAAPI, QSV, NVENC) + - Cluster mode (UDP broadcast requirement) + - Health check endpoint + +4. **Image pinning**: Before merge, verify the image tag exists in Docker Hub registry (manifest check) + +5. **Run validation**: `./scripts/validate-appstore.sh` + +6. **Optional**: `HOW_TO_VERIFY.md` with integration test cases + +### Risk Assessment + +- **High risk** due to `network_mode: host`, `privileged: true`, and device mounts +- Must document all three in README per AGENTS.md §3 +- Image must be pinned — no `:latest` + +### Branch name + +`snacks/initial/add-video-encoder` + +--- + +## Part 2: Update `apps.md` + +### Changes + +Replace current content with a table format that includes: +- Done/pending checkbox +- App name +- Source URL +- Brief description +- Agent instructions column (how to pick up this item) + +The file should serve as an agent-facing backlog — clear enough that an agent can read it, understand what is needed, and execute without additional prompting. + +### Suggested format + +```markdown +## Backlog + +| # | Done | Name | Source | What | Agent instructions | +|---|---|---|---|---|---| +| 1 | [ ] | Snacks | https://github.com/derekshreds/snacks | Automated video library encoder | Pick up, follow AGENTS.md §9 workflow, branch `snacks/initial/add-video-encoder` | + +## Adding a new app + +1. Copy `Apps/_template/` → `Apps//` +2. Set `name` in compose (lowercase + hyphen only) +3. Pin image to explicit version/tag (no `:latest`) +4. Add `x-casaos` metadata +5. Write `README.md` with purpose, ports, volumes, and risk justifications +6. Validate: `./scripts/validate-appstore.sh` +7. Run final validation before release: `./scripts/validate-appstore.sh --enforce-risk-docs` +``` + +--- + +## Verification + +- `docker-compose -f Apps/snacks/docker-compose.yaml config` passes (no syntax errors) +- No `:latest` references +- `x-casaos` metadata complete +- README documents all high-risk settings with justification +- `./scripts/validate-appstore.sh` reports `Validation OK` \ No newline at end of file diff --git a/.kilo/plans/1776627951342-lucky-tiger.md b/.kilo/plans/1776627951342-lucky-tiger.md new file mode 100644 index 0000000..2993297 --- /dev/null +++ b/.kilo/plans/1776627951342-lucky-tiger.md @@ -0,0 +1,192 @@ +# Plan: Local LLM Zima App (Intel NUC8) + +## Context +- **Hardware**: Intel NUC8 i7, 16GB RAM, 500GB SSD +- **Goal**: Zima app for local LLM inference with web UI +- **Constraints**: Intel Iris GPU cannot be used for LLM offload; CPU-only inference +- **Decisions**: + - Include OpenWebUI (two-container solution) + - 8G memory reservation (allows 7B Q4 models) + - App name: `llama-server` + +--- + +## Technology Decision + +### vLLM — **REJECTED** +- Requires NVIDIA CUDA GPU +- Cannot run on Intel NUC + +### llama.cpp (llama-server) — **SELECTED** +- CPU-only, AVX2/AVX512 optimized +- Built-in REST API server +- Minimal footprint, fast for quantized models +- Best fit for NUC8 constraints + +### LocalAI — **BACKUP OPTION** +- More features (TTS, image gen, multi-model) +- Can backend to llama.cpp +- Heavier; only choose if extra features needed + +### OpenWebUI — **RECOMMENDED COMPANION** +- Modern chat UI for LLM +- Docker-based, easy to deploy alongside +- Can be separate Zima app or documented companion + +--- + +## Architecture: Two Zima Apps + +``` +┌─────────────────────────┐ ┌─────────────────────────┐ +│ llama-server │ │ open-webui │ +│ - REST API :8080 │────▶│ - Chat UI :3000 │ +│ - Serves model │ │ - Connects to LLM API │ +└─────────────────────────┘ └─────────────────────────┘ +``` + +Both are separate Zima apps, deployed independently. OpenWebUI references `http://llama-server:8080` via Docker internal networking. + +### App 1: `llama-server` +- Container: `ghcr.io/ggerganov/llama.cpp:server` +- Port: 8080 +- Memory: 8G reservation + +### App 2: `open-webui` +- Container: `ghcr.io/open-webui/open-webui:main` +- Port: 3000 +- Memory: 2G reservation +- Environment: `OLLAMA_BASE_URL=http://llama-server:8080` + +--- + +## App: `llama-server` + +### Container: `ghcr.io/ggerganov/llama.cpp:server` + +**Environment Variables**: +| Variable | Default | Description | +|----------|---------|-------------| +| `MODEL` | (required) | Model filename in `/models` | +| `CTX_SIZE` | 2048 | Context window size | +| `N_THREADS` | auto | CPU threads (auto = all) | +| `HOST` | 0.0.0.0 | Listen address | +| `PORT` | 8080 | API port | +| `MAX_TOKENS` | 512 | Max tokens to generate | + +**Volumes**: +| Container | Description | +|-----------|-------------| +| `/models` | Model files (GGUF format) | +| `/DATA/AppData/$AppID/logs` | Server logs | + +**Ports**: +| Container | Protocol | Description | +|-----------|----------|-------------| +| 8080 | TCP | llama.cpp REST API | + +**Resources**: +- Memory reservation: **8G** (allows 7B Q4 models) + +**Security**: +- `security_opt: no-new-privileges:true` +- `cap_drop: ALL` +- No privileged needed (CPU-only) + +### Model Download (Documented in README) +Users download models manually: +```bash +# Example: Download Llama 3.2 3B Q4_K_M +curl -L -o /DATA/AppData/llama-server/models/llama-3.2-3b-q4_k_m.gguf \ + "https://huggingface.co/QuantFactory/Llama-3.2-3B-Instruct-GGUF/resolve/main/Llama-3.2-3B-Instruct.Q4_K_M.gguf" +``` + +**Recommended Models for 16GB RAM**: +| Model | Size | Quant | RAM Needed | Speed (est) | +|-------|------|-------|------------|-------------| +| Llama 3.2 3B | 1.8GB | Q4_K_M | ~4GB | ~15-20 tok/s | +| Phi-3.5 Mini 3B | 1.8GB | Q4_K_M | ~4GB | ~15-20 tok/s | +| Mistral 7B | 4.1GB | Q4_K_M | ~6-7GB | ~8-12 tok/s | +| Qwen 2.5 7B | 4.4GB | Q4_K_M | ~6-7GB | ~8-12 tok/s | + +--- + +## App: `open-webui` + +### Container: `ghcr.io/open-webui/open-webui:main` + +**Environment Variables**: +| Variable | Default | Description | +|----------|---------|-------------| +| `OLLAMA_BASE_URL` | http://llama-server:8080 | LLM API endpoint | +| `WEBUI_PORT` | 3000 | Web UI port | + +**Ports**: +| Container | Protocol | Description | +|-----------|----------|-------------| +| 3000 | TCP | OpenWebUI | + +**Resources**: +- Memory reservation: **2G** + +**Notes**: +- Connects to `http://llama-server:8080` via Docker internal networking +- Requires `llama-server` app to be running first + +--- + +## File Structure +``` +Apps/llama-server/ +├── docker-compose.yaml +├── README.md +└── HOW_TO_VERIFY.md (optional) + +Apps/open-webui/ +├── docker-compose.yaml +├── README.md +└── HOW_TO_VERIFY.md (optional) +``` + +--- + +## Implementation Steps + +### llama-server +1. Create `Apps/llama-server/` directory +2. Write `docker-compose.yaml` with: + - Image: `ghcr.io/ggerganov/llama.cpp:server` + - 8G memory reservation + - Port 8080 + - Model volume at `/models` + - Env vars: MODEL, CTX_SIZE, N_THREADS, HOST, PORT +3. Write `README.md` with: + - Model download instructions + - First-run setup + - API testing examples + - Performance tips for NUC8 +4. Validate with `./scripts/validate-appstore.sh` + +### open-webui +1. Create `Apps/open-webui/` directory +2. Write `docker-compose.yaml` with: + - Image: `ghcr.io/open-webui/open-webui:main` + - 2G memory reservation + - Port 3000 + - Environment: `OLLAMA_BASE_URL=http://llama-server:8080` +3. Write `README.md` with: + - Prerequisites (llama-server must be running first) + - How to access + - Troubleshooting connection issues +4. Validate with `./scripts/validate-appstore.sh` + +--- + +## Risk Assessment + +| Risk | Level | Mitigation | +|------|-------|------------| +| NUC8 RAM insufficient for 7B with other apps | Medium | 8G reservation; close other apps for 7B | +| Model download issues | Low | Provide direct HF links in README | +| OpenWebUI API compatibility | Low | llama.cpp v1 API is OpenAI-compatible | +| Intel AVX2 performance | Low | llama.cpp auto-detects and uses AVX2 | diff --git a/.kilo/plans/1776630080917-eager-moon.md b/.kilo/plans/1776630080917-eager-moon.md new file mode 100644 index 0000000..cab312b --- /dev/null +++ b/.kilo/plans/1776630080917-eager-moon.md @@ -0,0 +1,93 @@ +# Plan: Update AGENTS.md with Commit/Test/Build/Push Workflow + +## Context + +The repo's AGENTS.md (section 4 "Arbetsflöde för ändringar") currently only mentions `./scripts/validate-appstore.sh` as a loose recommendation. It lacks detailed guidance on the full development lifecycle: committing, testing images, building the appstore zip, and pushing. + +## Goal + +Add a new section to AGENTS.md (or expand section 4) covering the full workflow: + +### A. Branch & Commit Workflow +- Branch naming per existing section 8 +- Single-focus commits (one logical change per commit) +- Commit message format: short summary + bullet points for details +- What files can be committed (Apps/ scope rules from section 9) + +### B. Image Verification (Pre-commit) +- Before committing compose changes, verify images are online: + ```bash + docker manifest inspect + ``` +- Alternative: use build-appstore-zip.sh which does this automatically + +### C. Local Validation +- Always run before push/PR: + ```bash + ./scripts/validate-appstore.sh + ``` + +### D. Building the Appstore Package +- Script: `./scripts/build-appstore-zip.sh` +- Outputs to `dist/phirna-appstore.zip` +- Auto-generates SHA256 checksum +- Verifies all images online before building +- Commits `dist/` separately from app changes + +### E. Push & Release +- Push order: app commits → build zip → commit zip → push +- PR description must include (per existing section 6): + - Affected app IDs + - Security risk level + - High-risk settings changes + +## Proposed New Section (12) in AGENTS.md + +``` +## 12) Release- och publiceringsarbetsflöde + +### Steg 1: Branch +Skapa branch enligt format i sektion 8: +// + +### Steg 2: Verifiera images (innan commit) +Kontrollera att alla Docker-images är tillgängliga online: +docker manifest inspect + +### Steg 3: Validera lokalt +Kör validering innan commit: +./scripts/validate-appstore.sh + +### Steg 4: Committa ändringar +- Små, reviewbara commits +- Separera appfiler från dist/-filer +- Commit-meddelande: rubrik + bulletpunkter + +### Steg 5: Bygg appstore-zip +./scripts/build-appstore-zip.sh +- Skapar dist/phirna-appstore.zip +- Verifierar alla images +- Genererar SHA256 + +### Steg 6: Committa dist/ +Separer commit för dist/ från appfiler: +git add dist/ && git commit -m "Build appstore zip" + +### Steg 7: Push och PR +git push -u origin +Skapa PR med: +- Vilka app-id som påverkas +- Säkerhetsrisk (låg/medel/hög) +- Högrisk-inställningar vid introduktion +``` + +## Implementation + +1. Read current AGENTS.md +2. Insert new section 12 after existing section 11 +3. Renumber subsequent sections (12 → 13, etc.) + +## Questions for User + +- Should this be a new numbered section or expand existing section 4? +- Is `dist/phirna-appstore.zip` the correct output name for all repos, or should this be configurable? diff --git a/.kilo/plans/1776672399841-quick-meadow.md b/.kilo/plans/1776672399841-quick-meadow.md new file mode 100644 index 0000000..4d5f226 --- /dev/null +++ b/.kilo/plans/1776672399841-quick-meadow.md @@ -0,0 +1,170 @@ +# Plan: Gitea Bot User Setup for Tea CLI + +## Context + +Enable the agent (Kilo) to interact with Gitea (git.phirna.uk) via the `tea` CLI for: +- Creating branches +- Committing and pushing changes +- Creating pull requests +- Managing issues and labels + +## Step 1: Username Suggestion + +**Suggested username: `kilo-bot`** + +While not directly Norse mythology, "Kilo" evokes the Norse root meaning "coal" or "torch". Alternatives if you prefer pure mythology: + +| Username | Origin | +|----------|--------| +| `kilo-bot` | Kilo = "torch of life" from Old Norse "Kjöl" | +| `mimir-bot` | Mimir - Norse god of wisdom, keeper of knowledge | +| `hnir-bio` | Hnir - "breath" in Old Norse | +| `sowilo-bot` | Sowilo - the S rune, meaning "sun" | + +**Recommendation**: `kilo-bot` — maintains brand consistency with the agent name "Kilo". + +## Step 2: Required Permissions + +Based on Gitea granular scopes, the bot needs: + +| Scope | Reason | +|-------|--------| +| `write:repository` | Create branches, push commits, create PRs | +| `read:repository` | Read branches, commits, repos | +| `read:user` | Identify authenticated user | +| `write:issue` | Create/update issues if needed | +| `read:org` | Read org membership if needed | + +**Alternative**: Use `write:repository, read:user` for minimal permissions covering all git operations. + +**NOT needed**: `admin` (would allow deleting repos, managing orgs, etc.) + +## Step 3: Create the Bot User + +Requires admin access on git.phirna.uk. Steps: + +1. Go to `https://git.phirna.uk/admin/users/new` (or use `tea admin`) +2. Create user `kilo-bot` with email (e.g., `kilo-bot@phirna.uk`) +3. Set a strong random password (store in password manager) +4. Optionally add to relevant organization(s) + +## Step 4: Generate Access Token + +1. Login as `kilo-bot` +2. Go to Settings → Applications → "Manage Access Tokens" +3. Create token with name `kilo-cli` and scopes: + - `repository:write` + - `user:read` +4. Copy the generated token securely + +## Step 5: Configure Tea + +```bash +tea logins add --name kilo-bot --url https://git.phirna.uk --token +``` + +Or set environment variable `GITEA_TOKEN` or configure in `~/.config/tea/config.yml`. + +## Step 6: Update AGENTS.md + +Add new section or subsection covering: + +- Bot user credentials (token) storage approach +- Expected token scopes +- tea command patterns for common operations +- Security considerations (bot has limited scope) + +## Step 7: Create Skill (optional but recommended) + +Create `.kilo/.skills/gitea-agent.md`: + +- Standardized tea commands for branch creation +- Commit/push workflow via tea +- PR creation commands +- Issue management shortcuts + +## Security Considerations + +- Bot should **NOT** be admin +- Token should be scoped to `write:repository` + `read:user` only +- Token stored in environment or secured config, NOT in repo +- Consider setting bot's `MaxTokenPermissions` at org level if supported + +## Verification Steps + +After setup, test: + +```bash +# Verify identity +tea whoami --login kilo-bot + +# List repos (should see assigned repos) +tea repos list --login kilo-bot + +# Create a test branch +git checkout -b test/tea-cli-test +git push -u origin test/tea-cli-test --force +``` + +## Confirmed Decisions + +| Decision | Choice | +|----------|--------| +| Username | `mimir` (already created on Gitea) | +| Token storage | Tea login system (`tea logins add`) | +| Access scope | All repos on git.phirna.uk | + +## Implementation Steps + +### Step 1: Generate Access Token for mimir + +1. Login to `https://git.phirna.uk` as `mimir` +2. Go to Settings → Applications → "Manage Access Tokens" +3. Create token with name `kilo-cli` and scopes: + - `repository:write` + - `user:read` +4. Copy the generated token securely + +### Step 2: Add Tea Login + +```bash +tea logins add --name mimir --url https://git.phirna.uk --token +``` + +Verify with: +```bash +tea whoami --login mimir +``` + +### Step 3: Update AGENTS.md + +Add new section under "Repo-invarianter" or create new section: + +``` +## X) Gitea Bot (mimir) + +För att kunna skapa branches, commits och PRs via tea: + +- Användare: `mimir` på git.phirna.uk +- Token lagras i tea's login system (`tea logins add`) +- Scopes: `repository:write`, `user:read` +- Säkerhet: mimir är inte admin, token har begränsade scopes + +Exempel-kommandon: +tea pr create --login mimir --owner --repo +tea pulls list --login mimir --owner --repo +``` + +### Step 4: Create Skill (optional) + +Create `.kilo/.skills/gitea-agent.md` with tea command patterns. + +### Step 5: Verify Access + +```bash +# Should show mimir's identity +tea whoami --login mimir + +# Should list repos mimir can access +tea repos list --login mimir +``` diff --git a/AGENTS.md b/AGENTS.md index 0b94ccb..97db39f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -122,9 +122,42 @@ Filen ska vara praktiskt körbar och innehålla: - exakta kommandon för att verifiera DNS, nät och TLS, - en sektion \"data att samla\" för snabb Codex-felsökning. -Sektionen \"data att samla\" ska minst täcka: +Sektionen "data att samla" ska minst täcka: - versions-/buildinfo (appversion, branch/commit eller zip + checksum), - relevant konfiguration (med maskade secrets), - loggar från berörda containers, - konkreta felobservationer (hostname, tidpunkt, förväntat vs faktiskt beteende). + +## 11) Gitea Bot (mimir) + +För att kunna skapa branches, commits och PRs via tea-CLI: + +- **Användare**: `mimir` på git.phirna.uk +- **Token**: Lagras i tea's login-system via `tea logins add` +- **Scopes**: `repository:write`, `user:read` +- **Säkerhet**: mimir är inte admin, token har begränsade scopes + +### Vanliga kommandon + +```bash +# Sätt aktiv login +export GITEA_LOGIN=mimir + +# Lista repos +tea repos list --login mimir + +# Skapa branch och push +git checkout -b +git push -u origin + +# Skapa PR +tea pulls create --login mimir --owner --repo --head --base + +# Lista öppna PRs +tea pulls list --login mimir --owner --repo + +# Hantera issues +tea issues list --login mimir --owner --repo +tea issues create --login mimir --owner --repo --title "Titel" --body "Body" +```