App-creating app for HomeFree
  • Python 54.1%
  • JavaScript 22%
  • CSS 11.6%
  • Nix 7.7%
  • HTML 4.6%
Find a file
2026-06-13 16:50:55 -07:00
apps/homefree-ai updated to separate other peoples apps on home dashboard 2026-06-13 16:50:55 -07:00
docs moved to non-nix managed podman containers 2026-06-01 23:37:15 -07:00
.gitignore first revision 2026-05-29 22:54:26 -07:00
AGENTS.md guidance updates 2026-06-03 19:05:40 -07:00
CLAUDE.md guidance updates 2026-06-03 19:05:40 -07:00
flake.nix first revision 2026-05-29 22:54:26 -07:00
README.md moved to non-nix managed podman containers 2026-06-01 23:37:15 -07:00

homefree-ai

A HomeFree flake plugin that turns natural-language prompts into HomeFree plugin scaffolds — the same recursive idea as lovable.dev / gpt-engineer, narrowed to HomeFree's plugin contract.

The service runs as a HomeFree app: a small FastAPI backend, a single-page vanilla-JS frontend, an OCI container built from nixpkgs, SSO-gated by HomeFree's Caddy oauth2-proxy flow. The user enters a prompt ("build me a HomeFree plugin called homefree-feedreader that runs Tiny Tiny RSS on port 3060"); the model produces a complete plugin-flake directory on disk; the user registers it through the same admin panel Custom Flakes page they used to register this plugin.

It works against the Anthropic Claude API out of the box and against HomeFree's local Ollama instance when enabled, via a small provider abstraction.

What it adds

HomeFree AI runs as a single container, reverse-proxied at ai.<your-domain>. Once registered it appears in the admin panel under Services → HomeFree AI with these options:

  • enable — turn the service on/off
  • public — expose it on the WAN port
  • provideranthropic (default) or ollama
  • anthropic-model — defaults to claude-opus-4-7
  • ollama-model — defaults to llama3.1:8b
  • ollama-base-url — optional override; defaults to the local HomeFree Ollama instance when its enable flag is true

The web UI is gated by HomeFree's Zitadel SSO. The API key for Anthropic is read at runtime from /var/lib/homefree-secrets/homefree-ai/anthropic-api-key; populate it once and systemctl restart homefree-ai (the file is mounted read-only into the container, but re-read on every request, so a restart is only needed if the file was empty at boot).

How to add it to HomeFree

This plugin is registered through the admin panel — no command line, no editing /etc/nixos by hand.

  1. Put this repository on the HomeFree machine (it must be a git repository — a git+file:// flake requires one). Either clone it there, or copy the directory and run git init && git add -A && git commit inside it.
  2. Open the HomeFree admin panel and go to Developers → Custom Flakes.
  3. Click Add a custom flake and choose:
    • Local repository — file-browser to this directory, or
    • Remote URLgithub:<you>/homefree-ai (or wherever you publish it).
  4. Click Register flake, then Apply Changes.
  5. Open Services → HomeFree AI, enable it, choose a provider, Apply Changes.
  6. Populate the API key (Anthropic provider) or pull a model (Ollama provider) — see below.

To remove it: delete the entry on Custom Flakes and Apply Changes.

Populating the Anthropic API key

Until the admin UI grows a generic secrets-entry page, set the key once over SSH:

sudo install -d -m 700 /var/lib/homefree-secrets/homefree-ai
sudo install -m 600 /dev/stdin /var/lib/homefree-secrets/homefree-ai/anthropic-api-key <<'EOF'
sk-ant-...
EOF
sudo systemctl restart homefree-ai

Using the local Ollama provider

Enable HomeFree's built-in Ollama app first (Services → Ollama) and pull a model:

sudo podman exec ollama ollama pull llama3.1:8b

Then set provider = "ollama" in Services → HomeFree AI. The container will auto-resolve the Ollama base URL from the LAN address.

How it works

flake.nix              # exposes nixosModules.default
apps/homefree-ai/
  default.nix          # the NixOS module — declares options, container,
                       # systemd service, and the homefree.service-config
                       # entry that drives reverse proxy / SSO / backup.
  image.nix            # OCI image: python3 + fastapi/uvicorn/anthropic
                       # + jinja2 + httpx, plus the ./app source tree.
  icon.svg             # admin-panel tile icon
  app/                 # Python source copied into the image
    main.py            # FastAPI app: project APIs + SSE token stream
    settings.py        # env-var loader
    providers/         # LLM provider abstraction
    generator/         # prompt → file blocks → on-disk project
    static/            # vanilla-JS single-page UI

flake.nix's nixosModules.default is what HomeFree composes into the system build. apps/homefree-ai/default.nix is an ordinary HomeFree module — it declares options in both homefree.services.homefree-ai and homefree.service-options.homefree-ai (the dual-namespace pattern required for plugin flakes, see ~/homefree-navidrome/README.md for the rationale), wires a podman container with virtualisation.oci-containers, and contributes a single homefree.service-config list entry that the rest of HomeFree consumes (Caddy reads the reverse-proxy block, restic reads the backup paths, the admin panel reads the options-metadata).

The provider abstraction

providers/base.py defines an async LLMProvider.stream(system, messages) interface. Two implementations:

  • anthropic_provider.py — official anthropic SDK, streaming.
  • ollama_provider.pyhttpx over /api/chat with stream=true.

get_provider(name) returns the right one based on the configured provider name. Adding e.g. an OpenAI provider is a single new file plus a registry entry.

The generation flow

The model is given a system prompt that summarizes the HomeFree plugin contract in ~1500 tokens, plus one stripped Navidrome example for few-shot. It is told to emit project files as plain-text blocks:

<<<FILE path="flake.nix">>>
{
  outputs = ...;
}
<<<END>>>

generator/parser.py extracts these blocks with a deterministic regex; generator/projects.py writes them under /data/projects/<slug>/, refusing any path that escapes the project root. Tokens stream to the browser over SSE while the model is still producing output. The result is browsable, downloadable as a tarball, and ready for the user to git init and register through Custom Flakes — homefree-ai itself never writes to live system config or executes the generated code.

Security model

  • The UI is fully SSO-gated (oauth2 = true, kind = "caddy_gated").
  • The Anthropic key is owned by root and mounted read-only into the container.
  • The generator only writes inside /data/projects/<slug>/; path traversal is rejected before any write.
  • The model has no shell access, no tool-use that reaches the host, and no path to the live HomeFree configuration. The generated artifact is plain text the user reviews and registers themselves.

Limits and future work

  • v1 ships Anthropic + Ollama; OpenAI/Gemini providers are a straightforward addition.
  • The API key is set over SSH today; the admin panel will eventually grow a generic secrets-entry page.
  • Generated plugins are scaffolds — the user should still read and trim the output, and is expected to test in a HomeFree VM before deploying to a real box.