specrails 0.2.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/skills/openspec-apply-change/SKILL.md +156 -0
- package/.claude/skills/openspec-archive-change/SKILL.md +114 -0
- package/.claude/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.claude/skills/openspec-continue-change/SKILL.md +118 -0
- package/.claude/skills/openspec-explore/SKILL.md +290 -0
- package/.claude/skills/openspec-ff-change/SKILL.md +101 -0
- package/.claude/skills/openspec-new-change/SKILL.md +74 -0
- package/.claude/skills/openspec-onboard/SKILL.md +529 -0
- package/.claude/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.claude/skills/openspec-verify-change/SKILL.md +168 -0
- package/README.md +226 -0
- package/VERSION +1 -0
- package/bin/specrails.js +41 -0
- package/commands/setup.md +851 -0
- package/install.sh +488 -0
- package/package.json +34 -0
- package/prompts/analyze-codebase.md +87 -0
- package/prompts/generate-personas.md +61 -0
- package/prompts/infer-conventions.md +72 -0
- package/templates/agents/sr-architect.md +194 -0
- package/templates/agents/sr-backend-developer.md +54 -0
- package/templates/agents/sr-backend-reviewer.md +139 -0
- package/templates/agents/sr-developer.md +146 -0
- package/templates/agents/sr-doc-sync.md +167 -0
- package/templates/agents/sr-frontend-developer.md +48 -0
- package/templates/agents/sr-frontend-reviewer.md +132 -0
- package/templates/agents/sr-product-analyst.md +36 -0
- package/templates/agents/sr-product-manager.md +148 -0
- package/templates/agents/sr-reviewer.md +265 -0
- package/templates/agents/sr-security-reviewer.md +178 -0
- package/templates/agents/sr-test-writer.md +163 -0
- package/templates/claude-md/root.md +50 -0
- package/templates/commands/sr/batch-implement.md +282 -0
- package/templates/commands/sr/compat-check.md +271 -0
- package/templates/commands/sr/health-check.md +396 -0
- package/templates/commands/sr/implement.md +972 -0
- package/templates/commands/sr/product-backlog.md +195 -0
- package/templates/commands/sr/refactor-recommender.md +169 -0
- package/templates/commands/sr/update-product-driven-backlog.md +272 -0
- package/templates/commands/sr/why.md +96 -0
- package/templates/personas/persona.md +43 -0
- package/templates/personas/the-maintainer.md +78 -0
- package/templates/rules/layer.md +8 -0
- package/templates/security/security-exemptions.yaml +20 -0
- package/templates/settings/confidence-config.json +17 -0
- package/templates/settings/settings.json +15 -0
- package/templates/web-manager/README.md +107 -0
- package/templates/web-manager/client/index.html +12 -0
- package/templates/web-manager/client/package-lock.json +1727 -0
- package/templates/web-manager/client/package.json +20 -0
- package/templates/web-manager/client/src/App.tsx +83 -0
- package/templates/web-manager/client/src/components/AgentActivity.tsx +19 -0
- package/templates/web-manager/client/src/components/CommandInput.tsx +81 -0
- package/templates/web-manager/client/src/components/LogStream.tsx +57 -0
- package/templates/web-manager/client/src/components/PipelineSidebar.tsx +65 -0
- package/templates/web-manager/client/src/components/SearchBox.tsx +34 -0
- package/templates/web-manager/client/src/hooks/usePipeline.ts +62 -0
- package/templates/web-manager/client/src/hooks/useWebSocket.ts +59 -0
- package/templates/web-manager/client/src/main.tsx +9 -0
- package/templates/web-manager/client/tsconfig.json +21 -0
- package/templates/web-manager/client/tsconfig.node.json +11 -0
- package/templates/web-manager/client/vite.config.ts +13 -0
- package/templates/web-manager/package-lock.json +3327 -0
- package/templates/web-manager/package.json +30 -0
- package/templates/web-manager/server/hooks.test.ts +196 -0
- package/templates/web-manager/server/hooks.ts +71 -0
- package/templates/web-manager/server/index.test.ts +186 -0
- package/templates/web-manager/server/index.ts +99 -0
- package/templates/web-manager/server/spawner.test.ts +319 -0
- package/templates/web-manager/server/spawner.ts +89 -0
- package/templates/web-manager/server/types.ts +46 -0
- package/templates/web-manager/tsconfig.json +14 -0
- package/templates/web-manager/vitest.config.ts +8 -0
- package/update.sh +877 -0
package/install.sh
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# specrails installer
|
|
5
|
+
# Installs the agent workflow system into any repository.
|
|
6
|
+
# Step 1 of 2: Prerequisites + scaffold. Step 2: Run /setup inside Claude Code.
|
|
7
|
+
|
|
8
|
+
# Detect pipe mode (curl | bash) vs local execution
|
|
9
|
+
if [[ -z "${BASH_SOURCE[0]:-}" || "${BASH_SOURCE[0]:-}" == "bash" ]]; then
|
|
10
|
+
# Running via pipe — clone repo to temp dir
|
|
11
|
+
SPECRAILS_TMPDIR="$(mktemp -d)"
|
|
12
|
+
trap 'rm -rf "$SPECRAILS_TMPDIR"' EXIT
|
|
13
|
+
git clone --depth 1 https://github.com/fjpulidop/specrails.git "$SPECRAILS_TMPDIR/specrails" 2>/dev/null || {
|
|
14
|
+
echo "Error: failed to clone specrails repository." >&2
|
|
15
|
+
exit 1
|
|
16
|
+
}
|
|
17
|
+
SCRIPT_DIR="$SPECRAILS_TMPDIR/specrails"
|
|
18
|
+
else
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
|
+
fi
|
|
21
|
+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "")"
|
|
22
|
+
|
|
23
|
+
# Colors
|
|
24
|
+
RED='\033[0;31m'
|
|
25
|
+
GREEN='\033[0;32m'
|
|
26
|
+
YELLOW='\033[1;33m'
|
|
27
|
+
BLUE='\033[0;34m'
|
|
28
|
+
CYAN='\033[0;36m'
|
|
29
|
+
BOLD='\033[1m'
|
|
30
|
+
NC='\033[0m'
|
|
31
|
+
|
|
32
|
+
# ─────────────────────────────────────────────
|
|
33
|
+
# Argument parsing
|
|
34
|
+
# ─────────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
CUSTOM_ROOT_DIR=""
|
|
37
|
+
|
|
38
|
+
while [[ $# -gt 0 ]]; do
|
|
39
|
+
case "$1" in
|
|
40
|
+
--root-dir)
|
|
41
|
+
if [[ -z "${2:-}" ]]; then
|
|
42
|
+
echo "Error: --root-dir requires a path argument." >&2
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
CUSTOM_ROOT_DIR="$2"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
*)
|
|
49
|
+
echo "Unknown argument: $1" >&2
|
|
50
|
+
echo "Usage: install.sh [--root-dir <path>]" >&2
|
|
51
|
+
exit 1
|
|
52
|
+
;;
|
|
53
|
+
esac
|
|
54
|
+
done
|
|
55
|
+
|
|
56
|
+
# Override REPO_ROOT if --root-dir was provided
|
|
57
|
+
if [[ -n "$CUSTOM_ROOT_DIR" ]]; then
|
|
58
|
+
REPO_ROOT="$(cd "$CUSTOM_ROOT_DIR" 2>/dev/null && pwd)" || {
|
|
59
|
+
echo "Error: --root-dir path does not exist or is not accessible: $CUSTOM_ROOT_DIR" >&2
|
|
60
|
+
exit 1
|
|
61
|
+
}
|
|
62
|
+
if [[ ! -d "$REPO_ROOT" ]]; then
|
|
63
|
+
echo "Error: --root-dir path is not a directory: $CUSTOM_ROOT_DIR" >&2
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Detect if running from within the specrails source repo itself
|
|
69
|
+
if [[ -z "$CUSTOM_ROOT_DIR" && -f "$SCRIPT_DIR/install.sh" && -d "$SCRIPT_DIR/templates" && "$SCRIPT_DIR" == "$REPO_ROOT"* ]]; then
|
|
70
|
+
# We're inside the specrails source — ask for target repo
|
|
71
|
+
echo ""
|
|
72
|
+
echo -e "${YELLOW}⚠${NC} You're running the installer from inside the specrails source repo."
|
|
73
|
+
echo -e " specrails installs into a ${BOLD}target${NC} repository, not into itself."
|
|
74
|
+
echo ""
|
|
75
|
+
read -p " Enter the path to the target repo (or 'q' to quit): " TARGET_PATH
|
|
76
|
+
if [[ "$TARGET_PATH" == "q" || -z "$TARGET_PATH" ]]; then
|
|
77
|
+
echo " Aborted. No changes made."
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
# Expand ~ and resolve path
|
|
81
|
+
TARGET_PATH="${TARGET_PATH/#\~/$HOME}"
|
|
82
|
+
REPO_ROOT="$(cd "$TARGET_PATH" 2>/dev/null && pwd)" || {
|
|
83
|
+
echo "Error: path does not exist or is not accessible: $TARGET_PATH" >&2
|
|
84
|
+
exit 1
|
|
85
|
+
}
|
|
86
|
+
if [[ ! -d "$REPO_ROOT/.git" ]]; then
|
|
87
|
+
echo -e "${YELLOW}⚠${NC} Warning: $REPO_ROOT does not appear to be a git repository."
|
|
88
|
+
read -p " Continue anyway? (y/n): " CONTINUE_NOGIT
|
|
89
|
+
if [[ "$CONTINUE_NOGIT" != "y" && "$CONTINUE_NOGIT" != "Y" ]]; then
|
|
90
|
+
echo " Aborted. No changes made."
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
print_header() {
|
|
97
|
+
echo ""
|
|
98
|
+
echo -e "${BOLD}${CYAN}╔══════════════════════════════════════════════╗${NC}"
|
|
99
|
+
echo -e "${BOLD}${CYAN}║ specrails installer v0.1 ║${NC}"
|
|
100
|
+
echo -e "${BOLD}${CYAN}║ Agent Workflow System for Claude Code ║${NC}"
|
|
101
|
+
echo -e "${BOLD}${CYAN}╚══════════════════════════════════════════════╝${NC}"
|
|
102
|
+
echo ""
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
ok() { echo -e " ${GREEN}✓${NC} $1"; }
|
|
106
|
+
warn() { echo -e " ${YELLOW}⚠${NC} $1"; }
|
|
107
|
+
fail() { echo -e " ${RED}✗${NC} $1"; }
|
|
108
|
+
info() { echo -e " ${BLUE}→${NC} $1"; }
|
|
109
|
+
step() { echo -e "\n${BOLD}$1${NC}"; }
|
|
110
|
+
|
|
111
|
+
generate_manifest() {
|
|
112
|
+
local version
|
|
113
|
+
version="$(cat "$SCRIPT_DIR/VERSION")"
|
|
114
|
+
|
|
115
|
+
local installed_at
|
|
116
|
+
installed_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
117
|
+
|
|
118
|
+
# Write version file
|
|
119
|
+
printf '%s\n' "$version" > "$REPO_ROOT/.specrails-version"
|
|
120
|
+
|
|
121
|
+
# Build artifact checksums for all files under templates/
|
|
122
|
+
local artifacts_json=""
|
|
123
|
+
local first=true
|
|
124
|
+
while IFS= read -r -d '' filepath; do
|
|
125
|
+
local relpath
|
|
126
|
+
relpath="templates/${filepath#"$SCRIPT_DIR/templates/"}"
|
|
127
|
+
local checksum
|
|
128
|
+
checksum="sha256:$(shasum -a 256 "$filepath" | awk '{print $1}')"
|
|
129
|
+
if [ "$first" = true ]; then
|
|
130
|
+
first=false
|
|
131
|
+
else
|
|
132
|
+
artifacts_json="${artifacts_json},"
|
|
133
|
+
fi
|
|
134
|
+
artifacts_json="${artifacts_json}
|
|
135
|
+
\"${relpath}\": \"${checksum}\""
|
|
136
|
+
done < <(find "$SCRIPT_DIR/templates" -type f -not -path '*/node_modules/*' -not -name 'package-lock.json' -print0 | sort -z)
|
|
137
|
+
|
|
138
|
+
# Include commands/setup.md
|
|
139
|
+
local setup_checksum
|
|
140
|
+
setup_checksum="sha256:$(shasum -a 256 "$SCRIPT_DIR/commands/setup.md" | awk '{print $1}')"
|
|
141
|
+
if [ -n "$artifacts_json" ]; then
|
|
142
|
+
artifacts_json="${artifacts_json},"
|
|
143
|
+
fi
|
|
144
|
+
artifacts_json="${artifacts_json}
|
|
145
|
+
\"commands/setup.md\": \"${setup_checksum}\""
|
|
146
|
+
|
|
147
|
+
cat > "$REPO_ROOT/.specrails-manifest.json" << EOF
|
|
148
|
+
{
|
|
149
|
+
"version": "${version}",
|
|
150
|
+
"installed_at": "${installed_at}",
|
|
151
|
+
"artifacts": {${artifacts_json}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
EOF
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# ─────────────────────────────────────────────
|
|
158
|
+
# Phase 1: Prerequisites
|
|
159
|
+
# ─────────────────────────────────────────────
|
|
160
|
+
|
|
161
|
+
print_header
|
|
162
|
+
|
|
163
|
+
step "Phase 1: Checking prerequisites"
|
|
164
|
+
|
|
165
|
+
# 1.1 Git repository
|
|
166
|
+
if [[ -z "$REPO_ROOT" ]]; then
|
|
167
|
+
fail "Not inside a git repository and no --root-dir provided."
|
|
168
|
+
echo " Usage: install.sh [--root-dir <path>]"
|
|
169
|
+
exit 1
|
|
170
|
+
fi
|
|
171
|
+
if [[ -n "$CUSTOM_ROOT_DIR" ]]; then
|
|
172
|
+
ok "Install root (--root-dir): $REPO_ROOT"
|
|
173
|
+
else
|
|
174
|
+
ok "Git repository root: $REPO_ROOT"
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# 1.2 Claude Code CLI
|
|
178
|
+
if command -v claude &> /dev/null; then
|
|
179
|
+
CLAUDE_VERSION=$(claude --version 2>/dev/null || echo "unknown")
|
|
180
|
+
ok "Claude Code CLI: $CLAUDE_VERSION"
|
|
181
|
+
else
|
|
182
|
+
fail "Claude Code CLI not found."
|
|
183
|
+
echo ""
|
|
184
|
+
echo " Install it with: npm install -g @anthropic-ai/claude-code"
|
|
185
|
+
echo " Or see: https://docs.anthropic.com/en/docs/claude-code"
|
|
186
|
+
exit 1
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
# 1.3 npm
|
|
190
|
+
if command -v npm &> /dev/null; then
|
|
191
|
+
NPM_VERSION=$(npm --version 2>/dev/null)
|
|
192
|
+
ok "npm: v$NPM_VERSION"
|
|
193
|
+
HAS_NPM=true
|
|
194
|
+
else
|
|
195
|
+
warn "npm not found. Required for OpenSpec CLI."
|
|
196
|
+
echo ""
|
|
197
|
+
read -p " Install npm via nvm? (y/n): " INSTALL_NPM
|
|
198
|
+
if [ "$INSTALL_NPM" = "y" ] || [ "$INSTALL_NPM" = "Y" ]; then
|
|
199
|
+
info "Installing nvm + node..."
|
|
200
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
|
|
201
|
+
export NVM_DIR="$HOME/.nvm"
|
|
202
|
+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
|
203
|
+
nvm install --lts
|
|
204
|
+
nvm use --lts
|
|
205
|
+
ok "npm installed: v$(npm --version)"
|
|
206
|
+
HAS_NPM=true
|
|
207
|
+
else
|
|
208
|
+
warn "Skipping npm install. OpenSpec CLI will not be available."
|
|
209
|
+
HAS_NPM=false
|
|
210
|
+
fi
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# 1.4 OpenSpec CLI
|
|
214
|
+
if command -v openspec &> /dev/null; then
|
|
215
|
+
OPENSPEC_VERSION=$(openspec --version 2>/dev/null || echo "unknown")
|
|
216
|
+
ok "OpenSpec CLI: $OPENSPEC_VERSION"
|
|
217
|
+
HAS_OPENSPEC=true
|
|
218
|
+
elif [ -f "$REPO_ROOT/node_modules/.bin/openspec" ]; then
|
|
219
|
+
ok "OpenSpec CLI: found in node_modules"
|
|
220
|
+
HAS_OPENSPEC=true
|
|
221
|
+
else
|
|
222
|
+
warn "OpenSpec CLI not found."
|
|
223
|
+
if [ "$HAS_NPM" = true ]; then
|
|
224
|
+
read -p " Install OpenSpec CLI globally? (y/n): " INSTALL_OPENSPEC
|
|
225
|
+
if [ "$INSTALL_OPENSPEC" = "y" ] || [ "$INSTALL_OPENSPEC" = "Y" ]; then
|
|
226
|
+
info "Installing OpenSpec CLI..."
|
|
227
|
+
npm install -g @openspec/cli 2>/dev/null && {
|
|
228
|
+
ok "OpenSpec CLI installed"
|
|
229
|
+
HAS_OPENSPEC=true
|
|
230
|
+
} || {
|
|
231
|
+
warn "Global install failed. Trying local..."
|
|
232
|
+
cd "$REPO_ROOT" && npm install @openspec/cli 2>/dev/null && {
|
|
233
|
+
ok "OpenSpec CLI installed locally"
|
|
234
|
+
HAS_OPENSPEC=true
|
|
235
|
+
} || {
|
|
236
|
+
fail "Could not install OpenSpec CLI."
|
|
237
|
+
HAS_OPENSPEC=false
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else
|
|
241
|
+
warn "Skipping OpenSpec install. Spec-driven workflow will be limited."
|
|
242
|
+
HAS_OPENSPEC=false
|
|
243
|
+
fi
|
|
244
|
+
else
|
|
245
|
+
warn "Cannot install OpenSpec without npm."
|
|
246
|
+
HAS_OPENSPEC=false
|
|
247
|
+
fi
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
# 1.5 GitHub CLI (optional)
|
|
251
|
+
if command -v gh &> /dev/null; then
|
|
252
|
+
if gh auth status &> /dev/null; then
|
|
253
|
+
ok "GitHub CLI: authenticated"
|
|
254
|
+
HAS_GH=true
|
|
255
|
+
else
|
|
256
|
+
warn "GitHub CLI installed but not authenticated. Run: gh auth login"
|
|
257
|
+
HAS_GH=false
|
|
258
|
+
fi
|
|
259
|
+
else
|
|
260
|
+
warn "GitHub CLI (gh) not found. GitHub Issues backlog will be unavailable."
|
|
261
|
+
HAS_GH=false
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
# 1.6 OSS detection (requires gh auth; degrades gracefully)
|
|
265
|
+
IS_OSS=false
|
|
266
|
+
HAS_PUBLIC_REPO=false
|
|
267
|
+
HAS_CI=false
|
|
268
|
+
HAS_CONTRIBUTING=false
|
|
269
|
+
|
|
270
|
+
if [ "$HAS_GH" = true ]; then
|
|
271
|
+
_REPO_PRIVATE=$(gh repo view --json isPrivate --jq '.isPrivate' 2>/dev/null || echo "unknown")
|
|
272
|
+
if [ "$_REPO_PRIVATE" = "false" ]; then
|
|
273
|
+
HAS_PUBLIC_REPO=true
|
|
274
|
+
fi
|
|
275
|
+
if ls "$REPO_ROOT/.github/workflows/"*.yml > /dev/null 2>&1; then
|
|
276
|
+
HAS_CI=true
|
|
277
|
+
fi
|
|
278
|
+
if [ -f "$REPO_ROOT/CONTRIBUTING.md" ] || [ -f "$REPO_ROOT/.github/CONTRIBUTING.md" ]; then
|
|
279
|
+
HAS_CONTRIBUTING=true
|
|
280
|
+
fi
|
|
281
|
+
if [ "$HAS_PUBLIC_REPO" = true ] && [ "$HAS_CI" = true ] && [ "$HAS_CONTRIBUTING" = true ]; then
|
|
282
|
+
IS_OSS=true
|
|
283
|
+
ok "OSS project detected (public repo + CI + CONTRIBUTING.md)"
|
|
284
|
+
fi
|
|
285
|
+
fi
|
|
286
|
+
|
|
287
|
+
# 1.7 JIRA CLI (optional)
|
|
288
|
+
if command -v jira &> /dev/null; then
|
|
289
|
+
ok "JIRA CLI: found"
|
|
290
|
+
HAS_JIRA=true
|
|
291
|
+
else
|
|
292
|
+
HAS_JIRA=false
|
|
293
|
+
# Don't warn here — JIRA is only relevant if chosen during /setup.
|
|
294
|
+
# If the user selects JIRA in /setup and it's not installed, the setup
|
|
295
|
+
# wizard will offer to install it (go-jira via brew/go, or Atlassian CLI).
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
# ─────────────────────────────────────────────
|
|
299
|
+
# Phase 2: Detect existing setup
|
|
300
|
+
# ─────────────────────────────────────────────
|
|
301
|
+
|
|
302
|
+
step "Phase 2: Detecting existing setup"
|
|
303
|
+
|
|
304
|
+
EXISTING_SETUP=false
|
|
305
|
+
|
|
306
|
+
if [ -d "$REPO_ROOT/.claude" ]; then
|
|
307
|
+
if [ -d "$REPO_ROOT/.claude/agents" ] && [ "$(ls -A "$REPO_ROOT/.claude/agents" 2>/dev/null)" ]; then
|
|
308
|
+
warn "Existing .claude/agents/ found with content"
|
|
309
|
+
EXISTING_SETUP=true
|
|
310
|
+
fi
|
|
311
|
+
if [ -d "$REPO_ROOT/.claude/commands" ] && [ "$(ls -A "$REPO_ROOT/.claude/commands" 2>/dev/null)" ]; then
|
|
312
|
+
warn "Existing .claude/commands/ found with content"
|
|
313
|
+
EXISTING_SETUP=true
|
|
314
|
+
fi
|
|
315
|
+
if [ -d "$REPO_ROOT/.claude/rules" ] && [ "$(ls -A "$REPO_ROOT/.claude/rules" 2>/dev/null)" ]; then
|
|
316
|
+
warn "Existing .claude/rules/ found with content"
|
|
317
|
+
EXISTING_SETUP=true
|
|
318
|
+
fi
|
|
319
|
+
fi
|
|
320
|
+
|
|
321
|
+
if [ -d "$REPO_ROOT/openspec" ]; then
|
|
322
|
+
warn "Existing openspec/ directory found"
|
|
323
|
+
EXISTING_SETUP=true
|
|
324
|
+
fi
|
|
325
|
+
|
|
326
|
+
if [ "$EXISTING_SETUP" = true ]; then
|
|
327
|
+
echo ""
|
|
328
|
+
warn "This repo already has some agent/command/openspec artifacts."
|
|
329
|
+
read -p " Continue and merge with existing setup? (y/n): " CONTINUE
|
|
330
|
+
if [ "$CONTINUE" != "y" ] && [ "$CONTINUE" != "Y" ]; then
|
|
331
|
+
info "Aborted. No changes made."
|
|
332
|
+
exit 0
|
|
333
|
+
fi
|
|
334
|
+
else
|
|
335
|
+
ok "Clean repo — no existing .claude/ or openspec/ artifacts"
|
|
336
|
+
fi
|
|
337
|
+
|
|
338
|
+
# ─────────────────────────────────────────────
|
|
339
|
+
# Phase 3: Install artifacts
|
|
340
|
+
# ─────────────────────────────────────────────
|
|
341
|
+
|
|
342
|
+
step "Phase 3: Installing specrails artifacts"
|
|
343
|
+
|
|
344
|
+
# Create directory structure
|
|
345
|
+
mkdir -p "$REPO_ROOT/.claude/commands"
|
|
346
|
+
mkdir -p "$REPO_ROOT/.claude/setup-templates/agents"
|
|
347
|
+
mkdir -p "$REPO_ROOT/.claude/setup-templates/commands"
|
|
348
|
+
mkdir -p "$REPO_ROOT/.claude/setup-templates/rules"
|
|
349
|
+
mkdir -p "$REPO_ROOT/.claude/setup-templates/personas"
|
|
350
|
+
mkdir -p "$REPO_ROOT/.claude/setup-templates/claude-md"
|
|
351
|
+
mkdir -p "$REPO_ROOT/.claude/setup-templates/settings"
|
|
352
|
+
mkdir -p "$REPO_ROOT/.claude/setup-templates/prompts"
|
|
353
|
+
mkdir -p "$REPO_ROOT/.claude/agent-memory/explanations"
|
|
354
|
+
|
|
355
|
+
# Copy the /setup command
|
|
356
|
+
cp "$SCRIPT_DIR/commands/setup.md" "$REPO_ROOT/.claude/commands/setup.md"
|
|
357
|
+
ok "Installed /setup command"
|
|
358
|
+
|
|
359
|
+
# Copy templates
|
|
360
|
+
cp -r "$SCRIPT_DIR/templates/"* "$REPO_ROOT/.claude/setup-templates/"
|
|
361
|
+
ok "Installed setup templates"
|
|
362
|
+
|
|
363
|
+
# Write OSS detection results for /setup
|
|
364
|
+
cat > "$REPO_ROOT/.claude/setup-templates/.oss-detection.json" << EOF
|
|
365
|
+
{
|
|
366
|
+
"is_oss": $IS_OSS,
|
|
367
|
+
"signals": {
|
|
368
|
+
"public_repo": $HAS_PUBLIC_REPO,
|
|
369
|
+
"has_ci": $HAS_CI,
|
|
370
|
+
"has_contributing": $HAS_CONTRIBUTING
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
EOF
|
|
374
|
+
ok "OSS detection results written"
|
|
375
|
+
|
|
376
|
+
# Copy security exemptions config (skip if already exists — preserve user exemptions)
|
|
377
|
+
if [ ! -f "${REPO_ROOT}/.claude/security-exemptions.yaml" ]; then
|
|
378
|
+
cp "${SCRIPT_DIR}/templates/security/security-exemptions.yaml" "${REPO_ROOT}/.claude/security-exemptions.yaml"
|
|
379
|
+
ok "Created .claude/security-exemptions.yaml"
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
# Copy prompts
|
|
383
|
+
if [ -d "$SCRIPT_DIR/prompts" ] && [ "$(ls -A "$SCRIPT_DIR/prompts" 2>/dev/null)" ]; then
|
|
384
|
+
cp -r "$SCRIPT_DIR/prompts/"* "$REPO_ROOT/.claude/setup-templates/prompts/"
|
|
385
|
+
ok "Installed prompts"
|
|
386
|
+
fi
|
|
387
|
+
|
|
388
|
+
# Initialize OpenSpec if available and not already initialized
|
|
389
|
+
if [ "$HAS_OPENSPEC" = true ] && [ ! -d "$REPO_ROOT/openspec" ]; then
|
|
390
|
+
info "Initializing OpenSpec..."
|
|
391
|
+
cd "$REPO_ROOT" && openspec init 2>/dev/null && {
|
|
392
|
+
ok "OpenSpec initialized"
|
|
393
|
+
} || {
|
|
394
|
+
warn "OpenSpec init failed — you can run 'openspec init' manually later"
|
|
395
|
+
}
|
|
396
|
+
fi
|
|
397
|
+
|
|
398
|
+
# ─────────────────────────────────────────────
|
|
399
|
+
# Phase 3b: Install web manager
|
|
400
|
+
# ─────────────────────────────────────────────
|
|
401
|
+
|
|
402
|
+
step "Phase 3b: Installing web manager (Pipeline Monitor)"
|
|
403
|
+
|
|
404
|
+
WEB_MANAGER_DIR="$REPO_ROOT/.claude/web-manager"
|
|
405
|
+
|
|
406
|
+
if [ -d "$WEB_MANAGER_DIR" ]; then
|
|
407
|
+
warn "Existing .claude/web-manager/ found — skipping (delete it to reinstall)"
|
|
408
|
+
HAS_WEB_MANAGER=true
|
|
409
|
+
else
|
|
410
|
+
mkdir -p "$WEB_MANAGER_DIR"
|
|
411
|
+
cp -r "$SCRIPT_DIR/templates/web-manager/"* "$WEB_MANAGER_DIR/"
|
|
412
|
+
ok "Copied web manager to .claude/web-manager/"
|
|
413
|
+
|
|
414
|
+
if [ "$HAS_NPM" = true ]; then
|
|
415
|
+
info "Installing web manager dependencies..."
|
|
416
|
+
(cd "$WEB_MANAGER_DIR" && npm install --silent 2>/dev/null) && {
|
|
417
|
+
ok "Server dependencies installed"
|
|
418
|
+
} || {
|
|
419
|
+
warn "Server dependency install failed — run 'cd .claude/web-manager && npm install' manually"
|
|
420
|
+
}
|
|
421
|
+
(cd "$WEB_MANAGER_DIR/client" && npm install --silent 2>/dev/null) && {
|
|
422
|
+
ok "Client dependencies installed"
|
|
423
|
+
} || {
|
|
424
|
+
warn "Client dependency install failed — run 'cd .claude/web-manager/client && npm install' manually"
|
|
425
|
+
}
|
|
426
|
+
HAS_WEB_MANAGER=true
|
|
427
|
+
else
|
|
428
|
+
warn "npm not available — skipping dependency install. Run 'cd .claude/web-manager && npm install' later."
|
|
429
|
+
HAS_WEB_MANAGER=false
|
|
430
|
+
fi
|
|
431
|
+
fi
|
|
432
|
+
|
|
433
|
+
# ─────────────────────────────────────────────
|
|
434
|
+
# Phase 3c: Write version and manifest
|
|
435
|
+
# ─────────────────────────────────────────────
|
|
436
|
+
|
|
437
|
+
step "Phase 3c: Writing version and manifest"
|
|
438
|
+
|
|
439
|
+
generate_manifest
|
|
440
|
+
ok "Written .specrails-version ($(cat "$REPO_ROOT/.specrails-version"))"
|
|
441
|
+
ok "Written .specrails-manifest.json"
|
|
442
|
+
|
|
443
|
+
# ─────────────────────────────────────────────
|
|
444
|
+
# Phase 4: Summary & next steps
|
|
445
|
+
# ─────────────────────────────────────────────
|
|
446
|
+
|
|
447
|
+
step "Phase 4: Installation complete"
|
|
448
|
+
|
|
449
|
+
echo ""
|
|
450
|
+
echo -e "${BOLD}${GREEN}Installation summary:${NC}"
|
|
451
|
+
echo ""
|
|
452
|
+
echo " Files installed:"
|
|
453
|
+
echo " .claude/commands/setup.md ← The /setup command"
|
|
454
|
+
echo " .claude/setup-templates/ ← Templates (temporary, removed after setup)"
|
|
455
|
+
echo " .claude/web-manager/ ← Pipeline Monitor dashboard"
|
|
456
|
+
echo " .specrails-version ← Installed specrails version"
|
|
457
|
+
echo " .specrails-manifest.json ← Artifact checksums for update detection"
|
|
458
|
+
echo ""
|
|
459
|
+
|
|
460
|
+
echo -e "${BOLD}Prerequisites:${NC}"
|
|
461
|
+
echo ""
|
|
462
|
+
[ "$HAS_NPM" = true ] && ok "npm" || warn "npm (optional)"
|
|
463
|
+
[ "$HAS_OPENSPEC" = true ] && ok "OpenSpec" || warn "OpenSpec (optional)"
|
|
464
|
+
[ "$HAS_GH" = true ] && ok "GitHub CLI" || warn "GitHub CLI (optional, for GitHub Issues backlog)"
|
|
465
|
+
[ "$HAS_JIRA" = true ] && ok "JIRA CLI" || info "JIRA CLI not found (optional, for JIRA backlog)"
|
|
466
|
+
[ "$HAS_WEB_MANAGER" = true ] && ok "Web Manager" || warn "Web Manager (npm required)"
|
|
467
|
+
echo ""
|
|
468
|
+
|
|
469
|
+
echo -e "${BOLD}${CYAN}Next steps:${NC}"
|
|
470
|
+
echo ""
|
|
471
|
+
echo " 1. Open Claude Code in this repo:"
|
|
472
|
+
echo ""
|
|
473
|
+
echo -e " ${BOLD}cd $REPO_ROOT && claude${NC}"
|
|
474
|
+
echo ""
|
|
475
|
+
echo " 2. Run the setup wizard:"
|
|
476
|
+
echo ""
|
|
477
|
+
echo -e " ${BOLD}/setup${NC}"
|
|
478
|
+
echo ""
|
|
479
|
+
echo " 3. Launch the Pipeline Monitor (optional):"
|
|
480
|
+
echo ""
|
|
481
|
+
echo -e " ${BOLD}cd $REPO_ROOT/.claude/web-manager && npm run dev${NC}"
|
|
482
|
+
echo ""
|
|
483
|
+
echo -e " Opens at ${BOLD}http://localhost:4201${NC}"
|
|
484
|
+
echo ""
|
|
485
|
+
echo " Claude will analyze your codebase, ask about your users,"
|
|
486
|
+
echo " research the competitive landscape, and generate all agents,"
|
|
487
|
+
echo " commands, rules, and personas adapted to your project."
|
|
488
|
+
echo ""
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "specrails",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Agent Workflow System installer for Claude Code",
|
|
5
|
+
"bin": {
|
|
6
|
+
"specrails": "bin/specrails.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/",
|
|
10
|
+
"install.sh",
|
|
11
|
+
"update.sh",
|
|
12
|
+
"templates/",
|
|
13
|
+
"prompts/",
|
|
14
|
+
".claude/skills/",
|
|
15
|
+
"commands/",
|
|
16
|
+
"VERSION"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18.0.0"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/fjpulidop/specrails.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"claude",
|
|
27
|
+
"claude-code",
|
|
28
|
+
"ai-agents",
|
|
29
|
+
"workflow",
|
|
30
|
+
"developer-tools"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"author": "fjpulidop"
|
|
34
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Codebase Analysis Prompt
|
|
2
|
+
|
|
3
|
+
Analyze this repository to understand its architecture, stack, and conventions.
|
|
4
|
+
|
|
5
|
+
## What to detect
|
|
6
|
+
|
|
7
|
+
### 1. Languages & Frameworks
|
|
8
|
+
- Scan for language-specific files: `*.py`, `*.ts`, `*.tsx`, `*.js`, `*.go`, `*.rs`, `*.java`, `*.kt`, `*.rb`, `*.cs`, `*.swift`
|
|
9
|
+
- Check dependency files: `requirements.txt`, `pyproject.toml`, `package.json`, `go.mod`, `Cargo.toml`, `pom.xml`, `Gemfile`, `*.csproj`
|
|
10
|
+
- Identify frameworks from imports: FastAPI, Django, Flask, Express, Next.js, React, Vue, Angular, Spring, Gin, Actix, Rails, etc.
|
|
11
|
+
|
|
12
|
+
### 2. Architecture Layers
|
|
13
|
+
For each detected layer, identify:
|
|
14
|
+
- **Name**: e.g., "Backend", "Frontend", "Core", "API", "Mobile", "CLI"
|
|
15
|
+
- **Path**: e.g., `backend/`, `src/`, `frontend/`, `app/`, `lib/`
|
|
16
|
+
- **Tech**: e.g., "FastAPI (Python)", "React + TypeScript", "Go package"
|
|
17
|
+
- **Tag**: e.g., `[backend]`, `[frontend]`, `[core]`, `[mobile]`, `[test]`
|
|
18
|
+
|
|
19
|
+
### 3. CI/CD Commands
|
|
20
|
+
Parse `.github/workflows/*.yml`, `.gitlab-ci.yml`, `Jenkinsfile`, `Makefile`, `package.json` scripts to find:
|
|
21
|
+
- **Lint** commands (ruff, eslint, golangci-lint, clippy, rubocop)
|
|
22
|
+
- **Format** commands (ruff format, prettier, gofmt, rustfmt)
|
|
23
|
+
- **Test** commands (pytest, vitest, jest, go test, cargo test)
|
|
24
|
+
- **Build** commands (tsc, vite build, go build, cargo build)
|
|
25
|
+
- **Type check** commands (tsc --noEmit, mypy, pyright)
|
|
26
|
+
|
|
27
|
+
### 4. Conventions
|
|
28
|
+
Read 3-5 representative source files from each layer to detect:
|
|
29
|
+
- Naming style (snake_case, camelCase, PascalCase)
|
|
30
|
+
- Import organization patterns
|
|
31
|
+
- Error handling approach
|
|
32
|
+
- Testing patterns (framework, mocking, fixtures)
|
|
33
|
+
- API style (REST, GraphQL, tRPC, gRPC)
|
|
34
|
+
- State management (if frontend)
|
|
35
|
+
- Database access pattern (ORM, raw SQL, repository pattern)
|
|
36
|
+
|
|
37
|
+
### 5. Project Warnings
|
|
38
|
+
Look for:
|
|
39
|
+
- Concurrency constraints
|
|
40
|
+
- Authentication patterns
|
|
41
|
+
- State management gotchas
|
|
42
|
+
- Known test isolation issues
|
|
43
|
+
- Environment-specific behavior
|
|
44
|
+
|
|
45
|
+
## Output Format
|
|
46
|
+
|
|
47
|
+
Return a structured analysis:
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
project:
|
|
51
|
+
name: "project-name"
|
|
52
|
+
description: "One-line description"
|
|
53
|
+
|
|
54
|
+
stack:
|
|
55
|
+
- layer: "Backend"
|
|
56
|
+
tech: "FastAPI (Python 3.11)"
|
|
57
|
+
path: "backend/"
|
|
58
|
+
tag: "[backend]"
|
|
59
|
+
- layer: "Frontend"
|
|
60
|
+
tech: "React 19 + TypeScript + Vite"
|
|
61
|
+
path: "frontend/"
|
|
62
|
+
tag: "[frontend]"
|
|
63
|
+
|
|
64
|
+
ci:
|
|
65
|
+
backend:
|
|
66
|
+
lint: "ruff check ."
|
|
67
|
+
format: "ruff format --check ."
|
|
68
|
+
test: "pytest tests/ -q"
|
|
69
|
+
frontend:
|
|
70
|
+
lint: "npm run lint"
|
|
71
|
+
typecheck: "npx tsc --noEmit"
|
|
72
|
+
test: "npx vitest run"
|
|
73
|
+
|
|
74
|
+
conventions:
|
|
75
|
+
backend:
|
|
76
|
+
- "Routes are thin: validate → call service → return model"
|
|
77
|
+
- "Services own business logic"
|
|
78
|
+
- "Repository pattern for data access"
|
|
79
|
+
frontend:
|
|
80
|
+
- "Functional components with hooks"
|
|
81
|
+
- "TanStack Query for server state"
|
|
82
|
+
- "Tailwind for styling"
|
|
83
|
+
|
|
84
|
+
warnings:
|
|
85
|
+
- "Auth: All endpoints require authentication"
|
|
86
|
+
- "Tests: Fixtures must use scope='function'"
|
|
87
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Persona Generation Prompt
|
|
2
|
+
|
|
3
|
+
Generate Value Proposition Canvas personas for the target users of this project.
|
|
4
|
+
|
|
5
|
+
## Input
|
|
6
|
+
|
|
7
|
+
The user has described their target users in natural language. Use this description to:
|
|
8
|
+
|
|
9
|
+
1. **Research the competitive landscape** using WebSearch:
|
|
10
|
+
- Search for existing tools these users currently use
|
|
11
|
+
- Find common pain points and frustrations in forums (Reddit, HN, product reviews)
|
|
12
|
+
- Identify feature gaps in competitor products
|
|
13
|
+
- Understand workflow patterns and daily routines
|
|
14
|
+
|
|
15
|
+
2. **Generate a detailed VPC persona** for each user type that includes:
|
|
16
|
+
|
|
17
|
+
### Profile
|
|
18
|
+
- **Nickname + Role**: A memorable name and short role description
|
|
19
|
+
- **Age range**: Typical demographic
|
|
20
|
+
- **Key behaviors**: 4-5 bullet points describing how they work/interact with tools
|
|
21
|
+
- **Tools currently used**: List of specific competitor products/tools
|
|
22
|
+
- **Spending pattern**: If relevant (monthly spend, budget constraints)
|
|
23
|
+
- **Mindset**: How they think about the problem space
|
|
24
|
+
|
|
25
|
+
### Value Proposition Canvas
|
|
26
|
+
|
|
27
|
+
#### Customer Jobs (6-8 entries)
|
|
28
|
+
| Type | Job |
|
|
29
|
+
|------|-----|
|
|
30
|
+
| **Functional** | Concrete tasks they need to accomplish |
|
|
31
|
+
| **Social** | How they want to be perceived by others |
|
|
32
|
+
| **Emotional** | How they want to feel |
|
|
33
|
+
|
|
34
|
+
#### Pains (6-8 entries, graded by severity)
|
|
35
|
+
| Severity | Pain |
|
|
36
|
+
|----------|------|
|
|
37
|
+
| **Critical** | Major blockers — things that cause real frustration or wasted time |
|
|
38
|
+
| **High** | Significant issues that affect daily workflow |
|
|
39
|
+
| **Medium** | Annoyances that are tolerable but reduce satisfaction |
|
|
40
|
+
| **Low** | Minor inconveniences |
|
|
41
|
+
|
|
42
|
+
#### Gains (6-8 entries, graded by impact)
|
|
43
|
+
| Impact | Gain |
|
|
44
|
+
|--------|------|
|
|
45
|
+
| **High** | Game-changing improvements that would make them switch tools |
|
|
46
|
+
| **Medium** | Meaningful improvements to their workflow |
|
|
47
|
+
| **Low** | Nice-to-haves |
|
|
48
|
+
|
|
49
|
+
### Key Insight
|
|
50
|
+
> The single most important unmet need that this project can uniquely address. This should be the intersection of a critical pain + a high-impact gain that no competitor handles well.
|
|
51
|
+
|
|
52
|
+
### Sources
|
|
53
|
+
List the actual URLs used during research (competitive analysis, forums, reviews, documentation).
|
|
54
|
+
|
|
55
|
+
## Quality Criteria
|
|
56
|
+
|
|
57
|
+
- **Grounded in research**: Every pain and gain should be traceable to real user feedback, not assumptions
|
|
58
|
+
- **Specific, not generic**: "Spending 30 minutes swapping cards between decks" > "Managing multiple decks is hard"
|
|
59
|
+
- **Actionable**: Each pain/gain should suggest a potential feature
|
|
60
|
+
- **Differentiated**: Personas should have meaningfully different needs — if they're too similar, merge them
|
|
61
|
+
- **Realistic**: Don't invent fantasy users — base on actual market segments
|