Skip to content

Instantly share code, notes, and snippets.

@Wumpf
Created March 24, 2026 18:01
Show Gist options
  • Select an option

  • Save Wumpf/97534424d73e7da2931d3ce3ed5841d7 to your computer and use it in GitHub Desktop.

Select an option

Save Wumpf/97534424d73e7da2931d3ce3ed5841d7 to your computer and use it in GitHub Desktop.
Vibe coded script for building `nono` invocations that make the git directory either read-only or read+write
#!/usr/bin/env python3
"""
Launch a command under nono with fine-grained git permissions.
Instead of --allow-cwd (blanket read-write to the entire working directory),
this resolves the git directory (including worktree indirection) and passes
explicit --read / --write flags.
Usage:
nono-git.py [--git-read-only] [--] <command> [args...]
Examples:
nono-git.py -- claude
nono-git.py --git-read-only -- cargo build
nono-git.py --allow-proxy api.anthropic.com -- claude
"""
import os
import shlex
import subprocess
import sys
def git(*args: str) -> str:
"""Run a git command and return its stripped stdout, or None on failure."""
result = subprocess.run(
["git", *args],
capture_output=True,
text=True,
)
if result.returncode != 0:
return None
return result.stdout.strip()
def resolve_git_paths() -> dict:
"""Figure out the worktree root, git dir, and (for worktrees) the shared git dir."""
worktree = git("rev-parse", "--show-toplevel")
if not worktree:
sys.exit("Error: not inside a git repository.")
git_dir = git("-C", worktree, "rev-parse", "--absolute-git-dir")
git_common_dir = git("-C", worktree, "rev-parse", "--path-format=absolute", "--git-common-dir")
# Normalise so comparisons work
git_dir = os.path.realpath(git_dir) if git_dir else None
git_common_dir = os.path.realpath(git_common_dir) if git_common_dir else None
return {
"worktree": worktree,
"git_dir": git_dir,
"git_common_dir": git_common_dir,
}
def parse_args(argv: list[str]) -> tuple[bool, list[str], list[str]]:
"""
Split argv into:
- git_read_only flag
- extra nono flags (anything before --)
- the command to run (everything after --)
"""
git_read_only = False
nono_args = []
command = []
it = iter(argv)
for arg in it:
if arg == "--":
command = list(it)
break
elif arg == "--git-read-only":
git_read_only = True
else:
nono_args.append(arg)
return git_read_only, nono_args, command
def worktree_entries_except_git(worktree: str) -> list[tuple[str, bool]]:
"""List top-level entries in the worktree (excluding .git) as (path, is_dir) tuples."""
entries = []
for name in sorted(os.listdir(worktree)):
if name == ".git":
continue
full = os.path.join(worktree, name)
entries.append((full, os.path.isdir(full)))
return entries
def build_nono_command(paths: dict, git_read_only: bool, nono_args: list[str], command: list[str]) -> list[str]:
"""Assemble the full nono invocation."""
git_flag = "--read" if git_read_only else "--write"
cmd = ["nono", "run"]
# nono distinguishes files (--read-file/--write-file) from dirs (--read/--write)
git_dir_inside_worktree = os.path.isdir(os.path.join(paths["worktree"], ".git"))
if git_read_only and git_dir_inside_worktree:
# Can't use --write on the whole worktree because .git is a subdirectory
# and that would grant write access to it too.
# Instead, list every top-level entry except .git individually.
for path, is_dir in worktree_entries_except_git(paths["worktree"]):
flag = "--write" if is_dir else "--write-file"
cmd += [flag, path]
else:
# Either full access, or .git is external (worktree) so --write on the
# whole tree is safe.
cmd += ["--write", paths["worktree"]]
# Git directory — in a worktree .git is a file, in a normal repo it's a dir
git_dir_flag = git_flag if os.path.isdir(paths["git_dir"]) else f"{git_flag}-file"
cmd += [git_dir_flag, paths["git_dir"]]
# For worktrees the common dir is different from git_dir — grant access too
if paths["git_common_dir"] and paths["git_common_dir"] != paths["git_dir"]:
common_flag = git_flag if os.path.isdir(paths["git_common_dir"]) else f"{git_flag}-file"
cmd += [common_flag, paths["git_common_dir"]]
cmd += nono_args
cmd += ["--"]
cmd += command
return cmd
def confirm(cmd: list[str]) -> bool:
"""Show the command and ask the user to confirm."""
# Group flag+value pairs onto one line, show each on its own indented line
print("Will execute:\n")
print(f" nono run \\")
i = 1 # skip "nono"
i = 2 # skip "nono run"
while i < len(cmd):
arg = cmd[i]
if arg == "--":
# Everything after -- is the command
print(f" -- {shlex.join(cmd[i + 1:])}")
break
elif arg.startswith("--") and i + 1 < len(cmd) and not cmd[i + 1].startswith("-"):
# Flag with a value: print together
print(f" {arg} {shlex.quote(cmd[i + 1])} \\")
i += 2
else:
# Standalone flag
print(f" {arg} \\")
i += 1
print()
try:
answer = input("Proceed? [Y/n] ").strip().lower()
except (EOFError, KeyboardInterrupt):
print()
return False
return answer in ("", "y", "yes")
def main():
git_read_only, nono_args, command = parse_args(sys.argv[1:])
if not command:
print(__doc__.strip())
sys.exit(1)
paths = resolve_git_paths()
cmd = build_nono_command(paths, git_read_only, nono_args, command)
if confirm(cmd):
os.execvp(cmd[0], cmd)
else:
sys.exit("Aborted.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment