# ariesq/gh-safe-repo architecture

> Architecture diagram of the GitHub repository ariesq/gh-safe-repo, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-17). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ariesq/gh-safe-repo
- Repository: https://github.com/ariesq/gh-safe-repo

## Overview

1. **Project shape**
   - `gh-safe-repo` is a Python CLI tool, not a web service.
   - The runtime is the Python standard library only; there are no runtime third-party dependencies.
   - The main external boundaries are GitHub’s API, local git, and optional secret-scanning tooling.

2. **Top-level control flow**
   - The CLI exposes three entry points: `create`, `fix`, and `scan`.
   - `create` and `fix` both build a “plan” from desired vs current state, print that plan, then optionally apply it.
   - `scan` is standalone and local-only; it never talks to GitHub.

3. **Command layer**
   - `gh_safe_repo/cli.py` dispatches to subcommand handlers in `gh_safe_repo/commands/`.
   - `_common.py` holds shared CLI context, formatting, confirmation, and plan rendering logic.
   - `create.py`, `fix.py`, and `scan.py` orchestrate workflows but do not directly own the per-setting logic.

4. **Configuration boundary**
   - Configuration is loaded before command execution and merged with CLI overrides.
   - The precedence is explicit config path, local `./gh-safe-repo.ini`, then user-level XDG config, with built-in defaults as the fallback.
   - Configuration drives repository defaults, branch/tag protection behavior, security settings, scanner behavior, and git transport mode.

5. **Settings-as-plugins architecture**
   - Repository settings are split into plugins under `gh_safe_repo/plugins/`.
   - Each plugin owns one concern area: repository basics, Actions, branch protection, security, tag protection.
   - The plugins share the same lifecycle: fetch current state, diff against desired state, return plan changes, then apply only real deltas.

6. **Plan / diff model**
   - The tool’s central abstraction is a plan made of changes such as add, update, delete, or skip.
   - `create` usually compares against GitHub defaults; `fix` compares against an existing repository’s live state.
   - Dry-run and JSON output are both derived from this same plan model, so preview and execution stay consistent.

7. **GitHub API integration**
   - All GitHub API calls are executed through `gh api` in subprocesses, rather than through a native GitHub SDK.
   - Authentication is inherited from `GITHUB_TOKEN` or `gh auth token`, and the token is passed to child processes as `GH_TOKEN`.
   - This keeps credential handling outside the application code and makes GitHub the main remote system boundary.

8. **Repository creation and post-create mutation flow**
   - `create` first creates the repository, then applies repository settings, Actions policy, security settings, and protection rules.
   - Branch protection and tag protection are applied after code push when needed so the target refs exist.
   - In public repos or paid-plan private repos, protection and security features are enabled; on free private repos, unsupported items are surfaced as skipped in the plan.

9. **Local git transport path**
   - The `--local` and `--from` workflows introduce a separate git transport boundary via `gh_safe_repo/git_transport.py`.
   - These flows verify credentials up front, then use local clone/push operations to move code, not the GitHub API.
   - The tool supports both mirror-style repo transfer and push-all-tags style local publication, with the original repo’s upstream configured after push for convenience.

10. **Pre-flight security scanner**
   - `gh_safe_repo/security_scanner.py` is a local scanning subsystem used by `scan` and automatically before risky publish flows.
   - It prefers native `truffleHog`, can fall back to containerized `truffleHog` via Docker/Podman, and finally a regex-based fallback.
   - It detects secrets, banned strings, AI context files, emails, large files, and TODO/FIXME markers, with interactive approval before code ever reaches GitHub.

11. **User-visible safety model**
   - The architecture is intentionally conservative: it previews changes, skips unsupported features instead of failing silently, and avoids no-op API calls.
   - `fix` is audit-first; it can show drift without changing anything.
   - `create` is safety-first; when code import is involved, it scans locally before pushing.

12. **Supporting assets**
   - `tests/` mirrors the architecture with unit tests for config, diffing, transport, GitHub client behavior, plugins, and scanner logic, plus end-to-end CLI coverage.
   - `docs/` captures the design rationale, API discoveries, manual test cases, and security research that shaped the current behavior.

Main entry points: [`gh_safe_repo/github_client.py`](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/github_client.py) (GH client), [`tests`](https://github.com/ariesq/gh-safe-repo/tree/master/tests) (Tests), [`gh_safe_repo/commands/create.py`](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/create.py) (Create), [`gh_safe_repo/plugins/base.py`](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/base.py) (Plugin base)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_cli["CLI flow"]
  node_cli_main["CLI<br/>entrypoint<br/>[cli.py]"]
  node_cmd_common["Shared cmd<br/>command support<br/>[_common.py]"]
  node_cmd_create["Create<br/>workflow<br/>[create.py]"]
  node_cmd_fix["Fix<br/>workflow<br/>[fix.py]"]
  node_cmd_scan["Scan<br/>workflow<br/>[scan.py]"]
end

subgraph group_core["Core engine"]
  node_config_mgr["Config<br/>[config_manager.py]"]
  node_diff_model["Plan diff<br/>planning model<br/>[diff.py]"]
end

subgraph group_plugins["Settings plugins"]
  node_plugin_base["Plugin base<br/>plugin framework<br/>[base.py]"]
  node_plugin_repo["Repository<br/>setting plugin<br/>[repository.py]"]
  node_plugin_actions["Actions<br/>setting plugin<br/>[actions.py]"]
  node_plugin_branch["Branch prot.<br/>setting plugin"]
  node_plugin_security["Security<br/>setting plugin<br/>[security.py]"]
  node_plugin_tag["Tag prot.<br/>setting plugin<br/>[tag_protection.py]"]
end

subgraph group_boundaries["External boundaries"]
  node_gh_client["GH client<br/>api adapter<br/>[github_client.py]"]
  node_git_transport["Git transport<br/>git boundary<br/>[git_transport.py]"]
  node_scanner["Scanner"]
end

subgraph group_support["Support assets"]
  node_tests["Tests<br/>validation suite"]
  node_docs["Docs"]
end

node_cli_main -->|"dispatch"| node_cmd_create
node_cli_main -->|"dispatch"| node_cmd_fix
node_cli_main -->|"dispatch"| node_cmd_scan
node_cmd_create -->|"uses"| node_cmd_common
node_cmd_fix -->|"uses"| node_cmd_common
node_cmd_scan -->|"runs"| node_scanner
node_cmd_create -->|"loads"| node_config_mgr
node_cmd_fix -->|"loads"| node_config_mgr
node_cmd_scan -->|"loads"| node_config_mgr
node_cmd_create -->|"builds"| node_diff_model
node_cmd_fix -->|"builds"| node_diff_model
node_diff_model -->|"drives"| node_plugin_base
node_plugin_base -->|"implements"| node_plugin_repo
node_plugin_base -->|"implements"| node_plugin_actions
node_plugin_base -->|"implements"| node_plugin_branch
node_plugin_base -->|"implements"| node_plugin_security
node_plugin_base -->|"implements"| node_plugin_tag
node_plugin_repo -->|"queries"| node_gh_client
node_plugin_actions -->|"queries"| node_gh_client
node_plugin_branch -->|"queries"| node_gh_client
node_plugin_security -->|"queries"| node_gh_client
node_plugin_tag -->|"queries"| node_gh_client
node_cmd_create -->|"optional"| node_git_transport
node_cmd_create -->|"preflight"| node_scanner
node_gh_client -.->|"token flow"| node_git_transport
node_tests -.->|"covers"| node_cli_main
node_tests -.->|"covers"| node_config_mgr
node_tests -.->|"covers"| node_diff_model
node_tests -.->|"covers"| node_git_transport
node_tests -.->|"covers"| node_gh_client
node_tests -.->|"covers"| node_scanner
node_docs -.->|"documents"| node_config_mgr
node_docs -.->|"documents"| node_gh_client
node_docs -.->|"documents"| node_scanner

click node_cli_main "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/cli.py"
click node_cmd_common "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/_common.py"
click node_cmd_create "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/create.py"
click node_cmd_fix "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/fix.py"
click node_cmd_scan "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/scan.py"
click node_config_mgr "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/config_manager.py"
click node_diff_model "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/diff.py"
click node_gh_client "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/github_client.py"
click node_git_transport "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/git_transport.py"
click node_scanner "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/security_scanner.py"
click node_plugin_base "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/base.py"
click node_plugin_repo "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/repository.py"
click node_plugin_actions "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/actions.py"
click node_plugin_branch "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/branch_protection.py"
click node_plugin_security "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/security.py"
click node_plugin_tag "https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/tag_protection.py"
click node_tests "https://github.com/ariesq/gh-safe-repo/tree/master/tests"
click node_docs "https://github.com/ariesq/gh-safe-repo/tree/master/docs"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cli_main,node_cmd_common,node_cmd_create,node_cmd_fix,node_cmd_scan toneBlue
class node_config_mgr,node_diff_model toneAmber
class node_plugin_base,node_plugin_repo,node_plugin_actions,node_plugin_branch,node_plugin_security,node_plugin_tag toneMint
class node_gh_client,node_git_transport,node_scanner toneRose
class node_tests,node_docs toneIndigo
```

## Components

### CLI flow

Command dispatch and user-facing orchestration

- [CLI](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/cli.py): entrypoint · Dispatches subcommands and argument handling · `gh_safe_repo/cli.py`
- [Shared cmd](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/_common.py): command support · Shared formatting, confirmation, and plan rendering · `gh_safe_repo/commands/_common.py`
- [Create](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/create.py): workflow · Creates a repo plan, prints it, then applies it optionally · `gh_safe_repo/commands/create.py`
- [Fix](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/fix.py): workflow · Diffs live state against desired state and can apply drift fixes · `gh_safe_repo/commands/fix.py`
- [Scan](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/commands/scan.py): workflow · Runs local-only preflight scanning · `gh_safe_repo/commands/scan.py`

### Core engine

Config, planning, and shared runtime logic

- [Config](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/config_manager.py): configuration · Loads defaults, local files, XDG config, and CLI overrides · `gh_safe_repo/config_manager.py`
- [Plan diff](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/diff.py): planning model · Represents add, update, delete, and skip changes · `gh_safe_repo/diff.py`

### Settings plugins

Repository setting subsystems with shared lifecycle

- [Plugin base](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/base.py): plugin framework · Shared lifecycle for fetch, diff, plan, and apply · `gh_safe_repo/plugins/base.py`
- [Repository](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/repository.py): setting plugin · Repository basics and default settings · `gh_safe_repo/plugins/repository.py`
- [Actions](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/actions.py): setting plugin · GitHub Actions policy and repository automation settings · `gh_safe_repo/plugins/actions.py`
- [Branch prot.](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/branch_protection.py): setting plugin · Branch protection rules and related ref policy · `gh_safe_repo/plugins/branch_protection.py`
- [Security](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/security.py): setting plugin · Advanced security and repo security settings · `gh_safe_repo/plugins/security.py`
- [Tag prot.](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/plugins/tag_protection.py): setting plugin · Tag protection rules · `gh_safe_repo/plugins/tag_protection.py`

### External boundaries

GitHub, git, and local security scanning

- [GH client](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/github_client.py): api adapter · Executes GitHub API calls through gh subprocesses · `gh_safe_repo/github_client.py`
- [Git transport](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/git_transport.py): git boundary · Handles local clone, push, mirror, and tag publication flows · `gh_safe_repo/git_transport.py`
- [Scanner](https://github.com/ariesq/gh-safe-repo/blob/master/gh_safe_repo/security_scanner.py): security scanner · Local secret and policy scanning with fallback strategies · `gh_safe_repo/security_scanner.py`

### Support assets

Tests and documentation

- [Tests](https://github.com/ariesq/gh-safe-repo/tree/master/tests): validation suite · Unit and end-to-end coverage for CLI, config, diff, transport, plugins, and scanner · `tests`
- [Docs](https://github.com/ariesq/gh-safe-repo/tree/master/docs): design docs · Architecture notes, research, and manual test guidance · `docs`

## Connections

- CLI → Create: dispatch · Routes create subcommand
- CLI → Fix: dispatch · Routes fix subcommand
- CLI → Scan: dispatch · Routes scan subcommand
- Create → Shared cmd: uses · Shares plan rendering and confirmation
- Fix → Shared cmd: uses · Shares plan rendering and confirmation
- Scan → Scanner: runs · Invokes local scanning workflow
- Create → Config: loads · Builds runtime config before execution
- Fix → Config: loads · Builds runtime config before execution
- Scan → Config: loads · Reads scanner and CLI settings
- Create → Plan diff: builds · Constructs desired-versus-current plan
- Fix → Plan diff: builds · Constructs drift-remediation plan
- Plan diff → Plugin base: drives · Shared plan lifecycle across plugins
- Plugin base → Repository: implements · Repository settings plugin
- Plugin base → Actions: implements · Actions settings plugin
- Plugin base → Branch prot.: implements · Branch protection plugin
- Plugin base → Security: implements · Security settings plugin
- Plugin base → Tag prot.: implements · Tag protection plugin
- Repository → GH client: queries · Reads and mutates GitHub repository state
- Actions → GH client: queries · Reads and mutates GitHub repository state
- Branch prot. → GH client: queries · Reads and mutates GitHub repository state
- Security → GH client: queries · Reads and mutates GitHub repository state
- Tag prot. → GH client: queries · Reads and mutates GitHub repository state
- Create → Git transport: optional · Uses local publish and mirror flows when requested
- Create → Scanner: preflight · Scans local code before risky publish flows
- GH client → Git transport: token flow · Shares inherited GitHub auth with subprocesses
- Tests → CLI: covers · CLI behavior and command wiring
- Tests → Config: covers · Configuration precedence and merging
- Tests → Plan diff: covers · Plan and diff behavior
- Tests → Git transport: covers · Local transport flows
- Tests → GH client: covers · GitHub subprocess integration
- Tests → Scanner: covers · Security scanning behavior
- Docs → Config: documents · Captures configuration and defaults rationale
- Docs → GH client: documents · Captures API discovery and auth architecture
- Docs → Scanner: documents · Captures security research and manual testing
