luv-cli 0.0.8__tar.gz → 0.0.10__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.
- {luv_cli-0.0.8 → luv_cli-0.0.10}/PKG-INFO +1 -1
- {luv_cli-0.0.8 → luv_cli-0.0.10}/luv/__init__.py +47 -5
- {luv_cli-0.0.8 → luv_cli-0.0.10}/pyproject.toml +1 -1
- {luv_cli-0.0.8 → luv_cli-0.0.10}/.claude/settings.json +0 -0
- {luv_cli-0.0.8 → luv_cli-0.0.10}/.failproofai/policies-config.json +0 -0
- {luv_cli-0.0.8 → luv_cli-0.0.10}/.github/workflows/publish.yml +0 -0
- {luv_cli-0.0.8 → luv_cli-0.0.10}/.gitignore +0 -0
- {luv_cli-0.0.8 → luv_cli-0.0.10}/LICENSE +0 -0
- {luv_cli-0.0.8 → luv_cli-0.0.10}/README.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: luv-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.10
|
|
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
|
|
@@ -145,6 +145,34 @@ def docker_env_flags(env_vars: dict[str, str]) -> list[str]:
|
|
|
145
145
|
return flags
|
|
146
146
|
|
|
147
147
|
|
|
148
|
+
def ensure_failproofai_installed() -> None:
|
|
149
|
+
"""Install failproofai globally via npm — skip if already on PATH."""
|
|
150
|
+
if shutil.which("failproofai") is not None:
|
|
151
|
+
return
|
|
152
|
+
if shutil.which("npm") is None:
|
|
153
|
+
die("'npm' not found in PATH; install Node.js to use failproofai")
|
|
154
|
+
print("luv: installing failproofai globally...")
|
|
155
|
+
r = subprocess.run(["npm", "install", "-g", "failproofai"])
|
|
156
|
+
if r.returncode != 0:
|
|
157
|
+
die("'npm install -g failproofai' failed")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def run_failproofai_project(clone_dir: Path) -> None:
|
|
161
|
+
"""Run failproofai project-scope initialization in the cloned repo.
|
|
162
|
+
|
|
163
|
+
On failure, remove the clone_dir so the next run re-clones and retries
|
|
164
|
+
cleanly instead of short-circuiting to a half-initialized folder.
|
|
165
|
+
"""
|
|
166
|
+
print(f"luv: running failproofai project setup in {clone_dir.name}...")
|
|
167
|
+
r = subprocess.run(
|
|
168
|
+
["npx", "-y", "failproofai", "p", "-i", "all", "--scope", "project"],
|
|
169
|
+
cwd=str(clone_dir),
|
|
170
|
+
)
|
|
171
|
+
if r.returncode != 0:
|
|
172
|
+
shutil.rmtree(clone_dir, ignore_errors=True)
|
|
173
|
+
die("'npx -y failproofai p -i all --scope project' failed")
|
|
174
|
+
|
|
175
|
+
|
|
148
176
|
def ensure_pr_rules() -> None:
|
|
149
177
|
claude_dir = Path.home() / ".claude"
|
|
150
178
|
claude_md = claude_dir / "CLAUDE.md"
|
|
@@ -330,7 +358,9 @@ def resume(clone_dir: Path, extra_env: dict[str, str] = {}) -> None:
|
|
|
330
358
|
r = subprocess.run(base + ["exec", "-it"] + docker_env_flags(extra_env) + ["dev-environment",
|
|
331
359
|
"claude", "--dangerously-skip-permissions",
|
|
332
360
|
"--model", "claude-opus-4-7",
|
|
333
|
-
"--effort", "max", "--resume"
|
|
361
|
+
"--effort", "max", "--resume",
|
|
362
|
+
"--remote-control",
|
|
363
|
+
"--remote-control-session-name-prefix", clone_dir.name])
|
|
334
364
|
sys.exit(r.returncode)
|
|
335
365
|
finally:
|
|
336
366
|
stop_docker(clone_dir, compose_file, project)
|
|
@@ -340,7 +370,9 @@ def resume(clone_dir: Path, extra_env: dict[str, str] = {}) -> None:
|
|
|
340
370
|
die("'claude' not found in PATH")
|
|
341
371
|
os.environ.update(extra_env)
|
|
342
372
|
os.execv(claude_bin, [claude_bin, "--dangerously-skip-permissions",
|
|
343
|
-
"--model", "claude-opus-4-7", "--effort", "max", "--resume"
|
|
373
|
+
"--model", "claude-opus-4-7", "--effort", "max", "--resume",
|
|
374
|
+
"--remote-control",
|
|
375
|
+
"--remote-control-session-name-prefix", clone_dir.name])
|
|
344
376
|
|
|
345
377
|
|
|
346
378
|
def launch(clone_dir: Path, prompt: str | None, extra_env: dict[str, str] = {}) -> None:
|
|
@@ -353,7 +385,8 @@ def launch(clone_dir: Path, prompt: str | None, extra_env: dict[str, str] = {})
|
|
|
353
385
|
common_flags = ["--dangerously-skip-permissions",
|
|
354
386
|
"--model", "claude-opus-4-7",
|
|
355
387
|
"--effort", "max",
|
|
356
|
-
"--remote-control"
|
|
388
|
+
"--remote-control",
|
|
389
|
+
"--remote-control-session-name-prefix", clone_dir.name]
|
|
357
390
|
if prompt:
|
|
358
391
|
mode_flags = ["--permission-mode", "plan"]
|
|
359
392
|
initial_args = [prompt]
|
|
@@ -517,6 +550,8 @@ def open_existing(org: str, repo: str, number: int, prompt: str | None, nav_mode
|
|
|
517
550
|
if r.returncode != 0:
|
|
518
551
|
die(f"git checkout {branch} failed (exit {r.returncode})")
|
|
519
552
|
|
|
553
|
+
run_failproofai_project(clone_dir)
|
|
554
|
+
|
|
520
555
|
print(f"luv: ready — {clone_dir.name}, branch {branch}")
|
|
521
556
|
ensure_pr_rules()
|
|
522
557
|
if nav_mode:
|
|
@@ -559,6 +594,8 @@ def open_pr(org: str, repo: str, number: int, prompt: str | None, nav_mode: bool
|
|
|
559
594
|
if r.returncode != 0:
|
|
560
595
|
die(f"git checkout {branch} failed (exit {r.returncode})")
|
|
561
596
|
|
|
597
|
+
run_failproofai_project(clone_dir)
|
|
598
|
+
|
|
562
599
|
print(f"luv: ready — {clone_dir.name}, branch {branch}")
|
|
563
600
|
ensure_pr_rules()
|
|
564
601
|
if nav_mode:
|
|
@@ -617,6 +654,8 @@ Docker:
|
|
|
617
654
|
cmd_init()
|
|
618
655
|
return
|
|
619
656
|
|
|
657
|
+
ensure_failproofai_installed()
|
|
658
|
+
|
|
620
659
|
# luv -l <PR URL>
|
|
621
660
|
if args[0] == "-l":
|
|
622
661
|
if len(args) < 2:
|
|
@@ -706,13 +745,16 @@ Docker:
|
|
|
706
745
|
if r.returncode != 0:
|
|
707
746
|
die(f"git checkout -b failed (exit {r.returncode})")
|
|
708
747
|
|
|
709
|
-
# 6.
|
|
748
|
+
# 6. Run failproofai project setup in the fresh clone
|
|
749
|
+
run_failproofai_project(clone_dir)
|
|
750
|
+
|
|
751
|
+
# 7. Ensure PR rules in ~/.claude/CLAUDE.md and bypass-permissions default
|
|
710
752
|
ensure_pr_rules()
|
|
711
753
|
ensure_default_permission_mode()
|
|
712
754
|
|
|
713
755
|
print(f"luv: ready — {clone_dir.name}, branch {branch}")
|
|
714
756
|
|
|
715
|
-
#
|
|
757
|
+
# 8. Launch claude, resume session, or open shell (replace this process)
|
|
716
758
|
if nav_mode:
|
|
717
759
|
navigate(clone_dir, extra_env=extra_env)
|
|
718
760
|
elif resume_mode:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "luv-cli"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.10"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|