Metadata-Version: 2.4
Name: whycode
Version: 0.4.5
Summary: Verified decision provenance for AI-assisted development — memory, AST provenance, and quality verification.
Project-URL: Homepage, https://github.com/whycodeAI/whycode
Project-URL: Repository, https://github.com/whycodeAI/whycode
Project-URL: Documentation, https://github.com/whycodeAI/whycode/blob/main/README.md
Project-URL: Bug Tracker, https://github.com/whycodeAI/whycode/issues
Project-URL: Changelog, https://github.com/whycodeAI/whycode/blob/main/CHANGELOG.md
Author-email: WhyCodeAI <hello@whycodeai.github.io>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: agent-memory,ai-memory,claude-code,code-provenance,codebase-memory,cursor,developer-tools,mcp,windsurf
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Version Control
Requires-Python: >=3.11
Requires-Dist: aiosqlite~=0.20.0
Requires-Dist: argon2-cffi~=23.1.0
Requires-Dist: click<9.0,>=8.1
Requires-Dist: cryptography>=46.0.6
Requires-Dist: fastapi>=0.119.0
Requires-Dist: fastmcp>=3.2.0
Requires-Dist: httpx~=0.28.0
Requires-Dist: keyring~=25.0
Requires-Dist: ollama~=0.4.0
Requires-Dist: pgvector~=0.3.0
Requires-Dist: pyjwt>=2.12.0
Requires-Dist: pywin32>=307; sys_platform == 'win32'
Requires-Dist: rank-bm25~=0.2.2
Requires-Dist: slowapi~=0.1.9
Requires-Dist: sqlite-vec<0.2,>=0.1.6
Requires-Dist: tree-sitter-language-pack~=1.6
Requires-Dist: tree-sitter~=0.25.0
Requires-Dist: uvicorn>=0.34
Requires-Dist: watchdog~=6.0
Provides-Extra: all-connectors
Requires-Dist: aioboto3>=12.0.0; extra == 'all-connectors'
Requires-Dist: aiomysql>=0.2.0; extra == 'all-connectors'
Requires-Dist: cassandra-driver>=3.29.0; extra == 'all-connectors'
Requires-Dist: clickhouse-driver>=0.2.7; extra == 'all-connectors'
Requires-Dist: databricks-sql-connector>=3.0.0; extra == 'all-connectors'
Requires-Dist: elasticsearch[async]>=8.0.0; extra == 'all-connectors'
Requires-Dist: google-cloud-bigquery>=3.0.0; extra == 'all-connectors'
Requires-Dist: influxdb-client>=1.43.0; extra == 'all-connectors'
Requires-Dist: influxdb3-python>=0.18.0; extra == 'all-connectors'
Requires-Dist: motor>=3.3.0; extra == 'all-connectors'
Requires-Dist: redis[hiredis]>=5.0.0; extra == 'all-connectors'
Requires-Dist: snowflake-connector-python>=3.0.0; extra == 'all-connectors'
Provides-Extra: all-databases
Requires-Dist: aioboto3>=12.0.0; extra == 'all-databases'
Requires-Dist: aiomysql>=0.2.0; extra == 'all-databases'
Requires-Dist: cassandra-driver>=3.29.0; extra == 'all-databases'
Requires-Dist: clickhouse-driver>=0.2.7; extra == 'all-databases'
Requires-Dist: databricks-sql-connector>=3.0.0; extra == 'all-databases'
Requires-Dist: elasticsearch[async]>=8.0.0; extra == 'all-databases'
Requires-Dist: google-cloud-bigquery>=3.0.0; extra == 'all-databases'
Requires-Dist: influxdb-client>=1.43.0; extra == 'all-databases'
Requires-Dist: influxdb3-python>=0.18.0; extra == 'all-databases'
Requires-Dist: motor>=3.3.0; extra == 'all-databases'
Requires-Dist: redis[hiredis]>=5.0.0; extra == 'all-databases'
Requires-Dist: snowflake-connector-python>=3.0.0; extra == 'all-databases'
Provides-Extra: benchmark
Requires-Dist: datasets>=2.0.0; extra == 'benchmark'
Requires-Dist: requests>=2.28.0; extra == 'benchmark'
Provides-Extra: bigquery
Requires-Dist: google-cloud-bigquery>=3.0.0; extra == 'bigquery'
Provides-Extra: cassandra
Requires-Dist: cassandra-driver>=3.29.0; extra == 'cassandra'
Provides-Extra: clickhouse
Requires-Dist: clickhouse-driver>=0.2.7; extra == 'clickhouse'
Provides-Extra: databricks
Requires-Dist: databricks-sql-connector>=3.0.0; extra == 'databricks'
Provides-Extra: dev
Requires-Dist: mypy~=1.14.0; extra == 'dev'
Requires-Dist: pip-audit~=2.7.0; extra == 'dev'
Requires-Dist: pytest-asyncio~=0.25.0; extra == 'dev'
Requires-Dist: pytest-cov~=6.0; extra == 'dev'
Requires-Dist: pytest~=8.3.0; extra == 'dev'
Requires-Dist: ruff~=0.9.0; extra == 'dev'
Provides-Extra: dynamodb
Requires-Dist: aioboto3>=12.0.0; extra == 'dynamodb'
Provides-Extra: elasticsearch
Requires-Dist: elasticsearch[async]>=8.0.0; extra == 'elasticsearch'
Provides-Extra: influxdb2
Requires-Dist: influxdb-client>=1.43.0; extra == 'influxdb2'
Provides-Extra: influxdb3
Requires-Dist: influxdb3-python>=0.18.0; extra == 'influxdb3'
Provides-Extra: local-embed
Requires-Dist: sentence-transformers~=3.0; extra == 'local-embed'
Provides-Extra: mongodb
Requires-Dist: motor>=3.3.0; extra == 'mongodb'
Provides-Extra: mysql
Requires-Dist: aiomysql>=0.2.0; extra == 'mysql'
Provides-Extra: postgres
Requires-Dist: asyncpg~=0.30.0; extra == 'postgres'
Provides-Extra: redis-connector
Requires-Dist: redis[hiredis]>=5.0.0; extra == 'redis-connector'
Provides-Extra: snowflake
Requires-Dist: snowflake-connector-python>=3.0.0; extra == 'snowflake'
Provides-Extra: tiktoken
Requires-Dist: tiktoken~=0.8.0; extra == 'tiktoken'
Description-Content-Type: text/markdown

![License](https://img.shields.io/badge/license-Apache%202.0-green)
![Python](https://img.shields.io/badge/python-3.11+-blue)
![Tests](https://img.shields.io/badge/tests-1062%20passing-green)

# WhyCode

**Ask why any function exists. Get the decision that created it.**

WhyCode is an MCP server that gives AI coding agents persistent
memory, bidirectional code provenance, and independent quality
verification. It works with Claude Code, Cursor, Windsurf, and any
MCP-compatible client. Free forever for solo developers. Apache 2.0.

## See it in action

<!-- Demo GIF goes here — record with: asciinema rec demo.cast -->
<!-- Convert to GIF with: agg demo.cast demo.gif -->
<!-- Then: ![WhyCode provenance demo](docs/demo.gif) -->

```bash
$ provenance.reverse("backend/auth/auth_service.py", "hash_password")
decision   Use Argon2id for all password hashing
recorded   Apr 10 · claude-code · session sess_a1b2
rationale  OWASP 2024 recommendation, memory-hard, GPU-resistant
commit     a1b2c3d — [P1] Auth service with Argon2id hashing
changes    hash_password (added), verify_password (added)
verified   CI passed · run #9912 · Apr 10 10:12

$ drift.check("my-saas-project")
warning    backend/cache/redis.py imports asyncpg directly
violates   decision dec_007: "All DB access through db_backend.py"
```

## Quick start

Requires Node.js 18+. Python 3.11+ installed automatically.

```bash
npx whycode@latest init-and-serve
```

Open http://localhost:8100 — a 5-step walkthrough gets you to your
first provenance query in under 5 minutes.

Works with: Claude Code · Cursor · Windsurf · Any MCP client
Runs on: Windows · macOS · Linux
Backends: Git and non-git projects

## What WhyCode does

### Bidirectional code provenance
Every architectural decision links to the exact code it produced —
down to the AST level. Ask why any function exists and get back the
decision, the commit, and the CI verification.

### Active context injection
Relevant decisions are injected automatically before every session
and every file edit via Claude Code hooks. Your agent knows your
architecture before it types a character. No manual prompting required.

### Independent quality harness
Five sensors — coverage delta, complexity, import health, drift
violations, decision density — running independently of what the
agent reports. Catches tautological tests that prove implementation
instead of specification.

### Architectural drift detection
Compares your import graph against recorded architecture decisions
in real time. Catches violations before they compound into a refactor.

### Rollback impact planning
Before reverting any decision, see the full downstream dependency
graph — which functions break, which decisions become orphaned,
and the risk level.

## How it works

**1. Install once**
```bash
npx whycode@latest init-and-serve
```
One command on any OS. Python venv, server, and MCP config handled automatically.

**2. Init each project**
```bash
whycode init
```
Creates config, git hooks, and a project CLAUDE.md that instructs the agent.

**3. Work normally**
Open Claude Code or Cursor. Context is injected automatically. Record
decisions when you make architectural choices.

**4. Query anything**
```bash
provenance.reverse("path/to/file.py", "function_name")
drift.check("project-name")
harness.score("session-id")
```

## What makes WhyCode different

Most AI memory tools give agents session memory — the ability to
recall past conversations and past context.

WhyCode does something different: it links decisions to code.

When your agent writes a function, WhyCode records why — and you
can ask "why does this function exist" and get back the decision,
the commit, and the CI result that verified it.

| Capability | WhyCode | Typical AI memory tools |
|---|---|---|
| Semantic memory | ✓ | ✓ |
| Decision → code provenance | ✓ | — |
| Reverse trace: code → decision | ✓ | — |
| CI verification linked | ✓ | — |
| Drift detection | ✓ | — |
| Tautological test detection | ✓ | — |
| Rollback impact planning | ✓ | — |
| Auto context injection via hooks | ✓ | partial |

## Installation

### One command (recommended)
```bash
npx whycode@latest init-and-serve
```
Requires Node.js 18+. Detects or installs Python 3.11+ automatically.

### Custom port
```bash
npx whycode@latest init-and-serve --port 9000
```

### Team mode
```bash
npx whycode@latest init-and-serve --mode team
```

### Python directly
```bash
pip install whycode
cd your-project
whycode init
whycode serve
whycode connect
```

### Per-project setup
Once the server is running, initialise each project:
```bash
cd your-project
whycode init
```
One server serves all projects simultaneously.

## Configuration

WhyCode generates `whycode.toml` in each project directory.
See `whycode.toml.example` for all options.

Key settings:

```toml
[server]
port = 8100        # change if 8100 is in use
mode = "solo"      # or "team" for shared server

[embedding]
backend = "local"  # or "ollama" for higher quality

[billing]
open_beta = true   # all features free during beta
enabled = false    # set true when Stripe configured
```

## MCP client support

`whycode connect` auto-configures all detected clients.

| Client | MCP tools | Auto context | File hooks | Auto session |
|---|---|---|---|---|
| Claude Code | ✓ full | ✓ | ✓ | ✓ |
| Cursor | ✓ | ✓ via tool | ✓ via before_edit | ✓ inactivity |
| Windsurf | ✓ | ✓ via tool | ✓ via before_edit | ✓ inactivity |
| Claude Desktop | ✓ | ✓ via tool | ✓ via before_edit | ✓ inactivity |
| Any MCP client | ✓ | ✓ via tool | ✓ via before_edit | ✓ inactivity |

## OAuth login setup (optional)

WhyCode supports Google and GitHub OAuth for dashboard login. OAuth
is optional — the solo bearer token works for both the dashboard and
MCP clients without any additional setup.

### Show your solo bearer token

```bash
whycode token show
```

Paste the token into the dashboard login form, or run
`whycode token write-config --client claude-desktop` to wire it
into Claude Desktop automatically.

### Configure Google OAuth

1. Go to <https://console.cloud.google.com>
2. Create a project → APIs & Services → Credentials
3. Create an OAuth 2.0 Client ID → Web application
4. Add `http://localhost:8100/api/auth/oauth/google/callback` as an
   authorised redirect URI
5. Copy the client ID and secret, then run:

```bash
whycode config set-oauth --provider google
```

### Configure GitHub OAuth

1. Go to <https://github.com/settings/applications/new>
2. Homepage URL: `http://localhost:8100`
3. Authorization callback URL:
   `http://localhost:8100/api/auth/oauth/github/callback`
4. Copy the client ID and secret, then run:

```bash
whycode config set-oauth --provider github
```

Restart the server after configuring: `whycode serve`.

## Contributing

```bash
git clone https://github.com/whycodeAI/whycode.git
cd whycode
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest tests/ -v
```

Before submitting a PR:
- `ruff check .` must pass
- `mypy --strict backend/` must pass
- `pytest tests/ --cov=backend --cov-fail-under=82` must pass
- No new runtime CVEs (`pip-audit`)

See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for full guidelines.

## Security

WhyCode stores no credentials in its database. All secrets live
in your OS keyring or an AES-256-GCM encrypted vault file. Passwords
are hashed with Argon2id (64MB, 3 iterations, parallelism 4).

See [docs/SECURITY.md](docs/SECURITY.md) for the complete security model.

To report a vulnerability: open a GitHub Security Advisory or email
security@whycodeai.github.io

## Benchmarks

Retrieval quality measured against LongMemEval-S and LOCOMO datasets.
Results in [scripts/benchmark/README.md](scripts/benchmark/README.md).

Run benchmarks yourself:
```bash
pip install whycode[benchmark]
whycode-benchmark run --dataset longmemeval --output results.json
```

## Pricing

**Solo** — Free forever. Full capabilities. Apache 2.0. Self-hosted.
All features available during open beta.

**Team** — $9/seat/month (min 2 seats). Shared decision history,
conflict detection, sprint intelligence. Trigger: shared state,
not seat count.

**Enterprise** — Custom. RBAC, audit export, SSO, SLA.

All features free during open beta.

## License

Apache 2.0 — see [LICENSE](LICENSE) for details.

Copyright 2026 WhyCodeAI
