replit-tools 1.1.10 → 1.1.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replit-tools",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "DATA Tools - One command to set up Claude Code and Codex CLI on Replit with full persistence",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -3,20 +3,21 @@
3
3
  # Automatically refreshes Claude Code OAuth tokens before expiration
4
4
  # Part of DATA Tools - https://github.com/stevemoraco/DATAtools
5
5
 
6
- # Use .replit-tools structure
6
+ # Paths - credentials are at workspace root, not inside .replit-tools
7
7
  WORKSPACE="/home/runner/workspace"
8
8
  REPLIT_TOOLS="${WORKSPACE}/.replit-tools"
9
- CREDENTIALS_FILE="${CLAUDE_CONFIG_DIR:-${REPLIT_TOOLS}/.claude-persistent}/.credentials.json"
9
+ # Credentials are stored at /home/runner/workspace/.claude-persistent (NOT inside .replit-tools)
10
+ CREDENTIALS_FILE="${CLAUDE_CONFIG_DIR:-${WORKSPACE}/.claude-persistent}/.credentials.json"
10
11
  LOG_FILE="${REPLIT_TOOLS}/.logs/auth-refresh.log"
11
12
 
13
+ # Ensure log directory exists
14
+ mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null
15
+
12
16
  # OAuth configuration
13
17
  OAUTH_ENDPOINT="https://console.anthropic.com/v1/oauth/token"
14
18
  CLIENT_ID="9d1c250a-e61b-44d9-88ed-5944d1962f5e"
15
19
  REFRESH_THRESHOLD_HOURS=2 # Refresh when less than 2 hours remaining
16
20
 
17
- # Ensure log directory exists
18
- mkdir -p "${REPLIT_TOOLS}/.logs" 2>/dev/null
19
-
20
21
  # Logging function
21
22
  log() {
22
23
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
@@ -225,7 +225,27 @@ get_terminal_last_session() {
225
225
  fi
226
226
  }
227
227
 
228
- # Interactive session picker
228
+ # Run Claude and handle exit codes (returns to menu on failure)
229
+ run_claude_with_retry() {
230
+ local cmd="$1"
231
+ local session_desc="$2"
232
+
233
+ echo ""
234
+ echo " ${session_desc}..."
235
+
236
+ # Run Claude
237
+ eval "$cmd"
238
+ local exit_code=$?
239
+
240
+ # Save session state on success
241
+ if [ $exit_code -eq 0 ]; then
242
+ save_session_state "$(tail -1 "${HOME}/.claude/history.jsonl" 2>/dev/null | grep -oP '"sessionId":"[^"]+"' | cut -d'"' -f4)"
243
+ fi
244
+
245
+ return $exit_code
246
+ }
247
+
248
+ # Interactive session picker (loops until user exits to shell)
229
249
  claude_prompt() {
230
250
  # Only in interactive shells
231
251
  [[ $- != *i* ]] && return 0
@@ -236,104 +256,139 @@ claude_prompt() {
236
256
  fi
237
257
 
238
258
  # LOOP PREVENTION: Track if we've already prompted this terminal session
239
- local prompt_marker="${REPLIT_TOOLS}/.prompt-shown-${TERMINAL_ID}"
259
+ # Include the shell PID so new shells always get the menu
260
+ local prompt_marker="${REPLIT_TOOLS}/.prompt-active-${TERMINAL_ID}-$$"
261
+
262
+ # Clean up old markers from crashed/closed shells
263
+ # Remove markers older than 1 hour or from PIDs that no longer exist
264
+ find "${REPLIT_TOOLS}" -name ".prompt-active-*" -mmin +60 -delete 2>/dev/null
265
+ for marker in "${REPLIT_TOOLS}"/.prompt-active-*; do
266
+ if [ -f "$marker" ]; then
267
+ local marker_pid=$(basename "$marker" | rev | cut -d'-' -f1 | rev)
268
+ if [ -n "$marker_pid" ] && ! kill -0 "$marker_pid" 2>/dev/null; then
269
+ rm -f "$marker" 2>/dev/null
270
+ fi
271
+ fi
272
+ done
240
273
 
241
- # If we've already shown the prompt for this terminal, skip
274
+ # If THIS shell already showed the prompt, skip (prevents re-sourcing issues)
242
275
  if [ -f "$prompt_marker" ]; then
243
- # Clear old markers (older than 12 hours)
244
- find "${REPLIT_TOOLS}" -name ".prompt-shown-*" -mmin +720 -delete 2>/dev/null
245
276
  return 0
246
277
  fi
247
278
 
248
- # Mark that we're showing the prompt (create marker BEFORE showing)
279
+ # Mark that we're showing the prompt for THIS shell session
249
280
  touch "$prompt_marker" 2>/dev/null
250
281
 
251
- local running=$(count_claude_instances)
252
- local last_session=$(get_terminal_last_session)
282
+ # Cleanup function to remove marker when shell exits
283
+ trap "rm -f '$prompt_marker' 2>/dev/null" EXIT
284
+
285
+ # Main menu loop - keeps showing until user chooses shell
286
+ while true; do
287
+ local running=$(count_claude_instances)
288
+ local last_session=$(get_terminal_last_session)
289
+
290
+ echo ""
291
+ echo "╭─────────────────────────────────────────────────────────╮"
292
+ echo "│ Claude Session Manager │"
293
+ echo "╰─────────────────────────────────────────────────────────╯"
294
+
295
+ if [ "$running" -gt 0 ]; then
296
+ echo " ($running Claude instance(s) running in other terminals)"
297
+ fi
298
+ echo ""
299
+
300
+ # Show options
301
+ echo " [c] Continue last session for this terminal"
302
+ if [ -n "$last_session" ]; then
303
+ echo " └─ ${last_session:0:8}..."
304
+ fi
305
+ echo " [r] Resume a specific session (pick from list)"
306
+ echo " [n] Start new session"
307
+ echo " [l] Login to Claude (authenticate)"
308
+ echo " [s] Skip - just give me a shell"
309
+ echo ""
310
+
311
+ # Read choice with timeout
312
+ local choice
313
+ read -t 60 -n 1 -p " Choice [c/r/n/l/s]: " choice
314
+ echo ""
315
+
316
+ case "$choice" in
317
+ c|C|"")
318
+ # Continue last session (default on Enter or timeout)
319
+ if [ -n "$last_session" ]; then
320
+ run_claude_with_retry "claude -r '$last_session' --dangerously-skip-permissions" "Resuming session ${last_session:0:8}"
321
+ else
322
+ run_claude_with_retry "claude --dangerously-skip-permissions" "No previous session, starting new"
323
+ fi
324
+ # After Claude exits, loop back to menu
325
+ echo ""
326
+ echo " Claude exited. Returning to menu..."
327
+ sleep 1
328
+ ;;
329
+ r|R)
330
+ # Show session list with full details
331
+ echo ""
332
+ echo " Recent Sessions"
333
+ show_sessions
253
334
 
254
- echo ""
255
- echo "╭─────────────────────────────────────────────────────────╮"
256
- echo "│ Claude Session Manager │"
257
- echo "╰─────────────────────────────────────────────────────────╯"
335
+ # Get session IDs for selection
336
+ local session_ids=$(get_recent_sessions | grep "^ID|" | cut -d'|' -f2)
258
337
 
259
- if [ "$running" -gt 0 ]; then
260
- echo " ($running Claude instance(s) running in other terminals)"
261
- fi
262
- echo ""
338
+ read -t 60 -p " Enter number (or 'q' to cancel): " session_num
263
339
 
264
- # Show options
265
- echo " [c] Continue last session for this terminal"
266
- if [ -n "$last_session" ]; then
267
- echo " └─ ${last_session:0:8}..."
268
- fi
269
- echo " [r] Resume a specific session (pick from list)"
270
- echo " [n] Start new session"
271
- echo " [s] Skip - just give me a shell"
272
- echo ""
273
-
274
- # Read choice with timeout
275
- local choice
276
- read -t 30 -n 1 -p " Choice [c/r/n/s]: " choice
277
- echo ""
340
+ if [ "$session_num" = "q" ] || [ -z "$session_num" ]; then
341
+ echo " Cancelled, returning to menu..."
342
+ continue
343
+ fi
278
344
 
279
- case "$choice" in
280
- c|C|"")
281
- # Continue last session (default on Enter or timeout)
282
- if [ -n "$last_session" ]; then
345
+ local selected_id=$(echo "$session_ids" | sed -n "${session_num}p")
346
+ if [ -n "$selected_id" ]; then
347
+ run_claude_with_retry "claude -r '$selected_id' --dangerously-skip-permissions" "Resuming session $selected_id"
348
+ echo ""
349
+ echo " Claude exited. Returning to menu..."
350
+ sleep 1
351
+ else
352
+ echo " Invalid selection."
353
+ fi
354
+ ;;
355
+ n|N)
356
+ # Start new session
357
+ run_claude_with_retry "claude --dangerously-skip-permissions" "Starting new Claude session"
283
358
  echo ""
284
- echo " Resuming session ${last_session:0:8}..."
285
- claude -r "$last_session" --dangerously-skip-permissions
286
- save_session_state "$(tail -1 "${HOME}/.claude/history.jsonl" 2>/dev/null | grep -oP '"sessionId":"[^"]+"' | cut -d'"' -f4)"
287
- else
359
+ echo " Claude exited. Returning to menu..."
360
+ sleep 1
361
+ ;;
362
+ l|L)
363
+ # Login to Claude
364
+ echo ""
365
+ echo " Starting Claude login..."
288
366
  echo ""
289
- echo " No previous session for this terminal, starting new..."
290
- claude --dangerously-skip-permissions
291
- save_session_state "$(tail -1 "${HOME}/.claude/history.jsonl" 2>/dev/null | grep -oP '"sessionId":"[^"]+"' | cut -d'"' -f4)"
292
- fi
293
- ;;
294
- r|R)
295
- # Show session list with full details
296
- echo ""
297
- echo " Recent Sessions"
298
- show_sessions
299
367
 
300
- # Get session IDs for selection
301
- local session_ids=$(get_recent_sessions | grep "^ID|" | cut -d'|' -f2)
368
+ # Clear the auth failed marker so setup script will retry
369
+ rm -f "${REPLIT_TOOLS}/.auth-refresh-failed" 2>/dev/null
302
370
 
303
- read -t 30 -p " Enter number (or 'q' to cancel): " session_num
371
+ claude /login
304
372
 
305
- if [ "$session_num" = "q" ] || [ -z "$session_num" ]; then
306
- echo " Cancelled."
373
+ echo ""
374
+ echo " Login complete. Returning to menu..."
375
+ sleep 1
376
+ ;;
377
+ s|S)
378
+ # Skip - just shell
379
+ echo ""
380
+ echo " Okay, just a shell. Type 'claude-menu' to return here."
381
+ # Keep the marker so re-sourcing bashrc won't re-show menu
382
+ # The trap will clean it up when shell exits
307
383
  return 0
308
- fi
309
-
310
- local selected_id=$(echo "$session_ids" | sed -n "${session_num}p")
311
- if [ -n "$selected_id" ]; then
384
+ ;;
385
+ *)
312
386
  echo ""
313
- echo " Resuming session: $selected_id"
314
- claude -r "$selected_id" --dangerously-skip-permissions
315
- save_session_state "$selected_id"
316
- else
317
- echo " Invalid selection."
318
- fi
319
- ;;
320
- n|N)
321
- # Start new session
322
- echo ""
323
- echo " Starting new Claude session..."
324
- claude --dangerously-skip-permissions
325
- save_session_state "$(tail -1 "${HOME}/.claude/history.jsonl" 2>/dev/null | grep -oP '"sessionId":"[^"]+"' | cut -d'"' -f4)"
326
- ;;
327
- s|S)
328
- # Skip - just shell
329
- echo ""
330
- echo " Okay, just a shell. Type 'claude' or 'cr' when you want Claude."
331
- ;;
332
- *)
333
- echo ""
334
- echo " Unknown option. Type 'claude' to start manually."
335
- ;;
336
- esac
387
+ echo " Unknown option. Please choose c, r, n, l, or s."
388
+ sleep 1
389
+ ;;
390
+ esac
391
+ done
337
392
  }
338
393
 
339
394
  # Aliases for manual use
@@ -353,11 +408,17 @@ export TERMINAL_ID
353
408
 
354
409
  # Reset prompt marker and show menu
355
410
  claude_menu() {
356
- local prompt_marker="${REPLIT_TOOLS}/.prompt-shown-${TERMINAL_ID}"
411
+ # Clear the marker that claude_prompt uses to prevent re-showing
412
+ # This allows manual invocation to always show the menu
413
+ local prompt_marker="${REPLIT_TOOLS}/.prompt-active-${TERMINAL_ID}-$$"
357
414
  rm -f "$prompt_marker" 2>/dev/null
415
+ # Also clear any old-style markers for this terminal
416
+ rm -f "${REPLIT_TOOLS}/.prompt-shown-${TERMINAL_ID}" 2>/dev/null
417
+ rm -f "${REPLIT_TOOLS}/.prompt-active-${TERMINAL_ID}-"* 2>/dev/null
358
418
  claude_prompt
359
419
  }
360
420
  alias claude-menu='claude_menu'
421
+ alias cm='claude_menu'
361
422
 
362
423
  if [ "${CLAUDE_NO_PROMPT}" != "true" ]; then
363
424
  claude_prompt
@@ -21,7 +21,8 @@ WORKSPACE="/home/runner/workspace"
21
21
  REPLIT_TOOLS="${WORKSPACE}/.replit-tools"
22
22
 
23
23
  # Allow env vars to override (for custom config locations)
24
- CLAUDE_PERSISTENT="${CLAUDE_CONFIG_DIR:-${REPLIT_TOOLS}/.claude-persistent}"
24
+ # Note: Credentials are at workspace root (.claude-persistent), NOT inside .replit-tools
25
+ CLAUDE_PERSISTENT="${CLAUDE_CONFIG_DIR:-${WORKSPACE}/.claude-persistent}"
25
26
  CLAUDE_VERSIONS="${REPLIT_TOOLS}/.claude-versions"
26
27
  LOGS_DIR="${REPLIT_TOOLS}/.logs"
27
28
  SCRIPTS_DIR="${REPLIT_TOOLS}/scripts"