Files
PSProxmoxVE/CLAUDE.md
T
goodolclint-claude[bot] c706315483 chore: attribute agent commits to the bot identity
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 13:42:10 -05:00

4.9 KiB
Raw Blame History

PSProxmoxVE — Claude Code Instructions

Project Overview

C# binary PowerShell module for managing Proxmox VE (PVE) infrastructure. Two projects:

  • src/PSProxmoxVE/ — Cmdlets and module surface (targets netstandard2.0)
  • src/PSProxmoxVE.Core/ — Services, models, HTTP client (targets netstandard2.0)

Tests: xUnit (tests/PSProxmoxVE.Core.Tests/) and Pester 5 (tests/PSProxmoxVE.Tests/).

Development Workflow

All changes go through pull requests. The main branch has branch protection enabled (required build checks, required review, admin enforced). Never push directly to main.

# Create a feature branch
git checkout -b feat/my-feature

# ... make changes ...

# Commit using conventional commits
git commit -m "feat: add new cmdlet"

# Push and create PR
git push -u origin feat/my-feature
gh pr create

Agent commit identity

.claude/settings.json sets GIT_AUTHOR_* / GIT_COMMITTER_* to goodolclint-claude[bot], so commits made from an agent session are attributed to the App rather than to the operator. The push itself is an ordinary local git push over the operator's SSH key — the env vars change authorship, not transport. No Co-Authored-By trailer is needed when they are in effect.

The env block applies at session start, so a session that predates this file still commits as the operator.

A Docker-based dev environment replicates the full CI setup locally. Works on ARM Macs (build + test) and x86 (full provisioning flow).

./tests/dev.ps1              # Open pwsh shell in dev container
./tests/dev.ps1 build        # Build the module
./tests/dev.ps1 test         # Run unit tests (ARM + x86)
./tests/dev.ps1 integration  # Provision nested PVE, run tests, cleanup (x86 only)
./tests/dev.ps1 provision    # Provision nested PVE only, no tests (x86 only)

Configure parent PVE credentials by copying tests/.env.test.example to tests/.env.test.

Build & test without container

# Build
dotnet build PSProxmoxVE.sln

# xUnit tests
dotnet test tests/PSProxmoxVE.Core.Tests/

# Pester tests (requires pwsh)
pwsh -Command "Invoke-Pester tests/PSProxmoxVE.Tests/ -Output Detailed"

# Run all tests via dev container
./tests/dev.ps1 test

Key Conventions

  • All cmdlets use Pve noun prefix
  • All cmdlet classes must be sealed
  • All cmdlets must have [OutputType] attribute
  • Destructive cmdlets must set ConfirmImpact = ConfirmImpact.High
  • VmId parameters: [ValidateRange(100, 999999999)], nullable when optional
  • JSON: Newtonsoft.Json only ([JsonProperty]), no System.Text.Json attributes
  • Task polling: always use TaskService.WaitForTask, never inline loops
  • Passwords: SecureString type, never plain string
  • URL paths: Uri.EscapeDataString() on all dynamic path segments
  • No bare catch {} blocks — use specific or filtered exceptions
  • Verb class constants required (VerbsCommon.Get, not "Get")

Review System

This repo uses a structured review system to track findings and prevent regressions.

Key files

  • docs/review/findings.json — stable findings database. IDs are permanent (F001, F002...). Never renumber. Read this before any coding session to understand open issues.
  • docs/review/REVIEW_REPORT.md — latest full review report (scan-9, 2026-03-26, F001F085)
  • DECISIONS.md — architectural decisions and anti-patterns. Read this before writing any new code. It documents patterns that were deliberately chosen or changed and must not be reintroduced.

Before starting a coding session

  1. Read DECISIONS.md to understand established patterns
  2. Check docs/review/findings.json for open findings relevant to the area you're working in
  3. Do not introduce patterns listed as anti-patterns in DECISIONS.md

Finding ID stability

Finding IDs (F001, F002...) are permanent. A resolved finding is never deleted from findings.json — it is marked resolved with evidence of the fix. If a finding reappears, it is marked regressed and retains its original ID.

Releasing to PSGallery

Tag-driven: pushing a v* tag to main triggers .github/workflows/publish.yml (build → PS 5.1 smoke test → publish to PSGallery → create GitHub Release with auto-generated notes).

Each release PR must update three things in lockstep before the tag is cut:

  1. ModuleVersion in src/PSProxmoxVE/PSProxmoxVE.psd1 (semver patch for bug-fix-only; minor for new features; major for breaking changes).
  2. ReleaseNotes in the same psd1 — this is what PSGallery surfaces on the version page. Replace the previous version's notes; do not append.
  3. CHANGELOG.md — cut the [Unreleased] section into a new [X.Y.Z] - YYYY-MM-DD block and reset [Unreleased] to empty.

After merge, tag main with vX.Y.Z and push the tag. The publish workflow rewrites the psd1 ModuleVersion in the build artifact from the tag, so the tag and the source version must match.