thrivekit 2.0.18 → 2.0.20
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 +68 -59
- package/ralph/setup.sh +9 -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
|
@@ -186,66 +186,70 @@ auto_configure_project() {
|
|
|
186
186
|
fi
|
|
187
187
|
fi
|
|
188
188
|
|
|
189
|
-
# 2. Detect testUrlBase
|
|
189
|
+
# 2. Detect testUrlBase by parsing actual config files for port values
|
|
190
190
|
local base_url=""
|
|
191
|
+
local web_port=""
|
|
191
192
|
|
|
192
|
-
#
|
|
193
|
+
# Priority 1: docker-compose.yml - parse actual port mappings
|
|
193
194
|
for compose_file in "docker-compose.yml" "docker-compose.yaml" "compose.yml" "compose.yaml"; do
|
|
194
|
-
if [[ -f "$compose_file" && -z "$
|
|
195
|
-
#
|
|
196
|
-
local web_port
|
|
195
|
+
if [[ -f "$compose_file" && -z "$web_port" ]]; then
|
|
196
|
+
# Extract port from web/frontend service: "5173:5173" -> 5173
|
|
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
|
-
if [[ -n "$web_port" ]]; then
|
|
201
|
-
base_url="http://localhost:$web_port"
|
|
202
|
-
fi
|
|
203
200
|
fi
|
|
204
201
|
done
|
|
205
202
|
|
|
206
|
-
#
|
|
207
|
-
if [[ -z "$
|
|
203
|
+
# Priority 2: Vite config - parse server.port
|
|
204
|
+
if [[ -z "$web_port" ]]; then
|
|
208
205
|
for vite_config in "vite.config.ts" "vite.config.js" "apps/web/vite.config.ts" "apps/web/vite.config.js" \
|
|
209
206
|
"apps/frontend/vite.config.ts" "frontend/vite.config.ts"; do
|
|
210
207
|
if [[ -f "$vite_config" ]]; then
|
|
211
|
-
|
|
208
|
+
# Look for port: 3000 or port: '3000'
|
|
209
|
+
web_port=$(grep -E 'port\s*[=:]\s*[0-9]+' "$vite_config" 2>/dev/null | grep -oE '[0-9]{4}' | head -1)
|
|
210
|
+
[[ -z "$web_port" ]] && web_port="5173" # Vite's documented default
|
|
211
|
+
break
|
|
212
|
+
fi
|
|
213
|
+
done
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
# Priority 3: Hugo config - parse server.port or use documented default
|
|
217
|
+
if [[ -z "$web_port" ]]; then
|
|
218
|
+
for hugo_config in "hugo.toml" "hugo.yaml" "hugo.json" "config.toml"; do
|
|
219
|
+
if [[ -f "$hugo_config" ]] && [[ -d "content" || -d "layouts" || -d "themes" ]]; then
|
|
220
|
+
web_port=$(grep -E 'port\s*=' "$hugo_config" 2>/dev/null | grep -oE '[0-9]+' | head -1)
|
|
221
|
+
[[ -z "$web_port" ]] && web_port="1313" # Hugo's documented default
|
|
212
222
|
break
|
|
213
223
|
fi
|
|
214
224
|
done
|
|
215
225
|
fi
|
|
216
226
|
|
|
217
|
-
#
|
|
218
|
-
if [[ -z "$
|
|
227
|
+
# Priority 4: Next.js - check package.json dev script for -p flag
|
|
228
|
+
if [[ -z "$web_port" ]]; then
|
|
219
229
|
for next_config in "next.config.js" "next.config.ts" "next.config.mjs" \
|
|
220
230
|
"apps/web/next.config.js" "apps/web/next.config.mjs"; do
|
|
221
231
|
if [[ -f "$next_config" ]]; then
|
|
222
|
-
|
|
232
|
+
# Check if package.json has custom port: "dev": "next dev -p 4000"
|
|
233
|
+
local pkg_dir
|
|
234
|
+
pkg_dir=$(dirname "$next_config")
|
|
235
|
+
if [[ -f "$pkg_dir/package.json" ]]; then
|
|
236
|
+
web_port=$(grep -E '"dev".*-p\s*[0-9]+' "$pkg_dir/package.json" 2>/dev/null | grep -oE '\-p\s*[0-9]+' | grep -oE '[0-9]+')
|
|
237
|
+
fi
|
|
238
|
+
[[ -z "$web_port" ]] && web_port="3000" # Next.js documented default
|
|
223
239
|
break
|
|
224
240
|
fi
|
|
225
241
|
done
|
|
226
242
|
fi
|
|
227
243
|
|
|
228
|
-
#
|
|
229
|
-
if [[ -z "$
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
elif grep -q '"dev".*:5173' package.json 2>/dev/null; then
|
|
233
|
-
base_url="http://localhost:5173"
|
|
234
|
-
elif grep -q '"dev".*:8080' package.json 2>/dev/null; then
|
|
235
|
-
base_url="http://localhost:8080"
|
|
236
|
-
fi
|
|
244
|
+
# Priority 5: Generic package.json port detection
|
|
245
|
+
if [[ -z "$web_port" && -f "package.json" ]]; then
|
|
246
|
+
# Look for explicit port in scripts: --port 3000, -p 3000, :3000
|
|
247
|
+
web_port=$(grep -E '"(dev|start|serve)"' package.json 2>/dev/null | grep -oE '(--port|-p|:)[[:space:]]*[0-9]{4}' | grep -oE '[0-9]{4}' | head -1)
|
|
237
248
|
fi
|
|
238
249
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if grep -q ':3000' "$fe_pkg" 2>/dev/null; then
|
|
243
|
-
base_url="http://localhost:3000"
|
|
244
|
-
elif grep -q ':5173' "$fe_pkg" 2>/dev/null; then
|
|
245
|
-
base_url="http://localhost:5173"
|
|
246
|
-
fi
|
|
247
|
-
fi
|
|
248
|
-
done
|
|
250
|
+
if [[ -n "$web_port" ]]; then
|
|
251
|
+
base_url="http://localhost:$web_port"
|
|
252
|
+
fi
|
|
249
253
|
|
|
250
254
|
if [[ -n "$base_url" ]]; then
|
|
251
255
|
if jq -e '.testUrlBase' "$tmpfile" >/dev/null 2>&1 && [[ "$(jq -r '.testUrlBase' "$tmpfile")" != "" ]]; then
|
|
@@ -292,47 +296,52 @@ auto_configure_project() {
|
|
|
292
296
|
fi
|
|
293
297
|
fi
|
|
294
298
|
|
|
295
|
-
# 4. Detect API baseUrl
|
|
299
|
+
# 4. Detect API baseUrl by parsing actual config files for port values
|
|
296
300
|
local api_url=""
|
|
301
|
+
local api_port=""
|
|
297
302
|
|
|
298
|
-
#
|
|
303
|
+
# Priority 1: docker-compose.yml - parse actual port mappings
|
|
299
304
|
for compose_file in "docker-compose.yml" "docker-compose.yaml" "compose.yml" "compose.yaml"; do
|
|
300
|
-
if [[ -f "$compose_file" && -z "$
|
|
301
|
-
#
|
|
302
|
-
local api_port
|
|
305
|
+
if [[ -f "$compose_file" && -z "$api_port" ]]; then
|
|
306
|
+
# Extract port from api/backend service: "8000:8000" -> 8000
|
|
303
307
|
api_port=$(grep -A 20 -E '^\s*(api|backend|server|app):' "$compose_file" 2>/dev/null | \
|
|
304
308
|
grep -E '^\s*-\s*"?[0-9]+:[0-9]+"?' | head -1 | \
|
|
305
309
|
grep -oE '[0-9]+:' | head -1 | tr -d ':')
|
|
306
|
-
if [[ -n "$api_port" ]]; then
|
|
307
|
-
api_url="http://localhost:$api_port"
|
|
308
|
-
fi
|
|
309
310
|
fi
|
|
310
311
|
done
|
|
311
312
|
|
|
312
|
-
|
|
313
|
-
|
|
313
|
+
# Priority 2: Dockerfile EXPOSE directive
|
|
314
|
+
if [[ -n "$backend_dir" && -z "$api_port" ]]; then
|
|
314
315
|
if [[ -f "$backend_dir/Dockerfile" ]]; then
|
|
315
|
-
|
|
316
|
-
docker_port=$(grep -i "^EXPOSE" "$backend_dir/Dockerfile" 2>/dev/null | head -1 | grep -oE '[0-9]+' | head -1)
|
|
317
|
-
if [[ -n "$docker_port" ]]; then
|
|
318
|
-
api_url="http://localhost:$docker_port"
|
|
319
|
-
fi
|
|
316
|
+
api_port=$(grep -i "^EXPOSE" "$backend_dir/Dockerfile" 2>/dev/null | head -1 | grep -oE '[0-9]+' | head -1)
|
|
320
317
|
fi
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
api_url="http://localhost:4000"
|
|
330
|
-
else
|
|
331
|
-
api_url="http://localhost:3001"
|
|
318
|
+
fi
|
|
319
|
+
|
|
320
|
+
# Priority 3: Python - check for uvicorn/gunicorn port in scripts or pyproject.toml
|
|
321
|
+
if [[ -n "$backend_dir" && -z "$api_port" ]]; then
|
|
322
|
+
if [[ -f "$backend_dir/pyproject.toml" ]] || [[ -f "$backend_dir/requirements.txt" ]]; then
|
|
323
|
+
# Check pyproject.toml for port config
|
|
324
|
+
if [[ -f "$backend_dir/pyproject.toml" ]]; then
|
|
325
|
+
api_port=$(grep -E 'port\s*=' "$backend_dir/pyproject.toml" 2>/dev/null | grep -oE '[0-9]+' | head -1)
|
|
332
326
|
fi
|
|
327
|
+
# Check for uvicorn command with --port
|
|
328
|
+
if [[ -z "$api_port" && -f "$backend_dir/Makefile" ]]; then
|
|
329
|
+
api_port=$(grep -E 'uvicorn.*--port' "$backend_dir/Makefile" 2>/dev/null | grep -oE '\-\-port[[:space:]]*[0-9]+' | grep -oE '[0-9]+' | head -1)
|
|
330
|
+
fi
|
|
331
|
+
# Uvicorn/FastAPI default
|
|
332
|
+
[[ -z "$api_port" ]] && api_port="8000"
|
|
333
333
|
fi
|
|
334
334
|
fi
|
|
335
335
|
|
|
336
|
+
# Priority 4: Node backend - check package.json for port
|
|
337
|
+
if [[ -n "$backend_dir" && -z "$api_port" && -f "$backend_dir/package.json" ]]; then
|
|
338
|
+
api_port=$(grep -E '"(dev|start|serve)"' "$backend_dir/package.json" 2>/dev/null | grep -oE '(--port|-p|:)[[:space:]]*[0-9]{4}' | grep -oE '[0-9]{4}' | head -1)
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
if [[ -n "$api_port" ]]; then
|
|
342
|
+
api_url="http://localhost:$api_port"
|
|
343
|
+
fi
|
|
344
|
+
|
|
336
345
|
if [[ -n "$api_url" ]]; then
|
|
337
346
|
if jq -e '.api.baseUrl' "$tmpfile" >/dev/null 2>&1 && [[ "$(jq -r '.api.baseUrl' "$tmpfile")" != "" ]]; then
|
|
338
347
|
: # Already set
|
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
|
|