powershell-toolbox

A grab-bag of my PowerShell scripts, each one standalone

Copy one out and it still runs. The three in it now tidy up a GitHub account through the gh CLI: list every repo, put them all in one file for an LLM, then go through them one at a time.

Real output, recorded 2026-11-05 against my GitHub account. Private repos are left out.

PS> .\Get-RepoList.ps1
Name                        Status           Language   Pushed     Description
----                        ------           --------   ------     -----------
agent-toolkit               public           PowerShell 2026-11-05 Pinned installers and config for my coding setup
amazon-order-sync           public           JavaScript 2026-11-05 Syncs your Amazon orders into local Markdown notes
carify                      public           Shell      2026-11-05 Convert video for Uconnect USB playback, via ffmpeg
certapi                     public           C#         2026-11-05 mTLS API client for the Windows certificate store
forge-framework             public           Python     2026-08-06 Modular offensive-security framework with a Metasploit-style console - 60+ modules covering Active Directory, AD CS, Kerberos, SMB and web attacks, a persistent evidence workspace, and self-contained Docker labs (Samba AD DC, Windows Server 2022, Windows 11, Enterprise CA) that every module is integration-tested against.
identity-gen                public           HTML       2026-11-05 Offline generator for throwaway signup identities
killer-skills               public           JavaScript 2026-11-05 Claude Code skills for sites, repo pages and review councils
Kraken                      public, archived Rust       2026-06-20 OPSEC-first Rust C2 framework with minimal core and runtime modules
Lure                        public, archived Python     2026-06-20 SMB hash bait for authorized red team engagements - drops poisoned .url/.scf/.xml payloads onto writable shares to coerce NTLM authentication via Responder
Maelstrom                   public, archived Python     2026-06-20 NetExec wrapper combining 35+ AD enumeration modules into a single command
open-file                   public           TypeScript 2026-11-05 Learn and play chess in your browser, offline
port-sync                   public           PowerShell 2026-11-05 Keeps qBittorrent's port synced to Proton VPN
powershell-toolbox          public           PowerShell 2026-11-05 A grab-bag of my PowerShell scripts, each one standalone
proxflow                    public           TypeScript 2026-11-05 Proxmox map and lab builder that works offline
Rapids                      public, archived Python     2026-06-20 Modular credential spraying framework for authorized security testing
Real-Fruit-Snacks           public           Python     2026-11-05 Profile README
Real-Fruit-Snacks.github.io public           HTML       2026-11-05 Real tools. No filler.
rfs.tools                   public           HTML       2026-11-04 The front door at rfs.tools, one page pointing at GitHub
rfs-brand                   public           Python     2026-11-05 RFS brand, profile art and repo templates
screen-mark                 public           Rust       2026-11-05 Screenshot capture and annotation in pure Rust
Undertow                    public, archived Go         2026-06-20 Statically-linked SSH server for penetration testing - reverse/bind shells, SFTP, port forwarding, TLS wrapping with SNI spoofing, single static binary under 1.5MB. Written in Go.

Real run, recorded 2026-11-05 and sped up here: 16 repos took 17.5 s.

PS> .\Get-RepoDigest.ps1 -GitHub
Listing GitHub repos
  [1/16] Real-Fruit-Snacks/amazon-order-sync
  [2/16] Real-Fruit-Snacks/certapi
  [3/16] Real-Fruit-Snacks/agent-toolkit
  [4/16] Real-Fruit-Snacks/carify
  [5/16] Real-Fruit-Snacks/Real-Fruit-Snacks
  [6/16] Real-Fruit-Snacks/Real-Fruit-Snacks.github.io
  [7/16] Real-Fruit-Snacks/identity-gen
  [8/16] Real-Fruit-Snacks/killer-skills
  [9/16] Real-Fruit-Snacks/proxflow
  [10/16] Real-Fruit-Snacks/port-sync
  [11/16] Real-Fruit-Snacks/screen-mark
  [12/16] Real-Fruit-Snacks/open-file
  [13/16] Real-Fruit-Snacks/powershell-toolbox
  [14/16] Real-Fruit-Snacks/rfs-brand
  [15/16] Real-Fruit-Snacks/rfs.tools
  [16/16] Real-Fruit-Snacks/forge-framework

Wrote C:\Users\you\Projects\repos-digest.md (105 KB)

PS> Get-Content $HOME\Projects\repos-digest.md | Select-Object -Skip 4 -First 10
## GitHub repos (16)

| Repo | Lang | Private | Last push | Description |
|---|---|---|---|---|
| Real-Fruit-Snacks/amazon-order-sync | JavaScript | False | 2026-11-05 | Syncs your Amazon orders into local Markdown notes |
| Real-Fruit-Snacks/certapi | C# | False | 2026-11-05 | mTLS API client for the Windows certificate store |
| Real-Fruit-Snacks/agent-toolkit | PowerShell | False | 2026-11-05 | Pinned installers and config for my coding setup |
| Real-Fruit-Snacks/carify | Shell | False | 2026-11-05 | Convert video for Uconnect USB playback, via ffmpeg |
| Real-Fruit-Snacks/Real-Fruit-Snacks | Python | False | 2026-11-05 | Profile README |
| Real-Fruit-Snacks/Real-Fruit-Snacks.github.io | HTML | False | 2026-11-05 | Real tools. No filler. |

A real -WhatIf run against my public repos, recorded 2026-11-05. The keys replay it; nothing here reaches GitHub.

PS> .\Invoke-RepoReview.ps1 -SortBy size -WhatIf
Fetching repos

Reviewing 16 repos, sorted by size. Dry run: nothing will change.
Log: C:\Users\you\Projects\repo-review-20261105-053734.log

----------------------------------------------------------------------
[1/16] Real-Fruit-Snacks/open-file
   public   26.6 MB   last push 2026-11-05 (0 days ago)
   Learn and play chess in your browser, offline
   https://github.com/Real-Fruit-Snacks/open-file

   [D] delete   [A] archive   [K] keep   [O] open in browser   [Q] quit  k

----------------------------------------------------------------------
[2/16] Real-Fruit-Snacks/certapi
   public   7.0 MB    last push 2026-11-05 (0 days ago)
   mTLS API client for the Windows certificate store
   https://github.com/Real-Fruit-Snacks/certapi

   [D] delete   [A] archive   [K] keep   [O] open in browser   [Q] quit  a
What if: Performing the operation "Archive repository" on target "Real-Fruit-Snacks/certapi".

----------------------------------------------------------------------
[3/16] Real-Fruit-Snacks/rfs-brand
   public   3.2 MB    last push 2026-11-05 (0 days ago)
   RFS brand, profile art and repo templates
   https://github.com/Real-Fruit-Snacks/rfs-brand

   [D] delete   [A] archive   [K] keep   [O] open in browser   [Q] quit  q

Stopped. Deleted: 0  Archived: 0  Kept: 1  Failed: 0  Remaining: 14
Log: C:\Users\you\Projects\repo-review-20261105-053734.log

Get them

All of them

cd $HOME\Projects; git clone https://github.com/Real-Fruit-Snacks/powershell-toolbox; cd powershell-toolbox

They assume your projects live in C:\Users\<you>\Projects, and every file they write goes there. Get-Help .\<script>.ps1 -Full lists every parameter.

Just one

iwr https://raw.githubusercontent.com/Real-Fruit-Snacks/powershell-toolbox/main/Invoke-RepoReview.ps1 -OutFile Invoke-RepoReview.ps1

Each script carries everything it needs, so the one file is enough. This line follows the script picked above.

They need gh

winget install GitHub.cli; gh auth login

They wrap the GitHub CLI, so they see whatever your gh login sees, private repos included. If the execution policy blocks a script: powershell -ExecutionPolicy Bypass -File .\Get-RepoList.ps1

The scripts, as Get-Help shows them

Get-RepoList.ps1

Description

Pulls the repo list through the gh CLI, so private repos are included when your token can see them. Emits one row per repo: Name, Description, Visibility, Archived, Fork, Template, Empty, Language, Pushed, Stars, Url. Writes a table, objects on the pipeline, CSV, JSON, or a Markdown table. For an org's private repos the token also needs the read:org scope.

Syntax

.\Get-RepoList.ps1 [[-Owner] <String>] [[-Format] <String>] [[-OutFile] <String>] [[-Limit] <Int32>] [-ExcludeForks] [<CommonParameters>]

Parameters

ParameterEffect
-OwnerGitHub user or org. Defaults to the account gh is logged in as.
-FormatTable (default), Object, Csv, Json or Markdown.
-OutFileWrite the output to a file instead of the console. A relative path goes in your projects folder; an absolute path is used as given. Table output is written as plain text, Object output as Clixml.
-LimitMax repos to fetch. Default 1000.
-ExcludeForksLeave forks out. They are listed by default.

Examples

.\Get-RepoList.ps1 -Owner Real-Fruit-Snacks -Format Markdown -OutFile repos.md   # Projects\repos.md
.\Get-RepoList.ps1 -Format Object | Where-Object Archived | Select-Object Name, Pushed
.\Get-RepoList.ps1 -Format Csv -OutFile repos.csv -ExcludeForks

Get-RepoDigest.ps1

Description

Made for handing a whole set of repos to an LLM as a single upload. For GitHub repos (through the gh CLI) it writes a summary table, then per repo the metadata, topics, top-level file list and README. For local folders it treats every top-level directory under each root as a project and records git info (remote, branch, commit count, uncommitted files), manifests, a file-type count and the README.

Syntax

.\Get-RepoDigest.ps1 [-GitHub] [[-Owner] <String>] [-Local] [[-LocalRoot] <String[]>] [[-OutFile] <String>] [[-MaxReadmeChars] <Int32>] [-IncludeArchived] [-IncludeForks] [<CommonParameters>]

Parameters

ParameterEffect
-GitHubInclude GitHub repos. Needs gh, logged in with gh auth login.
-OwnerGitHub user or org for -GitHub. Defaults to the account gh is logged in as.
-LocalInclude every folder in your projects folder (default C:\Users\<you>\Projects).
-LocalRootOther folders whose top-level subfolders are treated as projects. Combines with -Local.
-OutFileWhere to write the digest. Default: repos-digest.md in your projects folder. A relative path goes in the projects folder; an absolute path is used as given.
-MaxReadmeCharsCut each README after this many characters. Default 8000.
-IncludeArchivedInclude archived GitHub repos. Skipped by default.
-IncludeForksInclude forked GitHub repos. Skipped by default.

Examples

.\Get-RepoDigest.ps1 -GitHub            # your GitHub repos only
.\Get-RepoDigest.ps1 -GitHub -Local     # and every folder in Projects, in one file
.\Get-RepoDigest.ps1 -GitHub -Owner Real-Fruit-Snacks -Local -OutFile all.md -MaxReadmeChars 12000

Invoke-RepoReview.ps1

Description

Uses the gh CLI. For every repo it shows the name, visibility, size, last push, fork/archived flags and description, then asks [D] delete [A] archive [K] keep [O] open in browser [Q] quit. Delete asks a second time: type the repo name exactly. Every decision is appended to a log file. -WhatIf walks the same list without changing anything.

Syntax

.\Invoke-RepoReview.ps1 [[-Owner] <String>] [[-Limit] <Int32>] [[-SortBy] <String>] [-IncludeForks] [-IncludeArchived] [[-LogPath] <String>] [-WhatIf] [-Confirm] [<CommonParameters>]

Parameters

ParameterEffect
-OwnerGitHub user or org to list repos for. Defaults to the account gh is logged in as.
-LimitMax repos to fetch. Default 1000.
-SortBypushed (oldest first, default), name, or size (largest first).
-IncludeForksInclude forked repos. Skipped by default.
-IncludeArchivedInclude archived repos. Skipped by default.
-LogPathWhere to write the decision log. Default: repo-review-<timestamp>.log in your projects folder. A relative path goes in the projects folder; an absolute path is used as given.
-WhatIfWalks the list and logs WHATIF for each archive or delete. Changes nothing.

Examples

.\Invoke-RepoReview.ps1 -SortBy size -WhatIf     # a dry run, largest first
.\Invoke-RepoReview.ps1 -Owner my-org -SortBy size
.\Invoke-RepoReview.ps1 -IncludeForks -IncludeArchived -WhatIf

Safety

Only Invoke-RepoReview.ps1 changes anything on GitHub: it archives when you press A, and deletes only after you type the name.

  • Delete asks again. You type the repo name exactly, and case counts: Open-file is not open-file.
  • -WhatIf changes nothing. It walks the same list, prints what it would do, and logs WHATIF.
  • Every decision is logged to repo-review-<time>.log in your projects folder: KEPT, ARCHIVED, DELETED, FAILED, QUIT.
  • Deleting needs the delete_repo scope on your gh token. The script offers to add it: gh auth refresh -h github.com -s delete_repo. Tokens that don't list their scopes, such as fine-grained ones, skip that check.
  • There is no undo here. GitHub keeps most deleted repos restorable for 90 days (Settings, Repositories, Deleted repositories). Forks, and repos that were part of a fork network, can't be restored there.
  • Nothing goes anywhere but GitHub, through gh. To report a way round any of this, use private vulnerability reporting.

Settings

VariableEffect
RFS_PROJECTSYour projects folder. Default $HOME\Projects. Relative -OutFile and -LogPath values land here; absolute paths are used as given.
RFS_THEMEdayshift for a light terminal. Nightshift, for dark terminals, is the default.
NO_COLORAny value: plain text, no colour at all (no-color.org).

To set a different projects folder for good: [Environment]::SetEnvironmentVariable('RFS_PROJECTS', 'D:\code', 'User'), then open a new window. In an old conhost window without VT support, output falls back to the nearest of the 16 console colours.

Tested on

  • Windows PowerShell 5.1 and PowerShell 7.6 on Windows Server 2025, and PowerShell 7.6 on Ubuntu 24.04: CI runs the Pester suite on every push, against a stub gh.
  • Windows 11 with Windows PowerShell 5.1 and gh 2.102: the runs on this page, against my real account.
  • Not tested: macOS. It should behave like Linux; I haven't checked.

Known issues

  • Get-RepoDigest.ps1 -GitHub makes two API calls per repo. At the 1,000-repo cap that is 2,000 of GitHub's 5,000 requests an hour, so a third run within the hour can hit the limit.
  • All three fetch at most 1,000 repos by default (-Limit on two of them; the digest is fixed at 1,000).