diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..79dac5a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,110 @@ +# Stegasoo — Claude Code Project Guide + +Stegasoo is a secure steganography toolkit with hybrid photo + passphrase + PIN authentication. +Version 4.2.1 · Python >=3.11 · MIT License + +## Quick commands + +```bash +pip install -e ".[dev]" # Install for development (includes all extras) +pytest # Run tests (coverage reported automatically) +black src/ tests/ frontends/ # Format code +ruff check src/ tests/ frontends/ --fix # Lint (auto-fix) +mypy src/ # Type check +pre-commit run --all-files # Run all pre-commit hooks +PYTHONPATH=src python -m stegasoo.cli # Run CLI directly without install +``` + +## Architecture + +``` +src/stegasoo/ Core library + crypto.py Argon2id / PBKDF2 key derivation + AES-256-GCM encryption + steganography.py LSB spatial embedding + dct_steganography.py DCT domain embedding (JPEG-safe, needs [dct] extras) + validation.py Input validation for all security factors + constants.py All magic numbers, crypto params, limits + models.py Dataclasses (EncodeResult, DecodeResult, etc.) + encode.py / decode.py High-level encode/decode orchestration + channel.py Channel key management (v4.0+) + compression.py Zstandard / zlib / lz4 payload compression + cli.py Click CLI entry point + generate.py Credential generation (passphrase, PIN, RSA keys) + exceptions.py Exception hierarchy (all inherit StegasooError) + __init__.py Public API surface (__all__) + +frontends/web/ Flask web UI (entry: app.py) +frontends/api/ FastAPI REST API (entry: main.py) +frontends/cli/ CLI extras + +tests/ Pytest suite + test_stegasoo.py Single test file covering core library +``` + +### Entry points + +| Interface | Entry point | Install extra | +|-----------|-------------|---------------| +| CLI | `stegasoo.cli:main` (`stegasoo` command) | `[cli]` | +| Web UI | `frontends/web/app.py` | `[web]` | +| REST API | `frontends/api/main.py` | `[api]` | + +## Code conventions + +- **Formatter**: Black, 100-char line length +- **Linter**: Ruff — rules E, F, I, N, W, UP (E501 ignored). N803/N806 suppressed in `dct_steganography.py` for colorspace variable names +- **Type hints**: Required on all new code. `mypy` with `ignore_missing_imports = true` +- **Pre-commit hooks**: ruff, ruff-format, trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-added-large-files (1MB), check-merge-conflict, debug-statements, bandit (excludes tests/) +- **Branch naming**: `feature/`, `fix/`, `docs/`, `refactor/` +- **Commits**: Imperative mood, clear subject line. Include what + why + +## Security-critical modules + +These files implement the cryptographic and steganographic core. Changes require extra care, thorough test coverage, and careful review: + +- **`crypto.py`** — Argon2id KDF (256 MB / 4 iterations / 4 parallelism) + PBKDF2 fallback (600K iterations) → AES-256-GCM authenticated encryption +- **`steganography.py`** — LSB spatial embedding/extraction +- **`dct_steganography.py`** — DCT domain embedding with Reed-Solomon error correction +- **`validation.py`** — Input validation for all security factors (PIN, passphrase, image, RSA key, channel key) +- **`constants.py`** — Crypto parameters (salt sizes, iteration counts, Argon2 memory cost, format versions). Do not change these casually — they affect backward compatibility and security margins + +## Public API + +`src/stegasoo/__init__.py` defines the full public API surface via `__all__`. Any new public function must be: +1. Imported in `__init__.py` +2. Added to the `__all__` list + +## Testing + +- Single test file: `tests/test_stegasoo.py` +- Requires `pip install -e ".[dev]"` (includes DCT dependencies) +- Coverage is reported automatically via pytest config (`--cov=stegasoo --cov-report=term-missing`) +- Run: `pytest` (no extra flags needed) + +## Worktree workflow + +When working on features or fixes that touch multiple files, prefer using a git worktree for isolation: + +```bash +# Claude Code can create worktrees automatically via /worktree or EnterWorktree +# Manual creation: +git worktree add .claude/worktrees/ -b +``` + +### Guidelines for worktree usage + +- **Use worktrees for**: multi-file refactors, experimental changes, anything that might need to be discarded +- **Worktree location**: `.claude/worktrees/` (gitignored by Claude Code) +- **Branch from**: always branch from `main` unless working on a version branch (e.g., `4.2`) +- **Naming**: use the same conventions as branches — `feature/description`, `fix/description`, etc. +- **Cleanup**: worktrees in `.claude/worktrees/` are ephemeral. Remove with `git worktree remove ` when done +- **Testing in worktrees**: run `pip install -e ".[dev]"` inside the worktree before running tests, since the editable install points to the worktree's source +- **Merging back**: create a PR from the worktree branch, or merge locally into `main` + +## Useful context + +- BIP-39 wordlist lives at `src/stegasoo/data/bip39-words.txt` (used for passphrase generation) +- Docker support: `src/stegasoo/Dockerfile` + `docs/DOCKER_QUICKSTART.md` +- Raspberry Pi builds: `rpi/` directory +- AUR packages: `aur/`, `aur-cli/`, `aur-api/` +- Version is defined in both `pyproject.toml` and `src/stegasoo/__init__.py` — keep them in sync diff --git a/docs/CLAUDE_WORKTREES.md b/docs/CLAUDE_WORKTREES.md new file mode 100644 index 0000000..0981b59 --- /dev/null +++ b/docs/CLAUDE_WORKTREES.md @@ -0,0 +1,224 @@ +# Using Claude Code with Git Worktrees — A Stegasoo Guide + +## What is a worktree? + +A git worktree is a second (or third, or fourth...) copy of your repo that shares the same `.git` history but lives in its own folder with its own branch. Think of it like opening the same project in a parallel universe — you can hack on a feature in one worktree while keeping `main` pristine in another. + +Claude Code has built-in worktree support, so you don't need to memorize any git commands. + +## Why bother? + +- **Safety net**: Your `main` branch stays untouched. If Claude's changes go sideways, just delete the worktree — zero damage. +- **Easy A/B comparison**: Keep the original code open in one editor tab, Claude's changes in another. +- **Parallel work**: You can keep working in `main` while Claude tinkers in a worktree. +- **Clean PRs**: The worktree branch becomes your PR branch with no stray changes mixed in. + +## The 30-second version + +1. Ask Claude to work in a worktree +2. Claude creates an isolated copy and works there +3. When done, you either merge or throw it away + +That's it. Everything below is details. + +--- + +## How to start a worktree session + +### Option A: Ask Claude directly + +Just tell Claude you want to work in a worktree: + +``` +> Let's work in a worktree for this +> Start a worktree called "dct-refactor" +> Can you make these changes in an isolated worktree? +``` + +Claude will use `EnterWorktree` behind the scenes and switch into it automatically. + +### Option B: Use the slash command + +``` +> /worktree +``` + +This drops you into a fresh worktree immediately. + +### Option C: Tell Claude to launch an agent in a worktree + +If you want Claude to do something in the background without touching your working directory: + +``` +> Run the tests in a worktree so we don't mess up my local state +``` + +Claude can spin up a sub-agent with `isolation: "worktree"` — it gets its own copy and reports back. + +--- + +## Where do worktrees live? + +Claude puts them in: + +``` +.claude/worktrees// +``` + +This directory is inside your repo but ignored by git, so it won't pollute your commits. + +## What happens inside a worktree? + +The worktree is a full checkout of your repo on a new branch. Claude's working directory switches to it, so all file reads, edits, and commands happen there — not in your main checkout. + +**Important for Stegasoo**: The first thing you (or Claude) should do in a fresh worktree is: + +```bash +pip install -e ".[dev]" +``` + +This points your editable install at the worktree's source code instead of your main checkout. Without this, `pytest` will test the wrong copy of the code. + +--- + +## Real-world examples + +### Example 1: Feature work + +``` +You: I want to add lz4 as a default compression option. Let's use a worktree. +Claude: *creates worktree, switches to it* +Claude: *installs dev deps, makes changes, runs tests* +Claude: All tests pass. Ready to merge or open a PR. +You: Looks good, make a PR. +Claude: *pushes branch, creates PR* +``` + +### Example 2: Risky refactor + +``` +You: Refactor the crypto module to split KDF logic into its own file. + Do it in a worktree so I can review before touching main. +Claude: *creates worktree "refactor/split-kdf"* +Claude: *does the refactor, runs tests* +You: Hmm, I don't love the approach. Throw it away. +Claude: *removes worktree — main is untouched* +``` + +### Example 3: Investigate a bug without side effects + +``` +You: Something's wrong with DCT encoding on large images. + Can you investigate in a worktree? I've got uncommitted work here. +Claude: *creates worktree, adds debug logging, runs tests* +Claude: Found it — the block size calculation overflows at >16MP. + Here's the fix. Want me to apply it to main? +``` + +--- + +## When to use a worktree vs. just editing in place + +| Situation | Worktree? | Why | +|-----------|-----------|-----| +| Quick one-file fix | No | Overkill — just edit directly | +| Multi-file refactor | Yes | Easy to discard if it goes wrong | +| Touching security-critical code (`crypto.py`, `steganography.py`, etc.) | Yes | Extra safety for sensitive changes | +| Experimental / "let's try this" work | Yes | Zero-cost throwaway | +| You have uncommitted changes you don't want to stash | Yes | Worktree won't touch your working tree | +| Adding a single test | No | Low risk, just do it | + +--- + +## Cleaning up + +### If you merged or created a PR + +The worktree served its purpose. Clean up: + +```bash +git worktree remove .claude/worktrees/ +``` + +Or ask Claude: + +``` +> Clean up the worktree +``` + +### If you want to throw everything away + +Same command — removing the worktree deletes the directory and its branch reference. Your `main` branch is completely unaffected. + +### If Claude's session ends + +When a Claude Code session ends while in a worktree, you'll be prompted to keep or remove it. If you keep it, you can resume later: + +```bash +cd .claude/worktrees/ +# pick up where you left off +``` + +--- + +## Branch naming in worktrees + +Follow the same conventions as the rest of the project: + +| Type | Branch name | Example | +|------|-------------|---------| +| Feature | `feature/description` | `feature/batch-progress-bars` | +| Bug fix | `fix/description` | `fix/dct-overflow-large-images` | +| Docs | `docs/description` | `docs/api-examples` | +| Refactor | `refactor/description` | `refactor/split-crypto-module` | + +When Claude creates a worktree automatically, it generates a random branch name. You can rename it before pushing: + +```bash +git branch -m feature/my-better-name +``` + +--- + +## Troubleshooting + +### "I ran pytest but it's testing the old code" + +You forgot to install in the worktree: + +```bash +pip install -e ".[dev]" +``` + +### "I can't find my worktree" + +```bash +git worktree list +``` + +This shows all worktrees and their paths. + +### "I accidentally deleted the worktree folder without removing it from git" + +```bash +git worktree prune +``` + +This cleans up stale worktree references. + +### "I want to switch back to my main checkout" + +If you're in a Claude Code session that entered a worktree, the session stays in the worktree until it ends. Start a new session to go back to your main checkout, or: + +```bash +cd /home/alee/Sources/stegasoo +``` + +--- + +## TL;DR + +1. Say "use a worktree" when asking Claude to make changes +2. Claude works in an isolated copy — your `main` is safe +3. Merge the good stuff, trash the bad stuff +4. Never think about it again until next time