mirror of
https://github.com/bgrolleman/dotfiles.git
synced 2026-08-09 04:31:44 +02:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be54b6b0ec | ||
|
|
f52815cc65 | ||
|
|
0835211ae9 | ||
|
|
865a1923f5 | ||
|
|
279ca4a247 | ||
|
|
4f6643fd8e | ||
|
|
772c26f0b1 | ||
|
|
35349a426d |
@@ -0,0 +1,64 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## What This Repo Is
|
||||
|
||||
Personal dotfiles for a Linux desktop, currently running **Niri** (Wayland compositor) with **Noctalia** as the desktop shell. There are legacy X11 configs (i3, polybar, picom) that are no longer the primary setup.
|
||||
|
||||
## Deployment
|
||||
|
||||
Configs are deployed by symlinking into `~/.config/` and `~/.profile`:
|
||||
|
||||
```bash
|
||||
bash ~/.dotfiles/setup.sh
|
||||
```
|
||||
|
||||
The script is idempotent — it skips links that already exist. After adding a new top-level config directory, add a `configlink <dirname>` line to `setup.sh`.
|
||||
|
||||
## Installing Desktop Applications
|
||||
|
||||
```bash
|
||||
cd ansible.desktop
|
||||
./install-desktop-toolsontech.sh
|
||||
```
|
||||
|
||||
This installs ansible if missing, then runs the playbook. Tasks are split by category in `ansible.desktop/tasks/`.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Niri (Wayland compositor)
|
||||
`niri/config.kdl` is just includes — the real config lives in `niri/cfg/`:
|
||||
- `input.kdl` — keyboard/mouse/touchpad settings
|
||||
- `keybinds.kdl` — all keybindings
|
||||
- `layout.kdl` — gaps, border, window sizing
|
||||
- `display.kdl` — monitor layout and scaling
|
||||
- `autostart.kdl` — apps launched on compositor start
|
||||
- `rules.kdl` — window-specific rules
|
||||
- `animation.kdl`, `misc.kdl` — tweaks
|
||||
|
||||
Edit the relevant split file, not `config.kdl` itself.
|
||||
|
||||
### Noctalia (desktop shell / bar)
|
||||
All settings live in `noctalia/settings.json` (JSON, edited by the Noctalia GUI or directly). Colorschemes are in `noctalia/colorschemes/` and plugins in `noctalia/plugins/`.
|
||||
|
||||
### Neovim
|
||||
Uses **LazyVIM** framework. Entry point is `nvim/init.lua` which bootstraps lazy.nvim via `nvim/lua/config/lazy.lua`.
|
||||
|
||||
- `nvim/lua/config/` — core config (options, keymaps, autocmds)
|
||||
- `nvim/lua/plugins/` — plugin overrides/additions on top of LazyVIM defaults
|
||||
- `nvim/lua/colorschemes/` — colorscheme configs
|
||||
|
||||
LazyVIM handles most plugin management; only deviations from LazyVIM defaults need entries in `lua/plugins/`.
|
||||
|
||||
### tmux
|
||||
`tmux/tmux.conf` + catppuccin theme as a git submodule at `tmux/plugins/catppuccin/tmux`. After cloning, initialize the submodule:
|
||||
|
||||
```bash
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
### Shell / profile
|
||||
`profile` is symlinked to `~/.profile`. It sets up SSH keys via `keychain` and defines the `notes` alias (attaches/creates a tmux session with nvim opening `~/Notes/Personal`).
|
||||
|
||||
`zoxide.bash` provides shell integration for zoxide (directory jumping) — sourced separately, not via `profile`.
|
||||
+44
-1
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"theme": "dark",
|
||||
"permissions": {
|
||||
"defaultMode": "auto"
|
||||
},
|
||||
"hooks": {
|
||||
"Stop": [
|
||||
{
|
||||
@@ -21,5 +23,46 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"statusLine": {
|
||||
"type": "command",
|
||||
"command": "bash \"/home/bgrolleman/.claude/statusline-command.sh\""
|
||||
},
|
||||
"enabledPlugins": {
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"lua-lsp@claude-plugins-official": true,
|
||||
"ponytail@ponytail": true
|
||||
},
|
||||
"extraKnownMarketplaces": {
|
||||
"ponytail": {
|
||||
"source": {
|
||||
"source": "github",
|
||||
"repo": "DietrichGebert/ponytail"
|
||||
}
|
||||
},
|
||||
"caveman": {
|
||||
"source": {
|
||||
"source": "github",
|
||||
"repo": "juliusbrussee/caveman"
|
||||
}
|
||||
}
|
||||
},
|
||||
"effortLevel": "high",
|
||||
"advisorModel": "opus",
|
||||
"voice": {
|
||||
"enabled": true,
|
||||
"mode": "hold"
|
||||
},
|
||||
"theme": "dark",
|
||||
"agentPushNotifEnabled": true,
|
||||
"skipAutoPermissionPrompt": true,
|
||||
"voiceEnabled": true,
|
||||
"mcpServers": {
|
||||
"comfyui-image-gen": {
|
||||
"command": "/home/bgrolleman/Project/ComfyUI/.venv/bin/python",
|
||||
"args": [
|
||||
"/home/bgrolleman/Project/ComfyUI/mcp_server.py"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
# Claude Code status line
|
||||
# Shows: model display name, a progress bar for context-window tokens
|
||||
# remaining in this session, current git branch, active subagent (if any),
|
||||
# and enabled plugins (read from ~/.claude/settings.json).
|
||||
|
||||
input=$(cat)
|
||||
|
||||
model=$(echo "$input" | jq -r '.model.display_name // "unknown"')
|
||||
cwd=$(echo "$input" | jq -r '.workspace.current_dir // empty')
|
||||
remaining=$(echo "$input" | jq -r '.context_window.remaining_percentage // empty')
|
||||
agent_name=$(echo "$input" | jq -r '.agent.name // empty')
|
||||
|
||||
# --- Colors (kept modest; Claude Code renders the status line dimmed) ---
|
||||
c_model='\033[36m' # cyan
|
||||
c_bar='\033[32m' # green
|
||||
c_branch='\033[33m' # yellow
|
||||
c_agent='\033[35m' # magenta
|
||||
c_plugin='\033[34m' # blue
|
||||
c_reset='\033[0m'
|
||||
|
||||
# --- Git branch (skip optional locks; silent if not a repo) ---
|
||||
branch=""
|
||||
if [ -n "$cwd" ]; then
|
||||
branch=$(git --no-optional-locks -C "$cwd" branch --show-current 2>/dev/null)
|
||||
fi
|
||||
|
||||
# --- Enabled plugins, read from settings.json (not present on stdin) ---
|
||||
settings_file="$HOME/.claude/settings.json"
|
||||
plugins=""
|
||||
if [ -f "$settings_file" ]; then
|
||||
plugins=$(jq -r '.enabledPlugins // {} | to_entries[] | select(.value == true) | .key | split("@")[0]' "$settings_file" 2>/dev/null | paste -sd, -)
|
||||
fi
|
||||
|
||||
# --- Context-window remaining-tokens progress bar ---
|
||||
bar=""
|
||||
if [ -n "$remaining" ]; then
|
||||
pct=${remaining%.*}
|
||||
[ -z "$pct" ] && pct=0
|
||||
[ "$pct" -lt 0 ] 2>/dev/null && pct=0
|
||||
[ "$pct" -gt 100 ] 2>/dev/null && pct=100
|
||||
total_blocks=10
|
||||
filled=$(( pct * total_blocks / 100 ))
|
||||
[ "$filled" -gt "$total_blocks" ] && filled=$total_blocks
|
||||
[ "$filled" -lt 0 ] && filled=0
|
||||
empty=$(( total_blocks - filled ))
|
||||
bar="["
|
||||
i=0
|
||||
while [ "$i" -lt "$filled" ]; do bar="${bar}█"; i=$((i + 1)); done
|
||||
i=0
|
||||
while [ "$i" -lt "$empty" ]; do bar="${bar}░"; i=$((i + 1)); done
|
||||
bar="${bar}] ${pct}% left"
|
||||
fi
|
||||
|
||||
# --- Assemble the status line ---
|
||||
printf "${c_model}%s${c_reset}" "$model"
|
||||
|
||||
if [ -n "$bar" ]; then
|
||||
printf " ${c_bar}%s${c_reset}" "$bar"
|
||||
fi
|
||||
|
||||
if [ -n "$branch" ]; then
|
||||
printf " ${c_branch}git:%s${c_reset}" "$branch"
|
||||
fi
|
||||
|
||||
if [ -n "$agent_name" ]; then
|
||||
printf " ${c_agent}agent:%s${c_reset}" "$agent_name"
|
||||
fi
|
||||
|
||||
if [ -n "$plugins" ]; then
|
||||
printf " ${c_plugin}plugins:%s${c_reset}" "$plugins"
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
@@ -0,0 +1,15 @@
|
||||
# Start keychain and source SSH agent variables for all private keys in ~/.ssh
|
||||
if status is-interactive
|
||||
if type -q keychain
|
||||
set -l _ssh_keys
|
||||
for _pub in ~/.ssh/*.pub
|
||||
set -l _key (string replace -r '\.pub$' '' $_pub)
|
||||
if test -f $_key
|
||||
set -a _ssh_keys $_key
|
||||
end
|
||||
end
|
||||
if test (count $_ssh_keys) -gt 0
|
||||
keychain --eval --quiet $_ssh_keys | source
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
# Machine-specific config (secrets, local overrides) — not tracked in dotfiles
|
||||
if test -f ~/.config/fish/local.fish
|
||||
source ~/.config/fish/local.fish
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
profile ultrawide-hdmi {
|
||||
output "DP-1" mode 5120x1440 position 0,0 scale 1
|
||||
output "HDMI-A-1" mode 1920x1080 position 1600,1440 scale 1
|
||||
}
|
||||
|
||||
profile ultrawide {
|
||||
output "DP-1" mode 5120x1440 position 0,0 scale 1
|
||||
}
|
||||
@@ -2,3 +2,4 @@
|
||||
// https://github.com/YaLTeR/niri/wiki/Configuration:-Miscellaneous#spawn-sh-at-startup
|
||||
|
||||
spawn-sh-at-startup "qs -c noctalia-shell"
|
||||
spawn-at-startup "kanshi"
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ input {
|
||||
}
|
||||
|
||||
touchpad {
|
||||
//tap // Enable tap-to-click
|
||||
tap // Enable tap-to-click
|
||||
dwt
|
||||
scroll-method "two-finger"
|
||||
tap-button-map "left-right-middle"
|
||||
|
||||
+17
-14
@@ -9,12 +9,16 @@ binds {
|
||||
//Mod+Shift+ESCAPE { show-hotkey-overlay; }
|
||||
|
||||
Mod+h { show-hotkey-overlay; }
|
||||
Mod+Shift+S { spawn-sh "flameshot gui"; }
|
||||
Mod+Shift+S { spawn-sh "grim -g \"$(slurp)\" - | satty --filename - -o ~/Pictures/Screenshots/satty-%Y%m%d-%H%M%S.png --copy-command wl-copy --actions-on-enter save-to-clipboard --save-after-copy"; }
|
||||
|
||||
// ─── Applications ───
|
||||
Alt+Return hotkey-overlay-title="Open Terminal: Alacritty" { spawn "alacritty"; }
|
||||
Mod+G hotkey-overlay-title="Focus: Gmail" { spawn-sh "$HOME/.config/niri/focus-or-launch.sh chrome-fmgjjmmmlfnkbppncabfkddbjimcfncm-Default /opt/helium-browser-bin/helium-wrapper --profile-directory=Default --app-id=fmgjjmmmlfnkbppncabfkddbjimcfncm"; }
|
||||
Mod+W hotkey-overlay-title="Focus: WhatsApp" { spawn-sh "$HOME/.config/niri/focus-or-launch.sh chrome-hnpfjngllnobngcgfapefoaidbinmjnm-Default /opt/helium-browser-bin/helium-wrapper --profile-directory=Default --app-id=hnpfjngllnobngcgfapefoaidbinmjnm"; }
|
||||
Mod+D hotkey-overlay-title="Focus: Todoist" { spawn-sh "$HOME/.config/niri/focus-or-launch.sh chrome-dlgohinmglaoopaiplliaecdpmnepmga-Default /opt/helium-browser-bin/helium-wrapper --profile-directory=Default --app-id=dlgohinmglaoopaiplliaecdpmnepmga"; }
|
||||
//Mod+CTRL+Return hotkey-overlay-title="Open App Launcher: noctalia launcher" { spawn-sh "qs -c noctalia-shell ipc call launcher toggle"; }
|
||||
Alt+Space hotkey-overlay-title="Open App Launcher: noctalia launcher" { spawn-sh "qs -c noctalia-shell ipc call launcher toggle"; }
|
||||
Alt+Shift+Space hotkey-overlay-title="Open Window Search: noctalia launcher" { spawn-sh "qs -c noctalia-shell ipc call launcher windows"; }
|
||||
Mod+B hotkey-overlay-title="Open Browser: helium" { spawn "helium-browser"; }
|
||||
Mod+L hotkey-overlay-title="Lock Screen: noctalia lock" { spawn-sh "qs -c noctalia-shell ipc call lockScreen lock"; }
|
||||
Mod+Shift+Q hotkey-overlay-title="Session Menu: noctalia sessionMenu" { spawn-sh "qs -c noctalia-shell ipc call sessionMenu toggle"; }
|
||||
@@ -98,22 +102,22 @@ binds {
|
||||
// Mod+CTRL+Shift+WheelScrollDown { move-column-right; }
|
||||
// Mod+CTRL+Shift+WheelScrollUp { move-column-left; }
|
||||
|
||||
Alt+1 { focus-workspace 1; }
|
||||
Alt+2 { focus-workspace 2; }
|
||||
Alt+3 { focus-workspace 3; }
|
||||
Alt+4 { focus-workspace 4; }
|
||||
Alt+5 { focus-workspace 5; }
|
||||
Alt+6 { focus-workspace 6; }
|
||||
Alt+1 { focus-workspace "1"; }
|
||||
Alt+2 { focus-workspace "2"; }
|
||||
Alt+3 { focus-workspace "3"; }
|
||||
Alt+4 { focus-workspace "4"; }
|
||||
Alt+5 { focus-workspace "5"; }
|
||||
Alt+6 { focus-workspace "6"; }
|
||||
Alt+7 { focus-workspace 7; }
|
||||
Alt+8 { focus-workspace 8; }
|
||||
Alt+9 { focus-workspace 9; }
|
||||
|
||||
Alt+Shift+1 { move-column-to-workspace 1; }
|
||||
Alt+Shift+2 { move-column-to-workspace 2; }
|
||||
Alt+Shift+3 { move-column-to-workspace 3; }
|
||||
Alt+Shift+4 { move-column-to-workspace 4; }
|
||||
Alt+Shift+5 { move-column-to-workspace 5; }
|
||||
Alt+Shift+6 { move-column-to-workspace 6; }
|
||||
Alt+Shift+1 { move-column-to-workspace "1"; }
|
||||
Alt+Shift+2 { move-column-to-workspace "2"; }
|
||||
Alt+Shift+3 { move-column-to-workspace "3"; }
|
||||
Alt+Shift+4 { move-column-to-workspace "4"; }
|
||||
Alt+Shift+5 { move-column-to-workspace "5"; }
|
||||
Alt+Shift+6 { move-column-to-workspace "6"; }
|
||||
Alt+Shift+7 { move-column-to-workspace 7; }
|
||||
Alt+Shift+8 { move-column-to-workspace 8; }
|
||||
Alt+Shift+9 { move-column-to-workspace 9; }
|
||||
@@ -132,7 +136,6 @@ binds {
|
||||
// ─── Modes ───
|
||||
Mod+T { toggle-window-floating; }
|
||||
Mod+F { fullscreen-window; }
|
||||
Mod+W { toggle-column-tabbed-display; }
|
||||
|
||||
// ─── Screenshots ───
|
||||
CTRL+Shift+1 { screenshot; }
|
||||
|
||||
+3
-1
@@ -5,7 +5,9 @@
|
||||
background-color "transparent" // <- needed for noctalia-shell to set wallpaper
|
||||
|
||||
//default-column-width { proportion 0.95; }
|
||||
default-column-width { proportion 0.40; }
|
||||
//default-column-width { proportion 0.40; }
|
||||
//default-column-width {}
|
||||
default-column-width { fixed 1200; }
|
||||
|
||||
preset-column-widths {
|
||||
proportion 0.33333
|
||||
|
||||
+18
-2
@@ -1,2 +1,18 @@
|
||||
workspace "browser"
|
||||
workspace "chat"
|
||||
workspace "1" {
|
||||
open-on-output "DP-1"
|
||||
}
|
||||
workspace "2" {
|
||||
open-on-output "DP-1"
|
||||
}
|
||||
workspace "3" {
|
||||
open-on-output "DP-1"
|
||||
}
|
||||
workspace "4" {
|
||||
open-on-output "DP-1"
|
||||
}
|
||||
workspace "5" {
|
||||
open-on-output "DP-1"
|
||||
}
|
||||
workspace "6" {
|
||||
open-on-output "HDMI-A-1"
|
||||
}
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# Focus an existing window by app-id, or launch it if not found.
|
||||
# If the target window is already focused, return to the previous window.
|
||||
# Usage: focus-or-launch.sh <app-id> <launch-command...>
|
||||
APP_ID="$1"
|
||||
shift
|
||||
|
||||
WINDOWS=$(niri msg -j windows)
|
||||
FOCUSED_ID=$(echo "$WINDOWS" | jq -r '.[] | select(.is_focused == true) | .id')
|
||||
TARGET_ID=$(echo "$WINDOWS" | jq -r --arg app "$APP_ID" '.[] | select(.app_id == $app) | .id' | head -1)
|
||||
|
||||
PREV_FILE="/tmp/niri-focus-prev-${APP_ID}"
|
||||
|
||||
if [ "$FOCUSED_ID" = "$TARGET_ID" ]; then
|
||||
if [ -f "$PREV_FILE" ]; then
|
||||
niri msg action focus-window --id "$(cat "$PREV_FILE")" 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
echo "$FOCUSED_ID" > "$PREV_FILE"
|
||||
if [ -n "$TARGET_ID" ]; then
|
||||
niri msg action focus-window --id "$TARGET_ID"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
||||
fi
|
||||
+22
-9
@@ -60,6 +60,7 @@
|
||||
"middleClickCommand": "",
|
||||
"middleClickFollowMouse": false,
|
||||
"monitors": [
|
||||
"DP-1"
|
||||
],
|
||||
"mouseWheelAction": "none",
|
||||
"mouseWheelWrap": true,
|
||||
@@ -149,7 +150,7 @@
|
||||
"hideUnoccupied": false,
|
||||
"iconScale": 0.8,
|
||||
"id": "Workspace",
|
||||
"labelMode": "index",
|
||||
"labelMode": "name",
|
||||
"occupiedColor": "secondary",
|
||||
"pillSize": 0.6,
|
||||
"showApplications": false,
|
||||
@@ -182,6 +183,18 @@
|
||||
"pinned": [
|
||||
]
|
||||
},
|
||||
{
|
||||
"displayMode": "onhover",
|
||||
"iconColor": "none",
|
||||
"id": "Network",
|
||||
"textColor": "none"
|
||||
},
|
||||
{
|
||||
"displayMode": "onhover",
|
||||
"iconColor": "none",
|
||||
"id": "Bluetooth",
|
||||
"textColor": "none"
|
||||
},
|
||||
{
|
||||
"hideWhenZero": false,
|
||||
"hideWhenZeroUnread": false,
|
||||
@@ -341,23 +354,23 @@
|
||||
"groupClickAction": "cycle",
|
||||
"groupContextMenuMode": "extended",
|
||||
"groupIndicatorStyle": "dots",
|
||||
"inactiveIndicators": false,
|
||||
"inactiveIndicators": true,
|
||||
"indicatorColor": "primary",
|
||||
"indicatorOpacity": 0.6,
|
||||
"indicatorThickness": 3,
|
||||
"launcherIcon": "",
|
||||
"launcherIconColor": "none",
|
||||
"launcherPosition": "end",
|
||||
"launcherUseDistroLogo": false,
|
||||
"launcherPosition": "start",
|
||||
"launcherUseDistroLogo": true,
|
||||
"monitors": [
|
||||
],
|
||||
"onlySameOutput": true,
|
||||
"pinnedApps": [
|
||||
],
|
||||
"pinnedStatic": false,
|
||||
"position": "bottom",
|
||||
"pinnedStatic": true,
|
||||
"position": "left",
|
||||
"showDockIndicator": true,
|
||||
"showLauncherIcon": false,
|
||||
"showLauncherIcon": true,
|
||||
"sitOnFrame": false,
|
||||
"size": 1
|
||||
},
|
||||
@@ -475,8 +488,8 @@
|
||||
"bluetoothRssiPollIntervalMs": 60000,
|
||||
"bluetoothRssiPollingEnabled": false,
|
||||
"disableDiscoverability": false,
|
||||
"networkPanelView": "wifi",
|
||||
"wifiDetailsViewMode": "grid"
|
||||
"networkPanelView": "ethernet",
|
||||
"wifiDetailsViewMode": "list"
|
||||
},
|
||||
"nightLight": {
|
||||
"autoSchedule": true,
|
||||
|
||||
@@ -14,6 +14,20 @@ link() {
|
||||
ln -s "$2" "$1"
|
||||
fi
|
||||
}
|
||||
# Like link(), but backs up existing regular files instead of skipping them
|
||||
smartlink() {
|
||||
local target="$1" source="$2"
|
||||
echo "Linking $target to $source"
|
||||
if [ -L "$target" ]; then
|
||||
: # already a symlink, nothing to do
|
||||
elif [ -e "$target" ]; then
|
||||
mv "$target" "${target}.bak"
|
||||
echo " Backed up existing file to ${target}.bak"
|
||||
ln -s "$source" "$target"
|
||||
else
|
||||
ln -s "$source" "$target"
|
||||
fi
|
||||
}
|
||||
configlink() {
|
||||
link ~/.config/$1 ~/.dotfiles/$1
|
||||
}
|
||||
@@ -29,6 +43,20 @@ configlink polybar
|
||||
configlink picom.conf
|
||||
configlink niri
|
||||
configlink noctalia
|
||||
configlink kanshi
|
||||
|
||||
checkdir ~/.claude
|
||||
link ~/.claude/settings.json ~/.dotfiles/claude/settings.json
|
||||
|
||||
# Fish shell config
|
||||
checkdir ~/.config/fish
|
||||
checkdir ~/.config/fish/conf.d
|
||||
smartlink ~/.config/fish/config.fish ~/.dotfiles/fish/config.fish
|
||||
link ~/.config/fish/conf.d/ssh-keychain.fish ~/.dotfiles/fish/conf.d/ssh-keychain.fish
|
||||
|
||||
# Migrate BW_SESSION and other machine-specific fish vars to local.fish
|
||||
if [ -f ~/.config/fish/config.fish.bak ] && [ ! -f ~/.config/fish/local.fish ]; then
|
||||
echo " Migrating machine-specific config from config.fish.bak to local.fish"
|
||||
grep -v '^#' ~/.config/fish/config.fish.bak | grep -v '^\s*$' > ~/.config/fish/local.fish
|
||||
echo " Review ~/.config/fish/local.fish and remove anything now handled by dotfiles"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user