mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-20 03:40:29 +08:00
Trimmed the description from ~1216 to ~620 chars while keeping trigger coverage (reproducible cross-platform envs, system deps, local services, .flox/manifest.toml/flox activate/FloxHub).
498 lines
14 KiB
Markdown
498 lines
14 KiB
Markdown
---
|
|
name: flox-environments
|
|
description: "Create reproducible, cross-platform (macOS/Linux) development environments with Flox, a declarative Nix-based environment manager. Use when setting up project toolchains for any language, installing system-level dependencies (compilers, databases, native libs like openssl/BLAS), pinning exact package versions for a team, running local services (PostgreSQL, Redis, Kafka), onboarding developers with one command, or solving 'works on my machine' problems — including agent/vibe-coding setups that need project-scoped tools without sudo. Also use when the user mentions .flox/, manifest.toml, flox activate, or FloxHub."
|
|
metadata:
|
|
origin: Flox
|
|
---
|
|
|
|
# Flox Environments
|
|
|
|
Flox creates reproducible development environments defined in a single TOML manifest. Every developer on the team gets identical packages, tools, and configuration — across macOS and Linux — without containers or VMs. Built on Nix with access to over 150,000 packages.
|
|
|
|
## When to Activate
|
|
|
|
Use this skill when the user has an environment management problem — even if they haven't mentioned Flox. Flox is the right tool when:
|
|
|
|
- The project needs **system-level packages** (compilers, databases, CLI tools) alongside language-specific dependencies
|
|
- **Reproducibility matters** — the setup should work identically on a teammate's machine, in CI, or on a fresh laptop
|
|
- The user needs **multiple tools to coexist** — e.g., Python 3.11 + PostgreSQL 16 + Redis + Node.js in one environment
|
|
- **Cross-platform support** is needed (macOS and Linux from the same config)
|
|
- **AI agents need to install tools** — Flox lets agents add packages to a project-scoped environment without sudo, system pollution, or sandbox restrictions
|
|
|
|
If the user just needs a single language runtime with no system dependencies, standard tooling (nvm, pyenv, rustup alone) may suffice. If they need full OS-level isolation, containers might be more appropriate. Flox sits in the sweet spot: declarative, reproducible environments without container overhead.
|
|
|
|
**Prerequisite:** Flox must be installed first — see [flox.dev/docs](https://flox.dev/docs/install-flox/install/) for macOS, Linux, and Docker.
|
|
|
|
## Core Concepts
|
|
|
|
Flox environments are defined in `.flox/env/manifest.toml` and activated with `flox activate`. The manifest declares packages, environment variables, setup hooks, and shell configuration — everything needed to reproduce the environment anywhere.
|
|
|
|
**Key paths:**
|
|
- `.flox/env/manifest.toml` — Environment definition (commit this)
|
|
- `$FLOX_ENV` — Runtime path to installed packages (like `/usr` — contains `bin/`, `lib/`, `include/`)
|
|
- `$FLOX_ENV_CACHE` — Persistent local storage for caches, venvs, data (survives rebuilds)
|
|
- `$FLOX_ENV_PROJECT` — Project root directory (where `.flox/` lives)
|
|
|
|
## Essential Commands
|
|
|
|
```bash
|
|
flox init # Create new environment
|
|
flox search <package> [--all] # Search for packages
|
|
flox show <package> # Show available versions
|
|
flox install <package> # Add a package
|
|
flox list # List installed packages
|
|
flox activate # Enter environment
|
|
flox activate -- <cmd> # Run a command in the environment without a subshell
|
|
flox edit # Edit manifest interactively
|
|
```
|
|
|
|
## Manifest Structure
|
|
|
|
```toml
|
|
# .flox/env/manifest.toml
|
|
|
|
[install]
|
|
# Packages to install — the core of the environment
|
|
ripgrep.pkg-path = "ripgrep"
|
|
jq.pkg-path = "jq"
|
|
|
|
[vars]
|
|
# Static environment variables
|
|
DATABASE_URL = "postgres://localhost:5432/myapp"
|
|
|
|
[hook]
|
|
# Non-interactive setup scripts (run every activation)
|
|
on-activate = """
|
|
echo "Environment ready"
|
|
"""
|
|
|
|
[profile]
|
|
# Shell functions and aliases (available in interactive shell)
|
|
common = """
|
|
alias dev="npm run dev"
|
|
"""
|
|
|
|
[options]
|
|
# Supported platforms
|
|
systems = ["x86_64-linux", "aarch64-linux", "x86_64-darwin", "aarch64-darwin"]
|
|
```
|
|
|
|
## Package Installation Patterns
|
|
|
|
### Basic Installation
|
|
|
|
```toml
|
|
[install]
|
|
nodejs.pkg-path = "nodejs"
|
|
python.pkg-path = "python311"
|
|
rustup.pkg-path = "rustup"
|
|
```
|
|
|
|
### Version Pinning
|
|
|
|
```toml
|
|
[install]
|
|
nodejs.pkg-path = "nodejs"
|
|
nodejs.version = "^20.0" # Semver range: latest 20.x
|
|
|
|
postgres.pkg-path = "postgresql"
|
|
postgres.version = "16.2" # Exact version
|
|
```
|
|
|
|
### Platform-Specific Packages
|
|
|
|
```toml
|
|
[install]
|
|
# Linux-only tools
|
|
valgrind.pkg-path = "valgrind"
|
|
valgrind.systems = ["x86_64-linux", "aarch64-linux"]
|
|
|
|
# macOS frameworks
|
|
Security.pkg-path = "darwin.apple_sdk.frameworks.Security"
|
|
Security.systems = ["x86_64-darwin", "aarch64-darwin"]
|
|
|
|
# GNU tools on macOS (where BSD defaults differ)
|
|
coreutils.pkg-path = "coreutils"
|
|
coreutils.systems = ["x86_64-darwin", "aarch64-darwin"]
|
|
```
|
|
|
|
### Resolving Package Conflicts
|
|
|
|
When two packages install the same binary, use `priority` (lower number wins):
|
|
|
|
```toml
|
|
[install]
|
|
gcc.pkg-path = "gcc12"
|
|
gcc.priority = 3
|
|
|
|
clang.pkg-path = "clang_18"
|
|
clang.priority = 5 # gcc wins file conflicts
|
|
```
|
|
|
|
Use `pkg-group` to group packages that should resolve versions together:
|
|
|
|
```toml
|
|
[install]
|
|
python.pkg-path = "python311"
|
|
python.pkg-group = "python-stack"
|
|
|
|
pip.pkg-path = "python311Packages.pip"
|
|
pip.pkg-group = "python-stack" # Resolves together with python
|
|
```
|
|
|
|
## Language-Specific Recipes
|
|
|
|
### Python with uv
|
|
|
|
```toml
|
|
[install]
|
|
python.pkg-path = "python311"
|
|
uv.pkg-path = "uv"
|
|
|
|
[vars]
|
|
UV_CACHE_DIR = "$FLOX_ENV_CACHE/uv-cache"
|
|
PIP_CACHE_DIR = "$FLOX_ENV_CACHE/pip-cache"
|
|
|
|
[hook]
|
|
on-activate = """
|
|
venv="$FLOX_ENV_CACHE/venv"
|
|
if [ ! -d "$venv" ]; then
|
|
uv venv "$venv" --python python3
|
|
fi
|
|
if [ -f "$venv/bin/activate" ]; then
|
|
source "$venv/bin/activate"
|
|
fi
|
|
|
|
if [ -f requirements.txt ] && [ ! -f "$FLOX_ENV_CACHE/.deps_installed" ]; then
|
|
uv pip install --python "$venv/bin/python" -r requirements.txt --quiet
|
|
touch "$FLOX_ENV_CACHE/.deps_installed"
|
|
fi
|
|
"""
|
|
```
|
|
|
|
### Node.js
|
|
|
|
```toml
|
|
[install]
|
|
nodejs.pkg-path = "nodejs"
|
|
nodejs.version = "^20.0"
|
|
|
|
[hook]
|
|
on-activate = """
|
|
if [ -f package.json ] && [ ! -d node_modules ]; then
|
|
npm install --silent
|
|
fi
|
|
"""
|
|
```
|
|
|
|
### Rust
|
|
|
|
```toml
|
|
[install]
|
|
rustup.pkg-path = "rustup"
|
|
pkg-config.pkg-path = "pkg-config"
|
|
openssl.pkg-path = "openssl"
|
|
|
|
[vars]
|
|
RUSTUP_HOME = "$FLOX_ENV_CACHE/rustup"
|
|
CARGO_HOME = "$FLOX_ENV_CACHE/cargo"
|
|
|
|
[profile]
|
|
common = """
|
|
export PATH="$CARGO_HOME/bin:$PATH"
|
|
"""
|
|
```
|
|
|
|
### Go
|
|
|
|
```toml
|
|
[install]
|
|
go.pkg-path = "go"
|
|
gopls.pkg-path = "gopls"
|
|
delve.pkg-path = "delve"
|
|
|
|
[vars]
|
|
GOPATH = "$FLOX_ENV_CACHE/go"
|
|
GOBIN = "$FLOX_ENV_CACHE/go/bin"
|
|
|
|
[profile]
|
|
common = """
|
|
export PATH="$GOBIN:$PATH"
|
|
"""
|
|
```
|
|
|
|
### C/C++
|
|
|
|
```toml
|
|
[install]
|
|
gcc.pkg-path = "gcc13"
|
|
gcc.pkg-group = "compilers"
|
|
|
|
# IMPORTANT: gcc alone doesn't expose libstdc++ headers — you need gcc-unwrapped
|
|
gcc-unwrapped.pkg-path = "gcc-unwrapped"
|
|
gcc-unwrapped.pkg-group = "libraries"
|
|
|
|
cmake.pkg-path = "cmake"
|
|
cmake.pkg-group = "build"
|
|
|
|
gnumake.pkg-path = "gnumake"
|
|
gnumake.pkg-group = "build"
|
|
|
|
gdb.pkg-path = "gdb"
|
|
gdb.systems = ["x86_64-linux", "aarch64-linux"]
|
|
```
|
|
|
|
## Hooks and Profile
|
|
|
|
### Hooks — Non-Interactive Setup
|
|
|
|
Hooks run on every activation. Keep them fast and idempotent. Rule of thumb: **if it should happen automatically, put it in `[hook]`; if the user should be able to type it, put it in `[profile]`.**
|
|
|
|
```toml
|
|
[hook]
|
|
on-activate = """
|
|
setup_database() {
|
|
if [ ! -d "$FLOX_ENV_CACHE/pgdata" ]; then
|
|
initdb -D "$FLOX_ENV_CACHE/pgdata" --no-locale --encoding=UTF8
|
|
fi
|
|
}
|
|
setup_database
|
|
"""
|
|
```
|
|
|
|
### Profile — Interactive Shell Configuration
|
|
|
|
Profile code is available in the user's shell session.
|
|
|
|
```toml
|
|
[profile]
|
|
common = """
|
|
dev() { npm run dev; }
|
|
test() { npm run test -- "$@"; }
|
|
"""
|
|
```
|
|
|
|
## Anti-Patterns
|
|
|
|
### Absolute Paths
|
|
|
|
```toml
|
|
# BAD — breaks on other machines
|
|
[vars]
|
|
PROJECT_DIR = "/home/alice/projects/myapp"
|
|
|
|
# GOOD — use Flox environment variables
|
|
[vars]
|
|
PROJECT_DIR = "$FLOX_ENV_PROJECT"
|
|
```
|
|
|
|
### Using exit in Hooks
|
|
|
|
```toml
|
|
# BAD — kills the shell
|
|
[hook]
|
|
on-activate = """
|
|
if [ ! -f config.json ]; then
|
|
echo "Missing config"
|
|
exit 1
|
|
fi
|
|
"""
|
|
|
|
# GOOD — return from hook, don't exit
|
|
[hook]
|
|
on-activate = """
|
|
if [ ! -f config.json ]; then
|
|
echo "Missing config — run setup first"
|
|
return 1
|
|
fi
|
|
"""
|
|
```
|
|
|
|
### Storing Secrets in Manifest
|
|
|
|
```toml
|
|
# BAD — manifest is committed to git
|
|
[vars]
|
|
API_KEY = "<set-at-runtime>"
|
|
|
|
# GOOD — reference external config or pass at runtime
|
|
# Use: API_KEY="<your-api-key>" flox activate
|
|
[vars]
|
|
API_KEY = "${API_KEY:-}"
|
|
```
|
|
|
|
### Slow Hooks Without Idempotency Guards
|
|
|
|
```toml
|
|
# BAD — reinstalls every activation
|
|
[hook]
|
|
on-activate = """
|
|
pip install -r requirements.txt
|
|
"""
|
|
|
|
# GOOD — skip if already installed
|
|
[hook]
|
|
on-activate = """
|
|
if [ ! -f "$FLOX_ENV_CACHE/.deps_installed" ]; then
|
|
uv pip install -r requirements.txt --quiet
|
|
touch "$FLOX_ENV_CACHE/.deps_installed"
|
|
fi
|
|
"""
|
|
```
|
|
|
|
### Putting User Commands in Hooks
|
|
|
|
```toml
|
|
# BAD — hook functions aren't available in the interactive shell
|
|
[hook]
|
|
on-activate = """
|
|
deploy() { kubectl apply -f k8s/; }
|
|
"""
|
|
|
|
# GOOD — use [profile] for user-invokable functions
|
|
[profile]
|
|
common = """
|
|
deploy() { kubectl apply -f k8s/; }
|
|
"""
|
|
```
|
|
|
|
## Full-Stack Example
|
|
|
|
A complete environment for a Python API with PostgreSQL:
|
|
|
|
```toml
|
|
[install]
|
|
python.pkg-path = "python311"
|
|
uv.pkg-path = "uv"
|
|
postgresql.pkg-path = "postgresql_16"
|
|
redis.pkg-path = "redis"
|
|
jq.pkg-path = "jq"
|
|
curl.pkg-path = "curl"
|
|
|
|
[vars]
|
|
UV_CACHE_DIR = "$FLOX_ENV_CACHE/uv-cache"
|
|
DATABASE_URL = "postgres://localhost:5432/myapp"
|
|
REDIS_URL = "redis://localhost:6379"
|
|
|
|
[hook]
|
|
on-activate = """
|
|
if [ ! -d "$FLOX_ENV_CACHE/pgdata" ]; then
|
|
initdb -D "$FLOX_ENV_CACHE/pgdata" --no-locale --encoding=UTF8
|
|
fi
|
|
|
|
venv="$FLOX_ENV_CACHE/venv"
|
|
if [ ! -d "$venv" ]; then
|
|
uv venv "$venv" --python python3
|
|
fi
|
|
if [ -f "$venv/bin/activate" ]; then
|
|
source "$venv/bin/activate"
|
|
fi
|
|
|
|
if [ -f requirements.txt ] && [ ! -f "$FLOX_ENV_CACHE/.deps_installed" ]; then
|
|
uv pip install --python "$venv/bin/python" -r requirements.txt --quiet
|
|
touch "$FLOX_ENV_CACHE/.deps_installed"
|
|
fi
|
|
"""
|
|
|
|
[profile]
|
|
common = """
|
|
serve() { uvicorn app.main:app --reload --host 0.0.0.0 --port 8000; }
|
|
migrate() { alembic upgrade head; }
|
|
"""
|
|
|
|
[services]
|
|
postgres.command = "postgres -D $FLOX_ENV_CACHE/pgdata -k $FLOX_ENV_CACHE"
|
|
redis.command = "redis-server --port 6379 --daemonize no"
|
|
|
|
[options]
|
|
systems = ["x86_64-linux", "aarch64-linux", "x86_64-darwin", "aarch64-darwin"]
|
|
```
|
|
|
|
Activate with services: `flox activate --start-services`
|
|
|
|
## Environment Sharing
|
|
|
|
Flox environments are git-native. Commit the `.flox/` directory and every collaborator gets the same environment:
|
|
|
|
```bash
|
|
git add .flox/
|
|
git commit -m "Add Flox environment"
|
|
# Teammates just run:
|
|
git clone <repo> && cd <repo> && flox activate
|
|
```
|
|
|
|
For reusable base environments across projects, push to FloxHub:
|
|
|
|
```bash
|
|
flox push # Push environment to FloxHub
|
|
flox activate -r owner/env-name # Activate remote environment anywhere
|
|
```
|
|
|
|
Compose environments with `[include]`:
|
|
|
|
```toml
|
|
[include]
|
|
base.floxhub = "myorg/python-base"
|
|
|
|
[install]
|
|
# Project-specific additions on top of base
|
|
fastapi.pkg-path = "python311Packages.fastapi"
|
|
```
|
|
|
|
## AI-Assisted and Vibe Coding
|
|
|
|
Flox is ideal for AI-assisted development and vibe coding workflows. When an AI agent needs a tool that isn't available in the current environment — a compiler, a database, a linter, a CLI utility — it can add it to the project's Flox manifest without requiring sudo access, polluting system packages, or hitting sandbox restrictions.
|
|
|
|
**Why this matters for agents:**
|
|
- **No sudo required** — `flox install` works entirely in user space, so agents can add packages without elevated permissions
|
|
- **Project-scoped** — packages are installed into the project environment only, not globally, so different projects can have different versions without conflict
|
|
- **Sandbox-friendly** — agents running in sandboxed or restricted environments can still install the tools they need through Flox
|
|
- **Reversible** — every change is captured in `manifest.toml`, so unwanted packages can be removed cleanly with no system residue
|
|
- **Reproducible** — when an agent sets up an environment, that exact setup is committed to git and works for everyone
|
|
|
|
**Agent workflow pattern:**
|
|
|
|
```bash
|
|
# Agent discovers it needs a tool (e.g., jq for JSON processing)
|
|
flox search jq # Verify the package exists
|
|
flox install jq # Install into project environment
|
|
|
|
# Or for more control, edit the manifest directly
|
|
tmp_manifest="$(mktemp)"
|
|
flox list -c > "$tmp_manifest"
|
|
# Add the package to [install] section, then apply
|
|
flox edit -f "$tmp_manifest"
|
|
|
|
# Run a command with the tool available
|
|
flox activate -- jq '.results[]' data.json
|
|
```
|
|
|
|
This makes Flox a natural fit for any workflow where Claude Code or other AI agents need to bootstrap project tooling on the fly.
|
|
|
|
## Debugging
|
|
|
|
```bash
|
|
flox list -c # Show raw manifest
|
|
flox activate -- which python # Check which binary resolves
|
|
flox activate -- env | grep FLOX # See Flox environment variables
|
|
flox search <package> --all # Broader package search (case-sensitive)
|
|
```
|
|
|
|
**Common issues:**
|
|
- **Package not found:** Search is case-sensitive — try `flox search --all`
|
|
- **File conflicts between packages:** Add `priority` to the package that should win
|
|
- **Hook failures:** Use `return` not `exit`; guard with `${FLOX_ENV_CACHE:-}`
|
|
- **Stale dependencies:** Delete the `$FLOX_ENV_CACHE/.deps_installed` flag file
|
|
|
|
## Related Skills
|
|
|
|
The following skills are available as part of the [Flox Claude Code plugin](https://github.com/flox/flox-agentic) for deeper integration:
|
|
|
|
- **flox-services** — Service management, database setup, background processes
|
|
- **flox-builds** — Reproducible builds and packaging with Flox
|
|
- **flox-containers** — Create Docker/OCI containers from Flox environments
|
|
- **flox-sharing** — Environment composition, remote environments, team patterns
|
|
- **flox-cuda** — CUDA and GPU development environments
|
|
|
|
Learn more and install at [flox.dev/docs](https://flox.dev/docs/install-flox/install/)
|