mise is a polyglot tool and task runner that manages Rust, Node, environment variables, and dev tasks from a single config file. Frona uses it as the single entry point for all development workflows.
mise.toml overview
The committed mise.toml in the project root defines three things:
Tools
[tools]
rust = "1.97.1"
node = "24.19.0"
rust-analyzer = "latest"
"cargo:cargo-watch" = "latest"Running mise install installs all of these automatically. No need to manage Rust or Node versions manually.
Environment variables
[env]
FRONA_DATABASE_PATH = "data/db"
FRONA_LOG_LEVEL = "debug"
FRONA_SERVER_BACKEND_URL = "http://localhost:3001"
FRONA_SERVER_FRONTEND_URL = "http://localhost:3000"
FRONA_SERVER_PORT = "3001"
ANTHROPIC_API_KEY = { required = true }
FRONA_SERVER_CORS_ORIGINS = "http://localhost:3000"
FRONA_BROWSER_WS_URL = "ws://localhost:3333"
FRONA_BROWSER_PROFILES_PATH = "/profiles"These defaults work out of the box for local development. Override any of them in mise.local.toml.
Tasks
All dev workflows are defined as mise tasks. Run any task with mise run <task>.
Key commands
| Command | Description |
|---|---|
mise run dev | Run full stack locally (backend + frontend with hot-reload) |
mise run dev:backend | Run backend only with cargo-watch |
mise run dev:frontend | Run Next.js frontend dev server only |
mise run build | Production build (frontend + backend) |
mise run check | Cargo check all crates |
mise run lint | Run clippy + frontend lint |
mise run test | Run all tests |
mise run fmt | Format the Rust workspace |
mise run fmt:check | Verify workspace-wide Rust formatting |
mise run container:dev | Run the full development stack with hot-reload |
mise run container:dev:build | Rebuild the development image and run the stack |
mise run container:dev:down | Stop the development stack and remove its named volumes |
mise run container:prod | Build and run the production stack |
mise run container:prod:down | Stop the production stack |
mise run container | Build the production container image |
mise run container:publish | Build the production image and push it to GHCR |
mise run container:update-versions | Pull dependencies and update pinned versions |
mise run release | Release: bump version, git tag, build and push Docker image |
mise run clean | Remove build artifacts and generated files |
The container tasks use Podman when it is installed, otherwise Docker. Set CONTAINER_RUNTIME=docker or CONTAINER_RUNTIME=podman to override detection. CONTAINER_BUILD_JOBS controls parallel Podman image-build jobs; the development wrapper derives CONTAINER_UID and CONTAINER_GID from the current user unless you override them.
Configuring mise.local.toml
mise.local.toml is gitignored and used for personal API keys and local overrides. Create it in the project root:
[env]
# Required
ANTHROPIC_API_KEY = "sk-ant-..."
# Optional: additional LLM providers
# OPENROUTER_API_KEY = "sk-or-..."
# OLLAMA_API_BASE_URL = "http://localhost:11434"
# Optional: SearXNG override (if running outside Docker)
# FRONA_SEARXNG_URL = "http://localhost:8888"
# Optional: Twilio voice integration
# FRONA_VOICE_TWILIO_ACCOUNT_SID = "AC..."
# FRONA_VOICE_TWILIO_AUTH_TOKEN = "..."
# FRONA_VOICE_TWILIO_FROM_NUMBER = "+1..."
# Optional: ngrok for exposing local instance
# NGROK_AUTHTOKEN = "..."Common overrides
Custom CORS origins
If you're accessing Frona from a different device on your network (e.g., testing on a phone):
[env]
FRONA_SERVER_CORS_ORIGINS = "http://localhost:3000,http://192.168.1.100:3000"
FRONA_SERVER_BACKEND_URL = "http://192.168.1.100:3001"Alternate backend URL
When testing the frontend against a remote or staging backend:
[env]
FRONA_SERVER_BACKEND_URL = "https://frona.example.com"