Skip to content

.claude/session-start-global-deny.sh rewrites git remotes across all sibling repos #63

@amavashev

Description

@amavashev

Issue

The session-start hook at `.claude/session-start-global-deny.sh` (mirrored across Cycles Java/non-Java repos) iterates `/home/user/*` and rewrites the `origin` remote URL of every sibling repo with a github.com remote — not just the current checkout.

Relevant lines:

```bash

Detect local git proxy: look for the proxy in any sibling repo's remote URL

for dir in /home/user/*/; do
...
done

if [ -n "$PROXY_BASE" ]; then
for dir in /home/user/*/; do
...
git -C "$dir" remote set-url origin "$new_url" 2>/dev/null || true
done
fi
```

This is intentional for Claude Code multi-repo sessions (where multiple repos are cloned under /home/user/ and all need to use the same local git proxy). But the script lives in a per-repo `.claude/` directory and is triggered on every session start, which makes the multi-repo mutation surprising to anyone reading just the one repo.

Tradeoff

The current behavior is correct for the multi-repo Claude Code workflow. The concern is:

  1. Surprise factor: a repo-local hook mutating unrelated repos.
  2. Reproducibility: developers running Claude Code locally may not realize their sibling repos' remotes got rewritten until the rewrite produces a confusing push failure later.

Proposed fix

Pick one:

  1. Document loudly + add an opt-out env var. Add a clear comment at the top of the script explaining the multi-repo scope and check for `CYCLES_CLAUDE_SKIP_REMOTE_REWRITE` to bail out.
  2. Restrict to current checkout. Detect the script's own repo via `$(git rev-parse --show-toplevel)` and only rewrite that one. Requires Claude Code session orchestration to install the hook in every cloned repo, but is more predictable per-repo.
  3. Move to global `~/.claude/` hook. Take the script out of per-repo `.claude/` directories and install it once in `~/.claude/` where its multi-repo scope makes sense as an environment-level operation rather than a repo-level one.

Recommendation: option 3 is the cleanest separation of concerns, but requires coordinated removal from every per-repo `.claude/`. Option 1 is the cheapest fix that addresses the surprise factor.

Affected repos

Every Cycles repo with a `.claude/` directory that includes this hook (currently mirrored across at least cycles-spring-boot-starter, cycles-spring-ai-starter, and likely the server repos).

Surface

Original review finding from PR #1 on cycles-spring-ai-starter (2026-05-12). Tracking org-wide because the same script lives in every Cycles repo's `.claude/` directory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions