Read this at session start. It is the standing context for any agent touching this repo.
A professional snipping tool for Windows 11 written in pure PowerShell 7.5+ on .NET 9. Smart hover-to-highlight capture, magnifier loupe, floating widget, system tray, chromeless WPF Fluent preview with a full annotation editor — single script, zero external runtime dependencies, no admin elevation.
The single-file shape (SnipIT.ps1) is a headline product feature — do not split it into modules without explicit board reversal.
SnipIT.ps1 113K the whole app (regions: Core / Bootstrap / PInvoke / Capture / Preview / Tray / Main)
Test-SnipIT.ps1 29K 40 pure-logic unit tests (Linux + Windows pwsh, no Pester)
Test-SnipIT-Interactive.ps1 26K 42 WPF integration tests against a real off-screen preview window (Windows only)
README.md install / hotkeys / usage / architecture (also: badges)
SECURITY.md disclosure policy + scope
LICENSE MIT — Amit Kumar
CLAUDE.md this file
.bestpractices.json OpenSSF Best Practices self-assessment (project_id 12647)
shared/runbooks/engineering-standards.md PowerShell variant of the company runbook
scripts/setup-git-signed.sh one-shot signed-commit setup for a fresh worktree
docs/ design notes + screenshots
.github/
├── workflows/
│ ├── test.yml headless tests (Linux + Windows) + Windows AST parse
│ ├── security.yml OSS-CLI stack: PSScriptAnalyzer · Trivy · Semgrep · Gitleaks · jscpd · SBOM
│ └── scorecard.yml OpenSSF Scorecard (push to main + Mondays 06:00 UTC)
└── dependabot.yml github-actions ecosystem, weekly, grouped
snipIT has no compile or package step — SnipIT.ps1 is the deliverable.
| Action | Command |
|---|---|
| Run the app | pwsh -Sta -File ./SnipIT.ps1 (Windows; double-click also works) |
| Headless unit tests (any platform) | pwsh -NoProfile -File ./Test-SnipIT.ps1 |
| Interactive WPF tests (Windows only) | pwsh -NoProfile -Sta -File ./Test-SnipIT-Interactive.ps1 |
| PSScriptAnalyzer (lint) | pwsh -c "Invoke-ScriptAnalyzer -Path ./SnipIT.ps1 -Severity Error" |
| Parse-only (Windows) | pwsh -NoProfile -Command "[System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path ./SnipIT.ps1), [ref]\$null, [ref]\$errors)" |
CI runs the same matrix on every PR (see .github/workflows/test.yml).
- PowerShell 7.5+ only. No PS5.1 fallbacks, no
Add-Typeshims that only compile on Windows PowerShell. - Functions:
Verb-NounPascalCase, approved verbs,[CmdletBinding()]+param()for anything > 1 arg. - The
Coreregion exports 10 pure functions designed to run on Linux pwsh. Adding a new pure helper? Put it inCoreso the test suite picks it up via-CoreOnly. - Preview-window mouse handlers are named closures captured at window-creation time (see
Build-PreviewWindowand the closures$beginPan,$pickColor,$handleMouseDown, …). The real WPF event handlers are one-line wrappers that call them. Tests drive every code path through these closures via the-TestActionhook onShow-PreviewWindow. SNIPIT_TEST_MODE=1short-circuits the single-instance mutex, tray, hotkeys, and main loop so a harness can dot-sourceSnipIT.ps1without side effects.- All commits on
mainare signed (SSH key, registered as both auth + signing key on GitHub). Runscripts/setup-git-signed.shonce per worktree.
The repo follows shared/runbooks/engineering-standards.md (PowerShell variant of the company canonical at /home/dev/.paperclip/instances/default/companies/31b9e445-1e14-45b6-9457-cfbb5cb17144/shared/runbooks/engineering-standards.md). TL;DR:
- Quality gates that block merge: tests, AST parse, PSScriptAnalyzer Error, Trivy HIGH/CRITICAL, Semgrep ERROR, Gitleaks, jscpd < 3%, signed commits.
- Surfaces only (do not block merge): SBOM, OpenSSF Scorecard score, Dependabot PRs.
- OSS-CLI only. No Sonar, no CodeQL, no NVD-direct tools (no PowerShell pack for CodeQL today; Semgrep + PSScriptAnalyzer cover SAST + lint).
| Aspect | Value |
|---|---|
| Workflow | .github/workflows/scorecard.yml (push to main + weekly Mondays 06:00 UTC + manual dispatch) |
| Engine | ossf/scorecard-action@v2.4.3 (SHA-pinned to 4eaacf0543bb3f2c246792bd56e8cdeffafb205a) |
| Output | SARIF → GitHub Security tab + public dashboard at https://securityscorecards.dev/viewer/?uri=github.com/RandomCodeSpace/snipIT |
| Baseline (RAN-54 land) | TBD — first scoreboard score will land on the first push to main after this PR merges. Recorded here in the next PR that touches CLAUDE.md. |
| Target | Best-effort, do not regress. Stretch ≥ 8.0 / 10. Best Practices passing is the only OpenSSF gate that blocks merge — Scorecard is observational. (Per shared/runbooks/engineering-standards.md §1 and the company runbook §9b.) |
| Configured-for-pass checks (RAN-54 bootstrap) | Branch-Protection (per §7), Code-Review (TechLead via Codex), Signed-Releases (tag.gpgsign=true), Dependency-Update-Tool (Dependabot, weekly, grouped), Pinned-Dependencies (every action SHA-pinned), CI-Tests (test.yml + security.yml required), CII-Best-Practices (.bestpractices.json + project 12647), Dangerous-Workflow (no pull_request_target + untrusted-checkout), License (MIT at root), Maintained (active commit cadence), Packaging (no public binary publish — script is the package), SAST (Semgrep + PSScriptAnalyzer), Security-Policy (SECURITY.md), Token-Permissions (permissions: read-all top-level), Vulnerabilities (Trivy gate), Webhooks (none configured). |
| Known not-a-pass (and why) | Packaging — snipIT does not publish a versioned binary artifact (the script is the deliverable; git clone + run is the install path). Scorecard's Packaging check looks for a published-via-CI release; absent here by design until a tagged-release flow is added. |
A material Scorecard regression on a PR files a follow-up chore (type:chore, area:security); it does not block the PR.
- Project page: https://www.bestpractices.dev/en/projects/12647.
- In-repo self-assessment:
.bestpractices.json(project_id 12647, targetpassing). passingis the only OpenSSF gate that blocks merge. Any PR that would fail a passing-level criterion is blocked at review.
- GitHub repo: https://github.com/RandomCodeSpace/snipIT (public, MIT, secret-scanning + push-protection on).
- Paperclip Project:
snipIT(ide6a01833-e7df-4068-849c-6a7c5154b70c). - Paperclip parent issue: RAN-50 — OpenSSF rollout across all 5 paperclip projects.
- Capture loop ownership.
Invoke-CaptureLoop(RAN-14 contract) takes ownership of each capturedSystem.Drawing.Bitmap— the preview disposes it on close, the loop creates a fresh one for each iteration via theCaptureFactoryclosure. Do not dispose the bitmap inside the factory or pre-allocate one outside the loop. - SnipIT-window exclusion in capture. The RAN-15 fix (shipped in v0.1.1) excludes the SnipIT widget / preview / tray windows from the capture targets. If you add a new top-level window, register it via
Hide-OwnSnipITWindowsForCaptureso it's not baked into the frame. - Per-monitor DPI. Capture math is DPI-aware on virtual desktops with mixed scaling. Negative-origin layouts (monitor to the left of the primary) are handled in
Get-VirtualScreenBounds; do not assume(0,0)is the top-left of the virtual desktop. - Single-instance mutex. A second launch shows a friendly notification and exits — unless
SNIPIT_TEST_MODE=1is set (test-harness escape hatch). actions/checkout@v4vs SHA-pin. Workflows in this repo MUST pin every action by commit SHA (ScorecardPinned-Dependencies). Dependabot opens routine bumps; do not manually downgrade to a tag-ref.
Paperclip. Issue prefix RAN (e.g., RAN-54 — this OpenSSF land). Link tickets as [RAN-XX](/RAN/issues/RAN-XX) in PR descriptions and code comments.