recon
Point recon at a domain and get its public technology and identity footprint: email security, mail and identity providers, SaaS indicators, and certificate-transparency findings. No credentials, no API keys, no active scanning. Ships as a CLI, versioned JSON, and a local MCP server for agent tools.
A domain is a query coordinate, not proof of one organization or product. Observations, not verdicts.
Defensive use only. Posture review, vendor diligence, architecture review. See docs/legal.md.
Quick Start
Install with uv or pipx:
uv tool install recon-tool
# or
pipx install recon-tool
Python 3.11 through 3.14, on Windows, macOS, or Linux.
Optional helpers at scripts/install.ps1 and scripts/install.sh drive an
existing uv or pipx installation. Download a
release-tag source archive,
review the helper locally, then run it. Each helper installs the exact version
represented by that tag, preserves a sole existing uv or pipx owner, and
refuses ambiguous or unmanaged installations. Do not pipe mutable branch
content into a shell. To verify published artifacts before installing, follow the
consumer verification recipe.
Verify the installed command offline:
recon --version
Then optionally test online connectivity to recon's public data sources:
recon doctor
Before the first lookup, know what leaves your machine. recon makes DNS queries
that recursive and authoritative DNS infrastructure may observe. Its only
default request to a target-owned endpoint is the standards-defined MTA-STS
policy fetch. Google CSE and BIMI certificate probes run only when
--direct-probes is explicitly enabled. Readable overview:
docs/how-it-works.md.
Formal correlation model (layers, Bayesian DAG, robustness research):
docs/correlation.md.
recon example.com
Every lookup is live. recon ships no offline demo mode, so that command
collects whatever example.com publishes in DNS and at the identity endpoints
on the day you run it. Reserved and .invalid names are safe to query, not
staged: they publish little or nothing, and what they do publish is public
residue rather than an organization's stack. Substitute a domain you are
authorized to review to see a populated panel.
Illustrated output (synthetic, not a captured run)
The panel above is generated, not captured:
scripts/generate_terminal_demo.py
drives recon's real formatter over a deterministic, no-network fixture for the
fictional Example Industries Ltd. It shows the shape of a full-signal
result, every row a rich target can fill, and no live lookup of reserved
example.com reproduces it. No real organization is depicted. Other project
fixtures use IETF reserved .invalid namespaces.
Accessible text transcript
$ recon example.com # synthetic fixture, not a captured run
Example Industries Ltd
example.com
──────────────────────────────────────────────────────────────────────────────
Provider Microsoft 365 + Proofpoint gateway
Tenant a1b2c3d4-e5f6-7890-abcd-ef1234567890 • NA
Tenant domain example-industries.onmicrosoft.example.com
Auth Federated
Confidence ●●● High (4 sources)
Services
Email Microsoft 365, Proofpoint, DMARC reject, DKIM,
SPF strict, MTA-STS enforce
Identity Okta
Cloud Cloudflare (CDN/edge), AWS Route 53 (DNS)
Security Wiz Security
Data & Analytics Snowflake, Datadog
Collaboration Slack, Atlassian (Jira/Confluence), GitHub, Zoom
Evidence roles: --explain
High-signal related domains
login.example.com, status.example.com, support.example.com
Insights
Federated identity observed; identity-vendor indicators: Okta
Email security: observed controls: DMARC reject, DKIM, SPF strict, MTA-STS
Install, update, uninstall, and first-run detail: docs/getting-started.md.
What recon Is Good For
| Need | Use recon for | Use something else when |
|---|---|---|
| Fast external stack context | Passive DNS, identity-endpoint, CT, SaaS, and posture indicators | You need authenticated tenant inventory or asset-management truth |
| Defensive review or vendor diligence | Hedged observations and evidence traces you can verify | You need vulnerability scanning, exploit checks, or host-level facts |
| Automation-friendly output | Stable JSON, batch mode, delta mode, and local MCP tools | You need dashboards, scheduling, or report generation built in |
recon reports observations, not verdicts. Public channel ceiling: docs/limitations.md.
Common Commands
recon example.com # default panel
recon example.com --explain # evidence trail
recon example.com --plain # panel as linear text (screen readers, grep)
recon example.com --json # structured record
recon batch domains.txt --json # batch JSON array
recon delta example.com # diff vs local cache
recon capsule capture example.com -o run.json # caller-owned replay artifact
recon mcp install --client=cursor # wire MCP into a client
More flags: docs/cli-surface.md. JSON contracts: schema · stability · operational contract.
Versioned JSON remains recon's structured runtime contract. The Open Knowledge Format v0.2 projection is deferred until a named consumer justifies the mapping. recon does not emit OKF, and any future OKF view would be additive rather than a replacement for JSON. Caller-owned JSON observation capsules are documented in docs/observation-capsules.md, with the decision boundary in ADR-0014.
docs/surface-inventory.json, docs/cli-surface.md, and
recon://surface-inventory are generated discovery context and drift guards,
not stable runtime API contracts. ADR-0007 records the promotion gate.
Use with an AI agent (plugin / MCP / skill)
Wire recon into Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, Kiro, or any MCP-compatible client:
recon mcp install --client=claude-desktop
# also: claude-code, cursor, vscode, windsurf, kiro
recon mcp doctor
Start with manual tool approvals. Treat agents as untrusted input. Full setup: docs/mcp.md. Per-client scaffolds and skills: agents/.
The current scaffolds use each client's native configuration. In particular,
the bundled Claude Code plugin uses Claude Code's client-specific layout; it
does not claim conformance with the portable
Agent Plugins v1.0.0 working draft.
A complete-surface portable candidate now lives under
agents/agent-plugin/
and passes network-free validation against the exact pinned v1.0.0 schemas.
That is not a compatibility or conformance claim. Until the frozen VS Code,
Cursor, and Kiro evaluation passes, use the documented client-specific install
path above.
| You say | What the agent should do |
|---|---|
| "Recon example.com" | Call lookup_tenant (or recon example.com) and return the panel-style summary |
| "What does example.com run for email and identity?" | Same lookup; lead with MX/IdP/tenant facts and confidence |
| "Why do you think that?" | Re-run with explain / provenance (--explain or explain=true) |
| "Compare example.com and example.net" | compare_postures or two lookups side by side |
| "Any public hardening gaps?" | find_hardening_gaps after a lookup - hedged "Consider" notes only |
Example chat. This transcript uses the same synthetic Example Industries
fixture as the illustration above, so it shows the shape of a full-signal
answer rather than what a live example.com lookup returns:
You: Recon example.com and tell me what you observe.
Agent: Public evidence for
example.com(fictional demo):
- Mail: Microsoft 365 delivery path plus Proofpoint gateway; DMARC
p=reject, SPF strict, MTA-STS enforce.- Identity: Federated; Okta indicator via CNAME.
- Tenant: GUID present, region NA; confidence high from four sources.
- Also seen: Cloudflare and Route 53 infrastructure, Wiz, Snowflake, Datadog, Slack, Atlassian, GitHub, and Zoom public indicators.
These are public-record observations, not a security grade or proof of active product use. Say if you want evidence detail or a gap review.
Guidance: agents/claude-code/skills/recon/, AGENTS.md.
Optional Cloud Access
Local execution is the default, and the project does not operate a hosted service. For teams that want shared remote access, the repository includes a draft authenticated container and Cloud Run Terraform starting point. It is intended to be directionally useful, not a validated production deployment. Operators own deployment, identity, data handling, cost, and operations.
Docs
| Topic | Link |
|---|---|
| Install and first commands | docs/getting-started.md |
| How it works | docs/how-it-works.md |
| Observation capsules | docs/observation-capsules.md |
| Correlation model | docs/correlation.md |
| MCP and agents | docs/mcp.md, agents/ |
| Full docs index | docs/README.md |
| Roadmap | ROADMAP.md · docs/roadmap.md · docs/strategic-gap-audit.md |
| Changelog | CHANGELOG.md |
| Security | SECURITY.md · docs/security.md |
Research and publication pointers (maintainer track, not the product core): docs/submission-freeze-checklist.md, validation/2026-06-30-submission-freeze-local-proof.md, docs/public-label-snapshot-decision.md (public lists as robustness checks rather than population rates), and docs/m365-tenancy-decision.md.
Development
uv sync
uv run pre-commit install
uv run python scripts/release_readiness.py --allow-dirty
uv run python scripts/check.py
uv run python scripts/check.py is the canonical local gate: lint, type
checks, coverage-gated tests, generated-artifact and catalog checks, text and
link hygiene, interface and claim checks, and size and complexity ratchets.
Green locally means green in CI.
Project hygiene: keep examples reserved and synthetic, keep validation artifacts aggregate-only, and avoid dead code or placeholders. See CONTRIBUTING.md.
License
Apache 2.0. Free to use, build on, fork, and share. See LICENSE for the full terms.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file recon_tool-2.15.0.tar.gz.
File metadata
- Download URL: recon_tool-2.15.0.tar.gz
- Upload date:
- Size: 3.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4dca8a497fe79ee095f65b8f06132be0a51bab1e91cf10c7aed3cd901cc2341b
|
|
| MD5 |
4a858e53548cd283541d84ffc08e2fcd
|
|
| BLAKE2b-256 |
b96adc9540cae67dcac61d24edc99ebc82634727c8183bc569df4a09d8db65d6
|
Provenance
The following attestation bundles were made for recon_tool-2.15.0.tar.gz:
Publisher:
release.yml on blisspixel/recon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recon_tool-2.15.0.tar.gz -
Subject digest:
4dca8a497fe79ee095f65b8f06132be0a51bab1e91cf10c7aed3cd901cc2341b - Sigstore transparency entry: 2490083753
- Sigstore integration time:
-
Permalink:
blisspixel/recon@e56dceec63156090c72e0b0ffdeabacde2961c0c -
Branch / Tag:
refs/tags/v2.15.0 - Owner: https://github.com/blisspixel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e56dceec63156090c72e0b0ffdeabacde2961c0c -
Trigger Event:
push
-
Statement type:
File details
Details for the file recon_tool-2.15.0-py3-none-any.whl.
File metadata
- Download URL: recon_tool-2.15.0-py3-none-any.whl
- Upload date:
- Size: 769.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69ffa63504e4a70d0d75e0fdfdd0a9280577830b913aed978fa759704b9eddac
|
|
| MD5 |
b846cd40c74a0eb3380aa2c556c0b316
|
|
| BLAKE2b-256 |
59034ec2e1997be4ca78f6f931ff0aa7ac157f4ea1cb71cdc6d3624f77cb0473
|
Provenance
The following attestation bundles were made for recon_tool-2.15.0-py3-none-any.whl:
Publisher:
release.yml on blisspixel/recon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recon_tool-2.15.0-py3-none-any.whl -
Subject digest:
69ffa63504e4a70d0d75e0fdfdd0a9280577830b913aed978fa759704b9eddac - Sigstore transparency entry: 2490083803
- Sigstore integration time:
-
Permalink:
blisspixel/recon@e56dceec63156090c72e0b0ffdeabacde2961c0c -
Branch / Tag:
refs/tags/v2.15.0 - Owner: https://github.com/blisspixel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e56dceec63156090c72e0b0ffdeabacde2961c0c -
Trigger Event:
push
-
Statement type: