@launchsecure/launch-kit 0.0.28 → 0.0.29
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/dist/server/chart-serve.js +3 -1
- package/dist/server/cli.js +231 -221
- package/dist/server/council-entry.js +0 -0
- package/dist/server/course-entry.js +3 -3
- package/dist/server/fb-wizard.js +0 -0
- package/dist/server/graph-mcp-entry.js +35 -72
- package/dist/server/init-entry.js +794 -195
- package/package.json +22 -21
- package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +4 -4
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/.claude-plugin/plugin.json +1 -10
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/activate-beacon.md +2 -2
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +46 -0
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-array.md +3 -3
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-clear.md +2 -2
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-pulse.md +7 -7
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-scan.md +7 -7
- package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +34 -0
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/show-mcp-status.md +6 -6
- package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/standup.md +52 -38
- package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
- package/scaffolds/recall-hook/scripts/ensure-recall.sh +0 -0
- package/scaffolds/statusline/statusline-mcp.sh +192 -0
- package/scaffolds/statusline/statusline-wrapper.sh +50 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# launch-kit MCP chip generator.
|
|
3
|
+
# Emits a colored one-line summary of MCP daemon health, one chip per daemon.
|
|
4
|
+
# Composes into any existing statusline via the launch-kit wrapper.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# statusline-mcp.sh # all known chips (recall, chart, deck, council)
|
|
8
|
+
# statusline-mcp.sh --show=recall,chart # only the listed chips
|
|
9
|
+
# statusline-mcp.sh --compact # collapse to `mcp <up>/<total>`
|
|
10
|
+
# green when all up, red if any down
|
|
11
|
+
#
|
|
12
|
+
# Project root is inferred from $LK_STATUSLINE_CWD (set by the wrapper) or
|
|
13
|
+
# $PWD by walking up until a `.launchsecure` dir is found. Silent exit when
|
|
14
|
+
# the cwd is not inside a launchsecure project.
|
|
15
|
+
set -u
|
|
16
|
+
|
|
17
|
+
show=""
|
|
18
|
+
compact=0
|
|
19
|
+
for arg in "$@"; do
|
|
20
|
+
case "$arg" in
|
|
21
|
+
--show=*) show="${arg#--show=}" ;;
|
|
22
|
+
--compact) compact=1 ;;
|
|
23
|
+
esac
|
|
24
|
+
done
|
|
25
|
+
[ -z "$show" ] && show="recall,chart,deck,council"
|
|
26
|
+
|
|
27
|
+
GREEN=$'\033[32m'
|
|
28
|
+
ORANGE=$'\033[33m'
|
|
29
|
+
RED=$'\033[31m'
|
|
30
|
+
RESET=$'\033[0m'
|
|
31
|
+
|
|
32
|
+
find_project_root() {
|
|
33
|
+
# `.recall` only exists at the repo root (launch-recall init creates it
|
|
34
|
+
# there). `.launchsecure` can appear in subdirs too (e.g. packages/cli
|
|
35
|
+
# when graphs are generated for a sub-project), so we prefer .recall as
|
|
36
|
+
# the canonical root marker. Fallback: outermost `.launchsecure` ancestor
|
|
37
|
+
# (walk up and keep overwriting → keeps the highest match).
|
|
38
|
+
local d="${1:-$PWD}"
|
|
39
|
+
local recall_root=""
|
|
40
|
+
local outermost_launchsecure=""
|
|
41
|
+
while [ -n "$d" ] && [ "$d" != "/" ]; do
|
|
42
|
+
if [ -z "$recall_root" ] && [ -d "$d/.recall" ]; then
|
|
43
|
+
recall_root="$d"
|
|
44
|
+
fi
|
|
45
|
+
if [ -d "$d/.launchsecure" ]; then
|
|
46
|
+
outermost_launchsecure="$d"
|
|
47
|
+
fi
|
|
48
|
+
d=$(dirname "$d")
|
|
49
|
+
done
|
|
50
|
+
if [ -n "$recall_root" ]; then echo "$recall_root"; return 0; fi
|
|
51
|
+
if [ -n "$outermost_launchsecure" ]; then echo "$outermost_launchsecure"; return 0; fi
|
|
52
|
+
return 1
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
PROJECT_ROOT=$(find_project_root "${LK_STATUSLINE_CWD:-$PWD}") || exit 0
|
|
56
|
+
|
|
57
|
+
iso_to_epoch() {
|
|
58
|
+
# Input is always UTC (ISO timestamps from .freshness.json end in Z).
|
|
59
|
+
# macOS BSD `date` defaults to local TZ, so without TZ=UTC the timestamp
|
|
60
|
+
# gets misread as local time → wildly wrong age (e.g. 6h instead of 55m).
|
|
61
|
+
local ts="$1"
|
|
62
|
+
ts="${ts%%.*}"; ts="${ts%%Z*}"; ts="${ts%%+*}"
|
|
63
|
+
TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%S" "$ts" +%s 2>/dev/null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fmt_age() {
|
|
67
|
+
local then="$1"
|
|
68
|
+
local now diff
|
|
69
|
+
now=$(date +%s)
|
|
70
|
+
diff=$((now - then))
|
|
71
|
+
if [ "$diff" -lt 60 ]; then echo "${diff}s"
|
|
72
|
+
elif [ "$diff" -lt 3600 ]; then echo "$((diff/60))m"
|
|
73
|
+
elif [ "$diff" -lt 86400 ]; then echo "$((diff/3600))h"
|
|
74
|
+
else echo "$((diff/86400))d"
|
|
75
|
+
fi
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
pid_from_lockfile() {
|
|
79
|
+
grep -o '"pid"[^,}]*' "$1" 2>/dev/null | head -1 | sed 's/[^0-9]//g'
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Each chip_* function sets two globals so the caller can use both the
|
|
83
|
+
# colored display string (verbose mode) and the abstract state (compact mode)
|
|
84
|
+
# without re-running the underlying probe. Must be called as a bare command
|
|
85
|
+
# (no subshell) so the assignments survive.
|
|
86
|
+
_state=""
|
|
87
|
+
_display=""
|
|
88
|
+
|
|
89
|
+
chip_recall() {
|
|
90
|
+
local pidfile="$PROJECT_ROOT/.recall/watch.pid"
|
|
91
|
+
local repo="$PROJECT_ROOT/.recall/repo.git"
|
|
92
|
+
if [ ! -f "$pidfile" ]; then _state="red"; _display="${RED}recall${RESET}"; return; fi
|
|
93
|
+
local pid
|
|
94
|
+
pid=$(cat "$pidfile" 2>/dev/null) || pid=""
|
|
95
|
+
if [ -z "$pid" ] || ! kill -0 "$pid" 2>/dev/null; then
|
|
96
|
+
_state="red"; _display="${RED}recall${RESET}"
|
|
97
|
+
return
|
|
98
|
+
fi
|
|
99
|
+
if [ -d "$repo" ]; then
|
|
100
|
+
local last
|
|
101
|
+
last=$(git --git-dir="$repo" log -1 --format=%ct 2>/dev/null)
|
|
102
|
+
if [ -n "$last" ]; then
|
|
103
|
+
local now diff age
|
|
104
|
+
now=$(date +%s); diff=$((now - last)); age=$(fmt_age "$last")
|
|
105
|
+
if [ "$diff" -gt 21600 ]; then
|
|
106
|
+
_state="orange"; _display="${ORANGE}recall(${age})${RESET}"
|
|
107
|
+
else
|
|
108
|
+
_state="green"; _display="${GREEN}recall(${age})${RESET}"
|
|
109
|
+
fi
|
|
110
|
+
return
|
|
111
|
+
fi
|
|
112
|
+
fi
|
|
113
|
+
_state="green"; _display="${GREEN}recall${RESET}"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
chip_chart() {
|
|
117
|
+
local freshness="$PROJECT_ROOT/.launchsecure/graphs/.freshness.json"
|
|
118
|
+
if [ ! -f "$freshness" ]; then _state="red"; _display="${RED}chart${RESET}"; return; fi
|
|
119
|
+
local last
|
|
120
|
+
last=$(grep -o '"lastFullRegenAt"[^,}]*' "$freshness" | head -1 | sed 's/.*"\([0-9TZ:.+-]*\)".*/\1/')
|
|
121
|
+
local lock="$PROJECT_ROOT/.launchsecure/launch-chart.lock"
|
|
122
|
+
local color="$ORANGE"; local state="orange"
|
|
123
|
+
if [ -f "$lock" ]; then
|
|
124
|
+
local pid
|
|
125
|
+
pid=$(pid_from_lockfile "$lock")
|
|
126
|
+
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
|
127
|
+
color="$GREEN"; state="green"
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
if [ -n "$last" ] && [ "$last" != "null" ]; then
|
|
131
|
+
local epoch age
|
|
132
|
+
epoch=$(iso_to_epoch "$last")
|
|
133
|
+
if [ -n "$epoch" ]; then
|
|
134
|
+
age=$(fmt_age "$epoch")
|
|
135
|
+
_state="$state"; _display="${color}chart(${age})${RESET}"
|
|
136
|
+
return
|
|
137
|
+
fi
|
|
138
|
+
fi
|
|
139
|
+
_state="$state"; _display="${color}chart${RESET}"
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
chip_deck() {
|
|
143
|
+
local lock="$PROJECT_ROOT/.launchsecure/launch-deck.lock"
|
|
144
|
+
if [ -f "$lock" ]; then
|
|
145
|
+
local pid; pid=$(pid_from_lockfile "$lock")
|
|
146
|
+
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
|
147
|
+
_state="green"; _display="${GREEN}deck${RESET}"; return
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
_state="orange"; _display="${ORANGE}deck${RESET}"
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
chip_council() {
|
|
154
|
+
local lock="$PROJECT_ROOT/.launchsecure/launch-council.lock"
|
|
155
|
+
if [ -f "$lock" ]; then
|
|
156
|
+
local pid; pid=$(pid_from_lockfile "$lock")
|
|
157
|
+
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
|
158
|
+
_state="green"; _display="${GREEN}council${RESET}"; return
|
|
159
|
+
fi
|
|
160
|
+
fi
|
|
161
|
+
_state="orange"; _display="${ORANGE}council${RESET}"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
show_list=$(echo "$show" | tr ',' ' ')
|
|
165
|
+
total=0
|
|
166
|
+
up=0
|
|
167
|
+
out=""
|
|
168
|
+
for d in $show_list; do
|
|
169
|
+
case "$d" in
|
|
170
|
+
recall) chip_recall ;;
|
|
171
|
+
chart) chip_chart ;;
|
|
172
|
+
deck) chip_deck ;;
|
|
173
|
+
council) chip_council ;;
|
|
174
|
+
*) continue ;;
|
|
175
|
+
esac
|
|
176
|
+
total=$((total + 1))
|
|
177
|
+
[ "$_state" = "green" ] && up=$((up + 1))
|
|
178
|
+
if [ "$compact" = "0" ]; then
|
|
179
|
+
if [ -z "$out" ]; then out="$_display"; else out="${out} · ${_display}"; fi
|
|
180
|
+
fi
|
|
181
|
+
done
|
|
182
|
+
|
|
183
|
+
if [ "$compact" = "1" ]; then
|
|
184
|
+
if [ "$total" -eq 0 ]; then exit 0; fi
|
|
185
|
+
if [ "$up" -eq "$total" ]; then
|
|
186
|
+
printf '%smcp %d/%d%s' "$GREEN" "$up" "$total" "$RESET"
|
|
187
|
+
else
|
|
188
|
+
printf '%smcp %d/%d%s' "$RED" "$up" "$total" "$RESET"
|
|
189
|
+
fi
|
|
190
|
+
else
|
|
191
|
+
printf '%s' "$out"
|
|
192
|
+
fi
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# launch-kit statusline wrapper.
|
|
3
|
+
# Runs the user's original statusline command, then appends MCP chip output.
|
|
4
|
+
# Reads Claude Code's statusline JSON from stdin once, fans it out.
|
|
5
|
+
#
|
|
6
|
+
# The original command is stored under `_launchKitStatuslineOriginal.command`
|
|
7
|
+
# in ~/.claude/settings.json (written by `launch-kit statusline activate`).
|
|
8
|
+
# `launch-kit statusline deactivate` restores it to `statusLine.command`.
|
|
9
|
+
set -u
|
|
10
|
+
|
|
11
|
+
input=$(cat)
|
|
12
|
+
settings="$HOME/.claude/settings.json"
|
|
13
|
+
|
|
14
|
+
original_cmd=""
|
|
15
|
+
if [ -f "$settings" ] && command -v jq >/dev/null 2>&1; then
|
|
16
|
+
original_cmd=$(jq -r '._launchKitStatuslineOriginal.command // empty' "$settings" 2>/dev/null || true)
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
original_output=""
|
|
20
|
+
if [ -n "$original_cmd" ]; then
|
|
21
|
+
original_output=$(printf '%s' "$input" | bash -c "$original_cmd" 2>/dev/null || true)
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
cwd=""
|
|
25
|
+
if command -v jq >/dev/null 2>&1; then
|
|
26
|
+
cwd=$(printf '%s' "$input" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null || true)
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
chips=""
|
|
30
|
+
if [ -x "$HOME/.launchsecure/statusline-mcp.sh" ]; then
|
|
31
|
+
# Build args array conditionally; `set -u` + empty `"${args[@]}"` would
|
|
32
|
+
# error on bash 4 (default macOS bash), so test length before expanding.
|
|
33
|
+
args=()
|
|
34
|
+
[ -n "${LK_STATUSLINE_SHOW:-}" ] && args+=("--show=$LK_STATUSLINE_SHOW")
|
|
35
|
+
[ "${LK_STATUSLINE_COMPACT:-0}" = "1" ] && args+=("--compact")
|
|
36
|
+
if [ "${#args[@]}" -eq 0 ]; then
|
|
37
|
+
chips=$(LK_STATUSLINE_CWD="$cwd" "$HOME/.launchsecure/statusline-mcp.sh" 2>/dev/null || true)
|
|
38
|
+
else
|
|
39
|
+
chips=$(LK_STATUSLINE_CWD="$cwd" "$HOME/.launchsecure/statusline-mcp.sh" "${args[@]}" 2>/dev/null || true)
|
|
40
|
+
fi
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
sep=$'\033[2m | \033[0m'
|
|
44
|
+
if [ -n "$original_output" ] && [ -n "$chips" ]; then
|
|
45
|
+
printf '%s%s%s' "$original_output" "$sep" "$chips"
|
|
46
|
+
elif [ -n "$original_output" ]; then
|
|
47
|
+
printf '%s' "$original_output"
|
|
48
|
+
elif [ -n "$chips" ]; then
|
|
49
|
+
printf '%s' "$chips"
|
|
50
|
+
fi
|