Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# AGENTS.md

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The main heading of a markdown file should describe its content, not its filename. The current heading # AGENTS.md is redundant. A more descriptive heading would improve clarity and is a common best practice for documentation files.

Suggested change
# AGENTS.md
# ctrld-sync Project Documentation


## Project Overview

**ctrld-sync** is a Python CLI tool that syncs Control D DNS filtering folders
with remote block-lists. It downloads JSON block-lists, deletes existing folders
with matching names, recreates them, and pushes rules in batches to the
Control D API.

## Language & Runtime

- Python 3.13+
- Runtime dependencies: `httpx`, `python-dotenv`
- Dependency metadata lives in `pyproject.toml` (source of truth);
`requirements.txt` is kept in sync for CI pip-caching.

## Repository Layout

```text
main.py # Single-file CLI application (~2900 lines)
fix_env.py # Utility for .env file permission repair
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description of fix_env.py is incomplete. The file does more than just "permission repair" - it also standardizes quotes, detects and corrects swapped TOKEN/PROFILE values, and checks for symlinks. Consider updating to something like "Utility for .env file validation, cleanup, and secure permission enforcement".

Suggested change
fix_env.py # Utility for .env file permission repair
fix_env.py # Utility for .env file validation, cleanup, and secure permission enforcement

Copilot uses AI. Check for mistakes.
pyproject.toml # Project metadata & dependency declarations
requirements.txt # Pinned runtime deps (mirrors pyproject.toml)
tests/ # pytest test suite (27 test files)
.github/workflows/ # 18 GitHub Actions workflows
.trunk/ # Trunk linter/formatter configuration
configs/ # Per-tool config (ruff, isort, markdownlint, yamllint)
Comment on lines +20 to +27

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Repository Layout section provides a great overview of the project structure, but it's missing an entry for this AGENTS.md file itself. For completeness, it would be helpful to include it.

Suggested change
main.py # Single-file CLI application (~2900 lines)
fix_env.py # Utility for .env file permission repair
pyproject.toml # Project metadata & dependency declarations
requirements.txt # Pinned runtime deps (mirrors pyproject.toml)
tests/ # pytest test suite (27 test files)
.github/workflows/ # 18 GitHub Actions workflows
.trunk/ # Trunk linter/formatter configuration
configs/ # Per-tool config (ruff, isort, markdownlint, yamllint)
AGENTS.md # This file; project documentation for agents
main.py # Single-file CLI application (~2900 lines)
fix_env.py # Utility for .env file permission repair
pyproject.toml # Project metadata & dependency declarations
requirements.txt # Pinned runtime deps (mirrors pyproject.toml)
tests/ # pytest test suite (27 test files)
.github/workflows/ # 18 GitHub Actions workflows
.trunk/ # Trunk linter/formatter configuration
configs/ # Per-tool config (ruff, isort, markdownlint, yamllint)

```

## Building & Running

No build step is required. Install dependencies and run directly:

```bash
pip install -r requirements.txt
python main.py --dry-run # safe preview, no API calls
python main.py --profiles <id> # live sync against Control D
```

The project also supports `uv sync` for local development.
Comment on lines +32 to +40

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The instructions for setting up the environment could be clearer by distinguishing between running the application and setting up a development environment. The Testing section mentions pytest, which is a dev dependency, but this section only shows how to install runtime dependencies. I suggest clarifying the setup for both use cases.

Suggested change
No build step is required. Install dependencies and run directly:
```bash
pip install -r requirements.txt
python main.py --dry-run # safe preview, no API calls
python main.py --profiles <id> # live sync against Control D
```
The project also supports `uv sync` for local development.
For running the application, install runtime dependencies:
```bash
pip install -r requirements.txt
python main.py --dry-run # safe preview, no API calls
python main.py --profiles <id> # live sync against Control D

For local development (e.g., to run tests), it's recommended to use uv to install all dependencies:

# Install runtime and dev dependencies in editable mode
uv pip install -e .[dev]


## Testing

Tests use **pytest** with `pytest-mock`, `pytest-xdist`, and `pytest-benchmark`.

```bash
pytest tests/ -v # run all tests
pytest tests/ -n auto # parallel execution
pytest tests/ -k "security" # run a subset by keyword
```

All test files live under `tests/` and follow the `test_*.py` naming convention.
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement is inaccurate. While there are 26 test files in the tests/ directory, test_main.py (776 lines) is located in the root directory, making it 27 total test files. Consider rephrasing to: "All test files follow the test_*.py naming convention. Most (26) live under tests/, with test_main.py in the repository root."

Copilot uses AI. Check for mistakes.
Test categories include security (SSRF, CSV injection, log sanitization),
validation (folders, hostnames, IDs), performance regression, UX, and caching.

## Linting & Formatting

The project uses [Trunk](https://trunk.io) to orchestrate linters. Key tools:

| Tool | Purpose |
|---------------|-----------------------------|
| ruff | Python linting |
| black | Python formatting |
| isort | Import sorting (black profile) |
| bandit | Security linting |
| markdownlint | Markdown linting |
| yamllint | YAML linting |
| actionlint | GitHub Actions linting |
| prettier | General formatting |

Ruff is configured to select rule sets `B`, `D3`, `E`, `F` and ignore `E501`
(line length is left to the formatter). See `.trunk/configs/ruff.toml`.

## Coding Conventions

- **Formatting**: Black style. Imports sorted with isort (black profile).
- **Naming**: `snake_case` for functions/variables, `PascalCase` for classes,
`UPPER_SNAKE_CASE` for module-level constants. Private helpers use a leading
underscore (e.g. `_retry_request()`).
- **Type hints**: Use `typing` annotations on function signatures.
- **Error handling**: Wrap external calls in try/except, log errors, and degrade
gracefully rather than crashing.
- **Security**: Validate all external inputs. Sanitize log output. Guard against
SSRF. Check `.env` file permissions before loading secrets.
- **Constants**: Defined at module top-level (e.g. `MAX_RETRIES`, `BATCH_SIZE`).
- **Comments**: Explain *why*, not *what*. Do not add redundant narrative
comments.

## CI / GitHub Actions

The primary workflow is `.github/workflows/sync.yml` (runs daily at 02:00 UTC).
Security scans (Bandit, Codacy) and performance regression tests run on push and
PR events. Workflows require `TOKEN` and `PROFILE` repository secrets.

## Environment Variables

| Variable | Purpose |
|-----------|--------------------------------------|
| `TOKEN` | Control D API token |
| `PROFILE` | Default Control D profile ID |
| `NO_COLOR`| Disable colored terminal output |

A `.env.example` template is provided. The real `.env` file is git-ignored.
Loading