# 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 using `clap`. Parses arguments and dispatches to command handlers in `src/commands/`.

- **Library crate (`src/lib.rs`)**: Core functionality exposed as a library:
  - `flk::flake` - Flake generation, parsing, and interfaces
  - `flk::utils` - Backup management, visual output, helpers

- **Nix integration (`src/nix/`)**: Wrappers for invoking `nix` commands (search, evaluate, develop) and processing output.

## Parser Design

Parsers in `src/flake/parsers/` use the [nom](https://docs.rs/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 template
- `templates/default.nix` - Default profile loader
- `templates/pins.nix` - Version pinning structure
- `templates/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

1. **CLI parsing**: `clap` in `src/main.rs` parses arguments
2. **Command dispatch**: Each subcommand calls a `run_*` function in `src/commands/`
3. **File operations**: Commands use parsers to read/modify `.flk/` files
4. **Nix operations**: Search, version lookup, and activation run through `nix` wrappers
5. **User feedback**: Spinners and formatted output via `src/utils/visual.rs`

## Key Interfaces

- **`FlakeConfig`**: Complete flake configuration with profiles, packages, env vars
- **`Profile`**: Single profile with packages, commands, environment variables
- **`Package`**: Package entry with name and optional version pin
- **`SourcesSection` / `OverlaysSection`**: Version pinning data structures
