luv-cli 0.0.16__tar.gz → 0.0.17__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: luv-cli
3
- Version: 0.0.16
3
+ Version: 0.0.17
4
4
  Summary: Launch Claude Code agents on GitHub repos with isolated workspaces and optional Docker dev environments
5
5
  Project-URL: Homepage, https://github.com/exospherehost/luv
6
6
  Project-URL: Repository, https://github.com/exospherehost/luv
@@ -87,6 +87,7 @@ All workspaces live under `~/prs/`. The number comes from the repo's GitHub issu
87
87
  | `luv [org/]<repo> -pr <number> [prompt]` | Open a PR by repo + number |
88
88
  | `luv --clean` | Delete workspaces where the branch is fully pushed/merged |
89
89
  | `luv --clean -f` | Force delete all workspaces |
90
+ | `luv --clean --safe -f` | Force delete only workspaces older than 24h |
90
91
 
91
92
  ### Flags
92
93
 
@@ -98,6 +99,7 @@ All workspaces live under `~/prs/`. The number comes from the repo's GitHub issu
98
99
  | `-nit` | Non-interactive: run `claude -p <prompt>` and exit (no REPL); streams `stream-json` events to stdout |
99
100
  | `-e` | Env: pass `LUV_*` environment variables (with prefix stripped) into the session |
100
101
  | `-f`, `--force` | Skip safety checks (with `--clean`) |
102
+ | `--safe` | With `--clean -f`, only delete workspaces older than 24h (mtime) |
101
103
 
102
104
  ## Docker dev environments
103
105
 
@@ -157,7 +159,7 @@ Docker mode works with all flags: `-n` opens a bash shell in the container, `-r`
157
159
  - No unpushed commits
158
160
  - If the remote branch is gone, verifies the PR was merged and local HEAD matches
159
161
 
160
- Use `luv --clean -f` to skip all safety checks and delete everything.
162
+ Use `luv --clean -f` to skip all safety checks and delete everything. Add `--safe` (i.e. `luv --clean --safe -f`) to restrict force-delete to workspaces whose folder mtime is older than 24 hours, leaving recently-touched workspaces alone.
161
163
 
162
164
  ## Configuration
163
165
 
@@ -64,6 +64,7 @@ All workspaces live under `~/prs/`. The number comes from the repo's GitHub issu
64
64
  | `luv [org/]<repo> -pr <number> [prompt]` | Open a PR by repo + number |
65
65
  | `luv --clean` | Delete workspaces where the branch is fully pushed/merged |
66
66
  | `luv --clean -f` | Force delete all workspaces |
67
+ | `luv --clean --safe -f` | Force delete only workspaces older than 24h |
67
68
 
68
69
  ### Flags
69
70
 
@@ -75,6 +76,7 @@ All workspaces live under `~/prs/`. The number comes from the repo's GitHub issu
75
76
  | `-nit` | Non-interactive: run `claude -p <prompt>` and exit (no REPL); streams `stream-json` events to stdout |
76
77
  | `-e` | Env: pass `LUV_*` environment variables (with prefix stripped) into the session |
77
78
  | `-f`, `--force` | Skip safety checks (with `--clean`) |
79
+ | `--safe` | With `--clean -f`, only delete workspaces older than 24h (mtime) |
78
80
 
79
81
  ## Docker dev environments
80
82
 
@@ -134,7 +136,7 @@ Docker mode works with all flags: `-n` opens a bash shell in the container, `-r`
134
136
  - No unpushed commits
135
137
  - If the remote branch is gone, verifies the PR was merged and local HEAD matches
136
138
 
137
- Use `luv --clean -f` to skip all safety checks and delete everything.
139
+ Use `luv --clean -f` to skip all safety checks and delete everything. Add `--safe` (i.e. `luv --clean --safe -f`) to restrict force-delete to workspaces whose folder mtime is older than 24 hours, leaving recently-touched workspaces alone.
138
140
 
139
141
  ## Configuration
140
142
 
@@ -6,6 +6,7 @@ import shutil
6
6
  import subprocess
7
7
  import sys
8
8
  import tempfile
9
+ import time
9
10
  from pathlib import Path
10
11
 
11
12
  LUV_DIR = Path.home() / ".luv"
@@ -391,7 +392,10 @@ def launch(clone_dir: Path, prompt: str | None, plan_mode: bool = False,
391
392
  os.execv(claude_bin, [claude_bin] + common_flags + mode_flags + initial_args)
392
393
 
393
394
 
394
- def cmd_clean(force: bool = False) -> None:
395
+ SAFE_AGE_SECONDS = 24 * 3600
396
+
397
+
398
+ def cmd_clean(force: bool = False, safe: bool = False) -> None:
395
399
  """Scan ~/prs/ and delete fully-pushed, clean work folders."""
396
400
  if not PRS_DIR.exists():
397
401
  print("luv: nothing to clean (~/prs/ does not exist)")
@@ -399,6 +403,7 @@ def cmd_clean(force: bool = False) -> None:
399
403
 
400
404
  cleaned: list[str] = []
401
405
  skipped: list[tuple[str, str]] = []
406
+ now = time.time()
402
407
 
403
408
  for entry in sorted(PRS_DIR.iterdir()):
404
409
  if not entry.is_dir():
@@ -409,6 +414,9 @@ def cmd_clean(force: bool = False) -> None:
409
414
  continue # doesn't match {repo}-{number} — skip silently
410
415
 
411
416
  if force:
417
+ if safe and (now - entry.stat().st_mtime) < SAFE_AGE_SECONDS:
418
+ skipped.append((entry.name, "younger than 24h (--safe)"))
419
+ continue
412
420
  shutil.rmtree(entry)
413
421
  cleaned.append(entry.name)
414
422
  continue
@@ -589,8 +597,9 @@ def main() -> None:
589
597
  plan_mode = "-p" in args
590
598
  non_interactive = "-nit" in args
591
599
  force = "-f" in args or "--force" in args
600
+ safe = "--safe" in args
592
601
  env_mode = "-e" in args
593
- args = [a for a in args if a not in ("-n", "-r", "-e", "-f", "--force", "-p", "-nit")]
602
+ args = [a for a in args if a not in ("-n", "-r", "-e", "-f", "--force", "-p", "-nit", "--safe")]
594
603
  extra_env = collect_luv_env() if env_mode else {}
595
604
 
596
605
  if not args or args[0] in ("-h", "--help"):
@@ -604,6 +613,7 @@ Flags:
604
613
  -nit non-interactive: run claude -p <prompt> and exit (no REPL)
605
614
  -e env: pass LUV_* environment variables (with prefix stripped) into the session
606
615
  -f, --force (with --clean) skip safety checks and delete all work folders
616
+ --safe (with --clean -f) only delete folders older than 24h
607
617
 
608
618
  Commands:
609
619
  luv --init configure default GitHub org
@@ -613,7 +623,7 @@ Commands:
613
623
  luv [org/]<repo> -pr <number> [prompt] open a GitHub PR by repo + number
614
624
  luv [org/]<repo> -n open shell in latest local clone
615
625
  luv [org/]<repo> -r resume Claude in latest local clone
616
- luv --clean [-f] delete fully-pushed work folders
626
+ luv --clean [-f] [--safe] delete fully-pushed work folders
617
627
 
618
628
  Org resolution:
619
629
  Explicit org/repo overrides the default. Run 'luv --init' to set a default.
@@ -625,8 +635,11 @@ Docker:
625
635
  "dev-environment" service. Torn down automatically on exit.""")
626
636
  sys.exit(0)
627
637
 
638
+ if safe and (args[0] != "--clean" or not force):
639
+ die("--safe only works with --clean -f")
640
+
628
641
  if args[0] == "--clean":
629
- cmd_clean(force=force)
642
+ cmd_clean(force=force, safe=safe)
630
643
  return
631
644
 
632
645
  if args[0] == "--init":
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "luv-cli"
7
- version = "0.0.16"
7
+ version = "0.0.17"
8
8
  description = "Launch Claude Code agents on GitHub repos with isolated workspaces and optional Docker dev environments"
9
9
  requires-python = ">=3.10"
10
10
  license = "MIT"
File without changes
File without changes
File without changes