Commit be264ba

HPCesia <me@hpcesia.com>
2025-09-30 17:51:40
refactor: migrate development environment
1 parent 5a66b77
home/base/tui/editors/helix/languages/astro.nix
@@ -1,32 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "astro";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        language-servers = ["astro-ls" "tailwindcss-ls"];
-        formatter = {
-          command = "prettier";
-          args = ["--parser" "astro" "--stdin-filepath" "%{buffer_name}"];
-        };
-      }
-    ];
-    language-server = {
-      astro-ls = {
-        command = "astro-ls";
-        args = ["--stdio"];
-        config = {
-          typescript = {
-            tsdk = "node_modules/typescript/lib";
-            environment = "node";
-          };
-          contentIntellisense = true;
-        };
-      };
-    };
-  };
-}
home/base/tui/editors/helix/languages/cpp.nix
@@ -1,33 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "c";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-      }
-      {
-        name = "cpp";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-      }
-    ];
-    language-server.clangd = {
-      command = "clangd";
-      args = [
-        "--all-scopes-completion"
-        "--completion-parse=auto"
-        "--completion-style=detailed"
-        "--background-index"
-        "--clang-tidy"
-        "--fallback-style=LLVM"
-      ];
-    };
-  };
-}
home/base/tui/editors/helix/languages/css.nix
@@ -1,48 +0,0 @@
-{...}: let
-  stylelintRoots = [
-    ".stylelintrc"
-    ".stylelintrc.mjs"
-    ".stylelintrc.cjs"
-    ".stylelintrc.js"
-    ".stylelintrc.json"
-    ".stylelintrc.yaml"
-    ".stylelintrc.yml"
-    "stylelint.config.mjs"
-    "stylelint.config.cjs"
-    "stylelint.config.js"
-  ];
-in {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "css";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        roots = stylelintRoots;
-        language-servers = ["stylelint-lsp" "tailwindcss-ls"];
-      }
-      {
-        name = "scss";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        roots = stylelintRoots;
-        language-servers = ["stylelint-lsp" "tailwindcss-ls"];
-      }
-    ];
-    language-server = {
-      stylelint-lsp = {
-        command = "stylelint-lsp";
-        args = ["--stdio"];
-        config = {
-          autoFixOnFormat = true;
-        };
-      };
-    };
-  };
-}
home/base/tui/editors/helix/languages/default.nix
@@ -1,10 +0,0 @@
-{mylib, ...}: {
-  imports = mylib.scanModules ./.;
-
-  programs.helix.languages.language-server = {
-    copilot-language-server = {
-      command = "copilot-language-server";
-      args = ["--stdio"];
-    };
-  };
-}
home/base/tui/editors/helix/languages/html.nix
@@ -1,19 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "html";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        language-servers = ["vscode-html-language-server" "tailwindcss-ls"];
-        formatter = {
-          command = "prettier";
-          args = ["--parser" "html" "--stdin-filepath" "%{buffer_name}"];
-        };
-      }
-    ];
-  };
-}
home/base/tui/editors/helix/languages/latex.nix
@@ -1,30 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "latex";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        formatter = {
-          command = "tex-fmt";
-          args = ["--stdin"];
-        };
-      }
-      {
-        name = "bibtex";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        formatter = {
-          command = "tex-fmt";
-          args = ["--stdin"];
-        };
-      }
-    ];
-  };
-}
home/base/tui/editors/helix/languages/lua.nix
@@ -1,41 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "lua";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        formatter = {
-          command = "stylua";
-          args = [
-            "--indent-type"
-            "Spaces"
-            "--indent-width"
-            "2"
-            "--column-width"
-            "80"
-            "--call-parentheses"
-            "NoSingleTable"
-            "--sort-requires"
-            "-" # From stdin
-          ];
-        };
-        roots = [
-          "stylua.toml"
-          ".stylua.toml"
-          ".editorconfig"
-        ];
-      }
-    ];
-    language-server.lua-language-server = {
-      command = "lua-language-server";
-      args = ["--locale=zh-cn"];
-      config.Lua = {
-        format.enable = false;
-      };
-    };
-  };
-}
home/base/tui/editors/helix/languages/markdown.nix
@@ -1,28 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "markdown";
-        auto-format = false;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        soft-wrap.enable = true;
-        roots = [
-          ".prettierignore"
-          ".prettierrc"
-          ".prettierrc.cjs"
-          ".prettierrc.mjs"
-          ".prettierrc.js"
-          ".marksman.toml"
-        ];
-        formatter = {
-          command = "prettier";
-          args = ["--parser" "markdown" "--stdin-filepath" "%{buffer_name}"];
-        };
-        language-servers = ["marksman"];
-      }
-    ];
-  };
-}
home/base/tui/editors/helix/languages/mdx.nix
@@ -1,46 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "mdx";
-        scope = "source.mdx";
-        injection-regex = "mdx";
-        file-types = ["mdx"];
-        block-comment-tokens = {
-          start = "<!--";
-          end = "-->";
-        };
-        auto-format = false;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        roots = [
-          ".prettierignore"
-          ".prettierrc"
-          ".prettierrc.cjs"
-          ".prettierrc.mjs"
-          ".prettierrc.js"
-        ];
-        formatter = {
-          command = "prettier";
-          args = ["--parser" "mdx" "--stdin-filepath" "%{buffer_name}"];
-        };
-        language-servers = ["mdx-language-server"];
-      }
-    ];
-    grammar = [
-      {
-        name = "mdx";
-        source = {
-          git = "https://github.com/parmort/tree-sitter-mdx";
-          rev = "413285231ce8fa8b11e7074bbe265b48aa7277f9";
-        };
-      }
-    ];
-    language-server.mdx-language-server = {
-      command = "mdx-language-server";
-      args = ["--stdio"];
-    };
-  };
-}
home/base/tui/editors/helix/languages/nix.nix
@@ -1,30 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "nix";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        language-servers = ["nixd"];
-      }
-    ];
-    language-server = {
-      nil.config.nil = {
-        formatting.command = ["alejandra"];
-        nix = {
-          maxMemoryMB = 4096;
-          flake = {
-            autoArchive = false;
-            autoEvalInputs = true;
-          };
-        };
-      };
-      nixd.config.nixd = {
-        formatting.command = ["alejandra"];
-      };
-    };
-  };
-}
home/base/tui/editors/helix/languages/rust.nix
@@ -1,16 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "rust";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-      }
-    ];
-    language-server.rust-analyzer.config = {
-    };
-  };
-}
home/base/tui/editors/helix/languages/typescript.nix
@@ -1,18 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "typescript";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        formatter = {
-          command = "prettier";
-          args = ["--parser" "typescript" "--stdin-filepath" "%{buffer_name}"];
-        };
-      }
-    ];
-  };
-}
home/base/tui/editors/helix/languages/typst.nix
@@ -1,19 +0,0 @@
-{...}: {
-  programs.helix.languages = {
-    language = [
-      {
-        name = "typst";
-        auto-format = true;
-        indent = {
-          tab-width = 2;
-          unit = "  ";
-        };
-        soft-wrap.enable = true;
-      }
-    ];
-    language-server.tinymist.config = {
-      formatterMode = "typstyle";
-      formatterIndentSize = 2;
-    };
-  };
-}
home/base/tui/editors/helix/default.nix
@@ -1,26 +0,0 @@
-{...}: {
-  imports = [./languages];
-
-  programs.helix = {
-    settings = {
-      editor = {
-        line-number = "relative";
-        cursorline = true;
-        bufferline = "multiple";
-        color-modes = true;
-        trim-trailing-whitespace = true;
-        inline-diagnostics.cursor-line = "warning";
-        end-of-line-diagnostics = "error";
-        lsp = {
-          display-inlay-hints = true;
-          inlay-hints-length-limit = 16;
-        };
-        indent-guides = {
-          render = true;
-          character = "┊";
-          skip-levels = 1;
-        };
-      };
-    };
-  };
-}
home/base/tui/editors/zide/default.nix
@@ -1,16 +0,0 @@
-{
-  pkgs,
-  nur-hpcesia,
-  ...
-}: let
-  zide = nur-hpcesia.packages.${pkgs.system}.zide.overrideAttrs (oldAttrs: {
-    passthru =
-      oldAttrs.passthru
-      // {
-        layoutDir = ./layouts;
-        useYaziConfig = false;
-      };
-  });
-in {
-  home.packages = [zide];
-}
home/base/tui/editors/default.nix
@@ -1,7 +0,0 @@
-{
-  mylib,
-  config,
-  ...
-}: {
-  imports = mylib.scanModules ./.;
-}
home/base/tui/editors/packages.nix
@@ -1,81 +0,0 @@
-{
-  osConfig,
-  pkgs,
-  pkgs-unstable,
-  pkgs-stable,
-  ...
-}: {
-  home.packages = with pkgs; [
-    # === Data & Configuration Languages === #
-    # -- Nix
-    # nil # Nix LSP
-    nixd # Nix LSP
-    alejandra # Nix Formatter
-
-    # -- Json Like
-    taplo # TOML LSP / Formatter / Validator
-    nodePackages.yaml-language-server
-    actionlint # GitHub Actions linter
-    kdlfmt # KDL Formatter
-
-    # -- Documents
-    marksman # Markdown LSP
-    tinymist # Typst LSP
-    typstyle # Typst Formatter
-    mdx-language-server
-    texlab # LaTeX LSP
-    tex-fmt # LaTeX Formatter
-    pandoc # Document converter
-
-    # === General Purpose Languages === #
-    # -- C/C++
-    cmake
-    pkgs-stable.cmake-language-server
-    gnumake
-    checkmake
-    xmake
-    gcc
-    gdb
-    clang-tools
-    lldb
-
-    # -- Python
-    pipx # Install and Run Python Applications in Isolated Environments
-    uv # Python package manager in rust
-    pixi # Python package manager in rust, supports conda
-    ruff # Python LSP and formatter
-    python313
-
-    #-- rust
-    pkgs-unstable.rustc
-    pkgs-unstable.rust-analyzer
-    pkgs-unstable.cargo # rust package manager
-    pkgs-unstable.rustfmt
-    pkgs-unstable.clippy # rust linter
-
-    # -- Lua
-    stylua
-    lua-language-server
-
-    #-- bash
-    nodePackages.bash-language-server
-    shellcheck
-    shfmt
-
-    # === Web Development === #
-    nodePackages.nodejs
-    pnpm
-    bun
-    deno
-
-    nodePackages.typescript
-    nodePackages.typescript-language-server
-    nodePackages.vscode-langservers-extracted # HTML/CSS/JSON/ESLint LSP extracted from vscode
-    nodePackages."@tailwindcss/language-server"
-    nodePackages."@astrojs/language-server"
-    # vue-language-server
-    stylelint-lsp
-    nodePackages.prettier
-    biome
-  ];
-}
home/base/tui/zellij.nix
@@ -1,29 +0,0 @@
-{...}: {
-  programs.zellij = {
-    enable = true;
-    settings = {
-      show_startup_tips = false;
-      show_release_notes = false;
-      default_shell = "fish";
-    };
-  };
-
-  # auto start zellij in nushell
-  # programs.nushell.extraConfig = ''
-  #   # auto start zellij
-  #   # except when in VSCode or zellij itself
-  #   if (not ("ZELLIJ" in $env)) and (not ($env.TERM_PROGRAM? == "vscode")) {
-  #     if "ZELLIJ_AUTO_ATTACH" in $env and $env.ZELLIJ_AUTO_ATTACH == "true" {
-  #       ^zellij attach -c
-  #     } else {
-  #       ^zellij
-  #     }
-
-  #     # Auto exit the shell session when zellij exit
-  #     $env.ZELLIJ_AUTO_EXIT = "false" # disable auto exit
-  #     if "ZELLIJ_AUTO_EXIT" in $env and $env.ZELLIJ_AUTO_EXIT == "true" {
-  #       exit
-  #     }
-  #   }
-  # '';
-}
home/linux/gui/vscode/profiles/default.nix
@@ -1,96 +0,0 @@
-{
-  # NOTE: the args not used in this file CAN NOT be removed!
-  # Just like haumea in `/outputs`.
-  lib,
-  mylib,
-  pkgs,
-  pkgs-unstable,
-  ...
-} @ args: let
-  baseExtensions = import ../baseExtensions.nix args;
-  baseMcp = import ../baseMcp.nix;
-  profilesList =
-    (map (path: import path args) (mylib.scanModules ./.))
-    ++ [
-      {
-        default = {
-          enableUpdateCheck = false;
-          enableExtensionUpdateCheck = false;
-          userSettings = {
-            # --- Editor Settings --- #
-            "editor.fontSize" = 16;
-            "editor.fontLigatures" = true;
-            "editor.guides.bracketPairs" = true;
-            "editor.formatOnSave" = true;
-            "editor.unicodeHighlight.allowedLocales"."zh-hans" = true;
-            "editor.lineNumbers" = "relative";
-            # --- Terminal Settings --- #
-            "terminal.integrated.fontSize" = 14;
-            "terminal.integrated.defaultProfile.linux" = "fish";
-            # --- Workbench Settings --- #
-            "workbench.colorTheme" = "Catppuccin Macchiato";
-            "workbench.iconTheme" = "material-icon-theme";
-            "workbench.startupEditor" = "none";
-            # --- Extension Settings --- #
-            "git.enabled" = false; # Disable git because I use jujutsu instead
-            # "GitCommitPlugin.ShowEmoji" = false;
-            # "GitCommitPlugin.MaxSubjectCharacters" = 25;
-            "github.copilot.advanced".useLanguageServer = true;
-            "nix.enableLanguageServer" = true;
-            "nix.serverPath" = "nixd";
-            "nix.serverSettings".nixd.formatting.command = ["alejandra"];
-            "evenBetterToml.formatter.alignEntries" = true;
-            "evenBetterToml.formatter.alignComments" = true;
-            "evenBetterToml.formatter.allowedBlankLines" = 1;
-            # --- Update Settings --- #
-            "extensions.autoCheckUpdates" = false;
-            "extensions.autoUpdate" = false;
-            "update.mode" = "none";
-            # --- Other Settings --- #
-            # Settings apply to all profiles
-            "telemetry.telemetryLevel" = "off";
-            "security.workspace.trust.untrustedFiles" = "open";
-            "window.newWindowProfile" = "Default";
-            "workbench.settings.applyToAllProfiles" = [
-              # -- Normal -- #
-              "editor.fontSize"
-              "editor.fontLigatures"
-              "editor.guides.bracketPairs"
-              "editor.formatOnSave"
-              "editor.lineNumbers"
-              "terminal.integrated.fontSize"
-              "terminal.integrated.defaultProfile.linux"
-              "workbench.colorTheme"
-              "workbench.iconTheme"
-              "workbench.startupEditor"
-              # -- Extension -- #
-              "git.enabled"
-              # "GitCommitPlugin.ShowEmoji"
-              # "GitCommitPlugin.MaxSubjectCharacters"
-              "github.copilot.advanced"
-              "nix.enableLanguageServer"
-              "nix.serverPath"
-              "nix.serverSettings"
-              "evenBetterToml.formatter.alignEntries"
-              "evenBetterToml.formatter.alignComments"
-              "evenBetterToml.formatter.allowedBlankLines"
-            ];
-          };
-        };
-      }
-    ];
-  profiles =
-    lib.mapAttrs
-    (_: v: (v
-      // {
-        extensions = v.extensions or [] ++ baseExtensions;
-        userMcp = {
-          servers = lib.mergeAttrs baseMcp.servers v.userMcp.servers or {};
-          inputs = v.userMcp.inputs or [] ++ baseMcp.inputs;
-        };
-      }))
-    (lib.mergeAttrsList profilesList);
-in {
-  catppuccin.vscode.profiles.default.icons.enable = false;
-  programs.vscode.profiles = profiles;
-}
home/linux/gui/vscode/baseExtensions.nix
@@ -1,54 +0,0 @@
-{pkgs, ...}:
-with pkgs.vscode-extensions;
-  [
-    # Translation
-    ms-ceintl.vscode-language-pack-zh-hans
-    w88975.code-translate
-
-    # Appearance
-    pkief.material-icon-theme
-    catppuccin.catppuccin-vsc
-
-    # Utils
-    mhutchie.git-graph
-    christian-kohler.path-intellisense
-    usernamehw.errorlens
-    shardulm94.trailing-spaces
-    gruntfuggly.todo-tree
-    editorconfig.editorconfig
-
-    # LLM
-    github.copilot
-    github.copilot-chat
-    rooveterinaryinc.roo-cline
-
-    # Nix
-    jnoortheen.nix-ide
-
-    # # Nushell
-    # thenuprojectcontributors.vscode-nushell-lang
-
-    # Configuration languages
-    tamasfe.even-better-toml
-    redhat.vscode-yaml
-  ]
-  ++ (pkgs.vscode-utils.extensionsFromVscodeMarketplace [
-    # {
-    #   name = "git-commit-plugin";
-    #   publisher = "redjue";
-    #   version = "1.5.0";
-    #   sha256 = "fOdeUuB4jFL0LvGsLcjz5EQslD8jRRGslbumMo3cZCs=";
-    # }
-    {
-      name = "aw-watcher-vscode";
-      publisher = "activitywatch";
-      version = "0.5.0";
-      sha256 = "OrdIhgNXpEbLXYVJAx/jpt2c6Qa5jf8FNxqrbu5FfFs=";
-    }
-    {
-      name = "jjk";
-      publisher = "jjk";
-      version = "0.8.1";
-      sha256 = "2JUn6wkWgZKZzhitQy6v9R/rCNLrt7DBtt59707hp6c=";
-    }
-  ])
home/linux/gui/vscode/baseMcp.nix
@@ -1,16 +0,0 @@
-{
-  servers = {
-    github = {
-      type = "http";
-      url = "https://api.githubcopilot.com/mcp/";
-      gallery = true;
-    };
-    context7 = {
-      type = "stdio";
-      command = "npx";
-      args = ["-y" "@upstash/context7-mcp@latest"];
-      gallery = true;
-    };
-  };
-  inputs = [];
-}
home/linux/gui/vscode/default.nix
@@ -1,118 +0,0 @@
-{
-  config,
-  lib,
-  pkgs,
-  ...
-}: let
-  inherit (lib.lists) concatLists;
-
-  homeDir = config.home.homeDirectory;
-  dataDir = config.xdg.dataHome;
-  userDataDir = "${dataDir}/vscode/data";
-  extensionsDir = "${dataDir}/vscode/extensions";
-
-  pkg = pkgs.vscode.override {
-    commandLineArgs = concatLists [
-      ["--extensions-dir" extensionsDir]
-      ["--user-data-dir" userDataDir]
-      ["--locale" "zh-cn"]
-      ["--ozone-platform-hint=auto"]
-      ["--enable-wayland-ime"]
-      ["--wayland-text-input-version=3"]
-    ];
-  };
-in {
-  imports = [./profiles];
-
-  programs.vscode = {
-    enable = true;
-    package = pkg;
-    mutableExtensionsDir = false;
-  };
-
-  # To solve VSCode wants to write settings.json
-  # VSCode will reset per reboot/rebuild.
-  systemd.user.services.vscode-setup = {
-    Unit = {
-      Description = "VSCode Setup service";
-      After = ["graphical-session-pre.target"];
-      Wants = ["graphical-session-pre.target"];
-    };
-    Install.WantedBy = ["graphical-session.target"];
-    Service = {
-      Type = "oneshot";
-      UMask = "0022";
-      ExecStart = lib.getExe (pkgs.writeShellApplication {
-        name = "vscode-setup";
-        runtimeInputs = with pkgs; [coreutils gnutar jq];
-        text = let
-          userSrc = "${homeDir}/.config/Code/User";
-          userDst = "${userDataDir}/User";
-          extSrc = "${homeDir}/.vscode/extensions";
-          extDst = extensionsDir;
-
-          dirsToPreserve = [
-            "workspaceStorage"
-            "History"
-          ];
-          backupCmds = builtins.concatStringsSep "\n" (map (dir: ''
-              if [ -e "${userDst}/${dir}" ]; then
-                echo "Backing up data/User/${dir}..."
-                mv "${userDst}/${dir}" "/tmp/vscode-${dir}-$$"
-              fi
-            '')
-            (dirsToPreserve ++ ["globalStorage"]));
-          restoreCmds = builtins.concatStringsSep "\n" (map (dir: ''
-              if [ -e "/tmp/vscode-${dir}-$$" ]; then
-                echo "Restoring data/User/${dir}..."
-                mv "/tmp/vscode-${dir}-$$" "${userDst}/${dir}"
-              fi
-            '')
-            dirsToPreserve);
-        in ''
-          set -eu
-
-          ${backupCmds}
-
-          echo "Cleaning old directories..."
-          rm -rf "${userDst}"
-          rm -rf "${extDst}"
-
-          mkdir -p "${userDataDir}"
-          mkdir -p "${extDst}"
-
-          echo "Copying user settings from ${userSrc}..."
-          cp -r --dereference --no-preserve=mode,ownership ${userSrc} "${userDst}"
-
-          echo "Copying extensions from ${extSrc}..."
-          tar -h -C "${extSrc}" -cf - . | tar -C "${extDst}" -xf - --no-same-owner --no-same-permissions --mode='u=rX,go=rX'
-          chmod u+w -R "${extDst}" 2>/dev/null || true
-
-          ${restoreCmds}
-
-          echo "Restoring and merging data/User/globalStorage..."
-          if [ -e "/tmp/vscode-globalStorage-$$" ]; then
-            cp -rT "/tmp/vscode-globalStorage-$$" "${userDst}/globalStorage"
-
-            src_storage_json="${userSrc}/globalStorage/storage.json"
-            dst_storage_json="${userDst}/globalStorage/storage.json"
-
-            if [ -f "$src_storage_json" ] && [ -f "$dst_storage_json" ]; then
-              echo "Merging data/globalStorage/storage.json with new data..."
-              merged_json=$(mktemp)
-              jq -s '.[0] * .[1]' "$dst_storage_json" "$src_storage_json" > "$merged_json"
-              mv "$merged_json" "$dst_storage_json"
-              echo "Merge complete."
-            else
-              echo "Skipping storage.json merge: one or both files do not exist."
-            fi
-          else
-            echo "No backed-up globalStorage found to restore."
-          fi
-
-          echo "VSCode setup complete."
-        '';
-      });
-    };
-  };
-}
home/linux/gui/xdg.nix
@@ -3,13 +3,11 @@
     mimeApps = {
       defaultApplications = let
         browser = ["firefox.desktop"];
-        editor = ["Helix.desktop" "code.desktop"];
       in {
         "application/json" = browser;
 
         "text/html" = browser;
         "text/xml" = browser;
-        "text/plain" = editor;
         "application/xml" = browser;
         "application/xhtml+xml" = browser;
         "application/xhtml_xml" = browser;
modules/dev/helix/languages/astro.nix
@@ -0,0 +1,34 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "astro";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          language-servers = ["astro-ls" "tailwindcss-ls"];
+          formatter = {
+            command = "prettier";
+            args = ["--parser" "astro" "--stdin-filepath" "%{buffer_name}"];
+          };
+        }
+      ];
+      language-server = {
+        astro-ls = {
+          command = "astro-ls";
+          args = ["--stdio"];
+          config = {
+            typescript = {
+              tsdk = "node_modules/typescript/lib";
+              environment = "node";
+            };
+            contentIntellisense = true;
+          };
+        };
+      };
+    };
+  };
+}
modules/dev/helix/languages/cpp.nix
@@ -0,0 +1,35 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "c";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+        }
+        {
+          name = "cpp";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+        }
+      ];
+      language-server.clangd = {
+        command = "clangd";
+        args = [
+          "--all-scopes-completion"
+          "--completion-parse=auto"
+          "--completion-style=detailed"
+          "--background-index"
+          "--clang-tidy"
+          "--fallback-style=LLVM"
+        ];
+      };
+    };
+  };
+}
modules/dev/helix/languages/css.nix
@@ -0,0 +1,50 @@
+{
+  flake.modules.homeManager.dev-helix = _: let
+    stylelintRoots = [
+      ".stylelintrc"
+      ".stylelintrc.mjs"
+      ".stylelintrc.cjs"
+      ".stylelintrc.js"
+      ".stylelintrc.json"
+      ".stylelintrc.yaml"
+      ".stylelintrc.yml"
+      "stylelint.config.mjs"
+      "stylelint.config.cjs"
+      "stylelint.config.js"
+    ];
+  in {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "css";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          roots = stylelintRoots;
+          language-servers = ["stylelint-lsp" "tailwindcss-ls"];
+        }
+        {
+          name = "scss";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          roots = stylelintRoots;
+          language-servers = ["stylelint-lsp" "tailwindcss-ls"];
+        }
+      ];
+      language-server = {
+        stylelint-lsp = {
+          command = "stylelint-lsp";
+          args = ["--stdio"];
+          config = {
+            autoFixOnFormat = true;
+          };
+        };
+      };
+    };
+  };
+}
modules/dev/helix/languages/html.nix
@@ -0,0 +1,21 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "html";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          language-servers = ["vscode-html-language-server" "tailwindcss-ls"];
+          formatter = {
+            command = "prettier";
+            args = ["--parser" "html" "--stdin-filepath" "%{buffer_name}"];
+          };
+        }
+      ];
+    };
+  };
+}
modules/dev/helix/languages/latex.nix
@@ -0,0 +1,32 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "latex";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          formatter = {
+            command = "tex-fmt";
+            args = ["--stdin"];
+          };
+        }
+        {
+          name = "bibtex";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          formatter = {
+            command = "tex-fmt";
+            args = ["--stdin"];
+          };
+        }
+      ];
+    };
+  };
+}
modules/dev/helix/languages/lua.nix
@@ -0,0 +1,43 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "lua";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          formatter = {
+            command = "stylua";
+            args = [
+              "--indent-type"
+              "Spaces"
+              "--indent-width"
+              "2"
+              "--column-width"
+              "80"
+              "--call-parentheses"
+              "NoSingleTable"
+              "--sort-requires"
+              "-" # From stdin
+            ];
+          };
+          roots = [
+            "stylua.toml"
+            ".stylua.toml"
+            ".editorconfig"
+          ];
+        }
+      ];
+      language-server.lua-language-server = {
+        command = "lua-language-server";
+        args = ["--locale=zh-cn"];
+        config.Lua = {
+          format.enable = false;
+        };
+      };
+    };
+  };
+}
modules/dev/helix/languages/markdown.nix
@@ -0,0 +1,30 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "markdown";
+          auto-format = false;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          soft-wrap.enable = true;
+          roots = [
+            ".prettierignore"
+            ".prettierrc"
+            ".prettierrc.cjs"
+            ".prettierrc.mjs"
+            ".prettierrc.js"
+            ".marksman.toml"
+          ];
+          formatter = {
+            command = "prettier";
+            args = ["--parser" "markdown" "--stdin-filepath" "%{buffer_name}"];
+          };
+          language-servers = ["marksman"];
+        }
+      ];
+    };
+  };
+}
modules/dev/helix/languages/mdx.nix
@@ -0,0 +1,48 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "mdx";
+          scope = "source.mdx";
+          injection-regex = "mdx";
+          file-types = ["mdx"];
+          block-comment-tokens = {
+            start = "<!--";
+            end = "-->";
+          };
+          auto-format = false;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          roots = [
+            ".prettierignore"
+            ".prettierrc"
+            ".prettierrc.cjs"
+            ".prettierrc.mjs"
+            ".prettierrc.js"
+          ];
+          formatter = {
+            command = "prettier";
+            args = ["--parser" "mdx" "--stdin-filepath" "%{buffer_name}"];
+          };
+          language-servers = ["mdx-language-server"];
+        }
+      ];
+      grammar = [
+        {
+          name = "mdx";
+          source = {
+            git = "https://github.com/parmort/tree-sitter-mdx";
+            rev = "413285231ce8fa8b11e7074bbe265b48aa7277f9";
+          };
+        }
+      ];
+      language-server.mdx-language-server = {
+        command = "mdx-language-server";
+        args = ["--stdio"];
+      };
+    };
+  };
+}
modules/dev/helix/languages/nix.nix
@@ -0,0 +1,32 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "nix";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          language-servers = ["nixd"];
+        }
+      ];
+      language-server = {
+        nil.config.nil = {
+          formatting.command = ["alejandra"];
+          nix = {
+            maxMemoryMB = 4096;
+            flake = {
+              autoArchive = false;
+              autoEvalInputs = true;
+            };
+          };
+        };
+        nixd.config.nixd = {
+          formatting.command = ["alejandra"];
+        };
+      };
+    };
+  };
+}
modules/dev/helix/languages/rust.nix
@@ -0,0 +1,18 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "rust";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+        }
+      ];
+      language-server.rust-analyzer.config = {
+      };
+    };
+  };
+}
modules/dev/helix/languages/typescript.nix
@@ -0,0 +1,20 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "typescript";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          formatter = {
+            command = "prettier";
+            args = ["--parser" "typescript" "--stdin-filepath" "%{buffer_name}"];
+          };
+        }
+      ];
+    };
+  };
+}
modules/dev/helix/languages/typst.nix
@@ -0,0 +1,21 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix.languages = {
+      language = [
+        {
+          name = "typst";
+          auto-format = true;
+          indent = {
+            tab-width = 2;
+            unit = "  ";
+          };
+          soft-wrap.enable = true;
+        }
+      ];
+      language-server.tinymist.config = {
+        formatterMode = "typstyle";
+        formatterIndentSize = 2;
+      };
+    };
+  };
+}
home/base/tui/editors/zide/layouts/default.kdl → modules/dev/helix/zide/layouts/default.kdl
File renamed without changes
modules/dev/helix/zide/default.nix
@@ -0,0 +1,14 @@
+{inputs, ...}: {
+  flake.modules.homeManager.dev-helix = {pkgs, ...}: let
+    zide = inputs.nur-hpcesia.packages.${pkgs.system}.zide.overrideAttrs (oldAttrs: {
+      passthru =
+        oldAttrs.passthru
+        // {
+          layoutDir = ./layouts;
+          useYaziConfig = false;
+        };
+    });
+  in {
+    home.packages = [zide];
+  };
+}
home/base/tui/editors/zide/README.md → modules/dev/helix/zide/README.md
File renamed without changes
modules/dev/helix/default.nix
@@ -0,0 +1,27 @@
+{
+  flake.modules.homeManager.dev-helix = _: {
+    programs.helix = {
+      enable = true;
+      settings = {
+        editor = {
+          line-number = "relative";
+          cursorline = true;
+          bufferline = "multiple";
+          color-modes = true;
+          trim-trailing-whitespace = true;
+          inline-diagnostics.cursor-line = "warning";
+          end-of-line-diagnostics = "error";
+          lsp = {
+            display-inlay-hints = true;
+            inlay-hints-length-limit = 16;
+          };
+          indent-guides = {
+            render = true;
+            character = "┊";
+            skip-levels = 1;
+          };
+        };
+      };
+    };
+  };
+}
home/linux/gui/vscode/profiles/astro.nix → modules/dev/vscode/profiles/_astro.nix
File renamed without changes
home/linux/gui/vscode/profiles/cpp.nix → modules/dev/vscode/profiles/_cpp.nix
File renamed without changes
home/linux/gui/vscode/profiles/rust.nix → modules/dev/vscode/profiles/_rust.nix
File renamed without changes
home/linux/gui/vscode/profiles/tauri.nix → modules/dev/vscode/profiles/_tauri.nix
File renamed without changes
home/linux/gui/vscode/profiles/typst.nix → modules/dev/vscode/profiles/_typst.nix
File renamed without changes
modules/dev/vscode/profiles/default.nix
@@ -0,0 +1,98 @@
+{
+  flake.modules.homeManager.dev-vscode = {
+    config,
+    lib, # Use inner lib to pass lib in args
+    # NOTE: this args not used in this file CAN NOT be removed!
+    pkgs,
+    ...
+  } @ args: let
+    scanModules = path:
+      builtins.map (f: (path + "/${f}")) (
+        builtins.attrNames (
+          lib.attrsets.filterAttrs (
+            path: _type:
+              (_type == "directory") || ((path != "default.nix") && (lib.strings.hasSuffix ".nix" path))
+          ) (builtins.readDir path)
+        )
+      );
+
+    baseExtensions = config.programs.vscode.baseExtensions;
+    profilesList =
+      (map (path: import path args) (scanModules ./.))
+      ++ [
+        {
+          default = {
+            enableUpdateCheck = false;
+            enableExtensionUpdateCheck = false;
+            userSettings = {
+              # --- Editor Settings --- #
+              "editor.fontSize" = 16;
+              "editor.fontLigatures" = true;
+              "editor.guides.bracketPairs" = true;
+              "editor.formatOnSave" = true;
+              "editor.unicodeHighlight.allowedLocales"."zh-hans" = true;
+              "editor.lineNumbers" = "relative";
+              # --- Terminal Settings --- #
+              "terminal.integrated.fontSize" = 14;
+              "terminal.integrated.defaultProfile.linux" = "fish";
+              # --- Workbench Settings --- #
+              "workbench.colorTheme" = "Catppuccin Macchiato";
+              "workbench.iconTheme" = "material-icon-theme";
+              "workbench.startupEditor" = "none";
+              # --- Extension Settings --- #
+              "git.enabled" = false; # Disable git because I use jujutsu instead
+              # "GitCommitPlugin.ShowEmoji" = false;
+              # "GitCommitPlugin.MaxSubjectCharacters" = 25;
+              "github.copilot.advanced".useLanguageServer = true;
+              "nix.enableLanguageServer" = true;
+              "nix.serverPath" = "nixd";
+              "nix.serverSettings".nixd.formatting.command = ["alejandra"];
+              "evenBetterToml.formatter.alignEntries" = true;
+              "evenBetterToml.formatter.alignComments" = true;
+              "evenBetterToml.formatter.allowedBlankLines" = 1;
+              # --- Update Settings --- #
+              "extensions.autoCheckUpdates" = false;
+              "extensions.autoUpdate" = false;
+              "update.mode" = "none";
+              # --- Other Settings --- #
+              # Settings apply to all profiles
+              "telemetry.telemetryLevel" = "off";
+              "security.workspace.trust.untrustedFiles" = "open";
+              "window.newWindowProfile" = "Default";
+              "workbench.settings.applyToAllProfiles" = [
+                # -- Normal -- #
+                "editor.fontSize"
+                "editor.fontLigatures"
+                "editor.guides.bracketPairs"
+                "editor.formatOnSave"
+                "editor.lineNumbers"
+                "terminal.integrated.fontSize"
+                "terminal.integrated.defaultProfile.linux"
+                "workbench.colorTheme"
+                "workbench.iconTheme"
+                "workbench.startupEditor"
+                # -- Extension -- #
+                "git.enabled"
+                # "GitCommitPlugin.ShowEmoji"
+                # "GitCommitPlugin.MaxSubjectCharacters"
+                "github.copilot.advanced"
+                "nix.enableLanguageServer"
+                "nix.serverPath"
+                "nix.serverSettings"
+                "evenBetterToml.formatter.alignEntries"
+                "evenBetterToml.formatter.alignComments"
+                "evenBetterToml.formatter.allowedBlankLines"
+              ];
+            };
+          };
+        }
+      ];
+    profiles =
+      lib.mapAttrs
+      (_: v: (v // {extensions = v.extensions or [] ++ baseExtensions;}))
+      (lib.mergeAttrsList profilesList);
+  in {
+    catppuccin.vscode.profiles.default.icons.enable = false;
+    programs.vscode.profiles = profiles;
+  };
+}
modules/dev/vscode/base-extensions.nix
@@ -0,0 +1,51 @@
+{lib, ...}: {
+  flake.modules.homeManager.dev-vscode = {pkgs, ...}: let
+    options.programs.vscode.baseExtensions = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
+    };
+
+    baseExtensions = with pkgs.vscode-extensions;
+      [
+        # Translation
+        ms-ceintl.vscode-language-pack-zh-hans
+        w88975.code-translate
+
+        # Appearance
+        pkief.material-icon-theme
+        catppuccin.catppuccin-vsc
+
+        # Utils
+        mhutchie.git-graph
+        christian-kohler.path-intellisense
+        usernamehw.errorlens
+        shardulm94.trailing-spaces
+        gruntfuggly.todo-tree
+        editorconfig.editorconfig
+
+        # LLM
+        github.copilot
+        github.copilot-chat
+        rooveterinaryinc.roo-cline
+
+        # Nix
+        jnoortheen.nix-ide
+
+        # Configuration languages
+        tamasfe.even-better-toml
+        redhat.vscode-yaml
+      ]
+      ++ (pkgs.vscode-utils.extensionsFromVscodeMarketplace [
+        {
+          name = "jjk";
+          publisher = "jjk";
+          version = "0.8.1";
+          sha256 = "2JUn6wkWgZKZzhitQy6v9R/rCNLrt7DBtt59707hp6c=";
+        }
+      ]);
+  in {
+    inherit options;
+    config.programs.vscode = {
+      inherit baseExtensions;
+    };
+  };
+}
modules/dev/vscode/default.nix
@@ -0,0 +1,161 @@
+{lib, ...}: {
+  flake.modules.homeManager.dev-vscode = {
+    config,
+    pkgs,
+    ...
+  }: let
+    bask-pkg = pkgs.vscode;
+
+    pkg = bask-pkg.override {
+      commandLineArgs = lib.lists.concatLists ([
+          ["--extensions-dir" extensionsDir]
+          ["--user-data-dir" userDataDir]
+          ["--locale" "zh-cn"]
+        ]
+        ++ lib.optionals pkgs.stdenv.hostPlatform.isLinux [
+          ["--ozone-platform-hint=auto"]
+          ["--enable-wayland-ime"]
+          ["--wayland-text-input-version=3"]
+        ]);
+    };
+
+    # Below VSCode paths are copied from home-manager's vscode module source
+    vscodePname = bask-pkg.pname;
+    vscodeConfigDir =
+      {
+        "vscode" = "Code";
+        "vscode-insiders" = "Code - Insiders";
+        "vscodium" = "VSCodium";
+        "openvscode-server" = "OpenVSCode Server";
+        "windsurf" = "Windsurf";
+        "cursor" = "Cursor";
+      }.${
+        vscodePname
+      };
+    vscodeExtensionDir =
+      {
+        "vscode" = "vscode";
+        "vscode-insiders" = "vscode-insiders";
+        "vscodium" = "vscode-oss";
+        "openvscode-server" = "openvscode-server";
+        "windsurf" = "windsurf";
+        "cursor" = "cursor";
+      }.${
+        vscodePname
+      };
+    vscodeUserDir =
+      if pkgs.stdenv.hostPlatform.isDarwin
+      then "${config.home.homeDirectory}/Library/Application Support/${vscodeConfigDir}/User"
+      else "${config.xdg.configHome}/${vscodeConfigDir}/User";
+
+    homeDir = config.home.homeDirectory;
+    dataDir = config.xdg.dataHome;
+    userDataDir = "${dataDir}/${vscodePname}/data";
+    extensionsDir = "${dataDir}/${vscodePname}/extensions";
+
+    vscodeSetupScript = pkgs.writeShellApplication {
+      name = "vscode-setup";
+      runtimeInputs = with pkgs; [coreutils gnutar jq];
+      text = let
+        userSrc = vscodeUserDir;
+        userDst = "${userDataDir}/User";
+        extSrc = ".${vscodeExtensionDir}/extensions";
+        extDst = extensionsDir;
+
+        dirsToPreserve = [
+          "workspaceStorage"
+          "History"
+        ];
+        backupCmds = builtins.concatStringsSep "\n" (map (dir: ''
+            if [ -e "${userDst}/${dir}" ]; then
+              echo "Backing up data/User/${dir}..."
+              mv "${userDst}/${dir}" "/tmp/vscode-${dir}-$$"
+            fi
+          '')
+          (dirsToPreserve ++ ["globalStorage"]));
+        restoreCmds = builtins.concatStringsSep "\n" (map (dir: ''
+            if [ -e "/tmp/vscode-${dir}-$$" ]; then
+              echo "Restoring data/User/${dir}..."
+              mv "/tmp/vscode-${dir}-$$" "${userDst}/${dir}"
+            fi
+          '')
+          dirsToPreserve);
+      in ''
+        set -eu
+
+        ${backupCmds}
+
+        echo "Cleaning old directories..."
+        rm -rf "${userDst}"
+        rm -rf "${extDst}"
+
+        mkdir -p "${userDataDir}"
+        mkdir -p "${extDst}"
+
+        echo "Copying user settings from ${userSrc}..."
+        cp -r --dereference --no-preserve=mode,ownership ${userSrc} "${userDst}"
+
+        echo "Copying extensions from ${extSrc}..."
+        tar -h -C "${extSrc}" -cf - . | tar -C "${extDst}" -xf - --no-same-owner --no-same-permissions --mode='u=rX,go=rX'
+        chmod u+w -R "${extDst}" 2>/dev/null || true
+
+        ${restoreCmds}
+
+        echo "Restoring and merging data/User/globalStorage..."
+        if [ -e "/tmp/vscode-globalStorage-$$" ]; then
+          cp -rT "/tmp/vscode-globalStorage-$$" "${userDst}/globalStorage"
+
+          src_storage_json="${userSrc}/globalStorage/storage.json"
+          dst_storage_json="${userDst}/globalStorage/storage.json"
+
+          if [ -f "$src_storage_json" ] && [ -f "$dst_storage_json" ]; then
+            echo "Merging data/globalStorage/storage.json with new data..."
+            merged_json=$(mktemp)
+            jq -s '.[0] * .[1]' "$dst_storage_json" "$src_storage_json" > "$merged_json"
+            mv "$merged_json" "$dst_storage_json"
+            echo "Merge complete."
+          else
+            echo "Skipping storage.json merge: one or both files do not exist."
+          fi
+        else
+          echo "No backed-up globalStorage found to restore."
+        fi
+
+        echo "VSCode setup complete."
+      '';
+    };
+  in {
+    programs.vscode = {
+      enable = true;
+      package = pkg;
+      mutableExtensionsDir = false;
+    };
+
+    systemd.user.services.vscode-setup = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
+      Unit = {
+        Description = "VSCode Setup service";
+        After = ["graphical-session-pre.target"];
+        Wants = ["graphical-session-pre.target"];
+      };
+      Install.WantedBy = ["graphical-session.target"];
+      Service = {
+        Type = "oneshot";
+        UMask = "0022";
+        ExecStart = lib.getExe vscodeSetupScript;
+      };
+    };
+
+    # TODO: Test on real macOS system.
+    # For now, it just a simple mirror of the Linux service.
+    launchd.agents.vscode-setup = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
+      enable = true;
+      config = {
+        Program = [lib.getExe vscodeSetupScript];
+        RunAtLoad = true;
+        StandardOutPath = "${homeDir}/Library/Logs/vscode-setup.log";
+        StandardErrorPath = "${homeDir}/Library/Logs/vscode-setup.log";
+        WorkingDirectory = homeDir;
+      };
+    };
+  };
+}
modules/dev/editors.nix
@@ -0,0 +1,14 @@
+{config, ...}: {
+  flake.modules.homeManager.dev = _: {
+    imports = with config.flake.modules.homeManager; [
+      dev-helix
+      dev-vscode
+    ];
+
+    xdg.mimeApps.defaultApplications = let
+      editor = ["Helix.desktop" "code.desktop"];
+    in {
+      "text/plain" = editor;
+    };
+  };
+}
modules/dev/packages.nix
@@ -0,0 +1,75 @@
+{
+  flake.modules.homeManager.dev = {pkgs, ...}: {
+    home.packages = with pkgs; [
+      # === Data & Configuration Languages === #
+      # -- Nix
+      # nil # Nix LSP
+      nixd # Nix LSP
+      alejandra # Nix Formatter
+
+      # -- Json Like
+      taplo # TOML LSP / Formatter / Validator
+      nodePackages.yaml-language-server
+      actionlint # GitHub Actions linter
+      kdlfmt # KDL Formatter
+
+      # -- Documents
+      marksman # Markdown LSP
+      tinymist # Typst LSP
+      typstyle # Typst Formatter
+      mdx-language-server
+      texlab # LaTeX LSP
+      tex-fmt # LaTeX Formatter
+      pandoc # Document converter
+
+      # === General Purpose Languages === #
+      # -- C/C++
+      cmake
+      cmake-language-server
+      gnumake
+      checkmake
+      xmake
+      gcc
+      gdb
+      clang-tools
+      lldb
+
+      # -- Python
+      pipx # Install and Run Python Applications in Isolated Environments
+      uv # Python package manager in rust
+      pixi # Python package manager in rust, supports conda
+      ruff # Python LSP and formatter
+      python313
+
+      #-- rust
+      rustc
+      rust-analyzer
+      cargo # rust package manager
+      rustfmt
+      clippy # rust linter
+
+      # -- Lua
+      stylua
+      lua-language-server
+
+      #-- bash
+      nodePackages.bash-language-server
+      shellcheck
+      shfmt
+
+      # === Web Development === #
+      nodePackages.nodejs
+      pnpm
+      bun
+      deno
+
+      nodePackages.typescript
+      nodePackages.typescript-language-server
+      nodePackages.vscode-langservers-extracted # HTML/CSS/JSON/ESLint LSP extracted from vscode
+      nodePackages."@tailwindcss/language-server"
+      nodePackages."@astrojs/language-server"
+      stylelint-lsp
+      nodePackages.prettier
+    ];
+  };
+}
modules/dev/zellij.nix
@@ -0,0 +1,12 @@
+{
+  flake.modules.homeManager.dev = _: {
+    programs.zellij = {
+      enable = true;
+      settings = {
+        show_startup_tips = false;
+        show_release_notes = false;
+        default_shell = "fish";
+      };
+    };
+  };
+}
modules/hosts/chaser-kevin/default.nix
@@ -23,6 +23,7 @@
               (with config.flake.modules.homeManager; [
                 core
                 desktop
+                dev
                 user-hpcesia
               ])
               # TODO: remove below after migrated all config to Dendritic Pattern