thrivekit 2.0.17 → 2.0.19
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/README.md +1 -1
- package/package.json +1 -1
- package/ralph/init.sh +45 -35
- package/ralph/loop.sh +13 -3
- package/ralph/setup.sh +9 -0
- package/ralph/utils.sh +14 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
A toolkit for implementing [RALPH](https://ghuntley.com/ralph/) with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) that helps you go from idea to shipped code.
|
|
6
6
|
|
|
7
|
-
> **Optimized for:** Python, TypeScript, React, and Docker projects. Auto-detects ports from `docker-compose.yml`, Vite, Next.js, and
|
|
7
|
+
> **Optimized for:** Python, TypeScript, React, Go/Hugo, and Docker projects. Auto-detects ports from `docker-compose.yml`, Vite, Next.js, Hugo, FastAPI, and more.
|
|
8
8
|
|
|
9
9
|
> You focus on what matters: your ideas. Brainstorm with `/idea`, then let Ralph handle the rest - coding, testing, and committing in an iterative loop until everything passes.
|
|
10
10
|
|
package/package.json
CHANGED
package/ralph/init.sh
CHANGED
|
@@ -188,64 +188,66 @@ auto_configure_project() {
|
|
|
188
188
|
|
|
189
189
|
# 2. Detect testUrlBase from common patterns
|
|
190
190
|
local base_url=""
|
|
191
|
+
local detected_framework=""
|
|
191
192
|
|
|
192
|
-
# Check docker-compose.yml for frontend/web service port mappings
|
|
193
|
+
# Check docker-compose.yml for frontend/web service port mappings (highest priority)
|
|
193
194
|
for compose_file in "docker-compose.yml" "docker-compose.yaml" "compose.yml" "compose.yaml"; do
|
|
194
195
|
if [[ -f "$compose_file" && -z "$base_url" ]]; then
|
|
195
|
-
# Look for web/frontend service port mapping
|
|
196
196
|
local web_port
|
|
197
197
|
web_port=$(grep -A 20 -E '^\s*(web|frontend|client|ui):' "$compose_file" 2>/dev/null | \
|
|
198
198
|
grep -E '^\s*-\s*"?[0-9]+:[0-9]+"?' | head -1 | \
|
|
199
199
|
grep -oE '[0-9]+:' | head -1 | tr -d ':')
|
|
200
200
|
if [[ -n "$web_port" ]]; then
|
|
201
201
|
base_url="http://localhost:$web_port"
|
|
202
|
+
detected_framework="docker"
|
|
202
203
|
fi
|
|
203
204
|
fi
|
|
204
205
|
done
|
|
205
206
|
|
|
206
|
-
#
|
|
207
|
+
# Detect framework and use default port from constants
|
|
207
208
|
if [[ -z "$base_url" ]]; then
|
|
209
|
+
# Vite
|
|
208
210
|
for vite_config in "vite.config.ts" "vite.config.js" "apps/web/vite.config.ts" "apps/web/vite.config.js" \
|
|
209
211
|
"apps/frontend/vite.config.ts" "frontend/vite.config.ts"; do
|
|
210
212
|
if [[ -f "$vite_config" ]]; then
|
|
211
|
-
|
|
213
|
+
detected_framework="vite"
|
|
214
|
+
base_url="http://localhost:${DEFAULT_PORTS[vite]}"
|
|
212
215
|
break
|
|
213
216
|
fi
|
|
214
217
|
done
|
|
215
218
|
fi
|
|
216
219
|
|
|
217
|
-
# Check for Next.js (uses port 3000 by default)
|
|
218
220
|
if [[ -z "$base_url" ]]; then
|
|
221
|
+
# Next.js
|
|
219
222
|
for next_config in "next.config.js" "next.config.ts" "next.config.mjs" \
|
|
220
223
|
"apps/web/next.config.js" "apps/web/next.config.mjs"; do
|
|
221
224
|
if [[ -f "$next_config" ]]; then
|
|
222
|
-
|
|
225
|
+
detected_framework="nextjs"
|
|
226
|
+
base_url="http://localhost:${DEFAULT_PORTS[nextjs]}"
|
|
223
227
|
break
|
|
224
228
|
fi
|
|
225
229
|
done
|
|
226
230
|
fi
|
|
227
231
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
232
|
+
if [[ -z "$base_url" ]]; then
|
|
233
|
+
# Hugo
|
|
234
|
+
for hugo_config in "hugo.toml" "hugo.yaml" "hugo.json" "config.toml"; do
|
|
235
|
+
if [[ -f "$hugo_config" ]] && [[ -d "content" || -d "layouts" || -d "themes" ]]; then
|
|
236
|
+
detected_framework="hugo"
|
|
237
|
+
base_url="http://localhost:${DEFAULT_PORTS[hugo]}"
|
|
238
|
+
break
|
|
239
|
+
fi
|
|
240
|
+
done
|
|
237
241
|
fi
|
|
238
242
|
|
|
239
|
-
# Check for
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
base_url="http://localhost:5173"
|
|
246
|
-
fi
|
|
243
|
+
# Fallback: Check package.json for port hints
|
|
244
|
+
if [[ -z "$base_url" && -f "package.json" ]]; then
|
|
245
|
+
local pkg_port
|
|
246
|
+
pkg_port=$(grep -oE ':[0-9]{4}' package.json 2>/dev/null | head -1 | tr -d ':')
|
|
247
|
+
if [[ -n "$pkg_port" ]]; then
|
|
248
|
+
base_url="http://localhost:$pkg_port"
|
|
247
249
|
fi
|
|
248
|
-
|
|
250
|
+
fi
|
|
249
251
|
|
|
250
252
|
if [[ -n "$base_url" ]]; then
|
|
251
253
|
if jq -e '.testUrlBase' "$tmpfile" >/dev/null 2>&1 && [[ "$(jq -r '.testUrlBase' "$tmpfile")" != "" ]]; then
|
|
@@ -294,17 +296,18 @@ auto_configure_project() {
|
|
|
294
296
|
|
|
295
297
|
# 4. Detect API baseUrl based on backend type
|
|
296
298
|
local api_url=""
|
|
299
|
+
local api_framework=""
|
|
297
300
|
|
|
298
|
-
# Check docker-compose.yml for API service port mappings (
|
|
301
|
+
# Check docker-compose.yml for API service port mappings (highest priority)
|
|
299
302
|
for compose_file in "docker-compose.yml" "docker-compose.yaml" "compose.yml" "compose.yaml"; do
|
|
300
303
|
if [[ -f "$compose_file" && -z "$api_url" ]]; then
|
|
301
|
-
# Look for api/backend service port mapping like "8000:8000" or "3001:3000"
|
|
302
304
|
local api_port
|
|
303
305
|
api_port=$(grep -A 20 -E '^\s*(api|backend|server|app):' "$compose_file" 2>/dev/null | \
|
|
304
306
|
grep -E '^\s*-\s*"?[0-9]+:[0-9]+"?' | head -1 | \
|
|
305
307
|
grep -oE '[0-9]+:' | head -1 | tr -d ':')
|
|
306
308
|
if [[ -n "$api_port" ]]; then
|
|
307
309
|
api_url="http://localhost:$api_port"
|
|
310
|
+
api_framework="docker"
|
|
308
311
|
fi
|
|
309
312
|
fi
|
|
310
313
|
done
|
|
@@ -316,20 +319,27 @@ auto_configure_project() {
|
|
|
316
319
|
docker_port=$(grep -i "^EXPOSE" "$backend_dir/Dockerfile" 2>/dev/null | head -1 | grep -oE '[0-9]+' | head -1)
|
|
317
320
|
if [[ -n "$docker_port" ]]; then
|
|
318
321
|
api_url="http://localhost:$docker_port"
|
|
322
|
+
api_framework="docker"
|
|
319
323
|
fi
|
|
320
324
|
fi
|
|
321
|
-
# Python backends
|
|
325
|
+
# Python backends - detect framework and use default port
|
|
322
326
|
if [[ -z "$api_url" ]] && { [[ -f "$backend_dir/pyproject.toml" ]] || [[ -f "$backend_dir/requirements.txt" ]] || [[ -f "$backend_dir/main.py" ]]; }; then
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
api_url="http://localhost:4000"
|
|
327
|
+
if grep -q "fastapi\|FastAPI" "$backend_dir"/*.py "$backend_dir/pyproject.toml" 2>/dev/null; then
|
|
328
|
+
api_framework="fastapi"
|
|
329
|
+
elif grep -q "django\|Django" "$backend_dir"/*.py "$backend_dir/pyproject.toml" 2>/dev/null; then
|
|
330
|
+
api_framework="django"
|
|
331
|
+
elif grep -q "flask\|Flask" "$backend_dir"/*.py "$backend_dir/pyproject.toml" 2>/dev/null; then
|
|
332
|
+
api_framework="flask"
|
|
330
333
|
else
|
|
331
|
-
|
|
334
|
+
api_framework="fastapi" # Default for Python
|
|
332
335
|
fi
|
|
336
|
+
api_url="http://localhost:${DEFAULT_PORTS[$api_framework]}"
|
|
337
|
+
# Node backends - check for port in package.json
|
|
338
|
+
elif [[ -z "$api_url" && -f "$backend_dir/package.json" ]]; then
|
|
339
|
+
local node_port
|
|
340
|
+
node_port=$(grep -oE ':[0-9]{4}' "$backend_dir/package.json" 2>/dev/null | head -1 | tr -d ':')
|
|
341
|
+
api_url="http://localhost:${node_port:-${DEFAULT_PORTS[express]}}"
|
|
342
|
+
api_framework="express"
|
|
333
343
|
fi
|
|
334
344
|
fi
|
|
335
345
|
|
package/ralph/loop.sh
CHANGED
|
@@ -44,13 +44,23 @@ preflight_checks() {
|
|
|
44
44
|
# Check for alembic migrations
|
|
45
45
|
if [[ -d "$backend_dir/alembic" ]] || [[ -d "$backend_dir/migrations" ]]; then
|
|
46
46
|
printf " Database migrations... "
|
|
47
|
-
#
|
|
47
|
+
# Detect Python runner
|
|
48
|
+
local py_runner="python"
|
|
49
|
+
if [[ -f "$backend_dir/uv.lock" ]]; then
|
|
50
|
+
py_runner="uv run"
|
|
51
|
+
elif [[ -f "$backend_dir/poetry.lock" ]]; then
|
|
52
|
+
py_runner="poetry run"
|
|
53
|
+
fi
|
|
54
|
+
# Try to verify DB connection via alembic
|
|
48
55
|
if [[ -f "$backend_dir/alembic.ini" ]]; then
|
|
49
|
-
if (cd "$backend_dir" && alembic current >/dev/null 2>&1); then
|
|
56
|
+
if (cd "$backend_dir" && $py_runner alembic current >/dev/null 2>&1); then
|
|
50
57
|
print_success "ok"
|
|
58
|
+
elif docker compose exec -T api alembic current >/dev/null 2>&1; then
|
|
59
|
+
# Try via Docker if local fails
|
|
60
|
+
print_success "ok (via docker)"
|
|
51
61
|
else
|
|
52
62
|
print_warning "check DB connection"
|
|
53
|
-
echo " Run: cd $backend_dir && alembic current"
|
|
63
|
+
echo " Run: cd $backend_dir && $py_runner alembic current"
|
|
54
64
|
((warnings++))
|
|
55
65
|
fi
|
|
56
66
|
fi
|
package/ralph/setup.sh
CHANGED
|
@@ -257,6 +257,15 @@ setup_claude_md() {
|
|
|
257
257
|
fi
|
|
258
258
|
[[ -f "manage.py" ]] && framework="${framework:+$framework + }Django"
|
|
259
259
|
|
|
260
|
+
# Detect Hugo (Go static site generator)
|
|
261
|
+
for hugo_config in "hugo.toml" "hugo.yaml" "hugo.json" "config.toml"; do
|
|
262
|
+
if [[ -f "$hugo_config" ]] && [[ -d "content" || -d "layouts" || -d "themes" ]]; then
|
|
263
|
+
framework="${framework:+$framework + }Hugo"
|
|
264
|
+
[[ -z "$runtime" ]] && runtime="Go"
|
|
265
|
+
break
|
|
266
|
+
fi
|
|
267
|
+
done
|
|
268
|
+
|
|
260
269
|
# Detect TypeScript
|
|
261
270
|
[[ -f "tsconfig.json" || -f "${fe_dir}/tsconfig.json" ]] && language="TypeScript"
|
|
262
271
|
|
package/ralph/utils.sh
CHANGED
|
@@ -24,6 +24,20 @@ readonly CURL_TIMEOUT_SECONDS=10
|
|
|
24
24
|
readonly FRONTEND_DIRS=("apps/web" "frontend" "client" "web")
|
|
25
25
|
readonly BACKEND_DIRS=("apps/api" "api" "backend" "server")
|
|
26
26
|
|
|
27
|
+
# Default ports by framework (used only during detection, then stored in config)
|
|
28
|
+
declare -A DEFAULT_PORTS=(
|
|
29
|
+
["vite"]=5173
|
|
30
|
+
["nextjs"]=3000
|
|
31
|
+
["hugo"]=1313
|
|
32
|
+
["react"]=3000
|
|
33
|
+
["vue"]=5173
|
|
34
|
+
["express"]=3001
|
|
35
|
+
["fastapi"]=8000
|
|
36
|
+
["django"]=8000
|
|
37
|
+
["flask"]=5000
|
|
38
|
+
["rails"]=3000
|
|
39
|
+
)
|
|
40
|
+
|
|
27
41
|
# Track temp files for safe cleanup
|
|
28
42
|
RALPH_TEMP_FILES=()
|
|
29
43
|
|