Skip to content

Code Structure Components

github-actions[bot] edited this page Mar 14, 2026 · 1 revision

Code-Structure-Components

wikigenは単一の Go ソースファイル(main.go、1070行)で構成された実行可能プログラムである。本ページでは、主要なデータ型・構造体、キー関数、およびモジュール全体の構成を詳細に解説する。標準ライブラリのみを使用し、外部依存なしで実装されている点が特徴的な設計上の決断であり、アーキテクチャ & 設計ページと合わせて参照することで全体像を把握できる。

本ページが対象とするリポジトリは wikigenmain.go)の単一ファイル実装である。ビルド手順や環境構成については インストール & セットアップ を、CLI フラグの詳細は CLI 使用法 & コマンド を参照のこと。


モジュール構成

パッケージ宣言とインポート

go.mod(3行)でモジュール名 wikigen、Go バージョン 1.25.7 を宣言する。外部依存は一切なく、標準ライブラリのみを使用している。

Sources: main.go:1-17

package main

import (
    "bytes"
    "encoding/json"
    "flag"
    "fmt"
    "log"
    "os"
    "os/exec"
    "path/filepath"
    "regexp"
    "strings"
    "sync"
    "sync/atomic"
    "time"
)

ファイル内の機能別領域

main.go は論理的に以下の 9 セクションに分かれている。

セクション 行番号 説明
インポート 3–17 標準ライブラリのインポート
Progress 追跡 19–58 並行進捗管理
データ型定義 60–112 主要構造体
入力バリデーション 77–92 セキュリティチェック
プロンプト & 言語 175–376 Claude 向けプロンプト生成
XML パース 378–458 構造レスポンス解析
エラー処理 & Wiki 生成 460–667 コアロジック
リトライロジック 741–877 失敗ページの再試行
メインエントリポイント 879–1069 フラグ解析・オーケストレーション

Sources: main.go:1-1070


主要データ型

Progress 構造体

type Progress struct {
    mu         sync.Mutex
    totalItems int
    doneItems  int32
    current    map[string]string
}

Sources: main.go:21-26

並列処理中の進捗をスレッドセーフに管理する。doneItemssync/atomic パッケージで操作されるため、Mutex ロックなしで更新できる。current マップは実行中タスクの名前とステータスを保持し、ターミナルへの進捗バー表示に使用される。

メソッド一覧

メソッド 行番号 説明
newProgress(total int) 28–30 コンストラクタ
set(name, status string) 32–37 タスクステータス更新(Mutex 保護)
done(name string) 39–45 タスク完了・マップから削除
print() 47–58 進捗バーをパーセンテージ付きで表示

Sources: main.go:28-58


WikiPage 構造体

type WikiPage struct {
    ID          string
    Title       string
    Filename    string
    Description string
    Content     string
}

Sources: main.go:62-68

Claude が返す XML 構造レスポンスから解析されたページ定義をメモリ内に保持する。Filename は GitHub Wiki 互換のハイフン区切り形式(例: Code-Structure-Components.md)となる。Content フィールドはフェーズ 2 のページ生成後に実際のファイル内容で埋められる。


RepoEntry 構造体

type RepoEntry struct {
    Project string
    Repo    string
}

Sources: main.go:72-75

repos.txt の各行を解析した結果を保持する。Project はグループ名(スタンドアロンの場合は空文字列)、Repoowner/repo 形式のリポジトリ識別子である。複数リポジトリの Wiki 生成については マルチリポジトリ Wiki 生成 を参照。


WikiResult 構造体と WikiPageResult 構造体

type WikiResult struct {
    Project    string           `json:"project"`
    Repos      []string         `json:"repos"`
    OutputDir  string           `json:"output_dir"`
    Pages      []WikiPageResult `json:"pages"`
    TotalPages int              `json:"total_pages"`
    Failed     int              `json:"failed"`
    Duration   string           `json:"duration"`
    Status     string           `json:"status"`
}

type WikiPageResult struct {
    Title    string `json:"title"`
    Filename string `json:"filename"`
    Size     int    `json:"size"`
    Status   string `json:"status"`
}

Sources: main.go:96-112

-json フラグ有効時に標準出力へ書き出す JSON シリアライズ用の構造体である。WikiPageResult.Status"ok""failed""pending" の 3 値を取る。JSON 出力の詳細は JSON 出力 & 構造化結果 を参照。


データ型関係図

classDiagram
    class Progress {
        +sync.Mutex mu
        +int totalItems
        +int32 doneItems
        +map current
        +newProgress(total)
        +set(name, status)
        +done(name)
        +print()
    }

    class WikiPage {
        +string ID
        +string Title
        +string Filename
        +string Description
        +string Content
    }

    class RepoEntry {
        +string Project
        +string Repo
    }

    class WikiResult {
        +string Project
        +[]string Repos
        +string OutputDir
        +[]WikiPageResult Pages
        +int TotalPages
        +int Failed
        +string Duration
        +string Status
    }

    class WikiPageResult {
        +string Title
        +string Filename
        +int Size
        +string Status
    }

    WikiResult "1" --> "many" WikiPageResult : contains
    WikiPage --> WikiPageResult : generates
Loading

キー関数

claudeCall — Claude CLI 呼び出し

Sources: main.go:116-143

func claudeCall(claudePath, model string, repoDirs []string,
    systemPrompt, prompt, workDir string) (string, error)

Claude CLI を -p(プロンプトモード)で起動する中心的な関数。実行引数の構成は以下の通り。

引数 説明
-p プロンプトモード(stdin から入力)
--output-format text テキスト出力のみ
--dangerously-skip-permissions ツール権限チェックをスキップ
--model [model] モデル指定(空なら省略)
--add-dir [dir] リポジトリディレクトリ追加(繰り返し可能)
--system-prompt [prompt] システムメッセージ(空なら省略)
--stdin stdin からプロンプトを読み込む

Claude へのプロンプトは bytes.Buffer を介して cmd.Stdin に渡される。戻り値はトリムされた標準出力文字列。Claude Code 連携の詳細は Claude Code 連携 を参照。


generateWiki — Wiki 生成コア

Sources: main.go:474-638

func generateWiki(claudePath, model string, projectName string,
    repos []string, token, language, outputDir, cloneDir string,
    pageParallel int, dryRun bool, localDir string,
    progress *Progress) (*WikiResult, error)

Wiki 生成の全フェーズを統括する中心関数。実行フローは以下の 4 フェーズで構成される。

flowchart TD
    A[Phase 0: リポジトリセットアップ] --> B[Phase 1: 構造決定]
    B --> C{dry-run?}
    C -->|Yes| D[構造のみ返却]
    C -->|No| E[Phase 3: ページ並列生成]
    E --> F[Phase 4: 結果集計]

    subgraph Phase0
        A1[リポジトリ検証] --> A2[git clone / local使用]
        A2 --> A3[repoDirs収集]
    end

    subgraph Phase1
        B1[structurePrompt生成] --> B2[claudeCall実行]
        B2 --> B3[XML解析・parsePages]
        B3 --> B4[Home.md / Sidebar生成]
    end

    subgraph Phase3
        E1[セマフォ作成] --> E2[goroutine起動]
        E2 --> E3[最大3回リトライ]
        E3 --> E4[ファイルサイズ検証]
    end
Loading

Phase 0: リポジトリセットアップ(lines 481–517)

  • -local フラグがある場合はローカルディレクトリをそのまま使用
  • それ以外は gitClone() を呼び出し depth=1 で取得

Phase 1: 構造決定(lines 526–549)

  • structurePrompt() を生成し claudeCall() へ送信
  • cleanXMLResponse()parsePages() で WikiPage スライスを生成
  • writeHomeAndSidebar() で Home.md と _Sidebar.md を即時生成

Phase 2: ドライランチェック(lines 557–563)

  • -dry-run 設定時は構造情報のみを返却して終了

Phase 3: 並列ページ生成(lines 565–617)

  • pageParallel 容量のセマフォで同時実行数を制御
  • 各ページで最大 3 回のリトライを実施
  • 100 バイト未満のファイルは失敗と判定

Phase 4: 結果集計(lines 619–637)

  • ファイルサイズで ok/failed を判定
  • WikiResult を返却

parsePages — XML 解析

Sources: main.go:399-434

func parsePages(xml string) []WikiPage

Claude が返す XML 構造レスポンスからページ定義を抽出する。<page id="..."> 要素を反復処理し、タグ内の titlefilenamedescription を抽出する。filename が省略された場合は titleToFilename() でタイトルから自動生成する。

// titleToFilename の変換例
func titleToFilename(title string) string {
    r := strings.NewReplacer(
        " ", "-", "/", "-", ":", "-",
        "(", "-", ")", "-",
        " ", "-", "・", "-",
    )
    ...
}

Sources: main.go:451-458


writeHomeAndSidebar — ナビゲーションファイル生成

Sources: main.go:640-667

func writeHomeAndSidebar(wikiDir, projectName, structureContent string,
    allPages []WikiPage, repos []string)

GitHub Wiki 特有の 2 ファイルを生成する。

Home.md の構成:

  • # {projectName} タイトル
  • XML から抽出した説明文
  • リポジトリ一覧(複数リポジトリの場合)
  • 生成タイムスタンプ
  • 全ページへのリンク一覧

_Sidebar.md の構成:

  • Home へのリンク
  • 全ページへのリンク(GitHub Wiki の左サイドバーナビゲーション用)

出力ファイル形式の詳細は 出力フォーマット & Wiki 構造 を参照。


parseRepoList — リポジトリリスト解析

Sources: main.go:674-690

func parseRepoList(lines []string) (standalone []RepoEntry,
    groups map[string][]string)

repos.txt の各行を解析し、スタンドアロンとグループの 2 種類に分類する。

入力フォーマット 分類 説明
owner/repo standalone 単独 Wiki
project:owner/repo groups プロジェクトグループ Wiki
# コメント スキップ コメント行
空行 スキップ 無視
flowchart TD
    A[lines 入力] --> B{行の形式?}
    B -->|空行・コメント| C[スキップ]
    B -->|project:repo 形式| D[groups マップに追加]
    B -->|owner/repo 形式| E[standalone スライスに追加]
    D --> F[戻り値: standalone, groups]
    E --> F
Loading

入力バリデーション

Sources: main.go:77-92

var validRepoPattern = regexp.MustCompile(`^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$`)

func validateRepo(repo string) error {
    if strings.Contains(repo, "..") {
        return fmt.Errorf("invalid repo: path traversal detected: %s", repo)
    }
    for _, c := range []string{";", "&", "|", "`", "$", "(", ")", "{", "}", "[", "]", "!", "~"} {
        if strings.Contains(repo, c) {
            return fmt.Errorf("invalid repo: dangerous character in: %s", repo)
        }
    }
    if !validRepoPattern.MatchString(repo) {
        return fmt.Errorf("invalid repo format (expected owner/repo): %s", repo)
    }
    return nil
}

3 段階のバリデーションを実施する。セキュリティの詳細は 入力バリデーション & セキュリティ を参照。

  1. パストラバーサル検出(.. の存在チェック)
  2. 危険文字ブロック(;, &, | 等)
  3. owner/repo 形式の正規表現マッチ

XML 応答クリーニング

Sources: main.go:380-397

func cleanXMLResponse(content string) string

Claude の応答からマークダウンコードフェンス(バックティック)・</wiki_structure> タグ以降のテキスト・思考タグ(/think/no_think)を除去する。これにより XML パーサーへの入力を安全な形式に変換する。


エラー処理とリトライ

appendError

Sources: main.go:462-470

func appendError(dir, msg string)

_errors.log にタイムスタンプ付きのエラーメッセージを追記する。ファイルが存在しない場合は新規作成、存在する場合は追記する。エラー処理の詳細は エラー処理 & リトライメカニズム を参照。

retryFailedPages

Sources: main.go:743-877

func retryFailedPages(claudePath, model, language, outputDir,
    cloneDir string, pageParallel int)

-retry フラグ有効時に呼び出される回復メカニズム。出力ディレクトリをスキャンし「Content generation failed」を含む、もしくは 200 バイト未満のページを特定して再生成する。Home.md からページ定義を再構築してクロスリンク情報を維持する。


環境設定ヘルパー

Sources: main.go:694-739

関数 行番号 説明
envOrDefault(key, fallback) 694–699 環境変数取得(フォールバック付き)
envOrDefaultInt(key, fallback) 701–710 整数環境変数解析
envOrDefaultBool(key, fallback) 712–717 ブール環境変数解析
loadEnvFile() 719–739 .env / .env.local 読み込み

loadEnvFile() は既に設定済みの環境変数を上書きしない(.env ファイルよりも実環境変数を優先)。設定の詳細は 設定 & 環境変数 を参照。


プロンプト生成

xmlSystemPrompt

Sources: main.go:175-181

Claude に対して生の XML のみを返すよう指示するシステムプロンプト。マークダウンのコードフェンスなどの装飾を禁止する。

structurePrompt

Sources: main.go:183-273

func structurePrompt(projectName string, repos []string,
    language string) string

Wiki 構造設計フェーズで使用するプロンプト。Claude に対して Read・Grep・Glob・Bash ツールでリポジトリを解析し、実際に存在するコードに基づくページ定義を XML 形式で返すよう指示する。

pagePrompt

Sources: main.go:275-362

func pagePrompt(page WikiPage, allPages []WikiPage,
    projectName string, repos []string, language string) string

個別ページ生成フェーズで使用するプロンプト。ページタイトル・説明・出力言語・クロスリンク情報・品質要件(コード引用必須・推測禁止)を含む。

languageName

Sources: main.go:364-376

言語コードを人間可読な名称にマッピングする。サポート言語の詳細は 言語サポート & ローカライゼーション を参照。

func languageName(code string) string {
    switch code {
    case "ja": return "Japanese"
    case "en": return "English"
    case "zh": return "Mandarin Chinese"
    // ...
    }
}

main() 関数の構成

Sources: main.go:881-1069

main() 関数は 7 フェーズで構成される。

flowchart TD
    A[Phase 1: 初期化] --> B[Phase 2: リトライモード確認]
    B -->|retry フラグあり| C[retryFailedPages 実行・終了]
    B -->|通常実行| D[Phase 3: 入力収集]
    D --> E[Phase 4: タスク構築]
    E --> F[Phase 5: バリデーション]
    F --> G[Phase 6: 並列実行]
    G --> H[Phase 7: 出力]

    subgraph 並列実行
        G1[セマフォ作成] --> G2[goroutine起動]
        G2 --> G3[generateWiki呼び出し]
        G3 --> G4[結果収集]
    end
Loading

フラグ定義一覧(lines 884–917)

フラグ デフォルト 説明
-retry bool false 失敗ページのみ再試行
-dry-run bool false 構造確認のみ(生成なし)
-json bool false JSON を標準出力に出力
-local string "" ローカルディレクトリ指定
-f string "" リポジトリリストファイル
-r string "" カンマ区切りリポジトリ
-token string $GITHUB_TOKEN GitHub PAT
-model string $CLAUDE_MODEL Claude モデル指定
-lang string ja 出力言語
-o string ./wiki-output 出力ディレクトリ
-clone-dir string ./.repos 一時クローンディレクトリ
-claude string claude Claude バイナリパス
-p int $WIKI_PARALLEL(1) プロジェクト並列数
-pp int $WIKI_PAGE_PARALLEL(3) ページ並列数
-log string "" ログファイルパス

Sources: main.go:884-917


並行処理アーキテクチャ

flowchart TD
    A[main: プロジェクト一覧] --> B[セマフォ: -p 容量]
    B --> C1[goroutine: プロジェクト1]
    B --> C2[goroutine: プロジェクト2]
    B --> C3[goroutine: プロジェクトN]

    C1 --> D[generateWiki]
    D --> E[セマフォ: -pp 容量]
    E --> F1[goroutine: ページ1]
    E --> F2[goroutine: ページ2]
    E --> F3[goroutine: ページM]

    F1 --> G[claudeCall]
    F2 --> G
    F3 --> G

    G --> H[atomic: doneItems++]
    H --> I[Progress.print]
Loading

2 レベルの並行処理が実装されている。プロジェクトレベル(-p フラグ)とページレベル(-pp フラグ)のそれぞれにセマフォが設けられ、Claude API へのリクエスト数を制御する。並行処理の詳細は 並列処理 & 並行性 を参照。


git 操作

Sources: main.go:147-171

func gitClone(repoURL, token, destDir string) error

2 パスの実装で構成される。

  1. リポジトリが既存の場合: git pull --ff-only で更新
  2. 新規クローンの場合:
    • PAT 認証: https://[token]@github.com/owner/repo 形式の HTTPS URL
    • SSH 認証: git@github.com:owner/repo.git 形式
    • git clone --depth=1 --single-branch で軽量取得

認証方式の詳細は リポジトリアクセス & 認証 を参照。


Related Pages

Clone this wiki locally