From d51b8c63a997e69768205eab64d7722776fcdcbf Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 8 Oct 2026 19:51:39 +0000 Subject: [PATCH 1/3] docs: keep private repository names out of public posts while still reporting the work done there --- AGENTS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index ef7fe86d..8f7fab62 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -75,6 +75,10 @@ This project is a Copier template used to generate other copier templates. It is - Before saving any memory or adding any rule, explicitly ask the user whether the concept should be: (1) added to AGENTS.md as a general rule applicable across all projects, (2) added to AGENTS.md as a rule specific to this project, or (3) stored as a temporary local memory only relevant to the current active work. The devcontainer environment is ephemeral, so local memory files are rarely the right choice. +## Public Repositories + +- Before posting to a repository (PR or issue text, comments, commit messages, file contents), check its visibility (`gh repo view / --json visibility`). In a public repository, never name, link to, or quote a private repository. Still say when relevant work happened in one, such as testing in a private repo that depends on this one, but anonymize it ("tested in a private repo") and give only the details needed to make the point. + ## Tooling - Before hand-assembling a multi-step workflow, run `task --list` — it is probably already a task. Definitions live in `.config/taskfiles/`; the root `Taskfile.yaml` only includes them. From 467862dd244f59ba2f45fc32b28621a59edad206 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 8 Oct 2026 20:49:56 +0000 Subject: [PATCH 2/3] build: close permission gaps around the GitHub API, repo changes and localhost curl - Deny gh api, gh auth token and gh auth status -t/--show-token: raw API access or the token itself gets around every other gh rule. Scripts that need the API, like the address-pr-comments skill, call it themselves. - Deny the gh repo subcommands that create or change repositories so they take a deliberate run with `!`. Fork still prompts, and view is allowed because AGENTS.md has Claude check repository visibility with it. - Remove the localhost curl allow rules. Their trailing wildcard also matched other hosts, extra URLs, uploads and file writes, and allowed commands skip auto mode's classifier, which now reviews every curl. --- .claude/settings/permissions/bash.jsonc | 58 ++++++++----------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/.claude/settings/permissions/bash.jsonc b/.claude/settings/permissions/bash.jsonc index ccf90bcb..f354625c 100644 --- a/.claude/settings/permissions/bash.jsonc +++ b/.claude/settings/permissions/bash.jsonc @@ -54,44 +54,7 @@ "Bash(gh search *)", "Bash(gh pr view *)", "Bash(gh pr diff *)", - // Local app interaction - // Claude currently has terrible support for this: https://github.com/anthropics/claude-code/issues/338 using `:*` as a pattern is not allowed (doesn't error, just doesn't really work), so have to specify _something_ between the colon and asterisk. - "Bash(curl http://localhost:1*)", - "Bash(curl http://localhost:2*)", - "Bash(curl http://localhost:3*)", - "Bash(curl http://localhost:4*)", - "Bash(curl http://localhost:5*)", - "Bash(curl http://localhost:6*)", - "Bash(curl http://localhost:7*)", - "Bash(curl http://localhost:8*)", - "Bash(curl http://localhost:9*)", - "Bash(curl -s http://localhost:1*)", - "Bash(curl -s http://localhost:2*)", - "Bash(curl -s http://localhost:3*)", - "Bash(curl -s http://localhost:4*)", - "Bash(curl -s http://localhost:5*)", - "Bash(curl -s http://localhost:6*)", - "Bash(curl -s http://localhost:7*)", - "Bash(curl -s http://localhost:8*)", - "Bash(curl -s http://localhost:9*)", - "Bash(curl \"http://localhost:1*)", - "Bash(curl \"http://localhost:2*)", - "Bash(curl \"http://localhost:3*)", - "Bash(curl \"http://localhost:4*)", - "Bash(curl \"http://localhost:5*)", - "Bash(curl \"http://localhost:6*)", - "Bash(curl \"http://localhost:7*)", - "Bash(curl \"http://localhost:8*)", - "Bash(curl \"http://localhost:9*)", - "Bash(curl -s \"http://localhost:1*)", - "Bash(curl -s \"http://localhost:2*)", - "Bash(curl -s \"http://localhost:3*)", - "Bash(curl -s \"http://localhost:4*)", - "Bash(curl -s \"http://localhost:5*)", - "Bash(curl -s \"http://localhost:6*)", - "Bash(curl -s \"http://localhost:7*)", - "Bash(curl -s \"http://localhost:8*)", - "Bash(curl -s \"http://localhost:9*)", + "Bash(gh repo view *)", // AGENTS.md has Claude check repo visibility with it before posting // Misc "Bash(amp *)", "Bash(atuin *)", @@ -126,7 +89,7 @@ ], "ask": [ // let's hold off before we let it use the github CLI in any free running allow mode...I don't want it somehow approving PRs with the user's credentials - "Bash(gh repo *)", + "Bash(gh repo fork *)", "Bash(gh release *)", "Bash(gh secret *)", "Bash(gh ruleset *)", @@ -146,6 +109,23 @@ "Bash(gh pr ready *)", "Bash(gh pr review *)", "Bash(gh pr update-branch *)", + // Raw API access and the token itself would let Claude get around every gh rule in this file. Scripts that need the API (like the address-pr-comments skill) are reviewed and run gh api themselves. + "Bash(gh api *)", + "Bash(gh auth token*)", + "Bash(gh auth status *-t*)", // -t / --show-token prints the token + // Creating or changing repositories should be a deliberate human step, so run these yourself with `!` + "Bash(gh repo archive *)", + "Bash(gh repo autolink create *)", + "Bash(gh repo autolink new *)", + "Bash(gh repo autolink delete *)", + "Bash(gh repo create *)", + "Bash(gh repo new *)", + "Bash(gh repo delete *)", + "Bash(gh repo deploy-key *)", + "Bash(gh repo edit *)", + "Bash(gh repo rename *)", + "Bash(gh repo sync *)", + "Bash(gh repo unarchive *)", // Task must run the repo's own taskfiles, which are the reviewed ones. These flags are the only ways to point it elsewhere (there is no environment variable equivalent -- https://github.com/go-task/task/issues/1721 was closed as a duplicate with nothing implemented), and `/tmp` is writable without a prompt, so without these denials `Bash(task *)` would be an allow-anything entry. "Bash(task -t *)", "Bash(task --taskfile *)", From 513789a70598711c65c382dc69c37f4c3a9335be Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Tue, 13 Oct 2026 10:17:57 +0000 Subject: [PATCH 3/3] clone --- .claude/settings/permissions/bash.jsonc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.claude/settings/permissions/bash.jsonc b/.claude/settings/permissions/bash.jsonc index f354625c..573bfa6a 100644 --- a/.claude/settings/permissions/bash.jsonc +++ b/.claude/settings/permissions/bash.jsonc @@ -54,7 +54,8 @@ "Bash(gh search *)", "Bash(gh pr view *)", "Bash(gh pr diff *)", - "Bash(gh repo view *)", // AGENTS.md has Claude check repo visibility with it before posting + "Bash(gh repo view *)", + "Bash(gh repo clone *)", // Misc "Bash(amp *)", "Bash(atuin *)",