flox-environments

Create reproducible, cross-platform development environments with Flox — a declarative environment manager built on Nix. ALWAYS use this skill when the user…

INSTALLATION
npx skills add https://github.com/affaan-m/everything-claude-code --skill flox-environments
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$2a

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

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

# .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

[install]

nodejs.pkg-path = "nodejs"

python.pkg-path = "python311"

rustup.pkg-path = "rustup"

Version Pinning

[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

[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):

[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:

[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

[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 ] &#x26;&#x26; [ ! -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

[install]

nodejs.pkg-path = "nodejs"

nodejs.version = "^20.0"

[hook]

on-activate = """

  if [ -f package.json ] &#x26;&#x26; [ ! -d node_modules ]; then

    npm install --silent

  fi

"""

Rust

[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

[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++

[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].**

[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.

[profile]

common = """

  dev() { npm run dev; }

  test() { npm run test -- "$@"; }

"""

Anti-Patterns

Absolute Paths

# 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

# 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

# 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

# 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

# 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:

[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 ] &#x26;&#x26; [ ! -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:

git add .flox/

git commit -m "Add Flox environment"

# Teammates just run:

git clone <repo> &#x26;&#x26; cd <repo> &#x26;&#x26; flox activate

For reusable base environments across projects, push to FloxHub:

flox push                         # Push environment to FloxHub

flox activate -r owner/env-name   # Activate remote environment anywhere

Compose environments with [include]:

[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 requiredflox 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:

# 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

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 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

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card