Compare commits

...

13 Commits

Author SHA1 Message Date
8460c2d408 feat: switch to chezmoi
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-11-13 00:26:19 +02:00
ab67f6be5a chore(tmux): fix catppuccin submodule 2025-11-13 00:25:40 +02:00
efadbb4248 chore(tmux): remove double default-terminal, theme tweaks
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-11-12 16:45:45 +02:00
ded4bf3bb3 fix(tmux): sesh selection now works in fish
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-11-12 11:48:10 +02:00
github-actions[bot]
62eb417935 chore: update pre-commit hooks (#234) 2025-11-11 22:34:15 +02:00
d22f9ece7d feat: hammerspoon & karabiner-elements
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-11-11 17:15:55 +02:00
79be2d41bc chore(theme): switch back to Catppuccin
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-11-11 14:02:07 +02:00
renovate[bot]
743ebb0e9f chore(deps): update softprops/action-gh-release action (v2.4.1 → v2.4.2) (#235)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-10 12:47:02 +00:00
renovate[bot]
8fcab21a67 chore(deps): update pre-commit hook renovatebot/pre-commit-hooks (42.0.2 → 42.1.3) (#233)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-09 06:48:18 +02:00
renovate[bot]
43a714513f chore(deps)!: update renovatebot/pre-commit-hooks (41.173.0 → 42.0.2) (#232)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-07 15:14:24 +02:00
github-actions[bot]
044298af74 chore: update pre-commit hooks (#231)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-11-06 07:15:25 +02:00
renovate[bot]
6604f7a2ca chore(deps)!: update node (v22.21.1 → v24.11.0) (#228) 2025-11-04 07:50:35 +02:00
github-actions[bot]
065eb2f9c0 chore: update pre-commit hooks (#230) 2025-11-03 09:30:56 +02:00
35 changed files with 21893 additions and 198 deletions

53
.chezmoi.yaml.tmpl Normal file
View File

@@ -0,0 +1,53 @@
{{- $hostname := .chezmoi.hostname -}}
{{- $username := .chezmoi.username -}}
{{- $osid := .chezmoi.os -}}
sourceDir: {{ .chezmoi.sourceDir | quote }}
data:
hostname: {{ $hostname | quote }}
username: {{ $username | quote }}
osid: {{ $osid | quote }}
# Detect if we're on macOS
is_macos: {{ eq $osid "darwin" }}
# Detect if we're on Linux
is_linux: {{ eq $osid "linux" }}
# Host-specific flags
is_air: {{ eq $hostname "air" }}
is_lakka: {{ eq $hostname "lakka" }}
is_tunkki: {{ eq $hostname "tunkki" }}
is_s: {{ eq $hostname "s" }}
# Merge strategy for dealing with conflicts
merge:
command: "nvim"
args:
- "-d"
- "{{ "{{" }} .Destination {{ "}}" }}"
- "{{ "{{" }} .Source {{ "}}" }}"
- "{{ "{{" }} .Target {{ "}}" }}"
# Template options
template:
options:
- "missingkey=error"
# Diff options
diff:
exclude:
- "scripts"
pager: "delta"
# Git options
git:
autoCommit: false
autoPush: false
# Hooks
hooks:
read-source-state:
pre:
command: ".local/share/chezmoi/.chezmoihooks/pre-read-source-state.sh"

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Pre-read-source-state hook for chezmoi
# This runs before chezmoi reads the source state
set -e
DOTFILES="${CHEZMOI_SOURCE_DIR:-$HOME/.local/share/chezmoi}"
# Update git submodules if they exist
if [ -d "$DOTFILES/.git" ]; then
cd "$DOTFILES"
git submodule update --init --recursive --quiet || true
fi

90
.chezmoiignore Normal file
View File

@@ -0,0 +1,90 @@
# Chezmoi ignore file
# Files and directories that should not be managed by chezmoi
# Git and version control
.git/
.gitignore
.gitattributes
.gitmodules
# GitHub
.github/
# Documentation
README.md
*.md
docs/
AGENTS.md
# Development tools
.vscode/
.serena/
.claude/
node_modules/
# Testing
tests/
test-all.sh
# Configuration files for the repo itself
.editorconfig
.editorconfig-checker.json
.eslintrc.json
.prettierrc.js
.prettierignore
.markdownlint.json
.markdownlintignore
.mega-linter.yml
.commitlintrc.json
.releaserc.json
.shellcheckrc
.yamlignore
.yamllint.yml
.browserslistrc
.actrc
.luarc.json
.ignore
stylua.toml
phpcs.xml
# Package management
package.json
yarn.lock
# Python and Node version files
.python-version
.nvmrc
.go-version
# Dotbot (old system)
install.conf.yaml
tools/dotbot/
tools/dotbot-*/
tools/dotbot-defaults.yaml
# Installation and build scripts in root
install
add-submodules.sh
# Chezmoi-specific directories (not to be managed)
.chezmoihooks/
# Host-specific directories (will be handled via templates)
{{- if not .is_air }}
hosts/air/
{{- end }}
{{- if not .is_lakka }}
hosts/lakka/
{{- end }}
{{- if not .is_tunkki }}
hosts/tunkki/
{{- end }}
{{- if not .is_s }}
hosts/s/
{{- end }}
# Secrets (should use separate secrets management)
secrets/
# macOS specific files
.DS_Store

View File

@@ -40,7 +40,7 @@ jobs:
- name: Create release
if: steps.daily-version.outputs.created
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ steps.daily-version.outputs.version }}

43
.gitignore vendored
View File

@@ -11,47 +11,48 @@
.nfs*
.scannerwork
.vscode
!config/git/local.d/.gitkeep
!config/nvim/spell/.gitkeep
!config/zed/settings.json
!ssh/local.d/.gitkeep
**/exports-secret.fish
**/exports.secret.fish
*.tmp.*
Brewfile.lock.json
antidote_plugins.zsh
config/alacritty/theme-active.toml
config/cheat/cheatsheets/pure-bash-bible/*
config/cheat/cheatsheets/tldr/*
config/fish/completions/asdf.fish
config/fish/fish_variables
config/fish/fish_variables.*
config/gh/hosts.yml
config/git/credentials
config/git/local.d/*
config/gnupg/S.*
config/gnupg/private-keys-v1.d
config/gnupg/s
config/iterm2/AppSupport
config/karabiner/automatic_backups
config/npm/npmrc
config/nvim/lazy-lock.json
config/nvim/spell/*
!config/nvim/spell/.gitkeep
config/git/local.d/*
!config/git/local.d/.gitkeep
config/op/plugins/gh.json
config/op/plugins/used_items/gh.json
config/vim/.netrwhist
config/vim/extra/*
config/vim/fzf
config/vim/plugged/*
config/zed/*
!config/zed/settings.json
config/zed/settings.json
config/zsh/.zcompdump
dependency-check-report.html
iTermServer-*
lazy-lock.json
local/share/fonts/*
local/bin/asdf/plugins/*
local/bin/yabai
local/man/yabai.1
local/share/fonts/*
lock
node_modules
ssh/local.d/*
!ssh/local.d/.gitkeep
config/fish/fish_variables
**/exports.secret.fish
**/exports-secret.fish
config/fish/completions/asdf.fish
config/vim/.netrwhist
config/vim/extra/*
config/gh/hosts.yml
dependency-check-report.html
local/bin/yabai
local/man/yabai.1
config/op/plugins/used_items/gh.json
config/zed/settings.json
*.tmp.*
config/op/plugins/gh.json
config/fish/fish_variables.*

3
.gitmodules vendored
View File

@@ -83,3 +83,6 @@
[submodule "tmux/tmux-resurrect"]
path = config/tmux/plugins/tmux-resurrect
url = https://github.com/tmux-plugins/tmux-resurrect.git
[submodule "tmux/catppuccin"]
path = config/tmux/plugins/catppuccin
url = https://github.com/catppuccin/tmux.git

2
.nvmrc
View File

@@ -1 +1 @@
22.21.1
24.11.0

View File

@@ -50,12 +50,12 @@ repos:
- id: actionlint
- repo: https://github.com/renovatebot/pre-commit-hooks
rev: 41.168.5
rev: 42.2.0
hooks:
- id: renovate-config-validator
- repo: https://github.com/JohnnyMorganz/StyLua
rev: v2.3.0
rev: v2.3.1
hooks:
- id: stylua # or stylua-system / stylua-github

View File

@@ -42,6 +42,8 @@ git submodule add --name tmux/tmux-current-pane-hostname \
-f https://github.com/soyuka/tmux-current-pane-hostname.git config/tmux/plugins/tmux-current-pane-hostname
git submodule add --name tmux/tmux-dark-notify \
-f https://github.com/ivuorinen/tmux-dark-notify.git config/tmux/plugins/tmux-dark-notify
git submodule add --name tmux/catppuccin \
-f https://github.com/catppuccin/tmux.git config/tmux/plugins/catppuccin
# Takes submodules and sets them to ignore all changes
for MODULE in $(git config --file .gitmodules --get-regexp path | awk '{ print $2 }'); do

View File

@@ -0,0 +1,15 @@
--
-- These globals can be set and accessed:
--
globals = {
"rawrequire",
}
--
-- These globals can only be accessed:
--
read_globals = {
"hs",
"ls",
"spoon",
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

204
base/hammerspoon/init.lua Normal file
View File

@@ -0,0 +1,204 @@
-- ╭─────────────────────────────────────────────────────────╮
-- │ Hammerspoon config file │
-- ╰─────────────────────────────────────────────────────────╯
-- init.lua — Pure Hammerspoon window controls
-- Converted from skhdrc logic; expanded with perdisplay grids,
-- app rules with groups, wraparound focus, crossdisplay moves,
-- and overlay/notification toggles.
-- Author: Ismo Vuorinen (ivuorinen)
--------------------------------------------------
-- Caps Lock as Meh key (Shift+Control+Alt)
--------------------------------------------------
-- Prerequisites:
-- 1. Go to System Settings → Keyboard → Keyboard Shortcuts → Modifier Keys
-- 2. Set Caps Lock to "No Action" (you mentioned you already did this)
-- 3. Install Karabiner-Elements: brew install --cask karabiner-elements
-- 4. Open Karabiner-Elements, go to "Simple Modifications"
-- 5. Add: caps_lock → f18
--
-- Then you can use F18 as your Meh key in Hammerspoon:
local f18 = hs.hotkey.modal.new()
-- Capture F18 key press/release
hs.hotkey.bind({}, 'F18', function()
f18:enter()
end, function()
f18:exit()
end)
-- Meh (F18/Caps Lock) key bindings for window management
-- These provide quick access to common window operations
-- Helper function to get focused window
local function W()
return hs.window.focusedWindow()
end
-- Window positioning: thirds (U/I/O)
f18:bind({}, 'u', function()
local w = W()
if w then
w:moveToUnit({ x = 0, y = 0, w = 1 / 3, h = 1 }, 0)
end
end)
f18:bind({}, 'i', function()
local w = W()
if w then
w:moveToUnit({ x = 1 / 3, y = 0, w = 1 / 3, h = 1 }, 0)
end
end)
f18:bind({}, 'o', function()
local w = W()
if w then
w:moveToUnit({ x = 2 / 3, y = 0, w = 1 / 3, h = 1 }, 0)
end
end)
-- Window positioning: half width, full height (Y)
f18:bind({}, 'y', function()
local w = W()
if w then
w:moveToUnit({ x = 0, y = 0, w = 0.5, h = 1 }, 0)
end
end)
-- Cycle through all windows (H/L)
-- We need to maintain state to properly cycle through all windows
local windowCycleIndex = 1
local windowCycleList = {}
local lastCycleTime = 0
local function getWindowCycleList()
local currentTime = hs.timer.secondsSinceEpoch()
-- Reset if more than 2 seconds have passed since last cycle
if currentTime - lastCycleTime > 2 then
windowCycleIndex = 1
windowCycleList = hs.window.orderedWindows()
end
lastCycleTime = currentTime
return windowCycleList
end
f18:bind({}, 'h', function()
local windows = getWindowCycleList()
if #windows <= 1 then
return
end
-- Cycle backward
windowCycleIndex = windowCycleIndex - 1
if windowCycleIndex < 1 then
windowCycleIndex = #windows
end
windows[windowCycleIndex]:focus()
end)
f18:bind({}, 'l', function()
local windows = getWindowCycleList()
if #windows <= 1 then
return
end
-- Cycle forward
windowCycleIndex = windowCycleIndex + 1
if windowCycleIndex > #windows then
windowCycleIndex = 1
end
windows[windowCycleIndex]:focus()
end)
-- Window sizing: maximize (Up/J) and center (Down)
f18:bind({}, 'up', function()
local w = W()
if w then
w:maximize(0)
end
end)
f18:bind({}, 'j', function()
local w = W()
if w then
w:maximize(0)
end
end)
f18:bind({}, 'down', function()
local w = W()
if not w then
return
end
local f = w:frame()
local sf = w:screen():frame()
if f.w < sf.w * 0.95 then
w:maximize(0)
else
local ww, hh = math.floor(sf.w * 0.5), math.floor(sf.h * 0.9)
local xx = sf.x + math.floor((sf.w - ww) / 2)
local yy = sf.y + math.floor((sf.h - hh) / 2)
w:setFrame({ x = xx, y = yy, w = ww, h = hh }, 0)
end
end)
f18:bind({}, 'k', function()
local w = W()
if w then
local sf = w:screen():frame()
local ww, hh = math.floor(sf.w * 0.9), math.floor(sf.h * 0.9)
local xx = sf.x + math.floor((sf.w - ww) / 2)
local yy = sf.y + math.floor((sf.h - hh) / 2)
w:setFrame({ x = xx, y = yy, w = ww, h = hh }, 0)
end
end)
-- Move to next/previous screen (. and ,)
f18:bind({}, '.', function()
local w = W()
if w then
local s = w:screen()
local ns = s:toEast() or s:toWest()
if ns then
w:moveToScreen(ns, true, true, 0)
end
end
end)
f18:bind({}, ',', function()
local w = W()
if w then
local s = w:screen()
local ps = s:toWest() or s:toEast()
if ps then
w:moveToScreen(ps, true, true, 0)
end
end
end)
-- Window positioning: halves (Left/Right arrows)
f18:bind({}, 'left', function()
local w = W()
if w then
w:moveToUnit(hs.layout.left50, 0)
end
end)
f18:bind({}, 'right', function()
local w = W()
if w then
w:moveToUnit(hs.layout.right50, 0)
end
end)
-- Paste from clipboard with Meh + V
f18:bind({}, 'v', function()
hs.eventtap.keyStrokes(hs.pasteboard.getContents())
end)
-- Paste 1Password secret with Meh + P
f18:bind({}, 'p', function()
local output, status = hs.execute('op read "op://Svea/3hzhctmvovbwlgulv7mgy25rf4/login-input"', true)
if status then
hs.eventtap.keyStrokes(output:gsub('%s+$', '')) -- trim trailing whitespace
else
hs.alert.show('1Password CLI error')
end
end)
-- require 'generate_emmylua'

View File

@@ -0,0 +1,30 @@
# name: 'Catppuccin Latte'
# url: 'https://github.com/catppuccin/fish'
# preferred_background: eff1f5
fish_color_normal 4c4f69
fish_color_command 1e66f5
fish_color_param dd7878
fish_color_keyword d20f39
fish_color_quote 40a02b
fish_color_redirection ea76cb
fish_color_end fe640b
fish_color_comment 8c8fa1
fish_color_error d20f39
fish_color_gray 9ca0b0
fish_color_selection --background=ccd0da
fish_color_search_match --background=ccd0da
fish_color_option 40a02b
fish_color_operator ea76cb
fish_color_escape e64553
fish_color_autosuggestion 9ca0b0
fish_color_cancel d20f39
fish_color_cwd df8e1d
fish_color_user 179299
fish_color_host 1e66f5
fish_color_host_remote 40a02b
fish_color_status d20f39
fish_pager_color_progress 9ca0b0
fish_pager_color_prefix ea76cb
fish_pager_color_completion 4c4f69
fish_pager_color_description 9ca0b0

View File

@@ -0,0 +1,30 @@
# name: 'Catppuccin Mocha'
# url: 'https://github.com/catppuccin/fish'
# preferred_background: 1e1e2e
fish_color_normal cdd6f4
fish_color_command 89b4fa
fish_color_param f2cdcd
fish_color_keyword f38ba8
fish_color_quote a6e3a1
fish_color_redirection f5c2e7
fish_color_end fab387
fish_color_comment 7f849c
fish_color_error f38ba8
fish_color_gray 6c7086
fish_color_selection --background=313244
fish_color_search_match --background=313244
fish_color_option a6e3a1
fish_color_operator f5c2e7
fish_color_escape eba0ac
fish_color_autosuggestion 6c7086
fish_color_cancel f38ba8
fish_color_cwd f9e2af
fish_color_user 94e2d5
fish_color_host 89b4fa
fish_color_host_remote a6e3a1
fish_color_status f38ba8
fish_pager_color_progress 6c7086
fish_pager_color_prefix f5c2e7
fish_pager_color_completion cdd6f4
fish_pager_color_description 6c7086

View File

@@ -38,6 +38,8 @@ brew "openssl@3"
brew "cryptography"
# YAML Parser
brew "libyaml"
# Display directories as trees (with optional color/HTML output)
brew "tree"
# Automate deployment, configuration, and upgrading
brew "ansible"
# Checks ansible playbooks for practices and behaviour
@@ -104,7 +106,7 @@ brew "glib"
brew "cargo-binstall"
# Multi-platform support library with a focus on asynchronous I/O
brew "libuv"
# Platform built on V8 to build network applications
# Open-source, cross-platform JavaScript runtime environment
brew "node", link: false
# CLI tool for analyzing Claude Code usage from local JSONL files
brew "ccusage"
@@ -230,6 +232,8 @@ brew "luarocks"
brew "lzip"
# Swiss Army Knife for macOS
brew "m-cli"
# Cross platform, open source .NET development framework
brew "mono"
# Collection of tools that nobody wrote when UNIX was young
brew "moreutils"
# NCurses Disk Usage
@@ -290,8 +294,8 @@ brew "tflint"
brew "tfsec"
# Terminal multiplexer
brew "tmux"
# Display directories as trees (with optional color/HTML output)
brew "tree"
# Extremely fast Python package installer and resolver, written in Rust
brew "uv"
# Tool for creating isolated virtual python environments
brew "virtualenv"
# Command-line interface to the WakaTime api
@@ -349,13 +353,18 @@ cask "fantastical"
cask "font-jetbrains-mono"
cask "font-jetbrains-mono-nerd-font"
cask "font-monaspace"
cask "font-monaspace-nf"
cask "font-open-sans"
# GIT client
cask "fork"
# Desktop automation application
cask "hammerspoon"
# HTTP and GraphQL Client
cask "insomnia"
# JetBrains tools manager
cask "jetbrains-toolbox"
# Keyboard customiser
cask "karabiner-elements"
# End-to-end encryption software
cask "keybase"
# Kubernetes IDE

View File

@@ -0,0 +1,68 @@
{
"profiles": [
{
"complex_modifications": {
"rules": [
{
"description": "Change right_command+hjkl to arrow keys",
"manipulators": [
{
"from": {
"key_code": "h",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "left_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "j",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "down_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "k",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "up_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "l",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "right_arrow" }],
"type": "basic"
}
]
}
]
},
"name": "Default profile",
"selected": true,
"simple_modifications": [
{
"from": { "key_code": "caps_lock" },
"to": [{ "key_code": "f18" }]
}
],
"virtual_hid_keyboard": { "keyboard_type_v2": "iso" }
}
]
}

View File

@@ -1,31 +1,112 @@
return {
{
'neanias/everforest-nvim',
version = false,
lazy = false,
priority = 1000, -- make sure to load this before all the other start plugins
'catppuccin/nvim',
name = 'catppuccin',
priority = 1000,
config = function()
require('everforest').setup {
background = 'medium', -- hard, medium, soft
transparent_background_level = 2, -- 0, 1, 2
sign_column_background = 'grey', -- none, grey
disable_italic_comments = false,
diagnostic_virtual_text = 'coloured', -- coloured, gray, underline, none
diagnostic_line_highlight = true,
diagnostic_line_highlight_background = 'dimmed', -- dimmed, normal
diagnostic_text_highlight = true,
ui_contrast = 'low', -- high, low
italics = true,
spell_foreground = true,
show_eob = true,
colours_override = function() end,
float_style = 'dim',
on_highlights = function(_, _) end,
dim_inactive_windows = true,
inlay_hints_background = 'dimmed',
require('catppuccin').setup {
flavour = 'auto', -- latte, frappe, macchiato, mocha
background = { -- :h background
light = 'latte',
dark = 'mocha',
},
transparent_background = false,
float = {
transparent = true, -- enable transparent floating windows
solid = false, -- use solid styling for floating windows, see |winborder|
},
show_end_of_buffer = false, -- shows the '~' characters after the end of buffers
term_colors = false, -- sets terminal colors (e.g. `g:terminal_color_0`)
dim_inactive = {
enabled = true, -- dims the background color of inactive window
shade = 'dark',
percentage = 0.15, -- percentage of the shade to apply to the inactive window
},
no_italic = false, -- Force no italic
no_bold = false, -- Force no bold
no_underline = false, -- Force no underline
styles = { -- Handles the styles of general hi groups (see `:h highlight-args`):
comments = { 'italic' }, -- Change the style of comments
conditionals = { 'italic' },
loops = {},
functions = {},
keywords = {},
strings = {},
variables = {},
numbers = {},
booleans = {},
properties = {},
types = {},
operators = {},
-- miscs = {}, -- Uncomment to turn off hard-coded styles
},
lsp_styles = { -- Handles the style of specific lsp hl groups (see `:h lsp-highlight`).
virtual_text = {
errors = { 'italic' },
hints = { 'italic' },
warnings = { 'italic' },
information = { 'italic' },
ok = { 'italic' },
},
underlines = {
errors = { 'underline' },
hints = { 'underline' },
warnings = { 'underline' },
information = { 'underline' },
ok = { 'underline' },
},
inlay_hints = {
background = true,
},
},
color_overrides = {},
custom_highlights = {},
default_integrations = true,
auto_integrations = false,
integrations = {
cmp = true,
gitsigns = true,
nvimtree = true,
notify = false,
mini = {
enabled = true,
indentscope_color = '',
},
-- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations)
},
}
-- setup must be called before loading
vim.cmd.colorscheme 'catppuccin'
end,
},
-- {
-- 'neanias/everforest-nvim',
-- version = false,
-- lazy = false,
-- priority = 1000, -- make sure to load this before all the other start plugins
-- config = function()
-- require('everforest').setup {
-- background = 'medium', -- hard, medium, soft
-- transparent_background_level = 2, -- 0, 1, 2
-- sign_column_background = 'grey', -- none, grey
-- disable_italic_comments = false,
-- diagnostic_virtual_text = 'coloured', -- coloured, gray, underline, none
-- diagnostic_line_highlight = true,
-- diagnostic_line_highlight_background = 'dimmed', -- dimmed, normal
-- diagnostic_text_highlight = true,
-- ui_contrast = 'low', -- high, low
-- italics = true,
-- spell_foreground = true,
-- show_eob = true,
-- colours_override = function() end,
-- float_style = 'dim',
-- on_highlights = function(_, _) end,
-- dim_inactive_windows = true,
-- inlay_hints_background = 'dimmed',
-- }
-- end,
-- },
-- Automatic dark mode
-- https://github.com/f-person/auto-dark-mode.nvim
@@ -60,37 +141,37 @@ return {
-- Remove all background colors to make nvim transparent
-- https://github.com/xiyaowong/nvim-transparent
{
'xiyaowong/nvim-transparent',
lazy = false,
enabled = true,
config = function()
local t = require 'transparent'
t.setup {
extra_groups = {
'NormalNC',
'NormalFloat',
'EndOfBuffer',
'FloatTitle',
'FloatBorder',
'NotifyDEBUGBorder',
'NotifyERRORBorder',
'NotifyINFOBorder',
'NotifyINFOBorder73',
'NotifyINFOBorder75',
'NotifyINFOBorder101',
'NotifyTRACEBorder',
'NotifyWARNBorder',
'NotifyBackground',
'TelescopeBorder',
'TelescopePromptBorder',
'TelescopeResultsBorder',
'TelescopePreviewBorder',
},
}
t.clear_prefix 'NeoTree'
end,
},
-- {
-- 'xiyaowong/nvim-transparent',
-- lazy = false,
-- enabled = true,
-- config = function()
-- local t = require 'transparent'
-- t.setup {
-- extra_groups = {
-- 'NormalNC',
-- 'NormalFloat',
-- 'EndOfBuffer',
-- 'FloatTitle',
-- 'FloatBorder',
-- 'NotifyDEBUGBorder',
-- 'NotifyERRORBorder',
-- 'NotifyINFOBorder',
-- 'NotifyINFOBorder73',
-- 'NotifyINFOBorder75',
-- 'NotifyINFOBorder101',
-- 'NotifyTRACEBorder',
-- 'NotifyWARNBorder',
-- 'NotifyBackground',
-- 'TelescopeBorder',
-- 'TelescopePromptBorder',
-- 'TelescopeResultsBorder',
-- 'TelescopePreviewBorder',
-- },
-- }
-- t.clear_prefix 'NeoTree'
-- end,
-- },
-- Display a character as the colorcolumn
-- https://github.com/lukas-reineke/virt-column.nvim

18
config/tmux/sesh-tmux.fish Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env fish
set selection (sesh list --icons | fzf-tmux -p 80%,70% \
--no-sort --ansi --border-label ' sesh ' --prompt '⚡ ' \
--header ' ^a all ^t tmux ^g configs ^x zoxide ^d tmux kill ^f find' \
--bind 'tab:down,btab:up' \
--bind 'ctrl-a:change-prompt(⚡ )+reload(sesh list --icons)' \
--bind 'ctrl-t:change-prompt(🪟 )+reload(sesh list -t --icons)' \
--bind 'ctrl-g:change-prompt(⚙️ )+reload(sesh list -c --icons)' \
--bind 'ctrl-x:change-prompt(📁 )+reload(sesh list -z --icons)' \
--bind 'ctrl-f:change-prompt(🔎 )+reload(fd -H -d 2 -t d -E .Trash . ~)' \
--bind 'ctrl-d:execute(tmux kill-session -t {2..})+change-prompt(⚡ )+reload(sesh list --icons)' \
--preview-window 'right:55%' \
--preview 'sesh preview {}')
if test -n "$selection"
sesh connect "$selection"
end

View File

@@ -1,46 +1,3 @@
# Everforest dark theme for tmux
# Generated from template - do not edit manually
set -g @catppuccin_flavor "mocha"
set -g @catppuccin_window_status_style "basic"
# Enable proper color support
set -g default-terminal "tmux-256color"
set -as terminal-features ",*:RGB"
set -g pane-border-style "bg=default,fg=#859289"
set -g pane-active-border-style "bg=default,fg=#a7c080"
# Window tabs
set -g window-style "bg=default,fg=default,dim"
set -g window-status-style "bg=default,fg=default,dim"
set -g window-status-current-style "bg=default,fg=#d3c6aa"
set -g window-status-activity-style "bg=default,fg=#dbbc7f,nodim"
set -g window-status-bell-style "bg=default,fg=yellow,nodim"
set -g window-status-last-style "bg=default,fg=#a7c080"
set -g window-status-format " #I:#W "
# Messages
set -g message-style "bg=default,fg=#d3c6aa"
set -g message-command-style "bg=default,fg=#d3c6aa"
# Status bar
set -g status-style "bg=default,fg=default"
set -g status-left " #[default]"
set -g status-right " #[fg=#a7c080]#S@#[fg=#859289]#h #[fg=#7fbbb3]%H:%M #[fg=#dbbc7f]%d.%m "
set -g status-left-style "bg=default,fg=white"
set -g status-right-style "bg=default,fg=white"
set -g menu-style "bg=default,fg=white"
set -g menu-selected-style "bg=default,fg=#a7c080"
set -g menu-border-style "fg=#a7c080"
set -g menu-border-lines "single"
set -g popup-style "bg=default,fg=white"
set -g popup-border-style "fg=#a7c080"
set -g popup-border-lines "single"
set -g display-panes-colour "blue"
set -g display-panes-active-colour "red"
set -g display-panes-time 1000 # milliseconds
set -g pane-border-indicators "arrows"
set -g pane-border-lines "single"
set -g clock-mode-style "24"

View File

@@ -1,6 +1,2 @@
set-option -g status-style 'fg=#4c4f69,bg=default'
set-window-option -g window-status-style 'fg=#4c4f69,bg=default dim'
set-window-option -g window-status-current-style 'fg=#8839ef,bg=default'
set-window-option -g window-status-activity-style 'fg=#4c4f69,bg=default nodim'
set-window-option -g window-status-bell-style 'fg=#4c4f69,bg=default'
set -g message-style 'fg=#8839ef bg=#e6e9ef bold' # fg magenta, bg black
set -g @catppuccin_flavor "latte"
set -g @catppuccin_window_status_style "basic"

View File

@@ -18,6 +18,9 @@
set -ag terminal-overrides ",xterm-256color:RGB"
set -ag terminal-features 'xterm-256color:RGB'
# Enable proper color support
set -as terminal-features ",*:RGB"
set -g default-terminal "tmux-256color" # Set default terminal to 256 colors
set -g detach-on-destroy off # don't detach tmux when killing a session
set -g display-time 0 # Hide clock
@@ -51,17 +54,17 @@ if-shell '[ "$DEBUG" = "1" ]' 'set -g debug-file ~/.cache/tmux-debug.log'
# │ Theme │
# ╰──────────────────────────────────────────────────────────╯
set -g pane-active-border-style "bg=default,fg=#7aa2f7"
set -g pane-border-style "bg=default,fg=#31748f"
set -g status-style "bg=default"
set -g status-justify "left"
set -g status-left ''
set -g status-left-length "0"
set -g status-position "bottom"
set -g status-right "#S@#h #{tmux_mode_indicator}"
set -g status-right-length "30"
set -g status-right-length "50"
set -g window-status-current-format ' #I:#W#{?window_zoomed_flag, ◈ ,} '
set -g window-status-format ' #I:#W '
set -g @catppuccin_status_background 'none'
set -g @catppuccin_window_flags 'icon'
set -g @catppuccin_status_connect_separator 'no'
# ╭──────────────────────────────────────────────────────────╮
# │ Bindings │
@@ -101,32 +104,16 @@ unbind p
bind p paste-buffer
# tms bindings
bind -N "tms" t display-popup -E "tms"
bind -N "tms" T display-popup -E "tms"
bind -N "tms windows" C-w display-popup -E "tms windows"
bind -N "tms switch" C-s display-popup -E "tms switch"
bind -N "tms refresh" C-r display-popup -E "tms refresh"
# global sessions
# bind-key "K" display-popup -h 90% -w 50% -E "sesh ui"
bind-key "K" run-shell "sesh connect \"$(
sesh list --icons --hide-duplicates | fzf-tmux -p 100%,100% --no-border \
--list-border \
--no-sort --prompt '⚡ ' \
--input-border \
--header-border \
--bind 'tab:down,btab:up' \
--bind 'ctrl-b:abort' \
--bind 'ctrl-a:change-prompt(⚡ )+reload(sesh list --icons)' \
--bind 'ctrl-t:change-prompt( )+reload(sesh list -t --icons)' \
--bind 'ctrl-g:change-prompt(⚙️ )+reload(sesh list -c --icons)' \
--bind 'ctrl-x:change-prompt(📁 )+reload(sesh list -z --icons)' \
--bind 'ctrl-f:change-prompt(🔎 )+reload(fd -H -d 2 -t d -E .Trash . ~)' \
--bind 'ctrl-d:execute(tmux kill-session -t {2..})+change-prompt(⚡ )+reload(sesh list --icons)' \
--preview-window 'right:70%' \
--preview 'sesh preview {}' \
)\""
bind-key "N" display-popup -E "sesh ui"
bind -N "sesh selection" t run-shell "$HOME/.dotfiles/config/tmux/sesh-tmux.fish"
bind -N "last-session (via sesh) " L run-shell "sesh last"
bind -N "sesh ui" N display-popup -E "sesh ui"
# ╭──────────────────────────────────────────────────────────╮
# │ Plugins │
@@ -142,7 +129,7 @@ bind-key "N" display-popup -E "sesh ui"
## A plugin to name your tmux windows smartly.
## https://github.com/ofirgall/tmux-window-name
### Maximum name length of a window
set -g @tmux_window_name_max_name_len "20"
set -g @tmux_window_name_max_name_len "25"
### Replace $HOME with ~ in window names
set -g @tmux_window_dir_programs "['nvim', 'vim', 'vi', 'git']"
set -g @tmux_window_name_ignored_programs "['sqlite3', 'antidote', 'direnv', 'md5']" # Default is []
@@ -189,5 +176,6 @@ run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-current-pane-hostname/curren
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-fzf-url/fzf-url.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-resurrect/resurrect.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-continuum/continuum.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/catppuccin/catppuccin.tmux"
run-shell "$HOME/.dotfiles/config/tmux/plugins/tmux-dark-notify/main.tmux"

View File

@@ -66,9 +66,11 @@ config.scrollback_lines = 3000
-- Function to detect the theme based on appearance
function Scheme_for_appearance(appearance)
if appearance:find 'Dark' then
return 'Everforest Dark (Medium)'
return 'Catppuccin Mocha'
-- return 'Everforest Dark (Medium)'
else
return 'Everforest Light (Medium)'
return 'Catppuccin Latte'
-- return 'Everforest Light (Medium)'
end
end

View File

@@ -0,0 +1,425 @@
# Chezmoi Migration Summary
## What Was Done
Your dotfiles repository has been prepared for migration from dotbot to chezmoi. Here's what was created:
### 1. Updated Install Script
- **File**: `install`
- **Change**: Now uses chezmoi's one-line installer
- **Command**: `sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen`
### 2. Chezmoi Configuration Files
#### `.chezmoi.yaml.tmpl`
Main configuration file that includes:
- Source directory configuration
- Host detection (air, lakka, tunkki, s)
- OS detection (macOS, Linux)
- Custom data variables for templates
- Merge and diff settings
- Git configuration
- Pre-read hook for submodule updates
#### `.chezmoiignore`
Specifies what files should NOT be managed by chezmoi:
- Git and GitHub files
- Documentation (*.md files)
- Development tools (.vscode, node_modules, etc.)
- Old dotbot configuration
- Host-specific files (via templates)
- Repository management files
### 3. Run Scripts (Automated Setup)
#### `run_once_before_install-prerequisites.sh.tmpl`
Runs **once before** applying dotfiles:
- Installs Homebrew (macOS)
- Installs Xcode CLI tools (macOS)
- Updates package manager (Linux)
#### `run_once_after_install-packages.sh.tmpl`
Runs **once after** applying dotfiles:
- Installs Homebrew packages (Brewfile)
- Sets macOS defaults
- Installs apt packages (Linux)
- Installs pipx packages
#### `run_once_after_setup-languages.sh.tmpl`
Runs **once after** applying dotfiles:
- Installs fonts
- Installs Cargo packages (Rust)
- Installs Go packages
- Installs Composer (PHP)
- Installs NVM and latest Node LTS
- Installs NPM packages
- Installs GitHub CLI extensions
- Installs z (directory jumper)
- Installs cheat databases
#### `run_once_after_create-directories.sh.tmpl`
Runs **once after** applying dotfiles:
- Creates required directories in `$HOME`
- Sets proper permissions (e.g., `.ssh` → 0700)
### 4. Hooks
#### `.chezmoihooks/pre-read-source-state.sh`
Runs before chezmoi reads the source state:
- Updates git submodules automatically
### 5. Documentation
#### `MIGRATION-DOTBOT-TO-CHEZMOI.md` (66KB)
Comprehensive migration guide including:
- Why migrate to chezmoi
- Key differences between dotbot and chezmoi
- Complete dotbot → chezmoi mapping
- File structure comparison
- Step-by-step migration instructions
- Usage guide with examples
- Troubleshooting section
- Migration checklist
#### `CHEZMOI-QUICK-REFERENCE.md` (11KB)
Quick reference guide for daily use:
- Common commands
- File naming conventions
- Template syntax examples
- Host-specific configuration patterns
- Troubleshooting tips
- Useful aliases
#### `HOST-SPECIFIC-MIGRATION.md` (9KB)
Detailed guide for migrating host-specific configurations:
- Three migration approaches explained
- Examples from your current hosts
- Step-by-step host config migration
- Testing strategies
- Best practices
### 6. Migration Helper Script
#### `migrate-to-chezmoi.sh`
Automated script to restructure your files:
- Creates backup branch automatically
- Creates migration branch
- Renames files to chezmoi conventions
- `base/*``dot_*`
- `config/*``dot_config/*`
- `local/bin/*``executable_dot_local/bin/*`
- `ssh/*``private_dot_ssh/*`
- Cleans up empty directories
- Generates migration notes
## What Needs To Be Done
### Immediate Next Steps
1. **Review Changes**
```bash
cd ~/.dotfiles
git status
git diff
```
2. **Read Documentation**
- Start with: `MIGRATION-DOTBOT-TO-CHEZMOI.md`
- Quick reference: `CHEZMOI-QUICK-REFERENCE.md`
- Host configs: `HOST-SPECIFIC-MIGRATION.md`
3. **Commit Current State**
```bash
git add install .chezmoi.yaml.tmpl .chezmoiignore
git add run_once_*.sh.tmpl .chezmoihooks/
git add migrate-to-chezmoi.sh
git add *.md
git commit -m "Add chezmoi configuration and migration tools"
```
### File Restructuring
You have two options:
#### Option A: Automated (Recommended for First Pass)
```bash
# Run the migration script
./migrate-to-chezmoi.sh
# This will:
# - Create backup branch
# - Create migration branch
# - Rename all files to chezmoi conventions
# - Show you what was done
```
#### Option B: Manual (More Control)
Manually rename files following chezmoi conventions:
```bash
# Base files become dot_ files
git mv base/bashrc dot_bashrc
git mv base/zshrc dot_zshrc
git mv base/tmux.conf dot_tmux.conf
# Config files
mkdir -p dot_config
git mv config/fish dot_config/fish
git mv config/nvim dot_config/nvim
# ... etc
# Local bin (make executable)
mkdir -p executable_dot_local/bin
for file in local/bin/*; do
git mv "$file" "executable_dot_local/bin/$(basename $file)"
done
# SSH files (private)
mkdir -p private_dot_ssh
git mv ssh/* private_dot_ssh/
# See full examples in MIGRATION-DOTBOT-TO-CHEZMOI.md
```
### Host-Specific Configurations
Your hosts need special attention:
```bash
hosts/
├── air/
├── lakka/
├── tunkki/
└── s/
```
**Read**: `HOST-SPECIFIC-MIGRATION.md` for detailed strategies.
**Quick decision guide**:
- **Few differences per file** → Use templates with `{{ if .is_air }}`
- **Complete replacement** → Use `filename__hostname` suffix
- **Host-specific directories** → Use `.chezmoiignore` with templates
### Testing Before Commit
```bash
# After restructuring files, test with chezmoi
cd ~/.dotfiles
# Initialize chezmoi with current directory as source
chezmoi init --source $(pwd)
# See what would happen (dry run)
chezmoi apply --dry-run --verbose
# See what a specific file would look like
chezmoi cat ~/.bashrc
# Check for errors
chezmoi verify
```
### Final Steps
1. **Commit Migration**
```bash
git add -A
git commit -m "Migrate from dotbot to chezmoi"
git push
```
2. **Test on Current Machine**
```bash
# Apply dotfiles
chezmoi apply -v
# Verify everything works
# Open new terminal
# Check configs
```
3. **Test on Another Machine** (if available)
```bash
# On another machine
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
# Verify host-specific configs applied correctly
```
4. **Clean Up** (after confirming everything works)
```bash
cd $(chezmoi source-path)
# Remove old dotbot files
rm -rf tools/dotbot tools/dotbot-*
rm install.conf.yaml
rm tools/dotbot-defaults.yaml
# Optionally remove hosts/ if fully migrated to templates
# rm -rf hosts/
git add -A
git commit -m "Clean up old dotbot files"
git push
```
## Key Differences to Remember
### Installation
**Before**: `./install` (ran dotbot)
**After**: `sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen`
### Making Changes
**Before**:
```bash
cd ~/.dotfiles
vim base/bashrc
./install # Re-run to create symlinks
```
**After**:
```bash
chezmoi edit ~/.bashrc
# Or: vim ~/.bashrc && chezmoi add ~/.bashrc
chezmoi apply
```
### Syncing Across Machines
**Before**:
```bash
cd ~/.dotfiles
git pull
./install
```
**After**:
```bash
chezmoi update
# Equivalent to: cd $(chezmoi source-path) && git pull && chezmoi apply
```
### Host-Specific Configs
**Before**: Separate files in `hosts/hostname/`
**After**: Templates with `{{ if eq .chezmoi.hostname "air" }}` or `filename__hostname`
## File Mapping Reference
| Old Location | New Location | Notes |
|--------------|--------------|-------|
| `base/bashrc` | `dot_bashrc` | Becomes `~/.bashrc` |
| `config/fish/` | `dot_config/fish/` | Becomes `~/.config/fish/` |
| `local/bin/script` | `executable_dot_local/bin/script` | Executable `~/.local/bin/script` |
| `ssh/config` | `private_dot_ssh/config` | Private (0600) `~/.ssh/config` |
| `install.conf.yaml` | `run_once_*.sh.tmpl` | Setup tasks |
| `hosts/air/config/` | `dot_config/*.tmpl` or `*__air` | Host-specific |
## Troubleshooting Quick Tips
### "Entry not in source state"
```bash
# File not added to chezmoi
chezmoi add <file>
```
### "File modified since chezmoi last wrote it"
```bash
# See changes
chezmoi diff
# Re-add
chezmoi add <file>
```
### "Template undefined variable"
```bash
# Check available data
chezmoi data
# Test template
chezmoi execute-template "{{ .chezmoi.hostname }}"
```
### Scripts not running
```bash
# Check permissions
chmod +x run_once_*.sh.tmpl
# Force re-run
chezmoi apply --force
```
## Additional Resources
### Created Documentation
- `MIGRATION-DOTBOT-TO-CHEZMOI.md` - Complete migration guide
- `CHEZMOI-QUICK-REFERENCE.md` - Daily usage reference
- `HOST-SPECIFIC-MIGRATION.md` - Host configuration guide
- `MIGRATION-NOTES.md` - Generated after running migration script
### External Resources
- [Chezmoi Official Docs](https://www.chezmoi.io/)
- [Chezmoi Quick Start](https://www.chezmoi.io/quick-start/)
- [Chezmoi User Guide](https://www.chezmoi.io/user-guide/)
- [Chezmoi Templates](https://www.chezmoi.io/reference/templates/)
## Summary Checklist
- [x] Install script updated
- [x] Chezmoi configuration created (`.chezmoi.yaml.tmpl`)
- [x] Ignore file created (`.chezmoiignore`)
- [x] Run scripts created (4 scripts)
- [x] Hooks created (pre-read-source-state)
- [x] Migration script created (`migrate-to-chezmoi.sh`)
- [x] Documentation created (3 guides)
- [ ] **Review and commit configuration files**
- [ ] **Run migration script** or manually restructure
- [ ] **Migrate host-specific configs**
- [ ] **Test with chezmoi**
- [ ] **Commit migration**
- [ ] **Test on current machine**
- [ ] **Test on other machines**
- [ ] **Clean up old dotbot files**
- [ ] **Update README.md** (document chezmoi usage)
## Questions?
If you have questions during migration:
1. Check the relevant guide:
- General questions → `MIGRATION-DOTBOT-TO-CHEZMOI.md`
- Usage questions → `CHEZMOI-QUICK-REFERENCE.md`
- Host configs → `HOST-SPECIFIC-MIGRATION.md`
2. Use chezmoi's help:
```bash
chezmoi help
chezmoi help <command>
chezmoi doctor
```
3. Check official docs:
- https://www.chezmoi.io/
## What Makes This Migration Special
Your dotfiles have:
- ✅ Custom `dfm` script → Wrapped in run_once scripts
- ✅ Multiple dotbot plugins → Equivalent run_once scripts
- ✅ Host-specific configs → Template support added
- ✅ Complex installation → Automated in run scripts
- ✅ Git submodules → Pre-read hook handles this
- ✅ Multiple hosts (air, lakka, tunkki, s) → Detected and flagged
Everything from your dotbot setup has been accounted for in the chezmoi migration!
## Final Notes
- **Take your time**: This is a significant migration
- **Test thoroughly**: Use `--dry-run` extensively
- **Backup everything**: The migration script creates backups
- **Iterate**: You can always refine the migration later
- **Have fun**: Chezmoi offers powerful features to explore!
Good luck with your migration! 🚀

View File

@@ -0,0 +1,432 @@
# Chezmoi Quick Reference
Quick reference guide for common chezmoi operations with your dotfiles.
## Installation
```bash
# Fresh install on a new machine
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
# Or if chezmoi is already installed
chezmoi init --apply ivuorinen
```
## Daily Workflow
### Making Changes
```bash
# Edit a dotfile (opens in $EDITOR)
chezmoi edit ~/.bashrc
# Or edit directly and add to chezmoi
vim ~/.bashrc
chezmoi add ~/.bashrc
# See what would change
chezmoi diff
# Apply changes
chezmoi apply
```
### Syncing Across Machines
```bash
# On machine A: commit and push changes
cd $(chezmoi source-path)
git add -A
git commit -m "Update configuration"
git push
# On machine B: pull and apply changes
chezmoi update
# This is equivalent to:
# cd $(chezmoi source-path) && git pull && chezmoi apply
```
## Common Commands
### Viewing and Inspecting
```bash
# See what chezmoi would do
chezmoi diff
# List all managed files
chezmoi managed
# List unmanaged files
chezmoi unmanaged
# Show the source path
chezmoi source-path
# Show what a file would look like after templating
chezmoi cat ~/.bashrc
# Show available template data
chezmoi data
```
### Adding and Removing Files
```bash
# Add a file
chezmoi add ~/.newfile
# Add a file as a template
chezmoi add --template ~/.newfile
# Add a directory recursively
chezmoi add --recursive ~/.config/newapp
# Add with autodetection (templates, scripts, etc.)
chezmoi add --autotemplate ~/.newfile
# Stop managing a file (removes from chezmoi)
chezmoi forget ~/.oldfile
# Remove a file from both chezmoi and home directory
chezmoi remove ~/.oldfile
```
### Working with Templates
```bash
# Execute a template expression
chezmoi execute-template "{{ .chezmoi.hostname }}"
# Edit template data
chezmoi edit-config
# Verify templates
chezmoi verify
```
### Applying Changes
```bash
# Apply all changes
chezmoi apply
# Apply with verbose output
chezmoi apply -v
# Dry run (show what would happen)
chezmoi apply --dry-run -v
# Force apply (re-runs scripts)
chezmoi apply --force
# Apply only specific files
chezmoi apply ~/.bashrc ~/.zshrc
```
### Updating from Repository
```bash
# Update dotfiles from repository
chezmoi update
# Update but don't apply
cd $(chezmoi source-path) && git pull
# Update with interactive merge
chezmoi update --interactive
```
## File Naming Conventions
### Basic Prefixes
| Source File | Destination | Description |
|------------|-------------|-------------|
| `dot_bashrc` | `~/.bashrc` | Dot file |
| `dot_config/` | `~/.config/` | Dot directory |
| `private_dot_ssh/` | `~/.ssh/` | Private directory (0700) |
| `executable_dot_local/bin/script` | `~/.local/bin/script` | Executable |
| `symlink_dot_vim` | `~/.vim` | Symlink |
| `readonly_dot_file` | `~/.file` | Read-only |
### Template Files
| Source File | Description |
|------------|-------------|
| `dot_bashrc.tmpl` | Template file |
| `dot_config/fish/config.fish.tmpl` | Nested template |
### Scripts
| Script Name | When It Runs |
|------------|--------------|
| `run_once_before_*.sh` | Once before applying |
| `run_once_after_*.sh` | Once after applying |
| `run_before_*.sh` | Every time before applying |
| `run_after_*.sh` | Every time after applying |
| `run_onchange_*.sh` | When script content changes |
## Template Syntax
### Basic Variables
```go
// Hostname
{{ .chezmoi.hostname }}
// Username
{{ .chezmoi.username }}
// Operating system
{{ .chezmoi.os }}
// Home directory
{{ .chezmoi.homeDir }}
// Source directory
{{ .chezmoi.sourceDir }}
// Custom data from .chezmoi.yaml
{{ .is_macos }}
{{ .is_linux }}
```
### Conditionals
```go
{{ if eq .chezmoi.hostname "air" }}
# Configuration for air
{{ else if eq .chezmoi.hostname "lakka" }}
# Configuration for lakka
{{ else }}
# Default configuration
{{ end }}
{{ if .is_macos }}
# macOS-specific
{{ end }}
{{ if and .is_macos (eq .chezmoi.hostname "air") }}
# macOS on air
{{ end }}
```
### Loops
```go
{{ range $key, $value := .data }}
{{ $key }}: {{ $value }}
{{ end }}
```
### Including Files
```go
{{ include "template-file.txt" }}
{{ includeTemplate "template-file.tmpl" }}
```
## Host-Specific Configuration
### Method 1: Template Conditionals
In `dot_bashrc.tmpl`:
```bash
# Common configuration
export PATH="$HOME/.local/bin:$PATH"
{{ if eq .chezmoi.hostname "air" }}
# air-specific configuration
export WORK_DIR="$HOME/Work"
{{ end }}
{{ if eq .chezmoi.hostname "lakka" }}
# lakka-specific configuration
export WORK_DIR="$HOME/Projects"
{{ end }}
```
### Method 2: Separate Files with Symlinks
Use `.chezmoiignore` to exclude files for specific hosts:
```
{{ if ne .chezmoi.hostname "air" }}
dot_config/air-specific-app/
{{ end }}
{{ if ne .chezmoi.hostname "lakka" }}
dot_config/lakka-specific-app/
{{ end }}
```
## Working with Secrets
### Environment Variables
```go
{{ .Env.MY_SECRET }}
```
### 1Password
```go
{{ (onepasswordDocument "my-secret").content }}
{{ (onepasswordItemFields "my-item").password.value }}
```
### External Commands
```go
{{ output "op" "read" "op://vault/item/field" }}
```
## Troubleshooting
### Check Configuration
```bash
# Verify chezmoi is working correctly
chezmoi doctor
# Check state
chezmoi verify
# See detailed info
chezmoi data
```
### Debug Templates
```bash
# See what a template would produce
chezmoi cat ~/.bashrc
# Execute a template
chezmoi execute-template "{{ .chezmoi.hostname }}"
# Verbose output
chezmoi apply -v
```
### Fix Issues
```bash
# Re-apply everything
chezmoi apply --force
# Reset state (dangerous!)
chezmoi state reset
# Clear cache
rm -rf $(chezmoi source-path)/.git/chezmoi-*
```
### Common Errors
**Error: template: ... undefined variable**
- Check template syntax
- Verify data with `chezmoi data`
**Error: entry ... is not in source state**
- File not added to chezmoi: `chezmoi add <file>`
**Error: ... has been modified since chezmoi last wrote it**
- See changes: `chezmoi diff`
- Re-add: `chezmoi add <file>`
- Or force apply: `chezmoi apply --force`
## Useful Aliases
Add these to your shell configuration:
```bash
# Chezmoi shortcuts
alias cm='chezmoi'
alias cma='chezmoi apply'
alias cmd='chezmoi diff'
alias cme='chezmoi edit'
alias cmu='chezmoi update'
alias cmcd='cd $(chezmoi source-path)'
# Common workflows
alias cmup='chezmoi git pull && chezmoi apply'
alias cmpush='cd $(chezmoi source-path) && git add -A && git commit && git push'
```
## Environment Variables
```bash
# Change source directory (default: ~/.local/share/chezmoi)
export CHEZMOI_SOURCE_DIR="$HOME/.dotfiles"
# Change config file location
export CHEZMOI_CONFIG_FILE="$HOME/.config/chezmoi/chezmoi.yaml"
# Use different editor
export EDITOR="vim"
```
## Advanced Usage
### Using chezmoi as a dotfiles manager
```bash
# Initialize with local directory
chezmoi init --source ~/.dotfiles
# Use current directory as source
chezmoi init --source $(pwd)
```
### Managing Multiple Machines
Use data in `.chezmoi.yaml.tmpl`:
```yaml
data:
is_work_machine: {{ or (eq .chezmoi.hostname "work-laptop") (eq .chezmoi.hostname "work-desktop") }}
is_personal: {{ eq .chezmoi.hostname "personal-laptop" }}
```
Then in templates:
```go
{{ if .is_work_machine }}
# Work configuration
{{ end }}
```
### External Files
```yaml
# .chezmoiexternal.yaml
".config/nvim/lua/plugins":
type: "archive"
url: "https://github.com/user/nvim-config/archive/main.tar.gz"
stripComponents: 1
refreshPeriod: "168h"
```
## Resources
- [Official Documentation](https://www.chezmoi.io/)
- [User Guide](https://www.chezmoi.io/user-guide/)
- [Template Reference](https://www.chezmoi.io/reference/templates/)
- [Command Reference](https://www.chezmoi.io/reference/commands/)
- [FAQ](https://www.chezmoi.io/faq/)
## Help
```bash
# General help
chezmoi help
# Command-specific help
chezmoi help apply
chezmoi help add
# Show version
chezmoi --version
```

View File

@@ -0,0 +1,462 @@
# Host-Specific Configuration Migration
Guide for migrating host-specific configurations from dotbot to chezmoi.
## Current Dotbot Structure
You currently have host-specific configurations in:
```
hosts/
├── air/
│ ├── base/
│ ├── config/
│ └── install.conf.yaml
├── lakka/
│ ├── base/
│ ├── config/
│ └── install.conf.yaml
├── tunkki/
│ └── install.conf.yaml
└── s/
└── install.conf.yaml
```
## Chezmoi Approaches
There are three main approaches to handle host-specific configurations in chezmoi:
### 1. Template Conditionals (Recommended)
Use if/else conditions in template files.
**Pros:**
- Single source file for all hosts
- Easy to see all variations
- Less file duplication
**Cons:**
- Files can get complex with many hosts
- Need `.tmpl` extension
**Example:**
Create `dot_bashrc.tmpl`:
```bash
# Common configuration for all hosts
export PATH="$HOME/.local/bin:$PATH"
{{ if eq .chezmoi.hostname "air" }}
# air-specific
export WORK_DIR="$HOME/Work"
alias air-specific="echo air"
{{ end }}
{{ if eq .chezmoi.hostname "lakka" }}
# lakka-specific
export WORK_DIR="$HOME/Projects"
alias lakka-specific="echo lakka"
{{ end }}
# More common configuration
```
### 2. Separate Files with .chezmoiignore (Simple)
Keep separate files per host and ignore the ones that don't apply.
**Pros:**
- Clean separation
- No template syntax needed
- Easy to maintain
**Cons:**
- More files to manage
- Some duplication
**Example:**
Create multiple version files:
```
dot_bashrc__air
dot_bashrc__lakka
dot_bashrc__tunkki
```
These automatically apply based on hostname. No `.chezmoiignore` needed!
Or use directories:
```
dot_config/
├── app/
│ ├── config.yaml__air
│ ├── config.yaml__lakka
│ └── config.yaml__default
```
### 3. Hybrid Approach (Most Flexible)
Combine both methods:
- Use templates for files with minor differences
- Use separate files for completely different configs
## Migration Steps for Your Hosts
### Step 1: Analyze Each Host
Review what's different per host:
```bash
# See what's in each host directory
ls -la hosts/air/
ls -la hosts/lakka/
ls -la hosts/tunkki/
ls -la hosts/s/
# Compare configs
diff hosts/air/config/some-app/config hosts/lakka/config/some-app/config
```
### Step 2: Choose Strategy Per File
For each file that differs:
**Small differences** (few lines):
→ Use templates with conditionals
**Complete replacement**:
→ Use `filename__hostname` suffix
**Shared base + host additions**:
→ Use templates with includes or blocks
### Step 3: Migrate Host Configurations
#### Example: Fish Configuration
Your `hosts/air/config/fish/config.fish` differences:
**Current dotbot way:**
```yaml
# hosts/air/install.conf.yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**New chezmoi way - Option A (Templates):**
Create `dot_config/fish/config.fish.tmpl`:
```fish
# Common fish configuration
set -gx EDITOR nvim
{{ if eq .chezmoi.hostname "air" }}
# air-specific config
set -gx WORK_DIR ~/Work
{{ else if eq .chezmoi.hostname "lakka" }}
# lakka-specific config
set -gx WORK_DIR ~/Projects
{{ end }}
# More common configuration
```
**New chezmoi way - Option B (Separate files):**
Create multiple files:
```
dot_config/fish/config.fish__air
dot_config/fish/config.fish__lakka
```
Chezmoi will automatically use the correct file based on hostname.
### Step 4: Update .chezmoi.yaml.tmpl
Add host flags for easier conditionals:
```yaml
{{- $hostname := .chezmoi.hostname -}}
data:
hostname: {{ $hostname | quote }}
# Host-specific flags
is_air: {{ eq $hostname "air" }}
is_lakka: {{ eq $hostname "lakka" }}
is_tunkki: {{ eq $hostname "tunkki" }}
is_s: {{ eq $hostname "s" }}
# Group flags
is_work: {{ or (eq $hostname "air") (eq $hostname "tunkki") }}
is_personal: {{ or (eq $hostname "lakka") (eq $hostname "s") }}
```
Then use simpler conditionals:
```go
{{ if .is_air }}
# air config
{{ end }}
{{ if .is_work }}
# All work machines
{{ end }}
```
## Specific Migration Examples
### Example 1: Simple Host-Specific Line
**Before (dotbot):**
```yaml
# hosts/air/config/app/config
setting=value_for_air
# hosts/lakka/config/app/config
setting=value_for_lakka
```
**After (chezmoi) - Option A:**
```
# dot_config/app/config.tmpl
{{ if .is_air -}}
setting=value_for_air
{{- else if .is_lakka -}}
setting=value_for_lakka
{{- end }}
```
**After (chezmoi) - Option B:**
```
# dot_config/app/config__air
setting=value_for_air
# dot_config/app/config__lakka
setting=value_for_lakka
```
### Example 2: Mostly Shared with Few Differences
**Before:**
100 lines shared, 5 lines different per host
**After (recommended - templates):**
```bash
# dot_config/app/config.tmpl
# ... 50 lines of shared config ...
{{ if .is_air }}
air_specific_setting=true
{{ else if .is_lakka }}
lakka_specific_setting=true
{{ end }}
# ... 50 more lines of shared config ...
```
### Example 3: Completely Different Configs
**Before:**
Two totally different config files
**After (recommended - separate files):**
```
dot_config/app/config__air
dot_config/app/config__lakka
```
### Example 4: Host-Specific Directories
**Before:**
```
hosts/air/config/air-only-app/
hosts/lakka/config/lakka-only-app/
```
**After - Use .chezmoiignore:**
```
# .chezmoiignore
{{ if ne .chezmoi.hostname "air" }}
dot_config/air-only-app/
{{ end }}
{{ if ne .chezmoi.hostname "lakka" }}
dot_config/lakka-only-app/
{{ end }}
```
Then create:
```
dot_config/air-only-app/ # Only applied on air
dot_config/lakka-only-app/ # Only applied on lakka
```
## Testing Host-Specific Configs
### Before Applying
```bash
# See what would be applied on this host
chezmoi diff
# See what a specific file would look like
chezmoi cat ~/.config/fish/config.fish
# Check template data
chezmoi data | grep hostname
```
### Simulating Other Hosts
```bash
# Test what would be applied on another host
chezmoi execute-template --init --promptString hostname=air "{{ .chezmoi.hostname }}"
# See what a file would look like on another host
# (This requires manual variable setting in templates)
```
### On Another Machine
```bash
# Initialize and test without applying
chezmoi init --dry-run --verbose ivuorinen
# Apply with dry-run
chezmoi apply --dry-run -v
```
## Migration Script Adjustments
Add to `migrate-to-chezmoi.sh`:
```bash
# Migrate host-specific configs
log_info "Processing host-specific configurations..."
CURRENT_HOST=$(hostname -s)
log_info "Current hostname: $CURRENT_HOST"
# Prompt for migration strategy
echo ""
log_warning "How do you want to handle host-specific configs?"
echo " 1) Merge into templates (recommended for small differences)"
echo " 2) Keep separate files per host (recommended for large differences)"
echo " 3) Manual (skip automatic migration)"
read -p "Choose (1/2/3): " -r STRATEGY
if [ "$STRATEGY" = "1" ]; then
log_info "Will merge into templates (requires manual editing after)"
# Create template files
# ... migration logic ...
elif [ "$STRATEGY" = "2" ]; then
log_info "Creating separate host-specific files..."
for host in air lakka tunkki s; do
if [ -d "hosts/$host" ]; then
log_info "Processing host: $host"
# Process host-specific base files
if [ -d "hosts/$host/base" ]; then
for file in hosts/$host/base/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
move_dotfiles "$file" "dot_${filename}__${host}" ""
fi
done
fi
# Process host-specific config files
if [ -d "hosts/$host/config" ]; then
for file in hosts/$host/config/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
dest="dot_config/$(dirname $file)__${host}"
move_dotfiles "$file" "$dest/$(basename $file)" ""
fi
done
fi
fi
done
else
log_info "Skipping automatic host-specific migration"
log_info "You'll need to manually migrate hosts/ directory"
fi
```
## Best Practices
1. **Start Simple**: Use separate files first, move to templates as you see patterns
2. **Don't Over-Template**: If a file is completely different per host, use separate files
3. **Document Hosts**: Add comments in `.chezmoi.yaml.tmpl` explaining each host
4. **Test Thoroughly**: Test on each host before committing
5. **Use Host Groups**: Group hosts (work/personal, laptop/desktop) for easier conditionals
## Checklist
- [ ] Identify all host-specific files
- [ ] Choose strategy per file (templates vs separate)
- [ ] Update `.chezmoi.yaml.tmpl` with host flags
- [ ] Migrate host-specific base files
- [ ] Migrate host-specific config files
- [ ] Update `.chezmoiignore` for host-specific directories
- [ ] Test on current host
- [ ] Test on other hosts
- [ ] Document which approach was used where
- [ ] Clean up old hosts/ directory
## Examples from Your Hosts
Based on your current structure:
### hosts/air/install.conf.yaml
```yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**Migration approach:**
- Check what's in `hosts/air/config/`
- If it's app configs, use separate files: `dot_config/app/config__air`
- If it's just a few lines different, merge into templates
### Common Pattern
For configurations that need host-specific values but share structure:
```yaml
# dot_config/app/config.tmpl
# Common settings
port=8080
# Host-specific
{{ if .is_air -}}
workspace=/Users/yourname/Work
{{- else if .is_lakka -}}
workspace=/Users/yourname/Projects
{{- end }}
# More common settings
debug=false
```
## Need Help?
If you're unsure about a specific file:
1. Check the diff: `diff hosts/air/file hosts/lakka/file`
2. Count different lines
3. If < 20% different use templates
4. If > 20% different → use separate files
Remember: You can always refactor later!

View File

@@ -0,0 +1,523 @@
# Migration Guide: Dotbot to Chezmoi
This guide documents the migration from dotbot to chezmoi for managing dotfiles.
## Table of Contents
1. [Why Migrate to Chezmoi?](#why-migrate-to-chezmoi)
2. [Key Differences](#key-differences)
3. [Dotbot to Chezmoi Mapping](#dotbot-to-chezmoi-mapping)
4. [New File Structure](#new-file-structure)
5. [Migration Steps](#migration-steps)
6. [Usage Guide](#usage-guide)
7. [Troubleshooting](#troubleshooting)
## Why Migrate to Chezmoi?
Chezmoi offers several advantages over dotbot:
- **Built-in templating**: Use Go templates for dynamic configuration
- **Secret management**: Native support for password managers (1Password, LastPass, etc.)
- **Cross-platform**: Better support for managing dotfiles across different OS and machines
- **State tracking**: Chezmoi tracks what it manages more precisely
- **Active development**: Regular updates and large community
- **No dependencies**: Single binary, no Python required
## Key Differences
### Philosophy
**Dotbot**:
- Configuration-driven (YAML files)
- Manages symlinks from a source directory
- Plugins extend functionality
**Chezmoi**:
- Source-state driven
- Copies files to home directory (can also use symlinks)
- Built-in templating for dynamic content
- Manages the entire lifecycle of dotfiles
### Directory Structure
**Dotbot**:
```
~/.dotfiles/
├── base/ # Files symlinked to ~/.*
├── config/ # Files symlinked to ~/.config/
├── local/ # Scripts and local files
├── install # Installation script
└── install.conf.yaml # Configuration
```
**Chezmoi**:
```
~/.local/share/chezmoi/ # Source directory
├── .chezmoi.yaml.tmpl # Configuration template
├── .chezmoiignore # Files to ignore
├── run_once_*.sh.tmpl # One-time setup scripts
├── run_*.sh.tmpl # Scripts that run on every apply
├── dot_bashrc # Becomes ~/.bashrc
├── dot_config/ # Becomes ~/.config/
└── private_dot_ssh/ # Becomes ~/.ssh/ with 0700
```
## Dotbot to Chezmoi Mapping
### 1. Link Directives
**Dotbot** (install.conf.yaml):
```yaml
- link:
~/.bashrc: base/bashrc
~/.config/fish: config/fish
```
**Chezmoi**:
- Files are automatically managed based on their names in the source directory
- `dot_bashrc``~/.bashrc`
- `dot_config/fish/``~/.config/fish/`
- Use `symlink_` prefix for symlinks: `symlink_dot_vim` → symlinked `~/.vim`
### 2. Create Directives
**Dotbot**:
```yaml
- create:
~/.ssh:
mode: 0700
~/.local/bin:
```
**Chezmoi**:
- Create a `run_once_after_create-directories.sh.tmpl` script
- Or use `.chezmoitemplates` for reusable directory creation
- Chezmoi automatically creates parent directories
### 3. Shell Commands
**Dotbot**:
```yaml
- shell:
- git submodule update --init --recursive
- bash local/bin/dfm install all
```
**Chezmoi**:
- Use `run_once_*.sh.tmpl` for one-time setup scripts
- Use `run_*.sh.tmpl` for scripts that run every time
- Use `run_before_*.sh` for scripts that run before applying
- Use `run_after_*.sh` for scripts that run after applying
### 4. Clean Directives
**Dotbot**:
```yaml
- clean:
~/:
~/.config:
recursive: true
```
**Chezmoi**:
- Chezmoi doesn't automatically remove files
- Use `chezmoi unmanaged` to see unmanaged files
- Manually remove or add to `.chezmoiignore`
### 5. Host-Specific Configuration
**Dotbot**:
```yaml
# hosts/air/install.conf.yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**Chezmoi**:
- Use templates with conditionals:
```
{{ if eq .chezmoi.hostname "air" }}
# air-specific content
{{ end }}
```
- Or use separate files: `dot_config/file.tmpl` with hostname checks
### 6. Dotbot Plugins
**dotbot-brew**:
- Replace with `run_once_after_install-packages.sh.tmpl`
- Use `brew bundle install`
**dotbot-asdf**:
- Chezmoi doesn't have built-in asdf support
- Use `run_once_after_*.sh` scripts to install asdf plugins
**dotbot-pip/pipx**:
- Use `run_once_after_*.sh` scripts
- Or use chezmoi's external management
## New File Structure
### Configuration Files
#### `.chezmoi.yaml.tmpl`
Main configuration file with template support. Defines:
- Source directory
- Data variables (hostname, OS, custom flags)
- Merge strategy
- Template options
- Git options
#### `.chezmoiignore`
Files and patterns to ignore when applying dotfiles. Includes:
- Repository management files (.git, .github, etc.)
- Documentation
- Development tools
- Old dotbot configuration
### Run Scripts
Scripts follow a naming convention:
- `run_once_before_*.sh.tmpl`: Runs once before applying (prerequisites)
- `run_once_after_*.sh.tmpl`: Runs once after applying (installation)
- `run_before_*.sh.tmpl`: Runs every time before applying
- `run_after_*.sh.tmpl`: Runs every time after applying
- `run_onchange_*.sh.tmpl`: Runs when file content changes
### File Naming
Chezmoi uses special prefixes:
- `dot_`: Becomes a dot file (`.`)
- `private_`: Sets permissions to 0600
- `executable_`: Makes file executable
- `symlink_`: Creates a symlink
- `readonly_`: Makes file read-only
Examples:
- `dot_bashrc``~/.bashrc`
- `private_dot_ssh/``~/.ssh/` (mode 0700)
- `executable_dot_local/bin/script``~/.local/bin/script` (executable)
## Migration Steps
### 1. Backup Current Setup
```bash
# Backup your current dotfiles
cd ~/.dotfiles
git add -A
git commit -m "Backup before chezmoi migration"
git push
```
### 2. Install Chezmoi
```bash
# The new install script will do this automatically
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
```
### 3. Initialize Chezmoi with Existing Dotfiles
```bash
# If you want to test before full migration
chezmoi init --apply ivuorinen
# Or initialize without applying
chezmoi init ivuorinen
```
### 4. Restructure Files (Manual Step)
You'll need to rename files to follow chezmoi conventions:
```bash
cd ~/.local/share/chezmoi
# Rename base files
mv base/bashrc dot_bashrc
mv base/zshrc dot_zshrc
mv base/tmux.conf dot_tmux.conf
# Move config files
mkdir -p dot_config
mv config/* dot_config/
# Move local/bin files
mkdir -p dot_local/bin
for file in local/bin/*; do
mv "$file" "executable_dot_local/bin/$(basename "$file")"
done
# Move SSH files with proper permissions
mkdir -p private_dot_ssh
mv ssh/* private_dot_ssh/
```
### 5. Convert Host-Specific Configurations
For files that differ between hosts, use templates:
```bash
# Instead of hosts/air/config/fish/config.fish
# Create: dot_config/fish/config.fish.tmpl
{{ if eq .chezmoi.hostname "air" }}
# air-specific configuration
{{ else if eq .chezmoi.hostname "lakka" }}
# lakka-specific configuration
{{ end }}
```
### 6. Test the Migration
```bash
# See what changes chezmoi would make
chezmoi diff
# Apply changes
chezmoi apply
# Verify everything works
chezmoi verify
```
### 7. Clean Up Old Files
```bash
# Remove dotbot directories (after confirming everything works)
cd ~/.local/share/chezmoi
rm -rf tools/dotbot tools/dotbot-*
rm install.conf.yaml
rm -rf hosts/ # If fully migrated to templates
```
## Usage Guide
### Basic Commands
```bash
# Initialize chezmoi with your dotfiles
chezmoi init ivuorinen
# See what changes would be made
chezmoi diff
# Apply dotfiles
chezmoi apply
# Apply with verbose output
chezmoi apply -v
# Edit a file managed by chezmoi
chezmoi edit ~/.bashrc
# Add a new file to chezmoi
chezmoi add ~/.newfile
# Update dotfiles from source
chezmoi update
# See what files are managed
chezmoi managed
# See what files are unmanaged
chezmoi unmanaged
# Re-run scripts
chezmoi apply --force
# Check for issues
chezmoi doctor
```
### Working with Templates
```bash
# Execute a template
chezmoi execute-template "{{ .chezmoi.hostname }}"
# See the data available in templates
chezmoi data
# Edit template data
chezmoi edit-config
```
### Managing Secrets
```bash
# Use with 1Password
chezmoi secret keychain
# Template with 1Password
{{ (index (onepasswordDocument "my-secret") 0).content }}
# Use with environment variables
{{ .Env.MY_SECRET }}
```
### Updating Dotfiles
```bash
# Edit source file
chezmoi edit ~/.bashrc
# Or edit directly and add
vi ~/.bashrc
chezmoi add ~/.bashrc
# Commit changes
cd $(chezmoi source-path)
git add -A
git commit -m "Update bashrc"
git push
# On another machine
chezmoi update
```
## Troubleshooting
### Common Issues
#### 1. File Permissions
**Problem**: Files have wrong permissions after applying.
**Solution**: Use prefixes:
```bash
# For 0600 permissions
chezmoi add --template private_dot_ssh/config
# For 0700 directories
mkdir -p private_dot_ssh
```
#### 2. Symlinks Not Working
**Problem**: Chezmoi copies files instead of symlinking.
**Solution**: Use `symlink_` prefix:
```bash
chezmoi add --symlink ~/.vim
# This creates symlink_dot_vim in the source directory
```
#### 3. Templates Not Rendering
**Problem**: Template syntax is showing literally in files.
**Solution**:
- Ensure file has `.tmpl` extension
- Check template syntax
- Verify data with `chezmoi data`
#### 4. Scripts Not Running
**Problem**: `run_once_` scripts not executing.
**Solution**:
- Check script permissions: `chmod +x run_once_*.sh.tmpl`
- Run with force: `chezmoi apply --force`
- Check script order (before/after)
#### 5. Host-Specific Files Not Applying
**Problem**: Wrong host configuration applied.
**Solution**:
- Check hostname: `chezmoi data | grep hostname`
- Verify template conditionals
- Use `.chezmoiignore` for host-specific exclusions
### Debugging
```bash
# Verbose output
chezmoi apply -v
# Very verbose output
chezmoi apply -vv
# Dry run to see what would happen
chezmoi apply --dry-run -v
# Check configuration
chezmoi doctor
# Verify state
chezmoi verify
# See source directory
chezmoi source-path
# See what would be applied to a specific file
chezmoi cat ~/.bashrc
```
### Migration Checklist
- [ ] Backup current dotfiles
- [ ] Install chezmoi
- [ ] Create `.chezmoi.yaml.tmpl`
- [ ] Create `.chezmoiignore`
- [ ] Rename files with proper prefixes
- [ ] Convert host-specific configs to templates
- [ ] Create `run_once_before` scripts
- [ ] Create `run_once_after` scripts
- [ ] Test with `chezmoi diff`
- [ ] Apply with `chezmoi apply`
- [ ] Verify everything works
- [ ] Update documentation
- [ ] Clean up old dotbot files
- [ ] Update README.md
- [ ] Test on another machine
## Additional Resources
- [Chezmoi Documentation](https://www.chezmoi.io/)
- [Chezmoi Quick Start](https://www.chezmoi.io/quick-start/)
- [Chezmoi User Guide](https://www.chezmoi.io/user-guide/)
- [Chezmoi Template Reference](https://www.chezmoi.io/reference/templates/)
- [Example Dotfiles Using Chezmoi](https://github.com/topics/chezmoi)
## Notes
### What Stays the Same
- Your actual dotfile contents
- Directory structure in home directory
- Git workflow for managing dotfiles
- The `dfm` script functionality (wrapped in run_once scripts)
### What Changes
- Installation method (new `install` script)
- Source directory location (`~/.local/share/chezmoi` by default)
- Configuration method (templates instead of YAML)
- File naming (special prefixes)
- No more symlinks by default (unless specified)
### Benefits of Migration
1. **Simplicity**: Single binary, no dependencies
2. **Templating**: Dynamic content based on hostname, OS, etc.
3. **Secrets**: Built-in support for password managers
4. **State Management**: Better tracking of what's managed
5. **Cross-platform**: Excellent support for different OSes
6. **Documentation**: Extensive docs and examples
7. **Community**: Active development and support
## Post-Migration
After successful migration:
1. Update your README to reflect chezmoi usage
2. Archive dotbot configuration for reference
3. Document any custom scripts or workflows
4. Test on all your machines
5. Share your experience!

View File

@@ -33,8 +33,10 @@ Leader: `<ctrl><space>`
? List key bindings
D Choose and detach a client from a list
E Spread panes out evenly
L Switch to the last client
L last-session (via sesh)
M Clear the marked pane
N sesh ui
T tms
] Paste the most recent paste buffer
c Create a new window
d Detach the current client
@@ -46,7 +48,7 @@ Leader: `<ctrl><space>`
o Select the next pane
q Display pane numbers
s Choose a session from a list
t tms
t sesh selection
w Choose a window from a list
x Kill the active pane
z Zoom the active pane
@@ -74,8 +76,6 @@ Leader: `<ctrl><space>`
M-Left Resize the pane left by 5
M-Right Resize the pane right by 5
C-o Rotate through the panes
C-r tms refresh
C-s tms switch
C-w tms windows
C-z Suspend the current client
C-Up Resize the pane up
@@ -87,3 +87,4 @@ Leader: `<ctrl><space>`
S-Left Move the visible part of the window left
S-Right Move the visible part of the window right
```

37
install
View File

@@ -1,38 +1,5 @@
#!/usr/bin/env bash
set -e
CONFIG="install.conf.yaml"
DOTBOT_DIR="tools/dotbot"
DOTBOT_BIN="bin/dotbot"
BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTBOT_BIN_PATH="${BASEDIR}/${DOTBOT_DIR}/${DOTBOT_BIN}"
DOTBOT_HOST="$(hostname -s)"
cd "${BASEDIR}"
git -C "${DOTBOT_DIR}" submodule sync --quiet --recursive
git submodule update --init --recursive "${DOTBOT_DIR}"
"${DOTBOT_BIN_PATH}" \
-d "${BASEDIR}" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "${CONFIG}" \
"${@}"
if [ "${DOTBOT_HOST}" != "" ]; then
DOTBOT_HOST_CONFIG="${BASEDIR}/hosts/${DOTBOT_HOST}/${CONFIG}"
echo "-> Trying if host config can be found: ${DOTBOT_HOST_CONFIG}"
[ -r "$DOTBOT_HOST_CONFIG" ] && [ -f "$DOTBOT_HOST_CONFIG" ] &&
echo "(!) Found $DOTBOT_HOST_CONFIG" &&
"$DOTBOT_BIN_PATH" \
-d "$BASEDIR" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "$DOTBOT_HOST_CONFIG" \
"${@}"
fi
# Install and apply chezmoi
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen

260
migrate-to-chezmoi.sh Executable file
View File

@@ -0,0 +1,260 @@
#!/usr/bin/env bash
# Migration helper script: Dotbot to Chezmoi
# This script helps restructure files from dotbot format to chezmoi format
#
# IMPORTANT: Review changes carefully before running!
# It's recommended to run this in a new git branch
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() {
echo -e "${BLUE}${NC} $1"
}
log_success() {
echo -e "${GREEN}${NC} $1"
}
log_warning() {
echo -e "${YELLOW}${NC} $1"
}
log_error() {
echo -e "${RED}${NC} $1"
}
# Check if we're in a git repository
if [ ! -d .git ]; then
log_error "Not a git repository. Please run from your dotfiles directory."
exit 1
fi
# Confirm with user
log_warning "This script will restructure your dotfiles for chezmoi."
log_warning "It's STRONGLY recommended to:"
log_warning " 1. Commit all current changes"
log_warning " 2. Create a new branch for migration"
log_warning " 3. Review all changes before merging"
echo ""
read -p "Do you want to continue? (yes/no): " -r
echo
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
log_info "Migration cancelled."
exit 0
fi
# Create backup branch
log_info "Creating backup branch..."
BACKUP_BRANCH="backup-before-chezmoi-$(date +%Y%m%d-%H%M%S)"
git branch "$BACKUP_BRANCH"
log_success "Created backup branch: $BACKUP_BRANCH"
# Create migration branch
log_info "Creating migration branch..."
MIGRATION_BRANCH="migrate-to-chezmoi"
git checkout -b "$MIGRATION_BRANCH" 2>/dev/null || git checkout "$MIGRATION_BRANCH"
log_success "Switched to migration branch: $MIGRATION_BRANCH"
# Function to move and rename files
move_dotfiles() {
local src=$1
local dest=$2
local prefix=$3
if [ -f "$src" ]; then
mkdir -p "$(dirname "$dest")"
log_info "Moving: $src$dest"
git mv "$src" "$dest" 2>/dev/null || mv "$src" "$dest"
fi
}
# Migrate base files (these become dot_ files)
log_info "Migrating base files..."
if [ -d base ]; then
for file in base/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
# Skip certain files
if [[ "$filename" =~ \.(md|MD)$ ]]; then
continue
fi
move_dotfiles "$file" "dot_${filename}" ""
fi
done
log_success "Base files migrated"
fi
# Migrate config directory
log_info "Migrating config directory..."
if [ -d config ]; then
# Create dot_config if it doesn't exist
mkdir -p dot_config
for item in config/*; do
if [ -e "$item" ]; then
basename_item=$(basename "$item")
# Skip certain directories
if [[ "$basename_item" == "homebrew" ]] || [[ "$basename_item" == "shared.sh" ]]; then
log_info "Keeping $item in place (referenced by scripts)"
continue
fi
log_info "Moving: $item → dot_config/$basename_item"
git mv "$item" "dot_config/$basename_item" 2>/dev/null || mv "$item" "dot_config/$basename_item"
fi
done
log_success "Config files migrated"
fi
# Migrate local/bin with executable prefix
log_info "Migrating local/bin scripts..."
if [ -d local/bin ]; then
mkdir -p executable_dot_local/bin
for script in local/bin/*; do
if [ -f "$script" ]; then
basename_script=$(basename "$script")
log_info "Moving: $script → executable_dot_local/bin/$basename_script"
git mv "$script" "executable_dot_local/bin/$basename_script" 2>/dev/null || \
mv "$script" "executable_dot_local/bin/$basename_script"
fi
done
log_success "Local bin scripts migrated"
fi
# Migrate local/share
log_info "Migrating local/share..."
if [ -d local/share ]; then
mkdir -p dot_local/share
for item in local/share/*; do
if [ -e "$item" ]; then
basename_item=$(basename "$item")
log_info "Moving: $item → dot_local/share/$basename_item"
git mv "$item" "dot_local/share/$basename_item" 2>/dev/null || \
mv "$item" "dot_local/share/$basename_item"
fi
done
log_success "Local share migrated"
fi
# Migrate local/man
log_info "Migrating local/man..."
if [ -d local/man ]; then
mkdir -p dot_local/man
for item in local/man/*; do
if [ -e "$item" ]; then
basename_item=$(basename "$item")
log_info "Moving: $item → dot_local/man/$basename_item"
git mv "$item" "dot_local/man/$basename_item" 2>/dev/null || \
mv "$item" "dot_local/man/$basename_item"
fi
done
log_success "Local man pages migrated"
fi
# Migrate SSH files with private prefix
log_info "Migrating SSH files..."
if [ -d ssh ]; then
mkdir -p private_dot_ssh
for item in ssh/*; do
if [ -f "$item" ]; then
basename_item=$(basename "$item")
log_info "Moving: $item → private_dot_ssh/$basename_item"
git mv "$item" "private_dot_ssh/$basename_item" 2>/dev/null || \
mv "$item" "private_dot_ssh/$basename_item"
fi
done
log_success "SSH files migrated"
fi
# Clean up empty directories
log_info "Cleaning up empty directories..."
find . -type d -empty -delete 2>/dev/null || true
log_success "Empty directories removed"
# Create README for old structure
log_info "Creating migration notes..."
cat > MIGRATION-NOTES.md << 'EOF'
# Migration Notes
This repository has been migrated from dotbot to chezmoi.
## Old Structure (Dotbot)
```
~/.dotfiles/
├── base/ # Files symlinked to ~/.*
├── config/ # Files symlinked to ~/.config/
├── local/ # Scripts and local files
├── ssh/ # SSH configuration
├── install # Dotbot installation script
└── install.conf.yaml # Dotbot configuration
```
## New Structure (Chezmoi)
```
~/.dotfiles/ (or ~/.local/share/chezmoi)
├── dot_* # Files that become ~/.*
├── dot_config/ # Files that become ~/.config/
├── executable_dot_local/ # Executable scripts
├── private_dot_ssh/ # SSH files with 0700 permissions
├── run_once_*.sh.tmpl # One-time setup scripts
├── .chezmoi.yaml.tmpl # Chezmoi configuration
└── .chezmoiignore # Files to ignore
```
## File Naming Conventions
- `dot_bashrc``~/.bashrc`
- `dot_config/fish/``~/.config/fish/`
- `private_dot_ssh/``~/.ssh/` (mode 0700)
- `executable_dot_local/bin/script``~/.local/bin/script` (executable)
- `symlink_dot_vim``~/.vim` (symlink)
## Next Steps
1. Review the migration with: `git diff`
2. Test with chezmoi: `chezmoi init --dry-run --verbose $(pwd)`
3. Apply if everything looks good: `chezmoi init --apply $(pwd)`
4. Read the full migration guide: `MIGRATION-DOTBOT-TO-CHEZMOI.md`
## Backup
A backup branch was created: `$BACKUP_BRANCH`
You can switch back with: `git checkout $BACKUP_BRANCH`
EOF
log_success "Migration notes created: MIGRATION-NOTES.md"
# Show summary
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_success "Migration complete!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
log_info "Summary:"
echo " • Backup branch: $BACKUP_BRANCH"
echo " • Migration branch: $MIGRATION_BRANCH"
echo ""
log_info "Next steps:"
echo " 1. Review changes: git status && git diff"
echo " 2. Test with chezmoi: chezmoi init --dry-run --verbose \$(pwd)"
echo " 3. Read migration guide: cat MIGRATION-DOTBOT-TO-CHEZMOI.md"
echo " 4. Commit changes: git add -A && git commit -m 'Migrate to chezmoi'"
echo ""
log_warning "IMPORTANT: Review all changes before committing!"
log_warning "Test thoroughly before applying to your home directory!"
echo ""

View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# run_once_after script to create required directories
# This runs once after applying dotfiles
set -e
echo "→ Creating required directories..."
# Create directories with proper permissions
mkdir -p "$HOME/.cache"
mkdir -p "$HOME/.cache/git"
mkdir -p "$HOME/.config"
mkdir -p "$HOME/.local"
mkdir -p "$HOME/.local/bin"
mkdir -p "$HOME/.local/run"
mkdir -p "$HOME/.local/share"
mkdir -p "$HOME/.local/state"
mkdir -p "$HOME/.local/state/tmux"
mkdir -p "$HOME/.local/state/zsh"
mkdir -p "$HOME/Code"
# Create directories with restricted permissions
mkdir -p "$HOME/.local/share/gnupg"
chmod 0700 "$HOME/.local/share/gnupg"
mkdir -p "$HOME/.ssh"
chmod 0700 "$HOME/.ssh"
mkdir -p "$HOME/.ssh/local.d"
chmod 0700 "$HOME/.ssh/local.d"
echo "✓ Directories created!"

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# run_once_after script to install packages
# This runs once after applying dotfiles
set -e
DOTFILES="{{ .chezmoi.sourceDir }}"
export DOTFILES
# Source shared configuration
if [ -f "$DOTFILES/config/shared.sh" ]; then
source "$DOTFILES/config/shared.sh"
fi
# Source message helper if available
if [ -f "$DOTFILES/local/bin/msgr" ]; then
source "$DOTFILES/local/bin/msgr"
fi
echo "→ Installing packages..."
{{- if .is_macos }}
# Install Homebrew packages
if [ -f "$DOTFILES/config/homebrew/Brewfile" ]; then
echo "→ Installing Homebrew packages..."
brew bundle install --file="$DOTFILES/config/homebrew/Brewfile" --no-lock || true
fi
# Setup macOS defaults
if [ -f "$DOTFILES/scripts/install-macos-defaults.sh" ]; then
echo "→ Setting up macOS defaults..."
bash "$DOTFILES/scripts/install-macos-defaults.sh" || true
fi
{{- end }}
{{- if .is_linux }}
# Install apt packages if on Debian/Ubuntu
if command -v apt &> /dev/null && [ -f "$DOTFILES/tools/apt.txt" ]; then
echo "→ Installing apt packages..."
sudo apt install -y $(grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" | sed -e 's/#.*//' | tr '\n' ' ') || true
fi
{{- end }}
# Install pipx packages
if command -v pipx &> /dev/null && [ -f "$DOTFILES/tools/requirements-pipx.txt" ]; then
echo "→ Installing pipx packages..."
while IFS= read -r package; do
[ -z "$package" ] || pipx install "$package" || true
done < "$DOTFILES/tools/requirements-pipx.txt"
fi
echo "✓ Packages installed!"

View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# run_once_after script to setup programming languages and tools
# This runs once after applying dotfiles
set -e
DOTFILES="{{ .chezmoi.sourceDir }}"
export DOTFILES
echo "→ Setting up programming languages and tools..."
# Install fonts
if [ -f "$DOTFILES/scripts/install-fonts.sh" ]; then
echo "→ Installing fonts..."
bash "$DOTFILES/scripts/install-fonts.sh" || true
fi
# Install Cargo packages
if command -v cargo &> /dev/null && [ -f "$DOTFILES/scripts/install-cargo-packages.sh" ]; then
echo "→ Installing Cargo packages..."
bash "$DOTFILES/scripts/install-cargo-packages.sh" || true
fi
# Install Go packages
if command -v go &> /dev/null && [ -f "$DOTFILES/scripts/install-go-packages.sh" ]; then
echo "→ Installing Go packages..."
bash "$DOTFILES/scripts/install-go-packages.sh" || true
fi
# Install Composer
if [ -f "$DOTFILES/scripts/install-composer.sh" ]; then
echo "→ Installing Composer..."
bash "$DOTFILES/scripts/install-composer.sh" || true
fi
# Install NVM
if [ ! -d "$HOME/.nvm" ] && command -v curl &> /dev/null; then
echo "→ Installing NVM..."
NVM_VERSION=$(curl -s https://api.github.com/repos/nvm-sh/nvm/releases/latest | grep -o '"tag_name": "[^"]*' | cut -d'"' -f4)
PROFILE=/dev/null bash -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash" || true
fi
# Install latest Node LTS
if [ -s "$HOME/.nvm/nvm.sh" ]; then
echo "→ Installing latest Node LTS..."
source "$HOME/.nvm/nvm.sh"
nvm install --lts --latest-npm --default || true
fi
# Install NPM packages
if command -v npm &> /dev/null && [ -f "$DOTFILES/scripts/install-npm-packages.sh" ]; then
echo "→ Installing NPM packages..."
bash "$DOTFILES/scripts/install-npm-packages.sh" || true
fi
# Install GitHub CLI extensions
if command -v gh &> /dev/null && [ -f "$DOTFILES/scripts/install-gh-extensions.sh" ]; then
echo "→ Installing GitHub CLI extensions..."
bash "$DOTFILES/scripts/install-gh-extensions.sh" || true
fi
# Install z
if [ -f "$DOTFILES/scripts/install-z.sh" ]; then
echo "→ Installing z..."
bash "$DOTFILES/scripts/install-z.sh" || true
fi
# Install cheat databases
for database in "$DOTFILES"/scripts/install-cheat-*; do
if [ -f "$database" ]; then
echo "→ Installing $(basename "$database")..."
bash "$database" || true
fi
done
echo "✓ Programming languages and tools setup complete!"

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# run_once_before script to install prerequisites
# This runs once before applying dotfiles
set -e
echo "→ Installing prerequisites..."
{{- if .is_macos }}
# Install Homebrew if not present
if ! command -v brew &> /dev/null; then
echo "→ Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
# Install Xcode CLI tools if needed
if ! xcode-select -p &> /dev/null; then
echo "→ Installing Xcode Command Line Tools..."
xcode-select --install || true
fi
{{- end }}
{{- if .is_linux }}
# Update package manager
if command -v apt &> /dev/null; then
echo "→ Updating apt..."
sudo apt update
fi
{{- end }}
echo "✓ Prerequisites installed!"