
安全なデフォルト設定を自動適用してGitHubリポジトリを作成します。作成後の5分間の設定チェックリストを1つのコマンドに置き換えます。``` gh-safe-repo create <owner/repo>
Branch protection、immutable tags、Dependabot、制限されたActions権限、push protection付きのsecret scanning、無効化されたwikiとprojects — これらはすべて、最初のコードを書く前に設定されます。
gh-safe-repoは活発に開発中です。新しいリポジトリを安全なデフォルト設定で作成するユースケースには適しています。CLIオプションをユーザーの期待に沿うよう改良中です。リリースを実施し、CI/CDを確立するまでは、破壊的な変更がある可能性があります。✌️
---
## Table of Contents
- [なぜ](#why)
- [変更内容](#what-it-changes)
- [必要条件](#requirements)
- [インストール](#installation)
- [クイックスタート](#quick-start)
- [CLIリファレンス](#cli-reference)
- [ドライラン / プラン出力](#dry-run--plan-output)
- [修正モード(既存リポジトリの監査)](#fix-mode-audit-existing-repos)
- [リポジトリのミラーリング (`--from`)](#mirroring-repos---from)
- [ローカルディレクトリからのリポジトリ作成 (`--local`)](#creating-a-repo-from-a-local-directory---local)
- [事前セキュリティスキャナー](#pre-flight-security-scanner)
- [スタンドアロンスキャン](#standalone-scan)
- [偽陽性の抑制](#suppressing-false-positives)
- [設定](#configuration)
- [GitHubプランの制限](#github-plan-limitations)
- [動作仕様](#how-it-works)
- [開発](#development)
---
## なぜ
GitHubのデフォルトのリポジトリ設定は、発見可能性と柔軟性のために最適化されており、セキュリティは考慮されていません。新しいリポジトリは、以下の設定で作成されます:
- WikiとProjectsが有効(未使用でも攻撃対象になる)
- マージコミットが許可(履歴が乱れるが、主な懸念ではない)
- ブランチ保護なし(書き込み権限のある人は誰でも`main`に直接プッシュ可能)
- Dependabotアラートなし
- リポジトリへの書き込み権限を持つGitHub Actions
- Actionsがプルリクエストを承認可能
これらを手動で修正するにはリポジトリごとに数分かかり、忘れがちです。`gh-safe-repo`は、意見が反映された実用的なデフォルト設定を一度に適用し、計画のプレビューで何が変更されるかを事前に確認できます。
---
## 変更内容
### リポジトリ設定
| 設定 | GitHubデフォルト | 安全なデフォルト | 備考 |
|---|---|---|---|
| 可視性 | Public | **Private** | `--public` で上書き可能 |
| Wiki | 有効 | **無効** | |
| Projects | 有効 | **無効** | |
| Issues | 有効 | 有効 | |
| マージ時にブランチを削除 | オフ | オフ | 自動クリーンアップには設定で`true`に設定 |
| マージコミットを許可 | オン | オン | スカッシュのみにするには設定で`false`に設定 |
| スカッシュマージを許可 | オン | オン | |
| リベースマージを許可 | オン | オン | |
### GitHub Actions
| 設定 | GitHubデフォルト | 安全なデフォルト |
|---|---|---|
| 許可されるアクション | すべて | **選択済み**(GitHub所有+確認済み作成者;カスタマイズ可能) |
| デフォルトのワークフロー権限 | 読み取り/書き込み | **読み取り専用** |
| ActionsがPRを承認可能 | はい | **いいえ** |
| SHAピン留めを要求 | いいえ | **はい**(ワークフローはアクションをコミットSHAにピン留めする必要があり、可変タグは不可) |
| フォークPR承認ポリシー | GitHub初めてのコントリビューター | **すべての外部コントリビューター** — フォークPRのワークフローがCIを実行する前に承認が必要。オプション:GitHubアカウントのみ新規(GitHubデフォルト)、リポジトリ初めてのコントリビューター、またはすべてのフォークPR(最も安全) |
### ブランチ保護(パブリックリポジトリ、または有料プランのリポジトリ)
| ルール | 値 |
|---|---|
| マージ前にプルリクエストを要求 | はい |
| 必須の承認レビュー | 1 |
| プッシュ時に古いレビューを却下 | はい |
| 会話の解決を要求 | はい |
| フォースプッシュを許可 | いいえ |
| ブランチ削除を許可 | いいえ |
| 管理者に強制 | いいえ(オーナーツールのプッシュを許可) |
ブランチ保護は、デフォルトでは**Rulesets API**を介して適用されます(`use_rulesets = true`):単一の`gh-safe-repo defaults`ルールセットがすべての設定済みブランチをカバーし、「管理者はバイパス可能」を従来の`enforce_admins`フラグではなくバイパスアクターで表現します。従来のクラシックなブランチごとのパスには`use_rulesets = false`を設定します(1リリースサイクル維持)。
**既存リポジトリのクラシック保護からの移行:** `fix`がリポジトリにクラシックブランチ保護を検出した場合、`--migrate-branch-protection`を指定しない限り、ルールセットへの変換を拒否します。クラシックのみのルールには、このツールが構築するルールセットに相当するものがないため、サイレントに削除されます。既知のギャップ:
- `required_status_checks` — 必須CIチェックはルールセット本体でモデル化されていません。
- `restrictions`(ユーザー/チームによるプッシュ制限)— Rulesetsはバイパスアクターを介して異なる方法でモデル化します。1:1のマッピングではありません。
- ブランチごとの差異 — 単一の共有条件ルールセットでは、`master`と`main`で異なるルールを表現できません。
このフラグを使用すると、`fix`はルールセットを作成/更新し、各ブランチのクラシック保護を削除して、2つのレイヤーが重ならないようにします。
### タグ保護(パブリックリポジトリ、または有料プランのリポジトリ)
タグ保護は、すべてのタグを対象とするGitHubルールセットを作成します(デフォルトは`*`、`protected_tags`で設定可能)。以下のルールが適用されます:
| ルールセットルール | 適用? | 備考 |
|---|---|---|
| 作成の制限 | いいえ | |
| **更新の制限** | **はい** | タグの書き換え/フォースプッシュを防止 |
| **削除の制限** | **はい** | タグの `git push --delete` を防止 |
| 線形履歴を要求 | いいえ | |
| デプロイの成功を要求 | いいえ | |
| 署名付きコミットを要求 | いいえ | |
| ステータスチェックの合格を要求 | いいえ | |
| フォースプッシュをブロック | いいえ | |
リポジトリ管理者はバイパスリストに含まれます(ブランチ保護の`enforce_admins = false`デフォルトと一致)。パブリックリポジトリまたは有料GitHubプランでのみ機能します(ブランチ保護と同じ制限)。無料プランのプライベートリポジトリでは、プラン出力でスキップされます。
### セキュリティ
| 機能 | 動作 |
|---|---|
| Dependabotアラート | 有効(パブリックリポジトリ/有料プラン) |
| Dependabotセキュリティ更新 | 有効(脆弱性のある依存関係のPRを自動で開く) |
| シークレットスキャニング | パブリックリポジトリでは自動;プライベート有料プランでは有効 |
| プッシュ保護 | 有効(サポートされているシークレットを含むコミットをブロック) |
| プライベート脆弱性報告 | 有効(セキュリティ研究者が非公開で報告可能) |
| 依存関係グラフ | パブリックリポジトリでは自動;プライベートではREST APIなし(UIのみ) |
---
## 必要条件
- Python 3.8+
- `gh` CLIがインストールされ認証済み(`gh auth login`)、**または**環境変数`GITHUB_TOKEN`が設定されていること
- `--local` / `--from`(コードをプッシュまたはクローンする場合)の場合、通常のgit認証情報が設定されている必要があります。`gh config get git_protocol`が`ssh`の場合は`ssh-agent`にロードされたSSHキー、またはHTTPSクレデンシャルヘルパー(`gh auth setup-git`で自動設定)を使用します。OAuthトークンはgit pushには使用されないため、ワークフローファイル(`.github/workflows/*`)のプッシュにOAuthの`workflow`スコープは不要です。
- ソースからのインストールには`uv`(推奨)
- `truffleHog` v3(オプション — 事前スキャナーで使用;PATHから自動検出、またはpodman/dockerで実行;どちらも利用できない場合は正規表現にフォールバック)
---
## インストール
### uvを使用したソースからのインストール(推奨)```bash
git clone https://github.com/your-username/gh-safe-repo
cd gh-safe-repo
uv tool install .
これにより、gh-safe-repo が uv のツール環境にインストールされ、PATH に追加されます。
git clone https://github.com/your-username/gh-safe-repo cd gh-safe-repo uv sync # creates .venv ./gh-safe-repo create <owner/repo>
### 確認```bash
gh-safe-repo --help
gh-safe-repo create <owner/repo>
gh-safe-repo create <owner/repo> --dry-run
gh-safe-repo create <owner/repo> --public
gh-safe-repo create <owner/repo> --from <owner/source>
gh-safe-repo create <owner/pub> --from <owner/priv> --public
gh-safe-repo create <owner/repo> --local ~/projects/myapp
gh-safe-repo create <owner/repo> --local ~/projects/myapp --public
gh-safe-repo fix <owner/repo>
gh-safe-repo fix <owner/repo> --dry-run
gh-safe-repo fix <owner/repo> --yes
gh-safe-repo scan . gh-safe-repo scan ~/projects/myapp
## CLIリファレンス```
gh-safe-repo create <owner/repo> [OPTIONS]
gh-safe-repo fix <owner/repo> [OPTIONS]
gh-safe-repo scan <path> [OPTIONS]
GitHubとやり取りするすべてのコマンドは、owner/repo形式(例:myuser/my-repo)が必要です。createの場合、オーナーは認証されたGitHubアカウントに対して検証され、マルチアカウントシステムでの誤りを防ぎます。fixの場合、代わりにターゲットリポジトリへの管理者権限が必要であり、自分が管理者アクセス権を持つ組織や他のアカウントが所有するリポジトリを修正できます。
create — 新しいリポジトリを作成プレーンなcreate(--local/--fromなし)は、デフォルトブランチがブランチ保護のために存在するようにリポジトリを初期化し、その後、自動生成されたREADME.mdを削除して、新しいリポジトリをクリーンな状態で開始します。代わりにREADMEを保持するには、設定でauto_init = trueを設定してください。--local/--fromは独自の履歴をプッシュし、READMEを作成しません。
fix — 既存のリポジトリを監査して修正scan — ローカルシークレットスキャン| オプション | 説明 |
|---|---|
--config [PATH] | 設定ファイルへのパス; 裸の--configは組み込みのデフォルトのみを使用 |
--debug | スキャナーの詳細を表示 |
終了コードは、重大な発見がない場合は0、重大な発見がある場合は1です。
--dry-runは、gh-safe-repoが実際に行うことを、変更やAPI呼び出しを行わずに正確に表示します。実際に実行する前に使用してください。--jsonと組み合わせると、機械可読な計画出力が得られます:```bash
gh-safe-repo create <owner/repo> --dry-run --json
gh-safe-repo fix <owner/repo> --dry-run --json
`--json` が有効な場合、計画は JSON オブジェクトとして stdout に書き込まれ、その他のメッセージ(進捗、警告、"Dry run" フッター)はすべて stderr に出力されるため、パイプやスクリプトで利用する際に出力がクリーンになります。```
$ gh-safe-repo create <owner/repo> --dry-run
Plan for my-project (private)
Category Action Setting Value
──────────────────────────────────────────────────────────────────
Repository ADD repository my-project (private)
Repository ADD has_wiki false
Repository ADD has_projects false
Actions ADD default_workflow_permissions read
Actions ADD can_approve_pull_request_reviews false
Branch Protection SKIP branch_protection Not available for private repos on free plan
Security SKIP dependabot_alerts Not available for private repos on free plan
1 setting skipped (GitHub plan limitation).
Dry run — no changes made.
アクションの色:
| アクション | 意味 |
|---|---|
ADD (green) |
JSON出力 (--json):```json
{
"changes": [
{ "type": "add", "category": "repository", "key": "has_wiki", "old": null, "new": false, "reason": null },
{ "type": "skip", "category": "branch_protection", "key": "branch_protection", "old": null, "new": null, "reason": "Not available for private repos on free plan" }
],
"summary": { "add": 5, "skip": 2 }
}
`summary` には、プランに存在するタイプのみが含まれます。利用者は、4つのキーすべてが存在すると仮定するのではなく、`.get("delete", 0)` などを使用する必要があります。
---
## 修正モード(既存リポジトリの監査)
`fix` は、既存リポジトリの現在の設定を安全なデフォルトと比較し、修正を適用します。シークレットスキャンは行いません。`fix` は純粋にリポジトリ設定に関するものです。```bash
# See what's out of compliance
gh-safe-repo fix <owner/repo> --dry-run
# Apply missing safe defaults
gh-safe-repo fix <owner/repo>
# Apply without confirmation prompt (scripting/batch use)
gh-safe-repo fix <owner/repo> --yes
修正モード:
UPDATE、すでに望ましい値になっている設定には SKIP(何も変更しない検出 — 何も変わらない API 呼び出しは決して行われません)を表示した計画表を示します--yes でスキップ)実際の変更のみが適用されます — すでに望ましい値になっている設定は SKIP と表示され、API 呼び出しは発生しません。
--from)--from は既存のリポジトリを新しいリポジトリに安全なデフォルト値でミラーリングします。プライベートおよびパブリックの両方の宛先で機能します。```bash
gh-safe-repo create <owner/repo> --from <owner/source>
gh-safe-repo create <owner/pub> --from <owner/priv> --public
**実行順序:**
1. `github.com` に対する git 認証情報が事前に検証されます(`gh config get git_protocol` が `ssh` の場合は SSH プローブによる確認、HTTPS は信頼されます)。そのため、キーが存在しない場合はリポジトリ作成前に迅速に失敗します。
2. ソースリポジトリがローカルにクローンされます(完全クローン、`--depth` は指定しないため、truffleHog が全コミット履歴を辿れます)。
3. ローカルクローンに対して[事前セキュリティスキャナー](#pre-flight-security-scanner)が実行されます。
4. あなたが結果を確認し、承認(または中断)します。
5. 新しいリポジトリが作成されます(デフォルトはプライベート、`--public` でパブリックになります)。
6. Actions の権限とセキュリティ設定が適用されます(Dependabot、シークレットスキャン、プッシュ保護)。
7. 完全な履歴がミラーリングされます: `git clone --mirror` + `git push --mirror`
8. ブランチとタグの保護が適用されます(コードプッシュ後に行われるため、対象ブランチが存在します)。
スキャンで問題が発見され中止した場合、コードが GitHub にコピーされることはありません。
> **注:** `--from` はソースとデスティネーションの両方で `owner/repo` 形式を使用します。
---
## ローカルディレクトリからリポジトリを作成する (`--local`)
`--local PATH` は `--from` のローカルから GitHub への対応版です。新しい GitHub リポジトリを作成し、ローカルの git リポジトリからコードをプッシュします。`PATH` は初期化済みの git リポジトリ(`git init` またはクローン)である必要があります。```bash
gh-safe-repo create <owner/repo> --local ~/projects/myapp
gh-safe-repo create <owner/repo> --local ~/projects/myapp --public
順番に何が起こるか:
github.com の Git 認証情報が事前に確認されます(gh config get git_protocol が ssh の場合は SSH プローブ、HTTPS は信頼されます)。そのため、キーがない場合はリポジトリが作成される前に迅速に失敗します。push --all --tags でプッシュされます(すべてのブランチとタグ)。origin が 元の ローカルリポジトリに追加され、新しい GitHub URL を指すように設定され、現在のブランチの上流トラッキングが構成されます。これにより、git push と git pull が追加設定なしで即座に動作します。--local と --from はどちらもプライベートおよびパブリックリポジトリで動作します。これらは相互排他的です。
ローカルのデフォルトブランチ(git -C PATH symbolic-ref HEAD による)は、ブランチ保護ルールの対象ブランチとして使用されるため、main でなくても正しいブランチに保護が適用されます。
ヒント: 何も作成せずに調査結果を確認したい場合は、最初に
gh-safe-repo scan PATHを実行してください。
スキャナーはローカルで実行され、コードをGitHubに送信することはありません。プッシュ前にスタンドアロンで使用するか、--from および --local ワークフローの一部として自動的に実行されます。
gh-safe-repo scan .
gh-safe-repo scan ~/projects/myapp
終了コードは、重大な問題が見つからない場合は`0`、重大な問題が見つかった場合は`1`です — これにより、他のコマンドとクリーンに連携できます:```bash
gh-safe-repo scan . && git push
完全な [pre_flight_scan] 設定が適用されます: banned_strings、max_file_size_mb、trufflehog_mode など。
gh-safe-repo は3段階の探索チェーンを使用して、利用可能な最適なスキャナーを自動的に選択します:
trufflehog --versionを実行し、v3であることを確認して使用します。v2のインストールまたは認識されないバージョンは警告を表示し、ステップ2にフォールスルーします。ghcr.io/trufflesecurity/trufflehog:latest)内でtruffleHogを実行し、podman run または docker run を使用して、スキャンパスを読み取り専用で同じ絶対パスにマウントするため、JSON出力パスはネイティブ実行と同一になります。選択されたスキャナーは、「Running pre-flight security scan...」ヘッダーと計画テーブルのSCANエントリに表示されます。例:``` Running pre-flight security scan... (truffleHog v3.93.4) Running pre-flight security scan... (truffleHog via podman) Running pre-flight security scan... (regex only — see warning above)
コンテナパスで認識される環境変数: `CONTAINER_RUNTIME` でランタイム選択を上書き(例 `CONTAINER_RUNTIME=docker`)、`TRUFFLEHOG_IMAGE` で特定のイメージタグを固定できます。
### podman または Docker 経由で truffleHog を実行する(ローカルインストール不要)
手動セットアップは不要です。`gh-safe-repo` は自動的に podman または docker を検出し(上記ステップ2)、正しいボリュームマウントで truffleHog をコンテナ内で実行します。`CONTAINER_RUNTIME` および `TRUFFLEHOG_IMAGE` 環境変数が認識されます。
シェルラッパー (`tools/trufflehog`) と、固定されたローカルイメージをビルドするための `Containerfile` が [`tools/`](https://github.com/ariesq/gh-safe-repo/blob/HEAD/tools/README.md) に用意されています。これは、コンテナベースの truffleHog をシステム全体で利用したいユーザーや、エアギャップ環境用のイメージが必要なユーザー向けです。
### 対話型レビュー```
Pre-flight scan: my-private-project
CRITICAL my_private_project/config.py:12 AWS Access Key ID
[redacted]
WARNING my_private_project/setup.py:3 Email address
author_email="[email protected]"
1 critical finding, 1 warning.
Critical findings detected. Continue anyway? [y/N]:
N) です。続行するには明示的に y と入力する必要があります。Y) です。Enter キーで進めるか、n と入力して中止します。シークレットは出力で編集されます。メールアドレスと TODO は一致する行を表示します。
ビルド成果物ディレクトリ (node_modules, __pycache__, .venv, venv, dist, build) は、スキャンを高速に保つためにデフォルトでスキップされます。Git リポジトリでは、このスキップは条件付きです。ディレクトリをスキップする前に、スキャナーは git ls-files -- <dir> を実行して、内部のファイルが追跡されているかどうかを確認します。追跡されている場合は、ディレクトリは通常通りスキャンされます。
つまり、コミットされた node_modules や dist ツリー(珍しいですが発生します)は、見落とされることはありません。コミットされていないディレクトリ(通常のケース)は、以前と同様にスキップされ続けます。
クローンされたソースリポジトリで SKIP_DIRS サブディレクトリが見つかった場合、警告が引き続き表示されます。それらの存在は、予想以上のコンテンツがコミットされている可能性があるためです。
2 つの設定キーを使用すると、チェックカテゴリ全体を無効にせずに、既知の安全な発見を抑制できます。
scan_exclude_paths — ファイルまたはディレクトリを完全にスキップします。値は、相対ファイルパスと照合される改行/カンマ区切りの正規表現パターンです。一致するファイルは、すべてのチェック(シークレット、メール、TODO、大規模ファイル、AI コンテキストファイル検出)から除外されます。同じパターンは --exclude-paths を介して truffleHog にも渡されるため、どのスキャナーエンジンがアクティブであってもカバレッジは一貫しています。```ini
[pre_flight_scan]
scan_exclude_paths = docs/api.github.com.json tests/fixtures/
**`exclude_emails`** — 特定のアドレスまたはドメイン全体に対するメール検出結果を抑制します。値は改行またはカンマ区切りで、大文字小文字を区別しません。`@` で始まるエントリはそのドメインのすべてのメールに一致し、それ以外の場合は完全なアドレスと正確に一致する必要があります。ワーキングツリーとgit履歴の両方の検出結果に適用されます。```ini
[pre_flight_scan]
# Suppress bot addresses and placeholder domains
exclude_emails = [email protected], [email protected], @example.com
[pre_flight_scan] scan_for_secrets = true scan_for_emails = true scan_for_todos = true max_file_size_mb = 100
禁止文字列やAIコンテキストファイルが見つかった場合、スキャナーは再実行前にソースリポジトリの履歴からそれらを削除するための、すぐに実行可能な `git filter-repo` コマンドを出力します。
---
## 設定
`gh-safe-repo` は次の優先順位で設定を検索します(最初に一致したものが優先):
1. **`--config PATH`** — 明示的な上書き
2. **`./gh-safe-repo.ini`** — カレントワーキングディレクトリ
3. **`$XDG_CONFIG_HOME/gh-safe-repo/gh-safe-repo.ini`** — `$XDG_CONFIG_HOME` が設定されていない場合は `~/.config` がデフォルト
単独の `--config`(パスなし)はファイル検索を完全にスキップし、組み込みのデフォルトのみを使用します。
すべての値には安全なデフォルトが設定されており、開始にあたって設定ファイルは必要ありません。
完全に注釈付きの設定例がリポジトリに `gh-safe-repo.ini.example` として含まれています。これをコピーして始めてください:```bash
# User-level config (XDG)
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/gh-safe-repo"
cp gh-safe-repo.ini.example "${XDG_CONFIG_HOME:-$HOME/.config}/gh-safe-repo/gh-safe-repo.ini"
# Or project-level config (current directory)
cp gh-safe-repo.ini.example ./gh-safe-repo.ini
[repo]
private = true
has_wiki = false has_projects = false has_issues = true
delete_branch_on_merge = false
allow_squash_merge = true allow_merge_commit = true allow_rebase_merge = true
create leaves an initialized README in the new repo.auto_init = false
[actions]
allowed_actions = selected
github_owned_allowed = true # actions maintained by GitHub (e.g. actions/checkout) verified_allowed = true # actions from Marketplace verified creators
default_workflow_permissions = read
can_approve_pull_request_reviews = false
sha_pinning_required = true
[branch_protection]
protected_branch = main
require_pull_request = true
required_approving_reviews = 1
dismiss_stale_reviews = true
require_conversation_resolution = true
enforce_admins = false
allow_force_pushes = false
allow_deletions = false
use_rulesets = true
[tag_protection]
protected_tags = *
prevent_tag_deletion = true
prevent_tag_update = true
[security]
enable_dependabot_alerts = true
enable_dependabot_security_updates = true
enable_private_vulnerability_reporting = true
enable_secret_scanning_push_protection = true
[pre_flight_scan] scan_for_secrets = true scan_for_emails = true scan_for_todos = true
max_file_size_mb = 100
[git_transport]
workflow token scope to pushworkflow scope intentionally.---
## GitHub プランの制限
一部の機能は、リポジトリの公開設定と GitHub プランに応じてのみ利用可能です。
| 機能 | 無料 + 公開 | 無料 + 非公開 | Pro/Team + 非公開 |
|---|---|:---:|:---:|
| ブランチ保護 / ルールセット | はい | いいえ | はい |
| タグ保護 (ルールセット) | はい | いいえ | はい |
| Dependabot アラート | はい | いいえ | はい |
| Dependabot セキュリティアップデート | はい | いいえ | はい |
| シークレットスキャン | 自動 | いいえ | はい |
| プッシュ保護 | はい | いいえ | はい |
| プライベート脆弱性レポート | はい | はい | はい |
| 依存関係グラフ | 自動 | いいえ | はい |
`gh-safe-repo` は実行時にプランレベルとリポジトリの公開設定を検出します。利用できない機能はプラン出力に `SKIP` として表示され、明確な理由が示されます。ツールがサイレントに失敗することはありません。
---
## 仕組み```
gh-safe-repo create <owner/repo>
│
├─ Parse owner/repo, validate owner matches authenticated user (create only)
├─ Load config (./gh-safe-repo.ini or $XDG_CONFIG_HOME/gh-safe-repo/gh-safe-repo.ini)
├─ Apply CLI flag overrides (--public, etc.)
├─ Authenticate via gh CLI or GITHUB_TOKEN
├─ GET /user → owner login + plan level (single cached call)
│
├─ Build plan (each plugin compares desired vs. current state)
│ ├─ RepositoryPlugin → repo creation + basic settings
│ ├─ ActionsPlugin → allowed actions, workflow permissions, SHA pinning
│ ├─ BranchProtectionPlugin → Rulesets API (default; classic if use_rulesets = false)
│ ├─ SecurityPlugin → Dependabot, secret scanning, push protection, private vuln reporting
│ └─ TagProtectionPlugin → immutable tags via Rulesets API
│
├─ Print plan table
│
└─ Apply (unless --dry-run)
├─ POST /user/repos
├─ PATCH /repos/{owner}/{repo} (settings)
├─ PUT /repos/{owner}/{repo}/actions/permissions/workflow
├─ POST/PATCH /repos/{owner}/{repo}/rulesets (branch protection; default)
│ or PUT /repos/{owner}/{repo}/branches/main/protection (if use_rulesets = false)
├─ PUT /repos/{owner}/{repo}/vulnerability-alerts
├─ PUT /repos/{owner}/{repo}/automated-security-fixes
├─ PUT /repos/{owner}/{repo}/private-vulnerability-reporting
├─ PATCH /repos/{owner}/{repo} (security_and_analysis: push protection)
├─ POST /repos/{owner}/{repo}/rulesets (tag protection ruleset)
├─ git clone --mirror + git push --mirror (if --from)
└─ git clone <local> + git push --all --tags (if --local, git repo)
or git init + add -A + commit + push (if --local, plain dir)
各設定カテゴリは、自己完結型のプラグインクラス(gh_safe_repo/plugins/)です。各プラグインは次のことを行います:
Plan(Changeオブジェクトのリスト: ADD / UPDATE / DELETE / SKIP)を返すつまり、監査モードと作成モードは同じ計画/適用パスを使用します。唯一の違いは、現在の状態を既存のリポジトリから取得するか、GitHubのデフォルトと仮定するかです。
API呼び出しは、以下の順序でトークンを解決します:
GITHUB_TOKEN環境変数 — アクティブなghセッションを切り替えずに特定のアカウントをターゲットにできます(CIで必要な唯一の認証情報です)gh auth token — gh auth loginで設定されたものトークンは、子プロセスのgh apiプロセスにGH_TOKENとして渡され、ログに記録されることはありません。
Git操作(--local/--fromのプッシュとクローン)は、デフォルトではAPIトークンではなく、自身のgit認証情報(SSHキーまたはcredential helper)を使用します。どちらもない環境(例:GITHUB_TOKENのみを持つCI)では、ツールはURL内のトークンを使用したHTTPS経由のプッシュにフォールバックします。[git_transport] mode設定オプションがこれを制御します(設定リファレンスを参照)。トークンを含むURLがリポジトリの.git/configに書き込まれることはなく、すべての出力から削除されます。
すべてのGitHub API呼び出しは、subprocess経由でgh apiを通じて行われます。これにより、認証は完全にgh CLIに委ねられます — トークン管理コード、OAuthフロー、PyGithubのバージョン固定はありません。JSONリクエストボディは、--fieldフラグではなく、--input -(stdin)を介して渡されます。
git clone https://github.com/your-username/gh-safe-repo cd gh-safe-repo uv sync # creates .venv, installs pytest
uv run pytest tests/ -v
./gh-safe-repo create <owner/repo> --dry-run
uv tool install .
参照 [`tests/README.md`](https://github.com/ariesq/gh-safe-repo/blob/HEAD/tests/README.md) テストファイルの説明、モッキングの慣例、新しいテストの追加方法について。
### プロジェクト構造```
gh-safe-repo/
├── gh-safe-repo # Thin launcher (entry point for direct use)
├── gh_safe_repo/ # Package — see gh_safe_repo/README.md for internals
│ ├── cli.py # Subparser dispatch (create, fix, scan)
│ ├── commands/ # Subcommand implementations
│ │ ├── _common.py # Shared helpers, CLIContext, plan formatting
│ │ ├── create.py # create subcommand
│ │ ├── fix.py # fix subcommand
│ │ └── scan.py # scan subcommand
│ └── plugins/ # Settings plugins (one per category)
├── pyproject.toml # Build config, entry points
├── gh-safe-repo.ini.example # Fully annotated example config
└── tests/
See gh_safe_repo/README.md を参照してください。モジュールマップ、プラグインアーキテクチャ、新しい設定の追加ガイドについて説明しています。
ランタイム依存関係はありません。すべて Python 標準ライブラリ (argparse, configparser, subprocess, json, re) を使用しています。議論なしにサードパーティパッケージを追加しないでください。
pytest は唯一の開発依存関係であり、pyproject.toml の UV ネイティブな [dependency-groups] エントリとして宣言されています。
これらのプロジェクトは設計時に研究され、gh-safe-repo のアーキテクチャに影響を与えました。これらはスコープとユーザーモデルが異なる独自のツールです。パターンがどのように適応されたかの詳細な技術ノートは、docs/LEARNINGS.md を参照してください。
mergeDeep 比較アプローチのソース。Diffable ベースプラグインパターンのよりクリーンなリファレンスを提供。plan/apply ワークフローを持つ。gh api サブプロセスラッパーパターンとドライランプラン出力設計の主なインスピレーション。| オプション | 説明 |
|---|
--public | 公開リポジトリとして作成(デフォルト:非公開) |
--local PATH | ローカルのGitリポジトリからコードを新しいリポジトリにプッシュします。最初にプリフライトスキャンを実行します。--fromとは排他的です。 |
--from OWNER/REPO | 既存のリポジトリからコードを新しいリポジトリにミラーリングします。プリフライトスキャンを実行します。--localとは排他的です。 |
--yes / -y | 確認プロンプトをスキップして即座に適用(スクリプト/バッチ処理用) |
--dry-run | 変更を加えずに計画を表示 |
--json | ANSIテーブルの代わりに計画をJSONとしてstdoutに出力 |
--config [PATH] | 設定ファイルへのパス; 裸の--configは組み込みのデフォルトのみを使用 |
--debug | すべてのAPI呼び出しと応答を表示 |
| オプション | 説明 |
|---|
--yes / -y | 確認プロンプトをスキップして即座に適用(スクリプト/バッチ処理用) |
--dry-run | 変更を適用せずに設定の差分を表示 |
--json | ANSIテーブルの代わりに計画をJSONとしてstdoutに出力 |
--config [PATH] | 設定ファイルへのパス; 裸の--configは組み込みのデフォルトのみを使用 |
--debug | すべてのAPI呼び出しと応答に加えて、解決されたリポジトリID(id、フルネーム、オーナータイプ)を表示 |
| 適用される新しい設定 |
UPDATE (yellow) | 変更される既存の設定(監査モード) |
DELETE (red) | 削除される設定 |
SKIP (dim) | アクション不要 — 既に目的の値になっているか、プラン/表示設定の組み合わせで機能が利用不可 |
| カテゴリ | 重大度 | 例 |
|---|
| ハードコードされたシークレット | 重大 | AWSキー (AKIA…)、GitHubトークン (ghp_…, github_pat_…)、秘密鍵、データベースURL |
| 禁止文字列 | 重大 | 設定したリテラル文字列(ユーザー名、内部ホスト名、コードネーム) |
| AIコンテキストファイル | 重大 | CLAUDE.md、AGENTS.md、.cursorrules、copilot-instructions.md、.cursor/ — 内部開発メモを含む可能性あり;git履歴は現在のバージョンよりも機密性が高い場合がある |
| メールアドレス | 警告 | ワーキングツリーとgit履歴内の [email protected] パターン |
| 大容量ファイル | 警告 | 設定されたサイズしきい値を超えるファイル(デフォルト: 100 MB) |
| TODO/FIXMEコメント | 情報 | # TODO、# FIXME、# HACK、# XXX |