acstack 0.48.5 → 0.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/assets/terminal-workspace/helpers/acstack-bridge +185 -0
- package/assets/terminal-workspace/helpers/acstack-clip +88 -0
- package/assets/terminal-workspace/helpers/acstack-dash +25 -0
- package/assets/terminal-workspace/helpers/acstack-db +86 -0
- package/assets/terminal-workspace/helpers/acstack-diff +268 -0
- package/assets/terminal-workspace/helpers/acstack-edit +25 -0
- package/assets/terminal-workspace/helpers/acstack-gh +47 -0
- package/assets/terminal-workspace/helpers/acstack-herdr-renumber +93 -0
- package/assets/terminal-workspace/helpers/acstack-herdr-tab +49 -0
- package/assets/terminal-workspace/helpers/acstack-md +401 -0
- package/assets/terminal-workspace/helpers/acstack-md-lib +219 -0
- package/assets/terminal-workspace/helpers/acstack-open +217 -0
- package/assets/terminal-workspace/helpers/acstack-popup +13 -0
- package/assets/terminal-workspace/helpers/acstack-view +33 -0
- package/assets/terminal-workspace/helpers/xclip +31 -0
- package/assets/terminal-workspace/lib/apply-ghdash.sh +78 -0
- package/assets/terminal-workspace/lib/apply-herdr-numbers.sh +49 -0
- package/assets/terminal-workspace/lib/apply-herdr.sh +308 -0
- package/assets/terminal-workspace/lib/apply-tools.sh +293 -0
- package/assets/terminal-workspace/lib/apply-tuicr.sh +133 -0
- package/assets/terminal-workspace/lib/apply-yazi.sh +389 -0
- package/assets/terminal-workspace/lib/commands.sh +296 -0
- package/assets/terminal-workspace/lib/core.sh +184 -0
- package/assets/terminal-workspace/lib/helper-install.sh +35 -0
- package/assets/terminal-workspace/lib/pi-packages.sh +331 -0
- package/assets/terminal-workspace/lib/pi-state.sh +479 -0
- package/assets/terminal-workspace/lib/versions.sh +254 -0
- package/assets/terminal-workspace/setup.sh +24 -4637
- package/cli/dist/index.js +8 -4
- package/cli/dist/index.js.map +2 -2
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/skills/archive/SKILL.md +3 -0
- package/skills/grilling/SKILL.md +2 -1
- package/skills/handoff/SKILL.md +14 -14
- package/skills/handoff/launch-herdr.md +15 -4
- package/skills/implement/SKILL.md +19 -3
- package/skills/map/SKILL.md +24 -24
- package/skills/map/alignment.md +38 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
version_table() {
|
|
2
|
+
cat <<'T'
|
|
3
|
+
delta delta github dandavison/delta x86_64-unknown-linux-gnu
|
|
4
|
+
diffnav diffnav github dlvhdr/diffnav Linux_x86_64
|
|
5
|
+
fzf diffnav github junegunn/fzf linux_amd64
|
|
6
|
+
lazygit lazygit github jesseduffield/lazygit linux_x86_64
|
|
7
|
+
tuicr tuicr github agavra/tuicr x86_64-unknown-linux-gnu
|
|
8
|
+
yazi yazi github sxyazi/yazi x86_64-unknown-linux-gnu
|
|
9
|
+
glow markdown github charmbracelet/glow Linux_x86_64
|
|
10
|
+
herdr herdr herdr - -
|
|
11
|
+
gh-dash gh_dash ghext dlvhdr/gh-dash -
|
|
12
|
+
harlequin harlequin pypi harlequin -
|
|
13
|
+
pi pi npm @earendil-works/pi-coding-agent -
|
|
14
|
+
pi-subagents pi npm pi-subagents -
|
|
15
|
+
billion-context pi npm billion-context -
|
|
16
|
+
@juicesharp/rpiv-todo pi npm @juicesharp/rpiv-todo -
|
|
17
|
+
pi-plugin-manager pi npm pi-plugin-manager -
|
|
18
|
+
@juicesharp/rpiv-ask-user-question pi npm @juicesharp/rpiv-ask-user-question -
|
|
19
|
+
pi-web-access pi npm pi-web-access -
|
|
20
|
+
pi-lens pi npm pi-lens -
|
|
21
|
+
pi-slash-anywhere pi npm pi-slash-anywhere -
|
|
22
|
+
pi-compact-tools pi npm pi-compact-tools -
|
|
23
|
+
pi-zentui pi npm pi-zentui -
|
|
24
|
+
actionlint pi github rhysd/actionlint linux_amd64
|
|
25
|
+
hadolint pi github hadolint/hadolint Linux-x86_64
|
|
26
|
+
terraform-ls pi github hashicorp/terraform-ls linux_amd64
|
|
27
|
+
tflint pi github terraform-linters/tflint linux_amd64
|
|
28
|
+
terragrunt pi github gruntwork-io/terragrunt linux_amd64
|
|
29
|
+
T
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
installed_version() { # installed_version <name> -> a bare version, or nothing
|
|
33
|
+
local v=""
|
|
34
|
+
case "$1" in
|
|
35
|
+
# delta 0.19.2
|
|
36
|
+
delta) v=$(delta --version 2>/dev/null | awk '{print $2}') ;;
|
|
37
|
+
# an ASCII banner, then: version v0.12.0
|
|
38
|
+
diffnav) v=$(diffnav --version 2>/dev/null | sed -n 's/^version //p') ;;
|
|
39
|
+
# 0.74.3 (15f64c49)
|
|
40
|
+
fzf) v=$(fzf --version 2>/dev/null | awk '{print $1}') ;;
|
|
41
|
+
# commit=..., version=0.64.1, os=linux, arch=amd64, git version=2.43.0
|
|
42
|
+
# Split on the commas first: the line ends in git's own version, and one
|
|
43
|
+
# regex over the whole line reads that one instead of lazygit's.
|
|
44
|
+
lazygit) v=$(lazygit --version 2>/dev/null | tr ',' '\n' | sed -n 's/^ *version=//p') ;;
|
|
45
|
+
# glow version 3.0.0 (add5e7a)
|
|
46
|
+
glow) v=$(glow --version 2>/dev/null | awk '{print $3}') ;;
|
|
47
|
+
# tuicr 0.23.0
|
|
48
|
+
tuicr) v=$(tuicr --version 2>/dev/null | awk '{print $2}') ;;
|
|
49
|
+
# a block of lines, one of them: " Version: 26.8.15 (1f3588d 2026-08-15)"
|
|
50
|
+
yazi) v=$(yazi --version 2>/dev/null | sed -n 's/^ *Version: \([^ ]*\).*/\1/p') ;;
|
|
51
|
+
# herdr 0.8.2
|
|
52
|
+
herdr) v=$(herdr --version 2>/dev/null | awk '{print $2}') ;;
|
|
53
|
+
# gh dash<TAB>dlvhdr/gh-dash<TAB>v4.25.2
|
|
54
|
+
gh-dash) v=$(gh extension list 2>/dev/null | awk -F'\t' '$2=="dlvhdr/gh-dash"{print $3}') ;;
|
|
55
|
+
# harlequin v2.13.0, then an indented line per command it installed
|
|
56
|
+
harlequin) v=$(uv tool list 2>/dev/null | awk '$1=="harlequin"{print $2}') ;;
|
|
57
|
+
# 1.1.0
|
|
58
|
+
pi) find_pi; v=$(pi --version 2>/dev/null | awk '{print $NF}') ;;
|
|
59
|
+
# actionlint version 1.7.7
|
|
60
|
+
actionlint) v=$(actionlint -version 2>/dev/null | awk '{print $2}') ;;
|
|
61
|
+
# Haskell Dockerfile Linter 2.12.0
|
|
62
|
+
hadolint) v=$(hadolint --version 2>/dev/null | awk '{print $NF}') ;;
|
|
63
|
+
# terraform-ls version 0.36.5
|
|
64
|
+
terraform-ls) v=$(terraform-ls version 2>/dev/null | awk '{print $2}') ;;
|
|
65
|
+
# TFLint version 0.59.1
|
|
66
|
+
tflint) v=$(tflint --version 2>/dev/null | awk 'NR==1{print $3}') ;;
|
|
67
|
+
# terragrunt version v0.91.2
|
|
68
|
+
terragrunt) v=$(terragrunt --version 2>/dev/null | awk '{print $NF}') ;;
|
|
69
|
+
# pi installs npm packages under its own directory, not npm's global one.
|
|
70
|
+
*) if pkg=$(pi_npm_package "$1"); then
|
|
71
|
+
v=$(json_field "$PI_DIR/npm/node_modules/${pkg#npm:}/package.json" version)
|
|
72
|
+
fi ;;
|
|
73
|
+
esac
|
|
74
|
+
printf '%s' "${v#v}"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# One JSON field, by dotted path, read from a file. install_binary hands its
|
|
78
|
+
# release document to python through the environment; this one cannot, because
|
|
79
|
+
# herdr's manifest carries a whole changelog and a document that size overflows
|
|
80
|
+
# the environment an exec is allowed. A file has no such ceiling.
|
|
81
|
+
json_field() { # json_field <file> <dotted.path>
|
|
82
|
+
py "$1" "$2" <<'PY'
|
|
83
|
+
import json, sys
|
|
84
|
+
try:
|
|
85
|
+
d = json.load(open(sys.argv[1]))
|
|
86
|
+
except (ValueError, OSError):
|
|
87
|
+
raise SystemExit
|
|
88
|
+
for k in sys.argv[2].split("."):
|
|
89
|
+
d = d.get(k) if isinstance(d, dict) else None
|
|
90
|
+
if d is None: raise SystemExit
|
|
91
|
+
print(d)
|
|
92
|
+
PY
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
latest_version() { # latest_version <source> <reference> -> a version, or nothing
|
|
96
|
+
[ "${ACSTACK_TW_OFFLINE:-0}" = "1" ] && return 0
|
|
97
|
+
local url field tmp v="" tok="${GH_TOKEN:-${GITHUB_TOKEN:-}}"
|
|
98
|
+
local -a auth=()
|
|
99
|
+
case "$1" in
|
|
100
|
+
github|ghext)
|
|
101
|
+
url="https://api.github.com/repos/$2/releases/latest"; field=tag_name
|
|
102
|
+
# An unauthenticated GitHub call gets 60 an hour, shared with everything
|
|
103
|
+
# else on the machine. Ten tools in one run is a sixth of that. A token
|
|
104
|
+
# raises it to 5000 and costs nothing to pass. It goes to GitHub and
|
|
105
|
+
# nowhere else: the two hosts below never see it.
|
|
106
|
+
[ -n "$tok" ] && auth=(-H "Authorization: Bearer $tok") ;;
|
|
107
|
+
# herdr publishes its own manifest, and `herdr update` installs from it.
|
|
108
|
+
herdr) url="https://herdr.dev/latest.json"; field=version ;;
|
|
109
|
+
pypi) url="https://pypi.org/pypi/$2/json"; field=info.version ;;
|
|
110
|
+
# A scoped name keeps its @ and escapes its slash.
|
|
111
|
+
npm) url="https://registry.npmjs.org/${2/\//%2F}/latest"; field=version ;;
|
|
112
|
+
*) return 0 ;;
|
|
113
|
+
esac
|
|
114
|
+
tmp=$(mktemp)
|
|
115
|
+
curl -sSf "${auth[@]}" --max-time 10 "$url" -o "$tmp" 2>/dev/null \
|
|
116
|
+
&& v=$(json_field "$tmp" "$field")
|
|
117
|
+
rm -f "$tmp"
|
|
118
|
+
printf '%s' "${v#v}"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
outdated_report() { # tab-separated rows on stdout, one per finding
|
|
122
|
+
local name key src ref inst latest
|
|
123
|
+
# Components that arrived since the last apply. See write_stamp for why this
|
|
124
|
+
# reads the stamp rather than the user's own config: a config that overrides
|
|
125
|
+
# four keys and defaults the rest is normal, and diffing against it would
|
|
126
|
+
# report every defaulted component as new.
|
|
127
|
+
if [ ! -f "$STAMP" ]; then
|
|
128
|
+
# No stamp and no managed block is a machine apply has never touched.
|
|
129
|
+
# Comparing versions there would report a workspace as current when none
|
|
130
|
+
# of it is installed, so say the one true thing and stop.
|
|
131
|
+
if ! grep -q "$BEGIN" "$HERDR_CFG" 2>/dev/null; then
|
|
132
|
+
printf 'missing\tworkspace\tnever applied on this machine\n'
|
|
133
|
+
return 0
|
|
134
|
+
fi
|
|
135
|
+
printf 'unknown\tcomponents\tno stamp yet, run apply once\n'
|
|
136
|
+
elif [ -f "$EXAMPLE" ]; then
|
|
137
|
+
# The row stays until apply installs the component and writes a new stamp.
|
|
138
|
+
# Only the detail moves: once upgrade has appended the block, "not in your
|
|
139
|
+
# config" is false, and a report that says it is stops being worth reading.
|
|
140
|
+
ACSTACK_STAMP="$STAMP" py "$EXAMPLE" "$CFG" <<'PY'
|
|
141
|
+
import os, re, sys
|
|
142
|
+
import yaml
|
|
143
|
+
had = {l.strip() for l in open(os.environ["ACSTACK_STAMP"])
|
|
144
|
+
if l.strip() and not l.startswith("#")}
|
|
145
|
+
mine = open(sys.argv[2]).read() if os.path.isfile(sys.argv[2]) else ""
|
|
146
|
+
for k in (yaml.safe_load(open(sys.argv[1])) or {}):
|
|
147
|
+
if k in had:
|
|
148
|
+
continue
|
|
149
|
+
if re.search(r"(?m)^%s:" % re.escape(k), mine):
|
|
150
|
+
print("new\t%s\tnew component, run apply to install it" % k)
|
|
151
|
+
else:
|
|
152
|
+
print("new\t%s\tnew component, not in your config" % k)
|
|
153
|
+
PY
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
while IFS=$'\t' read -r name key src ref _; do
|
|
157
|
+
[ "$(cfg_get "$key.enabled" "$(enabled_default "$key")")" = "true" ] || continue
|
|
158
|
+
# A fork build's version comes from a local checkout, so a release tag says
|
|
159
|
+
# nothing about it.
|
|
160
|
+
[ "$name" = "tuicr" ] && [ "$(cfg_get tuicr.build_from_fork false)" = "true" ] && continue
|
|
161
|
+
# pi update never moves a pinned npm source, so a newer release is nothing
|
|
162
|
+
# upgrade could fetch. Say so once instead of reporting it stale forever.
|
|
163
|
+
if pi_npm_pin "$name"; then
|
|
164
|
+
printf 'unknown\t%s\tpinned to %s in pi, which pi update never moves\n' "$name" "$(pi_state pkg "$(pi_npm_package "$name")")"
|
|
165
|
+
continue
|
|
166
|
+
fi
|
|
167
|
+
inst=$(installed_version "$name")
|
|
168
|
+
[ -n "$inst" ] || continue # not installed is apply's business, not this one
|
|
169
|
+
latest=$(latest_version "$src" "$ref")
|
|
170
|
+
if [ -z "$latest" ]; then
|
|
171
|
+
[ "${ACSTACK_TW_OFFLINE:-0}" = "1" ] \
|
|
172
|
+
|| printf 'unknown\t%s\tcould not reach %s\n' "$name" "$src"
|
|
173
|
+
elif [ "$inst" != "$latest" ]; then
|
|
174
|
+
printf 'stale\t%s\t%s -> %s\n' "$name" "$inst" "$latest"
|
|
175
|
+
fi
|
|
176
|
+
done < <(version_table)
|
|
177
|
+
|
|
178
|
+
# The ACStack package on pi is pinned to a release, so it falls behind the
|
|
179
|
+
# moment this plugin updates. Both versions are local, so this needs no
|
|
180
|
+
# network and reports even offline.
|
|
181
|
+
if [ "$(cfg_get pi.enabled false)" = "true" ]; then
|
|
182
|
+
local behind; behind=$(pi_acstack_behind)
|
|
183
|
+
[ -n "$behind" ] && printf 'stale\tpi-acstack\t%s -> %s\n' "${behind%%$'\t'*}" "${behind#*$'\t'}"
|
|
184
|
+
fi
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
# Reinstalls over what is there, from the coordinates the table already holds.
|
|
188
|
+
# Split out so the tuicr arm can guard the fork build and still reach it,
|
|
189
|
+
# rather than carrying a second copy of the repository and the asset match.
|
|
190
|
+
upgrade_from_table() { # upgrade_from_table <name>
|
|
191
|
+
local repo match
|
|
192
|
+
read -r repo match < <(version_table | awk -F'\t' -v n="$1" '$1==n{print $4, $5}')
|
|
193
|
+
[ -n "${repo:-}" ] && [ "$repo" != "-" ] \
|
|
194
|
+
|| { say "$1 is not a tool this script installs"; return 1; }
|
|
195
|
+
INSTALL_FORCE=1 install_binary "$1" "$repo" "$match"
|
|
196
|
+
# yazi's archive carries ya beside it, and the two must not drift.
|
|
197
|
+
if [ "$1" = "yazi" ]; then
|
|
198
|
+
INSTALL_FORCE=1 install_binary ya sxyazi/yazi "$match"
|
|
199
|
+
fi
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
upgrade_one() { # upgrade_one <name>
|
|
203
|
+
if [ "$1" = "pi-acstack" ] || pi_npm_package "$1" >/dev/null; then
|
|
204
|
+
find_pi
|
|
205
|
+
fi
|
|
206
|
+
case "$1" in
|
|
207
|
+
herdr) herdr update >/dev/null 2>&1 \
|
|
208
|
+
&& say "herdr updated" || say "herdr update failed" ;;
|
|
209
|
+
gh-dash) gh extension upgrade dlvhdr/gh-dash >/dev/null 2>&1 \
|
|
210
|
+
&& say "gh-dash upgraded" || say "gh-dash upgrade failed" ;;
|
|
211
|
+
harlequin) uv tool upgrade harlequin >/dev/null 2>&1 \
|
|
212
|
+
&& say "harlequin upgraded" || say "harlequin upgrade failed" ;;
|
|
213
|
+
# With no target, pi update updates pi itself and no package.
|
|
214
|
+
pi) if pi update >/dev/null 2>&1; then
|
|
215
|
+
say "pi updated"
|
|
216
|
+
patch_pi_win32_paste
|
|
217
|
+
else
|
|
218
|
+
say "pi update failed"
|
|
219
|
+
fi ;;
|
|
220
|
+
# Only a pin behind this plugin. A newer pin is the user's choice, and an
|
|
221
|
+
# absent or unpinned ACStack is apply's business.
|
|
222
|
+
pi-acstack)
|
|
223
|
+
[ -n "$(pi_acstack_behind)" ] || { say "pi-acstack: nothing behind this plugin to move"; return 0; }
|
|
224
|
+
pi_add "$PI_ACSTACK@$(acstack_version)" "$PI_ACSTACK" ;;
|
|
225
|
+
# Absent from the table, because it has no version flag for outdated to
|
|
226
|
+
# read. Naming it is the only way to refresh it, so the arm it needs is
|
|
227
|
+
# here rather than behind a table lookup that will never find it.
|
|
228
|
+
mermaid-ascii)
|
|
229
|
+
INSTALL_FORCE=1 install_binary mermaid-ascii AlexanderGrooff/mermaid-ascii Linux_x86_64 ;;
|
|
230
|
+
hadolint)
|
|
231
|
+
INSTALL_FORCE=1 install_plain_github_binary hadolint hadolint/hadolint Linux-x86_64 ;;
|
|
232
|
+
terragrunt)
|
|
233
|
+
INSTALL_FORCE=1 install_plain_github_binary terragrunt gruntwork-io/terragrunt linux_amd64 ;;
|
|
234
|
+
# The fork build comes from a local checkout, so a release archive would
|
|
235
|
+
# replace it with the stock binary and silently drop the patches it carries.
|
|
236
|
+
# outdated already skips it; naming it here has to skip it too.
|
|
237
|
+
tuicr)
|
|
238
|
+
if [ "$(cfg_get tuicr.build_from_fork false)" = "true" ]; then
|
|
239
|
+
say "tuicr is built from a fork here, so run apply to rebuild it"
|
|
240
|
+
return 0
|
|
241
|
+
fi
|
|
242
|
+
upgrade_from_table tuicr ;;
|
|
243
|
+
*) if pkg=$(pi_npm_package "$1"); then
|
|
244
|
+
if pi_npm_pin "$1"; then
|
|
245
|
+
say "$1 is pinned to $(pi_state pkg "$pkg") in pi, which pi update never moves"
|
|
246
|
+
return 0
|
|
247
|
+
fi
|
|
248
|
+
pi update "$pkg" >/dev/null 2>&1 \
|
|
249
|
+
&& say "$1 updated" || say "$1 update failed"
|
|
250
|
+
else
|
|
251
|
+
upgrade_from_table "$1"
|
|
252
|
+
fi ;;
|
|
253
|
+
esac
|
|
254
|
+
}
|