From 9e6791569eb49c2b0ff3d97f2a97e6b86f3c59d4 Mon Sep 17 00:00:00 2001 From: 0xrsydn Date: Thu, 9 Oct 2025 11:54:05 +0700 Subject: [PATCH] feat: refactor devshell as modular standalone path lol --- devshells/README.md | 148 ++++++++++++++++++++++++++++++++++++++ devshells/default.nix | 9 +++ devshells/go.nix | 13 ++++ devshells/ml-ai.nix | 41 +++++++++++ devshells/python-uv.nix | 12 ++++ devshells/rust.nix | 12 ++++ devshells/web-bun.nix | 19 +++++ devshells/zig-nightly.nix | 13 ++++ flake.nix | 92 ++++-------------------- 9 files changed, 282 insertions(+), 77 deletions(-) create mode 100644 devshells/README.md create mode 100644 devshells/default.nix create mode 100644 devshells/go.nix create mode 100644 devshells/ml-ai.nix create mode 100644 devshells/python-uv.nix create mode 100644 devshells/rust.nix create mode 100644 devshells/web-bun.nix create mode 100644 devshells/zig-nightly.nix diff --git a/devshells/README.md b/devshells/README.md new file mode 100644 index 0000000..4a281e3 --- /dev/null +++ b/devshells/README.md @@ -0,0 +1,148 @@ +# Development Shells + +This directory contains modular Nix devShell configurations for various programming languages and use cases. + +## Available Shells + +### `default` +Basic shell with git and nixfmt for dotfiles development. + +```bash +nix develop +``` + +### `python-uv` +Python development with UV package manager. + +```bash +nix develop .#python-uv +``` + +**Includes:** +- Python 3.12 +- UV (fast Python package manager) +- Ruff (linter/formatter) +- Pyright (type checker) + +### `ml-ai` +Machine Learning and AI development with HuggingFace model management. + +```bash +nix develop .#ml-ai +``` + +**Includes:** +- Python 3.12 with huggingface-hub +- `huggingface-cli` for downloading models +- UV for package management +- Git LFS for large files +- Ruff and Pyright + +**Model cache:** `~/.cache/huggingface` (persistent across projects) + +**Example usage:** +```bash +# Download a TTS model +huggingface-cli download facebook/mms-tts-eng + +# Download a small LLM +huggingface-cli download meta-llama/Llama-3.2-1B + +# Download specific files only +huggingface-cli download openai/whisper-large-v3 --include "*.json" "*.safetensors" + +# Use in your project +uv init my-ml-project +cd my-ml-project +uv add transformers torch +``` + +### `go` +Go development environment. + +```bash +nix develop .#go +``` + +**Includes:** +- Go compiler +- gopls (language server) +- golangci-lint +- delve (debugger) + +### `web-bun` +Modern web development with Bun runtime. + +```bash +nix develop .#web-bun +``` + +**Includes:** +- Bun +- Node.js 20 +- Yarn +- esbuild +- vscode-langservers-extracted + +### `rust` +Rust development environment. + +```bash +nix develop .#rust +``` + +**Includes:** +- Cargo & rustc +- rust-analyzer +- rustfmt +- clippy + +### `zig-nightly` (optional) +Zig nightly development (only available if zig overlay is working). + +```bash +nix develop .#zig-nightly +``` + +## Usage from Any Directory + +You can use these shells from anywhere by referencing your dotfiles: + +```bash +# From any directory +cd ~/my-project +nix develop ~/Development/dotfiles#ml-ai +``` + +## Auto-loading with direnv + +To automatically load a shell when entering a directory: + +```bash +cd ~/my-ml-project +echo "use flake ~/Development/dotfiles#ml-ai" > .envrc +direnv allow +``` + +Now the shell automatically activates when you `cd` into that directory! + +## Adding New Shells + +1. Create a new file in `devshells/` (e.g., `devshells/java.nix`) +2. Follow the pattern: +```nix +{ pkgs, ... }: + +pkgs.mkShell { + name = "java"; + packages = with pkgs; [ jdk maven ]; + shellHook = '' + echo "Java development shell ready" + ''; +} +``` +3. Add it to `flake.nix` imports: +```nix +java = importShell "java"; +``` +4. Test: `nix flake check` diff --git a/devshells/default.nix b/devshells/default.nix new file mode 100644 index 0000000..7659040 --- /dev/null +++ b/devshells/default.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: + +pkgs.mkShell { + name = "default"; + packages = with pkgs; [ git nixfmt-classic ]; + shellHook = '' + echo "Loaded default shell for dotfiles development" + ''; +} diff --git a/devshells/go.nix b/devshells/go.nix new file mode 100644 index 0000000..22e2c28 --- /dev/null +++ b/devshells/go.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: + +pkgs.mkShell { + name = "go"; + packages = with pkgs; [ go gopls golangci-lint delve git ]; + shellHook = '' + mkdir -p "$PWD/.cache/go" "$PWD/.cache/gomod" + export GOPATH="$PWD/.cache/go" + export GOMODCACHE="$PWD/.cache/gomod" + echo "Go toolchain shell ready" + echo "Go: ${pkgs.go.version}" + ''; +} diff --git a/devshells/ml-ai.nix b/devshells/ml-ai.nix new file mode 100644 index 0000000..aef7aa8 --- /dev/null +++ b/devshells/ml-ai.nix @@ -0,0 +1,41 @@ +{ pkgs, python ? pkgs.python312, ... }: + +let + # Create a Python environment with huggingface-cli + pythonWithHF = python.withPackages (ps: [ ps.huggingface-hub ]); +in pkgs.mkShell { + name = "ml-ai"; + packages = with pkgs; [ + pythonWithHF + uv + git-lfs + ruff + pyright + ]; + shellHook = '' + # Set up UV + export UV_PYTHON="${pythonWithHF}/bin/python3" + export UV_LINK_MODE=copy + + # Set up HuggingFace cache (persistent across projects) + export HF_HOME="''${XDG_CACHE_HOME:-$HOME/.cache}/huggingface" + export HF_HUB_CACHE="$HF_HOME/hub" + mkdir -p "$HF_HOME" + + # Optional: Set offline mode (uncomment to use only cached models) + # export HF_HUB_OFFLINE=1 + + echo "ML/AI shell ready" + echo "Python: ${python.version}" + echo "HuggingFace cache: $HF_HOME" + echo "" + echo "Download models with:" + echo " huggingface-cli download " + echo "" + echo "Example TTS:" + echo " huggingface-cli download facebook/mms-tts-eng" + echo "" + echo "Example LLM:" + echo " huggingface-cli download meta-llama/Llama-3.2-1B" + ''; +} diff --git a/devshells/python-uv.nix b/devshells/python-uv.nix new file mode 100644 index 0000000..d8021dd --- /dev/null +++ b/devshells/python-uv.nix @@ -0,0 +1,12 @@ +{ pkgs, python ? pkgs.python312, ... }: + +pkgs.mkShell { + name = "python-uv"; + packages = [ python pkgs.uv pkgs.ruff pkgs.pyright ]; + shellHook = '' + export UV_PYTHON="${python}/bin/python3" + export UV_LINK_MODE=copy + echo "Python (uv) shell ready" + echo "Python: ${python.version}" + ''; +} diff --git a/devshells/rust.nix b/devshells/rust.nix new file mode 100644 index 0000000..c8c015c --- /dev/null +++ b/devshells/rust.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: + +pkgs.mkShell { + name = "rust"; + packages = with pkgs; [ cargo rustc rust-analyzer rustfmt clippy ]; + shellHook = '' + mkdir -p "$PWD/.cache/cargo" + export CARGO_HOME="$PWD/.cache/cargo" + echo "Rust toolchain shell ready" + echo "Rust: ${pkgs.rustc.version}" + ''; +} diff --git a/devshells/web-bun.nix b/devshells/web-bun.nix new file mode 100644 index 0000000..ce9d20f --- /dev/null +++ b/devshells/web-bun.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: + +pkgs.mkShell { + name = "web-bun"; + packages = with pkgs; [ + bun + nodejs_20 + yarn + esbuild + vscode-langservers-extracted + ]; + shellHook = '' + mkdir -p "$PWD/.cache/bun" + export BUN_INSTALL_CACHE="$PWD/.cache/bun" + echo "Bun/Node web shell ready" + echo "Bun: ${pkgs.bun.version}" + echo "Node: ${pkgs.nodejs_20.version}" + ''; +} diff --git a/devshells/zig-nightly.nix b/devshells/zig-nightly.nix new file mode 100644 index 0000000..2d7b5be --- /dev/null +++ b/devshells/zig-nightly.nix @@ -0,0 +1,13 @@ +{ pkgs, lib, zigPackage, ... }: + +lib.optionalAttrs (zigPackage != null) (pkgs.mkShell { + name = "zig-nightly"; + packages = [ zigPackage pkgs.zls pkgs.pkg-config pkgs.cmake pkgs.gdb ]; + shellHook = '' + mkdir -p "$PWD/.cache/zig" + export ZIG_GLOBAL_CACHE_DIR="$PWD/.cache/zig" + echo "Zig shell using ${zigPackage.pname or "zig"} ${ + zigPackage.version or "" + }" + ''; +}) diff --git a/flake.nix b/flake.nix index e33b253..49a22dc 100644 --- a/flake.nix +++ b/flake.nix @@ -86,6 +86,7 @@ else pkgs.python3; + # Zig overlay setup for zig-nightly shell zigPackages = if zigOverlay != null && builtins.hasAttr "packages" zigOverlay then zigOverlay.packages @@ -126,85 +127,22 @@ else false; - zigShell = - lib.optionalAttrs (zigPackage != null && zlsBroken == false) { - zig-nightly = pkgs.mkShell { - name = "zig-nightly"; - packages = - [ zigPackage pkgs.zls pkgs.pkg-config pkgs.cmake pkgs.gdb ]; - shellHook = '' - mkdir -p "$PWD/.cache/zig" - export ZIG_GLOBAL_CACHE_DIR="$PWD/.cache/zig" - echo "Zig shell using ${zigPackage.pname or "zig"} ${ - zigPackage.version or "" - }" - ''; - }; - }; + # Common arguments passed to all devshell imports + shellArgs = { inherit pkgs lib python zigPackage; }; - baseShells = { - default = pkgs.mkShell { - name = "default"; - packages = with pkgs; [ git nixfmt-classic ]; - shellHook = '' - echo "Loaded default shell for ${system}" - ''; - }; + # Import all devshells from devshells/ directory + importShell = name: import (./devshells + "/${name}.nix") shellArgs; - python-uv = pkgs.mkShell { - name = "python-uv"; - packages = [ python pkgs.uv pkgs.ruff pkgs.pyright ]; - shellHook = '' - export UV_PYTHON="${python}/bin/python3" - export UV_LINK_MODE=copy - echo "Python (uv) shell ready" - ''; - }; - - go = pkgs.mkShell { - name = "go"; - packages = with pkgs; [ go gopls golangci-lint delve git ]; - shellHook = '' - mkdir -p "$PWD/.cache/go" "$PWD/.cache/gomod" - export GOPATH="$PWD/.cache/go" - export GOMODCACHE="$PWD/.cache/gomod" - echo "Go toolchain shell ready" - ''; - }; - - web-bun = pkgs.mkShell { - name = "web-bun"; - packages = with pkgs; [ - bun - nodejs_20 - yarn - esbuild - vscode-langservers-extracted - ]; - shellHook = '' - mkdir -p "$PWD/.cache/bun" - export BUN_INSTALL_CACHE="$PWD/.cache/bun" - echo "Bun/Node web shell ready" - ''; - }; - - rust = pkgs.mkShell { - name = "rust"; - packages = with pkgs; [ - cargo - rustc - rust-analyzer - rustfmt - clippy - ]; - shellHook = '' - mkdir -p "$PWD/.cache/cargo" - export CARGO_HOME="$PWD/.cache/cargo" - echo "Rust toolchain shell ready" - ''; - }; - }; - in baseShells // zigShell); + in { + default = importShell "default"; + python-uv = importShell "python-uv"; + ml-ai = importShell "ml-ai"; + go = importShell "go"; + web-bun = importShell "web-bun"; + rust = importShell "rust"; + } // lib.optionalAttrs (zigPackage != null && zlsBroken == false) { + zig-nightly = importShell "zig-nightly"; + }); formatter = forEachSystem (system: (mkPkgs system).nixfmt-classic);