inpaint()/img2img()/outpaint() called /v1/images/edits without a model
field, so OpenAI defaulted every cloud edit to dall-e-2 regardless of
configuration — while txt2img used dall-e-3. Add a separate
OPENAI_EDIT_MODEL (default gpt-image-1, the only current model that
supports masked edits at ChatGPT-comparable quality), thread it through
the provider and both compose files, and handle gpt-image-1's
b64_json-only response shape alongside the url shape dall-e-2/3 return.
setup.sh's run_service() looks up install_<name> using the literal
hyphenated registered name, not an underscore-converted one. borg-backup,
calibre-web, gaming-backup, and stirling-pdf all used underscored function
names and were therefore uninstallable ("has no install_<name>"). Same
fix already applied to ai-gpu/ai-stack; this closes out the rest of the
repo-wide audit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb2vJ8W7bHKx1JXVvpCraH
PaintPlus's backend already supported invokeai/comfyui providers (generic
"self-hosted, on another machine" remote APIs) but the installer never
exposed them and the compose file never passed the URLs through. Add a
3rd provider choice — shown only when the ai-stack service is installed —
that sets AI_PROVIDER + INVOKEAI_URL/COMFYUI_URL and joins ai-stack's
Docker network (ai-stack_default) so PaintPlus can reach those containers
by name. No cloud key, no extra GPU download: it rides on ai-stack's
already-running InvokeAI/ComfyUI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb2vJ8W7bHKx1JXVvpCraH
Add gpu-mode.sh (written into ~/docker/ai-stack at install): time-shares
one small GPU between local chat (Ollama, for Open WebUI) and local
image-gen (InvokeAI + ComfyUI, backends for PaintPlus), leaving the
always-on services (Open WebUI, Gitea, RAG, MCP, Kiwix) untouched. A new
"small local GPU?" prompt enables it: when on, the GPU defaults to chat
mode after install and the user is told to swap deliberately. Cloud
models need no swap.
Document the intended split in POST-INSTALL-NOTES: Open WebUI is the
text hub (chat/research/light coding, wired to Gitea + GitHub sync + RAG
+ MCP), PaintPlus is the single image hub (cloud or local comfyui/
invokeai backend). Note web search is DuckDuckGo — this installer path
generates no SearXNG, so the SearXNG references are dropped.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb2vJ8W7bHKx1JXVvpCraH
Vendor the functional source of github.com/outis1one/local-ai into
./ai-stack (22 files) and add services/ai-stack.sh, which copies the
source to ~/docker/ai-stack and hands off to the app's VRAM-aware
installer (local-ai-setup.sh). The stack bundles Ollama, Open WebUI,
RAG + MCP servers, ChromaDB, SearXNG, Kiwix, Gitea, InvokeAI, ComfyUI
and Portainer.
Cloud LLM providers (Groq/DeepInfra/OpenAI/OpenRouter) are optionally
wired into Open WebUI via the plural OPENAI_API_BASE_URLS list, with the
local RAG connection kept as the first entry so RAG keeps working. Open
WebUI ships built-in auth, so Caddy is configured without Authelia.
Excludes the upstream's two bundled copies of this very project
(ubuntu-post-install.sh, ubuntu-post-install-main.zip) — stale and
circular. Coexists with the existing ai-gpu service.
Also fix the install-function names for ai-gpu and ai-stack: the
dispatcher calls install_<raw-name>, so the function must be
install_ai-gpu / install_ai-stack (hyphen), matching the working
mail-archiver / wg-easy services. ai-gpu was previously uninstallable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb2vJ8W7bHKx1JXVvpCraH
Shows a numbered menu of 12 known SWBF2 maps (Galactic Assault, Planetary
Battles, Starfighter Assault) during install. Selected maps are encoded as
base64 JSON and written to KYBER_MAP_ROTATION in .env.
Map IDs decoded from maprotation.hive binary: Geonosis, Kamino, Endor,
Tatooine, Death Star II, Starkiller Base, Crait, Hoth, Fondor (space).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Bring the full EditmaskwithAI application into the repo under paintplus/
(429 files) so the service is self-contained — the installer copies the
vendored source to ~/docker/paintplus/src instead of cloning at runtime.
Rename to PaintPlus (service + branding; app logic untouched):
- services/editmaskwithai.sh -> services/paintplus.sh (register_service
paintplus, install_paintplus, ~/docker/paintplus, Caddy paintplus:8000,
Authelia option preserved)
- container names -> paintplus across docker-compose*.yml; dev network
-> paintplus-network
- browser <title> -> "PaintPlus - AI Image Editor"; README heading ->
PaintPlus with upstream provenance note
- README utilities table: editmaskwithai -> paintplus
Backend/frontend code (help strings referencing the old container name,
the ai_photo_edit.db filename) is intentionally left as-is to avoid
touching application logic.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb2vJ8W7bHKx1JXVvpCraH
Package the self-hosted mask-based AI photo editor
(github.com/outis1one/EditmaskwithAI) as a utilities service. Clones the
repo into ~/docker/editmaskwithai and deploys on port 3080.
Two install modes:
- Cloud API (no GPU): writes .env from the repo template with the chosen
AI_PROVIDER (OpenAI gpt-image or Replicate), API key, and a generated
SECRET_KEY, then `docker compose up -d --build`.
- Local GPU (NVIDIA): runs the repo's own install-local-gpu.sh and
bring-up-local-gpu.sh (downloads ~13 GB of models).
The app has no built-in auth, so it offers Authelia SSO and reverse-proxies
via Caddy (ai-photo-edit:8000). Cloud mode joins caddy_net through a
docker-compose.override.yml; GPU mode is attached with `docker network
connect` since the GPU compose runs with an explicit -f and does not merge
overrides.
Also lists the service in the README utilities table.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb2vJ8W7bHKx1JXVvpCraH
When run directly without setup.sh, write_readme is not defined.
Add a minimal implementation to the else block of both kyber-server.sh
and sunshine.sh so standalone runs no longer fail with command not found.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Generalize the optional Groq toggle into a provider picker so the GPU AI
stack can wire Groq, DeepInfra, OpenAI, and/or OpenRouter into Open WebUI
at once. All are OpenAI-compatible, so they share Open WebUI's
OPENAI_API_BASE_URLS / OPENAI_API_KEYS (semicolon-separated, matched by
position). Keys are written to llm/.env; only ${VAR} references go into
docker-compose.yml.
Updates the install prompt, .env template, compose patch, README, the
dry-run note, and the final summary accordingly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb2vJ8W7bHKx1JXVvpCraH
If the kyber bin symlink and desktop entry are not present, prompt to
set up the launcher. Calls install_kyber_launcher directly if already
loaded (wizard), or sources kyber-launcher.sh when run standalone.
Skips the prompt on rerun if the launcher is already installed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
If auth.toml has no token, launch the Kyber AppImage as the actual user
(with DISPLAY/XAUTHORITY passed through), prompt the user to log in via
the EA Account button, then re-read auth.toml once they close Kyber.
Falls back to manual token paste if auth.toml still has nothing.
Skips the AppImage entirely on rerun when a token is already cached.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Running kyber_cli get_token under sudo opens a broken browser OAuth flow.
Instead, read the token directly from ~/.local/share/maxima/auth.toml which
Kyber writes after a normal GUI login. If missing, show clear instructions
to run the AppImage as yourself first, then re-run the installer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
On rerun, if ~/.local/share/maxima exists, offer to wipe it so EA login
starts completely fresh (fixes stuck/broken auth states).
Single-quote all .env values so passwords and tokens containing $, !, &,
spaces, and other shell special characters are written safely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
The standard Steam path search missed installs on secondary drives.
Now also reads libraryfolders.vdf to find all Steam library paths, then
falls back to a broad find across home/mnt/media. Wolf's copy is excluded
from the fallback search to prefer the native Steam install.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Adds a Moonlight app entry that launches SWBF2 directly via Steam
(steam://rungameid/1237950) — both with and without the Kyber entry.
Moonlight app list now shows: Kyber SWBF2 | SWBF2 Single Player | Desktop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
When SWBF2 is not found locally, prompt to rsync from a remote host.
Asks for remote host, username, and path (defaults to the standard Steam
Linux path). Files land in ~/docker/kyber-server/swbf2/ and that path is
used automatically. Falls back to manual local path entry if rsync declined.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Instead of hard-failing, show an rsync example for copying game files from
another machine, then prompt for the path. Validates that starwarsbattlefrontii.exe
exists at the given location before continuing.
Also silence "register_service: command not found" in all three services when
run standalone (guard with command -v check).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Steam must be running when Kyber is used. The installer now detects whether
Steam is present (command or ~/.steam path), and if not, prompts to install
it via apt (steam-installer or steam package, with i386 multiarch enabled).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
When run directly (sudo bash services/foo.sh), bash executes the bootstrap
block before reaching the install_* function definition below it, causing
"command not found". Moving the bootstrap to the end of each file ensures
the function is defined by the time the bootstrap calls it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Installs the Kyber community multiplayer launcher (simonlinuxcraft/kyber-
linuxport-unofficial) via the setup.sh wizard. Handles glibc check, bwrap/
userns fix, GitHub release fetch, desktop entry, and bin symlink. Warns on
Intel integrated graphics and links to Sunshine as the streaming alternative.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Installs Sunshine (LizardByte) as a Moonlight-compatible streaming host,
offset to port 48090 so it coexists with Wolf. Auto-detects the Kyber
AppImage and adds a "Kyber SWBF2" app entry. Optional virtual display for
closed-lid/headless use. uinput udev rules for controller/mouse input.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
- Auto-detects SWBF2 install path; loud error with install instructions if missing
- Downloads Kyber AppImage if not present, extracts kyber_cli, runs get_token
(opens browser for EA OAuth — one-time step, token never expires)
- Prompts for EA credentials (written to .env, chmod 600) and server name
- Auto-detects GPU (NVIDIA/Intel/AMD) and adds appropriate passthrough config
- Writes docker-compose.yml + .env to ~/docker/kyber-server/
- Map rotation left blank by default with instructions in .env comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
- Add troubleshooting for 'Origin Error: title installed in language not
entitled to play' — Maxima's umu-run reg commands fail silently on some
systems; manual wine64 regedit import of Origin locale keys fixes it
- Add windowed-mode / HDR fix for SWBF2 crash during level load on
integrated GPUs (Intel Iris Xe, DXVK rendering crash)
- Document fix in both README.md and script header comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
- Bots are set via BOTS TEAM 1 / BOTS TEAM 2 sliders in HOST panel (not automatic)
- Correct launch order: Steam open but don't click Play; Kyber launches SWBF2 itself
- Document Alt+Tab / taskbar click workaround for window focus issue after game loads
- Add bwrap unprivileged userns fix (Ubuntu 24.04 blocks by default); script applies
automatically with sudo and persists via /etc/sysctl.d/99-userns.conf
- Script now checks/fixes userns at step 0 before download
- Kyber manages its own GE-Proton; no need to configure Proton for SWBF2 in Steam
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
The Windows kyber_launcher.exe approach under Wine/Proton has two
unfixable problems on Linux: Wine's cmd.exe crashes with STATUS_ACCESS_VIOLATION
on the long EA OAuth URL, and EA's auth callback uses the eadesktop://
URI scheme which has no Linux handler.
The correct solution is the native Linux port AppImage maintained at
github.com/simonlinuxcraft/kyber-linuxport-unofficial. It bundles Maxima
(open-source EA Desktop replacement) and handles OAuth natively — no shims,
no watchers, no per-Proton-update maintenance.
Script now: fetches latest release from GitHub API, downloads AppImage,
installs desktop entry and ~/.local/bin/kyber symlink.
README: add Gaming scripts section documenting Kyber setup, private server
hosting with bots, requirements, and what does not work.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
After extensive testing, Wine/Proton loads cmd.exe exclusively from
Proton's own installation (files/lib/wine/x86_64-windows/cmd.exe).
Replacing the prefix system32 copy, IFEO registry keys, WINEDLLOVERRIDES,
and Wine DllOverrides registry entries all have no effect — Proton's copy
always takes precedence.
The working fix: compile a tiny shim (GetCommandLineA scan for http URLs,
write to C:\kyber_oauth_url.txt, ExitProcess(0)) and replace Proton's
cmd.exe directly, backing up the original as cmd.exe.bak. The script
detects size (shim ~9KB vs real cmd.exe ~1.2MB) to avoid double-replacing.
Note for users: re-run setup-kyber-linux.sh after any Proton Experimental
update since Steam restores the original cmd.exe on update.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
system.reg values use \\ for one backslash, so C:\shim\kyber_cmd.exe
must be written as C:\\shim\\kyber_cmd.exe. The previous script wrote
C:\\\\shim\\\\kyber_cmd.exe (4 backslashes = two literal backslashes),
which Wine couldn't resolve.
Also detect when the shim slot contains Wine's cmd.exe (122231 bytes)
left behind by a failed earlier attempt, and recompile automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
Proton's prefix-setup phase overwrites system32/cmd.exe on every game
launch, breaking the previous approach of placing a shim there. Switch to
Windows Image File Execution Options (IFEO): the shim is compiled to
drive_c/shim/kyber_cmd.exe (Proton never touches that directory) and the
IFEO Debugger key is written to system.reg so Wine intercepts cmd.exe at
CreateProcess time without touching the filesystem binary.
Also fix the wine64 path used for winetricks: correct path is
files/lib/wine/x86_64-unix/wine64 not files/bin/wine64.
The shim is simplified to scan all args for any http URL (IFEO passes the
debuggee path as an extra arg, so the /c start pattern match was fragile).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs