@smartsoft001-mobilems/claude-plugins 2.85.0 → 2.86.0
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/marketplace.json +2 -6
- package/package.json +2 -2
- package/plugins/mobilems/.claude-plugin/README.md +30 -0
- package/plugins/mobilems/.claude-plugin/plugin.json +5 -0
- package/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh +372 -0
- package/plugins/mobilems/skills/mobilems-docs-reader/SKILL.md +116 -0
- package/plugins/flow/.claude-plugin/README.md +0 -91
- package/plugins/flow/.claude-plugin/merge-permissions.js +0 -97
- package/plugins/flow/.claude-plugin/plugin.json +0 -5
- package/plugins/flow/.claude-plugin/settings.template.json +0 -86
- package/plugins/flow/agents/angular-component-scaffolder.md +0 -175
- package/plugins/flow/agents/angular-directive-builder.md +0 -153
- package/plugins/flow/agents/angular-guard-builder.md +0 -243
- package/plugins/flow/agents/angular-jest-test-writer.md +0 -474
- package/plugins/flow/agents/angular-pipe-builder.md +0 -169
- package/plugins/flow/agents/angular-resolver-builder.md +0 -286
- package/plugins/flow/agents/angular-service-builder.md +0 -161
- package/plugins/flow/agents/angular-signal-state-builder.md +0 -339
- package/plugins/flow/agents/angular-test-diagnostician.md +0 -279
- package/plugins/flow/agents/angular-testbed-configurator.md +0 -315
- package/plugins/flow/agents/arch-scaffolder.md +0 -278
- package/plugins/flow/agents/e2e-data-testid-injector.md +0 -197
- package/plugins/flow/agents/e2e-project-scaffolder.md +0 -194
- package/plugins/flow/agents/e2e-test-writer.md +0 -350
- package/plugins/flow/agents/shared-agent-evolver.md +0 -294
- package/plugins/flow/agents/shared-build-verifier.md +0 -160
- package/plugins/flow/agents/shared-config-updater.md +0 -310
- package/plugins/flow/agents/shared-coverage-enforcer.md +0 -184
- package/plugins/flow/agents/shared-error-handler.md +0 -217
- package/plugins/flow/agents/shared-file-creator.md +0 -344
- package/plugins/flow/agents/shared-impl-orchestrator.md +0 -312
- package/plugins/flow/agents/shared-impl-reporter.md +0 -368
- package/plugins/flow/agents/shared-impl-teammate.md +0 -201
- package/plugins/flow/agents/shared-linear-subtask-iterator.md +0 -337
- package/plugins/flow/agents/shared-logic-implementer.md +0 -243
- package/plugins/flow/agents/shared-maia-api.md +0 -26
- package/plugins/flow/agents/shared-parallelization-analyzer.md +0 -343
- package/plugins/flow/agents/shared-performance-validator.md +0 -168
- package/plugins/flow/agents/shared-plan-perspective.md +0 -269
- package/plugins/flow/agents/shared-project-standardizer.md +0 -205
- package/plugins/flow/agents/shared-report-synthesizer.md +0 -188
- package/plugins/flow/agents/shared-review-teammate.md +0 -189
- package/plugins/flow/agents/shared-security-scanner.md +0 -186
- package/plugins/flow/agents/shared-style-enforcer.md +0 -230
- package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +0 -188
- package/plugins/flow/agents/shared-tdd-developer.md +0 -350
- package/plugins/flow/agents/shared-team-coordinator.md +0 -189
- package/plugins/flow/agents/shared-test-fixer.md +0 -186
- package/plugins/flow/agents/shared-test-runner.md +0 -191
- package/plugins/flow/agents/shared-ui-classifier.md +0 -263
- package/plugins/flow/agents/shared-verification-orchestrator.md +0 -194
- package/plugins/flow/agents/shared-verification-runner.md +0 -140
- package/plugins/flow/agents/ui-a11y-validator.md +0 -305
- package/plugins/flow/agents/ui-screenshot-reporter.md +0 -329
- package/plugins/flow/agents/ui-web-designer.md +0 -214
- package/plugins/flow/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow/skills/a11y-audit/SKILL.md +0 -214
- package/plugins/flow/skills/angular-patterns/SKILL.md +0 -191
- package/plugins/flow/skills/browser-capture/SKILL.md +0 -238
- package/plugins/flow/skills/commit/SKILL.md +0 -259
- package/plugins/flow/skills/debug-helper/SKILL.md +0 -375
- package/plugins/flow/skills/impl/SKILL.md +0 -992
- package/plugins/flow/skills/linear-suggestion/SKILL.md +0 -132
- package/plugins/flow/skills/maia-files-delete/SKILL.md +0 -59
- package/plugins/flow/skills/maia-files-upload/SKILL.md +0 -57
- package/plugins/flow/skills/nx-conventions/SKILL.md +0 -326
- package/plugins/flow/skills/plan/SKILL.md +0 -1033
- package/plugins/flow/skills/push/SKILL.md +0 -759
- package/plugins/flow/skills/review/SKILL.md +0 -443
- package/plugins/flow/skills/test-e2e/SKILL.md +0 -161
- package/plugins/flow/skills/test-unit/SKILL.md +0 -456
- package/plugins/flow-external/.claude-plugin/README.md +0 -152
- package/plugins/flow-external/.claude-plugin/merge-permissions.js +0 -80
- package/plugins/flow-external/.claude-plugin/plugin.json +0 -5
- package/plugins/flow-external/.claude-plugin/settings.template.json +0 -78
- package/plugins/flow-external/agents/angular-component-scaffolder.md +0 -269
- package/plugins/flow-external/agents/angular-directive-builder.md +0 -130
- package/plugins/flow-external/agents/angular-guard-builder.md +0 -70
- package/plugins/flow-external/agents/angular-pipe-builder.md +0 -82
- package/plugins/flow-external/agents/angular-resolver-builder.md +0 -74
- package/plugins/flow-external/agents/angular-service-builder.md +0 -160
- package/plugins/flow-external/agents/angular-state-builder.md +0 -254
- package/plugins/flow-external/agents/shared-build-verifier.md +0 -67
- package/plugins/flow-external/agents/shared-impl-orchestrator.md +0 -88
- package/plugins/flow-external/agents/shared-impl-reporter.md +0 -135
- package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +0 -70
- package/plugins/flow-external/agents/shared-ui-classifier.md +0 -38
- package/plugins/flow-external/agents/ui-web-designer.md +0 -179
- package/plugins/flow-external/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow-external/skills/a11y-audit/SKILL.md +0 -96
- package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +0 -267
- package/plugins/flow-external/skills/angular-patterns/SKILL.md +0 -170
- package/plugins/flow-external/skills/browser-capture/SKILL.md +0 -68
- package/plugins/flow-external/skills/commit/SKILL.md +0 -114
- package/plugins/flow-external/skills/debug-helper/SKILL.md +0 -131
- package/plugins/flow-external/skills/impl/SKILL.md +0 -217
- package/plugins/flow-external/skills/linear-suggestion/SKILL.md +0 -62
- package/plugins/flow-external/skills/maia-files-delete/SKILL.md +0 -34
- package/plugins/flow-external/skills/maia-files-upload/SKILL.md +0 -41
- package/plugins/flow-external/skills/plan/SKILL.md +0 -334
- package/plugins/flow-external/skills/push/SKILL.md +0 -232
- package/plugins/flow-legacy/.claude-plugin/README.md +0 -143
- package/plugins/flow-legacy/.claude-plugin/merge-permissions.js +0 -94
- package/plugins/flow-legacy/.claude-plugin/plugin.json +0 -5
- package/plugins/flow-legacy/.claude-plugin/settings.template.json +0 -79
- package/plugins/flow-legacy/agents/angular-component-scaffolder.md +0 -323
- package/plugins/flow-legacy/agents/angular-directive-builder.md +0 -258
- package/plugins/flow-legacy/agents/angular-guard-builder.md +0 -322
- package/plugins/flow-legacy/agents/angular-pipe-builder.md +0 -227
- package/plugins/flow-legacy/agents/angular-resolver-builder.md +0 -332
- package/plugins/flow-legacy/agents/angular-service-builder.md +0 -271
- package/plugins/flow-legacy/agents/angular-state-builder.md +0 -479
- package/plugins/flow-legacy/agents/shared-impl-orchestrator.md +0 -174
- package/plugins/flow-legacy/agents/shared-impl-reporter.md +0 -232
- package/plugins/flow-legacy/agents/shared-linear-subtask-iterator.md +0 -187
- package/plugins/flow-legacy/agents/shared-tdd-developer.md +0 -306
- package/plugins/flow-legacy/agents/shared-test-runner.md +0 -131
- package/plugins/flow-legacy/agents/shared-ui-classifier.md +0 -145
- package/plugins/flow-legacy/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow-legacy/skills/a11y-audit/SKILL.md +0 -214
- package/plugins/flow-legacy/skills/angular-patterns/SKILL.md +0 -346
- package/plugins/flow-legacy/skills/browser-capture/SKILL.md +0 -238
- package/plugins/flow-legacy/skills/commit/SKILL.md +0 -215
- package/plugins/flow-legacy/skills/debug-helper/SKILL.md +0 -395
- package/plugins/flow-legacy/skills/impl/SKILL.md +0 -710
- package/plugins/flow-legacy/skills/linear-suggestion/SKILL.md +0 -132
- package/plugins/flow-legacy/skills/maia-files-delete/SKILL.md +0 -59
- package/plugins/flow-legacy/skills/maia-files-upload/SKILL.md +0 -57
- package/plugins/flow-legacy/skills/nx-conventions/SKILL.md +0 -368
- package/plugins/flow-legacy/skills/plan/SKILL.md +0 -742
- package/plugins/flow-legacy/skills/push/SKILL.md +0 -645
- package/plugins/flow-legacy/skills/test-unit/SKILL.md +0 -500
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartsoft001-mobilems/claude-plugins",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.86.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"scripts": {
|
|
8
|
-
"postinstall": "claude plugin update
|
|
8
|
+
"postinstall": "claude plugin update mobilems@mobilems --scope project || true"
|
|
9
9
|
},
|
|
10
10
|
"types": "./src/index.d.ts",
|
|
11
11
|
"main": "./src/index.js",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Mobilems Plugin for Claude Code
|
|
2
|
+
|
|
3
|
+
MobileMS-specific skills for the MuzaCMS / MobileMS indexer API. This plugin is a thin complement to the generic `flow@smart-pro` workflow plugins — it provides skills that are tied to the MobileMS backend.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
| Type | Name | Purpose |
|
|
8
|
+
|------|------|---------|
|
|
9
|
+
| Skill | `mobilems-docs-reader` | Answer questions about the MuzaCMS / MobileMS indexer OpenAPI spec; fetches a fresh copy via the bundled refresh script |
|
|
10
|
+
|
|
11
|
+
The skill ships with `scripts/refresh-mobilems-api-spec.sh`, which logs into `https://develop-indexer.mobilems.pl` using `MOBILEMS_LOGIN` / `MOBILEMS_PASSWORD` (read from env or `.env`) and writes the spec to `shared-assets/mobilems-api.json` inside the installed package. The script caches the fetched spec per Claude Code session (8h TTL).
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Enable in the consumer project's `.claude/settings.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"enabledPlugins": {
|
|
20
|
+
"mobilems@mobilems": true
|
|
21
|
+
},
|
|
22
|
+
"permissions": {
|
|
23
|
+
"allow": [
|
|
24
|
+
"Bash(bash ./node_modules/@smartsoft001-mobilems/claude-plugins/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh:*)"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Generic workflow skills (`/commit`, `/impl`, `/plan`, `/push`, etc.) come from `flow@smart-pro` — see `@smartsoft001/pro-claude-plugins`. Maia API skills (`maia-files-upload`, `maia-files-delete`, `shared-maia-api`) are not MobilEMS-specific and live in `flow@smart-pro`.
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Refresh the MuzaCMS / MobileMS indexer OpenAPI spec.
|
|
3
|
+
#
|
|
4
|
+
# Logs in to https://develop-indexer.mobilems.pl via Symfony form-login,
|
|
5
|
+
# scrapes the Swagger 2.0 JSON from /docs/api, and writes it next to this
|
|
6
|
+
# skill's owning package under shared-assets/mobilems-api.json.
|
|
7
|
+
#
|
|
8
|
+
# Required tools: bash, curl, jq.
|
|
9
|
+
# Required env vars (read from shell or auto-loaded from $PWD/.env):
|
|
10
|
+
# MOBILEMS_LOGIN — MuzaCMS username
|
|
11
|
+
# MOBILEMS_PASSWORD — MuzaCMS password
|
|
12
|
+
#
|
|
13
|
+
# Cache: a sibling mobilems-api.meta.json stores { sessionId, fetchedAt }.
|
|
14
|
+
# The script skips the network call when the same Claude Code session
|
|
15
|
+
# (CLAUDE_CODE_SESSION_ID) already fetched the spec less than 8h ago.
|
|
16
|
+
|
|
17
|
+
set -u
|
|
18
|
+
|
|
19
|
+
BASE='https://develop-indexer.mobilems.pl'
|
|
20
|
+
LOGIN_URL="${BASE}/admin/login"
|
|
21
|
+
DOCS_URL="${BASE}/docs/api"
|
|
22
|
+
|
|
23
|
+
QUIET=0
|
|
24
|
+
for arg in "$@"; do
|
|
25
|
+
case "$arg" in
|
|
26
|
+
--quiet) QUIET=1 ;;
|
|
27
|
+
esac
|
|
28
|
+
done
|
|
29
|
+
if [[ "${CLAUDE_AGENT_INVOCATION:-0}" == "1" ]]; then
|
|
30
|
+
QUIET=1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
log() {
|
|
34
|
+
if [[ "$QUIET" -eq 0 ]]; then
|
|
35
|
+
printf '%s\n' "$*"
|
|
36
|
+
fi
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
err() {
|
|
40
|
+
printf '%s\n' "$*" >&2
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
die() {
|
|
44
|
+
err "$*"
|
|
45
|
+
exit 1
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# --- dependency check --------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
check_deps() {
|
|
51
|
+
local missing=()
|
|
52
|
+
command -v curl >/dev/null 2>&1 || missing+=("curl")
|
|
53
|
+
command -v jq >/dev/null 2>&1 || missing+=("jq")
|
|
54
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
55
|
+
err "✗ Brak wymaganych narzędzi: ${missing[*]}"
|
|
56
|
+
err ""
|
|
57
|
+
err "Zainstaluj:"
|
|
58
|
+
err " macOS: brew install ${missing[*]}"
|
|
59
|
+
err " Debian/Ubuntu: sudo apt install ${missing[*]}"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# --- .env loader -------------------------------------------------------------
|
|
65
|
+
# Minimal KEY=value parser. Ignores blank lines and #-comments, strips matching
|
|
66
|
+
# surrounding quotes, and never overrides already-set env vars (parity with the
|
|
67
|
+
# old refresh-mobilems-api-spec.js loader).
|
|
68
|
+
|
|
69
|
+
load_dotenv() {
|
|
70
|
+
local env_path="${PWD}/.env"
|
|
71
|
+
[[ -f "$env_path" ]] || return 0
|
|
72
|
+
local line key value first last
|
|
73
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
74
|
+
# trim leading/trailing whitespace
|
|
75
|
+
line="${line#"${line%%[![:space:]]*}"}"
|
|
76
|
+
line="${line%"${line##*[![:space:]]}"}"
|
|
77
|
+
[[ -z "$line" ]] && continue
|
|
78
|
+
[[ "${line:0:1}" == "#" ]] && continue
|
|
79
|
+
[[ "$line" != *"="* ]] && continue
|
|
80
|
+
key="${line%%=*}"
|
|
81
|
+
value="${line#*=}"
|
|
82
|
+
# trim whitespace around key/value
|
|
83
|
+
key="${key#"${key%%[![:space:]]*}"}"
|
|
84
|
+
key="${key%"${key##*[![:space:]]}"}"
|
|
85
|
+
value="${value#"${value%%[![:space:]]*}"}"
|
|
86
|
+
value="${value%"${value##*[![:space:]]}"}"
|
|
87
|
+
[[ -z "$key" ]] && continue
|
|
88
|
+
# strip matching surrounding quotes (single or double)
|
|
89
|
+
first="${value:0:1}"
|
|
90
|
+
last="${value: -1}"
|
|
91
|
+
if [[ ${#value} -ge 2 ]] && { [[ "$first" == '"' && "$last" == '"' ]] || [[ "$first" == "'" && "$last" == "'" ]]; }; then
|
|
92
|
+
value="${value:1:${#value}-2}"
|
|
93
|
+
fi
|
|
94
|
+
# only set if not already in env
|
|
95
|
+
if [[ -z "${!key+x}" ]]; then
|
|
96
|
+
export "$key=$value"
|
|
97
|
+
fi
|
|
98
|
+
done < "$env_path"
|
|
99
|
+
log "→ loaded .env from $env_path"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# --- env-var validation (per Linear FRA-95 — Emil's request) ----------------
|
|
103
|
+
# This runs as the very first step after .env loading. We MUST NOT attempt any
|
|
104
|
+
# HTTP call until both credentials are present.
|
|
105
|
+
|
|
106
|
+
validate_env_vars() {
|
|
107
|
+
if [[ -z "${MOBILEMS_LOGIN:-}" || -z "${MOBILEMS_PASSWORD:-}" ]]; then
|
|
108
|
+
err "✗ Brak wymaganych zmiennych środowiskowych dla MuzaCMS API:"
|
|
109
|
+
err " MOBILEMS_LOGIN, MOBILEMS_PASSWORD"
|
|
110
|
+
err ""
|
|
111
|
+
err "Ustaw je w shellu:"
|
|
112
|
+
err " export MOBILEMS_LOGIN=..."
|
|
113
|
+
err " export MOBILEMS_PASSWORD=..."
|
|
114
|
+
err ""
|
|
115
|
+
err "Lub w pliku .env w katalogu głównym projektu:"
|
|
116
|
+
err " MOBILEMS_LOGIN=..."
|
|
117
|
+
err " MOBILEMS_PASSWORD=..."
|
|
118
|
+
err ""
|
|
119
|
+
err "Szczegóły: @smartsoft001-mobilems/claude-plugins README.md"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# --- output dir resolution ---------------------------------------------------
|
|
125
|
+
# Mirrors resolveOutDir() in the old JS. Looks for shared-assets/ walking up
|
|
126
|
+
# from this script's directory.
|
|
127
|
+
|
|
128
|
+
resolve_out_dir() {
|
|
129
|
+
local script_dir
|
|
130
|
+
script_dir="$(cd "$(dirname "$0")" && pwd)"
|
|
131
|
+
# Installed layout (per-variant copy made by nx build):
|
|
132
|
+
# <pkg-root>/plugins/<variant>/scripts/refresh-mobilems-api-spec.sh
|
|
133
|
+
# <pkg-root>/shared-assets/mobilems-api.json
|
|
134
|
+
# Source layout:
|
|
135
|
+
# packages/shared/claude-plugins/scripts/refresh-mobilems-api-spec.sh
|
|
136
|
+
# packages/shared/claude-plugins/src/shared-assets/
|
|
137
|
+
local candidates=(
|
|
138
|
+
"$script_dir/../../../shared-assets"
|
|
139
|
+
"$script_dir/../shared-assets"
|
|
140
|
+
"$script_dir/../src/shared-assets"
|
|
141
|
+
)
|
|
142
|
+
local c
|
|
143
|
+
for c in "${candidates[@]}"; do
|
|
144
|
+
if [[ -d "$c" ]]; then
|
|
145
|
+
(cd "$c" && pwd)
|
|
146
|
+
return 0
|
|
147
|
+
fi
|
|
148
|
+
done
|
|
149
|
+
# No existing dir — pick the first candidate whose parent exists so we can
|
|
150
|
+
# mkdir into it.
|
|
151
|
+
for c in "${candidates[@]}"; do
|
|
152
|
+
if [[ -d "$(dirname "$c")" ]]; then
|
|
153
|
+
mkdir -p "$c"
|
|
154
|
+
(cd "$c" && pwd)
|
|
155
|
+
return 0
|
|
156
|
+
fi
|
|
157
|
+
done
|
|
158
|
+
# Last resort: create alongside the script.
|
|
159
|
+
mkdir -p "$script_dir/shared-assets"
|
|
160
|
+
(cd "$script_dir/shared-assets" && pwd)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# --- cache decision ----------------------------------------------------------
|
|
164
|
+
# Mirrors cacheDecision() in the old JS.
|
|
165
|
+
|
|
166
|
+
MAX_CACHE_AGE_S=$((8 * 60 * 60))
|
|
167
|
+
|
|
168
|
+
iso_to_epoch() {
|
|
169
|
+
# macOS BSD date and GNU date diverge — try both forms.
|
|
170
|
+
local iso="$1"
|
|
171
|
+
if date -j -f "%Y-%m-%dT%H:%M:%SZ" "${iso%%.*}Z" "+%s" >/dev/null 2>&1; then
|
|
172
|
+
date -j -f "%Y-%m-%dT%H:%M:%SZ" "${iso%%.*}Z" "+%s"
|
|
173
|
+
elif date -d "$iso" "+%s" >/dev/null 2>&1; then
|
|
174
|
+
date -d "$iso" "+%s"
|
|
175
|
+
else
|
|
176
|
+
echo "0"
|
|
177
|
+
fi
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
cache_decision() {
|
|
181
|
+
# Echoes either "fetch:<reason>" or "skip:<age_seconds>".
|
|
182
|
+
local session_id="$1"
|
|
183
|
+
if [[ -z "$session_id" ]]; then
|
|
184
|
+
echo "fetch:manual/terminal invocation"
|
|
185
|
+
return
|
|
186
|
+
fi
|
|
187
|
+
if [[ ! -f "$SPEC_PATH" ]]; then
|
|
188
|
+
echo "fetch:spec file missing"
|
|
189
|
+
return
|
|
190
|
+
fi
|
|
191
|
+
if [[ ! -f "$META_PATH" ]]; then
|
|
192
|
+
echo "fetch:meta file missing"
|
|
193
|
+
return
|
|
194
|
+
fi
|
|
195
|
+
local meta_session meta_fetched_at meta_epoch now age
|
|
196
|
+
meta_session="$(jq -r '.sessionId // ""' "$META_PATH" 2>/dev/null)"
|
|
197
|
+
meta_fetched_at="$(jq -r '.fetchedAt // ""' "$META_PATH" 2>/dev/null)"
|
|
198
|
+
if [[ "$meta_session" != "$session_id" ]]; then
|
|
199
|
+
echo "fetch:new Claude Code session"
|
|
200
|
+
return
|
|
201
|
+
fi
|
|
202
|
+
if [[ -z "$meta_fetched_at" ]]; then
|
|
203
|
+
echo "fetch:meta missing fetchedAt"
|
|
204
|
+
return
|
|
205
|
+
fi
|
|
206
|
+
meta_epoch="$(iso_to_epoch "$meta_fetched_at")"
|
|
207
|
+
now="$(date +%s)"
|
|
208
|
+
age=$((now - meta_epoch))
|
|
209
|
+
if [[ "$meta_epoch" -le 0 || "$age" -gt "$MAX_CACHE_AGE_S" ]]; then
|
|
210
|
+
echo "fetch:cache older than 8 hours"
|
|
211
|
+
return
|
|
212
|
+
fi
|
|
213
|
+
echo "skip:$age"
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# --- HTML extraction helpers -------------------------------------------------
|
|
217
|
+
|
|
218
|
+
extract_csrf() {
|
|
219
|
+
# Mirrors extractCsrf() in the old JS.
|
|
220
|
+
local html="$1"
|
|
221
|
+
local token
|
|
222
|
+
token="$(printf '%s' "$html" | grep -oE 'name="_csrf_token"[[:space:]]+value="[^"]+"' | head -n 1 | sed -E 's/.*value="([^"]+)".*/\1/')"
|
|
223
|
+
if [[ -z "$token" ]]; then
|
|
224
|
+
die "✗ Could not find _csrf_token in login form HTML."
|
|
225
|
+
fi
|
|
226
|
+
printf '%s' "$token"
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
extract_swagger_data() {
|
|
230
|
+
# Mirrors extractSwaggerData() in the old JS.
|
|
231
|
+
# The <script id="swagger-data" type="application/json"> tag wraps a JSON blob.
|
|
232
|
+
local html="$1"
|
|
233
|
+
local json
|
|
234
|
+
# awk lets us span newlines safely, where sed's portability gets hairy.
|
|
235
|
+
json="$(printf '%s' "$html" | awk '
|
|
236
|
+
BEGIN { in_block = 0 }
|
|
237
|
+
{
|
|
238
|
+
line = $0
|
|
239
|
+
if (in_block == 0) {
|
|
240
|
+
idx = index(line, "<script id=\"swagger-data\" type=\"application/json\">")
|
|
241
|
+
if (idx > 0) {
|
|
242
|
+
in_block = 1
|
|
243
|
+
line = substr(line, idx + length("<script id=\"swagger-data\" type=\"application/json\">"))
|
|
244
|
+
} else {
|
|
245
|
+
next
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
end_idx = index(line, "</script>")
|
|
249
|
+
if (end_idx > 0) {
|
|
250
|
+
printf "%s", substr(line, 1, end_idx - 1)
|
|
251
|
+
exit
|
|
252
|
+
} else {
|
|
253
|
+
printf "%s\n", line
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
')"
|
|
257
|
+
# trim leading/trailing whitespace
|
|
258
|
+
json="${json#"${json%%[![:space:]]*}"}"
|
|
259
|
+
json="${json%"${json##*[![:space:]]}"}"
|
|
260
|
+
if [[ -z "$json" ]]; then
|
|
261
|
+
die "✗ Could not find <script id=\"swagger-data\"> tag in /docs/api response. Login may have silently failed, or the docs page structure changed."
|
|
262
|
+
fi
|
|
263
|
+
printf '%s' "$json"
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
# --- main --------------------------------------------------------------------
|
|
267
|
+
|
|
268
|
+
check_deps
|
|
269
|
+
load_dotenv
|
|
270
|
+
validate_env_vars
|
|
271
|
+
|
|
272
|
+
OUT_DIR="$(resolve_out_dir)"
|
|
273
|
+
SPEC_PATH="$OUT_DIR/mobilems-api.json"
|
|
274
|
+
META_PATH="$OUT_DIR/mobilems-api.meta.json"
|
|
275
|
+
|
|
276
|
+
SESSION_ID="${CLAUDE_CODE_SESSION_ID:-}"
|
|
277
|
+
DECISION="$(cache_decision "$SESSION_ID")"
|
|
278
|
+
|
|
279
|
+
if [[ "$DECISION" == skip:* ]]; then
|
|
280
|
+
age_s="${DECISION#skip:}"
|
|
281
|
+
age_min=$(( (age_s + 30) / 60 ))
|
|
282
|
+
fetched_at="$(jq -r '.fetchedAt // "unknown"' "$META_PATH" 2>/dev/null)"
|
|
283
|
+
log "✓ spec cached for this Claude Code session (refreshed ${age_min} min ago at ${fetched_at}), skipping fetch"
|
|
284
|
+
exit 0
|
|
285
|
+
fi
|
|
286
|
+
|
|
287
|
+
REASON="${DECISION#fetch:}"
|
|
288
|
+
log "Refreshing MuzaCMS API spec from $BASE ($REASON)"
|
|
289
|
+
|
|
290
|
+
JAR="$(mktemp -t mobilems-cookies.XXXXXX)"
|
|
291
|
+
trap 'rm -f "$JAR"' EXIT
|
|
292
|
+
|
|
293
|
+
log "→ GET /admin/login (CSRF + session)"
|
|
294
|
+
LOGIN_HTML="$(curl --silent --show-error \
|
|
295
|
+
--cookie-jar "$JAR" \
|
|
296
|
+
"$LOGIN_URL")" || die "✗ Could not fetch $LOGIN_URL"
|
|
297
|
+
|
|
298
|
+
CSRF="$(extract_csrf "$LOGIN_HTML")"
|
|
299
|
+
|
|
300
|
+
log "→ POST /admin/login"
|
|
301
|
+
# We need the HTTP status of the POST without following the redirect.
|
|
302
|
+
LOGIN_POST_STATUS_BODY="$(curl --silent --show-error \
|
|
303
|
+
--output /dev/null \
|
|
304
|
+
--write-out '%{http_code} %{redirect_url}' \
|
|
305
|
+
--cookie-jar "$JAR" --cookie "$JAR" \
|
|
306
|
+
--data-urlencode "_username=${MOBILEMS_LOGIN}" \
|
|
307
|
+
--data-urlencode "_password=${MOBILEMS_PASSWORD}" \
|
|
308
|
+
--data-urlencode "_csrf_token=${CSRF}" \
|
|
309
|
+
--data-urlencode "_remember_me=on" \
|
|
310
|
+
-X POST \
|
|
311
|
+
"$LOGIN_URL")" || die "✗ POST $LOGIN_URL failed."
|
|
312
|
+
|
|
313
|
+
LOGIN_STATUS="${LOGIN_POST_STATUS_BODY%% *}"
|
|
314
|
+
LOGIN_REDIRECT="${LOGIN_POST_STATUS_BODY#* }"
|
|
315
|
+
|
|
316
|
+
if [[ "$LOGIN_STATUS" != "302" ]]; then
|
|
317
|
+
die "✗ Login failed: expected 302 redirect, got HTTP ${LOGIN_STATUS}. Check MOBILEMS_LOGIN and MOBILEMS_PASSWORD."
|
|
318
|
+
fi
|
|
319
|
+
if [[ "$LOGIN_REDIRECT" == *"/admin/login"* ]]; then
|
|
320
|
+
die "✗ Login failed: server redirected back to /admin/login. Credentials were likely rejected."
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
log "→ GET /docs/api"
|
|
324
|
+
DOCS_STATUS_FILE="$(mktemp -t mobilems-docs-status.XXXXXX)"
|
|
325
|
+
trap 'rm -f "$JAR" "$DOCS_STATUS_FILE"' EXIT
|
|
326
|
+
|
|
327
|
+
DOCS_HTML="$(curl --silent --show-error \
|
|
328
|
+
--write-out '%{http_code}' \
|
|
329
|
+
--cookie-jar "$JAR" --cookie "$JAR" \
|
|
330
|
+
--output - \
|
|
331
|
+
"$DOCS_URL" 2>/dev/null | tee >(tail -c 3 > "$DOCS_STATUS_FILE"))"
|
|
332
|
+
|
|
333
|
+
# Strip the trailing 3-char status code from the body
|
|
334
|
+
DOCS_STATUS="$(cat "$DOCS_STATUS_FILE")"
|
|
335
|
+
DOCS_HTML="${DOCS_HTML%$DOCS_STATUS}"
|
|
336
|
+
|
|
337
|
+
if [[ "$DOCS_STATUS" != "200" ]]; then
|
|
338
|
+
die "✗ Docs page returned HTTP ${DOCS_STATUS}. Session may not be authenticated."
|
|
339
|
+
fi
|
|
340
|
+
if [[ "$DOCS_HTML" == *"login-card-body"* ]]; then
|
|
341
|
+
die "✗ Docs page returned the login form — session not authenticated."
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
SPEC_JSON="$(extract_swagger_data "$DOCS_HTML")"
|
|
345
|
+
|
|
346
|
+
# Validate + pretty-print through jq.
|
|
347
|
+
if ! printf '%s' "$SPEC_JSON" | jq '.' > "${SPEC_PATH}.tmp"; then
|
|
348
|
+
rm -f "${SPEC_PATH}.tmp"
|
|
349
|
+
die "✗ Swagger JSON failed to parse."
|
|
350
|
+
fi
|
|
351
|
+
mv -f "${SPEC_PATH}.tmp" "$SPEC_PATH"
|
|
352
|
+
|
|
353
|
+
SPEC_TITLE="$(jq -r '.spec.info.title // .info.title // "unknown"' "$SPEC_PATH")"
|
|
354
|
+
SPEC_VERSION="$(jq -r '.spec.info.version // .info.version // "unknown"' "$SPEC_PATH")"
|
|
355
|
+
|
|
356
|
+
# Preserve cached sessionId when running outside Claude Code (manual/terminal)
|
|
357
|
+
# so a future in-session call still hits the cache. In-Claude-Code calls always
|
|
358
|
+
# overwrite with the current session id.
|
|
359
|
+
EFFECTIVE_SESSION_ID="$SESSION_ID"
|
|
360
|
+
if [[ -z "$EFFECTIVE_SESSION_ID" && -f "$META_PATH" ]]; then
|
|
361
|
+
EFFECTIVE_SESSION_ID="$(jq -r '.sessionId // ""' "$META_PATH" 2>/dev/null)"
|
|
362
|
+
fi
|
|
363
|
+
ISO_NOW="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
364
|
+
jq -n \
|
|
365
|
+
--arg sid "$EFFECTIVE_SESSION_ID" \
|
|
366
|
+
--arg ts "$ISO_NOW" \
|
|
367
|
+
'{sessionId: (if $sid == "" then null else $sid end), fetchedAt: $ts}' \
|
|
368
|
+
> "$META_PATH"
|
|
369
|
+
|
|
370
|
+
BYTES="$(wc -c < "$SPEC_PATH" | tr -d ' ')"
|
|
371
|
+
log "✓ Refreshed ${BYTES} bytes — ${SPEC_TITLE} ${SPEC_VERSION}"
|
|
372
|
+
log " $SPEC_PATH"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobilems-docs-reader
|
|
3
|
+
description: Answer questions about the MuzaCMS / MobileMS indexer API by reading a freshly-fetched OpenAPI spec. Use whenever the user asks about endpoints, request/response shapes, status codes, auth, or behavior of the indexer API (host develop-indexer-api.mobilems.pl). Read-only — never fabricates endpoints.
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Glob
|
|
8
|
+
- Grep
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You answer questions about the **MuzaCMS / MobileMS indexer API** strictly from the OpenAPI (Swagger 2.0) specification. You never invent endpoints, schemas, or status codes — if it is not in the spec, you say so plainly.
|
|
12
|
+
|
|
13
|
+
The spec is **not bundled**. It is fetched from the live MuzaCMS instance by a refresh script that lives next to this skill, using credentials supplied via environment variables. The script caches the fetched spec per Claude Code session (with an 8-hour TTL safety net), so it may skip the actual network call and reuse a cached copy on follow-up invocations within the same session.
|
|
14
|
+
|
|
15
|
+
## Step 1 — Run the refresh script (mandatory)
|
|
16
|
+
|
|
17
|
+
On every invocation, run the refresh script via Bash. The script itself decides whether to actually fetch — it owns the cache. Your job is only to run it and react to the result. A successful run may be either:
|
|
18
|
+
|
|
19
|
+
- A real fetch (`Refreshing MuzaCMS API spec from ... → GET /admin/login → POST /admin/login → GET /docs/api → ✓ Refreshed N bytes ...`), or
|
|
20
|
+
- A cache hit (`✓ spec cached for this Claude Code session (refreshed N min ago at ...), skipping fetch`).
|
|
21
|
+
|
|
22
|
+
Both are exit-code-0 successes. Treat them identically and proceed to Step 2. **Do not** attempt to bypass the cache, delete the cache file, or force a refetch — the cache is intentional and the script's decision is authoritative.
|
|
23
|
+
|
|
24
|
+
### Invocation
|
|
25
|
+
|
|
26
|
+
The refresh script is shipped under `plugins/mobilems/scripts/`. Invoke it through `bash` so the executable bit is irrelevant:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
bash ./node_modules/@smartsoft001-mobilems/claude-plugins/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh --quiet
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Outcomes:
|
|
33
|
+
|
|
34
|
+
- **Success (exit 0)** → jump to Step 2.
|
|
35
|
+
- **Script-level error** (missing env vars, missing tooling, auth rejected, HTTP error, parse failure, etc.) → jump to the matching Fail mode below.
|
|
36
|
+
- **Permission denied by Claude Code** → jump to "Fail mode — permission denied".
|
|
37
|
+
|
|
38
|
+
The script reads two environment variables — `MOBILEMS_LOGIN` and `MOBILEMS_PASSWORD` — performs the Symfony CSRF + session login against `https://develop-indexer.mobilems.pl`, fetches `/docs/api`, and writes the spec to `shared-assets/mobilems-api.json` inside the installed package. It also auto-loads `.env` from the current working directory; no shell sourcing is needed.
|
|
39
|
+
|
|
40
|
+
### Fail mode — permission denied by Claude Code
|
|
41
|
+
|
|
42
|
+
If the Bash call is rejected by Claude Code's permission system, stop and tell the user verbatim:
|
|
43
|
+
|
|
44
|
+
> The MuzaCMS spec could not be refreshed because Claude Code denied permission to run the refresh script. To allow it, add this entry to your project's `.claude/settings.json` (committed) or `.claude/settings.local.json` (per-dev, gitignored) under `permissions.allow`, then ask again:
|
|
45
|
+
>
|
|
46
|
+
> - `"Bash(bash ./node_modules/@smartsoft001-mobilems/claude-plugins/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh:*)"`
|
|
47
|
+
|
|
48
|
+
Do not attempt to answer the user's question from training knowledge. Do not invent alternative invocation patterns to try to bypass the denial.
|
|
49
|
+
|
|
50
|
+
### Fail mode — missing env vars
|
|
51
|
+
|
|
52
|
+
If the script exits non-zero with a message starting `✗ Brak wymaganych zmiennych środowiskowych` (or English equivalent listing `MOBILEMS_LOGIN` / `MOBILEMS_PASSWORD`), **stop immediately**. Relay the script's message verbatim to the user.
|
|
53
|
+
|
|
54
|
+
Do not attempt to answer the user's question from training knowledge. Do not guess. Do not read any pre-existing `mobilems-api.json` that may be lying around in `node_modules/` — without a successful refresh you have no confirmation it is current.
|
|
55
|
+
|
|
56
|
+
### Fail mode — missing tooling
|
|
57
|
+
|
|
58
|
+
If the script exits with a message about missing `curl` or `jq`, relay it verbatim. The script tells the user exactly how to install the missing dependency (`brew install jq` / `apt install jq`).
|
|
59
|
+
|
|
60
|
+
### Fail mode — other script failures
|
|
61
|
+
|
|
62
|
+
If the script fails for any other reason (HTTP error, auth rejected, parse failure), report the exact error message from the script back to the user and stop. Do not answer the API question.
|
|
63
|
+
|
|
64
|
+
## Step 2 — Locate the freshly-written spec
|
|
65
|
+
|
|
66
|
+
Use `Glob` with this pattern:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
**/claude-plugins/**/shared-assets/mobilems-api.json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The hit lives under `node_modules/@smartsoft001-mobilems/claude-plugins/shared-assets/` after a successful refresh. Exclude `dist/` and `tmp/` from the Glob, but **do** allow `node_modules/`.
|
|
73
|
+
|
|
74
|
+
If the Glob returns nothing after the refresh script reported success, something is wrong with the install layout — tell the user and stop.
|
|
75
|
+
|
|
76
|
+
## Step 3 — Answer from the spec
|
|
77
|
+
|
|
78
|
+
The spec is **Swagger 2.0** with this wrapping shape:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
{ "spec": { "swagger": "2.0", "paths": {...}, "definitions": {...} } }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Always traverse into `.spec` first.
|
|
85
|
+
|
|
86
|
+
When the user asks about endpoints:
|
|
87
|
+
|
|
88
|
+
1. **Locate the path** in `spec.paths`. Look for the exact path the user mentioned, including any path parameters (`{id}`).
|
|
89
|
+
2. **Quote the HTTP method(s) and path verbatim.** Example: `GET /api/objects/{id}`.
|
|
90
|
+
3. For request bodies and responses, cite the `$ref` target by name and (briefly) summarize its shape from `spec.definitions`.
|
|
91
|
+
4. For status codes, list each documented response from `responses` with its `description`.
|
|
92
|
+
5. For auth, check both the operation-level `security` and the global `spec.securityDefinitions`.
|
|
93
|
+
|
|
94
|
+
If the user asks about a path that is **not in the spec**, say so explicitly:
|
|
95
|
+
|
|
96
|
+
> The spec does not document a `DELETE /api/articles/{id}` endpoint. The articles paths in the spec are: `[list actual paths]`. If you've seen this endpoint elsewhere, it may exist in the running service without being documented — verify with a live request.
|
|
97
|
+
|
|
98
|
+
## Known caveats — always surface when relevant
|
|
99
|
+
|
|
100
|
+
- **Response schemas occasionally diverge from runtime.** Documented response shapes have, in practice, not always matched what the live API actually returns. When the user is about to implement against a response schema, add a brief reminder to verify with a real request before relying on the documented shape.
|
|
101
|
+
- **Spec is regenerated server-side from PHP annotations.** Newly added endpoints in the live service may not appear until the next backend deployment, even with a fresh fetch.
|
|
102
|
+
- **Auth flow nuance:** the spec describes the indexer API itself; the `/admin/login` flow used by the refresh script is separate and not documented in the spec.
|
|
103
|
+
|
|
104
|
+
## Answering style
|
|
105
|
+
|
|
106
|
+
- Be terse. The user wants a specific fact, not a tutorial on Swagger.
|
|
107
|
+
- Always include exact path + method + relevant status codes when applicable.
|
|
108
|
+
- When quoting definitions, use the schema name (e.g., `Object`, `Unauthorised`) as it appears in `spec.definitions`.
|
|
109
|
+
- If multiple endpoints match a vague question, list them — don't pick one arbitrarily.
|
|
110
|
+
|
|
111
|
+
## When NOT to use this skill
|
|
112
|
+
|
|
113
|
+
- Non-MobileMS APIs (any other host).
|
|
114
|
+
- Generic REST/OpenAPI guidance unrelated to the indexer.
|
|
115
|
+
- Schema design decisions ("should I add X field?") — this skill only describes what exists.
|
|
116
|
+
- Anything requiring a live network call to the API itself.
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Flow Plugin for Claude Code
|
|
2
|
-
|
|
3
|
-
Development flow skills for Linear-driven development workflow.
|
|
4
|
-
|
|
5
|
-
## Workflow Skills
|
|
6
|
-
|
|
7
|
-
| Skill | Description |
|
|
8
|
-
|-------|-------------|
|
|
9
|
-
| `/commit` | Create conventional commit based on Linear task |
|
|
10
|
-
| `/impl` | Implement plans from `plan.md` attachment on Linear issue; orchestration saved as `orchestration.md` attachment |
|
|
11
|
-
| `/plan` | Create implementation plan, save as `plan.md` attachment on Linear issue, add `AI Plan` label |
|
|
12
|
-
| `/push` | Push changes and update Linear status (keeps `plan.md` / `orchestration.md` attachments on the issue) |
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
15
|
-
|
|
16
|
-
### 1. Enable plugin in project's `.claude/settings.json`:
|
|
17
|
-
|
|
18
|
-
```json
|
|
19
|
-
{
|
|
20
|
-
"enabledPlugins": {
|
|
21
|
-
"flow@mobilems": true
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### 2. Merge permissions from template
|
|
27
|
-
|
|
28
|
-
Copy permissions from `settings.template.json` to your project's `.claude/settings.json`.
|
|
29
|
-
|
|
30
|
-
**Quick merge script:**
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
# From project root
|
|
34
|
-
node -e "
|
|
35
|
-
const template = require('node_modules/@smartsoft001-mobilems/claude-plugins/plugins/flow/.claude-plugin/settings.template.json');
|
|
36
|
-
const settings = require('.claude/settings.json');
|
|
37
|
-
|
|
38
|
-
settings.permissions = settings.permissions || { allow: [], deny: [], ask: [] };
|
|
39
|
-
settings.permissions.allow = [...new Set([...settings.permissions.allow, ...template.permissions.allow])];
|
|
40
|
-
settings.permissions.ask = [...new Set([...settings.permissions.ask, ...template.permissions.ask])];
|
|
41
|
-
|
|
42
|
-
require('fs').writeFileSync('.claude/settings.json', JSON.stringify(settings, null, 2));
|
|
43
|
-
console.log('Permissions merged!');
|
|
44
|
-
"
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Required MCP Servers
|
|
48
|
-
|
|
49
|
-
Configure these in your `.mcp.json`:
|
|
50
|
-
|
|
51
|
-
- `linear` - Linear API integration (MCP prefix `mcp__linear__`)
|
|
52
|
-
- `playwright` - Browser automation for screenshots
|
|
53
|
-
|
|
54
|
-
### Linear MCP tool dependencies
|
|
55
|
-
|
|
56
|
-
`/plan`, `/impl`, and `/push` depend on the following `mcp__linear__*` tools (in addition to the standard comment/issue tools):
|
|
57
|
-
|
|
58
|
-
- `create_attachment` (base64 upload), `get_attachment`, `delete_attachment` — for persisting `plan.md` / `orchestration.md` on issues (attachments are also returned by `get_issue`)
|
|
59
|
-
- `list_issue_labels` — to find the workspace-level `AI Plan` label (the label is pre-configured organization-wide; `/plan` does not create it)
|
|
60
|
-
|
|
61
|
-
Run `/mcp` after authenticating the Linear MCP server to see the exact loaded tool names. If a tool is exposed under a different name in your deployment, update `settings.template.json` and the `allowed-tools` lists in the three skills accordingly.
|
|
62
|
-
|
|
63
|
-
## Permission Strategy
|
|
64
|
-
|
|
65
|
-
### Automatic (allow)
|
|
66
|
-
- Git read operations (status, diff, log, show)
|
|
67
|
-
- Nx commands (test, lint, build)
|
|
68
|
-
- Linear API (read/write issues, comments)
|
|
69
|
-
- Playwright (screenshots)
|
|
70
|
-
- Utility skills
|
|
71
|
-
|
|
72
|
-
### Requires Confirmation (ask)
|
|
73
|
-
- Workflow skills (/commit, /impl, /plan, /push)
|
|
74
|
-
- `git commit` - creating commits
|
|
75
|
-
- `git push` - pushing to remote
|
|
76
|
-
- `gh pr create` - creating pull requests
|
|
77
|
-
|
|
78
|
-
## Utility Skills
|
|
79
|
-
|
|
80
|
-
| Skill | Description |
|
|
81
|
-
|-------|-------------|
|
|
82
|
-
| `maia-files-upload` | Upload files to Maia API |
|
|
83
|
-
| `maia-files-delete` | Delete files from Maia API |
|
|
84
|
-
| `browser-capture` | Capture screenshots with Playwright |
|
|
85
|
-
| `linear-suggestion` | Create Linear issues for improvements |
|
|
86
|
-
| `test-unit` | Run unit tests with coverage |
|
|
87
|
-
| `a11y-audit` | Accessibility audit |
|
|
88
|
-
|
|
89
|
-
## Agents
|
|
90
|
-
|
|
91
|
-
See `agents/` directory for full list of specialized agents used by flow skills.
|