built out personal preferences for AI tools

This commit is contained in:
2026-03-10 00:25:39 -07:00
parent 8fc6f77ca6
commit 22b0669f5b
6 changed files with 598 additions and 1 deletions

54
CLAUDE.md Normal file
View File

@@ -0,0 +1,54 @@
# Derek's AI Preferences
This file defines how AI assistants should work with me. Detailed references are in `preferences/`.
---
## Communication Style
- **Default:** Give a brief summary — what it does and why, not a full walkthrough
- **On request:** Go deep. If I ask for detail, explain fully with context
- **Format:** Bullet points and structured output always; avoid prose paragraphs
- **Before working:** Ask clarifying questions first — don't assume and do a bunch of work that needs to be redone
- **Tone:** Direct and concise; no filler, no preamble
See [preferences/communication.md](preferences/communication.md) for full detail.
---
## My Stack
| Context | Technologies |
|---|---|
| Org tooling (IT support) | PowerShell 5.1+, WPF, `.psd1` config files |
| Web apps (self-hosted) | FastAPI, async SQLAlchemy 2.0, MySQL 8, Docker Compose, Nginx |
| Static site | Hugo |
| Container management | Portainer |
| Version control | Gitea (self-hosted) |
---
## Always Do
- **Tests first:** Always provide a way to immediately test/run the code you write
- **No credentials in code:** Secrets go in `.env` files; always provide a `.env.example`
- **Consistent style:** Follow the conventions for the language in use — see preferences files
- **Ask before big changes:** Clarify scope before rewriting or restructuring
---
## Never Do
- Commit automatically unless explicitly asked
- Add features, refactoring, or cleanup beyond what was asked
- Put credentials, passwords, or tokens directly in code or config files
- Switch to a different stack/library without asking first
---
## Detailed References
- [preferences/communication.md](preferences/communication.md) — Response style and interaction rules
- [preferences/powershell-wpf.md](preferences/powershell-wpf.md) — PowerShell and WPF coding standards
- [preferences/python-web.md](preferences/python-web.md) — FastAPI, SQLAlchemy, Docker standards
- [preferences/project-structure.md](preferences/project-structure.md) — Standard folder layouts per project type

123
README.md
View File

@@ -1,2 +1,123 @@
# AI
# AI Preferences
A personal repository of markdown files that define how AI systems should work with me. Instead of re-explaining preferences every session, these files act as a persistent "operating manual" that can be loaded into any AI tool.
---
## What's in This Repo
```
AI/
├── CLAUDE.md # Main entry point — loaded automatically by Claude Code
└── preferences/
├── communication.md # How I like responses structured and how to interact
├── powershell-wpf.md # Standards for PowerShell and WPF applications
├── python-web.md # Standards for FastAPI, SQLAlchemy, Docker Compose
└── project-structure.md # Standard folder layouts per project type
```
**`CLAUDE.md`** is the top-level summary. It references the `preferences/` files for detail. This is the file you point AI tools to — or it gets picked up automatically.
**`preferences/`** contains the detail files. Each covers a specific domain. You generally don't point tools directly at these; `CLAUDE.md` references them for context.
---
## How to Use These Files
### Claude Code (Automatic)
Claude Code automatically reads `CLAUDE.md` from the root of any project it's working in.
**Option A — Per project:** Copy `CLAUDE.md` into the root of any project repo. Claude Code will pick it up automatically every session.
**Option B — Global (recommended):** Place `CLAUDE.md` in your Claude global config folder so it applies to *every* project without copying:
```
# Windows
Copy-Item "CLAUDE.md" "$env:USERPROFILE\.claude\CLAUDE.md"
```
> Note: If a project also has its own `CLAUDE.md`, Claude Code merges both — global preferences apply everywhere, project-specific ones add on top.
---
### Cursor
Cursor reads a `.cursorrules` file in the project root.
1. Copy the content of `CLAUDE.md` (and any relevant `preferences/` files) into a file named `.cursorrules` in your project root
2. Cursor will load it automatically as context for all AI interactions in that project
---
### GitHub Copilot (VS Code)
Copilot reads custom instructions from VS Code settings or a `.github/copilot-instructions.md` file.
1. In your project, create `.github/copilot-instructions.md`
2. Paste the content from `CLAUDE.md` into that file
3. Copilot will use it as persistent context for that workspace
---
### ChatGPT / Claude.ai (Manual)
These tools don't auto-load files, so you paste preferences at the start of a conversation.
1. Open `CLAUDE.md`
2. Copy the full contents
3. Paste it as the first message in a new conversation with the instruction: *"These are my preferences. Follow them for this session."*
---
### Other AI Tools
Most AI tools support some form of system prompt or custom instructions. The general approach:
1. Use `CLAUDE.md` as your base — it's written to be tool-agnostic
2. Look for the tool's "system prompt", "custom instructions", or "rules" setting
3. Paste the contents of `CLAUDE.md` there
---
## Keeping Preferences Up to Date
Preferences should evolve as your stack and habits change. Treat this repo like any other project — update it when something no longer matches how you work.
### When to Update
- You adopt a new tool or framework and want it recognized as your standard
- You find yourself correcting an AI on the same thing repeatedly — that's a sign it should be in the docs
- A project convention changes (e.g., switching from one library to another)
- You want to add a new project type template to `project-structure.md`
### How to Update
**Small change (tweak a preference):**
1. Open the relevant `preferences/` file
2. Edit the specific rule
3. Commit: `git commit -m "Update [topic] preference"`
**New topic area (e.g., you start working with a new stack):**
1. Create a new file in `preferences/` — e.g., `preferences/hugo-blog.md`
2. Add a link to it in the `CLAUDE.md` Detailed References section
3. Commit both files together
**Removing something outdated:**
1. Delete or edit the relevant section
2. If a whole `preferences/` file is no longer relevant, delete it and remove its link from `CLAUDE.md`
### After Updating
- If you're using the **global Claude Code** setup, the update applies automatically next session
- If you've **copied** `CLAUDE.md` into other project repos, re-copy the updated version to those projects
- If you're using **ChatGPT/Claude.ai** manually, you'll be pasting the updated file next time
---
## Tips
- **`CLAUDE.md` should stay concise** — it's the quick-reference. Put detail in `preferences/` files
- **Be specific, not general** — "use SQLAlchemy 2.0 async" is more useful than "use good database practices"
- **Version your preferences** — git history lets you see what changed and roll back if needed
- **One preference file per domain** — don't cram everything into one file; keep it organized so it's easy to find and update

View File

@@ -0,0 +1,37 @@
# Communication Preferences
## Response Depth
- **Default level:** Brief summary — what the code/change does, key decisions made, nothing more
- **Deep detail:** When I ask "explain this", "why does this work", or "walk me through it" — go full depth with context, reasoning, and examples
- **Never assume** I want the full explanation unless I ask; don't pad responses
## Format Rules
- Always use **bullet points** and **structured output** (headers, tables, lists)
- Avoid prose paragraphs unless explaining a concept I asked about
- Use code blocks for all code, commands, and file paths
- Keep section headers short and scannable
## Before Doing Work
- **Ask clarifying questions first** — it's better to pause and confirm than to do work that gets thrown away
- If a request is ambiguous, state your interpretation and ask if it's correct before proceeding
- If a task will touch many files or make large structural changes, outline the plan first and get confirmation
## When Something Is Unclear
- Say so directly — don't guess silently
- Offer 23 specific options to choose from rather than an open-ended question when possible
## Errors and Blockers
- Report errors clearly: what failed, why (if known), and what the options are
- Don't retry the same failing approach repeatedly — propose an alternative
## Things to Avoid
- Filler phrases ("Great question!", "Certainly!", "Of course!")
- Restating what I just said before answering
- Explaining things I didn't ask about
- Suggesting improvements or refactors beyond the scope of what was asked

View File

@@ -0,0 +1,121 @@
# PowerShell & WPF Standards
## General Rules
- Always include `#Requires -Version 5.1` at the top of every `.ps1` file
- Use `$script:` scope for module-level variables — never `$Global:` unless absolutely necessary
- Keep credential and sensitive values out of code — load from config files or environment variables only
- Use `.psd1` files for all external configuration (not JSON, not XML, not hardcoded)
## Code Structure
- Organize code using `#region` / `#endregion` blocks with descriptive names
- Group related functions within their own region
- One function per logical task — keep functions focused
```powershell
#region Configuration Functions
function Initialize-Config {
...
}
#endregion
#region UI Functions
function Show-MainWindow {
...
}
#endregion
```
## Naming Conventions
- **Functions:** PascalCase Verb-Noun (`Get-UserConfig`, `Show-MainWindow`, `Initialize-App`)
- **Variables:** PascalCase (`$UserConfig`, `$ScriptRoot`, `$AppVersion`)
- **Script-scoped:** `$script:VariableName`
- Use approved PowerShell verbs (`Get-`, `Set-`, `Show-`, `New-`, `Remove-`, `Initialize-`, `Invoke-`, etc.)
## Error Handling
- Use `try/catch` for all operations that can fail (file I/O, network, registry, etc.)
- Use `Write-Warning` for non-fatal errors that should be logged but allow execution to continue
- Use `Write-Error` for failures that should stop the current operation
- Create centralized helper functions for user-facing messages:
```powershell
function Show-Error { param([string]$Message, [string]$Title = "Error") ... }
function Show-Warning { param([string]$Message, [string]$Title = "Warning") ... }
function Show-Info { param([string]$Message, [string]$Title = "Information") ... }
```
## WPF Specifics
- Always ensure STA thread mode for WPF — include an STA re-launch block at the top of `.ps1` entry points
- Load all WPF assemblies at the top of the file:
```powershell
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
Add-Type -AssemblyName WindowsBase
Add-Type -AssemblyName System.Windows.Forms
```
- Define XAML as a here-string and load it via `[System.Windows.Markup.XamlReader]::Parse()`
- Use `$script:` variables to hold window/control references so they're accessible across functions
## Modules
- Shared/reusable functions belong in a `.psm1` module under a `Modules/` folder
- The main `.ps1` entry point imports the module at startup:
```powershell
Import-Module "$script:AppRoot\Modules\ProjectName.psm1" -Force
```
- Module files follow the same naming, scoping, and region conventions
## Configuration Files
- Use `.psd1` (PowerShell Data Files) for all config — they're native, typed, and easy to version
- Always provide a default config creation block if the file doesn't exist
- Config keys should use PascalCase nested hashtables:
```powershell
@{
Application = @{
WindowWidth = 800
WindowHeight = 600
}
Email = @{
SMTPServer = ''
From = ''
To = ''
}
}
```
- Never put actual credentials in `.psd1` config — use placeholder strings with comments
## Testing
- Use **Pester** for unit testing
- Always provide a Pester test file alongside new functions
- At minimum, test: happy path, expected failure cases, and edge cases
- Run tests with: `Invoke-Pester -Path .\Tests\ -Output Detailed`
```powershell
# Tests/Get-UserConfig.Tests.ps1
Describe "Get-UserConfig" {
It "Returns default config when file does not exist" { ... }
It "Loads config from valid .psd1 file" { ... }
}
```
## Comments
- Comment the **why**, not the **what** — code should be readable on its own
- Use inline comments for non-obvious logic
- Use block comments (`<# ... #>`) for function documentation (`.SYNOPSIS`, `.DESCRIPTION`, `.PARAMETER`, `.EXAMPLE`)

View File

@@ -0,0 +1,116 @@
# Standard Project Structures
## PowerShell / WPF Application
For IT tooling and local GUI applications.
```
ProjectName/
├── ProjectName.ps1 # Main entry point — UI, startup, STA check
├── company-settings.psd1 # External config — no credentials
├── README.md
├── Modules/
│ └── ProjectName.psm1 # Shared functions, config loading, helpers
├── Tests/
│ └── *.Tests.ps1 # Pester test files
└── Release-Notes/
├── v1.0.md
└── v1.1.md
```
**Rules:**
- Entry `.ps1` handles: STA check, assembly loading, module import, config load, show window
- All reusable logic lives in the `.psm1` module, not inline in the entry point
- Config file is always in the same directory as the script
- `Release-Notes/` uses one file per version: `v{major}.{minor}.md`
---
## FastAPI Web Application (Docker Compose)
For self-hosted web apps running behind Nginx.
```
project-name/
├── docker-compose.yml
├── .env.example # Always committed — placeholder values only
├── .gitignore # Must include .env
├── README.md
├── nginx/
│ └── default.conf
└── backend/
├── Dockerfile
├── requirements.txt
└── app/
├── main.py
├── config.py
├── database.py
├── dependencies.py
├── models/
│ └── user.py
├── schemas/
│ └── user.py
├── routers/
│ ├── auth.py
│ └── [resource].py
├── utils/
└── tests/
└── test_[resource].py
```
**Rules:**
- `.env` is never committed — `.env.example` always is
- Each resource (users, items, etc.) gets its own model, schema, and router file
- Tests live inside `backend/app/tests/`
---
## Hugo Blog (chns.tech)
Static site for tech blog posts.
```
site/
├── hugo.toml # Site config
├── content/
│ └── posts/
│ └── YYYY-MM-DD-post-title.md
├── themes/
├── static/
└── layouts/
```
**Post front matter standard:**
```yaml
---
title: "Post Title"
date: YYYY-MM-DD
draft: false
tags: ["tag1", "tag2"]
---
```
---
## Git Conventions
- **Branch:** Commit directly to `main` (solo projects)
- **Commit messages:** Short imperative summary — `Add user auth`, `Fix config loading`, `Update README`
- **Never commit:** `.env`, credentials, compiled binaries, `node_modules`, `__pycache__`
- **Always include** a `.gitignore` appropriate for the project type
### Standard `.gitignore` entries
**PowerShell projects:**
```
*.exe
company-settings.psd1 # If it contains org-specific paths
```
**Python projects:**
```
.env
__pycache__/
*.pyc
.pytest_cache/
```

148
preferences/python-web.md Normal file
View File

@@ -0,0 +1,148 @@
# Python Web Stack Standards
## Stack
- **API:** FastAPI (async)
- **ORM:** async SQLAlchemy 2.0 with ORM models (not raw queries)
- **Database:** MySQL 8
- **Runtime:** Docker Compose
- **Reverse proxy:** Nginx
- **Container management:** Portainer
## Project Layout
```
project-name/
├── docker-compose.yml
├── .env.example # Template — always include this, never commit .env
├── .gitignore
├── README.md
├── nginx/
│ └── default.conf
└── backend/
├── Dockerfile
├── requirements.txt
└── app/
├── main.py # App entry point, router registration, startup events
├── config.py # Settings loaded from environment via pydantic-settings
├── database.py # Async SQLAlchemy engine and session factory
├── dependencies.py # Shared FastAPI dependencies (auth, db session, etc.)
├── models/ # SQLAlchemy ORM table definitions
├── schemas/ # Pydantic request/response models
├── routers/ # API endpoint handlers, one file per resource
└── utils/ # Shared helpers
```
## Configuration & Secrets
- All secrets and environment-specific values go in `.env` — never hardcode them
- Always provide `.env.example` with placeholder values and comments explaining each variable
- Load settings via `pydantic-settings`:
```python
# app/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
db_host: str
db_port: int = 3306
db_name: str
db_user: str
db_password: str
secret_key: str
class Config:
env_file = ".env"
settings = Settings()
```
## Database (SQLAlchemy 2.0 Async)
- Use async engine and session factory
- Define models with `DeclarativeBase`
- One model per file in `models/`
```python
# app/database.py
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import DeclarativeBase
engine = create_async_engine(DATABASE_URL, echo=False)
AsyncSessionLocal = async_sessionmaker(engine, expire_on_commit=False)
class Base(DeclarativeBase):
pass
```
- Inject DB sessions via FastAPI dependencies (not global sessions)
- Use `async with session.begin()` for transactions
## Models
- One file per table in `models/`
- Use typed columns with SQLAlchemy 2.0 `Mapped` syntax:
```python
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
username: Mapped[str] = mapped_column(unique=True)
email: Mapped[str]
```
## Schemas (Pydantic)
- Separate schemas for Create, Update, and Response — don't reuse the same schema for all three
- Response schemas should never expose password hashes or internal fields
```python
class UserCreate(BaseModel): ...
class UserResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
```
## Routers
- One router file per resource (e.g., `routers/users.py`, `routers/auth.py`)
- Register all routers in `main.py` with a consistent prefix and tags
## Docker Compose
- Use named volumes for persistent data (database, uploads)
- Always define a `healthcheck` for the database service
- Use `depends_on` with `condition: service_healthy` for the backend
- Keep the Nginx config in a `nginx/` folder and mount it as a volume
```yaml
services:
db:
image: mysql:8
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
backend:
build: ./backend
depends_on:
db:
condition: service_healthy
```
## Testing
- Use **pytest** with **pytest-asyncio** for async tests
- Always provide a test for each router endpoint at minimum (happy path + 1 failure case)
- Use a separate test database — never run tests against the real DB
- Run with: `pytest -v`
## Comments
- Docstrings on all functions that aren't self-explanatory
- Comment the **why** for non-obvious logic, not the what