Skip to content

Latest commit

 

History

History
97 lines (75 loc) · 3.77 KB

File metadata and controls

97 lines (75 loc) · 3.77 KB

Contributing to IntelCLI

Thank you for considering a contribution! IntelCLI aims to stay a small, fast, lawful, and well-tested OSINT toolkit — contributions that keep that spirit are very welcome.

Ground rules

  • Lawful sources only. Every new data source must use a publicly documented protocol or API (standard WHOIS, public DNS, a site's own public HTTP/HTTPS endpoint, or a free/public API). PRs that scrape a site in violation of its terms of service, bypass authentication, or otherwise enable unauthorized access will not be merged.
  • No secrets in source. API keys are always optional and always read from the user's local config file via ConfigManager — never hardcoded.
  • Test everything. New services and commands need unit tests (network mocked) and, for commands, an integration test using Typer's CliRunner. We maintain 90%+ coverage; PRs that drop coverage below that will be asked to add tests before merge.

Development setup

git clone https://github.com/intelcli/intelcli.git
cd intelcli
pip install -e ".[dev]"

Run the full quality gate before opening a PR:

ruff check .
black --check .
mypy src
pytest --cov=intelcli --cov-report=term-missing

Project structure

See docs/architecture.md for the full layered design (cli → commands → services → models/storage/utils). In short:

  • services/ — one class per external data source. Pure logic, returns a typed Pydantic model, raises from exceptions.py. No print(), no Rich, no Typer.
  • commands/ — argument parsing, calling services, rendering Rich output, exporting, and history logging. Thin orchestration only.
  • models/ — Pydantic models shared across layers.

Adding a new command

  1. Add Pydantic model(s) to models/.
  2. Add service(s) to services/ with narrow, single-purpose public methods.
  3. Add a commands/<name>.py module exposing a plain function (not a nested Typer app, unless the command needs sub-commands like history/config).
  4. Register it in cli/app.py via app.command("name")(your_function).
  5. Add unit tests for the service(s) under tests/unit/.
  6. Add an integration test for the command under tests/integration/, mocking the service layer so the test is deterministic and offline.
  7. Update docs/usage.md with examples.

Adding a new data source to an existing command

Follow the try/except-and-append-to-errors pattern already used in commands/domain.py and commands/ip.py: a failing source should never take down the whole command. Catch intelcli.exceptions.IntelCLIError (or a specific subclass) and append a human-readable message to the report's errors list.

Code style

  • Python 3.12+, full type hints, from __future__ import annotations.
  • Formatted with Black (line length 100).
  • Linted with Ruff (E, F, I, UP, B, SIM, C4 rule sets).
  • Docstrings on every public class/function using a concise, factual style (see existing modules for the convention).
  • Prefer composition over inheritance; prefer small, focused classes.

Commit / PR process

  1. Fork the repo and create a feature branch.
  2. Make your changes with tests.
  3. Run the full quality gate (see above) — all checks must pass.
  4. Open a PR describing what changed and why. Link any relevant issue.
  5. Be responsive to review feedback; small, focused PRs merge fastest.

Reporting security issues

Please do not open a public issue for security vulnerabilities. Instead, email the maintainers directly (see the repository's security policy) so a fix can be prepared before public disclosure.

Code of conduct

Be respectful, assume good faith, and keep discussions focused on the technical merits. We want IntelCLI's community to be as welcoming as its codebase is clean.