fridai 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fridai-0.1.0/.github/workflows/release.yml +57 -0
- fridai-0.1.0/.github/workflows/test.yml +47 -0
- fridai-0.1.0/.gitignore +42 -0
- fridai-0.1.0/LICENSE +21 -0
- fridai-0.1.0/PKG-INFO +207 -0
- fridai-0.1.0/README.ko.md +156 -0
- fridai-0.1.0/README.md +161 -0
- fridai-0.1.0/pyproject.toml +39 -0
- fridai-0.1.0/scripts/embed_smoke.py +32 -0
- fridai-0.1.0/src/fridai/__init__.py +1 -0
- fridai-0.1.0/src/fridai/cli.py +98 -0
- fridai-0.1.0/src/fridai/core/__init__.py +0 -0
- fridai-0.1.0/src/fridai/core/config.py +37 -0
- fridai-0.1.0/src/fridai/core/embeddings.py +65 -0
- fridai-0.1.0/src/fridai/core/models.py +36 -0
- fridai-0.1.0/src/fridai/core/redact.py +87 -0
- fridai-0.1.0/src/fridai/core/search.py +136 -0
- fridai-0.1.0/src/fridai/core/sources/__init__.py +1 -0
- fridai-0.1.0/src/fridai/core/sources/agent_recall.py +176 -0
- fridai-0.1.0/src/fridai/core/sources/claude_recall.py +143 -0
- fridai-0.1.0/src/fridai/core/sources/code.py +232 -0
- fridai-0.1.0/src/fridai/core/sources/codex_recall.py +122 -0
- fridai-0.1.0/src/fridai/core/sources/commits.py +115 -0
- fridai-0.1.0/src/fridai/core/sources/gemini_recall.py +114 -0
- fridai-0.1.0/src/fridai/core/store.py +289 -0
- fridai-0.1.0/src/fridai/server.py +107 -0
- fridai-0.1.0/tests/__init__.py +17 -0
- fridai-0.1.0/tests/test_agent_recall.py +138 -0
- fridai-0.1.0/tests/test_claude_recall.py +121 -0
- fridai-0.1.0/tests/test_code.py +186 -0
- fridai-0.1.0/tests/test_codex_recall.py +158 -0
- fridai-0.1.0/tests/test_commits.py +82 -0
- fridai-0.1.0/tests/test_embeddings.py +46 -0
- fridai-0.1.0/tests/test_gemini_recall.py +121 -0
- fridai-0.1.0/tests/test_index.py +68 -0
- fridai-0.1.0/tests/test_redact.py +80 -0
- fridai-0.1.0/tests/test_search.py +116 -0
- fridai-0.1.0/tests/test_server.py +64 -0
- fridai-0.1.0/tests/test_store.py +188 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment:
|
|
14
|
+
name: pypi
|
|
15
|
+
url: https://pypi.org/p/fridai
|
|
16
|
+
permissions:
|
|
17
|
+
id-token: write
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Install build tools
|
|
26
|
+
run: pip install build twine
|
|
27
|
+
|
|
28
|
+
- name: Build
|
|
29
|
+
run: python -m build
|
|
30
|
+
|
|
31
|
+
- name: Check package metadata
|
|
32
|
+
run: twine check dist/*
|
|
33
|
+
|
|
34
|
+
- name: Verify version matches tag
|
|
35
|
+
run: |
|
|
36
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
37
|
+
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
|
|
38
|
+
echo "pyproject version=$VERSION tag=$TAG"
|
|
39
|
+
test "$VERSION" = "$TAG"
|
|
40
|
+
|
|
41
|
+
- name: Publish to PyPI
|
|
42
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
43
|
+
|
|
44
|
+
release:
|
|
45
|
+
needs: publish
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
permissions:
|
|
48
|
+
contents: write
|
|
49
|
+
steps:
|
|
50
|
+
- name: Create GitHub Release
|
|
51
|
+
uses: softprops/action-gh-release@v2
|
|
52
|
+
with:
|
|
53
|
+
tag_name: ${{ github.ref_name }}
|
|
54
|
+
name: Release ${{ github.ref_name }}
|
|
55
|
+
generate_release_notes: true
|
|
56
|
+
env:
|
|
57
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
cache: pip
|
|
22
|
+
- name: Install
|
|
23
|
+
run: pip install -e .
|
|
24
|
+
- name: Run tests
|
|
25
|
+
run: python -m unittest discover -s tests -v
|
|
26
|
+
|
|
27
|
+
# Verify fastembed actually works once (needs a model download). Isolated with
|
|
28
|
+
# continue-on-error so network/HF flakiness doesn't fail the whole run — the test job
|
|
29
|
+
# above is the authoritative gate.
|
|
30
|
+
embed-smoke:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
continue-on-error: true
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.12"
|
|
38
|
+
cache: pip
|
|
39
|
+
- name: Cache fastembed model
|
|
40
|
+
uses: actions/cache@v4
|
|
41
|
+
with:
|
|
42
|
+
path: ~/.cache/fastembed
|
|
43
|
+
key: fastembed-nomic-embed-text-v1.5
|
|
44
|
+
- name: Install
|
|
45
|
+
run: pip install -e .
|
|
46
|
+
- name: fastembed embedding smoke
|
|
47
|
+
run: python scripts/embed_smoke.py
|
fridai-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
.venv/
|
|
7
|
+
venv/
|
|
8
|
+
env/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
|
|
12
|
+
# Test / tooling caches
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.tox/
|
|
17
|
+
.coverage
|
|
18
|
+
.coverage.*
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# fastembed / model caches (if created inside the repo)
|
|
22
|
+
fastembed_cache/
|
|
23
|
+
.fastembed_cache/
|
|
24
|
+
local_cache/
|
|
25
|
+
|
|
26
|
+
# Environment
|
|
27
|
+
.env
|
|
28
|
+
.env.*
|
|
29
|
+
.python-version
|
|
30
|
+
|
|
31
|
+
# IDEs / editors
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
*.iml
|
|
35
|
+
*.swp
|
|
36
|
+
*.swo
|
|
37
|
+
*~
|
|
38
|
+
.\#*
|
|
39
|
+
|
|
40
|
+
# OS
|
|
41
|
+
.DS_Store
|
|
42
|
+
Thumbs.db
|
fridai-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chloe Jungah Kim (chloeeekim)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fridai-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fridai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local MCP server for recalling past code, commits, and AI conversations — search-only, no local LLM required
|
|
5
|
+
Project-URL: Homepage, https://github.com/chloeeekim/fridai
|
|
6
|
+
Project-URL: Repository, https://github.com/chloeeekim/fridai
|
|
7
|
+
Project-URL: Issues, https://github.com/chloeeekim/fridai/issues
|
|
8
|
+
Author-email: Chloe Jungah Kim <hiyaku0317@gmail.com>
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Chloe Jungah Kim (chloeeekim)
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
40
|
+
Classifier: Topic :: Software Development
|
|
41
|
+
Requires-Python: >=3.10
|
|
42
|
+
Requires-Dist: fastembed>=0.3
|
|
43
|
+
Requires-Dist: mcp>=1.0
|
|
44
|
+
Requires-Dist: numpy>=1.21
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# fridai 🛠️
|
|
48
|
+
|
|
49
|
+
*English | [한국어](README.ko.md)*
|
|
50
|
+
|
|
51
|
+
A lightweight **MCP server** that lets coding agents (Claude Code, etc.) recall your past
|
|
52
|
+
**code, commits, and AI conversations** via the `recall` tool — **100% local**.
|
|
53
|
+
Search & recall only — **no local LLM required.**
|
|
54
|
+
|
|
55
|
+
- **Search-only (read-only).** The calling agent (an LLM) does the reasoning; fridai
|
|
56
|
+
just returns evidence with sources.
|
|
57
|
+
- **Local embeddings (fastembed, onnx).** No Ollama or external API. Semantic search works
|
|
58
|
+
out of the box (falls back to lexical if fastembed isn't installed).
|
|
59
|
+
- **Multi-agent history.** Auto-indexes Claude Code · OpenAI Codex CLI · Gemini CLI conversations.
|
|
60
|
+
- **Private by design.** Your memory never leaves the machine; secrets are auto-masked at index time.
|
|
61
|
+
|
|
62
|
+
**Status:** early development. **Requires** Python 3.10+ and `git` (for code/commit indexing).
|
|
63
|
+
|
|
64
|
+
## How it works
|
|
65
|
+
|
|
66
|
+
1. **Index** (`fridai index`) builds a local database from three source types:
|
|
67
|
+
- **AI conversations** — parses each agent's session logs into question→answer *turns*, and
|
|
68
|
+
matches a question to its **resulting git commit** (time window ∩ touched files).
|
|
69
|
+
- **Code** — chunks git-tracked files by function/class (line-window fallback), with line ranges.
|
|
70
|
+
- **Commits** — indexes git commit history (subject + changed files).
|
|
71
|
+
2. Everything is stored in **sqlite + FTS5** (lexical) plus **float32 vectors** at `~/.fridai/index.db`.
|
|
72
|
+
3. **Recall** fuses lexical (BM25) and vector (cosine) results via **RRF**, then reranks so real work
|
|
73
|
+
artifacts (code/commits/edited turns) outrank bare question turns, and dedupes repeated questions.
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
git clone https://github.com/chloeeekim/fridai.git
|
|
79
|
+
cd fridai
|
|
80
|
+
pipx install . # isolated (recommended). Or: pip install -e . in a venv
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Pulls `numpy` + `fastembed` (onnx) + `mcp`. Registers the `fridai` command.
|
|
84
|
+
|
|
85
|
+
## Quickstart
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
fridai index --source all # build the index (current repo + all agent conversations)
|
|
89
|
+
fridai stats # index overview
|
|
90
|
+
claude mcp add fridai -- fridai mcp # register with Claude Code
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
After registering, the agent recalls via the `recall` tool. Re-run `fridai index` anytime to
|
|
94
|
+
refresh — it's **incremental** (only changed files/sessions/new commits are reprocessed), so it's cheap.
|
|
95
|
+
|
|
96
|
+
## CLI reference
|
|
97
|
+
|
|
98
|
+
| Command | Description |
|
|
99
|
+
| :--- | :--- |
|
|
100
|
+
| `fridai index` | Build/update the index. |
|
|
101
|
+
| `fridai mcp` | Run the stdio MCP server. |
|
|
102
|
+
| `fridai stats` | Print document counts by source. |
|
|
103
|
+
|
|
104
|
+
`index` flags:
|
|
105
|
+
|
|
106
|
+
| Flag | Meaning |
|
|
107
|
+
| :--- | :--- |
|
|
108
|
+
| `--source agent\|code\|commits\|all` | What to index (default `all`). `agent` = all AI conversations. |
|
|
109
|
+
| `--path DIR` | Target repo for code/commits (default: current directory). |
|
|
110
|
+
| `--reindex` | Ignore incremental state and rebuild everything. |
|
|
111
|
+
| `--no-embed` | Skip embeddings (lexical index only). |
|
|
112
|
+
| `--no-prune` | Keep chunks of files deleted from git (code). |
|
|
113
|
+
| `--no-redact` | Turn off secret masking (on by default). |
|
|
114
|
+
|
|
115
|
+
## The `recall` tool (MCP)
|
|
116
|
+
|
|
117
|
+
The server exposes one tool, `recall(query, k=5, repo="", source_type="")`:
|
|
118
|
+
|
|
119
|
+
- `query` — search text (natural language and/or code identifiers).
|
|
120
|
+
- `k` — max results (default 5).
|
|
121
|
+
- `repo` — empty = current working repo (server detects cwd); `"all"` = every repo; `"<name>"` = a specific repo.
|
|
122
|
+
- `source_type` — empty = all; one of `agent_turn` · `code` · `commit` · `note`.
|
|
123
|
+
|
|
124
|
+
It returns text with numbered, cited hits for the agent to read — for example:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
fridai recall — 2 memory item(s) for "docker mount" (all repos, with sources):
|
|
128
|
+
|
|
129
|
+
### [1] myrepo 2026-07-01 [codex] session:how did I add the docker mount?
|
|
130
|
+
Q: how did I add the docker mount?
|
|
131
|
+
A: added a bind mount via volumes.
|
|
132
|
+
|
|
133
|
+
### [2] myrepo/docker-compose.yml:1-20
|
|
134
|
+
volumes: ...
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Non-Claude sources are tagged (`🤖 codex` / `🤖 gemini` in the CLI, `[codex]`/`[gemini]` in citations).
|
|
138
|
+
|
|
139
|
+
## Registering with other MCP clients
|
|
140
|
+
|
|
141
|
+
fridai is a standard **stdio MCP server** — the launch command is `fridai mcp`. Any MCP-capable
|
|
142
|
+
client can use it. For clients that read an `mcpServers` config:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"fridai": { "command": "fridai", "args": ["mcp"] }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Indexed agent sources
|
|
153
|
+
|
|
154
|
+
| Agent | Default data path | Override env var |
|
|
155
|
+
| :--- | :--- | :--- |
|
|
156
|
+
| Claude Code | `~/.claude/projects/` | `FRIDAI_CLAUDE_PROJECTS` |
|
|
157
|
+
| OpenAI Codex CLI | `~/.codex/sessions/` | `FRIDAI_CODEX_SESSIONS` |
|
|
158
|
+
| Gemini CLI | `~/.gemini/tmp/` | `FRIDAI_GEMINI_SESSIONS` |
|
|
159
|
+
|
|
160
|
+
A missing agent directory is silently skipped.
|
|
161
|
+
|
|
162
|
+
## Security
|
|
163
|
+
|
|
164
|
+
Secrets (AWS keys, GitHub/Slack tokens, PEM private keys, JWTs, `password=`…) are auto-masked
|
|
165
|
+
at index time (on by default). Nothing is sent off the machine.
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
fridai index --source code --no-redact # disable masking
|
|
169
|
+
echo "*.env" >> .fridaiignore # exclude paths (repo root or ~/.fridai/)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The high-entropy heuristic is **off by default** (too many false positives on long identifiers);
|
|
173
|
+
enable it with `FRIDAI_REDACT_ENTROPY=1`.
|
|
174
|
+
|
|
175
|
+
## Environment variables
|
|
176
|
+
|
|
177
|
+
| Variable | Default | Description |
|
|
178
|
+
| :--- | :--- | :--- |
|
|
179
|
+
| `FRIDAI_HOME` | `~/.fridai` | Data home (index DB, etc.). |
|
|
180
|
+
| `FRIDAI_CLAUDE_PROJECTS` | `~/.claude/projects` | Claude Code transcript location. |
|
|
181
|
+
| `FRIDAI_CODEX_SESSIONS` | `~/.codex/sessions` | Codex CLI session location. |
|
|
182
|
+
| `FRIDAI_GEMINI_SESSIONS` | `~/.gemini/tmp` | Gemini CLI session location. |
|
|
183
|
+
| `FRIDAI_EMBED_BACKEND` | auto | `none` disables embeddings (lexical only). |
|
|
184
|
+
| `FRIDAI_FASTEMBED_MODEL` | `nomic-ai/nomic-embed-text-v1.5` | fastembed model name. |
|
|
185
|
+
| `FRIDAI_REDACT_ENTROPY` | off | `1` enables the high-entropy secret heuristic. |
|
|
186
|
+
| `FRIDAI_WORK_PENALTY` | `8` | How far to demote pure question turns in ranking. `0` disables. |
|
|
187
|
+
| `FRIDAI_COMMIT_WINDOW_MIN` | `180` | Minutes window for matching a question to its resulting commit. |
|
|
188
|
+
|
|
189
|
+
**Embedder consistency:** index and query with the same embedder. Mixing models makes vectors
|
|
190
|
+
incomparable even at the same dimension — the store then falls back to lexical search. Reindex
|
|
191
|
+
(`--reindex`) after switching models.
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
PYTHONPATH=src python3 -m unittest discover -s tests
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
CI (GitHub Actions) runs the suite on Python 3.10–3.14 plus a fastembed smoke check on every push/PR.
|
|
200
|
+
Tests are hermetic — `tests/__init__.py` isolates all `FRIDAI_*` paths and disables the embedder,
|
|
201
|
+
so no real `~/.fridai`/`~/.codex`/etc. is touched and no model is downloaded.
|
|
202
|
+
|
|
203
|
+
See [`docs/build-order.md`](docs/build-order.md) for the design & build-order rationale.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# fridai 🛠️
|
|
2
|
+
|
|
3
|
+
*[English](README.md) | 한국어*
|
|
4
|
+
|
|
5
|
+
코딩 에이전트(Claude Code 등)가 `recall` 툴로 당신의 과거 **코드·커밋·AI 대화 기록**을
|
|
6
|
+
**100% 로컬**에서 회수하게 해주는 경량 **MCP 서버**. 검색·회수 전용 — **로컬 LLM이 필요 없습니다.**
|
|
7
|
+
|
|
8
|
+
- **검색 전용(read-only).** 추론은 호출하는 에이전트(LLM)가 하고, fridai는 출처 포함 근거만 회수.
|
|
9
|
+
- **로컬 임베딩(fastembed, onnx).** Ollama·외부 API 불필요. 시맨틱 검색이 기본 동작(fastembed 없으면 어휘 검색 폴백).
|
|
10
|
+
- **멀티 에이전트 기록.** Claude Code · OpenAI Codex CLI · Gemini CLI 대화를 자동 인덱싱.
|
|
11
|
+
- **설계상 프라이버시.** 기억은 기기 밖으로 안 나가고, 시크릿은 인덱싱 시 자동 마스킹.
|
|
12
|
+
|
|
13
|
+
**상태:** 초기 개발. **요구사항:** Python 3.10+ 및 `git`(코드·커밋 인덱싱용).
|
|
14
|
+
|
|
15
|
+
## 동작 원리
|
|
16
|
+
|
|
17
|
+
1. **인덱싱**(`fridai index`)이 세 가지 소스로 로컬 DB를 만듭니다:
|
|
18
|
+
- **AI 대화** — 각 에이전트의 세션 로그를 질문→답변 *턴*으로 파싱하고, 질문을 **결과 git 커밋**과
|
|
19
|
+
매칭(시간창 ∩ 건드린 파일).
|
|
20
|
+
- **코드** — git 추적 파일을 함수/클래스 단위로 청킹(폴백은 N줄 윈도우), 인용용 라인범위 보존.
|
|
21
|
+
- **커밋** — git 커밋 히스토리(제목 + 변경 파일) 인덱싱.
|
|
22
|
+
2. 모두 `~/.fridai/index.db`의 **sqlite + FTS5**(어휘) + **float32 벡터**로 저장.
|
|
23
|
+
3. **회수**는 어휘(BM25)와 벡터(코사인)를 **RRF**로 융합한 뒤, 실제 작업 산물(코드/커밋/편집 턴)이
|
|
24
|
+
단순 질문 턴보다 위로 오게 재랭킹하고 반복 질문을 중복 제거합니다.
|
|
25
|
+
|
|
26
|
+
## 설치
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/chloeeekim/fridai.git
|
|
30
|
+
cd fridai
|
|
31
|
+
pipx install . # 격리 설치(권장). 또는 venv에서 pip install -e .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`numpy` + `fastembed`(onnx) + `mcp`가 딸려옵니다. `fridai` 명령이 등록됩니다.
|
|
35
|
+
|
|
36
|
+
## 빠른 시작
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
fridai index --source all # 인덱스 생성(현재 레포 + 모든 에이전트 대화)
|
|
40
|
+
fridai stats # 인덱스 개요
|
|
41
|
+
claude mcp add fridai -- fridai mcp # Claude Code에 등록
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
등록 후 에이전트가 `recall` 툴로 회수합니다. 언제든 `fridai index`를 다시 돌리면 갱신되는데,
|
|
45
|
+
**증분**(변경된 파일·세션·새 커밋만 재처리)이라 가볍습니다.
|
|
46
|
+
|
|
47
|
+
## CLI 레퍼런스
|
|
48
|
+
|
|
49
|
+
| 명령 | 설명 |
|
|
50
|
+
| :--- | :--- |
|
|
51
|
+
| `fridai index` | 인덱스 생성/갱신. |
|
|
52
|
+
| `fridai mcp` | stdio MCP 서버 실행. |
|
|
53
|
+
| `fridai stats` | 소스별 문서 수 출력. |
|
|
54
|
+
|
|
55
|
+
`index` 플래그:
|
|
56
|
+
|
|
57
|
+
| 플래그 | 의미 |
|
|
58
|
+
| :--- | :--- |
|
|
59
|
+
| `--source agent\|code\|commits\|all` | 인덱싱 대상(기본 `all`). `agent` = 모든 AI 대화. |
|
|
60
|
+
| `--path DIR` | code/commits 대상 레포(기본: 현재 디렉터리). |
|
|
61
|
+
| `--reindex` | 증분 무시하고 전체 재구성. |
|
|
62
|
+
| `--no-embed` | 임베딩 생략(어휘 인덱스만). |
|
|
63
|
+
| `--no-prune` | git에서 삭제된 파일의 청크 유지(code). |
|
|
64
|
+
| `--no-redact` | 시크릿 마스킹 끄기(기본 ON). |
|
|
65
|
+
|
|
66
|
+
## `recall` 툴 (MCP)
|
|
67
|
+
|
|
68
|
+
서버는 단일 툴 `recall(query, k=5, repo="", source_type="")`을 노출합니다:
|
|
69
|
+
|
|
70
|
+
- `query` — 검색어(자연어 및/또는 코드 식별자).
|
|
71
|
+
- `k` — 최대 결과 수(기본 5).
|
|
72
|
+
- `repo` — 빈값 = 현재 작업 레포(서버 cwd 감지); `"all"` = 전체; `"<이름>"` = 특정 레포.
|
|
73
|
+
- `source_type` — 빈값 = 전체; `agent_turn` · `code` · `commit` · `note` 중 하나.
|
|
74
|
+
|
|
75
|
+
에이전트가 읽을 수 있게 번호·출처가 달린 텍스트를 반환합니다. 예:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
fridai recall — 2 memory item(s) for "docker mount" (all repos, with sources):
|
|
79
|
+
|
|
80
|
+
### [1] myrepo 2026-07-01 [codex] session:how did I add the docker mount?
|
|
81
|
+
Q: how did I add the docker mount?
|
|
82
|
+
A: added a bind mount via volumes.
|
|
83
|
+
|
|
84
|
+
### [2] myrepo/docker-compose.yml:1-20
|
|
85
|
+
volumes: ...
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
비-Claude 소스는 태깅됩니다(CLI에선 `🤖 codex`/`🤖 gemini`, 출처엔 `[codex]`/`[gemini]`).
|
|
89
|
+
|
|
90
|
+
## 다른 MCP 클라이언트에 등록
|
|
91
|
+
|
|
92
|
+
fridai는 표준 **stdio MCP 서버**이고 실행 명령은 `fridai mcp` 입니다. MCP를 지원하는 어떤
|
|
93
|
+
클라이언트에서도 쓸 수 있습니다. `mcpServers` 설정을 읽는 클라이언트라면:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"mcpServers": {
|
|
98
|
+
"fridai": { "command": "fridai", "args": ["mcp"] }
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## 연동 에이전트 경로
|
|
104
|
+
|
|
105
|
+
| 에이전트 | 기본 데이터 경로 | 오버라이드 환경변수 |
|
|
106
|
+
| :--- | :--- | :--- |
|
|
107
|
+
| Claude Code | `~/.claude/projects/` | `FRIDAI_CLAUDE_PROJECTS` |
|
|
108
|
+
| OpenAI Codex CLI | `~/.codex/sessions/` | `FRIDAI_CODEX_SESSIONS` |
|
|
109
|
+
| Gemini CLI | `~/.gemini/tmp/` | `FRIDAI_GEMINI_SESSIONS` |
|
|
110
|
+
|
|
111
|
+
없는 에이전트 디렉터리는 조용히 건너뜁니다.
|
|
112
|
+
|
|
113
|
+
## 보안
|
|
114
|
+
|
|
115
|
+
시크릿(AWS 키, GitHub/Slack 토큰, PEM 개인키, JWT, `password=` 등)은 인덱싱 시 자동 마스킹됩니다(기본 ON).
|
|
116
|
+
기기 밖으로 아무것도 나가지 않습니다.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
fridai index --source code --no-redact # 마스킹 끄기
|
|
120
|
+
echo "*.env" >> .fridaiignore # 경로 제외(레포 루트 또는 ~/.fridai/)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
고엔트로피 휴리스틱은 긴 식별자 오탐이 많아 **기본 OFF**입니다. `FRIDAI_REDACT_ENTROPY=1`로 켭니다.
|
|
124
|
+
|
|
125
|
+
## 환경변수
|
|
126
|
+
|
|
127
|
+
| 변수 | 기본값 | 설명 |
|
|
128
|
+
| :--- | :--- | :--- |
|
|
129
|
+
| `FRIDAI_HOME` | `~/.fridai` | 데이터 홈(인덱스 DB 등). |
|
|
130
|
+
| `FRIDAI_CLAUDE_PROJECTS` | `~/.claude/projects` | Claude Code transcript 위치. |
|
|
131
|
+
| `FRIDAI_CODEX_SESSIONS` | `~/.codex/sessions` | Codex CLI 세션 위치. |
|
|
132
|
+
| `FRIDAI_GEMINI_SESSIONS` | `~/.gemini/tmp` | Gemini CLI 세션 위치. |
|
|
133
|
+
| `FRIDAI_EMBED_BACKEND` | 자동 | `none`이면 임베딩 끔(어휘만). |
|
|
134
|
+
| `FRIDAI_FASTEMBED_MODEL` | `nomic-ai/nomic-embed-text-v1.5` | fastembed 모델명. |
|
|
135
|
+
| `FRIDAI_REDACT_ENTROPY` | off | `1`이면 고엔트로피 시크릿 휴리스틱 활성. |
|
|
136
|
+
| `FRIDAI_WORK_PENALTY` | `8` | 순수 질문 턴 강등 정도. `0`이면 끔. |
|
|
137
|
+
| `FRIDAI_COMMIT_WINDOW_MIN` | `180` | 질문↔결과 커밋 매칭 시간창(분). |
|
|
138
|
+
|
|
139
|
+
**임베더 일치:** 인덱싱과 쿼리는 같은 임베더로. 모델을 섞으면 차원이 같아도 벡터가 호환되지 않아
|
|
140
|
+
어휘 검색으로 폴백합니다. 모델을 바꿨으면 `--reindex`.
|
|
141
|
+
|
|
142
|
+
## 개발
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
PYTHONPATH=src python3 -m unittest discover -s tests
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
CI(GitHub Actions)가 push/PR마다 Python 3.10–3.14에서 테스트 + fastembed 실동작 스모크를 돌립니다.
|
|
149
|
+
테스트는 격리돼 있어(`tests/__init__.py`가 모든 `FRIDAI_*` 경로를 임시로 두고 임베더를 끔) 실제
|
|
150
|
+
`~/.fridai`·`~/.codex` 등을 건드리지 않고 모델도 받지 않습니다.
|
|
151
|
+
|
|
152
|
+
설계·구축 순서 근거는 [`docs/build-order.md`](docs/build-order.md) 참고(영문).
|
|
153
|
+
|
|
154
|
+
## 라이선스
|
|
155
|
+
|
|
156
|
+
MIT.
|
fridai-0.1.0/README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# fridai 🛠️
|
|
2
|
+
|
|
3
|
+
*English | [한국어](README.ko.md)*
|
|
4
|
+
|
|
5
|
+
A lightweight **MCP server** that lets coding agents (Claude Code, etc.) recall your past
|
|
6
|
+
**code, commits, and AI conversations** via the `recall` tool — **100% local**.
|
|
7
|
+
Search & recall only — **no local LLM required.**
|
|
8
|
+
|
|
9
|
+
- **Search-only (read-only).** The calling agent (an LLM) does the reasoning; fridai
|
|
10
|
+
just returns evidence with sources.
|
|
11
|
+
- **Local embeddings (fastembed, onnx).** No Ollama or external API. Semantic search works
|
|
12
|
+
out of the box (falls back to lexical if fastembed isn't installed).
|
|
13
|
+
- **Multi-agent history.** Auto-indexes Claude Code · OpenAI Codex CLI · Gemini CLI conversations.
|
|
14
|
+
- **Private by design.** Your memory never leaves the machine; secrets are auto-masked at index time.
|
|
15
|
+
|
|
16
|
+
**Status:** early development. **Requires** Python 3.10+ and `git` (for code/commit indexing).
|
|
17
|
+
|
|
18
|
+
## How it works
|
|
19
|
+
|
|
20
|
+
1. **Index** (`fridai index`) builds a local database from three source types:
|
|
21
|
+
- **AI conversations** — parses each agent's session logs into question→answer *turns*, and
|
|
22
|
+
matches a question to its **resulting git commit** (time window ∩ touched files).
|
|
23
|
+
- **Code** — chunks git-tracked files by function/class (line-window fallback), with line ranges.
|
|
24
|
+
- **Commits** — indexes git commit history (subject + changed files).
|
|
25
|
+
2. Everything is stored in **sqlite + FTS5** (lexical) plus **float32 vectors** at `~/.fridai/index.db`.
|
|
26
|
+
3. **Recall** fuses lexical (BM25) and vector (cosine) results via **RRF**, then reranks so real work
|
|
27
|
+
artifacts (code/commits/edited turns) outrank bare question turns, and dedupes repeated questions.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/chloeeekim/fridai.git
|
|
33
|
+
cd fridai
|
|
34
|
+
pipx install . # isolated (recommended). Or: pip install -e . in a venv
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Pulls `numpy` + `fastembed` (onnx) + `mcp`. Registers the `fridai` command.
|
|
38
|
+
|
|
39
|
+
## Quickstart
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
fridai index --source all # build the index (current repo + all agent conversations)
|
|
43
|
+
fridai stats # index overview
|
|
44
|
+
claude mcp add fridai -- fridai mcp # register with Claude Code
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
After registering, the agent recalls via the `recall` tool. Re-run `fridai index` anytime to
|
|
48
|
+
refresh — it's **incremental** (only changed files/sessions/new commits are reprocessed), so it's cheap.
|
|
49
|
+
|
|
50
|
+
## CLI reference
|
|
51
|
+
|
|
52
|
+
| Command | Description |
|
|
53
|
+
| :--- | :--- |
|
|
54
|
+
| `fridai index` | Build/update the index. |
|
|
55
|
+
| `fridai mcp` | Run the stdio MCP server. |
|
|
56
|
+
| `fridai stats` | Print document counts by source. |
|
|
57
|
+
|
|
58
|
+
`index` flags:
|
|
59
|
+
|
|
60
|
+
| Flag | Meaning |
|
|
61
|
+
| :--- | :--- |
|
|
62
|
+
| `--source agent\|code\|commits\|all` | What to index (default `all`). `agent` = all AI conversations. |
|
|
63
|
+
| `--path DIR` | Target repo for code/commits (default: current directory). |
|
|
64
|
+
| `--reindex` | Ignore incremental state and rebuild everything. |
|
|
65
|
+
| `--no-embed` | Skip embeddings (lexical index only). |
|
|
66
|
+
| `--no-prune` | Keep chunks of files deleted from git (code). |
|
|
67
|
+
| `--no-redact` | Turn off secret masking (on by default). |
|
|
68
|
+
|
|
69
|
+
## The `recall` tool (MCP)
|
|
70
|
+
|
|
71
|
+
The server exposes one tool, `recall(query, k=5, repo="", source_type="")`:
|
|
72
|
+
|
|
73
|
+
- `query` — search text (natural language and/or code identifiers).
|
|
74
|
+
- `k` — max results (default 5).
|
|
75
|
+
- `repo` — empty = current working repo (server detects cwd); `"all"` = every repo; `"<name>"` = a specific repo.
|
|
76
|
+
- `source_type` — empty = all; one of `agent_turn` · `code` · `commit` · `note`.
|
|
77
|
+
|
|
78
|
+
It returns text with numbered, cited hits for the agent to read — for example:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
fridai recall — 2 memory item(s) for "docker mount" (all repos, with sources):
|
|
82
|
+
|
|
83
|
+
### [1] myrepo 2026-07-01 [codex] session:how did I add the docker mount?
|
|
84
|
+
Q: how did I add the docker mount?
|
|
85
|
+
A: added a bind mount via volumes.
|
|
86
|
+
|
|
87
|
+
### [2] myrepo/docker-compose.yml:1-20
|
|
88
|
+
volumes: ...
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Non-Claude sources are tagged (`🤖 codex` / `🤖 gemini` in the CLI, `[codex]`/`[gemini]` in citations).
|
|
92
|
+
|
|
93
|
+
## Registering with other MCP clients
|
|
94
|
+
|
|
95
|
+
fridai is a standard **stdio MCP server** — the launch command is `fridai mcp`. Any MCP-capable
|
|
96
|
+
client can use it. For clients that read an `mcpServers` config:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"mcpServers": {
|
|
101
|
+
"fridai": { "command": "fridai", "args": ["mcp"] }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Indexed agent sources
|
|
107
|
+
|
|
108
|
+
| Agent | Default data path | Override env var |
|
|
109
|
+
| :--- | :--- | :--- |
|
|
110
|
+
| Claude Code | `~/.claude/projects/` | `FRIDAI_CLAUDE_PROJECTS` |
|
|
111
|
+
| OpenAI Codex CLI | `~/.codex/sessions/` | `FRIDAI_CODEX_SESSIONS` |
|
|
112
|
+
| Gemini CLI | `~/.gemini/tmp/` | `FRIDAI_GEMINI_SESSIONS` |
|
|
113
|
+
|
|
114
|
+
A missing agent directory is silently skipped.
|
|
115
|
+
|
|
116
|
+
## Security
|
|
117
|
+
|
|
118
|
+
Secrets (AWS keys, GitHub/Slack tokens, PEM private keys, JWTs, `password=`…) are auto-masked
|
|
119
|
+
at index time (on by default). Nothing is sent off the machine.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
fridai index --source code --no-redact # disable masking
|
|
123
|
+
echo "*.env" >> .fridaiignore # exclude paths (repo root or ~/.fridai/)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The high-entropy heuristic is **off by default** (too many false positives on long identifiers);
|
|
127
|
+
enable it with `FRIDAI_REDACT_ENTROPY=1`.
|
|
128
|
+
|
|
129
|
+
## Environment variables
|
|
130
|
+
|
|
131
|
+
| Variable | Default | Description |
|
|
132
|
+
| :--- | :--- | :--- |
|
|
133
|
+
| `FRIDAI_HOME` | `~/.fridai` | Data home (index DB, etc.). |
|
|
134
|
+
| `FRIDAI_CLAUDE_PROJECTS` | `~/.claude/projects` | Claude Code transcript location. |
|
|
135
|
+
| `FRIDAI_CODEX_SESSIONS` | `~/.codex/sessions` | Codex CLI session location. |
|
|
136
|
+
| `FRIDAI_GEMINI_SESSIONS` | `~/.gemini/tmp` | Gemini CLI session location. |
|
|
137
|
+
| `FRIDAI_EMBED_BACKEND` | auto | `none` disables embeddings (lexical only). |
|
|
138
|
+
| `FRIDAI_FASTEMBED_MODEL` | `nomic-ai/nomic-embed-text-v1.5` | fastembed model name. |
|
|
139
|
+
| `FRIDAI_REDACT_ENTROPY` | off | `1` enables the high-entropy secret heuristic. |
|
|
140
|
+
| `FRIDAI_WORK_PENALTY` | `8` | How far to demote pure question turns in ranking. `0` disables. |
|
|
141
|
+
| `FRIDAI_COMMIT_WINDOW_MIN` | `180` | Minutes window for matching a question to its resulting commit. |
|
|
142
|
+
|
|
143
|
+
**Embedder consistency:** index and query with the same embedder. Mixing models makes vectors
|
|
144
|
+
incomparable even at the same dimension — the store then falls back to lexical search. Reindex
|
|
145
|
+
(`--reindex`) after switching models.
|
|
146
|
+
|
|
147
|
+
## Development
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
PYTHONPATH=src python3 -m unittest discover -s tests
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
CI (GitHub Actions) runs the suite on Python 3.10–3.14 plus a fastembed smoke check on every push/PR.
|
|
154
|
+
Tests are hermetic — `tests/__init__.py` isolates all `FRIDAI_*` paths and disables the embedder,
|
|
155
|
+
so no real `~/.fridai`/`~/.codex`/etc. is touched and no model is downloaded.
|
|
156
|
+
|
|
157
|
+
See [`docs/build-order.md`](docs/build-order.md) for the design & build-order rationale.
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT.
|