Last active
April 24, 2026 23:32
-
-
Save dfinke/54fda0c0202887efb141011f1810a316 to your computer and use it in GitHub Desktop.
Ask your project folders questions in plain English. This PowerShell script scans, reads .note files or README.md, and helps you recall
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ask-projects.ps1 | |
| # Scans top-level folders and lets you ask natural language questions about your projects. | |
| # Requires PSAISuite module (Invoke-ChatCompletion). | |
| # | |
| # USAGE: | |
| # .\ask-projects.ps1 -Root "C:\Dev" -Ask "what did I work on last week?" | |
| # .\ask-projects.ps1 -Root "C:\Dev" -Ask "anything related to python scraping?" | |
| # .\ask-projects.ps1 -Root "C:\Dev" -Ask "what did I create this month?" -Model "anthropic:claude-sonnet-4-20250514" | |
| # | |
| # BREADCRUMB FILES (optional but recommended): | |
| # Drop a ".note" file in any project folder with a one-line description. | |
| # Example: "Testing a RAG pipeline with local file embeddings" | Out-File .note | |
| #Requires -Modules PSAISuite | |
| param( | |
| [Parameter(Mandatory = $true)] | |
| [string]$Root, | |
| [Parameter(Mandatory = $true)] | |
| [string]$Ask, | |
| [string]$Model = "openai:gpt-4o", | |
| [int]$MaxFolders = 200 | |
| ) | |
| # ── Validate ────────────────────────────────────────────────────────────────── | |
| if (-not (Test-Path $Root)) { | |
| Write-Error "Root folder not found: $Root" | |
| exit 1 | |
| } | |
| # ── Scan top-level folders ──────────────────────────────────────────────────── | |
| Write-Host "Scanning: $Root" -ForegroundColor Cyan | |
| $folders = Get-ChildItem -Path $Root -Directory -ErrorAction SilentlyContinue | | |
| Select-Object -First $MaxFolders | |
| if ($folders.Count -eq 0) { | |
| Write-Error "No folders found in $Root" | |
| exit 1 | |
| } | |
| Write-Host "Found $($folders.Count) folders. Building summary..." -ForegroundColor Cyan | |
| $summaries = @() | |
| foreach ($folder in $folders) { | |
| $created = $folder.CreationTime.ToString("yyyy-MM-dd") | |
| $modified = $folder.LastWriteTime.ToString("yyyy-MM-dd") | |
| # Breadcrumb: prefer .note, fall back to README.md | |
| $breadcrumb = "" | |
| $notePath = Join-Path $folder.FullName ".note" | |
| $readmePath = Join-Path $folder.FullName "README.md" | |
| if (Test-Path $notePath) { | |
| $raw = Get-Content $notePath -Raw -ErrorAction SilentlyContinue | |
| if ($raw) { $breadcrumb = $raw.Trim().Substring(0, [Math]::Min(300, $raw.Trim().Length)) } | |
| } | |
| elseif (Test-Path $readmePath) { | |
| $raw = Get-Content $readmePath -Raw -ErrorAction SilentlyContinue | |
| if ($raw) { | |
| $snippet = $raw.Trim().Substring(0, [Math]::Min(300, $raw.Trim().Length)) | |
| $breadcrumb = "[README] $snippet" | |
| } | |
| } | |
| # Top-level file type breakdown (no recursion) | |
| $files = Get-ChildItem -Path $folder.FullName -File -ErrorAction SilentlyContinue | |
| $typeBreakdown = "" | |
| if ($files) { | |
| $typeBreakdown = $files | | |
| Group-Object Extension | | |
| Sort-Object Count -Descending | | |
| Select-Object -First 6 | | |
| ForEach-Object { "$($_.Count)$($_.Name)" } | | |
| Join-String -Separator ", " | |
| } | |
| $entry = [ordered]@{ | |
| name = $folder.Name | |
| created = $created | |
| modified = $modified | |
| files = if ($typeBreakdown) { $typeBreakdown } else { "empty" } | |
| } | |
| if ($breadcrumb) { $entry["note"] = $breadcrumb } | |
| $summaries += $entry | |
| } | |
| # ── Build prompt ────────────────────────────────────────────────────────────── | |
| $now = Get-Date | |
| $today = $now.ToString("yyyy-MM-dd") | |
| # Anchor common relative terms to exact dates | |
| $yesterday = $now.AddDays(-1).ToString("yyyy-MM-dd") | |
| $weekStart = $now.AddDays( - ([int]$now.DayOfWeek - 1)).ToString("yyyy-MM-dd") # Monday | |
| $monthStart = (Get-Date -Day 1).ToString("yyyy-MM-dd") | |
| $last7 = $now.AddDays(-7).ToString("yyyy-MM-dd") | |
| $last30 = $now.AddDays(-30).ToString("yyyy-MM-dd") | |
| $jsonData = $summaries | ConvertTo-Json -Depth 3 -Compress | |
| $prompt = @" | |
| Today's date is $today. | |
| For reference: | |
| - "today" = $today | |
| - "yesterday" = $yesterday | |
| - "this week" = $weekStart to $today (Monday to today) | |
| - "last 7 days"= $last7 to $today | |
| - "this month" = $monthStart to $today | |
| - "last 30 days"= $last30 to $today | |
| Use the "modified" date to determine recency. Be strict about date ranges — | |
| only include folders whose modified date falls within the requested period. | |
| You are helping a developer recall what they have been working on. | |
| Each entry below is a top-level project folder with its name, created date, last modified date, | |
| file type breakdown, and optionally a "note" or README snippet describing the project. | |
| Treat the note/README as the most reliable description of what the folder contains. | |
| Answer naturally and concisely. Group or highlight folders where useful. | |
| If nothing matches the timeframe, say so clearly. | |
| Folders: | |
| $jsonData | |
| Question: $Ask | |
| "@ | |
| # ── Ask ─────────────────────────────────────────────────────────────────────── | |
| Write-Host "Asking ($Model): $Ask`n" -ForegroundColor Cyan | |
| Invoke-ChatCompletion -Model $Model $prompt |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment