Kaynağa Gözat

Add multi-host dotfiles support with groups and in-file markers

- Groups system: groups.<hostname> files define host membership (e.g., wayland)
- In-file markers: # @host <name> / # @end for per-host config sections
- Files with markers are processed and written with a warning header
- Files without markers remain symlinked (backward compatible)
- Resolution order: common -> groups (alpha) -> host-specific overrides
- Migrate sway, waybar configs to use @host markers for jellyfish/tompot
- Move tompot's alacritty config to dots.tompot/ override
- Clean up stale backup and temp files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
G. Capella 23 saat önce
ebeveyn
işleme
2d48e25952

+ 15 - 0
dots.tompot/.config/alacritty/alacritty.toml

@@ -0,0 +1,15 @@
+[font]
+size = 13
+
+[font.bold]
+style = "Bold"
+
+[font.bold_italic]
+style = "Bold Italic"
+
+[font.italic]
+style = "Italic"
+
+[font.normal]
+family="Ubuntu Mono derivative Powerline"
+style = "Regular"

+ 7 - 8
dots/.config/alacritty/alacritty.toml

@@ -1,5 +1,5 @@
 [font]
-size = 13
+size = 9
 
 [font.bold]
 style = "Bold"
@@ -11,11 +11,10 @@ style = "Bold Italic"
 style = "Italic"
 
 [font.normal]
-# family = "JetBrainsMono"
-# family="Unifont"
-
-# family = "xos4 Terminess Powerline"
-family="Ubuntu Mono derivative Powerline"
-# family="FreeMono"
-# family="JetBrainsMono"
+family = "JetBrains Mono"
 style = "Regular"
+
+[[keyboard.bindings]]
+key = "Return"
+mods = "Shift"
+chars = "\u001B\r"

+ 0 - 18
dots/.config/alacritty/alacritty.yml

@@ -1,18 +0,0 @@
-font:
-  normal:
-    family: "Adwaita Sans"
-    style: Regular
-
-  bold:
-    family: "Adwaita Sans"
-    style: Bold
-
-  italic:
-    family: "Adwaita Sans"
-    style: Italic
-
-  bold_italic:
-    family: "Adwaita Sans"
-    style: Bold Italic
-
-  size: 12

+ 14 - 0
dots/.config/fish/conf.d/fish_frozen_key_bindings.fish

@@ -0,0 +1,14 @@
+# This file was created by fish when upgrading to version 4.3, to migrate
+# the 'fish_key_bindings' variable from its old default scope (universal)
+# to its new default scope (global).  We recommend you delete this file
+# and configure key bindings in ~/.config/fish/config.fish if needed.
+
+set --global fish_key_bindings fish_vi_key_bindings
+
+# Prior to version 4.3, fish shipped an event handler that runs
+# `set --universal fish_key_bindings fish_default_key_bindings`
+# whenever the fish_key_bindings variable is erased.
+# This means that as long as any fish < 4.3 is still running on this system,
+# we cannot complete the migration.
+# As a workaround, erase the universal variable at every shell startup.
+set --erase --universal fish_key_bindings

+ 14 - 0
dots/.config/fish/conf.d/fish_frozen_key_bindings.fish.bak

@@ -0,0 +1,14 @@
+# This file was created by fish when upgrading to version 4.3, to migrate
+# the 'fish_key_bindings' variable from its old default scope (universal)
+# to its new default scope (global).  We recommend you delete this file
+# and configure key bindings in ~/.config/fish/config.fish if needed.
+
+set --global fish_key_bindings fish_vi_key_bindings
+
+# Prior to version 4.3, fish shipped an event handler that runs
+# `set --universal fish_key_bindings fish_default_key_bindings`
+# whenever the fish_key_bindings variable is erased.
+# This means that as long as any fish < 4.3 is still running on this system,
+# we cannot complete the migration.
+# As a workaround, erase the universal variable at every shell startup.
+set --erase --universal fish_key_bindings

+ 38 - 0
dots/.config/fish/conf.d/fish_frozen_theme.fish

@@ -0,0 +1,38 @@
+# This file was created by fish when upgrading to version 4.3, to migrate
+# theme variables from universal to global scope.
+# Don't edit this file, as it will be written by the web-config tool (`fish_config`).
+# To customize your theme, delete this file and see
+#     help interactive#syntax-highlighting
+# or
+#     man fish-interactive | less +/^SYNTAX.HIGHLIGHTING
+# for appropriate commands to add to ~/.config/fish/config.fish instead.
+# See also the release notes for fish 4.3.0 (run `help relnotes`).
+
+set --global fish_color_autosuggestion 555
+set --global fish_color_cancel -r
+set --global fish_color_command 005fd7
+set --global fish_color_comment 990000
+set --global fish_color_cwd green
+set --global fish_color_cwd_root red
+set --global fish_color_end 009900
+set --global fish_color_error ff0000
+set --global fish_color_escape bryellow --bold
+set --global fish_color_history_current --bold
+set --global fish_color_host normal
+set --global fish_color_host_remote yellow
+set --global fish_color_match --background=brblue
+set --global fish_color_normal normal
+set --global fish_color_operator bryellow
+set --global fish_color_param 00afff
+set --global fish_color_quote 999900
+set --global fish_color_redirection 00afff
+set --global fish_color_search_match white --background=brblack
+set --global fish_color_selection white --bold --background=brblack
+set --global fish_color_status red
+set --global fish_color_user brgreen
+set --global fish_color_valid_path --underline
+set --global fish_pager_color_completion
+set --global fish_pager_color_description B3A06D yellow
+set --global fish_pager_color_prefix white --bold --underline
+set --global fish_pager_color_progress brwhite --background=cyan
+set --global fish_pager_color_selected_background -r

+ 38 - 0
dots/.config/fish/conf.d/fish_frozen_theme.fish.bak

@@ -0,0 +1,38 @@
+# This file was created by fish when upgrading to version 4.3, to migrate
+# theme variables from universal to global scope.
+# Don't edit this file, as it will be written by the web-config tool (`fish_config`).
+# To customize your theme, delete this file and see
+#     help interactive#syntax-highlighting
+# or
+#     man fish-interactive | less +/^SYNTAX.HIGHLIGHTING
+# for appropriate commands to add to ~/.config/fish/config.fish instead.
+# See also the release notes for fish 4.3.0 (run `help relnotes`).
+
+set --global fish_color_autosuggestion 555
+set --global fish_color_cancel -r
+set --global fish_color_command 005fd7
+set --global fish_color_comment 990000
+set --global fish_color_cwd green
+set --global fish_color_cwd_root red
+set --global fish_color_end 009900
+set --global fish_color_error ff0000
+set --global fish_color_escape bryellow --bold
+set --global fish_color_history_current --bold
+set --global fish_color_host normal
+set --global fish_color_host_remote yellow
+set --global fish_color_match --background=brblue
+set --global fish_color_normal normal
+set --global fish_color_operator bryellow
+set --global fish_color_param 00afff
+set --global fish_color_quote 999900
+set --global fish_color_redirection 00afff
+set --global fish_color_search_match white --background=brblack
+set --global fish_color_selection white --bold --background=brblack
+set --global fish_color_status red
+set --global fish_color_user brgreen
+set --global fish_color_valid_path --underline
+set --global fish_pager_color_completion
+set --global fish_pager_color_description B3A06D yellow
+set --global fish_pager_color_prefix white --bold --underline
+set --global fish_pager_color_progress brwhite --background=cyan
+set --global fish_pager_color_selected_background -r

+ 0 - 62
dots/.config/fish/config.fish.backup

@@ -1,62 +0,0 @@
-set fish_greeting "Capella"
-
-export PATH="/usr/local/bin:/bin:/usr/sbin:/sbin:/usr/bin/"
-export PATH="$PATH:$HOME/.node/bin"
-export PATH="$PATH:$HOME/go/bin"
-
-# test -e {$HOME}/.iterm2_shell_integration.fish ; and source {$HOME}/.iterm2_shell_integration.fish
-# set -g fish_user_paths "/usr/local/sbin" $fish_user_paths
-# set -g fish_user_paths "/usr/local/opt/gnu-getopt/bin" $fish_user_paths
-
-# #if status is-interactive
-# #and not set -q TMUX
-# #    exec tmux
-# #end
-
-
-# # The next line updates PATH for the Google Cloud SDK.
-# if [ -f '/Users/gabrielcapella/.g/google-cloud-sdk/path.fish.inc' ]; . '/Users/gabrielcapella/.g/google-cloud-sdk/path.fish.inc'; end
-# set -g fish_user_paths "/usr/local/opt/openssl@1.1/bin" $fish_user_paths
-
-
-# status --is-interactive; and source (rbenv init -|psub)
-
-
-# # Add environment variable COCOS_CONSOLE_ROOT for cocos2d-x
-# export COCOS_CONSOLE_ROOT="/Users/gabrielcapella/cocos2d-x/tools/cocos2d-console/bin"
-# export PATH="$COCOS_CONSOLE_ROOT:$PATH"
-
-# # Add environment variable COCOS_X_ROOT for cocos2d-x
-# export COCOS_X_ROOT="/Users/gabrielcapella"
-# export PATH="$COCOS_X_ROOT:$PATH"
-
-# # Add environment variable COCOS_TEMPLATES_ROOT for cocos2d-x
-# export COCOS_TEMPLATES_ROOT="/Users/gabrielcapella/cocos2d-x/templates"
-# export PATH="$COCOS_TEMPLATES_ROOT:$PATH"
-
-# # Add environment variable ANDROID_SDK_ROOT for cocos2d-x
-export ANDROID_SDK_ROOT="/Users/gabrielcapella/Library/Android/sdk"
-export PATH="$ANDROID_SDK_ROOT:$PATH"
-export PATH="$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:$PATH"
-export ANDROID_AVD_HOME="$HOME/.android/"
-
-
-# # Add environment variable NDK_ROOT for cocos2d-x
-# export NDK_ROOT="/Users/gabrielcapella/Library/Android/sdk/ndk-bundle/"
-# export PATH="$NDK_ROOT:$PATH"
-
-# # Add environment variable SDKBOX_HOME for sdkbox installer
-# export SDKBOX_HOME="/Users/gabrielcapella/.sdkbox"
-
-# export PATH="/usr/bin/:$PATH"
-function subl;
-	"/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" $argv;
-end
-
-alias pb='curl -s --data-binary @- https://p.capella.pro/ | awk \'{ print "https://p.capella.pro/"$0; }\' | tee /tmp/pb | pbcopy && cat /tmp/pb'
-
-# The next line updates PATH for the Google Cloud SDK.
-if [ -f '/Users/gabrielcapella/Documents/google-cloud-sdk/path.fish.inc' ]; . '/Users/gabrielcapella/Documents/google-cloud-sdk/path.fish.inc'; end
-
-alias syncdots='curl https://git.capella.pro/capella/dotfiles/raw/master/start | bash -s -- sync'
-

+ 0 - 3
dots/.config/fish/fish/config.fish

@@ -1,3 +0,0 @@
-if status is-interactive
-    # Commands to run in interactive sessions can go here
-end

+ 0 - 31
dots/.config/fish/fish/fish_variables

@@ -1,31 +0,0 @@
-# This file contains fish universal variable definitions.
-# VERSION: 3.0
-SETUVAR __fish_initialized:3400
-SETUVAR fish_color_autosuggestion:555\x1ebrblack
-SETUVAR fish_color_cancel:\x2dr
-SETUVAR fish_color_command:blue
-SETUVAR fish_color_comment:red
-SETUVAR fish_color_cwd:green
-SETUVAR fish_color_cwd_root:red
-SETUVAR fish_color_end:green
-SETUVAR fish_color_error:brred
-SETUVAR fish_color_escape:brcyan
-SETUVAR fish_color_history_current:\x2d\x2dbold
-SETUVAR fish_color_host:normal
-SETUVAR fish_color_host_remote:yellow
-SETUVAR fish_color_normal:normal
-SETUVAR fish_color_operator:brcyan
-SETUVAR fish_color_param:cyan
-SETUVAR fish_color_quote:yellow
-SETUVAR fish_color_redirection:cyan\x1e\x2d\x2dbold
-SETUVAR fish_color_search_match:bryellow\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_status:red
-SETUVAR fish_color_user:brgreen
-SETUVAR fish_color_valid_path:\x2d\x2dunderline
-SETUVAR fish_key_bindings:fish_default_key_bindings
-SETUVAR fish_pager_color_completion:normal
-SETUVAR fish_pager_color_description:B3A06D\x1eyellow\x1e\x2di
-SETUVAR fish_pager_color_prefix:normal\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
-SETUVAR fish_pager_color_selected_background:\x2dr

+ 1 - 1
dots/.config/fish/fish_variables

@@ -30,7 +30,7 @@ SETUVAR fish_color_user:brgreen
 SETUVAR fish_color_valid_path:\x2d\x2dunderline
 SETUVAR fish_greeting:Capella
 SETUVAR fish_key_bindings:fish_vi_key_bindings
-SETUVAR fish_most_recent_dir:/home/capella
+SETUVAR fish_most_recent_dir:/home/capella/\x2edofiles/dotfiles
 SETUVAR fish_pager_color_completion:\x1d
 SETUVAR fish_pager_color_description:B3A06D\x1eyellow
 SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline

+ 0 - 39
dots/.config/fish/fish_variables.MKfPab

@@ -1,39 +0,0 @@
-# This file contains fish universal variable definitions.
-# VERSION: 3.0
-SETUVAR __fish_classic_git_prompt_initialized:\x1d
-SETUVAR __fish_init_2_39_8:\x1d
-SETUVAR __fish_init_2_3_0:\x1d
-SETUVAR __fish_initialized:3800
-SETUVAR _fish_abbr_l:ls
-SETUVAR fish_color_autosuggestion:555
-SETUVAR fish_color_cancel:\x2dr
-SETUVAR fish_color_command:005fd7
-SETUVAR fish_color_comment:990000
-SETUVAR fish_color_cwd:green
-SETUVAR fish_color_cwd_root:red
-SETUVAR fish_color_end:009900
-SETUVAR fish_color_error:ff0000
-SETUVAR fish_color_escape:bryellow\x1e\x2d\x2dbold
-SETUVAR fish_color_history_current:\x2d\x2dbold
-SETUVAR fish_color_host:normal
-SETUVAR fish_color_host_remote:yellow
-SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue
-SETUVAR fish_color_normal:normal
-SETUVAR fish_color_operator:bryellow
-SETUVAR fish_color_param:00afff
-SETUVAR fish_color_quote:999900
-SETUVAR fish_color_redirection:00afff
-SETUVAR fish_color_search_match:white\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_status:red
-SETUVAR fish_color_user:brgreen
-SETUVAR fish_color_valid_path:\x2d\x2dunderline
-SETUVAR fish_greeting:Capella
-SETUVAR fish_key_bindings:fish_vi_key_bindings
-SETUVAR fish_most_recent_dir:/home/capella/\x2egcloud/google\x2dcloud\x2dsdk
-SETUVAR fish_pager_color_completion:\x1d
-SETUVAR fish_pager_color_description:B3A06D\x1eyellow
-SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
-SETUVAR fish_pager_color_selected_background:\x2dr
-SETUVAR fish_user_abbreviations:l\x20ls

+ 0 - 39
dots/.config/fish/fish_variables.aIk53a

@@ -1,39 +0,0 @@
-# This file contains fish universal variable definitions.
-# VERSION: 3.0
-SETUVAR __fish_classic_git_prompt_initialized:\x1d
-SETUVAR __fish_init_2_39_8:\x1d
-SETUVAR __fish_init_2_3_0:\x1d
-SETUVAR __fish_initialized:3800
-SETUVAR _fish_abbr_l:ls
-SETUVAR fish_color_autosuggestion:555
-SETUVAR fish_color_cancel:\x2dr
-SETUVAR fish_color_command:005fd7
-SETUVAR fish_color_comment:990000
-SETUVAR fish_color_cwd:green
-SETUVAR fish_color_cwd_root:red
-SETUVAR fish_color_end:009900
-SETUVAR fish_color_error:ff0000
-SETUVAR fish_color_escape:bryellow\x1e\x2d\x2dbold
-SETUVAR fish_color_history_current:\x2d\x2dbold
-SETUVAR fish_color_host:normal
-SETUVAR fish_color_host_remote:yellow
-SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue
-SETUVAR fish_color_normal:normal
-SETUVAR fish_color_operator:bryellow
-SETUVAR fish_color_param:00afff
-SETUVAR fish_color_quote:999900
-SETUVAR fish_color_redirection:00afff
-SETUVAR fish_color_search_match:white\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_status:red
-SETUVAR fish_color_user:brgreen
-SETUVAR fish_color_valid_path:\x2d\x2dunderline
-SETUVAR fish_greeting:Capella
-SETUVAR fish_key_bindings:fish_vi_key_bindings
-SETUVAR fish_most_recent_dir:/home/capella/\x2egcloud/google\x2dcloud\x2dsdk
-SETUVAR fish_pager_color_completion:\x1d
-SETUVAR fish_pager_color_description:B3A06D\x1eyellow
-SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
-SETUVAR fish_pager_color_selected_background:\x2dr
-SETUVAR fish_user_abbreviations:l\x20ls

+ 0 - 39
dots/.config/fish/fish_variables.bvNfZ9

@@ -1,39 +0,0 @@
-# This file contains fish universal variable definitions.
-# VERSION: 3.0
-SETUVAR __fish_classic_git_prompt_initialized:\x1d
-SETUVAR __fish_init_2_39_8:\x1d
-SETUVAR __fish_init_2_3_0:\x1d
-SETUVAR __fish_initialized:3800
-SETUVAR _fish_abbr_l:ls
-SETUVAR fish_color_autosuggestion:555
-SETUVAR fish_color_cancel:\x2dr
-SETUVAR fish_color_command:005fd7
-SETUVAR fish_color_comment:990000
-SETUVAR fish_color_cwd:green
-SETUVAR fish_color_cwd_root:red
-SETUVAR fish_color_end:009900
-SETUVAR fish_color_error:ff0000
-SETUVAR fish_color_escape:bryellow\x1e\x2d\x2dbold
-SETUVAR fish_color_history_current:\x2d\x2dbold
-SETUVAR fish_color_host:normal
-SETUVAR fish_color_host_remote:yellow
-SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue
-SETUVAR fish_color_normal:normal
-SETUVAR fish_color_operator:bryellow
-SETUVAR fish_color_param:00afff
-SETUVAR fish_color_quote:999900
-SETUVAR fish_color_redirection:00afff
-SETUVAR fish_color_search_match:white\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_status:red
-SETUVAR fish_color_user:brgreen
-SETUVAR fish_color_valid_path:\x2d\x2dunderline
-SETUVAR fish_greeting:Capella
-SETUVAR fish_key_bindings:fish_vi_key_bindings
-SETUVAR fish_most_recent_dir:/home/capella/\x2egcloud/google\x2dcloud\x2dsdk
-SETUVAR fish_pager_color_completion:\x1d
-SETUVAR fish_pager_color_description:B3A06D\x1eyellow
-SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
-SETUVAR fish_pager_color_selected_background:\x2dr
-SETUVAR fish_user_abbreviations:l\x20ls

+ 0 - 39
dots/.config/fish/fish_variables.m2VbKw

@@ -1,39 +0,0 @@
-# This file contains fish universal variable definitions.
-# VERSION: 3.0
-SETUVAR __fish_classic_git_prompt_initialized:\x1d
-SETUVAR __fish_init_2_39_8:\x1d
-SETUVAR __fish_init_2_3_0:\x1d
-SETUVAR __fish_initialized:3800
-SETUVAR _fish_abbr_l:ls
-SETUVAR fish_color_autosuggestion:555
-SETUVAR fish_color_cancel:\x2dr
-SETUVAR fish_color_command:005fd7
-SETUVAR fish_color_comment:990000
-SETUVAR fish_color_cwd:green
-SETUVAR fish_color_cwd_root:red
-SETUVAR fish_color_end:009900
-SETUVAR fish_color_error:ff0000
-SETUVAR fish_color_escape:bryellow\x1e\x2d\x2dbold
-SETUVAR fish_color_history_current:\x2d\x2dbold
-SETUVAR fish_color_host:normal
-SETUVAR fish_color_host_remote:yellow
-SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue
-SETUVAR fish_color_normal:normal
-SETUVAR fish_color_operator:bryellow
-SETUVAR fish_color_param:00afff
-SETUVAR fish_color_quote:999900
-SETUVAR fish_color_redirection:00afff
-SETUVAR fish_color_search_match:white\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_status:red
-SETUVAR fish_color_user:brgreen
-SETUVAR fish_color_valid_path:\x2d\x2dunderline
-SETUVAR fish_greeting:Capella
-SETUVAR fish_key_bindings:fish_vi_key_bindings
-SETUVAR fish_most_recent_dir:/home/capella/\x2egcloud/google\x2dcloud\x2dsdk
-SETUVAR fish_pager_color_completion:\x1d
-SETUVAR fish_pager_color_description:B3A06D\x1eyellow
-SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
-SETUVAR fish_pager_color_selected_background:\x2dr
-SETUVAR fish_user_abbreviations:l\x20ls

+ 0 - 39
dots/.config/fish/fish_variables.vjYZqx

@@ -1,39 +0,0 @@
-# This file contains fish universal variable definitions.
-# VERSION: 3.0
-SETUVAR __fish_classic_git_prompt_initialized:\x1d
-SETUVAR __fish_init_2_39_8:\x1d
-SETUVAR __fish_init_2_3_0:\x1d
-SETUVAR __fish_initialized:3800
-SETUVAR _fish_abbr_l:ls
-SETUVAR fish_color_autosuggestion:555
-SETUVAR fish_color_cancel:\x2dr
-SETUVAR fish_color_command:005fd7
-SETUVAR fish_color_comment:990000
-SETUVAR fish_color_cwd:green
-SETUVAR fish_color_cwd_root:red
-SETUVAR fish_color_end:009900
-SETUVAR fish_color_error:ff0000
-SETUVAR fish_color_escape:bryellow\x1e\x2d\x2dbold
-SETUVAR fish_color_history_current:\x2d\x2dbold
-SETUVAR fish_color_host:normal
-SETUVAR fish_color_host_remote:yellow
-SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue
-SETUVAR fish_color_normal:normal
-SETUVAR fish_color_operator:bryellow
-SETUVAR fish_color_param:00afff
-SETUVAR fish_color_quote:999900
-SETUVAR fish_color_redirection:00afff
-SETUVAR fish_color_search_match:white\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SETUVAR fish_color_status:red
-SETUVAR fish_color_user:brgreen
-SETUVAR fish_color_valid_path:\x2d\x2dunderline
-SETUVAR fish_greeting:Capella
-SETUVAR fish_key_bindings:fish_vi_key_bindings
-SETUVAR fish_most_recent_dir:/home/capella/\x2egcloud/google\x2dcloud\x2dsdk
-SETUVAR fish_pager_color_completion:\x1d
-SETUVAR fish_pager_color_description:B3A06D\x1eyellow
-SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
-SETUVAR fish_pager_color_selected_background:\x2dr
-SETUVAR fish_user_abbreviations:l\x20ls

+ 0 - 30
dots/.config/fish/fishd.80e650246adb

@@ -1,30 +0,0 @@
-# This file is automatically generated by the fish.
-# Do NOT edit it directly, your changes will be overwritten.
-SET __fish_init_2_39_8:\x1d
-SET __fish_init_2_3_0:\x1d
-SET fish_color_autosuggestion:555\x1ebrblack
-SET fish_color_cancel:\x2dr
-SET fish_color_command:\x2d\x2dbold
-SET fish_color_comment:red
-SET fish_color_cwd:green
-SET fish_color_cwd_root:red
-SET fish_color_end:brmagenta
-SET fish_color_error:brred
-SET fish_color_escape:bryellow\x1e\x2d\x2dbold
-SET fish_color_history_current:\x2d\x2dbold
-SET fish_color_host:normal
-SET fish_color_match:\x2d\x2dbackground\x3dbrblue
-SET fish_color_normal:normal
-SET fish_color_operator:bryellow
-SET fish_color_param:cyan
-SET fish_color_quote:yellow
-SET fish_color_redirection:brblue
-SET fish_color_search_match:bryellow\x1e\x2d\x2dbackground\x3dbrblack
-SET fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SET fish_color_user:brgreen
-SET fish_color_valid_path:\x2d\x2dunderline
-SET fish_key_bindings:fish_default_key_bindings
-SET fish_pager_color_completion:\x1d
-SET fish_pager_color_description:B3A06D\x1eyellow
-SET fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SET fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan

+ 0 - 34
dots/.config/fish/fishd.80e65024db6a

@@ -1,34 +0,0 @@
-# This file is automatically generated by the fish.
-# Do NOT edit it directly, your changes will be overwritten.
-SET __fish_classic_git_prompt_initialized:\x1d
-SET __fish_init_2_39_8:\x1d
-SET __fish_init_2_3_0:\x1d
-SET fish_color_autosuggestion:555
-SET fish_color_cancel:\x2dr
-SET fish_color_command:005fd7
-SET fish_color_comment:990000
-SET fish_color_cwd:green
-SET fish_color_cwd_root:red
-SET fish_color_end:009900
-SET fish_color_error:ff0000
-SET fish_color_escape:bryellow\x1e\x2d\x2dbold
-SET fish_color_history_current:\x2d\x2dbold
-SET fish_color_host:normal
-SET fish_color_match:\x2d\x2dbackground\x3dbrblue
-SET fish_color_normal:normal
-SET fish_color_operator:bryellow
-SET fish_color_param:00afff
-SET fish_color_quote:999900
-SET fish_color_redirection:00afff
-SET fish_color_search_match:bryellow\x1e\x2d\x2dbackground\x3dbrblack
-SET fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
-SET fish_color_status:red
-SET fish_color_user:brgreen
-SET fish_color_valid_path:\x2d\x2dunderline
-SET fish_greeting:Capella
-SET fish_key_bindings:fish_default_key_bindings
-SET fish_pager_color_completion:\x1d
-SET fish_pager_color_description:B3A06D\x1eyellow
-SET fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
-SET fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
-SET fish_user_abbreviations:l\x20ls

+ 55 - 29
dots/.config/sway/config

@@ -1,25 +1,23 @@
-# It will not be overwritten, so edit it as you like.
-#
-# Should you change your keyboard layout some time, delete
-# this file and re-run i3-config-wizard(1).
-#
-
-# i3 config file (v4)
+# sway config file
 #
 # Please see https://i3wm.org/docs/userguide.html for a complete reference!
 
+# @host jellyfish
+set $mod Mod4
+# @end
+# @host tompot
 set $mod Mod1
+# @end
 
 # Font for window titles. Will also be used by the bar unless a different font
 # is used in the bar {} block below.
+# @host jellyfish
+font pango:Inter 11
+# @end
+# @host tompot
 font pango:monospace 12
-
-# This font is widely installed, provides lots of unicode glyphs, right-to-left
-# text rendering and scalability on retina/hidpi displays (thanks to pango).
 font pango:B612 12
-
-# The combination of xss-lock, nm-applet and pactl is a popular choice, so
-# they are included here as an example. Modify as you see fit.
+# @end
 
 # NetworkManager is the most popular way to manage wireless networks on Linux,
 # and nm-applet is a desktop environment-independent system tray GUI for it.
@@ -36,10 +34,10 @@ bindsym $mod+Return exec alacritty
 bindsym $mod+Shift+q kill
 
 # start dmenu (a program launcher)
-bindsym $mod+d exec bemenu-run -l 10 -p  --counter always -c -W 0.2 -B 10 \
+bindsym $mod+d exec bemenu-run -l 10 -p  --counter always -c -W 0.2 -B 10 \
     --fixed-height --fn  'B612 11'  \
     --bdr "#323232" --tf "#FFFFFF" --hf "#FFFFFF"
-bindsym $mod+Shift+v exec cliphist list | bemenu -l 15 -p  --counter always -c -W 0.2 -B 10 \
+bindsym $mod+Shift+v exec cliphist list | bemenu -l 15 -p  --counter always -c -W 0.2 -B 10 \
     --fixed-height --fn  'B612 11'  \
     --bdr "#323232" --tf "#FFFFFF" --hf "#FFFFFF" \
     | cliphist decode | wl-copy
@@ -129,31 +127,23 @@ bindsym $mod+Shift+0 move container to workspace number $ws10
 
 # reload the configuration file
 bindsym $mod+Shift+c reload
-# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
+# restart sway inplace
 bindsym $mod+Shift+r restart
-# exit i3 (logs you out of your X session)
+# exit sway
 bindsym $mod+Shift+e exec "swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'sway exit'"
 
 # resize window (you can also use the mouse for that)
 mode "resize" {
-        # These bindings trigger as soon as you enter the resize mode
-
-        # Pressing left will shrink the window’s width.
-        # Pressing right will grow the window’s width.
-        # Pressing up will shrink the window’s height.
-        # Pressing down will grow the window’s height.
         bindsym j resize shrink width 10 px or 10 ppt
         bindsym k resize grow height 10 px or 10 ppt
         bindsym l resize shrink height 10 px or 10 ppt
         bindsym semicolon resize grow width 10 px or 10 ppt
 
-        # same bindings, but for the arrow keys
         bindsym Left resize shrink width 10 px or 10 ppt
         bindsym Down resize grow height 10 px or 10 ppt
         bindsym Up resize shrink height 10 px or 10 ppt
         bindsym Right resize grow width 10 px or 10 ppt
 
-        # back to normal: Enter or Escape or $mod+r
         bindsym Return mode "default"
         bindsym Escape mode "default"
         bindsym $mod+r mode "default"
@@ -161,12 +151,8 @@ mode "resize" {
 
 bindsym $mod+r mode "resize"
 
-# Start i3bar to display a workspace bar (plus the system information i3status
-# finds out, if available)
 bar {
     position top
-    # modifier Mod1
-    # status_command while date +'%Y-%m-%d %I:%M:%S %p (UTC)'; do sleep 1; done
     bar swaybar_command waybar
 }
 
@@ -180,7 +166,9 @@ bindsym XF86AudioPrev exec playerctl previous
 bindsym XF86MonBrightnessUp exec ddcutil setvcp --sn 6L1M413 10 + 5
 bindsym XF86MonBrightnessDown exec ddcutil setvcp --sn 6L1M413 10 - 5
 
+# @host tompot
 bindsym $mod+b exec ~/.config/sway/scripts/brightness-slider.sh
+# @end
 
 # Audio
 bindsym XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5%
@@ -213,6 +201,28 @@ input * {
     scroll_factor 1
 }
 
+# @host jellyfish
+input "9610:8214:SINO_WEALTH_USB_KEYBOARD" {
+    xkb_options "ctrl:nocaps"
+    xkb_layout br
+    xkb_variant abnt2
+}
+# @end
+
+# @host jellyfish
+exec swayidle -w \
+         timeout 300 'gtklock -d -c /home/capella/.config/gtklock/config.ini' \
+         timeout 600 'swaymsg "output * power off" && ddcutil setvcp --sn 6L1M413 D6 0x05' \
+         timeout 900 'systemctl suspend' \
+         resume 'swaymsg "output * power on" && ddcutil setvcp --sn 6L1M413 D6 0x01' \
+         before-sleep 'gtklock -d -c /home/capella/.config/gtklock/config.ini'
+
+bindsym $mod+q exec 'gtklock -d -c /home/capella/.config/gtklock/config.ini'
+
+bindswitch --reload --locked lid:on exec 'gtklock -d -c /home/capella/.config/gtklock/config.ini && systemctl suspend'
+# @end
+
+# @host tompot
 exec swayidle -w \
          timeout 300 'swaylock -f -c 000000 -i /tmp/mercator_projection.png' \
          timeout 600 'swaymsg "output * power off" && ddcutil setvcp --sn 6L1M413 D6 0x05' \
@@ -220,6 +230,7 @@ exec swayidle -w \
          before-sleep 'swaylock -f -c 000000 -i /tmp/mercator_projection.png'
 
 bindsym $mod+q exec 'swaylock -f -c 000000 -i /tmp/mercator_projection.png'
+# @end
 
 smart_borders on
 hide_edge_borders both
@@ -227,6 +238,7 @@ for_window [class="^.*"] border pixel 2
 
 include @sysconfdir@/sway/config.d/*
 
+# @host jellyfish
 output HDMI-A-1 pos 0 0
 
 output HDMI-A-2 {
@@ -235,3 +247,17 @@ output HDMI-A-2 {
     scale 1
 }
 
+output "BOE 0x0832 Unknown" {
+    scale 1
+}
+# @end
+
+# @host tompot
+output HDMI-A-1 pos 0 0
+
+output HDMI-A-2 {
+    transform 270
+    pos 930 2160
+    scale 1
+}
+# @end

+ 42 - 33
dots/.config/waybar/config

@@ -26,13 +26,18 @@
         "sway/window"
     ],
     "modules-right": [
+// @host tompot
         "custom/brightness",
+// @end
         "pulseaudio",
         "network",
         "memory",
         "cpu",
         "custom/keyboard-layout",
         "tray",
+// @host jellyfish
+        "battery",
+// @end
         "clock#date",
         "clock#time"
     ],
@@ -42,6 +47,7 @@
     // Modules
     // -------------------------------------------------------------------------
 
+// @host tompot
     "custom/brightness": {
         "exec": "~/.config/sway/scripts/get-monitor-brightness.sh",
         "return-type": "json",
@@ -53,6 +59,7 @@
         "format": "🖵  {}",
         "smooth-scrolling-threshold": 1
     },
+// @end
 
     "battery": {
         "interval": 10,
@@ -61,15 +68,15 @@
             "critical": 15
         },
         // Connected to AC
-        "format": "  {icon}  {capacity}%", // Icon: bolt
+        "format": "  {icon}  {capacity}%", // Icon: bolt
         // Not connected to AC
         "format-discharging": "{icon}  {capacity}%",
         "format-icons": [
-            "", // Icon: battery-full
-            "", // Icon: battery-three-quarters
-            "", // Icon: battery-half
-            "", // Icon: battery-quarter
-            ""  // Icon: battery-empty
+            "", // Icon: battery-full
+            "", // Icon: battery-three-quarters
+            "", // Icon: battery-half
+            "", // Icon: battery-quarter
+            ""  // Icon: battery-empty
         ],
         "tooltip": true
     },
@@ -82,13 +89,13 @@
 
     "clock#date": {
       "interval": 10,
-      "format": "  {:%e %b %Y}", // Icon: calendar-alt
+      "format": "  {:%e %b %Y}", // Icon: calendar-alt
       "tooltip-format": "{:%e %B %Y}"
     },
 
     "cpu": {
         "interval": 5,
-        "format": "  {usage}% ({load})", // Icon: microchip
+        "format": "  {usage}% ({load})", // Icon: microchip
         "states": {
           "warning": 70,
           "critical": 90
@@ -99,7 +106,7 @@
       "exec": "swaymsg -t get_inputs | grep -m1 'xkb_active_layout_name' | cut -d '\"' -f4",
       // Interval set only as a fallback, as the value is updated by signal
       "interval": 30,
-      "format": "  {}", // Icon: keyboard
+      "format": "  {}", // Icon: keyboard
       // Signal sent by Sway key binding (~/.config/sway/key-bindings)
       "signal": 1, // SIGHUP
       "tooltip": false
@@ -107,7 +114,7 @@
 
     "memory": {
         "interval": 5,
-        "format": "  {}%", // Icon: memory
+        "format": "  {}%", // Icon: memory
         "states": {
             "warning": 70,
             "critical": 90
@@ -116,15 +123,17 @@
 
     "network": {
         "interval": 5,
-        "format-wifi": "  {essid} ({signalStrength}%)", // Icon: wifi
-        "format-ethernet": "  {ifname}: {ipaddr}/{cidr}", // Icon: ethernet
+        "format-wifi": "  {essid} ({signalStrength}%)", // Icon: wifi
+        "format-ethernet": "  {ifname}: {ipaddr}/{cidr}", // Icon: ethernet
         "format-disconnected": "⚠  Disconnected",
         "tooltip-format": "{ifname}: {ipaddr}",
+// @host tompot
         "on-click": "~/.config/waybar/scripts/iwd-connect.sh"
+// @end
     },
 
     "sway/mode": {
-        "format": "<span style=\"italic\">  {}</span>", // Icon: expand-arrows-alt
+        "format": "<span style=\"italic\">  {}</span>", // Icon: expand-arrows-alt
         "tooltip": false
     },
 
@@ -138,12 +147,12 @@
         "disable-scroll": true,
         "format": "{icon} {name}",
         "format-icons": {
-            "1:www": "", // Icon: firefox-browser
-            "2:mail": "", // Icon: mail
-            "3:editor": "", // Icon: code
-            "4:terminals": "", // Icon: terminal
-            "5:portal": "", // Icon: terminal
-            "urgent": "",
+            "1:www": "", // Icon: firefox-browser
+            "2:mail": "", // Icon: mail
+            "3:editor": "", // Icon: code
+            "4:terminals": "", // Icon: terminal
+            "5:portal": "", // Icon: terminal
+            "urgent": "",
             "focused": "",
             "default": ""
         }
@@ -152,16 +161,16 @@
     "pulseaudio": {
         //"scroll-step": 1,
         "format": "{icon}  {volume}%",
-        "format-bluetooth": "{icon}  {volume}%",
-        "format-muted": "",
+        "format-bluetooth": "{icon}  {volume}%",
+        "format-muted": "",
         "format-icons": {
-            "headphones": "",
-            "handsfree": "",
-            "headset": "",
-            "phone": "",
-            "portable": "",
-            "car": "",
-            "default": ["", ""]
+            "headphones": "",
+            "handsfree": "",
+            "headset": "",
+            "phone": "",
+            "portable": "",
+            "car": "",
+            "default": ["", ""]
         },
         "on-click": "pavucontrol"
     },
@@ -171,11 +180,11 @@
       "interval": 5,
       "format": "{icon}  {temperatureC}°C",
       "format-icons": [
-          "", // Icon: temperature-empty
-          "", // Icon: temperature-quarter
-          "", // Icon: temperature-half
-          "", // Icon: temperature-three-quarters
-          ""  // Icon: temperature-full
+          "", // Icon: temperature-empty
+          "", // Icon: temperature-quarter
+          "", // Icon: temperature-half
+          "", // Icon: temperature-three-quarters
+          ""  // Icon: temperature-full
       ],
       "tooltip": true
     },

+ 1 - 0
groups.jellyfish

@@ -0,0 +1 @@
+wayland

+ 1 - 0
groups.tompot

@@ -0,0 +1 @@
+wayland

+ 294 - 56
start

@@ -4,9 +4,11 @@
 set -euo pipefail
 
 # Configuration
+hostname_id=$(uname -n)
 checkout_dir=$HOME/.dofiles
 script_dir=$checkout_dir/dotfiles
 dots_dir=$checkout_dir/dotfiles/dots
+dots_host_dir=$checkout_dir/dotfiles/dots.$hostname_id
 repo="https://git.capella.pro/capella/dotfiles.git"
 ProgName=$(basename "$0")
 
@@ -21,6 +23,109 @@ log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
 log_warn() { echo -e "${YELLOW}[WARN]${NC} $*" >&2; }
 log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
 
+# Get group names for the current host (sorted, one per line)
+get_groups() {
+    local groups_file="$script_dir/groups.$hostname_id"
+    if [[ -f "$groups_file" ]]; then
+        grep -v '^\s*#' "$groups_file" | grep -v '^\s*$' | sort
+    fi
+}
+
+# Get combined sync list (common + groups + host-specific, deduplicated)
+get_sync_list() {
+    {
+        cat "$script_dir/to_sync" 2>/dev/null
+        while IFS= read -r group; do
+            cat "$script_dir/to_sync.@$group" 2>/dev/null
+        done < <(get_groups)
+        cat "$script_dir/to_sync.$hostname_id" 2>/dev/null
+    } | grep -v '^\s*$' | sort -u
+}
+
+# Resolve source path: common -> groups (alpha) -> host-specific (last wins)
+resolve_source() {
+    local p="$1"
+    local result="$dots_dir/$p"
+
+    while IFS= read -r group; do
+        if [[ -e "$script_dir/dots.@$group/$p" ]]; then
+            result="$script_dir/dots.@$group/$p"
+        fi
+    done < <(get_groups)
+
+    if [[ -e "$dots_host_dir/$p" ]]; then
+        result="$dots_host_dir/$p"
+    fi
+
+    echo "$result"
+}
+
+# Check if a file contains @host or @group markers
+file_has_markers() {
+    grep -qE '@(host|group) ' "$1" 2>/dev/null
+}
+
+# Detect the comment prefix from the first marker line in a file
+detect_comment_prefix() {
+    local src="$1"
+    local marker_line
+    marker_line=$(grep -m1 -E '@(host|group) ' "$src")
+    # Extract everything before @host or @group
+    local prefix="${marker_line%%@*}"
+    # Trim trailing whitespace
+    prefix="${prefix%"${prefix##*[![:space:]]}"}"
+    echo "$prefix"
+}
+
+# Process a file with @host/@group markers, outputting only matching sections
+process_markers() {
+    local src="$1"
+    local in_block=0
+    local include_block=0
+
+    # Pre-load groups into an associative array for fast lookup
+    declare -A host_groups
+    while IFS= read -r g; do
+        host_groups["$g"]=1
+    done < <(get_groups)
+
+    while IFS= read -r line || [[ -n "$line" ]]; do
+        if [[ $in_block -eq 0 ]]; then
+            if [[ "$line" =~ @host[[:space:]]+([^[:space:]]+) ]]; then
+                in_block=1
+                if [[ "${BASH_REMATCH[1]}" == "$hostname_id" ]]; then
+                    include_block=1
+                else
+                    include_block=0
+                fi
+            elif [[ "$line" =~ @group[[:space:]]+([^[:space:]]+) ]]; then
+                in_block=1
+                if [[ -v "host_groups[${BASH_REMATCH[1]}]" ]]; then
+                    include_block=1
+                else
+                    include_block=0
+                fi
+            elif [[ "$line" =~ @end ]]; then
+                # Stray @end outside a block, skip it
+                continue
+            else
+                printf '%s\n' "$line"
+            fi
+        else
+            if [[ "$line" =~ @end ]]; then
+                in_block=0
+                include_block=0
+            elif [[ $include_block -eq 1 ]]; then
+                printf '%s\n' "$line"
+            fi
+        fi
+    done < "$src"
+
+    if [[ $in_block -eq 1 ]]; then
+        log_warn "Unclosed @host/@group block in $src"
+    fi
+}
+
 # Ensure we cleanup on exit
 trap 'cd "$HOME"' EXIT
 
@@ -29,13 +134,31 @@ mkdir -p "$checkout_dir"
 
 
 sub_help(){
+    local groups
+    groups=$(get_groups | tr '\n' ', ' | sed 's/,$//')
     cat << EOF
 Usage: $ProgName <subcommand> [options]
 
 Subcommands:
-    sync [dot_file_to_add]    Sync dotfiles (optionally add a new dotfile to track)
-    list                      List currently synced dotfiles
-    status                    Show git status of dotfiles repo
+    sync [--machine|--group <name>] [dot_file]
+                                 Sync dotfiles (optionally add a new dotfile)
+                                 --machine: add to host-specific config ($hostname_id)
+                                 --group <name>: add to group-specific config
+    list                         List currently synced dotfiles
+    status                       Show git status of dotfiles repo
+
+Host: $hostname_id
+Groups: ${groups:-none}
+  Resolution order: common -> groups (alpha) -> host-specific
+
+  Common dotfiles:   dots/ + to_sync
+  Group dotfiles:    dots.@<group>/ + to_sync.@<group>
+  Host overrides:    dots.$hostname_id/ + to_sync.$hostname_id
+
+In-file markers:
+  # @host <name> ... # @end   (host-specific block)
+  # @group <name> ... # @end  (group-specific block)
+  Files with markers are processed and written (not symlinked).
 
 For help with each subcommand run:
     $ProgName <subcommand> -h|--help
@@ -66,6 +189,21 @@ sub_sync(){
     git pull origin "$current_branch" || log_warn "Git pull failed, continuing anyway"
     git submodule update --init --recursive
 
+    # Parse flags for adding new dotfiles
+    local machine_specific=0
+    local group_target=""
+    if [[ "${1:-}" == "--machine" ]]; then
+        machine_specific=1
+        shift
+    elif [[ "${1:-}" == "--group" ]]; then
+        group_target="${2:-}"
+        if [[ -z "$group_target" ]]; then
+            log_error "--group requires a group name"
+            exit 1
+        fi
+        shift 2
+    fi
+
     # Add new dotfile if provided
     if [ -n "${1:-}" ]; then
         local file_to_add="$1"
@@ -81,44 +219,68 @@ sub_sync(){
         real_path=$(realpath "$HOME/$file_to_add")
         to_copy=${real_path#"$HOME/"}
 
-        # Create parent directory structure in dots_dir
-        mkdir -p "$(dirname "$dots_dir/$to_copy")"
+        if [[ $machine_specific -eq 1 ]]; then
+            target_dots_dir="$dots_host_dir"
+            sync_file="$script_dir/to_sync.$hostname_id"
+            log_info "Adding as host-specific ($hostname_id)"
+        elif [[ -n "$group_target" ]]; then
+            target_dots_dir="$script_dir/dots.@$group_target"
+            sync_file="$script_dir/to_sync.@$group_target"
+            log_info "Adding as group-specific (@$group_target)"
+        else
+            target_dots_dir="$dots_dir"
+            sync_file="$script_dir/to_sync"
+        fi
+
+        # Create parent directory structure
+        mkdir -p "$(dirname "$target_dots_dir/$to_copy")"
 
         # Copy to dots directory
-        if cp -R "$real_path" "$dots_dir/$to_copy"; then
-            log_info "Copied $file_to_add to $dots_dir/$to_copy"
+        if cp -R "$real_path" "$target_dots_dir/$to_copy"; then
+            log_info "Copied $file_to_add to $target_dots_dir/$to_copy"
         else
             log_error "Failed to copy $file_to_add"
             exit 1
         fi
 
-        # Add to to_sync file if not already there
-        if ! grep -qxF "$to_copy" "$script_dir/to_sync" 2>/dev/null; then
-            echo "$to_copy" >> "$script_dir/to_sync"
-            log_info "Added $to_copy to sync list"
+        # Add to sync file if not already there
+        if ! grep -qxF "$to_copy" "$sync_file" 2>/dev/null; then
+            echo "$to_copy" >> "$sync_file"
+            log_info "Added $to_copy to $(basename "$sync_file")"
         else
-            log_info "$to_copy already in sync list"
+            log_info "$to_copy already in $(basename "$sync_file")"
         fi
 
         # Remove original and create symlink
         rm -rf "$real_path"
-        ln -s "$dots_dir/$to_copy" "$real_path"
-        log_info "Created symlink: $real_path -> $dots_dir/$to_copy"
+        ln -s "$target_dots_dir/$to_copy" "$real_path"
+        log_info "Created symlink: $real_path -> $target_dots_dir/$to_copy"
     fi
 
-    # Add tracked files to git
+    # Stage tracked files from all source directories
     log_info "Staging changes..."
-    while IFS= read -r p; do
-        [[ -z "$p" ]] && continue  # Skip empty lines
-        file="$dots_dir/$p"
-        if [[ -e "$file" ]]; then
-            git add "$file"
-        else
-            log_warn "Tracked file $file does not exist"
+    get_sync_list | while IFS= read -r p; do
+        if [[ -e "$dots_dir/$p" ]]; then
+            git add "$dots_dir/$p"
+        fi
+        while IFS= read -r group; do
+            if [[ -e "$script_dir/dots.@$group/$p" ]]; then
+                git add "$script_dir/dots.@$group/$p"
+            fi
+        done < <(get_groups)
+        if [[ -e "$dots_host_dir/$p" ]]; then
+            git add "$dots_host_dir/$p"
         fi
-    done < "$script_dir/to_sync"
+    done
 
     git add start to_sync
+    # Stage host-specific, group-specific, and groups files
+    for f in to_sync.* groups.*; do
+        [[ -f "$f" ]] && git add "$f"
+    done
+    for d in dots.*/; do
+        [[ -d "$d" ]] && git add "$d"
+    done
 
     # Commit and push if there are changes
     if git diff --cached --quiet; then
@@ -140,58 +302,133 @@ sub_sync(){
         fi
     fi
 
-    # Create symlinks for all tracked dotfiles
-    log_info "Creating symlinks..."
-    while IFS= read -r p; do
-        [[ -z "$p" ]] && continue  # Skip empty lines
-        destination="$HOME/$p"
-        source="$dots_dir/$p"
+    # Deploy dotfiles (symlink or process markers)
+    log_info "Deploying dotfiles for $hostname_id..."
+    get_sync_list | while IFS= read -r p; do
+        local source
+        source=$(resolve_source "$p")
+        local destination="$HOME/$p"
 
         if [[ ! -e "$source" ]]; then
             log_warn "Source file $source does not exist, skipping"
             continue
         fi
 
-        # Check if destination is already a correct symlink
-        if [[ -L "$destination" ]] && [[ "$(readlink "$destination")" == "$source" ]]; then
-            continue  # Already correctly linked
-        fi
+        mkdir -p "$(dirname "$destination")"
 
-        # Remove destination if it exists
-        if [[ -e "$destination" ]] || [[ -L "$destination" ]]; then
-            log_warn "Removing existing $destination"
-            rm -rf "$destination"
-        fi
+        if [[ -f "$source" ]] && file_has_markers "$source"; then
+            # File has markers — process and write (not symlink)
+            if [[ -L "$destination" ]]; then
+                rm "$destination"
+            fi
 
-        # Create parent directory if needed
-        mkdir -p "$(dirname "$destination")"
+            local comment_prefix
+            comment_prefix=$(detect_comment_prefix "$source")
 
-        # Create symlink
-        if ln -s "$source" "$destination"; then
-            log_info "Linked: $destination -> $source"
+            {
+                echo "$comment_prefix DO NOT EDIT - Generated by dotsync from:"
+                echo "$comment_prefix $source"
+                echo ""
+                process_markers "$source"
+            } > "$destination.dotsync_tmp"
+
+            # Only update if content changed
+            if [[ -f "$destination" ]] && cmp -s "$destination" "$destination.dotsync_tmp"; then
+                rm "$destination.dotsync_tmp"
+            else
+                [[ -e "$destination" ]] && rm "$destination"
+                mv "$destination.dotsync_tmp" "$destination"
+                chmod --reference="$source" "$destination"
+                log_info "Processed: $destination (from $source)"
+            fi
         else
-            log_error "Failed to create symlink for $p"
+            # No markers — symlink as before
+            if [[ -L "$destination" ]] && [[ "$(readlink "$destination")" == "$source" ]]; then
+                continue  # Already correctly linked
+            fi
+
+            if [[ -e "$destination" ]] || [[ -L "$destination" ]]; then
+                log_warn "Removing existing $destination"
+                rm -rf "$destination"
+            fi
+
+            if ln -s "$source" "$destination"; then
+                log_info "Linked: $destination -> $source"
+            else
+                log_error "Failed to create symlink for $p"
+            fi
         fi
-    done < "$script_dir/to_sync"
+    done
 
     log_info "Sync complete!"
 }
 
 sub_list(){
-    if [[ ! -f "$script_dir/to_sync" ]]; then
-        log_error "No to_sync file found"
-        exit 1
+    echo "Host: $hostname_id"
+
+    local groups
+    groups=$(get_groups | tr '\n' ', ' | sed 's/,$//')
+    if [[ -n "$groups" ]]; then
+        echo "Groups: $groups"
+    fi
+    echo ""
+
+    if [[ -f "$script_dir/to_sync" ]]; then
+        echo "Common dotfiles (to_sync):"
+        while IFS= read -r p; do
+            [[ -z "$p" ]] && continue
+            local source
+            source=$(resolve_source "$p")
+            local tag=""
+            if [[ "$source" == "$dots_host_dir/"* ]]; then
+                tag=" [override: $hostname_id]"
+            elif [[ "$source" == *"/dots.@"* ]]; then
+                local gname
+                gname=$(echo "$source" | sed 's|.*dots\.@\([^/]*\)/.*|\1|')
+                tag=" [override: @$gname]"
+            fi
+            local marker_tag=""
+            if [[ -f "$source" ]] && file_has_markers "$source"; then
+                marker_tag=" [processed]"
+            fi
+            if [[ -L "$HOME/$p" ]] || [[ -f "$HOME/$p" ]] || [[ -d "$HOME/$p" ]]; then
+                echo "  + $p$tag$marker_tag"
+            else
+                echo "  - $p (not deployed)$tag$marker_tag"
+            fi
+        done < "$script_dir/to_sync"
     fi
 
-    echo "Currently synced dotfiles:"
-    while IFS= read -r p; do
-        [[ -z "$p" ]] && continue
-        if [[ -L "$HOME/$p" ]]; then
-            echo "  ✓ $p"
-        else
-            echo "  ✗ $p (not linked)"
+    # Group-specific dotfiles
+    while IFS= read -r group; do
+        local gsync="$script_dir/to_sync.@$group"
+        if [[ -f "$gsync" ]] && [[ -s "$gsync" ]]; then
+            echo ""
+            echo "Group dotfiles (to_sync.@$group):"
+            while IFS= read -r p; do
+                [[ -z "$p" ]] && continue
+                if [[ -L "$HOME/$p" ]] || [[ -f "$HOME/$p" ]] || [[ -d "$HOME/$p" ]]; then
+                    echo "  + $p"
+                else
+                    echo "  - $p (not deployed)"
+                fi
+            done < "$gsync"
         fi
-    done < "$script_dir/to_sync"
+    done < <(get_groups)
+
+    # Host-specific dotfiles
+    if [[ -f "$script_dir/to_sync.$hostname_id" ]] && [[ -s "$script_dir/to_sync.$hostname_id" ]]; then
+        echo ""
+        echo "Host-specific dotfiles (to_sync.$hostname_id):"
+        while IFS= read -r p; do
+            [[ -z "$p" ]] && continue
+            if [[ -L "$HOME/$p" ]] || [[ -f "$HOME/$p" ]] || [[ -d "$HOME/$p" ]]; then
+                echo "  + $p"
+            else
+                echo "  - $p (not deployed)"
+            fi
+        done < "$script_dir/to_sync.$hostname_id"
+    fi
 }
 
 sub_status(){
@@ -201,6 +438,7 @@ sub_status(){
     fi
 
     cd "$script_dir"
+    log_info "Host: $hostname_id"
     log_info "Git status:"
     git status
 }