Introduction
flk is a modern CLI tool for managing Nix flake development environments with the simplicity of tools like Devbox. It provides an intuitive interface for working with Nix flakes without manually editing configuration files.
Why flk?
- π― Smart Initialization: Auto-detects your project type
- π¦ Easy Package Management: Add/remove packages with simple commands
- β‘ Custom Commands: Define reusable shell commands
- π Environment Management: Manage environment variables easily
- π Lock File Management: Version control for your dependencies
Quick Example
# Initialize a Rust project
flk init
# Add packages
flk add ripgrep fd-find
# Define a custom command
flk cmd add build "cargo build --release"
# Enter the development environment
nix develop
# Use your custom command
build
Upgrading to v0.5.X (switch/refresh changes)
WARNING (pre v0.5.0 users): If you are using flk < v0.5.0 and you run flk update / nix flake update, your devshell switch / refresh behavior may break because the nix-profile-lib input may update to a newer version with different activation semantics.
If you intend to stay on flk < v0.5.0, use one of these options:
-
Do not update flake inputs. Avoid running
flk updateornix flake update. If you already did, restore a previous lockfile backup with:flk lock restore <BACKUP> -
Pin
nix-profile-libto v0.1.0. In yourflake.nix:inputs = { nix-profile-lib.url = "github:AEduardo-dev/nix-profile-lib?ref=v0.1.0"; };Then update the lock entry:
nix flake lock --update-input nix-profile-lib(or
nix flake update --update-input nix-profile-lib)
Once you upgrade to flk v0.5.0+, this restriction is lifted.
Documentation Structure
- User Guide: Learn how to use flk effectively
- Commands: Detailed reference for all commands
- Advanced Topics: Deep dives into specific features
- API Documentation: Internal API reference for contributors
Getting Help
Installation
Prerequisites
- Nix with flakes enabled
- We recommend the Lix package manager for easy Nix installation: Lix since it comes with flakes enabled by default.
- Or using the Determinate System installer: Determinate, as it provides a user-friendly way to install (and uninstall) Nix.
- Rust 1.83+ (if building from source)
Hooks
If you would like to use hot reloading and switching features, you will need to add the following shell hook to your shell configuration file (~/.bashrc, ~/.zshrc, etc.):
Example for bash:
# flk shell hook
if command -v flk &> /dev/null; then
eval "$(flk hook bash)"
fi
Support for other shells (zsh and fish) is also available via flk hook <shell>.
From Source
git clone https://github.com/AEduardo-dev/flk.git
cd flk
cargo build --release
sudo cp target/release/flk /usr/local/bin/
From Cargo (crates.io)
cargo install flk
From Release Binaries
- Go to https://github.com/AEduardo-dev/flk/releases
- Download the archive for your OS/arch (Linux x86_64, macOS Intel, macOS ARM).
- Unpack and place
flkin your PATH.
Nix (with Cachix binaries)
This flake is prebuilt and published to Cachix.
- Install Cachix (once):
nix profile install nixpkgs#cachix
- Trust the cache:
cachix use flk-cache
or add the following substituters and trusted-public-keys to your nix.conf content:
substituters = https://flk-cache.cachix.org ...
trusted-public-keys = flk-cache.cachix.org-1:6xobbpP9iIK5sIH/75DQrsJYKN/61nTOChcH9MJnBR0= ...
- Use the flake:
- Run (no install):
nix run github:AEduardo-dev/flk#flk - Install to your profile:
nix profile install github:AEduardo-dev/flk#flk
Nix β Using as a flake input
You can consume flk from another flake either directly or via the overlay.
Direct (no overlay):
{
description = "My NixOS config with flk";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flk.url = "github:AEduardo-dev/flk";
};
outputs = { self, nixpkgs, flk, ... }:
let
system = "x86_64-linux"; # set per host
pkgs = import nixpkgs { inherit system; };
in {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
{
environment.systemPackages = [
flk.packages.${system}.flk
];
}
];
};
};
}
With overlay (exposes pkgs.flk):
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.flk.url = "github:AEduardo-dev/flk";
outputs = { self, nixpkgs, flk, ... }:
let
system = "x86_64-linux"; # set per host
pkgs = import nixpkgs {
inherit system;
overlays = [ flk.overlay ];
};
in {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
{ environment.systemPackages = [ pkgs.flk ]; }
];
};
};
}
Home Manager example (per-user install via flake):
{
inputs.flk.url = "github:AEduardo-dev/flk";
outputs = { self, flk, ... }: {
homeConfigurations.myhost = {
# ...
home.packages = [ flk.packages.${system}.flk ];
};
};
}
Architectures covered by the cache
- x86_64-linux
- x86_64-darwin
- aarch64-darwin
- aarch64-linux (built via qemu on CI; may be slower/occasional misses)
Other architectures will fall back to building from source.
Next Steps
π Getting Started
1. Initialize Your Project
# Auto-detect project type and create flake.nix
flk init
# Or specify a template
flk init --template rust
flk init --template python
flk init --template node
flk init --template go
Supported auto-detection:
Cargo.tomlβ Rust templatepackage.jsonβ Node.js templatepyproject.tomlorrequirements.txtβ Python templatego.modβ Go template
2. Add Packages
# Search for packages
flk search ripgrep
# Get detailed package info and versions
flk deep-search ripgrep
# Add packages to your environment
flk add ripgrep
flk add git
flk add neovim
# Or add pinned versions
flk add ripgrep --version '15.1.0'
flk add git --version '2.42.0'
3. Add Custom Commands
# Add inline commands
flk command add test "cargo test --all"
flk command add dev "npm run dev"
4. Manage Environment Variables
# Add environment variables
flk env add DATABASE_URL "postgresql://localhost/mydb"
flk env add API_KEY "your-api-key"
# List all environment variables
flk env list
# Remove an environment variable
flk env remove API_KEY
5. Enter Your Development Environment
flk activate
Your custom commands and environment variables will be automatically available!
6. Generate completions
# Generates the completion file and prints it
flk completions
# Install the generated completions to the detected shell
flk completions --install
Follow the instructions after the command to make the completions available for you.
7. Attach to your direnv (optional)
If you use direnv, you can set it up to automatically load your flk environment when you enter the project directory.
# Generates a .envrc file for direnv with use flake command
flk direnv init
#or
# Add the direnv hook to an existing project
flk direnv attach
if you ever want to detach the direnv hook, you can run:
flk direnv detach
8. Switch / Refresh your environment
Add the following to your shell profile (~/.bashrc, ~/.zshrc, etc.) to enable switching and refreshing of your flk environment when you navigate between project directories:
e.g. Bash
eval "$(flk hook bash)"
Currently supported shells are: bash, zsh and fish.
Next Steps
Core Concepts
flk is built around a few core concepts that help you manage your development environments effectively. Understanding these concepts will help you make the most out of flk.
Projects
A project in flk is a directory that contains a flake.nix file. This file is the entry point to the environment for that project, including dependencies, custom commands, and environment variables.
When you navigate to a project directory and activate the flk environment, flk reads the profile.nix file and sets up the environment accordingly, using the files located in the .flk/profiles/ directory.
Profiles
Profiles are a way to manage different sets of dependencies and configurations for your projects. Each profile corresponds to a specific profile.nix configuration and is stored in the .flk/profiles/ directory. You can switch between profiles using the switch command (given you set up the hook for your shell accordingly), allowing you to easily change your development environment based on the project youβre working on.
Custom Commands
Custom commands are user-defined scripts that can be added to your flk environment. These commands are defined in the profile.nix file and can be executed directly from the command line when the flk environment is activated. This allows you to create project-specific tools and utilities that are easily accessible.
Environment Variables
Environment variables are key-value pairs that can be set within your flk environment. They are defined in the profile.nix file and are automatically loaded when you activate the flk environment for a project. This allows you to manage project-specific configurations, such as API keys or database URLs, without affecting your global environment.
Warning CAUTION: Be careful not to store sensitive information in plain text within your
profile.nixfile, especially if the project is shared or version-controlled.
Lock Files
Lock files are used to ensure that the dependencies for your flk projects remain consistent across different environments and over time. The lock file records the exact versions of dependencies used in your project, allowing you to reproduce the same environment later or on different machines. You can manage the lock file using the flk lock together with flk update commands.
Overlays
Overlays are a powerful feature in flk that allow you to customize and extend the Nix package set used in your projects. By defining overlays in your environment, your profiles can modify existing packages or add new ones, tailoring the environment to your specific needs. This is particularly useful for projects that require specific versions of packages or custom builds, and is tightly integrated with the flkβs lock file management to ensure consistency.
Shell Integration
flk integrates with your shell to provide a seamless experience when working with different projects. By setting up shell hooks, flk can expose a set of convenient commands that allow you to switch between profiles, and hot reload them. This integration enhances productivity by making it easy to work within the context of your flk-managed projects without the need to exit and re-enter your shell environment on every change.
Direnv Integration
flk can also integrate with direnv, a popular tool for managing environment variables based on the current directory. By using the flk direnv init command, you can generate a .envrc file that automatically loads your flk environment whenever you enter the project directory. This integration simplifies the workflow by ensuring that your development environment is always correctly set up without manual intervention.
Flk provides a set of commands flk direnv to help you manage this integration, making it easy to set up and maintain your development environments with direnv.
Container Exporting
flk supports exporting your development environment to container formats like Docker and Podman. This feature allows you to create portable and reproducible environments that can be easily shared and deployed across different systems. By using the flk export command, you can generate container images that encapsulate your projectβs dependencies, custom commands, and environment variables. This is particularly useful if flk is not natively supported on your target system, or if you want to ensure consistency across development, testing, and production environments.
Examples
This page provides complete, practical examples for common development scenarios.
Python Data Science Environment
Set up a complete data science environment with Jupyter, scientific packages, and helper commands.
# Initialize Python project
flk init --template python
# Add Python and data science packages
flk add python312
flk add python312Packages.numpy
flk add python312Packages.pandas
flk add python312Packages.matplotlib
flk add python312Packages.scikit-learn
flk add jupyter
# Add convenience commands
flk cmd add notebook "jupyter notebook --port=8888"
flk cmd add lab "jupyter lab --port=8888"
flk cmd add ipython "python -m IPython"
# Configure environment
flk env add JUPYTER_CONFIG_DIR "./.jupyter"
flk env add PYTHONDONTWRITEBYTECODE "1"
# Enter environment and start working
flk activate
notebook
Rust Web Backend
Full-stack Rust development with database, caching, and development tools.
# Initialize Rust project
flk init --template rust
# Add development dependencies
flk add postgresql
flk add redis
flk add sqlx-cli
flk add cargo-watch
# Add development commands
flk cmd add dev "cargo watch -x run"
flk cmd add test "cargo test --all-features"
flk cmd add migrate "sqlx migrate run"
flk cmd add db "psql $DATABASE_URL"
# Configure database connection
flk env add DATABASE_URL "postgresql://localhost/myapp"
flk env add REDIS_URL "redis://localhost:6379"
flk env add RUST_LOG "debug"
# Activate and start development
flk activate
dev
Node.js Full-Stack Application
Modern JavaScript/TypeScript development with database and tooling.
# Initialize Node project
flk init --template node
# Add runtime and tools
flk add nodejs_20
flk add postgresql
flk add docker-compose
flk add nodePackages.typescript
flk add nodePackages.eslint
# Add development commands
flk cmd add dev "npm run dev"
flk cmd add build "npm run build"
flk cmd add db:start "docker-compose up -d postgres"
flk cmd add db:stop "docker-compose down"
flk cmd add lint "npm run lint"
flk cmd add typecheck "tsc --noEmit"
# Set environment variables
flk env add NODE_ENV "development"
flk env add DATABASE_URL "postgresql://localhost/myapp"
flk env add PORT "3000"
# Start development
flk activate
db:start
dev
Go Microservice
Go development with common tools and testing setup.
# Initialize Go project
flk init --template go
# Add Go and tools
flk add go
flk add gopls
flk add golangci-lint
flk add mockgen
flk add protobuf
# Add commands
flk cmd add run "go run ./cmd/server"
flk cmd add test "go test ./..."
flk cmd add lint "golangci-lint run"
flk cmd add proto "protoc --go_out=. --go-grpc_out=. ./proto/*.proto"
flk cmd add build "go build -o bin/server ./cmd/server"
# Configure
flk env add GOPROXY "https://proxy.golang.org,direct"
flk env add CGO_ENABLED "0"
# Activate
flk activate
run
Multi-Language Monorepo
For projects with multiple languages, you can create separate profiles.
# Initialize with generic template
flk init --template generic
# The default profile is in .flk/profiles/default.nix
# You can create additional profiles by copying and modifying:
# .flk/profiles/frontend.nix
# .flk/profiles/backend.nix
# Add shared tools to default profile
flk add git
flk add docker-compose
flk add make
# Add commands that work across the project
flk cmd add up "docker-compose up -d"
flk cmd add down "docker-compose down"
flk cmd add logs "docker-compose logs -f"
Pinning Package Versions
When you need reproducible builds with specific versions:
# Pin specific package versions
flk add ripgrep --version 14.1.0
flk add nodejs --version 20.10.0
flk add python3 --version 3.11.6
# View what's pinned
flk list packages
# The version info is stored in .flk/pins.nix
Using with Direnv
Automatically activate environments when entering directories:
# Set up direnv integration
flk direnv init
# Allow the .envrc file
direnv allow
# Now the environment loads automatically when you cd into the project
cd ~/projects/myapp # Environment activates
cd ~ # Environment deactivates
Container Export for CI/CD
Export your development environment for use in CI or on machines without Nix:
# Export as Docker image
flk export --format docker
# Export as Podman image
flk export --format podman
# Export configuration as JSON (useful for debugging or other tools)
flk export --format json
Project Templates
flk uses templates to scaffold development environments tailored to your projectβs language and toolchain.
Using Templates
flk init --template rust
flk init --template python
flk init --template node
flk init --template go
flk init --template generic
Auto-Detection
If you omit --template, flk auto-detects the project type by looking for:
| File | Detected Template |
|---|---|
Cargo.toml | rust |
package.json | node |
pyproject.toml or requirements.txt | python |
go.mod | go |
| (none found) | generic |
Available Templates
base
Minimal template with no language-specific tools. Used as the default when creating profiles via flk profile add.
rust
Includes Rust toolchain essentials:
- Rust compiler and Cargo
- Common development tools (rust-analyzer, clippy, rustfmt)
- Build dependencies (pkg-config, openssl)
python
Includes Python development essentials:
- Python interpreter
- pip and virtualenv support
- Common development tools
node
Includes Node.js development essentials:
- Node.js runtime
- npm package manager
- Common development tools
go
Includes Go development essentials:
- Go compiler
- Go tools (gopls, etc.)
generic
A minimal starting point with basic utilities. Use this when your project doesnβt fit a specific language category or when you want to build a custom environment from scratch.
Template Files
Templates are stored in the templates/ directory of the flk source and are embedded at compile time:
templates/flake.nixβ Root flake templatetemplates/default.nixβ Profile loader/importertemplates/pins.nixβ Version pinning structuretemplates/overlays.nixβ Package overlaystemplates/profiles/*.nixβ Language-specific profile templates
Creating Additional Profiles
After initialization, you can create additional profiles from any template:
flk profile add backend --template rust
flk profile add frontend --template node
flk profile add scripts --template python
See Also
Custom Commands
Custom commands let you define reusable scripts in your flk environment. They become available as shell functions when the development environment is activated.
Basic Usage
flk cmd add dev "npm run dev"
flk cmd add test "cargo test --all"
flk cmd add lint "cargo clippy -- -D warnings"
flk cmd list
flk cmd remove dev
Loading from Files
For complex or multiline commands, use the --file flag:
flk cmd add deploy --file scripts/deploy.sh
This reads the command body from the specified file instead of inline text.
Profile Targeting
Commands are stored per-profile. Use --profile to target a specific one:
flk cmd add build "cargo build --release" --profile backend
flk cmd list --profile frontend
How It Works
Commands are stored in the commands block of your profile file (.flk/profiles/<profile>.nix):
commands = [
{ name = "dev"; script = ''npm run dev''; }
{ name = "test"; script = ''cargo test --all''; }
];
Each command becomes a shell function (via writeShellScriptBin) when you activate the environment.
Naming Rules
Command names must follow these rules:
- Letters, numbers, hyphens, and underscores only
- Cannot start with a hyphen
- Examples:
dev,run-tests,build_release
Examples
# Web development commands
flk cmd add dev "npm run dev"
flk cmd add build "npm run build && npm run typecheck"
flk cmd add db:migrate "npx prisma migrate dev"
# Rust project commands
flk cmd add watch "cargo watch -x 'run -- --port 8080'"
flk cmd add bench "cargo bench --all-features"
# Complex command from a file
echo '#!/bin/bash
echo "Running full CI pipeline..."
cargo fmt --check
cargo clippy -- -D warnings
cargo test --all' > scripts/ci.sh
flk cmd add ci --file scripts/ci.sh
See Also
Environment Variables
Manage per-project environment variables without touching your global shell configuration.
Basic Usage
flk env add DATABASE_URL "postgresql://localhost:5432/mydb"
flk env add NODE_ENV "development"
flk env remove DATABASE_URL
flk env list
Profile Targeting
Environment variables are stored per-profile. Use --profile to target a specific one:
flk env add API_URL "http://localhost:3000" --profile backend
flk env list --profile frontend
How It Works
Variables are stored in the envVars block of your profile file (.flk/profiles/<profile>.nix):
envVars = {
DATABASE_URL = "postgresql://localhost:5432/mydb";
NODE_ENV = "development";
};
They are automatically exported when you activate the environment via flk activate, nix develop, or direnv.
Naming Rules
Variable names must follow these rules:
- Start with a letter or underscore
- Contain only letters, numbers, and underscores
- Examples:
DATABASE_URL,MY_VAR,_PRIVATE_KEY - Invalid:
123VAR,my-var,my var
Security Considerations
Warning: Do not store secrets (API keys, passwords, tokens) directly in profile files, especially if your project is version-controlled.
For sensitive values, consider:
- Using direnv with a
.envrc.localfile (add to.gitignore) - Referencing secrets from a secrets manager at runtime
- Using environment-specific tooling outside of flk
See Also
Lock File Management
flk protects your flake.lock file with automatic backups, preview-before-update, and easy rollback.
Commands
flk lock show # inspect current lock file
flk lock history # list available backups
flk lock restore latest # restore most recent backup
flk update # update inputs (creates backup first)
flk update --show # preview updates without applying
How It Works
Automatic Backups
Every time you run flk update, a backup of the current flake.lock is created before any changes are made. Backups are stored in .flk/backups/ with timestamped filenames:
.flk/backups/
βββ flake.lock.2025-01-27_14-30-00
βββ flake.lock.2025-02-15_09-45-22
βββ flake.lock.2025-03-01_16-00-00
Preview Updates
Use flk update --show to see what would change without modifying your lock file:
flk update --show
This temporarily updates the lock file, shows the diff, then restores the original β a safe way to check for upstream changes.
Inspecting the Lock File
flk lock show
Displays structured information about each input in your flake.lock, including:
- Input name and type (e.g., github, indirect)
- Source URL
- Current revision/commit
- Last modified date
Viewing Backup History
flk lock history
Lists all available backups with their timestamps and sizes, so you can identify which snapshot to restore.
Restoring a Backup
flk lock restore latest # most recent backup
flk lock restore 2025-01-27_14-30-00 # specific timestamp
Replaces the current flake.lock with the selected backup.
Interaction with Version Pinning
When you pin a package version with flk add --version, the pinning data is stored in .flk/pins.nix (not in flake.lock). Lock file backups and restores do not affect version pins β they only manage the Nix input lock state.
Best Practices
- Run
flk update --showbeforeflk updateto review changes - Use
flk lock restore latestimmediately if an update causes issues - Backups accumulate over time; periodically clean old ones from
.flk/backups/if needed
See Also
Commands Overview
flk ships a small set of focused subcommands. They fall into a few groups:
- Project setup:
flk init,flk activate,flk hook <shell>, direnv helpers,flk profile - Packages:
flk search,flk deep-search,flk add,flk remove,flk list,flk show - Customization:
flk cmd,flk env,flk export - State management:
flk lock,flk update - Developer experience:
flk completions
Each command description below is intentionally shortβsee the examples on each page and the README for longer walkthroughs.
flk activate
Enter the Nix development shell for your project.
flk activate
flk activate --profile backend
Options
-p, --profile <PROFILE>: Activate a specific profile instead of the default
Behavior
- Runs
nix develop .#<profile> --impureto enter the dev shell - Reuses a cached develop profile from
.flk/.nix-profile-<profile>when your flake config is unchanged - Refreshes that cached profile when
flake.nix,flake.lock, or the relevant.flkprofile files change - Uses standard profile resolution when
--profileis not specified - Custom commands and environment variables from the profile are available inside the shell
Notes
- For automatic environment switching when navigating between projects, add the shell hook:
eval "$(flk hook bash)" # or zsh/fish - For automatic activation when entering a directory, use direnv integration
See Also
- flk hook β for
refreshandswitchcommands - flk direnv β for automatic directory-based activation
flk add
Add a package to your flake.nix.
flk add ripgrep
flk add git
flk add nodejs
flk add ripgrep --version '15.1.0' # pinned version
flk add cargo-watch --profile backend # specific profile
Options
-v, --version <VERSION>: pin to a specific version-p, --profile <PROFILE>: target a specific profile instead of the default
Behavior
- Validates the package exists (
nix-versions). - Writes to
.flk/profiles/<profile>.nix; updates.flk/pins.nixwhen pinning. - Fails if the package is already present.
flk cmd
Manage custom shell commands for your flk environment.
flk cmd add dev "npm run dev"
flk cmd add test "cargo test --all"
flk cmd list
flk cmd remove dev
Subcommands
add <NAME> <COMMAND> [--file <PATH>]: add a command (inline or from file)remove <NAME>: delete a commandlist: list all custom commands
Options
-p, --profile <PROFILE>: target a specific profile instead of the default
Notes
- Command names: letters, numbers, hyphens, underscores; cannot start with hyphen.
flk completions
Generate shell completions.
flk completions # print to stdout
flk completions --install # auto-install for detected shell
flk completions --shell zsh
Options
--install: install to the detected shell location--shell <SHELL>: override shell detection (bash,zsh,fish, etc.)
flk deep-search
Get detailed version and attribute information about a specific package from nixpkgs.
flk deep-search ripgrep
flk deep-search python3
Behavior
- Queries nixpkgs using
nix-versionsunder the hood - Displays available versions, attribute paths, and package metadata
- More detailed than
flk search, which only lists matching package names
Example Output
Package: ripgrep
Version: 14.1.1
Attribute: ripgrep
Description: A utility that combines the usability of The Silver Searcher with the raw speed of grep
When to Use
- Use
flk search <term>to find packages by name - Use
flk deep-search <package>to inspect a specific package in detail, especially to find available versions for pinning
See Also
flk env
Manage environment variables for your dev shell.
flk env add DATABASE_URL "postgresql://localhost:5432/mydb"
flk env remove DATABASE_URL
flk env list
Subcommands
add <NAME> <VALUE>: add/update a variableremove <NAME>: delete a variablelist: show all configured variables
Options
-p, --profile <PROFILE>: target a specific profile instead of the default
Notes
- Names must start with a letter/underscore and contain only letters, numbers, underscores.
flk export
Export the current flake configuration to Docker, Podman, or JSON.
flk export --format docker
flk export --format podman
flk export --format json
flk export --format docker --profile backend
Options
-f, --format <FORMAT>: Export format βdocker,podman, orjson(required)-p, --profile <PROFILE>: Target a specific profile instead of the default
Formats
Docker
Builds a Nix-based Docker image from the flake and loads it into the local Docker daemon.
- Requires Docker to be installed and running
- The image is built via
nix build .#docker-<profile>and loaded withdocker load - Output image is stored at
.flk/resultbefore loading
Podman
Same as Docker but uses Podman instead.
- Requires Podman to be installed and running
- Built via
nix build .#podman-<profile>and loaded withpodman load
JSON
Serializes the parsed flake configuration to a flake.json file in the project root.
- Includes all profiles, packages, environment variables, and inputs
- Useful for debugging, CI pipelines, or integrating with other tools
- Does not require Docker or Podman
Notes
- Docker and Podman exports use
--impurefor Nix builds - Uses standard profile resolution when
--profileis not specified
See Also
flk hook
Generate shell hooks that enable the refresh and switch commands for hot-reloading your development environment.
flk hook bash
flk hook zsh
flk hook fish
Usage
Add the hook output to your shell profile to enable refresh and switch:
# Bash (~/.bashrc)
eval "$(flk hook bash)"
# Zsh (~/.zshrc)
eval "$(flk hook zsh)"
# Fish (~/.config/fish/config.fish)
flk hook fish | source
Supported Shells
bashzshfish
Commands Provided by the Hook
Once sourced, two shell functions become available:
refresh
Reload the current development environment. Picks up changes youβve made (added packages, env vars, commands) without leaving the shell.
# After adding a package
flk add ripgrep
refresh
- If direnv is present and
.envrcexists, runsdirenv reload - Otherwise, reuses a cached
nix developprofile when it is still fresh - Rebuilds that cached profile when the flake inputs or relevant
.flkfiles change - Uses
FLK_FLAKE_REF(fallback:FLK_PROFILE) to determine the active profile
switch <profile>
Switch to a different profile and reload the environment.
switch backend
switch frontend
- Validates the profile name before switching
- Updates
FLK_FLAKE_REFandFLK_PROFILE, then reloads via direnv ornix develop - Reuses the saved profile cache until the environment definition changes
Notes
- The hook integrates with direnv automatically β if
.envrcis present, it usesdirenv reloadinstead ofexec nix develop - Profile names must be alphanumeric (with
-or_) - See also: flk activate, flk direnv
flk init
Initialize a new flake.nix for your project.
flk init # Auto-detect project type
flk init --template rust # Use Rust template
flk init --force # Overwrite existing flake.nix
Options
-t, --template <TYPE>:rust,python,node,go,generic(auto-detect if omitted)-f, --force: overwrite an existingflake.nix
What it does
- Creates
flake.nix,.flk/helper files, and a default profile under.flk/profiles/ - Auto-detects project type from common files (Cargo.toml, package.json, pyproject/requirements, go.mod)
- Prints next steps, including adding
flk hook <shell>to your shell config
flk lock
Manage flake.lock backups and inspection.
flk lock show # show lock info
flk lock history # list backups
flk lock restore latest # restore most recent backup
flk lock restore 2025-01-27_14-30-00
Subcommands
show: pretty-prints lock detailshistory: lists available backupsrestore <BACKUP>: restores a backup (timestamp orlatest)
flk list
List all packages in the current profile.
flk list
flk list --profile backend
Options
-p, --profile <PROFILE>: Target a specific profile instead of the default
Behavior
- Reads
.flk/profiles/<profile>.nixand displays all packages in thepackages = [ ... ];section - Uses standard profile resolution when
--profileis not specified - Outputs one package per line with a bullet marker
- Shows an error message if no packages are found
Example Output
β’ ripgrep
β’ fd
β’ git
β’ nodejs_20
flk remove
Remove a package from your flake.nix.
flk remove ripgrep
flk remove ripgrep --profile backend
Options
-p, --profile <PROFILE>: target a specific profile instead of the default
Behavior
- Removes from
.flk/profiles/<profile>.nix. - Cleans up pinned entries from
.flk/pins.nixwhen needed. - Errors if the package is not present.
flk search
Search nixpkgs for packages.
flk search ripgrep
flk search python --limit 20
Options
-l, --limit <NUMBER>: number of results (default 10)
Notes
- Uses
nix-versionsunder the hood. - For detailed info, use
flk deep-search <PACKAGE>.
flk show
Pretty-print the current flake configuration for inspection.
flk show
Behavior
- Parses
flake.nixand all profiles in.flk/profiles/ - Displays a structured summary including:
- Flake inputs (name, URL, type)
- Each profile with its packages, environment variables, and custom commands
- Useful for verifying your configuration at a glance without reading raw Nix files
Example Output
Flake Inputs:
nixpkgs: github:NixOS/nixpkgs/nixos-unstable (indirect)
nix-profile-lib: github:AEduardo-dev/nix-profile-lib (github)
Profile: rust
Packages:
β’ ripgrep
β’ cargo-watch
Environment Variables:
RUST_LOG = "debug"
Commands:
dev: cargo watch -x run
test: cargo test --all
Notes
- Shows all profiles, not just the default
- Read-only β does not modify any files
flk switch / refresh
Shell commands for hot-reloading and profile switching within an active development environment. These are provided by the flk hook and are not standalone flk subcommands.
Setup
Add the shell hook to your profile:
# Bash
eval "$(flk hook bash)"
# Zsh
eval "$(flk hook zsh)"
# Fish
flk hook fish | source
refresh
Reload the current environment to pick up configuration changes.
# Make changes
flk add ripgrep
flk env add MY_VAR "hello"
# Apply without leaving the shell
refresh
Behavior
- With direnv: runs
direnv reload - Without direnv: reuses a saved
nix developprofile when it is current - Without direnv: refreshes that saved profile when the environment definition changes
- Reads the active profile from
FLK_FLAKE_REF(fallback:FLK_PROFILE)
switch <profile>
Switch to a different profile and reload the environment.
switch backend
switch frontend
Behavior
- Validates the profile name (alphanumeric,
-,_only) - Sets
FLK_FLAKE_REFandFLK_PROFILEto the new profile reference - Reloads via direnv or
nix developas appropriate, reusing the saved profile cache when possible
Direnv Integration
When direnv is available and .envrc exists, both refresh and switch use direnv reload for a seamless experience. Without direnv, they use exec nix develop, which replaces the current shell process.
Notes
- Supported shells: bash, zsh, fish
- Requires the flk shell hook to be sourced in your shell profile
- See also: flk hook, flk activate
flk update
Update all flake inputs (creates a lockfile backup first).
flk update # apply updates
flk update --show # preview without applying
Options
--show: check for updates without modifyingflake.lock
Behavior
- Backs up
flake.lockto.flk/backupsbefore applying. - Uses
nix flake update; preview restores the original lockfile after diffing.
flk direnv
Integrate flk with direnv.
flk direnv init # create .envrc with use flake
flk direnv attach # add hook to existing .envrc
flk direnv detach # remove hook
Subcommands
init: generate.envrcattach: add hook to existing.envrcdetach: remove hook
flk profile
Manage profiles for your flk project. Profiles let you maintain separate sets of packages, commands, and environment variables within the same project.
Subcommands
flk profile add
Create a new profile from a template.
flk profile add backend
flk profile add frontend --template node
flk profile add ci --template base --force
Options
<NAME>: Profile name (alphanumeric, hyphens, underscores only)-t, --template <TYPE>: Template to use (base,rust,python,node,go,generic). Defaults tobase-f, --force: Overwrite if profile already exists
Behavior
- Creates
.flk/profiles/<NAME>.nixfrom the selected template - Profile names are validated β no path separators or spaces allowed
- Fails if the profile already exists unless
--forceis used
flk profile remove
Remove an existing profile.
flk profile remove frontend
Behavior
- Deletes
.flk/profiles/<NAME>.nix - Cannot remove the profile that is currently set as default β change the default first with
flk profile set-default
flk profile list
List all available profiles.
flk profile list
Behavior
- Lists all
.nixfiles in.flk/profiles/(excludingdefault.nix) - Profiles are sorted alphabetically
flk profile set-default
Set which profile is used when no --profile flag is provided.
flk profile set-default backend
Behavior
- Updates the
defaultShellattribute in.flk/default.nix - The specified profile must already exist
- Affects all commands that use profile resolution (
add,remove,list,activate,export,cmd,env)
Profile Resolution
When you run a command without --profile, flk resolves the profile in this order:
- Explicit
--profile/-pargument FLK_FLAKE_REFenvironment variabledefaultShellin.flk/default.nix- First available profile in
.flk/profiles/
Examples
# Set up a multi-profile project
flk init --template generic
# Create specialized profiles
flk profile add backend --template rust
flk profile add frontend --template node
# Add packages to specific profiles
flk add cargo-watch --profile backend
flk add nodejs_20 --profile frontend
# Switch the default
flk profile set-default backend
# Now commands target "backend" by default
flk add ripgrep # goes to backend profile
flk add eslint --profile frontend # explicit override
See Also
Architecture
This page describes the internal architecture of flk for contributors and curious users.
Overview
flk is a Rust CLI application that generates and modifies Nix flake configurations. It acts as a user-friendly layer on top of Nix, handling the complexity of flake syntax and structure.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β flk CLI β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β Commands β β Parsers β β Generator β β
β β (clap CLI) β β (nom-based) β β (templates) β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Nix Flake Files β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β flake.nix β β .flk/ β β flake.lock β β
β β (root) β β profiles/ β β (inputs) β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Crate Structure
-
Binary crate (
src/main.rs): CLI entrypoint usingclap. Parses arguments and dispatches to command handlers insrc/commands/. -
Library crate (
src/lib.rs): Core functionality exposed as a library:flk::flake- Flake generation, parsing, and interfacesflk::utils- Backup management, visual output, helpers
-
Nix integration (
src/nix/): Wrappers for invokingnixcommands (search, evaluate, develop) and processing output.
Parser Design
Parsers in src/flake/parsers/ use the nom library to read and modify specific sections of Nix files:
- Surgical editing: Instead of parsing entire Nix files, parsers target specific sections (packages, env vars, commands) and track byte positions for precise modifications.
- Round-trip safety: Parse β modify struct β render back to Nix syntax, preserving comments and formatting outside the edited section.
Each parser returns a section struct containing:
- Parsed entries (packages, variables, etc.)
- Byte positions (
section_start,section_end,list_end) - Indentation information for consistent formatting
Template System
Templates in templates/ are embedded at compile time via include_str!:
templates/flake.nix- Root flake templatetemplates/default.nix- Default profile loadertemplates/pins.nix- Version pinning structuretemplates/profiles/*.nix- Language-specific profiles (rust, python, node, go, generic)
The generator (src/flake/generator.rs) selects and instantiates these templates based on project type.
Data Layout
A flk-managed project has this structure:
project/
βββ flake.nix # Root flake (generated by flk init)
βββ flake.lock # Nix lock file (managed by Nix)
βββ .flk/
βββ default.nix # Default profile selector
βββ pins.nix # Version pinning data
βββ overlays.nix # Package overlays
βββ profiles/
β βββ default.nix # Default profile (symlink or import)
β βββ rust.nix # Language-specific profile
β βββ ...
βββ backups/ # Lockfile backups from flk update
Command Flow
- CLI parsing:
clapinsrc/main.rsparses arguments - Command dispatch: Each subcommand calls a
run_*function insrc/commands/ - File operations: Commands use parsers to read/modify
.flk/files - Nix operations: Search, version lookup, and activation run through
nixwrappers - User feedback: Spinners and formatted output via
src/utils/visual.rs
Key Interfaces
FlakeConfig: Complete flake configuration with profiles, packages, env varsProfile: Single profile with packages, commands, environment variablesPackage: Package entry with name and optional version pinSourcesSection/OverlaysSection: Version pinning data structures
API Documentation
The flk library exposes Rust APIs for programmatic access to flake generation and parsing.
Generating Documentation
Build the API documentation locally:
cargo doc --no-deps --open
Or with all features and dependencies:
cargo doc --all-features --open
Module Overview
flk::flake
Core flake functionality:
-
flk::flake::generator- Template loading and flake generationgenerate_flake(project_type)- Generate profile content for a project typegenerate_helper_module()- Generate the.flk/default.nixloadergenerate_pins()- Generate empty pins file
-
flk::flake::parsers- Nix file parsing and modificationpackages- Parse/modifypackages = [ ... ];sectionsenv- Parse/modifyenvVars = { ... };sectionscommands- Parse/modify shell hook commandsoverlays- Parse/modifypins.nixfor version pinningflake- Parse top-level flake structureutils- Profile resolution and parsing helpers
-
flk::flake::interfaces- Data structuresFlakeConfig- Complete flake configurationProfile- Single profile with packages, commands, env varsPackage- Package entry with optional versionEnvVar- Environment variable key-value pair
-
flk::flake::nix_render- Safe Nix syntax renderingnix_string(s)- Escape string for Nix double-quoted stringsnix_attr_key(s)- Format attribute key (quote if needed)
flk::utils
Utility functions:
flk::utils::backup- Lockfile backup managementflk::utils::visual- Spinner and progress display
Example Usage
#![allow(unused)]
fn main() {
use flk::flake::generator::generate_flake;
use flk::flake::parsers::packages::parse_packages_section;
// Generate a Rust profile template
let profile_content = generate_flake("rust")?;
// Parse packages from an existing profile
let content = std::fs::read_to_string(".flk/profiles/rust.nix")?;
let section = parse_packages_section(&content)?;
// Add a package (returns new content directly)
let new_content = section.add_package(&content, "ripgrep", None);
std::fs::write(".flk/profiles/rust.nix", new_content)?;
}
Contributing to the API
When contributing:
- Document all public items with
///doc comments - Include
# Arguments,# Returns, and# Errorssections where applicable - Add examples in doc comments for non-obvious behavior
- Run
cargo doc --no-depsbefore submitting to check for warnings - Keep internal/unstable functions prefixed with underscore (
_parse_*)
Troubleshooting
This page covers common issues and their solutions.
Nix Not Found
Symptom: command not found: nix or flk commands fail with Nix errors.
Solution:
- Ensure Nix is installed:
curl -L https://nixos.org/nix/install | sh - Verify installation:
nix --version - Enable flakes in
~/.config/nix/nix.conf:experimental-features = nix-command flakes - Restart your shell or run
source ~/.bashrc
Search/Version Lookup Errors
Symptom: flk search or flk add --version fails with network or evaluation errors.
Solution:
- These commands use
nix run github:vic/nix-versionswhich requires network access - Check your internet connection
- Try running directly:
nix run github:vic/nix-versions -- -p ripgrep - If behind a proxy, ensure Nix proxy settings are configured
Lock File Missing or Corrupted
Symptom: error: getting status of flake.lock: No such file or directory
Solution:
# Generate a new lock file
nix flake lock
# Or reinitialize the project
flk init --force
Shell Hook Not Working
Symptom: switch and refresh commands not available after activating.
Solution:
- Ensure the hook is in your shell profile:
# For bash (~/.bashrc) eval "$(flk hook bash)" # For zsh (~/.zshrc) eval "$(flk hook zsh)" # For fish (~/.config/fish/config.fish) flk hook fish | source - Restart your terminal or source your profile
- Verify with
type switch- it should show a function definition
Direnv Not Loading Environment
Symptom: Environment doesnβt activate when entering project directory.
Solution:
- Initialize direnv integration:
flk direnv init - Allow the
.envrcfile:direnv allow - Ensure direnv hook is in your shell profile
- Check
.envrcexists and containsuse flake
Package Not Found
Symptom: flk add <package> fails with βpackage not foundβ.
Solution:
- Search for the correct package name:
flk search <term> - For deep search with versions:
flk deep-search <package> - Package names in Nix may differ from common names (e.g.,
ripgrepnotrg)
Profile Errors
Symptom: βProfile not foundβ or profile-related errors.
Solution:
- List available profiles:
flk list profiles - Check
.flk/profiles/directory exists - Ensure profile names contain only alphanumeric characters, dashes, and underscores
Activation Fails
Symptom: flk activate or nix develop fails with evaluation errors.
Solution:
- Check for syntax errors in
.flk/profiles/*.nixfiles - Validate the flake:
nix flake check - Try updating inputs:
flk update - Check the error message for specific package or syntax issues
Container Export Issues
Symptom: flk export --format docker fails.
Solution:
- Ensure Docker/Podman is installed and running
- Check you have permissions to run container commands
- For Docker:
docker infoshould succeed - For Podman:
podman infoshould succeed
FAQ
General
What is flk?
flk is a CLI tool that simplifies working with Nix flake development environments. It provides commands for managing packages, environment variables, and custom commands without manually editing Nix files.
Does flk work without Nix installed?
No, Nix with flakes enabled is required. However, you can export your environment to Docker/Podman containers using flk export --format docker for systems without Nix.
What Nix version do I need?
Any recent Nix version (2.4+) with experimental features nix-command and flakes enabled.
Environment Management
How do I enable auto-switching between projects?
Add the hook to your shell profile:
# Bash
eval "$(flk hook bash)"
# Zsh
eval "$(flk hook zsh)"
# Fish
flk hook fish | source
Then use switch to reload after changes and refresh to re-enter the environment.
How do I pin a package to a specific version?
Use the --version flag:
flk add ripgrep --version 14.1.0
This stores version information in .flk/pins.nix and locks the nixpkgs commit that contains that version.
Can I have multiple profiles in one project?
Yes! Profiles are stored in .flk/profiles/. You can create additional profiles and switch between them. The default profile is set in .flk/default.nix.
How do I see whatβs currently installed?
flk list # List packages
flk command list # List custom commands
flk env list # List environment variables
flk show # Show full flake configuration
Updates and Lock Files
Can I preview updates before applying?
Yes, use flk update --show which shows the diff and then restores the original lockfile.
How do I restore a previous lockfile?
Backups are stored in .flk/backups/. Restore with:
flk lock restore <backup-name>
What happens when I run flk update?
It creates a backup of your current lockfile, runs nix flake update, and shows you what changed.
Integration
Can I use flk with direnv?
Yes! Initialize with flk direnv init to create a .envrc file, then run direnv allow. Your environment will automatically load when entering the project directory.
Does flk support VS Code / other editors?
flk works with any editor. For VS Code with direnv, install the direnv extension and initialize flk direnv integration. The environment will be available in integrated terminals.
Can I export my environment to a container?
Yes:
flk export --format docker # Creates a Docker image
flk export --format podman # Creates a Podman image
flk export --format json # Exports config as JSON
Troubleshooting
Why canβt flk find my package?
Package names in Nix may differ from common names. Use flk search <term> to find the correct name, or flk deep-search <package> for detailed info including available versions.
Why isnβt my shell hook working?
Ensure youβve added the hook to your shell profile and restarted your terminal. The switch and refresh commands are only available inside an activated flk environment.
Contributing
Contributing to CONTRIBUTING.md
First off, thanks for taking the time to contribute! β€οΈ
All types of contributions are encouraged and valued. See the Table of Contents for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. π
And if you like the project, but just donβt have time to contribute, thatβs fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
- Star the project
- Tweet about it
- Refer this project in your projectβs readme
- Mention the project at local meetups and tell your friends/colleagues
Table of Contents
- Code of Conduct
- I Have a Question
- I Want To Contribute
- Reporting Bugs
- Suggesting Enhancements
- Your First Code Contribution
- Improving The Documentation
- Styleguides
- Commit Messages
- Join The Project Team
Code of Conduct
This project and everyone participating in it is governed by the CONTRIBUTING.md Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to <>.
I Have a Question
If you want to ask a question, we assume that you have read the available Documentation.
Before you ask a question, it is best to search for existing Issues that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first.
If you then still feel the need to ask a question and need clarification, we recommend the following:
- Open an Issue.
- Provide as much context as you can about what youβre running into.
- Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant.
We will then take care of the issue as soon as possible.
I Want To Contribute
Legal Notice
When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
Reporting Bugs
Before Submitting a Bug Report
A good bug report shouldnβt leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
- Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the documentation. If you are looking for support, you might want to check this section).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the bug tracker.
- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
- Collect information about the bug:
- Stack trace (Traceback)
- OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
- Possibly your input and the output
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
How Do I Submit a Good Bug Report?
You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to <>.
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
- Open an Issue. (Since we canβt be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
- Explain the behavior you would expect and the actual behavior.
- Please provide as much context as possible and describe the reproduction steps that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
- Provide the information you collected in the previous section.
Once itβs filed:
- The project team will label the issue accordingly.
- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as
needs-repro. Bugs with theneeds-reprotag will not be addressed until they are reproduced. - If the team is able to reproduce the issue, it will be marked
needs-fix, as well as possibly other tags (such ascritical), and the issue will be left to be implemented by someone.
Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for CONTRIBUTING.md, including completely new features and minor improvements to existing functionality. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.
Before Submitting an Enhancement
- Make sure that you are using the latest version.
- Read the documentation carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a search to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. Itβs up to you to make a strong case to convince the projectβs developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If youβre just targeting a minority of users, consider writing an add-on/plugin library.
How Do I Submit a Good Enhancement Suggestion?
Enhancement suggestions are tracked as GitHub issues.
- Use a clear and descriptive title for the issue to identify the suggestion.
- Provide a step-by-step description of the suggested enhancement in as many details as possible.
- Describe the current behavior and explain which behavior you expected to see instead and why. At this point you can also tell which alternatives do not work for you.
- You may want to include screenshots and animated GIFs which help you demonstrate the steps or point out the part which the suggestion is related to. You can use this tool to record GIFs on macOS and Windows, and this tool or this tool on Linux.
- Explain why this enhancement would be useful to most CONTRIBUTING.md users. You may also want to point out the other projects that solved it better and which could serve as inspiration.
Commit Messages
All commit messages in this repo shall follow the Conventional commit guidelines
Attribution
This guide is based on the contributing.md. Make your own!
Code of Conduct
Contributor Covenant Code of Conduct
Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
Our Standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing othersβ private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at development@pixlracks.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the projectβs leadership.
Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
Development Setup
This guide helps you set up a development environment for contributing to flk.
Requirements
- Nix with flakes enabled (Lix or Determinate installer recommended)
- Rust toolchain (1.70+ recommended)
- Git for version control
Quick Start with Nix
The easiest way to get started is using flkβs own flake:
git clone https://github.com/AEduardo-dev/flk.git
cd flk
nix develop
This provides all required tools including Rust, cargo, and testing dependencies.
Building from Source
# Clone the repository
git clone https://github.com/AEduardo-dev/flk.git
cd flk
# Debug build (faster compilation)
cargo build
# Release build (optimized)
cargo build --release
# The binary is at target/release/flk
Running Tests
# Run all tests
cargo test
# Run a specific test
cargo test test_add_package
# Run tests with output
cargo test -- --nocapture
Linting and Formatting
# Check formatting
cargo fmt --all -- --check
# Apply formatting
cargo fmt --all
# Run clippy lints
cargo clippy -- -D warnings
Running the CLI Locally
During development, use cargo run:
# Run flk commands
cargo run -- init --template rust
cargo run -- add ripgrep
cargo run -- list packages
# With release optimizations (faster execution)
cargo run --release -- search git
For shell integration while iterating:
# Build and install locally
cargo install --path .
# Or add an alias
alias flk="cargo run --release --"
Building Documentation
API Documentation (cargo doc)
# Generate and open API docs
cargo doc --no-deps --open
# Check for documentation warnings
cargo doc --no-deps 2>&1 | grep warning
User Guide (mdbook)
# Install mdbook if needed
cargo install mdbook
# Serve the book locally (auto-reloads)
cd flk-book
mdbook serve
# Open http://localhost:3000
# Build static HTML
mdbook build
# Output in flk-book/book/
Combined Documentation
The Nix flake can build both:
nix build .#docs
# Output in result/
Project Structure
flk/
βββ src/
β βββ main.rs # CLI entrypoint
β βββ lib.rs # Library exports
β βββ commands/ # CLI command handlers
β βββ flake/ # Flake generation and parsing
β β βββ generator.rs # Template instantiation
β β βββ parsers/ # Nix file parsers
β β βββ interfaces/ # Data structures
β βββ nix/ # Nix command wrappers
β βββ utils/ # Helpers (backup, visual)
βββ templates/ # Nix templates (embedded at compile time)
βββ tests/ # Integration tests
βββ flk-book/ # mdbook documentation
βββ flake.nix # Nix flake for development
Testing Changes
Before submitting a PR:
# Run the full test suite
cargo test
# Check formatting and lints
cargo fmt --all -- --check
cargo clippy -- -D warnings
# Build documentation without warnings
cargo doc --no-deps
# Test the binary manually
cargo run -- init --template rust
cargo run -- add ripgrep
cargo run -- list packages
Debugging
For verbose output during development:
# Enable Rust backtraces
RUST_BACKTRACE=1 cargo run -- add ripgrep
# Debug Nix commands
RUST_LOG=debug cargo run -- search git