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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/bin/bash
# omarchy:summary=Clone a built-in Omarchy shell plugin into your own config
# omarchy:group=plugin
# omarchy:args=<source-id> [--edit]
set -euo pipefail
PLUGINS_DIR="$HOME/.config/omarchy/plugins"
fail() {
echo "omarchy-plugin-clone: $*" >&2
exit 1
}
copy_plugin() {
local source_dir="$1"
local manifest="$2"
local target_dir="$3"
if [[ ${manifest##*/} == "manifest.json" ]]; then
cp -aL "$source_dir/." "$target_dir/"
return
fi
cp -aL "$manifest" "$target_dir/manifest.json"
local source target source_pattern file
while IFS=$'\t' read -r source target; do
[[ $target != /* && $target != *".."* ]] || fail "invalid clone target path: $target"
if [[ -d $source_dir/$source ]]; then
mkdir -p "$target_dir/$target"
cp -aL "$source_dir/$source/." "$target_dir/$target/"
else
mkdir -p "$(dirname "$target_dir/$target")"
cp -aL "$source_dir/$source" "$target_dir/$target"
fi
if [[ $source != "$target" ]]; then
source_pattern=${source//./\\.}
while IFS= read -r -d '' file; do
sed -i "s|$source_pattern|$target|g" "$file"
done < <(rg --files-with-matches --null --fixed-strings "$source" "$target_dir")
fi
done < <(jq -r '
[
(.entryPoints[] | {source: ., target: .}),
(.omarchy.clonePaths[]? | {source: .source, target: .target})
] | unique_by(.target)[] | [.source, .target] | @tsv
' "$manifest")
}
update_manifest() {
local target_dir="$1"
local source_id="$2"
local new_id="$3"
local display_name="$4"
local manifest="$target_dir/manifest.json"
# Keep built-in ids inside the plugin code as stable IPC targets. The shell
# uses clonedFrom to route those calls to this local manifest id.
jq \
--arg id "$new_id" \
--arg name "$display_name" \
--arg sourceId "$source_id" '
.id = $id |
.name = $name |
if (.barWidget | type) == "object" then
.barWidget.displayName = $name
else
.
end |
.omarchy = (
(if (.omarchy | type) == "object" then .omarchy else {} end) +
{ clonedFrom: $sourceId }
) |
del(.omarchy.clonePaths)
' "$manifest" >"$manifest.tmp"
mv "$manifest.tmp" "$manifest"
}
usage() {
cat <<USAGE
Usage: omarchy plugin clone <source-id> [--edit]
Copies a built-in plugin into ~/.config/omarchy/plugins/<username>.<id>/ so you
can edit it freely. The clone keeps all of the source plugin's files and kinds
and uses "My <name>" as its display name, then replaces the built-in with the
clone. The username prefix keeps the id yours, so a shared clone does not
collide with anyone else's. --edit opens the clone in \$EDITOR afterwards.
USAGE
}
source_id=""
edit_clone=0
if (( $# > 0 )) && [[ $1 != --* ]]; then
source_id="$1"
shift
fi
while (( $# > 0 )); do
case "$1" in
--edit)
edit_clone=1
shift
;;
-h | --help)
usage
exit 0
;;
*)
fail "unknown clone option: $1"
;;
esac
done
[[ -n $source_id ]] || fail "clone source is required"
source_info=$(omarchy-plugin-catalog | jq -r --arg id "$source_id" '
.[] | select(.firstParty and .id == $id)
| [
.sourceDir,
.manifestPath,
(.name // .id)
] | @tsv
')
[[ -n $source_info ]] || fail "unknown built-in plugin: $source_id"
IFS=$'\t' read -r source_dir source_manifest source_name <<<"$source_info"
new_id="${USER:-$(id -un)}.${source_id#omarchy.}"
display_name="My $source_name"
target_dir="$PLUGINS_DIR/$new_id"
[[ ! -e $target_dir && ! -L $target_dir ]] || fail "$target_dir already exists"
mkdir -p "$PLUGINS_DIR"
stage=$(mktemp -d "$PLUGINS_DIR/.clone.XXXXXX")
clone_complete=0
cleanup() {
[[ -d ${stage:-} ]] && rm -rf "$stage"
(( clone_complete )) || rm -rf "$target_dir"
}
trap cleanup EXIT
copy_plugin "$source_dir" "$source_manifest" "$stage"
update_manifest "$stage" "$source_id" "$new_id" "$display_name"
mv "$stage" "$target_dir"
stage=""
omarchy-shell shell rescanPlugins >/dev/null
discovered=0
for (( attempt = 0; attempt < 40; attempt++ )); do
if omarchy-plugin-list --json | jq -e --arg id "$new_id" 'any(.[]; .id == $id)' >/dev/null; then
discovered=1
break
fi
sleep 0.05
done
(( discovered )) || fail "cloned plugin '$new_id' was not discovered"
omarchy-plugin-enable "$new_id" >/dev/null
clone_complete=1
omarchy-notification-send -g \
"Editing Cloned Plugin" \
"Original plugin has been replace by clone."
echo "Cloned $source_id to $target_dir and switched to $new_id"
if (( edit_clone )); then
# Word-splitting is deliberate: EDITOR may carry flags.
exec $EDITOR "$target_dir"
fi