[![Support on Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/mrerin)
[![Sponsor](https://img.shields.io/badge/sponsor-❤-pink)](https://github.com/sponsors/MrErin)

# Unfamiliar

[![PyPI version](https://img.shields.io/pypi/v/unfamiliar.svg)](https://pypi.org/project/unfamiliar/)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

*The rain hammers the window while you stare at 50,000 lines of someone else's mistakes. No README. No comments worth
a damn. Just functions calling functions calling functions, disappearing into the dark like a lead that goes cold at
midnight.*

This is `unfamiliar`, a tool that analyzes code and gamifies the process of learning a new codebase, taking you from
overwhelmed gumshoe to hardboiled detective.

Oh yeah. It's all themed like a Film Noir mystery. Because we live in an age of wonders and you might as well do fun
things with technology.

![Unfamiliar demo](assets/demo.gif)

---

## What it does

Unfamiliar runs static analysis across your codebase, then uses an LLM to generate a set of investigation missions
organized into seven categories:

| Category                | What you investigate                                   |
|-------------------------|--------------------------------------------------------|
| Architecture            | Module structure, entry points, how components connect |
| Domain & Business Logic | Core workflows, rules, failure modes                   |
| Data Flow               | Schema, state management, how data moves               |
| Dependencies            | External services, APIs, key libraries, configuration  |
| Conventions             | Patterns, idioms, error handling style, naming         |
| Testing                 | Coverage, test quality, untested paths                 |
| Technical Debt          | Code smells, structural risks, violations              |

Missions are chained — completing one unlocks the next. You start with a small set of leads and progressively
unlock the big picture. Each mission tells you exactly what to look at and what question to answer; you're
reviewing the code in your own IDE. Unfamiliar just offers structure for your investigation.

Your code never leaves your machine. Unfamiliar runs static analysis locally and sends only structural metadata (file
paths, complexity scores, import relationships) to the LLM to generate your missions. The mission output is also stored
locally, so the entire investigation can be played offline after initialization without further LLM calls.

---

## Requirements

- Python 3.11 or later
- A **git repository** to investigate (Unfamiliar requires `.git` to be present)
- An API key for a supported LLM provider:
    - **Anthropic**  — Claude models via [console.anthropic.com](https://console.anthropic.com)
    - **Zhipu GLM** — GLM models

---

## Installation

```bash
pip install unfamiliar
```

Or in a virtual environment (recommended):

```bash
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install unfamiliar
```

---

## Quick start

**1. Set your API key**

Anthropic:

```bash
export ANTHROPIC_API_KEY=sk-ant-...
```

Zhipu GLM:

```bash
export ZHIPUAI_API_KEY=your-key
```

**2. Start an investigation**

Anthropic (default):

```bash
unfamiliar investigate /path/to/some/repo
```

GLM:

```bash
UNFAMILIAR_PROVIDER=glm unfamiliar investigate /path/to/some/repo
```

Or set the provider in your config (see Configuration below) and run normally:

```bash
unfamiliar investigate /path/to/some/repo
```

Unfamiliar analyzes the codebase, generates your missions, and opens the investigation terminal.

**3. Work your leads**

Inside the terminal, type commands to navigate your case:

```
investigate          — show available leads (missions)
investigate 3        — start lead #3
file report          — mark the current lead complete
case board           — campaign overview and progress
case file            — re-read the codebase briefing
bury the day         — end session (progress is saved)
```

Type `call in a marker` to see the full command reference.

---

## Configuration

On first run, Unfamiliar creates `~/.unfamiliar/config.toml` with these defaults:

```toml
[general]
provider = "anthropic"   # "anthropic" or "glm"
token_budget = 30000     # LLM token budget for analysis
theme = "film_noir"
```

API keys are **never** stored in the config file. Set them as environment variables:

| Provider              | Environment variable | Notes                      |
|-----------------------|----------------------|----------------------------|
| `anthropic` (default) | `ANTHROPIC_API_KEY`  |                            |
| `glm`                 | `ZHIPUAI_API_KEY`    | OpenAI-compatible endpoint |

**To use Zhipu GLM:**

```toml
[general]
provider = "glm"
```

```bash
export ZHIPUAI_API_KEY=your-key
```

**Advanced: override provider defaults**

```toml
[llm]
model = "claude-opus-4"       # override default model
max_tokens = 8192              # override max output tokens
base_url = "https://..."       # custom OpenAI-compatible endpoint
api_key_env = "MY_KEY"         # read API key from a custom env var
```

You can also override model and token limit per-session via environment variables:

```bash
UNFAMILIAR_MODEL=claude-haiku-4-5 unfamiliar investigate /path/to/repo
UNFAMILIAR_MAX_TOKENS=2048 unfamiliar investigate /path/to/repo
```

---

## All CLI commands

```
unfamiliar investigate <repo>   Start or resume an investigation for a repo
unfamiliar campaigns            List all saved campaigns
unfamiliar resume               Resume the most recent active campaign
unfamiliar --version            Show version
```

---

## All TUI commands

Commands inside the investigation terminal (Film Noir theme):

| Command            | What it does                         |
|--------------------|--------------------------------------|
| `investigate`      | Show available leads                 |
| `investigate <N>`  | Start lead number N                  |
| `lead <N>`         | Show details for lead N              |
| `file report`      | Mark current lead complete           |
| `case board`       | Campaign overview and progress       |
| `case file`        | Re-read the codebase briefing        |
| `break in <N>`     | Force-unlock a sealed lead by number |
| `call in a marker` | Show all commands                    |
| `bury the day`     | End session (progress saved)         |
| `close the case`   | End the campaign with a final report |

---

## Campaign storage

Campaigns are stored locally at `~/.unfamiliar/campaigns/`. Each repo gets its own subdirectory. Nothing is sent
anywhere except to your configured LLM provider during analysis.

---

## Future Plans

I've got a bunch of ideas for new themes and gamification possibilities, plus expanding the LLM provider support. If you
have a suggestion, feel free to open a feature request.

---

## Support

If Unfamiliar is useful to you, consider leaving a tip. I got laid off and my kids need braces.

[![Support on Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/mrerin)
[![Sponsor](https://img.shields.io/badge/sponsor-❤-pink)](https://github.com/sponsors/MrErin)

---

## License

MIT — see [LICENSE](LICENSE) for details.
