@purpleraven/hits 0.2.1 → 0.2.3
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.
- package/README.md +271 -222
- package/bin/hits-mcp.js +133 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,116 +1,91 @@
|
|
|
1
|
-
#
|
|
1
|
+
# hits
|
|
2
2
|
|
|
3
3
|
> Replicate your predecessor's brain as perfectly as possible, using the least amount of AI.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A secure web-based knowledge management system that preserves organizational context across AI tool sessions. When your Claude session hits the token limit and you switch to a new one — HITS ensures nothing is lost.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## What Problem Does This Solve?
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
You're working on a project with Claude Code. After a long session, you hit the token limit. A new session starts — but it has **no idea** what you did, what decisions were made, or what was left unfinished.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- **Context Preservation**: Store decision-making processes in a Why-How-What hierarchy
|
|
13
|
-
- **Failure Experience**: Record failed approaches alongside successes as Negative Paths
|
|
14
|
-
- **Security Hardened**: Argon2id hashing, JWT HttpOnly cookies, CSP, Rate Limiting
|
|
15
|
-
- **AI Session Handover**: Automatically transfer project context when AI sessions rotate due to token limits
|
|
16
|
-
- **Centralized Storage**: All AI tool work logs are consolidated at `~/.hits/data/`
|
|
17
|
-
- **Project Isolation**: Completely independent context management based on project path
|
|
11
|
+
**HITS fixes this:**
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
1. **Record work** during each AI session (manually or via MCP tools)
|
|
14
|
+
2. **Query handover** when a new session starts — it gets the full context
|
|
15
|
+
3. **Knowledge trees** preserve the WHY/HOW/WHAT of every project
|
|
16
|
+
4. **All AI tools share the same data** — Claude, OpenCode, Cursor, it doesn't matter
|
|
20
17
|
|
|
21
|
-
| Area | Technology |
|
|
22
|
-
|------|-----------|
|
|
23
|
-
| **Backend** | Python 3.10+, FastAPI, Pydantic v2 |
|
|
24
|
-
| **Frontend** | Svelte 5, Vite, TypeScript |
|
|
25
|
-
| **Authentication** | Argon2id (passwords), JWT HS256 (HttpOnly cookies) |
|
|
26
|
-
| **Storage** | File-based (`~/.hits/data/`), Redis (optional) |
|
|
27
|
-
| **Security** | CSP, CORS, Rate Limiting, Secure Headers |
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
### Requirements
|
|
32
|
-
|
|
33
|
-
- Python 3.10 or later
|
|
34
|
-
- Node.js 18+ (for frontend build)
|
|
35
|
-
- Redis (optional — falls back to file storage)
|
|
36
|
-
|
|
37
|
-
### Quick Start
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
cd hits
|
|
41
|
-
./run.sh # Auto-install + start server
|
|
42
18
|
```
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
19
|
+
[OpenCode session ends] [Claude session starts]
|
|
20
|
+
│ │
|
|
21
|
+
Record work: Query handover:
|
|
22
|
+
"Added JWT auth, → Previous: Added JWT auth
|
|
23
|
+
chose Argon2id over → Decisions: Argon2id > bcrypt
|
|
24
|
+
bcrypt, still need to → Pending: rate limiting
|
|
25
|
+
add rate limiting" → Files: auth/manager.py, ...
|
|
48
26
|
```
|
|
49
27
|
|
|
50
|
-
|
|
28
|
+
## Quick Start
|
|
51
29
|
|
|
52
|
-
|
|
53
|
-
# Python environment
|
|
54
|
-
python3 -m venv venv
|
|
55
|
-
source venv/bin/activate
|
|
56
|
-
pip install -r requirements.txt
|
|
30
|
+
### One Command — That's It
|
|
57
31
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
npm install
|
|
61
|
-
npm run build
|
|
62
|
-
cd ..
|
|
63
|
-
|
|
64
|
-
# Start server
|
|
65
|
-
python -m hits_core.main --port 8765
|
|
32
|
+
```bash
|
|
33
|
+
npx hits
|
|
66
34
|
```
|
|
67
35
|
|
|
68
|
-
|
|
36
|
+
That single command will:
|
|
69
37
|
|
|
70
|
-
|
|
38
|
+
1. **Detect Python 3.10+** on your system
|
|
39
|
+
2. **Create a virtual environment** automatically
|
|
40
|
+
3. **Install Python dependencies** (FastAPI, Argon2id, etc.)
|
|
41
|
+
4. **Start the Python backend** (FastAPI on port 8765)
|
|
42
|
+
5. **Start the web server** (Express on port 8765)
|
|
43
|
+
6. Open **http://127.0.0.1:8765** in your browser
|
|
71
44
|
|
|
72
|
-
|
|
73
|
-
|---------|---------------|
|
|
74
|
-
| **Password Hashing** | Argon2id (memory=64MB, iterations=3, parallelism=1) |
|
|
75
|
-
| **Minimum Password Length** | 8 characters |
|
|
76
|
-
| **JWT Tokens** | HttpOnly + Secure + SameSite=Lax cookies |
|
|
77
|
-
| **Access Token** | 15-minute expiry |
|
|
78
|
-
| **Refresh Token** | 7-day expiry, sent only to `/api/auth/refresh` |
|
|
79
|
-
| **First User** | Automatically assigned admin role |
|
|
80
|
-
| **Subsequent Users** | Can only be created by admin |
|
|
45
|
+
### First Time Setup
|
|
81
46
|
|
|
82
|
-
|
|
47
|
+
On first visit, you'll create an admin account:
|
|
83
48
|
|
|
84
49
|
```
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
50
|
+
┌──────────────────────────────────────┐
|
|
51
|
+
│ 🌳 HITS │
|
|
52
|
+
│ Hybrid Intel Trace System │
|
|
53
|
+
│ │
|
|
54
|
+
│ ┌────────────────────────────────┐ │
|
|
55
|
+
│ │ Username: [____________] │ │
|
|
56
|
+
│ │ Password: [____________] │ │
|
|
57
|
+
│ │ │ │
|
|
58
|
+
│ │ [ Create Account ] │ │
|
|
59
|
+
│ │ │ │
|
|
60
|
+
│ │ First account = admin role │ │
|
|
61
|
+
│ └────────────────────────────────┘ │
|
|
62
|
+
└──────────────────────────────────────┘
|
|
91
63
|
```
|
|
92
64
|
|
|
93
|
-
###
|
|
65
|
+
### Custom Port
|
|
94
66
|
|
|
95
|
-
|
|
96
|
-
|
|
67
|
+
```bash
|
|
68
|
+
npx hits --port 9000
|
|
69
|
+
# or
|
|
70
|
+
HITS_PORT=9000 npx hits
|
|
71
|
+
```
|
|
97
72
|
|
|
98
|
-
|
|
73
|
+
## Requirements
|
|
99
74
|
|
|
100
|
-
|
|
|
101
|
-
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
| `~/.hits/.jwt_secret` | 600 | JWT signing key (owner only) |
|
|
105
|
-
| `~/.hits/.auth/` | 700 | Auth directory (owner only) |
|
|
75
|
+
| Requirement | Version | Why |
|
|
76
|
+
|-------------|---------|-----|
|
|
77
|
+
| **Node.js** | ≥ 18 | Runs the web server and manages the Python process |
|
|
78
|
+
| **Python** | ≥ 3.10 | Runs the FastAPI backend (auto-installed into venv) |
|
|
106
79
|
|
|
107
|
-
|
|
80
|
+
That's it. No database required — HITS uses file-based storage at `~/.hits/data/`.
|
|
108
81
|
|
|
109
|
-
|
|
82
|
+
## What You Get
|
|
83
|
+
|
|
84
|
+
### Web UI
|
|
110
85
|
|
|
111
86
|
```
|
|
112
87
|
┌─────────────┬───────────────────────────────────┐
|
|
113
|
-
│ Sidebar │ Header (tabs + user menu)
|
|
88
|
+
│ Sidebar │ Header (tabs + user menu 🌐 lang) │
|
|
114
89
|
│ ├───────────────────────────────────┤
|
|
115
90
|
│ 📂 Projects│ │
|
|
116
91
|
│ ────────── │ Main content area │
|
|
@@ -121,64 +96,193 @@ Permissions-Policy: camera=(), microphone=(), geolocation=()
|
|
|
121
96
|
└─────────────┴───────────────────────────────────┘
|
|
122
97
|
```
|
|
123
98
|
|
|
124
|
-
|
|
99
|
+
**Knowledge Tree** — Organize project knowledge as Why-How-What nodes:
|
|
125
100
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
101
|
+
```
|
|
102
|
+
📁 Authentication
|
|
103
|
+
├── WHY "Need secure user auth for web UI"
|
|
104
|
+
├── HOW "Argon2id hashing + JWT HttpOnly cookies"
|
|
105
|
+
└── WHAT "POST /api/auth/login → Set-Cookie"
|
|
106
|
+
└── ❌ Negative Path: "Tried bcrypt first — too fast, GPU-vulnerable"
|
|
107
|
+
```
|
|
131
108
|
|
|
132
|
-
|
|
109
|
+
**Timeline** — Chronological work log, grouped by date, filterable by project
|
|
133
110
|
|
|
134
|
-
|
|
111
|
+
**Handover** — Auto-generated summary of a project's context, ready to paste into a new AI session
|
|
135
112
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
113
|
+
**i18n** — Korean/English toggle (🌐 button in header)
|
|
114
|
+
|
|
115
|
+
### MCP Tools for AI Assistants
|
|
116
|
+
|
|
117
|
+
HITS includes an MCP server so your AI can read and write handover data directly. No need to clone the repo — it works right out of the npm package.
|
|
118
|
+
|
|
119
|
+
#### Register with OpenCode (`~/.config/opencode/opencode.json`)
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"mcp": {
|
|
124
|
+
"hits": {
|
|
125
|
+
"type": "local",
|
|
126
|
+
"command": ["npx", "hits-mcp"]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
149
130
|
```
|
|
150
131
|
|
|
151
|
-
|
|
132
|
+
#### Register with Claude Code
|
|
152
133
|
|
|
153
|
-
|
|
134
|
+
```bash
|
|
135
|
+
claude mcp add hits -- npx hits-mcp
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### Register with Any MCP Client
|
|
154
139
|
|
|
155
140
|
```json
|
|
156
141
|
{
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
|
|
160
|
-
|
|
142
|
+
"mcpServers": {
|
|
143
|
+
"hits": {
|
|
144
|
+
"command": "npx",
|
|
145
|
+
"args": ["hits-mcp"]
|
|
146
|
+
}
|
|
161
147
|
}
|
|
162
148
|
}
|
|
163
149
|
```
|
|
164
150
|
|
|
165
|
-
MCP
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
151
|
+
> **How it works:** `npx hits-mcp` auto-detects Python, creates a venv inside the npm package, installs dependencies, and spawns the MCP server over stdio — all automatically on first run.
|
|
152
|
+
|
|
153
|
+
#### 5 MCP Tools
|
|
154
|
+
|
|
155
|
+
| Tool | What It Does |
|
|
156
|
+
|------|-------------|
|
|
157
|
+
| `hits_record_work` | Record a work entry (auto-detects project path from CWD) |
|
|
158
|
+
| `hits_get_handover` | Get handover summary for the current project |
|
|
159
|
+
| `hits_search_works` | Search past work by keyword |
|
|
160
|
+
| `hits_list_projects` | List all projects with recorded work |
|
|
161
|
+
| `hits_get_recent` | Get the most recent work entries |
|
|
162
|
+
|
|
163
|
+
#### Example AI Workflow
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
User: "Continue working on the auth system"
|
|
167
|
+
|
|
168
|
+
AI (auto-calls hits_get_handover):
|
|
169
|
+
→ Previous session added Argon2id password hashing
|
|
170
|
+
→ Decisions: Argon2id (not bcrypt), JWT HS256, HttpOnly cookies
|
|
171
|
+
→ Pending: Rate limiting, password change endpoint
|
|
172
|
+
|
|
173
|
+
AI: "I see the auth system uses Argon2id + JWT. Let me add rate limiting..."
|
|
174
|
+
|
|
175
|
+
(later)
|
|
176
|
+
|
|
177
|
+
AI (auto-calls hits_record_work):
|
|
178
|
+
→ Recorded: "Added rate limiting (10 req/min on login endpoint)"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### REST API
|
|
182
|
+
|
|
183
|
+
All features are also accessible via HTTP API:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Health check
|
|
187
|
+
curl http://localhost:8765/api/health
|
|
188
|
+
|
|
189
|
+
# Record work
|
|
190
|
+
curl -X POST http://localhost:8765/api/work-log \
|
|
191
|
+
-H "Content-Type: application/json" \
|
|
192
|
+
-b cookies.txt \
|
|
193
|
+
-d '{
|
|
194
|
+
"performed_by": "claude",
|
|
195
|
+
"request_text": "Added rate limiting to login endpoint",
|
|
196
|
+
"context": "10 req/min per IP, 429 response on limit",
|
|
197
|
+
"project_path": "/home/user/my-project",
|
|
198
|
+
"tags": ["security", "api"]
|
|
199
|
+
}'
|
|
200
|
+
|
|
201
|
+
# Get handover summary
|
|
202
|
+
curl "http://localhost:8765/api/handover?project_path=/home/user/my-project" \
|
|
203
|
+
-b cookies.txt
|
|
204
|
+
|
|
205
|
+
# Search past work
|
|
206
|
+
curl "http://localhost:8765/api/work-logs/search?q=auth" \
|
|
207
|
+
-b cookies.txt
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Security
|
|
211
|
+
|
|
212
|
+
HITS is built with security as a first-class concern:
|
|
213
|
+
|
|
214
|
+
| Feature | Implementation |
|
|
215
|
+
|---------|---------------|
|
|
216
|
+
| **Password Hashing** | Argon2id (64MB memory, 3 iterations, parallelism=1) |
|
|
217
|
+
| **JWT Tokens** | HttpOnly + Secure + SameSite=Lax cookies |
|
|
218
|
+
| **Access Token** | 15-minute expiry |
|
|
219
|
+
| **Refresh Token** | 7-day expiry, restricted to `/api/auth/refresh` path |
|
|
220
|
+
| **Brute Force Protection** | 10 login attempts/minute per IP |
|
|
221
|
+
| **Security Headers** | CSP, X-Frame-Options: DENY, HSTS preload, nosniff |
|
|
222
|
+
| **Data Protection** | Auth files stored with `chmod 600` (owner-only) |
|
|
223
|
+
| **First User Policy** | First registered user becomes admin; subsequent users need admin approval |
|
|
224
|
+
|
|
225
|
+
## How It Works Under the Hood
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
npx hits
|
|
229
|
+
│
|
|
230
|
+
├── 1. findPython() → Detect Python 3.10+ on system
|
|
231
|
+
├── 2. setupPython() → Create venv, install deps
|
|
232
|
+
├── 3. startBackend() → Spawn FastAPI process (port 8765)
|
|
233
|
+
└── 4. startExpress() → Serve frontend + proxy /api → FastAPI
|
|
234
|
+
|
|
235
|
+
Browser Express (8765) FastAPI (8765 internal)
|
|
236
|
+
│ │ │
|
|
237
|
+
├── GET / ───→ static (Svelte SPA) │
|
|
238
|
+
├── GET /some/route ───→ SPA fallback │
|
|
239
|
+
└── GET /api/* ───→ proxy ──────────────→ FastAPI routes
|
|
240
|
+
POST /api/* ───→ proxy ──────────────→ FastAPI routes
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
All data is stored centrally:
|
|
171
244
|
|
|
172
|
-
|
|
245
|
+
```
|
|
246
|
+
~/.hits/
|
|
247
|
+
├── data/ ← All project data
|
|
248
|
+
│ ├── work_logs/ ← AI session work logs (JSON)
|
|
249
|
+
│ ├── trees/ ← Knowledge trees
|
|
250
|
+
│ └── workflows/ ← Workflows
|
|
251
|
+
├── .auth/ ← User accounts (chmod 700)
|
|
252
|
+
│ └── users.json ← User data (chmod 600)
|
|
253
|
+
├── .pepper ← HMAC pepper (chmod 600)
|
|
254
|
+
└── .jwt_secret ← JWT signing key (chmod 600)
|
|
255
|
+
|
|
256
|
+
Override with HITS_DATA_PATH environment variable
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## CLI Options
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
npx hits [options]
|
|
263
|
+
|
|
264
|
+
Options:
|
|
265
|
+
-p, --port <port> Server port (default: 8765)
|
|
266
|
+
-d, --dev Development mode (verbose logging)
|
|
267
|
+
-s, --setup Install dependencies only, don't start
|
|
268
|
+
-h, --help Show help
|
|
269
|
+
|
|
270
|
+
Environment:
|
|
271
|
+
HITS_PORT Server port override
|
|
272
|
+
HITS_PYTHON Path to python executable (default: auto-detect)
|
|
273
|
+
HITS_DATA_PATH Data storage path (default: ~/.hits/data)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## API Reference
|
|
173
277
|
|
|
174
278
|
### Authentication
|
|
175
279
|
|
|
176
280
|
| Method | Path | Description |
|
|
177
281
|
|--------|------|-------------|
|
|
178
|
-
| GET | `/api/auth/status` | Check auth status |
|
|
179
|
-
| POST | `/api/auth/register` | Register user |
|
|
180
|
-
| POST | `/api/auth/login` | Login
|
|
181
|
-
| POST | `/api/auth/logout` | Logout |
|
|
282
|
+
| GET | `/api/auth/status` | Check if auth is initialized, current login status |
|
|
283
|
+
| POST | `/api/auth/register` | Register user (first user = admin) |
|
|
284
|
+
| POST | `/api/auth/login` | Login — sets HttpOnly cookies |
|
|
285
|
+
| POST | `/api/auth/logout` | Logout — clears cookies |
|
|
182
286
|
| POST | `/api/auth/refresh` | Refresh access token |
|
|
183
287
|
| GET | `/api/auth/me` | Get current user info |
|
|
184
288
|
| PUT | `/api/auth/password` | Change password |
|
|
@@ -188,8 +292,8 @@ MCP Tools:
|
|
|
188
292
|
| Method | Path | Description |
|
|
189
293
|
|--------|------|-------------|
|
|
190
294
|
| POST | `/api/work-log` | Create work log |
|
|
191
|
-
| GET | `/api/work-logs` | List
|
|
192
|
-
| GET | `/api/work-logs/search?q=...` | Search
|
|
295
|
+
| GET | `/api/work-logs` | List logs (filter by `project_path`) |
|
|
296
|
+
| GET | `/api/work-logs/search?q=...` | Search logs by keyword |
|
|
193
297
|
| GET | `/api/work-log/{id}` | Get single entry |
|
|
194
298
|
| PUT | `/api/work-log/{id}` | Update entry |
|
|
195
299
|
| DELETE | `/api/work-log/{id}` | Delete entry |
|
|
@@ -199,10 +303,10 @@ MCP Tools:
|
|
|
199
303
|
| Method | Path | Description |
|
|
200
304
|
|--------|------|-------------|
|
|
201
305
|
| GET | `/api/handover?project_path=...` | Get project handover summary |
|
|
202
|
-
| GET | `/api/handover/projects` | List projects |
|
|
203
|
-
| GET | `/api/handover/project-stats?project_path=...` | Get project
|
|
306
|
+
| GET | `/api/handover/projects` | List all projects |
|
|
307
|
+
| GET | `/api/handover/project-stats?project_path=...` | Get project statistics |
|
|
204
308
|
|
|
205
|
-
### Knowledge
|
|
309
|
+
### Knowledge
|
|
206
310
|
|
|
207
311
|
| Method | Path | Description |
|
|
208
312
|
|--------|------|-------------|
|
|
@@ -210,127 +314,72 @@ MCP Tools:
|
|
|
210
314
|
| POST | `/api/knowledge/category` | Create category |
|
|
211
315
|
| PUT | `/api/knowledge/category/{name}` | Update category |
|
|
212
316
|
| DELETE | `/api/knowledge/category/{name}` | Delete category |
|
|
213
|
-
| POST | `/api/knowledge/category/{name}/nodes` | Add node |
|
|
317
|
+
| POST | `/api/knowledge/category/{name}/nodes` | Add node to category |
|
|
214
318
|
| PUT | `/api/knowledge/category/{name}/nodes/{idx}` | Update node |
|
|
215
319
|
| DELETE | `/api/knowledge/category/{name}/nodes/{idx}` | Delete node |
|
|
216
320
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
| AI Tool | Value |
|
|
220
|
-
|---------|-------|
|
|
221
|
-
| OpenCode | `opencode` |
|
|
222
|
-
| Claude Code | `claude` |
|
|
223
|
-
| Cursor | `cursor` |
|
|
224
|
-
| Manual | `manual` |
|
|
225
|
-
|
|
226
|
-
## Architecture
|
|
227
|
-
|
|
228
|
-
```
|
|
229
|
-
┌──────────────────────────────────────────────────────────┐
|
|
230
|
-
│ hits_web (Svelte 5 + Vite) │
|
|
231
|
-
│ Material Dark theme · TypeScript │
|
|
232
|
-
│ ┌──────────┬──────────┬──────────────────────────┐ │
|
|
233
|
-
│ │ Sidebar │ Knowledge│ HandoverPanel │ │
|
|
234
|
-
│ │ Projects │ Tree │ Handover summary view │ │
|
|
235
|
-
│ │ Filter │ Timeline │ │ │
|
|
236
|
-
│ └──────────┴──────────┴──────────────────────────┘ │
|
|
237
|
-
│ ↕ API Client (fetch + HttpOnly cookies) │
|
|
238
|
-
├──────────────────────────────────────────────────────────┤
|
|
239
|
-
│ hits_core (Apache 2.0) │
|
|
240
|
-
│ ┌──────────┬──────────┬──────────┬──────────┐ │
|
|
241
|
-
│ │ Models │ Storage │ AI │ Auth │ │
|
|
242
|
-
│ │ Tree │ Redis │ Compress │ Argon2id │ │
|
|
243
|
-
│ │ Node │ File │ SLM/LLM │ JWT │ │
|
|
244
|
-
│ │ WorkLog │(~/.hits) │ Filter │ Middleware│ │
|
|
245
|
-
│ └──────────┴──────────┴──────────┴──────────┘ │
|
|
246
|
-
│ ┌──────────┬──────────┬──────────┐ │
|
|
247
|
-
│ │ API │ Collector│ MCP │ │
|
|
248
|
-
│ │ FastAPI │ Git/Shell│ Server │ │
|
|
249
|
-
│ │ + Static │ AI Sess. │ 5 Tools │ │
|
|
250
|
-
│ │ Serve │ │ │ │
|
|
251
|
-
│ └──────────┴──────────┴──────────┘ │
|
|
252
|
-
│ ┌──────────────────────────────┐ │
|
|
253
|
-
│ │ Service Layer │ │
|
|
254
|
-
│ │ TreeService HandoverService│ │
|
|
255
|
-
│ │ KnowledgeService │ │
|
|
256
|
-
│ └──────────────────────────────┘ │
|
|
257
|
-
└──────────────────────────────────────────────────────────┘
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
## Knowledge Tree Structure
|
|
261
|
-
|
|
262
|
-
### Why-How-What Hierarchy
|
|
321
|
+
## Troubleshooting
|
|
263
322
|
|
|
264
|
-
|
|
265
|
-
├── WHY (Intent/Purpose)
|
|
266
|
-
│ ├── "Why was this system built?"
|
|
267
|
-
│ └── "What is the business goal?"
|
|
268
|
-
│
|
|
269
|
-
├── HOW (Logic/Method)
|
|
270
|
-
│ ├── "How was it implemented?"
|
|
271
|
-
│ └── "What decisions were made?"
|
|
272
|
-
│
|
|
273
|
-
└── WHAT (Execution/Tasks)
|
|
274
|
-
├── "What specifically does it do?"
|
|
275
|
-
└── "Actionable tasks"
|
|
276
|
-
```
|
|
323
|
+
### "Python 3.10+ not found"
|
|
277
324
|
|
|
278
|
-
|
|
325
|
+
Install Python 3.10 or later:
|
|
326
|
+
```bash
|
|
327
|
+
# Ubuntu/Debian
|
|
328
|
+
sudo apt install python3.12
|
|
279
329
|
|
|
280
|
-
|
|
330
|
+
# macOS
|
|
331
|
+
brew install python@3.12
|
|
281
332
|
|
|
282
|
-
|
|
283
|
-
|
|
333
|
+
# Or set manually:
|
|
334
|
+
export HITS_PYTHON=/usr/bin/python3.12
|
|
284
335
|
```
|
|
285
336
|
|
|
286
|
-
###
|
|
337
|
+
### "Frontend not built"
|
|
287
338
|
|
|
339
|
+
This shouldn't happen with the npm package (frontend is pre-built). If it does:
|
|
288
340
|
```bash
|
|
289
|
-
|
|
341
|
+
npx hits --setup
|
|
290
342
|
```
|
|
291
343
|
|
|
292
|
-
###
|
|
344
|
+
### "ModuleNotFoundError: No module named 'hits_core'"
|
|
293
345
|
|
|
346
|
+
Python dependencies failed to install. Try:
|
|
294
347
|
```bash
|
|
295
|
-
|
|
296
|
-
npm install # Install dependencies
|
|
297
|
-
npm run dev # Vite dev server (http://localhost:5173)
|
|
298
|
-
npm run build # Production build
|
|
348
|
+
npx hits --setup
|
|
299
349
|
```
|
|
300
350
|
|
|
301
|
-
|
|
351
|
+
### Redis Connection Failed
|
|
302
352
|
|
|
303
|
-
|
|
304
|
-
|---------|---------|---------------|
|
|
305
|
-
| `hits_core` | Apache 2.0 | ✅ Free |
|
|
306
|
-
| `hits_web` | Apache 2.0 | ✅ Free |
|
|
353
|
+
Not a problem — HITS automatically uses file-based storage. Redis is optional.
|
|
307
354
|
|
|
308
|
-
##
|
|
355
|
+
## Development
|
|
309
356
|
|
|
310
|
-
|
|
357
|
+
If you're working on HITS itself:
|
|
311
358
|
|
|
312
359
|
```bash
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
sudo apt install -y nodejs
|
|
316
|
-
```
|
|
360
|
+
git clone https://github.com/lhjnano/hits.git
|
|
361
|
+
cd hits
|
|
317
362
|
|
|
318
|
-
|
|
363
|
+
# Backend setup
|
|
364
|
+
python3 -m venv venv
|
|
365
|
+
source venv/bin/activate
|
|
366
|
+
pip install -r requirements.txt
|
|
319
367
|
|
|
320
|
-
|
|
368
|
+
# Frontend build
|
|
369
|
+
cd hits_web && npm install && npm run build && cd ..
|
|
321
370
|
|
|
322
|
-
|
|
371
|
+
# Development mode (Vite HMR + FastAPI)
|
|
372
|
+
./run.sh --dev
|
|
323
373
|
|
|
374
|
+
# Run tests
|
|
375
|
+
./run.sh --test
|
|
324
376
|
```
|
|
325
|
-
~/.hits/
|
|
326
|
-
├── data/ ← Default location for all data
|
|
327
|
-
│ ├── work_logs/ ← AI session work logs
|
|
328
|
-
│ ├── trees/ ← Knowledge trees
|
|
329
|
-
│ └── workflows/ ← Workflows
|
|
330
|
-
├── .auth/ ← Authentication data
|
|
331
|
-
│ └── users.json ← User info (permissions 600)
|
|
332
|
-
├── .pepper ← HMAC pepper (permissions 600)
|
|
333
|
-
└── .jwt_secret ← JWT signing key (permissions 600)
|
|
334
377
|
|
|
335
|
-
|
|
336
|
-
|
|
378
|
+
## License
|
|
379
|
+
|
|
380
|
+
Apache 2.0 — free for commercial use.
|
|
381
|
+
|
|
382
|
+
## Links
|
|
383
|
+
|
|
384
|
+
- **GitHub**: [https://github.com/lhjnano/hits](https://github.com/lhjnano/hits)
|
|
385
|
+
- **Issues**: [https://github.com/lhjnano/hits/issues](https://github.com/lhjnano/hits/issues)
|
package/bin/hits-mcp.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HITS MCP Server - Node.js Wrapper
|
|
5
|
+
*
|
|
6
|
+
* Launches the HITS Python MCP server over stdio transport.
|
|
7
|
+
* Auto-detects Python, creates venv, installs deps — same as `npx hits`.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* npx hits-mcp
|
|
11
|
+
*
|
|
12
|
+
* Or in MCP config:
|
|
13
|
+
* { "command": ["npx", "hits-mcp"] }
|
|
14
|
+
*
|
|
15
|
+
* Environment:
|
|
16
|
+
* HITS_PYTHON Path to python executable (default: auto-detect)
|
|
17
|
+
* HITS_DATA_PATH Data storage path (default: ~/.hits/data)
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { spawn, execSync } from 'node:child_process';
|
|
21
|
+
import { existsSync } from 'node:fs';
|
|
22
|
+
import { join, dirname } from 'node:path';
|
|
23
|
+
import { fileURLToPath } from 'node:url';
|
|
24
|
+
import { platform } from 'node:os';
|
|
25
|
+
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const ROOT = __dirname;
|
|
28
|
+
const isWin = platform() === 'win32';
|
|
29
|
+
|
|
30
|
+
// ─── Python Detection (same logic as server.js) ────────────────
|
|
31
|
+
|
|
32
|
+
function findPython() {
|
|
33
|
+
const envPython = process.env.HITS_PYTHON;
|
|
34
|
+
if (envPython && existsSync(envPython)) return envPython;
|
|
35
|
+
|
|
36
|
+
const candidates = isWin
|
|
37
|
+
? ['python', 'python3', 'py']
|
|
38
|
+
: ['python3', 'python'];
|
|
39
|
+
|
|
40
|
+
for (const cmd of candidates) {
|
|
41
|
+
try {
|
|
42
|
+
const ver = execSync(`${cmd} --version`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
43
|
+
const match = ver.match(/Python (\d+)\.(\d+)/);
|
|
44
|
+
if (match && (parseInt(match[1]) > 3 || (parseInt(match[1]) === 3 && parseInt(match[2]) >= 10))) {
|
|
45
|
+
return cmd;
|
|
46
|
+
}
|
|
47
|
+
} catch {}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─── Venv Management ────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
const VENV_DIR = join(ROOT, 'venv');
|
|
55
|
+
const PYTHON_BIN = isWin
|
|
56
|
+
? join(VENV_DIR, 'Scripts', 'python.exe')
|
|
57
|
+
: join(VENV_DIR, 'bin', 'python');
|
|
58
|
+
|
|
59
|
+
function runCommand(cmd, args, opts = {}) {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const proc = spawn(cmd, args, { stdio: 'inherit', ...opts });
|
|
62
|
+
proc.on('close', (code) => {
|
|
63
|
+
if (code === 0) resolve();
|
|
64
|
+
else reject(new Error(`Command failed: ${cmd} ${args.join(' ')} (exit ${code})`));
|
|
65
|
+
});
|
|
66
|
+
proc.on('error', reject);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function ensurePython() {
|
|
71
|
+
const pythonCmd = findPython();
|
|
72
|
+
if (!pythonCmd) {
|
|
73
|
+
console.error('[hits-mcp] Error: Python 3.10+ not found.');
|
|
74
|
+
console.error('[hits-mcp] Install: https://www.python.org/downloads/');
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Create venv if needed
|
|
79
|
+
if (!existsSync(PYTHON_BIN)) {
|
|
80
|
+
console.error(`[hits-mcp] Creating virtual environment... (${pythonCmd})`);
|
|
81
|
+
await runCommand(pythonCmd, ['-m', 'venv', VENV_DIR], { cwd: ROOT });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check if deps are installed
|
|
85
|
+
try {
|
|
86
|
+
execSync(
|
|
87
|
+
`${PYTHON_BIN} -c "import fastapi, pydantic, argon2, jose"`,
|
|
88
|
+
{ stdio: 'ignore' }
|
|
89
|
+
);
|
|
90
|
+
} catch {
|
|
91
|
+
console.error('[hits-mcp] Installing Python dependencies...');
|
|
92
|
+
await runCommand(PYTHON_BIN, ['-m', 'pip', 'install', '-q', '--upgrade', 'pip'], { cwd: ROOT });
|
|
93
|
+
await runCommand(PYTHON_BIN, ['-m', 'pip', 'install', '-q', '-r', join(ROOT, 'requirements.txt')], { cwd: ROOT });
|
|
94
|
+
console.error('[hits-mcp] Dependencies installed.');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ─── Launch MCP Server ──────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
async function main() {
|
|
101
|
+
await ensurePython();
|
|
102
|
+
|
|
103
|
+
// Spawn Python MCP server with stdio transport
|
|
104
|
+
const proc = spawn(PYTHON_BIN, ['-m', 'hits_core.mcp.server'], {
|
|
105
|
+
cwd: ROOT,
|
|
106
|
+
stdio: 'inherit', // stdin/stdout/stderr all connected to parent (MCP stdio)
|
|
107
|
+
env: {
|
|
108
|
+
...process.env,
|
|
109
|
+
PYTHONPATH: ROOT,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
proc.on('error', (err) => {
|
|
114
|
+
console.error(`[hits-mcp] Failed to start: ${err.message}`);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
proc.on('exit', (code, signal) => {
|
|
119
|
+
if (signal) {
|
|
120
|
+
console.error(`[hits-mcp] Terminated by signal: ${signal}`);
|
|
121
|
+
}
|
|
122
|
+
process.exit(code || 0);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Forward signals
|
|
126
|
+
process.on('SIGINT', () => proc.kill('SIGINT'));
|
|
127
|
+
process.on('SIGTERM', () => proc.kill('SIGTERM'));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
main().catch((err) => {
|
|
131
|
+
console.error(`[hits-mcp] Fatal: ${err.message}`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@purpleraven/hits",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "HITS - Hybrid Intel Trace System. AI session handover with secure web UI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"knowledge-management",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"author": "HITS Team",
|
|
13
13
|
"type": "module",
|
|
14
14
|
"bin": {
|
|
15
|
-
"hits": "bin/hits.js"
|
|
15
|
+
"hits": "bin/hits.js",
|
|
16
|
+
"hits-mcp": "bin/hits-mcp.js"
|
|
16
17
|
},
|
|
17
18
|
"scripts": {
|
|
18
19
|
"start": "node bin/hits.js",
|
|
@@ -51,7 +52,7 @@
|
|
|
51
52
|
"devDependencies": {},
|
|
52
53
|
"repository": {
|
|
53
54
|
"type": "git",
|
|
54
|
-
"url": "git+https://
|
|
55
|
+
"url": "git+https://github.com/lhjnano/hits.git"
|
|
55
56
|
},
|
|
56
57
|
"bugs": {
|
|
57
58
|
"url": "https://github.com/lhjnano/hits/issues"
|