CLAUDE.md · trailofbits/algo
CLAUDE.md from trailofbits/algo: 478 lines covering Project Overview, Architecture and Structure, Development Workflow, Ansible Pitfalls and more.
Template by trailofbits
Install
Works with Claude Code. Read the repository before you give any tool access to your data.
curl -fsSL https://raw.githubusercontent.com/trailofbits/algo/main/CLAUDE.md -o CLAUDE.md
Read it and adapt it to your project before use.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: cloud-management, infrastructure-as-code
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
What's in it
A CLAUDE.md file: project memory Claude Code loads at the start of every session.
- For
- Claude Code
- Length
- 478 lines
- File
CLAUDE.md
Sections
- Project Overview
- Architecture and Structure
- Development Workflow
- Ansible Pitfalls
- DNS Architecture
- Common Issues
- Time Wasters to Avoid
- What to Avoid
- Writing Effective Tests
- Quick Reference
- Non-Interactive Deployment
- Security Considerations
- Platform Support
First lines (shown under the repo's AGPL-3.0 license)
# CLAUDE.md - LLM Guidance for Algo VPN
This document provides essential context and guidance for LLMs working on the Algo VPN codebase.
## Project Overview
Algo is an Ansible-based tool that sets up a personal VPN in the cloud. It's designed to be:
- **Security-focused**: Creates hardened VPN servers with minimal attack surface
- **Easy to use**: Automated deployment with sensible defaults
- **Multi-platform**: Supports various cloud providers and operating systems
- **Privacy-preserving**: No logging, minimal data retention
### Core Technologies
- **VPN Protocols**: WireGuard (preferred) and IPsec/IKEv2
- **Configuration Management**: Ansible (v12+)
- **Languages**: Python, YAML, Shell, Jinja2 templates
- **Supported Providers**: AWS, Azure, DigitalOcean, GCP, Vultr, Hetzner, local deployment
### Philosophy
- Stability over features
- Security over convenience
- Clarity over cleverness
- Test everything
- Stay in scope - solve exactly what the issue asks, nothing more
- Test assumptions - run the code before committing
- Resist new dependencies - each one is attack surface and maintenance
## Architecture and Structure
```
algo/
├── main.yml # Primary playbook
├── users.yml # User management playbook
├── server.yml # Server-specific tasks
├── config.cfg # Main configuration file
├── pyproject.toml # Python project configuration and dependencies
├── uv.lock # Exact dependency versions lockfile
├── requirements.yml # Ansible collections
├── roles/ # Ansible roles
│ ├── common/ # Base system configuration, firewall, hardening
│ ├── wireguard/ # WireGuard VPN setup
│ ├── strongswan/ # IPsec/IKEv2 setup
│ ├── dns/ # DNS configuration (dnscrypt-proxy)
│ └── cloud-*/ # Cloud provider specific roles
├── library/ # Custom Ansible modules
└── tests/unit/ # Python unit tests
```
## Development Workflow
### Quality Gates (MANDATORY)
**All PRs must pass these checks locally before submission.** CI will reject failures:
```bash
# Run the full lint suite (same as CI)
ansible-lint . && yamllint . && ruff check . && shellcheck scripts/*.sh && semgrep --config auto --exclude-rule dockerfile.security.last-user-is-root.last-user-is-root --error --quiet .
ansible-playbook main.yml --syntax-check
ansible-playbook users.yml --syntax-check
pytest tests/unit/ -q
```
Common lint issues to fix before submitting:
- YAML files missing `---` document start markers
- GitHub workflows with unquoted `on:` (must be `'on':`)
- Using `ignore_errors: true` instead of `failed_when: false`
- Jinja2 spacing errors (`{{foo}}` should be `{{ foo }}`)
- Missing `mode:` on file/directory tasks
### Zero-Tolerance Warning Policy
**No warnings are tolerated in CI.** Every linter finding must be either fixed or explicitly allowlisted in the tool's config file (`.ansible-lint`, `pyproject.toml`, etc.).
Why this matters for Algo:
- **Security tool** - VPN misconfigurations silently break privacy guarantees. A "cosmetic" warning today hides a real bug tomorrow.
- **Ansible complexity** - YAML+Jinja2 linting catches real runtime failures (wrong key order breaks `when` evaluation, spacing errors cause template failures). Warnings in Ansible are not style nits.
- **CI signal integrity** - If 30 warnings scroll by on every run, the 31st one (a real regression) goes unnoticed. Zero warnings means every new finding gets human attention.
Resolution order of preference:
1. **Fix it** - Preferred. Most findings have straightforward fixes.
2. **Allowlist in config** - If the rule is wrong for this project, add to `skip_list` with a comment explaining why.
3. **Inline suppress** - Last resort. Use `# noqa: rule-name` with a comment justifying the exception.
Never use `warn_list` in `.ansible-lint` — it exists as a migration tool, not a permanent home. Rules either pass or are explicitly skipped.
### Design Requirements
When adding or modifying features, verify these before requesting review:
1. **Validate inputs early** - Check for empty lists, missing configs, permission mismatches before expensive operations
2. **Explicit file modes** - Always specify `mode:` on file/directory tasks (never rely on umask)
3. **Fail vs warn** - Permission/security issues should fail; optional features can warn
4. **Actionable errors** - Include fix commands in error messages: `"Run: sudo chown -R $USER configs/"`
5. **Follow existing patterns** - Search codebase first: `rg "when:.*localhost" --type yaml`
### Linting Tools
| Tool | Target | Key Rules |
|------|--------|-----------|
| `ansible-lint` | YAML tasks | Use `failed_when` not `ignore_errors`, add `mode:` to files |
| `yamllint` | All YAML | Document start `---`, quote `'on':` in workflows |
| `ruff` | Python | Line length 120, target Python 3.11 |
| `shellcheck` | Shell scripts | Quote variables, use `set -euo pipefail` |
| `semgrep` | All code | SAST scanner, `--config auto`, suppress with `# nosemgrep: rule-id` |
### Git Workflow
1. Create feature branches from `master`
2. Run all linters before pushing
3. Make atomic commits with clear messages
4. Update PR description with test results
### Self-Review Checklist
Before creating a PR, review your own diff:
- [ ] Did I run all linters locally?
- [ ] Did I search for similar patterns in the codebase?
- [ ] Did I add explicit `mode:` to file/directory tasks?
- [ ] Did I validate inputs before expensive operations?
- [ ] Did I update tests if I changed file paths or behavior?
- [ ] Would a reviewer ask "what happens if X is empty/missing?"
## Ansible Pitfalls
### with_items vs loop
`with_items` auto-flattens lists; `loop` does not. **Never mechanically convert:**
```yaml
# WRONG - treats list as single item, creates file named "['alice', 'bob']"
loop:
- "{{ users }}"
# CORRECT - iterates over list contents
loop: "{{ users }}"
# CORRECT - combining lists (with_items did this automatically)
loop: "{{ users + [server_name] }}"
```
**Always test loop conversions** - verify the task creates expected files.
### Path Variables
Never include trailing slashes - causes double-slash bugs:
```yaml
# WRONG - creates paths like /etc/ipsec.d//private
ipsec_path: "configs/{{ server }}/ipsec/"
# CORRECT
ipsec_path: "configs/{{ server }}/ipsec"
```
### ignore_errors vs failed_when
```yaml
# WRONG - ansible-lint failure
- name: Clear historySignals
- Stars
- 30,438
- Forks
- 2,369
- Open issues
- 73
- Last commit (this folder)
- Feb 8, 2026 (8 months ago)
- Last release
- Nov 27, 2025 (11 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- AGPL-3.0
- Repository
- github.com/trailofbits/algo
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from trailofbits
- 0.767score
github-triage
trailofbits
Triages a repository's open GitHub issues and pull requests via the gh CLI.
SkillAFreshness: A★ 7.8KClaude Code +9 - 0.767score
entry-point-analyzer
trailofbits
Analyzes smart contract codebases to identify state-changing entry points for security auditing.
SkillAFreshness: A★ 7.8KClaude Code +9 - 0.767score
interpreting-culture-index
trailofbits
Interprets Culture Index (CI) surveys, behavioral profiles, and personality assessment data.
SkillAFreshness: A★ 7.8KClaude Code +9 - 0.767score
firebase-apk-scanner
trailofbits
Scans Android APKs for Firebase security misconfigurations including open databases, storage buckets, authentication issues, and exposed cloud functions.
SkillAFreshness: A★ 7.8KClaude Code +9 - 0.767score
dimensional-analysis
trailofbits
Audits code for unit and decimal-scaling bugs and annotates it with dimensional comments recording the units of each value.
SkillAFreshness: A★ 7.8KClaude Code - 0.767score
let-fate-decide
trailofbits
Draws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated.
SkillAFreshness: A★ 7.8KClaude Code +9
Cite this page
CLAUDE.md · trailofbits/algo. Agent Mart. https://agentmart.dev/templates/trailofbits-algo-claude-md (last updated 2026-10-24)