Metadata-Version: 2.4
Name: frictionlog
Version: 0.1.1
Summary: Your AGENTS.md should grow from your scars, not from a template. A local-first Claude Code companion.
Project-URL: Homepage, https://github.com/SHzzzAyys/frictionlog
Project-URL: Repository, https://github.com/SHzzzAyys/frictionlog
Project-URL: Issues, https://github.com/SHzzzAyys/frictionlog/issues
Author: FrictionLog contributors
License: MIT License
        
        Copyright (c) 2026 FrictionLog contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: agents-md,ai-coding,claude-code,cli,developer-tools
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: openai>=1.40
Requires-Dist: pydantic-settings>=2.4
Requires-Dist: pydantic>=2.7
Requires-Dist: sqlmodel>=0.0.22
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-mock>=3.14; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# FrictionLog

> Your AGENTS.md should grow from your scars, not from a template.
> A local-first Claude Code companion.

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

FrictionLog watches your Claude Code sessions and only records *correction moments* — the times you rolled back an edit, told the AI "no, do X instead," or renamed something it just created. Every week it writes you a markdown digest with your top recurring frictions, drafts AGENTS.md rules you can copy-paste, and flags rules that have gone 30 days without a single match — so your rule set can shrink as well as grow.

It does not analyze your code. It does not phone home. It does not tell you how to be a better engineer.

---

## 30-second install

```bash
# uv (recommended)
uv tool install frictionlog

# or pipx
pipx install frictionlog
```

Then, inside your Claude Code project:

```bash
cd path/to/your/project
fl init
```

That's it. Now use Claude Code normally. Seven days later, look in `~/.frictionlog/digest/` for your first weekly digest.

---

## The five commands you actually use

| Command | What it does |
|---|---|
| `fl init` | Inject FrictionLog hooks into `.claude/settings.local.json`. Run once per project. |
| `fl recent` | List recent friction events, newest first. `--days N` to widen the window. |
| `fl pattern` | Show your Top-5 recurring friction categories over the last 30 days. |
| `fl pending` | Show events FrictionLog flagged but you haven't confirmed yet. |
| `fl digest` | Generate this week's digest now. `fl digest open` opens it. `fl digest --force` bypasses the 7-day cooldown. |

There are more (`fl confirm`, `fl status`, `fl ack`, `fl share-stats`, `fl uninstall`). Run `fl --help` to see them.

---

## How it works (60 seconds)

1. **`fl init` injects two hooks** into `.claude/settings.local.json`:
   - `PostToolUse` — fires after every Edit / Write / Bash / MultiEdit.
   - `UserPromptSubmit` — fires when you send Claude your next message.
2. **The PostToolUse hook** records the tool call to a local SQLite, runs a fast heuristic ("did the user just undo something?"), and writes one line to stderr if it suspects a correction:
   ```
   💡 [FrictionLog] 检测到可能纠正:撤销 try-except. 下条消息以 fl:y / fl:n 开头确认。
   ```
3. **Start your next message with `fl:y`** to confirm, `fl:n` to reject, `fl:i` to ignore. The prefix is stripped before Claude sees the message — you only "pay" 4 characters.
4. **Every 7 days**, the hook silently spawns a background worker that scans your AGENTS.md, matches recent confirmed frictions, and writes `~/.frictionlog/digest/YYYY-MM-DD.md`.
5. **Read the digest, run `fl ack`**. Connect 4 weeks in a row and you've hit the north-star.

---

## The privacy contract (three rules, no asterisks)

1. **Nothing leaves your machine without your explicit command.** No telemetry, no auto-upload, no "anonymous usage stats." The only thing that calls out is the LLM SDK — and only when you've put your own key in `~/.frictionlog/config.toml`.
2. **The only place data lives is `~/.frictionlog/`.** SQLite + markdown files. Uninstall = delete that folder (FrictionLog won't touch it for you).
3. **`fl share-stats` is the *only* way to share anything**, and it just opens `gist.github.com/new` with a pre-rendered markdown of *counts only* — no event summaries, no project paths. You copy. You paste. You publish. We never see it.

If you're worried about the LLM hop: don't configure an LLM key. The heuristic-only path still works — you just lose the "second-pass classification" and the weekly rule-draft generation. The digest still ships with your Top-5.

---

## Where things live

```
~/.frictionlog/
├── db.sqlite              ← events, digests, rules, share_history
├── config.toml            ← your LLM key (you create this; FrictionLog doesn't)
├── digest/
│   └── 2026-05-24.md      ← weekly digests
├── queue/
│   └── pending_llm.jsonl  ← async LLM classification queue
└── logs/
    └── 2026-05-18.log     ← rolling 7-day hook log
```

---

## Configuring an LLM key (optional)

Create `~/.frictionlog/config.toml`:

```toml
[llm]
provider = "deepseek"
base_url = "https://api.deepseek.com"
api_key = "sk-..."
classify_model = "deepseek-chat"
draft_model = "deepseek-reasoner"
```

Any OpenAI-compatible provider works — just point `base_url` at it. The hook *never* calls the LLM directly; classification runs in an async batch worker so you never wait for it.

**Without a key**, FrictionLog runs heuristic-only:
- ✅ Events recorded
- ✅ Stderr nudge + `fl:y/n` confirmation works
- ✅ Weekly digest still ships with Top-5
- ❌ No LLM second-pass classification (heuristic is the only judge)
- ❌ No LLM-generated rule drafts in the digest

---

## Frequently asked

**"Does this slow Claude Code down?"**
No. Hook function-body p90 is ~26ms; the OS process spawn adds ~300ms but that's invisible next to the tool call itself (1-5s). LLM calls happen in a detached background process.

**"What if I have other hooks in `.claude/settings.json`?"**
`fl init` writes to `.claude/settings.local.json` (which Claude Code gitignores) instead, so it doesn't touch the shared file. It also detects and merges around any existing hooks. `fl uninstall` only removes the blocks FrictionLog added.

**"Does it work on Windows?"**
Yes. Windows is a first-class target. CI runs on macOS + Ubuntu + Windows × Python 3.11 + 3.12.

**"What if my AGENTS.md is in a weird format?"**
FrictionLog parses bullet (`-`, `*`, `+`) and numbered (`1.`) lists outside of code fences and headers. Anything else is skipped. If your rule list isn't structured that way, the "stale rules" section just stays empty — nothing breaks.

**"What gets sent to my LLM provider?"**
Per event: heuristic category, tool name, a short sanitized tool-input summary (file *basename* only, never the path), and your next user message truncated to 300 chars. Per digest: the Top-5 category names, counts, and one example summary each. No file contents. No project paths.

---

## Uninstall

```bash
fl uninstall          # removes the hook block from .claude/settings.local.json
rm -rf ~/.frictionlog/  # optional — your data and digests live here
uv tool uninstall frictionlog
```

`fl uninstall` deliberately leaves `~/.frictionlog/` alone. If you want to come back later, your event history is still there.

---

## Status

**Current version: v0.1.0** — MVP launch. Tested on Python 3.11 / 3.12 across macOS / Ubuntu / Windows. 297 tests in CI.

**Roadmap:**

| Milestone | Date | What |
|---|---|---|
| M4 (current) | 2026-07-09 | v0.1.0 public on PyPI |
| M5 | 2026-10-09 | 3-month north-star review |
| v0.2 | TBD | Cursor + Codex CLI adapters, web view |

---

## Contributing

See [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md). Bugs and feature requests welcome at [GitHub Issues](https://github.com/SHzzzAyys/frictionlog/issues).

For deeper details: [`docs/PRIVACY.md`](docs/PRIVACY.md) (the long version of the privacy contract), [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md) (hook not firing, sqlite locked, LLM config), [`docs/CHANGELOG.md`](docs/CHANGELOG.md) (version history).

---

## License

MIT. See [`LICENSE`](LICENSE).
