Options for the {module} module.
{data.description}
51 | 52 |
53 | Type: {data.type}
54 |
57 | Default: {data.default.text}
58 |
61 | Declared in:{" "} 62 | 63 | {filenameFromLink(data.declarations[0])} 64 | 65 |
66 | > 67 | )) 68 | } 69 |
15 |
16 |
23 |
27 |
31 |
35 |
54 |
55 |
58 | Copyright © 2023-present Catppuccin Org 59 |
60 | 61 | 64 | -------------------------------------------------------------------------------- /pkgs/paws.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #! nix-shell --pure -i python3 -p python3 cacert nix 3 | import asyncio 4 | import argparse 5 | import json 6 | import subprocess 7 | from multiprocessing import cpu_count 8 | from datetime import datetime, timezone 9 | from pathlib import Path 10 | 11 | # Directory of the current script 12 | ROOT = Path(__file__).resolve().parent 13 | 14 | # Nix command to fetch a port with 15 | FETCH_ARGS = [ 16 | "--extra-experimental-features", 17 | "nix-command flakes", 18 | "flake", 19 | "prefetch", 20 | "--json", 21 | ] 22 | 23 | SOURCES_FILE = ROOT / "sources.json" 24 | 25 | 26 | fetch_port_sem = asyncio.Semaphore(cpu_count()) 27 | 28 | async def fetch_port(port: str) -> dict: 29 | """Fetch a Catppuccin port""" 30 | 31 | async with fetch_port_sem: 32 | repository = f"github:catppuccin/{port}" 33 | print(f"🔃 Fetching {repository}") 34 | 35 | command = FETCH_ARGS + [repository] 36 | proc = await asyncio.create_subprocess_exec("nix", *command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL) 37 | stdout, _ = await proc.communicate() 38 | 39 | if proc.returncode != 0: 40 | raise Exception(f"Failed to fetch {repository}") 41 | 42 | return json.loads(stdout) 43 | 44 | 45 | def update_file_with(old_sources: dict, new_sources: dict): 46 | """Update file with new sources only when needed""" 47 | if new_sources != old_sources: 48 | with open(SOURCES_FILE, "w") as f: 49 | json.dump(new_sources, f, indent=2, sort_keys=True) 50 | else: 51 | print("⚠ No updates made") 52 | 53 | 54 | async def handle_port(sources: dict, port: str, remove=False): 55 | """Handle updating a port in the given sources""" 56 | if remove: 57 | sources.pop(port, None) 58 | print(f"💣 Removed {port}") 59 | else: 60 | data = await fetch_port(port) 61 | locked = data["locked"] 62 | last_modified = datetime.fromtimestamp(int(locked["lastModified"]), tz = timezone.utc).strftime('%Y-%m-%d') 63 | sources[port] = {"rev": locked["rev"], "hash": data["hash"], "lastModified": last_modified} 64 | 65 | 66 | async def main(): 67 | cur_sources = dict() 68 | if SOURCES_FILE.exists(): 69 | with open(SOURCES_FILE, "r") as f: 70 | cur_sources = json.load(f) 71 | 72 | parser = argparse.ArgumentParser(prog="paws") 73 | parser.add_argument("ports", default=cur_sources.keys(), nargs="*") 74 | parser.add_argument("-r", "--remove", action="store_true") 75 | args = parser.parse_args() 76 | 77 | assert ( 78 | not args.remove or len(args.ports) > 0 79 | ), "Ports must be provided when passing --remove" 80 | 81 | new_sources = cur_sources.copy() 82 | await asyncio.gather( 83 | *[handle_port(new_sources, port, remove=args.remove) for port in args.ports] 84 | ) 85 | 86 | update_file_with(cur_sources, new_sources) 87 | 88 | print("✅ Done!") 89 | 90 | 91 | asyncio.run(main()) 92 | -------------------------------------------------------------------------------- /dev/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "catppuccin": { 4 | "inputs": { 5 | "nixpkgs": "nixpkgs" 6 | }, 7 | "locked": { 8 | "path": "../.", 9 | "type": "path" 10 | }, 11 | "original": { 12 | "path": "../.", 13 | "type": "path" 14 | }, 15 | "parent": [] 16 | }, 17 | "flake-utils": { 18 | "inputs": { 19 | "systems": "systems" 20 | }, 21 | "locked": { 22 | "lastModified": 1731533236, 23 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 24 | "owner": "numtide", 25 | "repo": "flake-utils", 26 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 27 | "type": "github" 28 | }, 29 | "original": { 30 | "owner": "numtide", 31 | "repo": "flake-utils", 32 | "type": "github" 33 | } 34 | }, 35 | "home-manager": { 36 | "inputs": { 37 | "nixpkgs": [ 38 | "nixpkgs" 39 | ] 40 | }, 41 | "locked": { 42 | "lastModified": 1764194569, 43 | "narHash": "sha256-iUM9ktarEzThkayyZrzQ7oycPshAY2XRQqVKz0xX/L0=", 44 | "owner": "nix-community", 45 | "repo": "home-manager", 46 | "rev": "9651819d75f6c7ffaf8a9227490ac704f29659f0", 47 | "type": "github" 48 | }, 49 | "original": { 50 | "owner": "nix-community", 51 | "repo": "home-manager", 52 | "type": "github" 53 | } 54 | }, 55 | "nixpkgs": { 56 | "locked": { 57 | "lastModified": 1763966396, 58 | "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", 59 | "owner": "NixOS", 60 | "repo": "nixpkgs", 61 | "rev": "5ae3b07d8d6527c42f17c876e404993199144b6a", 62 | "type": "github" 63 | }, 64 | "original": { 65 | "owner": "NixOS", 66 | "ref": "nixos-unstable", 67 | "repo": "nixpkgs", 68 | "type": "github" 69 | } 70 | }, 71 | "root": { 72 | "inputs": { 73 | "catppuccin": "catppuccin", 74 | "flake-utils": "flake-utils", 75 | "home-manager": "home-manager", 76 | "nixpkgs": [ 77 | "catppuccin", 78 | "nixpkgs" 79 | ] 80 | } 81 | }, 82 | "systems": { 83 | "locked": { 84 | "lastModified": 1681028828, 85 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 86 | "owner": "nix-systems", 87 | "repo": "default", 88 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 89 | "type": "github" 90 | }, 91 | "original": { 92 | "owner": "nix-systems", 93 | "repo": "default", 94 | "type": "github" 95 | } 96 | } 97 | }, 98 | "root": "root", 99 | "version": 7 100 | } 101 | -------------------------------------------------------------------------------- /modules/home-manager/zsh-syntax-highlighting.nix: -------------------------------------------------------------------------------- 1 | { catppuccinLib }: 2 | { 3 | options, 4 | config, 5 | lib, 6 | ... 7 | }: 8 | 9 | let 10 | inherit (config.catppuccin) sources; 11 | 12 | cfg = config.catppuccin.zsh-syntax-highlighting; 13 | oldCfg = config.programs.zsh.syntaxHighlighting.catppuccin; 14 | 15 | isSubmoduleOptionDefined = value: (builtins.tryEval value).success; 16 | in 17 | 18 | { 19 | options = { 20 | catppuccin.zsh-syntax-highlighting = catppuccinLib.mkCatppuccinOption { 21 | name = "Zsh Syntax Highlighting"; 22 | }; 23 | 24 | # `mkRenamedOptionModule` can't rename submodule options to top-level ones 25 | # Enter this nonsense 26 | # TODO: Abstract this 27 | 28 | # Extend the base submodule with our own options 29 | programs.zsh.syntaxHighlighting = { 30 | # Create options manually as `mkRenamedOptionModule` would 31 | catppuccin = { 32 | # But don't include the `trace` to each option since we do need to 33 | # check them with `isSubmoduleOptionDefined` 34 | enable = lib.mkOption { 35 | type = lib.types.bool; 36 | description = "Alias of `catppuccin.zsh-syntax-highlighting.enable`"; 37 | visible = false; 38 | }; 39 | 40 | flavor = lib.mkOption { 41 | type = catppuccinLib.types.flavor; 42 | description = "Alias of `catppuccin.zsh-syntax-highlighting.flavor`"; 43 | visible = false; 44 | }; 45 | }; 46 | }; 47 | }; 48 | 49 | config = lib.mkMerge [ 50 | (lib.mkIf (isSubmoduleOptionDefined oldCfg.enable) { 51 | # Place the warning, also like `mkRenamedOptionModule` normally would 52 | warnings = [ 53 | "The option `programs.zsh.syntaxHighlighting.catppuccin.enable` has been renamed to `catppuccin.zsh-syntax-highlighting.enable`." 54 | ]; 55 | 56 | # Actually alias the option 57 | catppuccin.zsh-syntax-highlighting.enable = oldCfg.enable; 58 | }) 59 | 60 | # Do it again for the flavor 61 | (lib.mkIf (isSubmoduleOptionDefined oldCfg.flavor) { 62 | warnings = [ 63 | "The option `programs.zsh.syntaxHighlighting.catppuccin.flavor` has been renamed to `catppuccin.zsh-syntax-highlighting.flavor`." 64 | ]; 65 | 66 | catppuccin.zsh-syntax-highlighting.flavor = oldCfg.flavor; 67 | }) 68 | 69 | # And this is our actual module 70 | (lib.mkIf cfg.enable { 71 | programs.zsh = 72 | let 73 | key = if options.programs.zsh ? initContent then "initContent" else "initExtra"; 74 | in 75 | { 76 | # NOTE: Backwards compatible mkOrder priority working with stable/unstable HM. 77 | "${key}" = lib.mkOrder (if key == "initContent" then 950 else 500) '' 78 | source '${sources.zsh-syntax-highlighting}/catppuccin_${cfg.flavor}-zsh-syntax-highlighting.zsh' 79 | ''; 80 | }; 81 | }) 82 | ]; 83 | } 84 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Nix 2 | result 3 | result-* 4 | repl-result-* 5 | gcroot/ 6 | 7 | ## Astro 8 | 9 | .astro/ 10 | 11 | ## Git 12 | 13 | .worktree/ 14 | 15 | ## NodeJS 16 | 17 | # Logs 18 | logs 19 | *.log 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | lerna-debug.log* 24 | 25 | # Diagnostic reports (https://nodejs.org/api/report.html) 26 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 27 | 28 | # Runtime data 29 | pids 30 | *.pid 31 | *.seed 32 | *.pid.lock 33 | 34 | # Directory for instrumented libs generated by jscoverage/JSCover 35 | lib-cov 36 | 37 | # Coverage directory used by tools like istanbul 38 | coverage 39 | *.lcov 40 | 41 | # nyc test coverage 42 | .nyc_output 43 | 44 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 45 | .grunt 46 | 47 | # Bower dependency directory (https://bower.io/) 48 | bower_components 49 | 50 | # node-waf configuration 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | build/Release 55 | 56 | # Dependency directories 57 | node_modules/ 58 | jspm_packages/ 59 | 60 | # Snowpack dependency directory (https://snowpack.dev/) 61 | web_modules/ 62 | 63 | # TypeScript cache 64 | *.tsbuildinfo 65 | 66 | # Optional npm cache directory 67 | .npm 68 | 69 | # Optional eslint cache 70 | .eslintcache 71 | 72 | # Optional stylelint cache 73 | .stylelintcache 74 | 75 | # Optional REPL history 76 | .node_repl_history 77 | 78 | # Output of 'npm pack' 79 | *.tgz 80 | 81 | # Yarn Integrity file 82 | .yarn-integrity 83 | 84 | # dotenv environment variable files 85 | .env 86 | .env.* 87 | !.env.example 88 | 89 | # parcel-bundler cache (https://parceljs.org/) 90 | .cache 91 | .parcel-cache 92 | 93 | # Next.js build output 94 | .next 95 | out 96 | 97 | # Nuxt.js build / generate output 98 | .nuxt 99 | dist 100 | 101 | # Gatsby files 102 | .cache/ 103 | # Comment in the public line in if your project uses Gatsby and not Next.js 104 | # https://nextjs.org/blog/next-9-1#public-directory-support 105 | # public 106 | 107 | # vuepress build output 108 | .vuepress/dist 109 | 110 | # vuepress v2.x temp and cache directory 111 | .temp 112 | .cache 113 | 114 | # Sveltekit cache directory 115 | .svelte-kit/ 116 | 117 | # vitepress build output 118 | **/.vitepress/dist 119 | 120 | # vitepress cache directory 121 | **/.vitepress/cache 122 | 123 | # Docusaurus cache and generated files 124 | .docusaurus 125 | 126 | # Serverless directories 127 | .serverless/ 128 | 129 | # FuseBox cache 130 | .fusebox/ 131 | 132 | # DynamoDB Local files 133 | .dynamodb/ 134 | 135 | # Firebase cache directory 136 | .firebase/ 137 | 138 | # TernJS port file 139 | .tern-port 140 | 141 | # Stores VSCode versions used for testing VSCode extensions 142 | .vscode-test 143 | 144 | # yarn v3 145 | .pnp.* 146 | .yarn/* 147 | !.yarn/patches 148 | !.yarn/plugins 149 | !.yarn/releases 150 | !.yarn/sdks 151 | !.yarn/versions 152 | 153 | # Vite logs files 154 | vite.config.js.timestamp-* 155 | vite.config.ts.timestamp-* 156 | -------------------------------------------------------------------------------- /cliff.toml: -------------------------------------------------------------------------------- 1 | # git-cliff ~ configuration file 2 | # https://git-cliff.org/docs/configuration 3 | # 4 | # To bump the changelog: 5 | # 6 | # ```console 7 | # $ TAG="x.y.z" 8 | # $ TAG=v"$TAG" 9 | # $ git-cliff --github-token (gh auth token) --prepend CHANGELOG.md --tag "$TAG" --unreleased 10 | # ``` 11 | 12 | [changelog] 13 | header = """ 14 | # Changelog\n 15 | """ 16 | 17 | body = """ 18 | {% if version -%} 19 | ## [{{ version | trim_start_matches(pat="v") }}](https://github.com/catppuccin/nix/releases/tag/{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }} 20 | {% else -%} 21 | ## [Unreleased] 22 | {% endif -%} 23 | 24 | {% for group, commits in commits | group_by(attribute="group") %} 25 | ### {{ group | striptags | trim | upper_first }} 26 | 27 | {% for commit in commits | filter(attribute="scope") | sort(attribute="scope") -%} 28 | - **{{ commit.scope }}**: {{ commit.message | trim }}\ 29 | {%- if commit.remote.username %} by @{{ commit.remote.username }}{% endif %} 30 | {% endfor -%} 31 | 32 | {% for commit in commits -%} 33 | {% if commit.scope -%} 34 | {% else -%} 35 | - {{ commit.message | trim }}\ 36 | {% if commit.remote.username %} by @{{ commit.remote.username }}{% endif %} 37 | {% endif -%} 38 | {% endfor -%} 39 | {% endfor -%} 40 | 41 | {% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} 42 | ### New Contributors 43 | 44 | {% endif -%} 45 | 46 | {% for contributor in github.contributors | filter(attribute="username") | filter(attribute="is_first_time", value=true) | sort(attribute="username") -%} 47 | * @{{ contributor.username }} made their first contribution\ 48 | {% if contributor.pr_number %} in #{{ contributor.pr_number }}{% endif %} 49 | {% endfor %}\n 50 | """ 51 | 52 | footer = """ 53 | 54 | """ 55 | 56 | trim = true 57 | 58 | postprocessors = [ 59 | # Issues/PR 60 | { pattern = "#([0-9]+)", replace = "[#${1}](https://github.com/catppuccin/nix/issues/${1})" }, 61 | # Commits 62 | { pattern = "([a-f0-9]{7})", replace = "[${1}](https://github.com/catppuccin/nix/commit/${1})" }, 63 | # GitHub Users 64 | { pattern = " @([a-zA-Z0-9-_]+)", replace = " [@${1}](https://github.com/${1})" } 65 | ] 66 | 67 | [git] 68 | commit_preprocessors = [ 69 | # Remove issue numbers 70 | { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" }, 71 | ] 72 | 73 | commit_parsers = [ 74 | # This commit message isn't properly escaped 75 | { sha = "aa3a9816e9d6bc361ab1156f1e7a850fc0b5f4f8", skip = true }, 76 | 77 | # Ignore bot PRs 78 | { field = "author.name", pattern = "\\[bot\\]", skip = true }, 79 | 80 | # Ignore some commits not matched by the above 81 | { message = "^docs: update docs for( ([a-f0-9]{7}))?$", skip = true }, 82 | { message = "^style: format ([a-f0-9]{7})?$", skip = true }, 83 | 84 | # Regular matches 85 | { message = "^(.*)!:", group = "🚨 Breaking Changes" }, 86 | { message = "^feat", group = "🚀 Features" }, 87 | { message = "^fix", group = "🐛 Bug Fixes" }, 88 | { message = "^revert", group = " ⏪ Reverted"}, 89 | { message = "^docs", group = "📚 Documentation" }, 90 | ] 91 | 92 | filter_commits = true 93 | 94 | [remote.github] 95 | owner = "catppuccin" 96 | repo = "nix" 97 | -------------------------------------------------------------------------------- /modules/home-manager/gtk.nix: -------------------------------------------------------------------------------- 1 | { catppuccinLib }: 2 | { 3 | config, 4 | lib, 5 | pkgs, 6 | ... 7 | }: 8 | 9 | let 10 | inherit (lib) 11 | concatStringsSep 12 | mkRenamedOptionModule 13 | mkRemovedOptionModule 14 | toList 15 | ; 16 | 17 | cfg = config.catppuccin.gtk; 18 | 19 | namespaceRenameModules = 20 | catppuccinLib.mkRenamedCatppuccinOptions { 21 | from = [ 22 | "gtk" 23 | "catppuccin" 24 | ]; 25 | to = "gtk"; 26 | accentSupport = true; 27 | } 28 | ++ catppuccinLib.mkRenamedCatppuccinOptions { 29 | from = [ 30 | "gtk" 31 | "catppuccin" 32 | "cursor" 33 | ]; 34 | to = "cursors"; 35 | accentSupport = true; 36 | } 37 | ++ [ 38 | (mkRenamedOptionModule 39 | [ 40 | "gtk" 41 | "catppuccin" 42 | "size" 43 | ] 44 | [ 45 | "catppuccin" 46 | "gtk" 47 | "size" 48 | ] 49 | ) 50 | 51 | (mkRenamedOptionModule 52 | [ 53 | "gtk" 54 | "catppuccin" 55 | "tweaks" 56 | ] 57 | [ 58 | "catppuccin" 59 | "gtk" 60 | "tweaks" 61 | ] 62 | ) 63 | 64 | (mkRenamedOptionModule 65 | [ 66 | "gtk" 67 | "catppuccin" 68 | "gnomeShellTheme" 69 | ] 70 | [ 71 | "catppuccin" 72 | "gtk" 73 | "gnomeShellTheme" 74 | ] 75 | ) 76 | 77 | (mkRenamedOptionModule 78 | [ 79 | "gtk" 80 | "catppuccin" 81 | "icon" 82 | ] 83 | [ 84 | "catppuccin" 85 | "gtk" 86 | "icon" 87 | ] 88 | ) 89 | ]; 90 | 91 | # Relative to `catppuccin.gtk` 92 | removedOptions = [ 93 | "enable" 94 | "flavor" 95 | "accent" 96 | 97 | "gnomeShellTheme" 98 | "size" 99 | "tweaks" 100 | ]; 101 | 102 | removedOptionModules = map ( 103 | optionPath: 104 | 105 | let 106 | attrPath = [ 107 | "catppuccin" 108 | "gtk" 109 | ] 110 | ++ toList optionPath; 111 | moduleName = concatStringsSep "." attrPath; 112 | in 113 | 114 | mkRemovedOptionModule attrPath '' 115 | `${moduleName}` was removed from catppuccin/nix, as the upstream port has been archived and began experiencing breakages. 116 | 117 | Please see https://github.com/catppuccin/gtk/issues/262 118 | '' 119 | ) removedOptions; 120 | in 121 | 122 | { 123 | imports = namespaceRenameModules ++ removedOptionModules; 124 | 125 | options.catppuccin.gtk = { 126 | icon = catppuccinLib.mkCatppuccinOption { 127 | name = "GTK modified Papirus icon theme"; 128 | 129 | accentSupport = true; 130 | }; 131 | }; 132 | 133 | config = lib.mkIf cfg.icon.enable { 134 | gtk.iconTheme = 135 | let 136 | # use the light icon theme for latte 137 | polarity = if cfg.icon.flavor == "latte" then "Light" else "Dark"; 138 | in 139 | { 140 | name = "Papirus-${polarity}"; 141 | package = pkgs.catppuccin-papirus-folders.override { inherit (cfg.icon) accent flavor; }; 142 | }; 143 | }; 144 | } 145 | -------------------------------------------------------------------------------- /docs/content/docs/Getting Started/stable.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Stable Nix 3 | description: Start using Catppuccin with Flakes, NixOS, and home-manager 4 | --- 5 | 6 | import { Tabs, TabItem } from "@astrojs/starlight/components"; 7 | 8 | When using stable Nix, we have a couple options for installing `catppuccin/nix`: 9 | 10 | ## With `npins` 11 | 12 | [`npins`](https://github.com/andir/npins) provides a way to easily ["pin"](https://nix.dev/tutorials/first-steps/towards-reproducibility-pinning-nixpkgs) and update external dependencies for your configurations. 13 | 14 | Assuming you have followed [their getting started guide](https://github.com/andir/npins#getting-started), you can run the following: 15 | 16 |