refactor: group stow packages into common, mac and kde

Split the packages by platform so each app stays an opt-in Stow package
under common/, mac/ or kde/. KDE gets its own Fastfetch, Helium and
Spectacle packages, and darwin-breeze becomes kde/theme. The READMEs
document stowing a whole group as well as individual packages.
This commit is contained in:
tri committed 2026-10-30 21:57:15 +07:00
1 parent 1e99a15f6c
commit 34e978e84c
74 files changed
+526 -145

No files matched your search

+30 -30
View File
@@ -1,54 +1,54 @@
# My personal opinionated dotfiles for `zsh`
# Personal dotfiles
## Requirement
- **GNU** `stow`
- `zsh` (I mean, duh)
These are my config files for macOS and KDE, managed with GNU Stow. You need `stow` and `zsh` installed.
## Installation
1. clone this repo to your `$HOME` and switch to cloned dir:
```sh
git -C $HOME clone https://github.com/vokhactri/.dotfiles.git && cd $HOME/.dotfiles
git clone https://github.com/vokhactri/.dotfiles.git "$HOME/.dotfiles"
cd "$HOME/.dotfiles"
```
2. use `stow` to symlink configs to `$HOME/.config`:
The packages are split into three groups:
- to symlink all config dirs
```sh
stow */
```
- to symlink only one config dir, for example `zsh`
```sh
stow zsh
```
- [common/](common/README.md) has Git, Micro, mpv, npm, Starship and Zsh.
- [mac/](mac/README.md) has Ghostty and the original Fastfetch config.
- [kde/](kde/README.md) has the Darwin Breeze theme, Helium, Konsole Fastfetch, Spectacle and tray icons.
3. reload your `zsh` to apply changes:
Install all of `common`, then the group for your platform:
```sh
exec zsh
(cd common && stow -t "$HOME" */)
(cd mac && stow -t "$HOME" */) # macOS
(cd kde && stow -t "$HOME" */) # KDE
```
### `darwin-breeze` + `helium` (theme and colors)
`*/` matches every package in the group. Each line runs in a subshell, so you stay in the repo root and can run them one after another. KDE needs a few more steps after this. They're in [`kde/README.md`](kde/README.md).
The Darwin Breeze Dark KDE color scheme and global theme, and the Helium, T3
Code, Ghostty, VS Code and Telegram themes generated from it. After stowing, apply it
once (Telegram imports its theme by hand):
### Picking packages
You don't have to install everything. List only the packages you want:
```sh
./darwin-breeze/apply.sh
stow -d common -t "$HOME" git zsh starship
stow -d mac -t "$HOME" ghostty
stow -d kde -t "$HOME" spectacle fastfetch
```
To change colors, edit `DarwinBreezeDark.colors` and run `apply.sh` again; see
[`darwin-breeze/README.md`](darwin-breeze/README.md).
`-d` tells Stow which group to read from. `-t` puts the symlinks in your home directory. You can mix packages from different groups. Fastfetch is the exception. Install `mac/fastfetch` or `kde/fastfetch`, never both.
### `tray-icons` (tray icons that match Breeze)
### Previewing and removing
Some icons need an extra step after `stow tray-icons` (a root step for
Ngó Sen); see [`tray-icons/README.md`](tray-icons/README.md).
`-n -v` prints what Stow would do and changes nothing. `-D` removes the symlinks. Pass the same `-d` and `-t` you used to install:
## Credit
```sh
stow -n -v -d kde -t "$HOME" spectacle
stow -D -d kde -t "$HOME" spectacle
```
Once the Zsh config is linked, run `exec zsh` to reload the shell.
## Credits
- [Machfiles](https://github.com/ChristianChiarulli/Machfiles/)
- [zsh_unplugged](https://github.com/mattmc3/zsh_unplugged)
+18
View File
@@ -0,0 +1,18 @@
# Common packages
Shared configuration for Git, Micro, mpv, npm, Starship, and Zsh.
From the repository root, install all shared packages:
```sh
(cd common && stow -t "$HOME" */)
```
Or choose individual packages:
```sh
stow -d common -t "$HOME" git
stow -d common -t "$HOME" zsh starship
```
Choose any of `git`, `micro`, `mpv`, `npm`, `starship`, and `zsh`.
Reload Zsh with `exec zsh` after installing its configuration.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env zsh
# Modern alternatives to traditional commands
alias cat='bat'
alias ls='lsd -A'
alias la='lsd -lA'
alias tree='lsd --tree'
alias nano='micro'
alias fetch='fastfetch'
# Global alias
alias \-g -- --help="--help | bat -plhelp"
docker() {
if command -v podman >/dev/null 2>&1; then
podman "$@"
else
command docker "$@"
fi
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
@@ -1,23 +0,0 @@
# Generated by darwin-breeze/build.py from DarwinBreezeDark.colors
background = #1e1e1e
foreground = #dddddd
cursor-color = #007aff
cursor-text = #ffffff
selection-background = #007aff
selection-foreground = #ffffff
palette = 0=#3b3b3b
palette = 1=#ff4a4c
palette = 2=#30d158
palette = 3=#ff9230
palette = 4=#419cff
palette = 5=#bf5af2
palette = 6=#64d2ff
palette = 7=#dddddd
palette = 8=#747474
palette = 9=#ff7779
palette = 10=#64dc82
palette = 11=#ffad64
palette = 12=#70b5ff
palette = 13=#cf83f5
palette = 14=#8bddff
palette = 15=#f1f1f1
+37
View File
@@ -0,0 +1,37 @@
# KDE Plasma packages
From the repository root, install all KDE packages:
```sh
(cd kde && stow -t "$HOME" */)
```
Or choose individual packages:
```sh
stow -d kde -t "$HOME" spectacle fastfetch
```
| Package | Details |
| ---------------------------------- | -------------------------------------------------------- |
| [theme](theme/README.md) | Darwin Breeze KDE colors and generated app themes |
| [helium](helium/README.md) | Browser flags and the generated Helium theme |
| [fastfetch](fastfetch/README.md) | Konsole configuration and a pre-scaled inline image logo |
| [spectacle](spectacle/README.md) | Screenshots to clipboard with a notification, no preview |
| [tray-icons](tray-icons/README.md) | Ngó Sen and qBittorrent tray icons |
Theme and Spectacle need an additional apply step after stowing their package:
```sh
# If you selected theme:
./kde/theme/apply.sh
# If you selected spectacle:
./kde/spectacle/apply.py
```
The apply scripts require a running KDE Plasma 6 session. Ngó Sen icons need
an additional install step described in the tray-icons README.
Packages can be selected independently. Helium includes its generated theme;
it does not require the KDE theme to be installed. Choose either
`kde/fastfetch` or `mac/fastfetch`; both own `~/.config/fastfetch/`.
@@ -0,0 +1 @@
_Ga=T,f=100,t=d,c=20,r=10,q=2,m=1;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\_Gm=1;2CzUiM53eKtBKKIrpLeyTzEjo54ifjUgpOfqaqxO8jgVGiX/zaZiv5kqvU+SQXJkYerUqQJ8bk6hBL52goHe22igSfbziCfL1U+A8b9pkDCguZ5MtWrGcHcPISB6wdTUCXr61qhS1Rz2toGIDGqAGlFZwkXD+4cTY/IXjiLOeTM831+7dm21Fl2BxbgZUkSoUB/8bzWV3tdEXvGvMd+K5SvE5Lg6hgi3xttErq7O+mFsWCNYmDoTAzUv4DbR7n+PHaXP107qKAyh0qXLw9HBCdUTYpDZpB6aZ9ZH3TopiAyPgJuzn9g34ukcj7jwTGGps69QKvHRVBgnHPbj+xw+fPhrIFQtyh7yeBUvBOH/salErz6t8qvyAL9UxBC348dPoHyFcrCx8JCYjybrP2Eq1v9sLN0RHZqB9MR2mjow7MvjRyk5obWUavXe39mCgN0E5sZuSEtNxoK543Ht4l48fXCeqJtu5/lVvHx6GfdvncTp45sxb/ZvaNemOXy9Auh+fIk5U4mdvxTxaV5UzM5erlEoUvRTsSdZ1v00RCg/chkuJW5cWBD9/9KQ73IZqV7liv7z+PETeHl7okpFY3lL5N93JitAqZvSCa4OoQQWD3g4xcLO0o9A4AVbKy/xaGflD3vrELKY676zFIfCqjGhjeDjGYgFc8YJsL14fAkP75zBnZzjuHXzGPWjot/JPYFHd8/i1VMC5YvruHFlP2ZMHY60Wsn0+x5wc4ghADanhdBKLA5jA3tYWVvi9u3bUI+HDELFKf+TAsBCnfA/aMhPnXeHnL2srHJl1Xfu0lmUPpOUeEXk/T3gsd4V7FubAOdPYtATdWun4MeBvTBn1hisXTUTmzfLine truncated
File renamed without changes.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 138 KiB

@@ -0,0 +1,80 @@
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/master/doc/json_schema.json",
"display": {
"key": {
"width": 10
},
"size": {
"binaryPrefix": "jedec"
},
"separator": ""
},
"logo": {
"type": "raw",
"source": "~/.config/fastfetch/albedo-konsole.kitty",
"width": 20,
"height": 10
},
"modules": [
"break",
{
"type": "os",
"key": "os",
"keyColor": "yellow",
"format": "{name}"
},
{
"type": "kernel",
"key": "ker",
"keyColor": "green"
},
{
"type": "packages",
"key": "pkgs",
"keyColor": "cyan"
},
{
"type": "shell",
"key": "sh",
"keyColor": "blue",
"format": "{pretty-name}"
},
{
"type": "wm",
"key": "wm",
"keyColor": "red",
"format": "{pretty-name}"
},
{
"type": "uptime",
"key": "up",
"keyColor": "green"
},
{
"type": "cpu",
"key": "cpu",
"keyColor": "red",
"format": "{name}"
},
{
"type": "memory",
"key": "ram",
"keyColor": "yellow",
"format": "{used} / {total}"
},
{
"type": "disk",
"key": "disk",
"keyColor": "cyan",
"folders": [
"/"
],
"format": "{size-used} / {size-total}"
},
"break",
{
"type": "custom",
"format": "\u001b[33m󰮯 \u001b[32m󰊠 \u001b[34m󰊠 \u001b[31m󰊠 \u001b[36m󰊠 \u001b[35m󰊠 \u001b[37m󰊠 \u001b[97m󰊠"
}
]
}
+3
View File
@@ -0,0 +1,3 @@
^/README.*
^/build\.py
__pycache__
+26
View File
@@ -0,0 +1,26 @@
# Fastfetch for Konsole
From the repository root:
```sh
stow -d kde -t "$HOME" fastfetch
```
The configuration, source PNG, and generated logo live in
`kde/fastfetch/.config/fastfetch/`. The generated logo is included, so a new
machine does not need to run the build script.
Choose either this package or `mac/fastfetch`; both own `~/.config/fastfetch/`.
Konsole needs inline image data instead of the original `kitty-direct` file
transfer. The committed `albedo-konsole.kitty` logo is pre-scaled to 20 × 10
cells to avoid grainy terminal scaling.
After changing `albedo.png`, the logo dimensions, or Konsole's font, update
the cell size in `build.py` and regenerate the logo from the repository root:
```sh
python3 kde/fastfetch/build.py
```
The build script requires `vipsthumbnail` from libvips.
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
"""Encode albedo.png as kitty graphics escapes for fastfetch's "raw" logo.
fastfetch's "kitty-direct" logo sends the terminal a file path (t=f). Konsole
only accepts inline data (t=d) and answers t=f with ENOTSUPPORTED, which lands
on the prompt as typed input. These files carry the PNG inline instead, with
q=2 so the terminal never answers at all.
.config/fastfetch/albedo-konsole.kitty pre-scaled for Konsole
Konsole stretches the image to the c x r cell box with nearest-neighbour
scaling, at logical (not device) pixel size, so a 512px source turns grainy.
The Konsole copy is resized with Lanczos to exactly that box, which leaves
Konsole nothing to scale. Rerun after changing the image, the logo size or the
Konsole font.
"""
import base64
import subprocess
import tempfile
from pathlib import Path
PKG = Path(__file__).resolve().parent
DIR = PKG / ".config/fastfetch"
SOURCE = DIR / "albedo.png"
# Logo size in cells; keep in sync with "width" and "height" in config.jsonc.
COLS, ROWS = 20, 10
# Konsole's cell size in logical pixels for JetBrainsMono Nerd Font 10pt
# (QFontMetrics: average advance of Konsole's REPCHAR, and height()).
KONSOLE_CELL = 8, 17
def encode(png, dst):
data = base64.b64encode(png)
chunks = [data[i : i + 4096] for i in range(0, len(data), 4096)]
out = bytearray()
for n, chunk in enumerate(chunks):
more = int(n < len(chunks) - 1)
if n == 0:
keys = b"a=T,f=100,t=d,c=%d,r=%d,q=2,m=%d" % (COLS, ROWS, more)
else:
keys = b"m=%d" % more
out += b"\x1b_G" + keys + b";" + chunk + b"\x1b\\"
dst.write_bytes(out)
def resize(width, height):
with tempfile.TemporaryDirectory() as tmp:
out = Path(tmp) / "out.png"
subprocess.run(
["vipsthumbnail", SOURCE, "--size", f"{width}x{height}!", "-o", out],
check=True,
)
return out.read_bytes()
encode(resize(COLS * KONSOLE_CELL[0], ROWS * KONSOLE_CELL[1]), DIR / "albedo-konsole.kitty")
@@ -2,5 +2,5 @@
--ozone-platform-hint=auto
--enable-features=AcceleratedVideoDecodeLinuxGL,AcceleratedVideoDecodeLinuxZeroCopyGL,AcceleratedVideoEncoder
# Darwin Breeze theme, generated by darwin-breeze/build.py
# Darwin Breeze theme, generated by kde/theme/build.py
--load-extension=~/.local/share/helium-themes/darwinbreeze
+2
View File
@@ -0,0 +1,2 @@
# Helium caches the built theme next to the manifest.
Cached Theme.pak
@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Darwin Breeze",
"version": "1.0",
"description": "Generated by darwin-breeze/build.py from DarwinBreezeDark.colors",
"description": "Generated by kde/theme/build.py from DarwinBreezeDark.colors",
"theme": {
"colors": {
"frame": [
+11
View File
@@ -0,0 +1,11 @@
# Helium
Browser flags and the generated Darwin Breeze theme. From the repository root:
```sh
stow -d kde -t "$HOME" helium
```
The theme files are included, so the KDE `theme` package does not need to be
stowed to use Helium's theme. To regenerate its colors from the shared color
scheme, run `python3 kde/theme/build.py` and restart Helium.
@@ -0,0 +1,61 @@
[Desktop Entry]
GenericName=Screenshot Capture Utility
Name=Spectacle
Comment=Take screenshots and screen recordings
Categories=Qt;KDE;Utility;
Keywords=snapshot;capture;print;screenshot;snipping;snipping tool;snip;
Exec=/usr/bin/spectacle --background --region --copy-image
Icon=spectacle
Type=Application
StartupNotify=false
Actions=FullScreenScreenShot;CurrentMonitorScreenShot;ActiveWindowScreenShot;RectangularRegionScreenShot;WindowUnderCursorScreenShot;RecordRegion;RecordScreen;RecordWindow;OpenWithoutScreenshot;
DBusActivatable=false
X-DBUS-StartupType=Unique
X-DBUS-ServiceName=org.kde.Spectacle
X-KDE-Shortcuts=Print,Meta+Shift+S
X-KDE-DBUS-Restricted-Interfaces=org.kde.KWin.ScreenShot2
X-KDE-Wayland-Interfaces=org_kde_plasma_window_management,zkde_screencast_unstable_v1
[Desktop Action FullScreenScreenShot]
Name=Capture Entire Desktop
Exec=/usr/bin/spectacle --background --copy-image -f
X-KDE-Shortcuts=Shift+Print
[Desktop Action CurrentMonitorScreenShot]
Name=Capture Current Monitor
Exec=/usr/bin/spectacle --background --copy-image -m
[Desktop Action ActiveWindowScreenShot]
Name=Capture Active Window
Exec=/usr/bin/spectacle --background --copy-image -a
X-KDE-Shortcuts=Meta+Print
[Desktop Action RectangularRegionScreenShot]
Name=Capture Rectangular Region
Exec=/usr/bin/spectacle --background --copy-image -r
X-KDE-Shortcuts=Meta+Shift+Print
[Desktop Action WindowUnderCursorScreenShot]
Name=Capture Window Under Cursor
Exec=/usr/bin/spectacle --background --copy-image -u
X-KDE-Shortcuts=Meta+Ctrl+Print
[Desktop Action RecordRegion]
Name=Start/Stop Region Recording
Exec=/usr/bin/spectacle -R region
X-KDE-Shortcuts=Meta+Shift+R,Meta+R
[Desktop Action RecordScreen]
Name=Start/Stop Screen Recording
Exec=/usr/bin/spectacle -R screen
X-KDE-Shortcuts=Meta+Alt+R
[Desktop Action RecordWindow]
Name=Start/Stop Window Recording
Exec=/usr/bin/spectacle -R window
X-KDE-Shortcuts=Meta+Ctrl+R
[Desktop Action OpenWithoutScreenshot]
Name=Launch without taking a screenshot
Exec=/usr/bin/spectacle -l
@@ -0,0 +1 @@
../applications/org.kde.spectacle.desktop
+4
View File
@@ -0,0 +1,4 @@
^/README.*
^/apply\.py
^/settings
__pycache__
+28
View File
@@ -0,0 +1,28 @@
# Spectacle
Capture screenshots in the background, copy the image to the clipboard, and
show a completion notification. Screenshots are not automatically saved.
```sh
stow -d kde -t "$HOME" spectacle
./kde/spectacle/apply.py
```
Requires Spectacle, KDE Plasma 6, GNU Stow, Python 3, `kwriteconfig6`,
`kbuildsycoca6`, `qdbus6`, and `gdbus`. Run the apply script in your KDE session.
Move any existing files reported as conflicts by Stow out of the way first.
- **Print** / **Meta+Shift+S**: select a rectangular region.
- **Shift+Print**: entire desktop.
- **Meta+Print**: active window.
- **Meta+Shift+Print**: select a rectangular region.
- **Meta+Ctrl+Print**: window under the cursor.
The desktop launcher and shortcut entry are managed by Stow. The files in
`settings/` are merged into `~/.config/spectaclerc` and `~/.config/klipperrc`
by `apply.py`, preserving unrelated preferences and window state. Klipper's
`SaveImages=true` keeps captured images available after Spectacle exits.
After editing settings or launcher commands, run `apply.py` again. It rebuilds
the cache using the KDE session's environment and reloads only Spectacle's
shortcut component, preserving custom key bindings.
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""Apply screenshot preferences and reload Spectacle's KDE shortcuts."""
import ast
import configparser
import os
from pathlib import Path
import re
import subprocess
HERE = Path(__file__).resolve().parent
COMPONENT = "org.kde.spectacle.desktop"
ACCEL = "/component/org_kde_spectacle_desktop"
def run(*args, **kwargs):
return subprocess.run(args, check=True, text=True, **kwargs)
def accel(path, method, *args):
return run(
"gdbus", "call", "--session", "--dest", "org.kde.kglobalaccel",
"--object-path", path, "--method", method, *args,
capture_output=True,
).stdout
def main():
for name in ("spectaclerc", "klipperrc"):
config = configparser.ConfigParser(interpolation=None)
config.optionxform = str
config.read(HERE / "settings" / name)
for group in config.sections():
for key, value in config[group].items():
run("kwriteconfig6", "--file", name, "--group", group,
"--key", key, value)
# T3's locale and XDG_DATA_DIRS can differ from the running KDE session.
# Build the cache KDE actually reads, rather than an app-specific cache.
session = dict(
line.split("=", 1) for line in
run("systemctl", "--user", "show-environment", capture_output=True)
.stdout.splitlines() if "=" in line
)
env = os.environ.copy()
for key in ("LANG", "LANGUAGE", "XDG_DATA_DIRS", "XDG_DATA_HOME",
"XDG_CACHE_HOME", "XDG_CONFIG_HOME"):
env.pop(key, None)
if key in session:
env[key] = session[key]
for key in set(env) | set(session):
if key.startswith("LC_"):
env.pop(key, None)
if key in session:
env[key] = session[key]
run("kbuildsycoca6", "--noincremental", env=env)
# Existing shortcut components retain their old Exec commands. Recreate
# only Spectacle's component, preserving any customized key bindings.
try:
output = accel(ACCEL, "org.kde.kglobalaccel.Component.allShortcutInfos")
except subprocess.CalledProcessError:
shortcuts = [] # Component has not been registered yet.
else:
shortcuts = ast.literal_eval(re.sub(r"@a[is] ", "", output))[0]
accel(ACCEL, "org.kde.kglobalaccel.Component.cleanUp")
action = [COMPONENT, "_reload_config", "Spectacle", "Reload configuration"]
accel("/kglobalaccel", "org.kde.KGlobalAccel.doRegister", repr(action))
accel("/kglobalaccel", "org.kde.KGlobalAccel.unregister",
COMPONENT, "_reload_config")
for name, label, component, friendly, context, _, keys, defaults in shortcuts:
if keys != defaults:
identity = component if context == "default" else f"{component}|{context}"
accel("/kglobalaccel", "org.kde.KGlobalAccel.setForeignShortcut",
repr([identity, name, friendly, label]), repr(keys))
run("qdbus6", "org.kde.klipper", "/klipper",
"org.kde.klipper.klipper.reloadConfig")
print("Applied Spectacle: copy to clipboard with a notification, no preview.")
if __name__ == "__main__":
main()
+2
View File
@@ -0,0 +1,2 @@
[General]
SaveImages=true
+3
View File
@@ -0,0 +1,3 @@
[General]
autoSaveImage=false
clipboardGroup=PostScreenshotCopyImage
@@ -1,5 +1,3 @@
# Helium caches the built theme next to the manifest.
Cached Theme.pak
__pycache__/
# Binary packages built by build.py.
*.vsix
@@ -1,9 +1,8 @@
# Build and apply scripts stay in the repo; only the dotfiles get linked.
^/README.*
^/\.gitignore
^/apply\.sh
^/build\.py
__pycache__
^/\.gitignore
^/t3
^/telegram
^/vscode
__pycache__
+12 -12
View File
@@ -1,7 +1,7 @@
# Darwin Breeze
Breeze for KDE Plasma 6 in the macOS dark system colors, with Helium, T3 Code,
Ghostty, VS Code and Telegram themed from the same colors.
VS Code and Telegram themed from the same colors.
Only the colors change. Breeze still draws the widgets and the title bar, and
the window buttons stay on the right.
@@ -18,8 +18,8 @@ the window buttons stay on the right.
From `~/.dotfiles`:
```sh
stow darwin-breeze helium
./darwin-breeze/apply.sh
stow -d kde -t "$HOME" theme
./kde/theme/apply.sh
```
`apply.sh` regenerates the app themes, applies the global theme, hides the
@@ -31,7 +31,7 @@ Reload Window.
Telegram has to import its theme by hand: Settings → Chat Settings → Chat
background → Choose from file, then pick
`darwin-breeze/telegram/DarwinBreezeDark.tdesktop-theme` and Apply. Import it
`kde/theme/telegram/DarwinBreezeDark.tdesktop-theme` and Apply. Import it
again after the colors change.
## Changing colors
@@ -39,19 +39,18 @@ again after the colors change.
The color scheme is the only place colors are defined:
```
.local/share/color-schemes/DarwinBreezeDark.colors
kde/theme/.local/share/color-schemes/DarwinBreezeDark.colors
```
Edit it, then run `./darwin-breeze/apply.sh` again. Everything else follows:
Edit it, then run `./kde/theme/apply.sh` again. Everything else follows:
| App | How it gets the colors |
| --- | --- |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Qt / KDE apps | the color scheme itself |
| GTK apps | Breeze GTK, which `kde-gtk-config` syncs from the scheme |
| Tray icons in `tray-icons/` | `ColorScheme-Text`, recolored by Plasma |
| Helium | `.local/share/helium-themes/`, generated by `build.py` |
| Tray icons in `kde/tray-icons/` | `ColorScheme-Text`, recolored by Plasma |
| Helium | `../helium/.local/share/helium-themes/`, generated by `build.py` |
| T3 Code | `t3/darwin-breeze.json`, generated by `build.py` and published with `t3 theme set` |
| Ghostty | `.config/ghostty/themes/`, generated by `build.py` |
| VS Code | `vscode/package.json` and `vscode/themes/`, generated by `build.py`, packed into `darwin-breeze.vsix` and installed by `apply.sh` |
| Telegram | `telegram/DarwinBreezeDark.tdesktop-theme`, built by `build.py` and imported by hand |
@@ -80,7 +79,7 @@ are built by `build.py` instead. Don't edit generated files by hand.
- Syntax colors are Pierre Dark's, the theme T3 Code highlights code with
(`vscode/base/pierre-dark.json`, taken from T3 Code). They are used as they
are, without gamma compensation, so code looks the same in both apps.
- The terminal uses the same 16 colors as Ghostty.
- The terminal palette is generated from the color scheme.
- VS Code is Electron, so its workbench colors get the same gamma
compensation as Helium and T3 Code.
- The `.vsix` isn't committed; `build.py` packs it from `vscode/`.
@@ -103,7 +102,8 @@ are built by `build.py` instead. Don't edit generated files by hand.
## Helium notes
- Helium loads the theme from `~/.local/share/helium-themes/darwinbreeze`
through `--load-extension` in `helium/.config/helium-browser-flags.conf`.
through `--load-extension` in `kde/helium/.config/helium-browser-flags.conf`.
Install it separately with `stow -d kde -t "$HOME" helium`.
- In Helium's compact layout the active tab and the toolbar segments on either
side share one theme color, so the toolbar is the same color as the tab
strip and inactive tabs are drawn lighter, as Dolphin does.
@@ -1,14 +1,14 @@
#!/usr/bin/env bash
# Regenerate the app themes from the color scheme and apply Darwin Breeze.
#
# Run `stow darwin-breeze helium` first.
# Run `stow -d kde -t "$HOME" theme` from the repo root first.
set -euo pipefail
here="$(cd "$(dirname "$0")" && pwd)"
data="${XDG_DATA_HOME:-$HOME/.local/share}"
if [ ! -e "$data/color-schemes/DarwinBreezeDark.colors" ]; then
echo "DarwinBreezeDark.colors is not installed; run 'stow darwin-breeze' in ~/.dotfiles" >&2
echo 'DarwinBreezeDark.colors is not installed; run: stow -d kde -t "$HOME" theme' >&2
exit 1
fi
+15 -37
View File
@@ -4,8 +4,7 @@
.local/share/color-schemes/DarwinBreezeDark.colors is the only place colors
are defined. This script derives from it:
.local/share/helium-themes/darwinbreeze/manifest.json
.config/ghostty/themes/DarwinBreezeDark
../helium/.local/share/helium-themes/darwinbreeze/manifest.json
t3/darwin-breeze.json (published to T3 Code by apply.sh)
telegram/DarwinBreezeDark.tdesktop-theme (not committed; imported into Telegram by hand)
vscode/ (packed into vscode/darwin-breeze.vsix, installed by apply.sh)
@@ -21,25 +20,25 @@ import zipfile
import zlib
from pathlib import Path
PKG = Path(__file__).resolve().parent
HERE = Path(__file__).resolve().parent
PKG = HERE
SCHEME = PKG / ".local/share/color-schemes/DarwinBreezeDark.colors"
HELIUM = PKG / ".local/share/helium-themes/darwinbreeze"
GHOSTTY = PKG / ".config/ghostty/themes/DarwinBreezeDark"
T3 = PKG / "t3/darwin-breeze.json"
HELIUM = PKG.parent / "helium/.local/share/helium-themes/darwinbreeze"
T3 = HERE / "t3/darwin-breeze.json"
# Telegram Desktop's built-in night theme, used as the base for every key the
# scheme has no role for: the colors file from telegramdesktop/tdesktop at
# 837b256, Telegram/Resources/night.tdesktop-theme.
TELEGRAM_BASE = PKG / "telegram/night.tdesktop-palette"
TELEGRAM = PKG / "telegram/DarwinBreezeDark.tdesktop-theme"
VSCODE = PKG / "vscode"
TELEGRAM_BASE = HERE / "telegram/night.tdesktop-palette"
TELEGRAM = HERE / "telegram/DarwinBreezeDark.tdesktop-theme"
VSCODE = HERE / "vscode"
VSCODE_THEME = "themes/DarwinBreezeDark-color-theme.json"
# VS Code's default dark theme, Dark 2026 (which includes Dark Modern, Dark+
# and Visual Studio Dark), from Code - OSS 1.138 extensions/theme-defaults.
# The workbench colors start from it.
VSCODE_UI = PKG / "vscode/base/2026-dark.json"
VSCODE_UI = VSCODE / "base/2026-dark.json"
# Pierre Dark, the syntax theme T3 Code highlights code with (from T3 Code
# 0.1.4). The editor uses its token colors as they are.
VSCODE_SYNTAX = PKG / "vscode/base/pierre-dark.json"
VSCODE_SYNTAX = VSCODE / "base/pierre-dark.json"
WHITE = (255, 255, 255)
@@ -125,7 +124,7 @@ def helium(color):
def ansi(color):
"""The 16 terminal colors, shared by Ghostty and the VS Code terminal."""
"""The 16 colors for the VS Code terminal."""
bg = color("View", "BackgroundNormal")
fg = color("View", "ForegroundNormal")
normal = [
@@ -146,25 +145,6 @@ def ansi(color):
return normal + bright
def ghostty(color):
bg = color("View", "BackgroundNormal")
fg = color("View", "ForegroundNormal")
accent = color("Selection", "BackgroundNormal")
accent_text = color("Selection", "ForegroundNormal")
lines = [
f"# Generated by darwin-breeze/build.py from {SCHEME.name}",
f"background = {hexc(bg)}",
f"foreground = {hexc(fg)}",
f"cursor-color = {hexc(accent)}",
f"cursor-text = {hexc(accent_text)}",
f"selection-background = {hexc(accent)}",
f"selection-foreground = {hexc(accent_text)}",
]
lines += [f"palette = {i}={hexc(c)}" for i, c in enumerate(ansi(color))]
return "\n".join(lines) + "\n"
def t3(color):
"""Every color slot of a T3 Code theme, mapped onto a scheme role."""
window, window_text = color("Window", "BackgroundNormal"), color("Window", "ForegroundNormal")
@@ -432,7 +412,7 @@ def telegram_theme(color):
pinned = telegram(color)
seen = set()
out = [f"// Generated by darwin-breeze/build.py from {SCHEME.name}"]
out = [f"// Generated by kde/theme/build.py from {SCHEME.name}"]
for line in base.splitlines():
m = line_re.match(line)
if m:
@@ -565,7 +545,7 @@ def vscode_files(color):
package = {
"name": "darwin-breeze",
"displayName": "Darwin Breeze",
"description": f"Generated by darwin-breeze/build.py from {SCHEME.name}",
"description": f"Generated by kde/theme/build.py from {SCHEME.name}",
"publisher": "trivk",
"version": "1.0.0",
"engines": {"vscode": "^1.70.0"},
@@ -645,7 +625,7 @@ def write(path, data):
if path.exists() and path.read_bytes() == data:
return False
path.write_bytes(data)
print(f"wrote {path.relative_to(PKG)}")
print(f"wrote {path.relative_to(PKG.parent)}")
return True
@@ -655,15 +635,13 @@ def main():
"manifest_version": 3,
"name": "Darwin Breeze",
"version": "1.0",
"description": f"Generated by darwin-breeze/build.py from {SCHEME.name}",
"description": f"Generated by kde/theme/build.py from {SCHEME.name}",
"theme": {"colors": helium(color)},
}
if write(HELIUM / "manifest.json", json.dumps(manifest, indent=2) + "\n"):
# Helium would keep showing the old colors from its cache.
(HELIUM / "Cached Theme.pak").unlink(missing_ok=True)
write(GHOSTTY, ghostty(color))
theme = {"version": 1, "name": "Darwin Breeze", "appearance": "dark", "colors": t3(color)}
write(T3, json.dumps(theme, indent=2) + "\n")
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
{
"name": "darwin-breeze",
"displayName": "Darwin Breeze",
"description": "Generated by darwin-breeze/build.py from DarwinBreezeDark.colors",
"description": "Generated by kde/theme/build.py from DarwinBreezeDark.colors",
"publisher": "trivk",
"version": "1.0.0",
"engines": {
File renamed without changes.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 426 B

After

Width:  |  Height:  |  Size: 426 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 426 B

After

Width:  |  Height:  |  Size: 426 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 440 B

After

Width:  |  Height:  |  Size: 440 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 440 B

After

Width:  |  Height:  |  Size: 440 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 434 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 434 B

@@ -1,7 +1,7 @@
# Tray icons that match Breeze
```sh
stow tray-icons
stow -d kde -t "$HOME" tray-icons
```
Some icons need one more step after stowing; see below.
+21
View File
@@ -0,0 +1,21 @@
# macOS packages
From the repository root, install all macOS packages:
```sh
(cd mac && stow -t "$HOME" */)
```
Or choose individual packages:
```sh
stow -d mac -t "$HOME" ghostty
stow -d mac -t "$HOME" fastfetch
```
- `ghostty`: JetBrainsMono Nerd Font and Ghostty's bundled SpaceGray Eighties theme.
- `fastfetch`: the original configuration, with a `kitty-direct` image logo.
Its source PNG is included in `fastfetch/.config/fastfetch/`.
These packages are independent. Choose either `mac/fastfetch` or
`kde/fastfetch`; both own `~/.config/fastfetch/`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

@@ -1,3 +1,3 @@
font-family = "JetBrainsMono Nerd Font"
theme = DarwinBreezeDark
theme = "SpaceGray Eighties"
cursor-style = bar
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env zsh
# Modern alternatives to traditional commands
alias cat='bat'
alias ls='lsd -A'
alias la='lsd -lA'
alias tree='lsd --tree'
alias nano='micro'
alias fetch='fastfetch'
alias claudex='ANTHROPIC_BASE_URL="$(pass tk_ai/cc_url)" \
ANTHROPIC_AUTH_TOKEN="$(pass tk_ai/api_key)" \
ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5.6-sol \
ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-5.6-terra \
ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5.6-luna \
CLAUDE_CODE_DISABLE_1M_CONTEXT=1 \
CLAUDE_CODE_SUBAGENT_MODEL=gpt-5.6-sol \
CLAUDE_CODE_ALWAYS_ENABLE_EFFORT=1 \
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY=3 \
ENABLE_TOOL_SEARCH=false \
claude --model gpt-5.6-sol'
# Global alias
alias \-g -- --help="--help | bat -plhelp"
docker() {
if command -v podman >/dev/null 2>&1; then
podman "$@"
else
command docker "$@"
fi
}