angreal.integrations.flox¶
Cross-language development environment and services management powered by Flox.
Overview¶
Angreal's Flox integration provides environment activation and services management using Flox, a Nix-based development environment manager. It activates a Flox environment — applying its environment variables to the current process — and manages the declarative background services defined in the environment's manifest.toml.
Prerequisites¶
Flox CLI must be installed before using this integration.
Installation:
# macOS
curl -fsSL https://flox.dev/install | bash
# Linux
curl -fsSL https://flox.dev/install | bash
# Verify installation
flox --version
Creating a Flox Environment:
Functions¶
flox_required¶
Decorator that wraps a function to run in a Flox environment with optional services.
Parameters:
- path (str | Path, optional): Path to Flox environment. Defaults to current directory.
- services (List[str], optional): Services to start before execution.
Example:
from angreal.integrations.flox import flox_required
import angreal
@angreal.command(name="test")
@flox_required(".", services=["postgres"])
def run_tests():
"""Run tests with Flox environment and Postgres service."""
import subprocess
subprocess.run(["pytest", "-v"])
# Without services
@angreal.command(name="build")
@flox_required(".")
def build():
"""Build in Flox environment."""
import subprocess
subprocess.run(["npm", "run", "build"])
The decorator: 1. Activates the Flox environment 2. Starts specified services (if any) 3. Executes the wrapped function 4. Stops services and deactivates environment (even on exception)
Classes¶
Flox¶
Main class for managing Flox environments.
Constructor¶
Parameters:
- path (str | Path, optional): Path to Flox environment. Defaults to current directory.
Properties¶
exists¶
Check if the Flox environment exists (.flox/ directory present).
Returns:
- bool: True if .flox/ directory exists
has_manifest¶
Check if the environment has a manifest file.
Returns:
- bool: True if .flox/env/manifest.toml exists
path¶
Get the environment path.
Returns:
- Path: Absolute path to the Flox environment
services¶
Get a FloxServices manager for this environment.
Returns:
- FloxServices: Services manager instance
Instance Methods¶
activate¶
Activate the Flox environment in the current Python process.
Modifies os.environ to include Flox environment variables. Changes persist until deactivate() is called.
Raises:
- RuntimeError: If the environment does not exist
Example:
flox = Flox(".")
flox.activate()
# Environment variables now include Flox paths
# FLOX_ENV, PATH, etc. are modified
flox.deactivate()
deactivate¶
Restore the original environment.
Restores all environment variables to their state before activation. Safe to call multiple times.
run¶
Execute a command within the Flox environment.
Parameters:
- command (str): Command to execute
- args (List[str], optional): Command arguments
Returns:
- tuple[int, str, str]: (exit_code, stdout, stderr)
Example:
flox = Flox(".")
exit_code, stdout, stderr = flox.run("python", ["--version"])
print(f"Python version: {stdout}")
Context Manager Support¶
Flox supports the context manager protocol for automatic activation/deactivation:
with Flox(".") as flox:
# Environment is activated
exit_code, stdout, _ = flox.run("node", ["--version"])
print(f"Node version: {stdout}")
# Environment is automatically deactivated
Class Methods¶
is_available¶
Check if Flox CLI is installed.
Returns:
- bool: True if flox command is available in PATH
Example:
if not Flox.is_available():
print("Please install Flox: curl -fsSL https://flox.dev/install | bash")
version¶
Get Flox version string.
Returns:
- str: Flox version (e.g., "1.2.0")
Raises:
- RuntimeError: If Flox is not installed
FloxServices¶
Manages Flox services for an environment.
from angreal.integrations.flox import FloxServices
services = FloxServices(".")
# Or via Flox instance
services = Flox(".").services
Methods¶
start¶
Start services and return a handle for later cleanup.
Parameters:
- *services: Service names to start. If empty, starts all services.
Returns:
- FloxServiceHandle: Handle for managing started services
Example:
services = FloxServices(".")
handle = services.start("postgres", "redis")
# Services are running...
handle.stop()
stop¶
Stop all services in the environment.
status¶
Get status of all services.
Returns:
- List[ServiceInfo]: List of service status objects
Example:
logs¶
Get logs for a service.
Parameters:
- service (str): Service name
- follow (bool): Follow log output (default: False)
- tail (int, optional): Number of lines from end
Returns:
- str: Log output
restart¶
Restart services.
Parameters:
- *services: Service names to restart. If empty, restarts all.
FloxServiceHandle¶
Handle for managing started services across sessions.
Properties¶
flox_env_path(Path): Path to the Flox environmentservices(List[ServiceInfo]): List of service info objectsstarted_at(str): ISO timestamp when services were started
Methods¶
stop¶
Stop the services tracked by this handle.
save¶
Save handle to JSON file for later restoration.
Parameters:
- path (str, optional): File path. Defaults to .flox-services.json
Example:
handle = services.start("postgres")
handle.save() # Saves to .flox-services.json
# Later, in another session...
handle = FloxServiceHandle.load()
handle.stop()
load (classmethod)¶
Load handle from JSON file.
Parameters:
- path (str, optional): File path. Defaults to .flox-services.json
Returns:
- FloxServiceHandle: Loaded handle
ServiceInfo¶
Information about a service.
Attributes¶
name(str): Service namestatus(str): Status (e.g., "Running", "Stopped")pid(int | None): Process ID if running
Methods¶
as_tuple¶
Convert to tuple format.
Returns:
- tuple: (name, status, pid)
Examples¶
Full Development Workflow¶
from angreal.integrations.flox import Flox, flox_required
import angreal
# Check Flox availability at module load
if not Flox.is_available():
print("Warning: Flox not installed. Some commands may not work.")
@angreal.command(name="setup")
def setup():
"""Initialize Flox environment."""
import subprocess
subprocess.run(["flox", "init"])
subprocess.run(["flox", "install", "python@3.11", "nodejs@20", "postgresql"])
@angreal.command(name="test")
@flox_required(".", services=["postgres"])
def test():
"""Run tests with database."""
import subprocess
result = subprocess.run(["pytest", "-v", "tests/"])
return result.returncode
@angreal.command(name="dev")
@flox_required(".", services=["postgres", "redis"])
def dev():
"""Start development server."""
import subprocess
subprocess.run(["python", "manage.py", "runserver"])
@angreal.command(name="build")
@flox_required(".")
def build():
"""Build the project."""
flox = Flox(".")
exit_code, stdout, stderr = flox.run("npm", ["run", "build"])
if exit_code != 0:
print(f"Build failed: {stderr}")
return 1
print("Build successful")
return 0
Service Status Dashboard¶
from angreal.integrations.flox import Flox
import angreal
@angreal.command(name="status")
def status():
"""Show Flox environment and service status."""
flox = Flox(".")
print(f"Flox version: {Flox.version()}")
print(f"Environment exists: {flox.exists}")
print(f"Has manifest: {flox.has_manifest}")
print(f"Path: {flox.path}")
print()
print("Services:")
for svc in flox.services.status():
pid_info = f"PID {svc.pid}" if svc.pid else "no PID"
print(f" {svc.name}: {svc.status} ({pid_info})")
See Also¶
- Virtual Environment Integration - Python venv integration
- Docker Compose Integration - Docker integration
- Flox Documentation - Official Flox documentation