One file to rule the repo, and why that changes everything
Most reviews fail where context gets sliced thin. A pull request shows a tidy diff, meanwhile the real story hides across services, scripts, and tests. Reviewers hop between tabs, miss cross‑module assumptions, then spend a sprint fixing what slipped through. A simple habit changes that, create a single, prompt‑friendly text file of the whole repository, let your AI assistant read it end to end, then ask for an honest critique.
GitHub Copilot’s documented strengths include refactoring, maintainability improvements, unit test generation, and diagramming when you give it enough context, and consolidation lifts the ceiling on all of those outcomes (Copilot Chat Cookbook, Copilot docs). GitHub also rolled out richer file interactions, previews, and attachments on github.com, which makes long reviews more practical in the browser (changelog).
Quick links: What this script does in one run · Generate a single-file repo digest behind the firewall · Usage, prompts, and review flow · Keep IP inside the perimeter · Appendix A, full PowerShell script · Further Reading
What this script does in one run
Use the PowerShell script in this article to produce a single text file that includes the directory tree, filtered code contents, dependency info, and a clean summary. Keep it inside your perimeter, share it with Copilot or Claude, and request deep analysis without juggling files.
For public GitHub repos, tools like Gitingest and Repomix do similar packaging automatically. They excel when privacy is not a concern and when token budgeting matters (Gitingest site, Repomix site).
What the output looks like, a small slice for flavor.
=== Project Information === Generated on: 2025-10-29 === Project Structure === src/controllers/authController.ts src/services/userService.ts tests/auth.spec.ts === Code Files Content === ----- src/controllers/authController.ts ----- export async function login(req, res) { ... } === Dependency Information === Dependencies: express: ^4.19.2 jsonwebtoken: ^9.0.2 Dev Dependencies: vitest: ^2.0.0 === Summary === Project directory: C:\Repos\MyProject Output file: C:\Reports\MyProject-info.txt
With one file, AI stops guessing. It sees naming patterns, repeated utilities, and tests that never touch edge cases. GitHub’s Copilot Chat improvements on github.com, richer attachments and file previews, make it easier to inspect AI feedback without losing your place (changelog).
Why the single‑file digest matters
Holistic reviews, not line diffs. Models track design decisions across modules, spot duplicated logic, and call out brittle interfaces. Copilot’s cookbook covers performance refactoring, readability, test generation, and diagram creation, all of which improve when a digest provides complete context (Cookbook, Create diagrams).
Design alignment you can verify. Ask for swimlanes that mirror actual code paths, then compare the diagram with your design docs in the same file. The assistant points to mismatches and proposes adjustments. Copilot’s prompt recipes make this natural (Cookbook).
Fewer “we fixed it, right” moments. Code comments claim a fix, tests tell a different story. A single digest lets the model check both and suggest the missing assertions. For public repos, Gitingest and Repomix add useful stats, token counts, and formatting that help you plan what to include within model limits (Gitingest README, Repomix features).
Tools that help GitHub users
When a repo is open source, convenience wins.
- Gitingest. Replace “hub” with “ingest” in a GitHub URL, or run the CLI, and you get a prompt‑friendly text digest with structure, contents, and token counts. It respects
.gitignore, supports private repos via PAT, and ships a browser extension for quick use (site, repo, PyPI). - Repomix. Pack the entire codebase into one AI‑friendly file, choose Markdown or XML, compress code with Tree‑sitter to reduce tokens, remove comments, count tokens, and run Secretlint to avoid leaking credentials (site, repo).
These tools shine for public repos and onboarding, they offer instant extracts and transparent budgets. For enterprise IP, a local script keeps the same benefits while staying on your side of the firewall. GitHub’s Copilot docs outline enterprise controls for content exclusion and network settings, which pair well with a local packaging approach (content exclusion concept, how‑to).
Generate a single‑file repo digest behind the firewall
Core excerpt, the essentials from the full PowerShell script, trimmed for readability. This version initializes the output, writes structure, copies filtered code files, and captures dependency info, all on local disk.
# Generate-ProjectInfo.ps1 (core excerpt) [CmdletBinding()] param( [Parameter(Mandatory=$false)] [string]$Root = (Get-Location).Path, [Parameter(Mandatory=$false)] [string]$OutputFile = "project_info.txt" ) # Directories to exclude $ExcludeDirs = @( 'node_modules','build','dist','.git','.expo','.venv', '.next','.output','.turbo','.cache','coverage', 'target','gradle','.gradle','vendor','Pods', '.pytest_cache','.mypy_cache','.ruff_cache' ) # Include common code extensions $CodeExtensions = @('js','jsx','ts','tsx','py','rb','java','cpp','c','h','sh') function Initialize-OutputFile { param([string]$Path) $dir = Split-Path -Path $Path -Parent if ($dir -and -not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } Set-Content -Path $Path -Value "=== Project Information ===" Add-Content -Path $Path -Value ("Generated on: {0}" -f (Get-Date)) Add-Content -Path $Path -Value "" } function Write-Section { param([string]$Title) Add-Content -Path $OutputFile -Value ("=== {0} ===" -f $Title) } function Write-Line { param([string]$Text = "") Add-Content -Path $OutputFile -Value $Text } function Is-UnderExcludedDir { param([string]$FullName,[string]$RootPath) $relative = $FullName.Substring($RootPath.Length).TrimStart('','/') if ([string]::IsNullOrWhiteSpace($relative)) { return $false } $segments = $relative -split '[\/]' | Where-Object { $_ -ne "" } foreach ($seg in $segments) { if ($ExcludeDirs -contains $seg) { return $true } } return $false } function Get-ProjectItems { param([string]$RootPath) Get-ChildItem -LiteralPath $RootPath -Recurse -Force -ErrorAction SilentlyContinue | Where-Object { if (Is-UnderExcludedDir -FullName $_.FullName -RootPath $RootPath) { return $false } return $true } } function Get-ProjectStructure { param([string]$RootPath) Write-Line "(tree-like listing with exclusions)" $items = Get-ProjectItems -RootPath $RootPath $dirs = $items | Where-Object { $_.PSIsContainer } $files = $items | Where-Object { -not $_.PSIsContainer } foreach ($dir in ($dirs | Sort-Object FullName)) { $rel = $dir.FullName.Substring($RootPath.Length).TrimStart('','/') if ($rel) { Write-Line $rel } } foreach ($file in ($files | Sort-Object FullName)) { $rel = $file.FullName.Substring($RootPath.Length).TrimStart('','/') if ($rel) { Write-Line $rel } } } function Get-CodeFiles { param([string]$RootPath) $items = Get-ProjectItems -RootPath $RootPath $files = $items | Where-Object { -not $_.PSIsContainer } $files | Where-Object { $ext = $_.Extension.TrimStart('.').ToLowerInvariant() $CodeExtensions -contains $ext } } # Begin $Root = (Resolve-Path -LiteralPath $Root).Path Initialize-OutputFile -Path $OutputFile Write-Section "Project Structure" Get-ProjectStructure -RootPath $Root Write-Line Write-Section "Code Files Content" $codeFiles = Get-CodeFiles -RootPath $Root foreach ($file in $codeFiles) { $rel = $file.FullName.Substring($Root.Length).TrimStart('\','/') Write-Line ("----- {0} -----" -f $rel) Get-Content -LiteralPath $file.FullName -ErrorAction SilentlyContinue | Add-Content -Path $OutputFile Write-Line } Write-Section "Dependency Information" $packageJsonPath = Join-Path $Root "package.json" $requirementsPath = Join-Path $Root "requirements.txt" if (Test-Path -LiteralPath $packageJsonPath) { $pkg = Get-Content -LiteralPath $packageJsonPath -Raw | ConvertFrom-Json -ErrorAction SilentlyContinue Write-Line "Dependencies:"; ($pkg.dependencies | Get-Member -MemberType NoteProperty | ForEach-Object { Write-Line ("{0}: {1}" -f $_.Name, $pkg.dependencies.($_.Name)) }) ; Write-Line Write-Line "Dev Dependencies:"; ($pkg.devDependencies | Get-Member -MemberType NoteProperty | ForEach-Object { Write-Line ("{0}: {1}" -f $_.Name, $pkg.devDependencies.($_.Name)) }) } elseif (Test-Path -LiteralPath $requirementsPath) { Write-Line "Python Dependencies (requirements.txt):" Get-Content -LiteralPath $requirementsPath | Add-Content -Path $OutputFile } else { Write-Line "No dependency file found." } Write-Line Write-Section "Summary" Write-Line ("Project directory: {0}" -f $Root) Write-Line ("Output file: {0}" -f (Resolve-Path -LiteralPath $OutputFile).Path) Write-Line "Done!"
Why this local approach works for enterprises. You keep IP inside the perimeter, you tailor filters to your stack, and you can route the digest to an approved AI endpoint on your own terms. Copilot’s enterprise documentation covers content exclusion and admin controls (concepts, how‑to).
Usage, prompts, and review flow
Run it, keep the output in a controlled folder.
# From repo root .\Generate-ProjectInfo.ps1 # Or choose paths .\Generate-ProjectInfo.ps1 -Root "C:\Repos\MyProject" -OutputFile "C:\Reports\MyProject-info.txt"
Feed it to your AI, then ask for layered analysis.
You are reviewing a complete repository digest. First, list performance hotspots with file and line references, then propose concrete refactorings. Next, surface maintainability issues, naming, duplication, dead code. Finally, verify whether documented fixes in /docs match tests in /tests, report gaps, and suggest test cases.
Ask for a swimlane that matches reality.
Extract the end to end login flow as a swimlane, actors (User, Web App, Auth Service, Database). Use Mermaid. Validate against controllers, services, and data access code in the digest. Point out any missing steps.
Copilot’s cookbook includes patterns for refactoring, generating tests, and creating diagrams. Gitingest and Repomix help with public repos by formatting content for prompt consumption and by counting tokens so you plan the slices you send (Cookbook, Gitingest, Repomix).
Automate reviews carefully. If you use GitHub for CI, explore Claude’s GitHub integration to trigger AI reviews on mention, or to draft PRs from issues. Keep permissions tight, run in draft mode first, and log all actions (Claude Code Action repo, setup guide).
Keep IP inside the perimeter
- Local only. Run the script on managed endpoints, store outputs in internal artifact repositories, and route analysis through approved services. Copilot enterprise controls help admins enforce what leaves the environment (concepts, how‑to).
- Audit friendly. Attach the digest to a change ticket, require approvals, and keep immutable logs of AI suggestions and applied diffs. Claude’s GitHub Actions documentation and guides show permission scopes and enterprise setups for Bedrock or Vertex (action docs, cloud providers).
- Secrets stay out. Even local outputs can include credentials if someone committed them by mistake. Repomix integrates Secretlint to catch sensitive strings. Adopt a preflight secret scan and fail the job if anything appears risky (Repomix features).
Appendix A, full PowerShell script
This is the complete script, ready to drop into your tooling. It generates the project report with structure, code contents, dependency info, and a summary, and it excludes common build and dependency folders by default.
<# .SYNOPSIS Generates a project report with structure, code contents, and dependency info. .DESCRIPTION Produces a text report containing: - Project structure (with directory/file listing) - Full contents of code files (filtered by extension) - Dependency information from package.json or requirements.txt - Summary By default, excludes common build/dependency/derived directories and hidden files. Output path is customizable. .PARAMETER Root Root directory of the project (defaults to the current directory). .PARAMETER OutputFile Path to the output report file (relative or absolute). Default: "project_info.txt" in the current directory. .EXAMPLE .\Generate-ProjectInfo.ps1 .EXAMPLE .\Generate-ProjectInfo.ps1 -OutputFile "reports\project_info.txt" .EXAMPLE .\Generate-ProjectInfo.ps1 -Root "C:\Repos\MyProject" -OutputFile "C:\Reports\MyProject-info.txt" #> [CmdletBinding()] param( [Parameter(Mandatory=$false)] [string]$Root = (Get-Location).Path, [Parameter(Mandatory=$false)] [string]$OutputFile = "project_info.txt" ) # --------------------------- # Configuration # --------------------------- # Directories to exclude (names only; apply anywhere in the path) $ExcludeDirs = @( 'node_modules','build','dist','.git','.expo','.venv', '.next','.output','.turbo','.cache','coverage', 'target','gradle','.gradle','vendor','Pods', '.pytest_cache','.mypy_cache','.ruff_cache' ) # Exclude hidden files/dirs (dotfiles) via Attributes $ExcludeHidden = $true # Code extensions to include $CodeExtensions = @('js','jsx','ts','tsx','py','rb','java','cpp','c','h','sh') # --------------------------- # Helpers # --------------------------- function Initialize-OutputFile { param([string]$Path) $dir = Split-Path -Path $Path -Parent if ($dir -and -not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } # Overwrite with header Set-Content -Path $Path -Value "=== Project Information ===" Add-Content -Path $Path -Value ("Generated on: {0}" -f (Get-Date)) Add-Content -Path $Path -Value "" } function Write-Section { param([string]$Title) Add-Content -Path $OutputFile -Value ("=== {0} ===" -f $Title) } function Write-Line { param([string]$Text = "") Add-Content -Path $OutputFile -Value $Text } function Is-UnderExcludedDir { param( [string]$FullName, [string]$RootPath ) # Compute relative segments and check if any segment matches an excluded dir name $relative = $FullName.Substring($RootPath.Length).TrimStart('\','/') if ([string]::IsNullOrWhiteSpace($relative)) { return $false } $segments = $relative -split '[\/]' | Where-Object { $_ -ne "" } foreach ($seg in $segments) { if ($ExcludeDirs -contains $seg) { return $true } } return $false } function Get-ProjectItems { param([string]$RootPath) # Use -Force to see hidden items, but we'll filter them out if $ExcludeHidden Get-ChildItem -LiteralPath $RootPath -Recurse -Force -ErrorAction SilentlyContinue | Where-Object { # Exclude anything within excluded directories if (Is-UnderExcludedDir -FullName $_.FullName -RootPath $RootPath) { return $false } # Exclude hidden items if requested if ($ExcludeHidden -and ($_.Attributes -band [IO.FileAttributes]::Hidden)) { return $false } return $true } } function Get-ProjectStructure { param([string]$RootPath) Write-Line "(PowerShell tree-like listing with exclusions)" $items = Get-ProjectItems -RootPath $RootPath $dirs = $items | Where-Object { $_.PSIsContainer } $files = $items | Where-Object { -not $_.PSIsContainer } foreach ($dir in ($dirs | Sort-Object FullName)) { $rel = $dir.FullName.Substring($RootPath.Length).TrimStart('\','/') if (-not [string]::IsNullOrWhiteSpace($rel)) { Write-Line $rel } } foreach ($file in ($files | Sort-Object FullName)) { $rel = $file.FullName.Substring($RootPath.Length).TrimStart('\','/') if (-not [string]::IsNullOrWhiteSpace($rel)) { Write-Line $rel } } } function Get-CodeFiles { param([string]$RootPath) $items = Get-ProjectItems -RootPath $RootPath $files = $items | Where-Object { -not $_.PSIsContainer } $files | Where-Object { $ext = $_.Extension.TrimStart('.').ToLowerInvariant() $CodeExtensions -contains $ext } } # --------------------------- # Begin # --------------------------- # Normalize Root to full path $Root = (Resolve-Path -LiteralPath $Root).Path Initialize-OutputFile -Path $OutputFile # 1) Project Structure Write-Section "Project Structure" Get-ProjectStructure -RootPath $Root Write-Line # 2) Code Files Content Write-Section "Code Files Content" $codeFiles = Get-CodeFiles -RootPath $Root foreach ($file in $codeFiles) { $rel = $file.FullName.Substring($Root.Length).TrimStart('\','/') Write-Line ("----- {0} -----" -f $rel) try { # Output full contents (no size guardrails per request) Get-Content -LiteralPath $file.FullName -ErrorAction Stop | Add-Content -Path $OutputFile } catch { Write-Line ("[Error reading file: {0}]" -f $_.Exception.Message) } Write-Line } # 3) Dependency Information Write-Section "Dependency Information" $packageJsonPath = Join-Path $Root "package.json" $requirementsPath = Join-Path $Root "requirements.txt" if (Test-Path -LiteralPath $packageJsonPath) { try { $pkg = Get-Content -LiteralPath $packageJsonPath -Raw | ConvertFrom-Json -ErrorAction Stop Write-Line "Dependencies:" if ($pkg.PSObject.Properties.Name -contains 'dependencies' -and $pkg.dependencies) { $pkg.dependencies.GetEnumerator() | Sort-Object Name | ForEach-Object { Write-Line ("{0}: {1}" -f $_.Name, $_.Value) } } else { Write-Line "{}" } Write-Line Write-Line "Dev Dependencies:" if ($pkg.PSObject.Properties.Name -contains 'devDependencies' -and $pkg.devDependencies) { $pkg.devDependencies.GetEnumerator() | Sort-Object Name | ForEach-Object { Write-Line ("{0}: {1}" -f $_.Name, $_.Value) } } else { Write-Line "{}" } } catch { Write-Line "(Error parsing package.json; printing raw contents)" Get-Content -LiteralPath $packageJsonPath | Add-Content -Path $OutputFile } } elseif (Test-Path -LiteralPath $requirementsPath) { Write-Line "Python Dependencies (requirements.txt):" Get-Content -LiteralPath $requirementsPath | Add-Content -Path $OutputFile } else { Write-Line "No dependency file (e.g., package.json, requirements.txt) found." } Write-Line # 4) Summary Write-Section "Summary" Write-Line ("Project directory: {0}" -f $Root) Write-Line ("Output file: {0}" -f (Resolve-Path -LiteralPath $OutputFile).Path) Write-Line "Done!" # Console confirmation Write-Host "Project information has been extracted to $OutputFile"
Further Reading
GitHub Copilot
- Excluding content from GitHub Copilot (Enterprise Cloud Docs)
- Content exclusion for GitHub Copilot (Concepts)
- Copilot content exclusions now available for enterprise admins (Changelog)
- Copilot content exclusion GA announcement
- GitHub Copilot Chat Cookbook (Prompt examples)
- Creating diagrams with Copilot Chat
- New Copilot Chat features now GA on GitHub



