▸ Agent Skills
1 min read

Extending devenv

Projects can encode their best practices by creating custom modules with opinionated defaults in a central repository:

devenv.nix

{ lib, config, pkgs, ... }: {
  options.myproject = {
    languages.rust.enable = lib.mkEnableOption "Rust development stack";
    services.database.enable = lib.mkEnableOption "Database services";
  };


  config = {
    packages = lib.mkIf config.myproject.languages.rust.enable [
      pkgs.cargo-watch
    ];


    languages.rust = lib.mkIf config.myproject.languages.rust.enable {
      enable = true;
      channel = "nightly";
    };


    services.postgres = lib.mkIf config.myproject.services.database.enable {
      enable = true;
      initialScript = "CREATE DATABASE myapp;";
    };
  };
}

Once you have your best practices module defined, you can start using it in new projects:

devenv.yaml

inputs:
  myproject:
    url: github:myorg/devenv-myproject
    flake: false
imports:
- myproject

This automatically includes your centrally managed module. Since options default to false, you’ll need to enable them per project.

Profiles

You can enable common defaults globally and use profiles to activate additional components on demand.

Module Replacement

You can replace existing devenv modules using the disabledModules mechanism. This allows you to override built-in behavior or provide custom implementations.

{ pkgs, lib, config, ... }: {
  # Disable the original module
  disabledModules = [ "languages/rust.nix" ];


  options.languages.rust = {
    enable = lib.mkOption {
      type = lib.types.bool;
      default = false;
    };
  };


  config = lib.mkIf config.languages.rust.enable {
    packages = [ pkgs.rustc ];
  };
}

Last updated Oct 11, 2026