Devenv Ecosystem

Installation
SKILL.md

<devenv_20> devenv 2.0 released March 2026 — "A Fresh Interface to Nix" Every devenv command now shows a live terminal interface with structured progress: evaluation status, derivation build/download counts, task execution hierarchy, and auto-expanding error details. Background rebuilds while shell stays interactive. Save a file, devenv rebuilds in background, status line shows progress, Ctrl+Alt+R applies new environment. Errors appear in status line without disruption. Replaced multiple nix CLI invocations with C FFI backend (nix-bindings-rust). Calls Nix evaluator and store directly through C API instead of spawning separate processes. Each evaluated attribute cached individually with tracked file/env dependencies. Only changed attributes re-evaluated. Reference outputs from another devenv project (third most upvoted feature request). <breaking_changes> Native process manager is now the default. Set process.manager.implementation = "process-compose" for old behavior. devenv 0.x is deprecated. Support will be dropped in devenv 3. </breaking_changes> </devenv_20>

<pattern name="version_specification">
  <description>Specify language version (available for some languages)</description>
  <example>
    languages.python.version = "3.13";
    languages.ruby.version = "3.2.1";
    languages.rust.channel = "stable";
  </example>
</pattern>

<pattern name="package_override">
  <description>Use custom package instead of default</description>
  <example>
    languages.go.package = pkgs.go_1_26;
    languages.java.jdk.package = pkgs.jdk17;
  </example>
</pattern>

<pattern name="version_file">
  <description>Read version from file (Ruby, Python)</description>
  <example>
    languages.ruby.versionFile = "./.ruby-version";
    languages.python.versionFile = "./.python-version";
  </example>
</pattern>

<pattern name="dev_tooling">
  <description>Configure LSP, debugger, linter, formatter (devenv 1.8+, enhanced in 2.0)</description>
  <example>
    languages.rust.dev = {
      lsp.enable = true;
      debugger.enable = true;
      linter.enable = true;
      formatter.enable = true;
    };
  </example>
</pattern>

</common_patterns>

<language name="rust">
  <example>
    languages.rust = {
      enable = true;
      channel = "stable"; # or "nightly", "beta"
      edition = "2024"; # Rust edition (2015, 2018, 2021, 2024)
      components = [ "rustc" "cargo" "clippy" "rustfmt" "rust-analyzer" ];
      targets = [ "wasm32-unknown-unknown" ];
    };
  </example>
  <output_pattern>
    outputs.rust-app = config.languages.rust.import ./rust-app {};
  </output_pattern>
</language>

<language name="go">
  <example>
    languages.go = {
      enable = true;
      package = pkgs.go_1_26;
    };
  </example>
  <output_pattern>
    outputs.go-app = config.languages.go.import ./go-app {};
  </output_pattern>
</language>

<language name="c_cpp">
  <example>
    languages.c.enable = true;
    languages.cplusplus.enable = true;
  </example>
</language>

<language name="zig">
  <example>
    languages.zig = {
      enable = true;
      package = pkgs.zig;
      zls.package = pkgs.zls;
    };
  </example>
</language>

<language name="nim">
  <example>
    languages.nim = {
      enable = true;
      package = pkgs.nim;
    };
  </example>
</language>

<language name="odin">
  <example>
    languages.odin = {
      enable = true;
      package = pkgs.odin;
    };
  </example>
</language>

<language name="v">
  <example>
    languages.v = {
      enable = true;
      package = pkgs.vlang;
    };
  </example>
</language>
<language name="python">
  <example>
    languages.python = {
      enable = true;
      version = "3.13";
      uv.enable = true;
      uv.sync.enable = true;
    };
  </example>
  <poetry_example>
    languages.python = {
      enable = true;
      poetry = {
        enable = true;
        install.enable = true;
        install.allExtras = true;
      };
    };
  </poetry_example>
  <output_pattern>
    outputs.python-app = config.languages.python.import ./python-app {};
  </output_pattern>
</language>

<language name="ruby">
  <example>
    languages.ruby = {
      enable = true;
      version = "3.3.0";
      bundler.enable = true;
    };
  </example>
</language>

<language name="php">
  <example>
    languages.php = {
      enable = true;
      package = pkgs.php85;
      extensions = [ "opcache" "redis" ];
    };
  </example>
</language>

<language name="perl">
  <example>
    languages.perl.enable = true;
  </example>
</language>

<language name="lua">
  <example>
    languages.lua.enable = true;
  </example>
</language>
<language name="java">
  <example>
    languages.java = {
      enable = true;
      jdk.package = pkgs.jdk21;
      maven.enable = true;
      gradle.enable = true;
    };
  </example>
</language>

<language name="kotlin">
  <example>
    languages.kotlin.enable = true;
  </example>
</language>

<language name="scala">
  <example>
    languages.scala = {
      enable = true;
      package = pkgs.scala_3;
      sbt.enable = true;
    };
  </example>
</language>

<language name="clojure">
  <example>
    languages.clojure.enable = true;
  </example>
</language>
<language name="haskell">
  <example>
    languages.haskell = {
      enable = true;
      languageServer = pkgs.haskell-language-server;
      stack = {
        enable = true;
        args = [ "--no-nix" "--system-ghc" "--no-install-ghc" ];
      };
    };
  </example>
</language>

<language name="ocaml">
  <example>
    languages.ocaml = {
      enable = true;
      packages = pkgs.ocaml-ng.ocamlPackages_5_1;
    };
  </example>
</language>

<language name="elixir">
  <example>
    languages.elixir.enable = true;
  </example>
</language>

<language name="erlang">
  <example>
    languages.erlang.enable = true;
  </example>
</language>

<language name="elm">
  <example>
    languages.elm.enable = true;
  </example>
</language>

<language name="purescript">
  <example>
    languages.purescript = {
      enable = true;
      package = pkgs.purescript;
    };
  </example>
</language>

<language name="gleam">
  <example>
    languages.gleam.enable = true;
  </example>
</language>

<language name="idris">
  <example>
    languages.idris = {
      enable = true;
      package = pkgs.idris2;
    };
  </example>
</language>

<language name="lean4">
  <example>
    languages.lean4 = {
      enable = true;
      package = pkgs.lean4;
    };
  </example>
</language>

<language name="unison">
  <example>
    languages.unison.enable = true;
  </example>
</language>
<language name="javascript">
  <example>
    languages.javascript = {
      enable = true;
      package = pkgs.nodejs_24;
      npm.enable = true;
      npm.install.enable = true;
    };
  </example>
  <pnpm_example>
    languages.javascript = {
      enable = true;
      pnpm.enable = true;
      pnpm.install.enable = true;
    };
  </pnpm_example>
  <bun_example>
    languages.javascript = {
      enable = true;
      bun.enable = true;
      bun.install.enable = true;
    };
  </bun_example>
  <yarn_example>
    languages.javascript = {
      enable = true;
      yarn.enable = true;
      yarn.install.enable = true;
    };
  </yarn_example>
  <corepack_example>
    languages.javascript = {
      enable = true;
      corepack.enable = true;
    };
  </corepack_example>
</language>

<language name="typescript">
  <example>
    languages.typescript.enable = true;
  </example>
</language>

<language name="deno">
  <example>
    languages.deno.enable = true;
  </example>
</language>
<language name="nix">
  <example>
    languages.nix = {
      enable = true;
      lsp.package = pkgs.nil; # or pkgs.nixd
    };
  </example>
</language>

<language name="swift">
  <example>
    languages.swift.enable = true;
  </example>
</language>

<language name="crystal">
  <example>
    languages.crystal.enable = true;
  </example>
</language>

<language name="dart">
  <example>
    languages.dart.enable = true;
  </example>
</language>

<language name="r">
  <example>
    languages.r.enable = true;
  </example>
</language>

<language name="julia">
  <example>
    languages.julia.enable = true;
  </example>
</language>

<language name="fortran">
  <example>
    languages.fortran.enable = true;
  </example>
</language>

<language name="pascal">
  <example>
    languages.pascal = {
      enable = true;
      lazarus.enable = true;
    };
  </example>
</language>

<language name="raku">
  <example>
    languages.raku.enable = true;
  </example>
</language>

<language name="racket">
  <example>
    languages.racket.enable = true;
  </example>
</language>

<language name="standardml">
  <example>
    languages.standardml.enable = true;
  </example>
</language>

<language name="solidity">
  <example>
    languages.solidity = {
      enable = true;
      package = pkgs.solc;
    };
  </example>
</language>

<language name="terraform">
  <example>
    languages.terraform.enable = true;
  </example>
</language>

<language name="opentofu">
  <example>
    languages.opentofu.enable = true;
  </example>
</language>

<language name="ansible">
  <example>
    languages.ansible = {
      enable = true;
      package = pkgs.ansible;
    };
  </example>
</language>

<language name="helm">
  <example>
    languages.helm = {
      enable = true;
      languageServer.enable = true;
    };
  </example>
</language>

<language name="cue">
  <example>
    languages.cue = {
      enable = true;
      package = pkgs.cue;
    };
  </example>
</language>

<language name="jsonnet">
  <example>
    languages.jsonnet.enable = true;
  </example>
</language>

<language name="typst">
  <example>
    languages.typst = {
      enable = true;
      fontPaths = [ "${pkgs.roboto}/share/fonts/truetype" ];
    };
  </example>
</language>

<language name="texlive">
  <example>
    languages.texlive.enable = true;
  </example>
</language>

<language name="gawk">
  <example>
    languages.gawk.enable = true;
  </example>
</language>

<language name="shell">
  <example>
    languages.shell.enable = true;
  </example>
</language>

<language name="robotframework">
  <example>
    languages.robotframework.enable = true;
  </example>
</language>

<language name="vala">
  <example>
    languages.vala.enable = true;
  </example>
</language>

<language name="dotnet">
  <example>
    languages.dotnet.enable = true;
  </example>
</language>

<decision_tree name="language_selection"> What type of project are you building? Use Rust, Go, Zig, or C/C++ Use JavaScript/TypeScript, Python, Ruby, Go, or Rust Use JavaScript/TypeScript with npm/pnpm/bun Use Python with uv or poetry Use Haskell, OCaml, Elixir, or Gleam Use Java, Kotlin, or Scala with gradle/maven/sbt Use Terraform, OpenTofu, Ansible, or Nix </decision_tree>

<decision_tree name="package_manager_selection"> Which JavaScript/TypeScript package manager to use? Match existing lock file (package-lock.json=npm, pnpm-lock.yaml=pnpm, yarn.lock=yarn, bun.lockb=bun) Use pnpm or bun Use npm (most widely supported) Use pnpm or yarn with workspaces Use corepack.enable with packageManager in package.json </decision_tree>

<decision_tree name="devenv_vs_flakes"> Should you use devenv or pure Nix flakes? Use devenv - services.* is simpler Use devenv - git-hooks integration built-in Use devenv - native process manager (2.0 default) or process-compose Use devenv - languages.* handles versions Use flakes - devenv adds overhead Use flakes - devenv is for dev environments </decision_tree>

<service name="mysql">
  <example>
    services.mysql = {
      enable = true;
      package = pkgs.mysql80;
      initialDatabases = [{ name = "myapp"; }];
    };
  </example>
</service>

<service name="mongodb">
  <example>
    services.mongodb = {
      enable = true;
    };
  </example>
</service>

<service name="redis">
  <example>
    services.redis = {
      enable = true;
      port = 6379;
    };
  </example>
</service>

<service name="memcached">
  <example>
    services.memcached = {
      enable = true;
    };
  </example>
</service>

<service name="minio">
  <example>
    services.minio = {
      enable = true;
    };
  </example>
</service>

<service name="elasticsearch">
  <example>
    services.elasticsearch = {
      enable = true;
    };
  </example>
</service>

<service name="opensearch">
  <example>
    services.opensearch = {
      enable = true;
    };
  </example>
</service>
<service name="kafka">
  <example>
    services.kafka = {
      enable = true;
    };
  </example>
</service>
<service name="caddy">
  <example>
    services.caddy = {
      enable = true;
    };
  </example>
</service>

<service name="varnish">
  <example>
    services.varnish = {
      enable = true;
      vcl = ''
        vcl 4.0;
        backend default {
          .host = "127.0.0.1";
          .port = "8080";
        }
      '';
    };
  </example>
</service>
<service name="mailpit">
  <example>
    services.mailpit.enable = true;
  </example>
</service>

<decision_tree name="service_selection"> What type of storage/service do you need? Use postgres or mysql Use mongodb Use redis or memcached Use minio Use elasticsearch or opensearch Use rabbitmq or kafka Use nginx or caddy Use mailhog or mailpit </decision_tree>

    # Linters
    eslint.enable = true;
    clippy.enable = true;
    shellcheck.enable = true;

    # Security
    detect-private-keys.enable = true;
    check-merge-conflicts.enable = true;

    # Git hygiene
    check-case-conflicts.enable = true;
    editorconfig-checker.enable = true;
  };
</example>

<custom_hook>
  git-hooks.hooks.my-custom-hook = {
    enable = true;
    name = "my-custom-hook";
    entry = "${pkgs.bash}/bin/bash -c 'echo Running custom hook'";
    files = "\\.nix$";
    pass_filenames = true;
  };
</custom_hook>

<common_hooks>
  <hook name="nixfmt-rfc-style">Nix code formatter (RFC style)</hook>
  <hook name="prettier">JavaScript/TypeScript/CSS/HTML formatter</hook>
  <hook name="black">Python code formatter</hook>
  <hook name="rustfmt">Rust code formatter</hook>
  <hook name="ormolu">Haskell code formatter</hook>
  <hook name="gofmt">Go code formatter</hook>
  <hook name="eslint">JavaScript/TypeScript linter</hook>
  <hook name="clippy">Rust linter</hook>
  <hook name="shellcheck">Shell script linter</hook>
  <hook name="yamllint">YAML linter</hook>
  <hook name="actionlint">GitHub Actions linter</hook>
  <hook name="hadolint">Dockerfile linter</hook>
  <hook name="markdownlint">Markdown linter</hook>
  <hook name="detect-private-keys">Prevent committing private keys</hook>
  <hook name="check-merge-conflicts">Prevent committing merge conflicts</hook>
  <hook name="check-case-conflicts">Detect case conflicts in filenames</hook>
  <hook name="editorconfig-checker">Check editorconfig compliance</hook>
  <hook name="treefmt">Universal formatter via treefmt</hook>
</common_hooks>
    # With description
    deploy = {
      exec = "kubectl apply -f k8s/";
      description = "Deploy to Kubernetes";
    };

    # Using packages
    migrate = {
      exec = "${pkgs.dbmate}/bin/dbmate up";
      description = "Run database migrations";
    };
  };
</example>
<process_compose_example>
  # To use process-compose (no longer the default in 2.0):
  process.manager.implementation = "process-compose";

  processes = {
    web = {
      exec = "npm run dev";
      process-compose = {
        depends_on.api.condition = "process_healthy";
        readiness_probe = {
          http_get = {
            host = "localhost";
            port = 3000;
          };
        };
      };
    };
    api = {
      exec = "cargo run";
      process-compose = {
        readiness_probe = {
          http_get = {
            host = "localhost";
            port = 8080;
            path = "/health";
          };
        };
      };
    };
  };
</process_compose_example>
<dotenv_example>
  dotenv.enable = true;
  dotenv.filename = ".env.local";
</dotenv_example>
    outputs = {
      rust-app = config.languages.rust.import ./rust-app {};
      python-app = config.languages.python.import ./python-app {};
      go-app = config.languages.go.import ./go-app {};
    };
  }
</example>
    devenv.shells.ci = {
      languages.python.enable = true;
      packages = [ pkgs.git pkgs.buildkit ];
      env.CI = "true";
    };

    devenv.shells.docs = {
      packages = [ pkgs.mdbook ];
      scripts.build-docs.exec = "mdbook build";
    };
  }
</example>
    profiles = {
      "python-3.12".config = {
        languages.python.version = "3.12";
      };
      "python-3.11".config = {
        languages.python.version = "3.11";
      };
    };
  }
</example>
<usage>devenv shell --profile python-3.12</usage>
    profiles = {
      backend.module = {
        languages.rust.enable = true;
        services.postgres.enable = true;
        services.redis.enable = true;
      };

      frontend.module = {
        languages.javascript.enable = true;
        languages.typescript.enable = true;
      };

      fullstack.extends = [ "backend" "frontend" ];
    };
  }
</example>
      user."developer".module = {
        packages = [ pkgs.gh ];
      };
    };
  }
</example>
    languages = {
      javascript = {
        enable = true;
        package = pkgs.nodejs_24;
        pnpm.enable = true;
      };
      typescript.enable = true;
    };

    services = {
      postgres = {
        enable = true;
        initialDatabases = [{ name = "app_dev"; }];
      };
      redis.enable = true;
    };

    processes = {
      frontend.exec = "pnpm dev";
      api.exec = "pnpm api:dev";
    };

    scripts = {
      db-migrate.exec = "pnpm db:migrate";
      db-seed.exec = "pnpm db:seed";
    };

    git-hooks.hooks = {
      prettier.enable = true;
      eslint.enable = true;
    };
  }
</example>
    packages = [ pkgs.nixfmt-rfc-style ];

    git-hooks.hooks = {
      nixfmt-rfc-style.enable = true;
      editorconfig-checker.enable = true;
    };
  }
</example>

<decision_tree name="configuration_approach"> What type of project are you setting up? Use minimal_config pattern Use full_stack pattern Use nix_project pattern Use profiles with team modules </decision_tree>

<context7_integration> <library_id>/cachix/devenv</library_id> <trust_score>9.7</trust_score> 1354 <usage_patterns> Fetch specific language configuration options Fetch service configuration details Fetch available pre-commit hooks Fetch packaging patterns Fetch profile configuration (1.9+) Fetch devenv 2.0 features and migration guide </usage_patterns> </context7_integration>

<best_practices> Use languages.*.enable instead of adding language packages directly to packages list

<anti_patterns> Hardcoding specific package versions instead of using version options Use languages..version or languages..package with nixpkgs packages

<error_escalation> Missing optional configuration attribute Note in output, suggest improvement Service configuration incomplete or enterShell too slow Document issue, suggest refactoring approach Configuration fails to evaluate or services fail to start Debug with devenv info, present options to user Security issue in configuration (secrets exposed, unsafe permissions) Block operation, require explicit user acknowledgment </error_escalation>

<related_skills> Nix language fundamentals, flakes, Home Manager (devenv uses Nix) Symbol operations for navigating devenv configurations Fetch latest devenv documentation </related_skills>

Related skills
Installs
GitHub Stars
67
First Seen