@open-mercato/cli 0.6.6-develop.6483.1.b623f50e2b → 0.6.6-develop.6485.1.6021282db1
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/.turbo/turbo-build.log +3 -3
- package/dist/agentic/guides/module-facts.json +53 -53
- package/dist/agentic/guides/modules/ai_assistant.md +1 -1
- package/dist/agentic/guides/modules/api_docs.md +1 -1
- package/dist/agentic/guides/modules/api_keys.md +1 -1
- package/dist/agentic/guides/modules/attachments.md +1 -1
- package/dist/agentic/guides/modules/audit_logs.md +1 -1
- package/dist/agentic/guides/modules/auth.md +1 -1
- package/dist/agentic/guides/modules/business_rules.md +1 -1
- package/dist/agentic/guides/modules/catalog.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail.md +1 -1
- package/dist/agentic/guides/modules/channel_imap.md +1 -1
- package/dist/agentic/guides/modules/checkout.md +1 -1
- package/dist/agentic/guides/modules/communication_channels.md +1 -1
- package/dist/agentic/guides/modules/configs.md +1 -1
- package/dist/agentic/guides/modules/content.md +1 -1
- package/dist/agentic/guides/modules/currencies.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts.md +1 -1
- package/dist/agentic/guides/modules/customers.md +1 -1
- package/dist/agentic/guides/modules/dashboards.md +1 -1
- package/dist/agentic/guides/modules/data_sync.md +1 -1
- package/dist/agentic/guides/modules/dictionaries.md +1 -1
- package/dist/agentic/guides/modules/directory.md +1 -1
- package/dist/agentic/guides/modules/entities.md +1 -1
- package/dist/agentic/guides/modules/events.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
- package/dist/agentic/guides/modules/generators.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops.md +1 -1
- package/dist/agentic/guides/modules/integrations.md +1 -1
- package/dist/agentic/guides/modules/messages.md +1 -1
- package/dist/agentic/guides/modules/notifications.md +1 -1
- package/dist/agentic/guides/modules/onboarding.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways.md +1 -1
- package/dist/agentic/guides/modules/perspectives.md +1 -1
- package/dist/agentic/guides/modules/planner.md +1 -1
- package/dist/agentic/guides/modules/portal.md +1 -1
- package/dist/agentic/guides/modules/progress.md +1 -1
- package/dist/agentic/guides/modules/query_index.md +1 -1
- package/dist/agentic/guides/modules/record_locks.md +1 -1
- package/dist/agentic/guides/modules/resources.md +1 -1
- package/dist/agentic/guides/modules/sales.md +1 -1
- package/dist/agentic/guides/modules/scheduler.md +1 -1
- package/dist/agentic/guides/modules/search.md +1 -1
- package/dist/agentic/guides/modules/security.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
- package/dist/agentic/guides/modules/sso.md +1 -1
- package/dist/agentic/guides/modules/staff.md +1 -1
- package/dist/agentic/guides/modules/storage_s3.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
- package/dist/agentic/guides/modules/sync_excel.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
- package/dist/agentic/guides/modules/translations.md +1 -1
- package/dist/agentic/guides/modules/webhooks.md +1 -1
- package/dist/agentic/guides/modules/workflows.md +1 -1
- package/dist/agentic/shared/AGENTS.md.template +16 -10
- package/dist/agentic/shared/ai/agentic.config.json +61 -0
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr/SKILL.md +16 -318
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +16 -581
- package/dist/agentic/shared/ai/skills/om-auto-create-pr/SKILL.md +16 -397
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +16 -738
- package/dist/agentic/shared/ai/skills/om-auto-fix-issue/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +16 -565
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +1 -1
- package/dist/agentic/shared/ai/skills/tiers.json +47 -0
- package/dist/agentic/shared/ai/skills/tiers.schema.json +73 -0
- package/dist/agentic/shared/ai/trackers/github.md +376 -0
- package/dist/agentic/shared/scripts/install-skills.sh +488 -0
- package/dist/lib/agentic-setup.js +9 -40
- package/dist/lib/agentic-setup.js.map +2 -2
- package/package.json +5 -5
- package/src/lib/agentic-setup.ts +19 -42
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr/STANDALONE.md +0 -98
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/STANDALONE.md +0 -96
- package/dist/agentic/shared/ai/skills/om-auto-create-pr/STANDALONE.md +0 -98
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/STANDALONE.md +0 -96
- package/dist/agentic/shared/ai/skills/om-auto-fix-github/SKILL.md +0 -419
- package/dist/agentic/shared/ai/skills/om-auto-fix-github/STANDALONE.md +0 -98
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/STANDALONE.md +0 -98
- package/dist/agentic/shared/ai/skills/om-code-review/SKILL.md +0 -108
- package/dist/agentic/shared/ai/skills/om-code-review/references/review-checklist.md +0 -83
- package/dist/agentic/shared/ai/skills/om-integration-tests/SKILL.md +0 -279
- package/dist/agentic/shared/ai/skills/om-prepare-issue/SKILL.md +0 -202
- package/dist/agentic/shared/ai/skills/om-spec-writing/SKILL.md +0 -85
- package/dist/agentic/shared/ai/skills/om-spec-writing/references/spec-checklist.md +0 -67
- package/dist/agentic/shared/ai/skills/om-spec-writing/references/spec-template.md +0 -86
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
# Skill installer for a standalone Open Mercato app (Claude Code + Codex).
|
|
5
|
+
# Two sources are mixed in:
|
|
6
|
+
#
|
|
7
|
+
# 1. Local tiered skills: reads .ai/skills/tiers.json and creates per-skill
|
|
8
|
+
# symlinks under .claude/skills/ and .codex/skills/. If a legacy
|
|
9
|
+
# directory-level symlink (e.g. .claude/skills -> ../.ai/skills) is found,
|
|
10
|
+
# it is replaced with a real directory of per-skill symlinks.
|
|
11
|
+
# 2. External shared skills: installs the subset this app ships from the
|
|
12
|
+
# open-mercato/skills collection via `npx skills add` into .agents/skills/
|
|
13
|
+
# (read natively by Codex; the CLI also symlinks .claude/skills/<name>),
|
|
14
|
+
# then `npx skills update` so a re-run refreshes them to the latest
|
|
15
|
+
# published versions. The external source + explicit skill list live under
|
|
16
|
+
# `external` in tiers.json. A folder under .ai/skills/ matching an external
|
|
17
|
+
# skill name is a repo-local override the external skill reads in place; it
|
|
18
|
+
# is never symlinked into the harness directories.
|
|
19
|
+
#
|
|
20
|
+
# The scaffold is offline: `npx skills add`/`update` only run when you invoke
|
|
21
|
+
# this script (yarn install-skills). Pass --no-external (or set
|
|
22
|
+
# OM_SKIP_EXTERNAL_SKILLS=1) to skip the network step entirely.
|
|
23
|
+
#
|
|
24
|
+
# Usage:
|
|
25
|
+
# install-skills.sh # default tier set (core) + install/update external skills
|
|
26
|
+
# install-skills.sh --with <csv> # default + extra tiers (additive)
|
|
27
|
+
# install-skills.sh --tiers <csv> # exactly the listed tiers (replaces default)
|
|
28
|
+
# install-skills.sh --all # every tier
|
|
29
|
+
# install-skills.sh --no-external # skip the npx external-skills install/update step (offline)
|
|
30
|
+
# install-skills.sh --list # print tier table and exit
|
|
31
|
+
# install-skills.sh --clean # remove all skill symlinks and exit
|
|
32
|
+
# install-skills.sh --help | -h # show usage and exit
|
|
33
|
+
|
|
34
|
+
usage() {
|
|
35
|
+
cat <<'EOF'
|
|
36
|
+
Usage: install-skills.sh [options]
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
(no options) Install the default tier set from .ai/skills/tiers.json
|
|
40
|
+
plus the external open-mercato/skills subset this app ships.
|
|
41
|
+
--with <csv> Install default tiers plus the given tier names (additive).
|
|
42
|
+
--tiers <csv> Install exactly the given tier names (replaces default).
|
|
43
|
+
--all Install every tier defined in tiers.json.
|
|
44
|
+
--no-external Skip the external-collection step — `npx skills add` on
|
|
45
|
+
first run and `npx skills update` on re-runs (also:
|
|
46
|
+
OM_SKIP_EXTERNAL_SKILLS=1). Use when offline.
|
|
47
|
+
--list Print the tier table and exit without installing.
|
|
48
|
+
--clean Remove all skill symlinks (local and external) and exit.
|
|
49
|
+
--help, -h Show this message.
|
|
50
|
+
|
|
51
|
+
--with, --tiers, and --all are mutually exclusive.
|
|
52
|
+
EOF
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
56
|
+
echo "install-skills: jq is required but not installed." >&2
|
|
57
|
+
echo "Install jq (e.g. 'sudo apt-get install jq' or 'brew install jq') and re-run." >&2
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Resolve the app root from this script's own location (scripts/install-skills.sh),
|
|
62
|
+
# falling back to git and finally the current directory. A freshly scaffolded app
|
|
63
|
+
# may not be a git checkout yet, so git is optional here.
|
|
64
|
+
script_path="$0"
|
|
65
|
+
case "${script_path}" in
|
|
66
|
+
/*) : ;;
|
|
67
|
+
*) script_path="$(pwd)/${script_path}" ;;
|
|
68
|
+
esac
|
|
69
|
+
script_dir=$(CDPATH= cd -- "$(dirname -- "${script_path}")" && pwd)
|
|
70
|
+
repo_root=$(CDPATH= cd -- "${script_dir}/.." && pwd)
|
|
71
|
+
if [ ! -f "${repo_root}/.ai/skills/tiers.json" ]; then
|
|
72
|
+
git_root=$(git rev-parse --show-toplevel 2>/dev/null || true)
|
|
73
|
+
if [ -n "${git_root}" ] && [ -f "${git_root}/.ai/skills/tiers.json" ]; then
|
|
74
|
+
repo_root="${git_root}"
|
|
75
|
+
elif [ -f "$(pwd)/.ai/skills/tiers.json" ]; then
|
|
76
|
+
repo_root="$(pwd)"
|
|
77
|
+
fi
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
manifest="${repo_root}/.ai/skills/tiers.json"
|
|
81
|
+
skills_dir="${repo_root}/.ai/skills"
|
|
82
|
+
|
|
83
|
+
if [ ! -f "${manifest}" ]; then
|
|
84
|
+
echo "install-skills: missing manifest ${manifest}" >&2
|
|
85
|
+
echo " Run this from your app root (yarn install-skills)." >&2
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
mode=""
|
|
90
|
+
with_csv=""
|
|
91
|
+
tiers_csv=""
|
|
92
|
+
list_only=0
|
|
93
|
+
clean_only=0
|
|
94
|
+
# Any non-empty value other than "0" skips the external npx step.
|
|
95
|
+
case "${OM_SKIP_EXTERNAL_SKILLS:-0}" in
|
|
96
|
+
""|0) no_external=0 ;;
|
|
97
|
+
*) no_external=1 ;;
|
|
98
|
+
esac
|
|
99
|
+
|
|
100
|
+
set_mode() {
|
|
101
|
+
new_mode="$1"
|
|
102
|
+
if [ -n "${mode}" ] && [ "${mode}" != "${new_mode}" ]; then
|
|
103
|
+
echo "install-skills: --with, --tiers, and --all are mutually exclusive." >&2
|
|
104
|
+
usage >&2
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
mode="${new_mode}"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
while [ $# -gt 0 ]; do
|
|
111
|
+
case "$1" in
|
|
112
|
+
--help|-h)
|
|
113
|
+
usage
|
|
114
|
+
exit 0
|
|
115
|
+
;;
|
|
116
|
+
--list)
|
|
117
|
+
list_only=1
|
|
118
|
+
shift
|
|
119
|
+
;;
|
|
120
|
+
--clean)
|
|
121
|
+
clean_only=1
|
|
122
|
+
shift
|
|
123
|
+
;;
|
|
124
|
+
--no-external)
|
|
125
|
+
no_external=1
|
|
126
|
+
shift
|
|
127
|
+
;;
|
|
128
|
+
--all)
|
|
129
|
+
set_mode all
|
|
130
|
+
shift
|
|
131
|
+
;;
|
|
132
|
+
--with)
|
|
133
|
+
set_mode with
|
|
134
|
+
if [ $# -lt 2 ]; then
|
|
135
|
+
echo "install-skills: --with requires a comma-separated list of tier names." >&2
|
|
136
|
+
exit 1
|
|
137
|
+
fi
|
|
138
|
+
with_csv="$2"
|
|
139
|
+
shift 2
|
|
140
|
+
;;
|
|
141
|
+
--with=*)
|
|
142
|
+
set_mode with
|
|
143
|
+
with_csv="${1#--with=}"
|
|
144
|
+
shift
|
|
145
|
+
;;
|
|
146
|
+
--tiers)
|
|
147
|
+
set_mode tiers
|
|
148
|
+
if [ $# -lt 2 ]; then
|
|
149
|
+
echo "install-skills: --tiers requires a comma-separated list of tier names." >&2
|
|
150
|
+
exit 1
|
|
151
|
+
fi
|
|
152
|
+
tiers_csv="$2"
|
|
153
|
+
shift 2
|
|
154
|
+
;;
|
|
155
|
+
--tiers=*)
|
|
156
|
+
set_mode tiers
|
|
157
|
+
tiers_csv="${1#--tiers=}"
|
|
158
|
+
shift
|
|
159
|
+
;;
|
|
160
|
+
*)
|
|
161
|
+
echo "install-skills: unknown option '$1'" >&2
|
|
162
|
+
usage >&2
|
|
163
|
+
exit 1
|
|
164
|
+
;;
|
|
165
|
+
esac
|
|
166
|
+
done
|
|
167
|
+
|
|
168
|
+
split_csv() {
|
|
169
|
+
printf '%s' "$1" | tr ',' '\n' | sed 's/^ *//; s/ *$//' | grep -v '^$' || true
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
all_tier_names=$(jq -r '.tiers | keys[]' "${manifest}")
|
|
173
|
+
default_tier_names=$(jq -r '.default[]' "${manifest}")
|
|
174
|
+
|
|
175
|
+
tier_defined() {
|
|
176
|
+
needle="$1"
|
|
177
|
+
for candidate in ${all_tier_names}; do
|
|
178
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
179
|
+
return 0
|
|
180
|
+
fi
|
|
181
|
+
done
|
|
182
|
+
return 1
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
tier_skills() {
|
|
186
|
+
jq -r --arg t "$1" '.tiers[$t].skills[]' "${manifest}"
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
tier_skill_count() {
|
|
190
|
+
jq -r --arg t "$1" '.tiers[$t].skills | length' "${manifest}"
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
is_default_tier() {
|
|
194
|
+
needle="$1"
|
|
195
|
+
for candidate in ${default_tier_names}; do
|
|
196
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
197
|
+
return 0
|
|
198
|
+
fi
|
|
199
|
+
done
|
|
200
|
+
return 1
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
dedup_lines() {
|
|
204
|
+
awk 'NF && !seen[$0]++'
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
agents_dir="${repo_root}/.agents/skills"
|
|
208
|
+
|
|
209
|
+
resolves_into_skills_dir() {
|
|
210
|
+
link_path="$1"
|
|
211
|
+
resolved=$(readlink -f -- "${link_path}" 2>/dev/null || true)
|
|
212
|
+
if [ -z "${resolved}" ]; then
|
|
213
|
+
return 1
|
|
214
|
+
fi
|
|
215
|
+
case "${resolved}" in
|
|
216
|
+
"${skills_dir}"/*)
|
|
217
|
+
return 0
|
|
218
|
+
;;
|
|
219
|
+
esac
|
|
220
|
+
return 1
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
resolves_into_agents_dir() {
|
|
224
|
+
link_path="$1"
|
|
225
|
+
resolved=$(readlink -f -- "${link_path}" 2>/dev/null || true)
|
|
226
|
+
if [ -z "${resolved}" ]; then
|
|
227
|
+
return 1
|
|
228
|
+
fi
|
|
229
|
+
case "${resolved}" in
|
|
230
|
+
"${agents_dir}"/*)
|
|
231
|
+
return 0
|
|
232
|
+
;;
|
|
233
|
+
esac
|
|
234
|
+
return 1
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
clean_harness() {
|
|
238
|
+
harness_dir="$1"
|
|
239
|
+
if [ ! -d "${harness_dir}" ] && [ ! -L "${harness_dir}" ]; then
|
|
240
|
+
return 0
|
|
241
|
+
fi
|
|
242
|
+
if [ -L "${harness_dir}" ]; then
|
|
243
|
+
rm -f "${harness_dir}"
|
|
244
|
+
return 0
|
|
245
|
+
fi
|
|
246
|
+
for entry in "${harness_dir}"/* "${harness_dir}"/.[!.]* "${harness_dir}"/..?*; do
|
|
247
|
+
[ -e "${entry}" ] || [ -L "${entry}" ] || continue
|
|
248
|
+
if [ -L "${entry}" ] && { resolves_into_skills_dir "${entry}" || resolves_into_agents_dir "${entry}"; }; then
|
|
249
|
+
rm -f "${entry}"
|
|
250
|
+
fi
|
|
251
|
+
done
|
|
252
|
+
if [ -d "${harness_dir}" ]; then
|
|
253
|
+
rmdir "${harness_dir}" 2>/dev/null || true
|
|
254
|
+
fi
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
# Replace any legacy directory-level symlink (.claude/skills -> ../.ai/skills)
|
|
258
|
+
# with a real directory holding per-skill symlinks.
|
|
259
|
+
prepare_harness_dir() {
|
|
260
|
+
harness_dir="$1"
|
|
261
|
+
parent_dir=$(dirname "${harness_dir}")
|
|
262
|
+
mkdir -p "${parent_dir}"
|
|
263
|
+
if [ -L "${harness_dir}" ]; then
|
|
264
|
+
rm -f "${harness_dir}"
|
|
265
|
+
fi
|
|
266
|
+
if [ ! -d "${harness_dir}" ]; then
|
|
267
|
+
mkdir -p "${harness_dir}"
|
|
268
|
+
fi
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
sweep_harness() {
|
|
272
|
+
harness_dir="$1"
|
|
273
|
+
selected_list="$2"
|
|
274
|
+
[ -d "${harness_dir}" ] || return 0
|
|
275
|
+
for entry in "${harness_dir}"/*; do
|
|
276
|
+
[ -L "${entry}" ] || continue
|
|
277
|
+
base=$(basename "${entry}")
|
|
278
|
+
keep=0
|
|
279
|
+
for skill in ${selected_list}; do
|
|
280
|
+
if [ "${skill}" = "${base}" ]; then
|
|
281
|
+
keep=1
|
|
282
|
+
break
|
|
283
|
+
fi
|
|
284
|
+
done
|
|
285
|
+
if [ "${keep}" -eq 0 ] && resolves_into_skills_dir "${entry}"; then
|
|
286
|
+
rm -f "${entry}"
|
|
287
|
+
fi
|
|
288
|
+
done
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
print_list() {
|
|
292
|
+
for tier in ${all_tier_names}; do
|
|
293
|
+
count=$(tier_skill_count "${tier}")
|
|
294
|
+
if is_default_tier "${tier}"; then
|
|
295
|
+
label="default"
|
|
296
|
+
else
|
|
297
|
+
label="opt-in"
|
|
298
|
+
fi
|
|
299
|
+
printf '%-12s (%s skills, %s):\n' "${tier}" "${count}" "${label}"
|
|
300
|
+
skills=$(tier_skills "${tier}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
|
|
301
|
+
printf ' %s\n' "${skills}"
|
|
302
|
+
done
|
|
303
|
+
|
|
304
|
+
external_source=$(jq -r '.external.source // empty' "${manifest}")
|
|
305
|
+
if [ -n "${external_source}" ]; then
|
|
306
|
+
printf '\n'
|
|
307
|
+
printf 'external (from %s):\n' "${external_source}"
|
|
308
|
+
ext=$(jq -r '.external.skills[]?' "${manifest}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
|
|
309
|
+
printf ' %s\n' "${ext}"
|
|
310
|
+
fi
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if [ "${list_only}" -eq 1 ]; then
|
|
314
|
+
print_list
|
|
315
|
+
exit 0
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
if [ "${clean_only}" -eq 1 ]; then
|
|
319
|
+
clean_harness "${repo_root}/.claude/skills"
|
|
320
|
+
clean_harness "${repo_root}/.codex/skills"
|
|
321
|
+
if [ -d "${agents_dir}" ]; then
|
|
322
|
+
rm -rf "${agents_dir}"
|
|
323
|
+
echo "info: removed external skill copies under .agents/skills/."
|
|
324
|
+
fi
|
|
325
|
+
echo "info: removed all skill symlinks under .claude/skills/ and .codex/skills/."
|
|
326
|
+
exit 0
|
|
327
|
+
fi
|
|
328
|
+
|
|
329
|
+
selected_tiers=""
|
|
330
|
+
|
|
331
|
+
case "${mode}" in
|
|
332
|
+
""|"with")
|
|
333
|
+
for tier in ${default_tier_names}; do
|
|
334
|
+
selected_tiers="${selected_tiers}
|
|
335
|
+
${tier}"
|
|
336
|
+
done
|
|
337
|
+
if [ "${mode}" = "with" ]; then
|
|
338
|
+
extra_tiers=$(split_csv "${with_csv}")
|
|
339
|
+
if [ -z "${extra_tiers}" ]; then
|
|
340
|
+
echo "install-skills: --with requires at least one tier name." >&2
|
|
341
|
+
exit 1
|
|
342
|
+
fi
|
|
343
|
+
for tier in ${extra_tiers}; do
|
|
344
|
+
if ! tier_defined "${tier}"; then
|
|
345
|
+
echo "install-skills: unknown tier '${tier}'." >&2
|
|
346
|
+
echo " Valid tiers: $(printf '%s\n' ${all_tier_names} | tr '\n' ' ' | sed 's/ $//')" >&2
|
|
347
|
+
exit 1
|
|
348
|
+
fi
|
|
349
|
+
selected_tiers="${selected_tiers}
|
|
350
|
+
${tier}"
|
|
351
|
+
done
|
|
352
|
+
fi
|
|
353
|
+
;;
|
|
354
|
+
"tiers")
|
|
355
|
+
requested_tiers=$(split_csv "${tiers_csv}")
|
|
356
|
+
if [ -z "${requested_tiers}" ]; then
|
|
357
|
+
echo "install-skills: --tiers requires at least one tier name." >&2
|
|
358
|
+
exit 1
|
|
359
|
+
fi
|
|
360
|
+
for tier in ${requested_tiers}; do
|
|
361
|
+
if ! tier_defined "${tier}"; then
|
|
362
|
+
echo "install-skills: unknown tier '${tier}'." >&2
|
|
363
|
+
echo " Valid tiers: $(printf '%s\n' ${all_tier_names} | tr '\n' ' ' | sed 's/ $//')" >&2
|
|
364
|
+
exit 1
|
|
365
|
+
fi
|
|
366
|
+
selected_tiers="${selected_tiers}
|
|
367
|
+
${tier}"
|
|
368
|
+
done
|
|
369
|
+
;;
|
|
370
|
+
"all")
|
|
371
|
+
for tier in ${all_tier_names}; do
|
|
372
|
+
selected_tiers="${selected_tiers}
|
|
373
|
+
${tier}"
|
|
374
|
+
done
|
|
375
|
+
;;
|
|
376
|
+
esac
|
|
377
|
+
|
|
378
|
+
selected_tiers=$(printf '%s\n' "${selected_tiers}" | dedup_lines)
|
|
379
|
+
|
|
380
|
+
selected_skills=""
|
|
381
|
+
for tier in ${selected_tiers}; do
|
|
382
|
+
for skill in $(tier_skills "${tier}"); do
|
|
383
|
+
selected_skills="${selected_skills}
|
|
384
|
+
${skill}"
|
|
385
|
+
done
|
|
386
|
+
done
|
|
387
|
+
selected_skills=$(printf '%s\n' "${selected_skills}" | dedup_lines)
|
|
388
|
+
|
|
389
|
+
if [ -z "${selected_skills}" ]; then
|
|
390
|
+
echo "install-skills: no skills selected for installation." >&2
|
|
391
|
+
exit 1
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
external_skills_list=$(jq -r '.external.skills[]?' "${manifest}")
|
|
395
|
+
|
|
396
|
+
is_external_skill() {
|
|
397
|
+
needle="$1"
|
|
398
|
+
for candidate in ${external_skills_list}; do
|
|
399
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
400
|
+
return 0
|
|
401
|
+
fi
|
|
402
|
+
done
|
|
403
|
+
return 1
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
install_into_harness() {
|
|
407
|
+
harness_dir="$1"
|
|
408
|
+
prepare_harness_dir "${harness_dir}"
|
|
409
|
+
for skill in ${selected_skills}; do
|
|
410
|
+
if is_external_skill "${skill}"; then
|
|
411
|
+
# Owned by the external collection; a same-named .ai/skills/ folder is a
|
|
412
|
+
# repo-local override and must not shadow the npx-installed skill.
|
|
413
|
+
echo "install-skills: warning: '${skill}' is an external skill; skipping local symlink." >&2
|
|
414
|
+
continue
|
|
415
|
+
fi
|
|
416
|
+
skill_target="${skills_dir}/${skill}"
|
|
417
|
+
if [ ! -d "${skill_target}" ]; then
|
|
418
|
+
echo "install-skills: skill folder '${skill_target}' is missing on disk." >&2
|
|
419
|
+
exit 1
|
|
420
|
+
fi
|
|
421
|
+
link_path="${harness_dir}/${skill}"
|
|
422
|
+
ln -sfn "../../.ai/skills/${skill}" "${link_path}"
|
|
423
|
+
done
|
|
424
|
+
sweep_harness "${harness_dir}" "${selected_skills}"
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
install_into_harness "${repo_root}/.claude/skills"
|
|
428
|
+
install_into_harness "${repo_root}/.codex/skills"
|
|
429
|
+
|
|
430
|
+
# Mix in the external shared collection (open-mercato/skills). Only the explicit
|
|
431
|
+
# subset this app ships (external.skills) is installed — never the whole
|
|
432
|
+
# collection. The npx CLI copies each skill into .agents/skills/ and symlinks
|
|
433
|
+
# .claude/skills/<name> because that directory exists.
|
|
434
|
+
external_source=$(jq -r '.external.source // empty' "${manifest}")
|
|
435
|
+
external_status="none"
|
|
436
|
+
# The skills CLI matches each --skill value against skill names verbatim (no
|
|
437
|
+
# comma splitting), so the subset must be passed as repeated --skill flags.
|
|
438
|
+
external_skill_args=""
|
|
439
|
+
for external_skill in $(printf '%s\n' "${external_skills_list}" | dedup_lines); do
|
|
440
|
+
external_skill_args="${external_skill_args} --skill ${external_skill}"
|
|
441
|
+
done
|
|
442
|
+
if [ -n "${external_source}" ] && [ -n "${external_skill_args}" ]; then
|
|
443
|
+
if [ "${no_external}" = "1" ]; then
|
|
444
|
+
external_status="skipped (--no-external)"
|
|
445
|
+
elif ! command -v npx >/dev/null 2>&1; then
|
|
446
|
+
external_status="skipped (npx not found)"
|
|
447
|
+
echo "install-skills: warning: npx not found; skipping external skills from ${external_source}." >&2
|
|
448
|
+
elif (cd "${repo_root}" && npx -y skills add "${external_source}" ${external_skill_args} --agent claude-code --agent codex -y); then
|
|
449
|
+
external_status="installed from ${external_source}"
|
|
450
|
+
# `add` seeds the subset; a follow-up `update` bumps already-installed skills
|
|
451
|
+
# to the latest published versions on a re-run. Non-fatal when offline mid-run.
|
|
452
|
+
if (cd "${repo_root}" && npx -y skills update --project -y); then
|
|
453
|
+
external_status="updated to latest from ${external_source}"
|
|
454
|
+
else
|
|
455
|
+
echo "install-skills: warning: could not update external skills to latest;" >&2
|
|
456
|
+
echo " the installed versions are kept. Re-run when online to refresh." >&2
|
|
457
|
+
fi
|
|
458
|
+
# The npx CLI symlinks .claude/skills/<name> itself and expects Codex to read
|
|
459
|
+
# .agents/skills/ natively; mirror the symlinks into .codex/skills/ too.
|
|
460
|
+
if [ -d "${agents_dir}" ]; then
|
|
461
|
+
mkdir -p "${repo_root}/.codex/skills"
|
|
462
|
+
for external_entry in "${agents_dir}"/*; do
|
|
463
|
+
[ -d "${external_entry}" ] || continue
|
|
464
|
+
ln -sfn "../../.agents/skills/$(basename "${external_entry}")" "${repo_root}/.codex/skills/$(basename "${external_entry}")"
|
|
465
|
+
done
|
|
466
|
+
fi
|
|
467
|
+
else
|
|
468
|
+
external_status="FAILED"
|
|
469
|
+
echo "install-skills: warning: installing external skills from ${external_source} failed;" >&2
|
|
470
|
+
echo " local tier skills are installed. Re-run when online, or pass --no-external to silence this." >&2
|
|
471
|
+
fi
|
|
472
|
+
fi
|
|
473
|
+
|
|
474
|
+
skill_count=$(printf '%s\n' "${selected_skills}" | grep -c '.' || true)
|
|
475
|
+
tier_count=$(printf '%s\n' "${selected_tiers}" | grep -c '.' || true)
|
|
476
|
+
tier_summary=$(printf '%s\n' "${selected_tiers}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
|
|
477
|
+
|
|
478
|
+
printf 'Installed %s local skills across %s tiers: %s.\n' "${skill_count}" "${tier_count}" "${tier_summary}"
|
|
479
|
+
if [ "${external_status}" != "none" ]; then
|
|
480
|
+
printf 'External skills: %s.\n' "${external_status}"
|
|
481
|
+
fi
|
|
482
|
+
|
|
483
|
+
if [ -z "${mode}" ]; then
|
|
484
|
+
cat <<'EOF'
|
|
485
|
+
Tip: opt into more skills with `yarn install-skills --with automation` or `--all`.
|
|
486
|
+
See `yarn install-skills --list` for the full catalog.
|
|
487
|
+
EOF
|
|
488
|
+
fi
|
|
@@ -104,22 +104,11 @@ function generateShared(config) {
|
|
|
104
104
|
writeTemplate(srcDir, "ai/specs/README.md", join(targetDir, ".ai", "specs", "README.md"), config);
|
|
105
105
|
copyFile(srcDir, "ai/specs/SPEC-000-template.md", join(targetDir, ".ai", "specs", "SPEC-000-template.md"));
|
|
106
106
|
copyFile(srcDir, "ai/lessons.md", join(targetDir, ".ai", "lessons.md"));
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
);
|
|
113
|
-
copyFile(
|
|
114
|
-
srcDir,
|
|
115
|
-
"ai/skills/om-spec-writing/references/spec-template.md",
|
|
116
|
-
join(targetDir, ".ai", "skills", "om-spec-writing", "references", "spec-template.md")
|
|
117
|
-
);
|
|
118
|
-
copyFile(
|
|
119
|
-
srcDir,
|
|
120
|
-
"ai/skills/om-spec-writing/references/spec-checklist.md",
|
|
121
|
-
join(targetDir, ".ai", "skills", "om-spec-writing", "references", "spec-checklist.md")
|
|
122
|
-
);
|
|
107
|
+
copyFile(srcDir, "ai/skills/tiers.json", join(targetDir, ".ai", "skills", "tiers.json"));
|
|
108
|
+
copyFile(srcDir, "ai/skills/tiers.schema.json", join(targetDir, ".ai", "skills", "tiers.schema.json"));
|
|
109
|
+
copyFile(srcDir, "ai/agentic.config.json", join(targetDir, ".ai", "agentic.config.json"));
|
|
110
|
+
copyFile(srcDir, "ai/trackers/github.md", join(targetDir, ".ai", "trackers", "github.md"));
|
|
111
|
+
copyFile(srcDir, "scripts/install-skills.sh", join(targetDir, "scripts", "install-skills.sh"));
|
|
123
112
|
copyFile(
|
|
124
113
|
srcDir,
|
|
125
114
|
"ai/skills/om-backend-ui-design/SKILL.md",
|
|
@@ -130,16 +119,6 @@ function generateShared(config) {
|
|
|
130
119
|
"ai/skills/om-backend-ui-design/references/ui-components.md",
|
|
131
120
|
join(targetDir, ".ai", "skills", "om-backend-ui-design", "references", "ui-components.md")
|
|
132
121
|
);
|
|
133
|
-
copyFile(
|
|
134
|
-
srcDir,
|
|
135
|
-
"ai/skills/om-code-review/SKILL.md",
|
|
136
|
-
join(targetDir, ".ai", "skills", "om-code-review", "SKILL.md")
|
|
137
|
-
);
|
|
138
|
-
copyFile(
|
|
139
|
-
srcDir,
|
|
140
|
-
"ai/skills/om-code-review/references/review-checklist.md",
|
|
141
|
-
join(targetDir, ".ai", "skills", "om-code-review", "references", "review-checklist.md")
|
|
142
|
-
);
|
|
143
122
|
copyFile(srcDir, "ai/skills/om-integration-builder/SKILL.md", join(targetDir, ".ai", "skills", "om-integration-builder", "SKILL.md"));
|
|
144
123
|
if (existsSync(join(srcDir, "ai", "skills", "om-integration-builder", "STANDALONE.md"))) {
|
|
145
124
|
copyFile(
|
|
@@ -215,11 +194,6 @@ function generateShared(config) {
|
|
|
215
194
|
"ai/skills/om-implement-spec/SKILL.md",
|
|
216
195
|
join(targetDir, ".ai", "skills", "om-implement-spec", "SKILL.md")
|
|
217
196
|
);
|
|
218
|
-
copyFile(
|
|
219
|
-
srcDir,
|
|
220
|
-
"ai/skills/om-integration-tests/SKILL.md",
|
|
221
|
-
join(targetDir, ".ai", "skills", "om-integration-tests", "SKILL.md")
|
|
222
|
-
);
|
|
223
197
|
copyFile(
|
|
224
198
|
srcDir,
|
|
225
199
|
"ai/skills/om-help/SKILL.md",
|
|
@@ -246,21 +220,16 @@ function generateShared(config) {
|
|
|
246
220
|
"om-auto-create-pr-loop",
|
|
247
221
|
"om-auto-continue-pr-loop",
|
|
248
222
|
"om-auto-review-pr",
|
|
249
|
-
"om-auto-fix-
|
|
250
|
-
"om-prepare-issue"
|
|
223
|
+
"om-auto-fix-issue"
|
|
251
224
|
]) {
|
|
225
|
+
if (!existsSync(join(srcDir, "ai", "skills", autoSkill, "SKILL.md"))) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
252
228
|
copyFile(
|
|
253
229
|
srcDir,
|
|
254
230
|
`ai/skills/${autoSkill}/SKILL.md`,
|
|
255
231
|
join(targetDir, ".ai", "skills", autoSkill, "SKILL.md")
|
|
256
232
|
);
|
|
257
|
-
if (existsSync(join(srcDir, "ai", "skills", autoSkill, "STANDALONE.md"))) {
|
|
258
|
-
copyFile(
|
|
259
|
-
srcDir,
|
|
260
|
-
`ai/skills/${autoSkill}/STANDALONE.md`,
|
|
261
|
-
join(targetDir, ".ai", "skills", autoSkill, "STANDALONE.md")
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
233
|
}
|
|
265
234
|
copyFile(
|
|
266
235
|
srcDir,
|