swadhinbiswas Initial de-omarchy: Omarchy UI layer for Arch-based distros · 8/22/2026
9f393b2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/bin/bash
# omarchy:summary=Sync Omarchy theme to VS Code, VSCodium, and Cursor
# omarchy:hidden=true
VS_CODE_THEME_DESCRIPTOR="$HOME/.local/state/omarchy/current/theme/vscode.json"
GENERATED_THEME="$HOME/.local/state/omarchy/current/theme/vscode-theme.json"
GENERATED_EXTENSION_NAME="omarchy-theme"
GENERATED_EXTENSION_ID="local.$GENERATED_EXTENSION_NAME"
GENERATED_EXTENSION_VERSION="1.0.0"
register_generated_extension() {
local ext_dir="$1"
local ext_base extensions_file obsolete_file relative tmp
ext_base=$(dirname "$ext_dir")
extensions_file="$ext_base/extensions.json"
obsolete_file="$ext_base/.obsolete"
relative=$(basename "$ext_dir")
if [[ -f $obsolete_file ]]; then
tmp=$(mktemp)
if jq --arg key "$GENERATED_EXTENSION_ID-$GENERATED_EXTENSION_VERSION" 'del(.[$key])' "$obsolete_file" >"$tmp"; then
mv "$tmp" "$obsolete_file"
[[ $(jq 'length' "$obsolete_file") == "0" ]] && rm -f "$obsolete_file"
else
rm -f "$tmp"
fi
fi
[[ -f $extensions_file ]] || printf '[]\n' >"$extensions_file"
tmp=$(mktemp)
if jq \
--arg id "$GENERATED_EXTENSION_ID" \
--arg version "$GENERATED_EXTENSION_VERSION" \
--arg fs_path "$ext_dir" \
--arg external "file://$ext_dir" \
--arg relative "$relative" \
'map(select(.identifier.id != $id)) + [{
identifier: { id: $id },
version: $version,
location: {
"$mid": 1,
fsPath: $fs_path,
external: $external,
path: $fs_path,
scheme: "file"
},
relativeLocation: $relative
}]' \
"$extensions_file" >"$tmp"; then
mv "$tmp" "$extensions_file"
else
rm -f "$tmp"
fi
}
# Install generated theme as a local extension for a given editor
install_generated_extension() {
local ext_dir="$1"
local theme_type ui_theme
theme_type=$(jq -r '.type // "dark"' "$GENERATED_THEME")
if [[ $theme_type == "light" ]]; then
ui_theme="vs"
else
ui_theme="vs-dark"
fi
mkdir -p "$ext_dir/themes"
ln -sfn "$GENERATED_THEME" "$ext_dir/themes/omarchy-color-theme.json"
cat > "$ext_dir/package.json" <<EOF
{
"name": "$GENERATED_EXTENSION_NAME",
"displayName": "Omarchy",
"description": "Omarchy color theme",
"publisher": "local",
"version": "$GENERATED_EXTENSION_VERSION",
"engines": { "vscode": "^1.70.0" },
"categories": ["Themes"],
"contributes": {
"themes": [{
"label": "Omarchy",
"uiTheme": "$ui_theme",
"path": "./themes/omarchy-color-theme.json"
}]
}
}
EOF
register_generated_extension "$ext_dir"
}
set_theme() {
local editor_cmd="$1"
local settings_path="$2"
local ext_base="$3"
omarchy-cmd-present "$editor_cmd" || return 0
local theme_name=""
if [[ -f "$VS_CODE_THEME_DESCRIPTOR" ]]; then
# Theme specifies a preferred 3rd-party extension/theme pair. Both fields
# come from the theme, so neither is trusted as a shell or sed argument.
local extension
theme_name=$(jq -r '.name // empty' "$VS_CODE_THEME_DESCRIPTOR")
extension=$(jq -r '.extension // empty' "$VS_CODE_THEME_DESCRIPTOR")
# A label with quotes, backslashes, or control characters can't land in
# settings.json as valid JSON, so drop it rather than write it out.
[[ $theme_name =~ ^[^[:cntrl:]\"\\]+$ ]] || theme_name=""
# Only install a well-formed publisher.name id; a malformed one skips the
# install without skipping the colorTheme write below.
if [[ $extension =~ ^[a-zA-Z0-9._-]+$ ]] &&
! "$editor_cmd" --list-extensions 2>/dev/null | grep -Fxq "$extension"; then
"$editor_cmd" --install-extension "$extension" >/dev/null 2>&1
fi
elif [[ -f "$GENERATED_THEME" ]]; then
# VS Code only discovers local color themes through an extension package.
install_generated_extension "$ext_base/$GENERATED_EXTENSION_NAME"
theme_name="Omarchy"
fi
if [[ -n "$theme_name" ]]; then
mkdir -p "$(dirname "$settings_path")"
[[ -f $settings_path ]] || printf '{\n}\n' >"$settings_path"
# settings.json is JSONC: comments and trailing commas are legal there and
# common in practice, so it's edited in place rather than round-tripped
# through a strict JSON parser that would reject it and reformat the rest.
local escaped=${theme_name//&/\\&}
escaped=${escaped//|/\\|}
if ! grep -q '"workbench.colorTheme"' "$settings_path"; then
sed -i --follow-symlinks -E '0,/\{/{s/\{/{\ "workbench.colorTheme": "",/}' "$settings_path"
fi
sed -i --follow-symlinks -E \
"s|(\"workbench.colorTheme\"[[:space:]]*:[[:space:]]*\")[^\"]*(\")|\1$escaped\2|" \
"$settings_path"
elif [[ -f $settings_path ]]; then
sed -i --follow-symlinks -E 's/\"workbench\.colorTheme\"[[:space:]]*:[^,}]*,?//' "$settings_path"
fi
}
! omarchy-toggle-enabled skip-vscode-theme-changes && set_theme "code" "$HOME/.config/Code/User/settings.json" "$HOME/.vscode/extensions"
! omarchy-toggle-enabled skip-vscode-insiders-theme-changes && set_theme "code-insiders" "$HOME/.config/Code - Insiders/User/settings.json" "$HOME/.vscode-insiders/extensions"
! omarchy-toggle-enabled skip-codium-theme-changes && set_theme "codium" "$HOME/.config/VSCodium/User/settings.json" "$HOME/.vscode-oss/extensions"
! omarchy-toggle-enabled skip-cursor-theme-changes && set_theme "/usr/bin/cursor" "$HOME/.config/Cursor/User/settings.json" "$HOME/.cursor/extensions"