kyp-mem 0.2.0 → 0.2.1
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 +18 -14
- package/bin/cli.mjs +53 -18
- package/bin/install.mjs +59 -18
- package/kyp_mem/__init__.py +2 -2
- package/kyp_mem/cli.py +18 -10
- package/kyp_mem/server.py +1 -1
- package/kyp_mem/ui.py +1 -1
- package/package.json +7 -6
- package/pyproject.toml +4 -4
- package/kyp_mem/__pycache__/__init__.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/cli.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/config.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/ui.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/vault.cpython-314.pyc +0 -0
package/README.md
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
# KYP-MEM — Know Your Project Memory
|
|
2
2
|
|
|
3
|
-
**Headless
|
|
3
|
+
**Headless knowledge base for AI agents.** Markdown notes with wikilinks, backlinks, tags, related notes, and a neon web UI — all powered by an MCP server so Claude (or any AI) can read and write your project knowledge directly.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npx -y kyp-mem
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install the command globally:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g kyp-mem
|
|
9
15
|
```
|
|
10
16
|
|
|
11
17
|
## Setup (3 commands)
|
|
12
18
|
|
|
13
19
|
```bash
|
|
14
20
|
# 1. Choose where your vault (knowledge base) lives
|
|
15
|
-
kyp-mem init
|
|
21
|
+
npx -y kyp-mem init
|
|
16
22
|
|
|
17
23
|
# 2. Connect to Claude Code — auto-configures MCP
|
|
18
|
-
kyp-mem setup-claude
|
|
24
|
+
npx -y kyp-mem setup-claude
|
|
19
25
|
|
|
20
26
|
# 3. Restart Claude Code — done!
|
|
21
27
|
# kyp-mem now runs headlessly every session.
|
|
@@ -27,10 +33,10 @@ That's it. Claude now has `kyp_read`, `kyp_write`, `kyp_search`, and 7 other too
|
|
|
27
33
|
## Optional: Web UI
|
|
28
34
|
|
|
29
35
|
```bash
|
|
30
|
-
kyp-mem ui
|
|
36
|
+
npx -y kyp-mem ui
|
|
31
37
|
```
|
|
32
38
|
|
|
33
|
-
Opens
|
|
39
|
+
Opens a rich interface at `localhost:3333` with:
|
|
34
40
|
- Collapsible folder tree
|
|
35
41
|
- Rendered markdown with syntax highlighting
|
|
36
42
|
- Clickable `[[wikilinks]]`
|
|
@@ -50,7 +56,7 @@ Opens an Obsidian-like interface at `localhost:3333` with:
|
|
|
50
56
|
```
|
|
51
57
|
|
|
52
58
|
- **Headless by default** — runs as an MCP server (stdio), no GUI needed
|
|
53
|
-
- **Markdown files on disk** —
|
|
59
|
+
- **Markdown files on disk** — plain `.md` files with YAML frontmatter, no database
|
|
54
60
|
- **In-memory index** — links, backlinks, tags, search, similarity scoring
|
|
55
61
|
- **Web UI optional** — `kyp-mem ui` when you want to browse visually
|
|
56
62
|
|
|
@@ -83,7 +89,7 @@ Opens an Obsidian-like interface at `localhost:3333` with:
|
|
|
83
89
|
|
|
84
90
|
## Note Format
|
|
85
91
|
|
|
86
|
-
Standard markdown with YAML frontmatter
|
|
92
|
+
Standard markdown with YAML frontmatter:
|
|
87
93
|
|
|
88
94
|
```markdown
|
|
89
95
|
---
|
|
@@ -108,8 +114,8 @@ If you prefer to configure manually instead of using `setup-claude`:
|
|
|
108
114
|
{
|
|
109
115
|
"mcpServers": {
|
|
110
116
|
"kyp-mem": {
|
|
111
|
-
"command": "
|
|
112
|
-
"args": ["serve"],
|
|
117
|
+
"command": "npx",
|
|
118
|
+
"args": ["-y", "kyp-mem", "serve"],
|
|
113
119
|
"env": {
|
|
114
120
|
"KYP_VAULT": "~/.kyp-mem/vault"
|
|
115
121
|
}
|
|
@@ -134,12 +140,10 @@ Add to `~/.claude/settings.json` (global) or `.claude/settings.json` (per-projec
|
|
|
134
140
|
└── ...
|
|
135
141
|
```
|
|
136
142
|
|
|
137
|
-
## Publishing to
|
|
143
|
+
## Publishing to npm
|
|
138
144
|
|
|
139
145
|
```bash
|
|
140
|
-
|
|
141
|
-
python3 -m build
|
|
142
|
-
twine upload dist/*
|
|
146
|
+
npm publish
|
|
143
147
|
```
|
|
144
148
|
|
|
145
149
|
## License
|
package/bin/cli.mjs
CHANGED
|
@@ -1,33 +1,68 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { spawnSync } from "child_process";
|
|
4
|
+
import { delimiter, dirname, resolve } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
4
6
|
|
|
5
7
|
const args = process.argv.slice(2);
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const root = resolve(__dirname, "..");
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const env = {
|
|
12
|
+
...process.env,
|
|
13
|
+
PYTHONPATH: process.env.PYTHONPATH
|
|
14
|
+
? `${root}${delimiter}${process.env.PYTHONPATH}`
|
|
15
|
+
: root,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function run(command, cmdArgs, stdio = "ignore") {
|
|
19
|
+
return spawnSync(command, cmdArgs, { stdio, env });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function pythonCandidates() {
|
|
23
|
+
if (process.env.KYP_MEM_PYTHON) {
|
|
24
|
+
return [[process.env.KYP_MEM_PYTHON, []]];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const candidates = [
|
|
28
|
+
["python3", []],
|
|
29
|
+
["python", []],
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
if (process.platform === "win32") {
|
|
33
|
+
candidates.unshift(["py", ["-3"]]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return candidates;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function findPython() {
|
|
40
|
+
for (const [command, prefixArgs] of pythonCandidates()) {
|
|
41
|
+
const result = run(command, [...prefixArgs, "--version"]);
|
|
42
|
+
if (result.status === 0) {
|
|
43
|
+
return [command, prefixArgs];
|
|
44
|
+
}
|
|
13
45
|
}
|
|
46
|
+
|
|
47
|
+
return null;
|
|
14
48
|
}
|
|
15
49
|
|
|
16
|
-
|
|
17
|
-
if (tryRun("kyp-mem", args)) process.exit(0);
|
|
50
|
+
const python = findPython();
|
|
18
51
|
|
|
19
|
-
|
|
20
|
-
|
|
52
|
+
if (python) {
|
|
53
|
+
const [command, prefixArgs] = python;
|
|
54
|
+
const result = run(command, [...prefixArgs, "-m", "kyp_mem.cli", ...args], "inherit");
|
|
21
55
|
|
|
22
|
-
|
|
23
|
-
|
|
56
|
+
if (result.signal) {
|
|
57
|
+
process.kill(process.pid, result.signal);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
process.exit(result.status ?? 1);
|
|
61
|
+
}
|
|
24
62
|
|
|
25
63
|
console.error("");
|
|
26
|
-
console.error(" \x1b[31mError:\x1b[0m
|
|
64
|
+
console.error(" \x1b[31mError:\x1b[0m Python 3 was not found.");
|
|
27
65
|
console.error("");
|
|
28
|
-
console.error(" Install
|
|
29
|
-
console.error(" \x1b[33mpip install kyp-mem\x1b[0m");
|
|
30
|
-
console.error(" Or from source:");
|
|
31
|
-
console.error(" \x1b[33mpip install git+https://github.com/Adhithya-Karthikeyan/KYP-MEM.git\x1b[0m");
|
|
66
|
+
console.error(" Install Python 3.10+ and rerun this command.");
|
|
32
67
|
console.error("");
|
|
33
68
|
process.exit(1);
|
package/bin/install.mjs
CHANGED
|
@@ -1,36 +1,77 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { spawnSync } from "child_process";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { dirname, resolve } from "path";
|
|
6
6
|
|
|
7
7
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
const root = resolve(__dirname, "..");
|
|
9
9
|
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
function run(command, args, options = {}) {
|
|
11
|
+
return spawnSync(command, args, {
|
|
12
|
+
cwd: root,
|
|
13
|
+
stdio: options.stdio ?? "ignore",
|
|
14
|
+
env: {
|
|
15
|
+
...process.env,
|
|
16
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1",
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function pythonCandidates() {
|
|
22
|
+
if (process.env.KYP_MEM_PYTHON) {
|
|
23
|
+
return [[process.env.KYP_MEM_PYTHON, []]];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const candidates = [
|
|
27
|
+
["python3", []],
|
|
28
|
+
["python", []],
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
if (process.platform === "win32") {
|
|
32
|
+
candidates.unshift(["py", ["-3"]]);
|
|
16
33
|
}
|
|
34
|
+
|
|
35
|
+
return candidates;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function findPython() {
|
|
39
|
+
for (const [command, prefixArgs] of pythonCandidates()) {
|
|
40
|
+
const result = run(command, [...prefixArgs, "--version"]);
|
|
41
|
+
if (result.status === 0) {
|
|
42
|
+
return [command, prefixArgs];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return null;
|
|
17
47
|
}
|
|
18
48
|
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
execSync("kyp-mem --help", { stdio: "pipe" });
|
|
49
|
+
if (process.env.KYP_MEM_SKIP_PYTHON_INSTALL === "1") {
|
|
22
50
|
process.exit(0);
|
|
23
|
-
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const python = findPython();
|
|
54
|
+
|
|
55
|
+
if (!python) {
|
|
56
|
+
console.log(" \x1b[33m!\x1b[0m Python 3 was not found.");
|
|
57
|
+
console.log(" \x1b[33m!\x1b[0m Install Python 3.10+ and run: python3 -m pip install --user .");
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const [pythonCommand, pythonPrefixArgs] = python;
|
|
24
62
|
|
|
25
63
|
console.log(" Installing kyp-mem Python package...");
|
|
26
64
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
65
|
+
const result = run(
|
|
66
|
+
pythonCommand,
|
|
67
|
+
[...pythonPrefixArgs, "-m", "pip", "install", "--user", "."],
|
|
68
|
+
{ stdio: "inherit" },
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (result.status === 0) {
|
|
32
72
|
console.log(" \x1b[32m✓\x1b[0m kyp-mem installed successfully");
|
|
33
73
|
} else {
|
|
34
|
-
console.log(" \x1b[33m!\x1b[0m Could not auto-install Python package.");
|
|
35
|
-
console.log(
|
|
74
|
+
console.log(" \x1b[33m!\x1b[0m Could not auto-install the Python package.");
|
|
75
|
+
console.log(` \x1b[33m!\x1b[0m Run manually from ${root}:`);
|
|
76
|
+
console.log(" python3 -m pip install --user .");
|
|
36
77
|
}
|
package/kyp_mem/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"""KYP-MEM — Know Your Project Memory. Headless
|
|
1
|
+
"""KYP-MEM — Know Your Project Memory. Headless knowledge base for AI agents."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.2.
|
|
3
|
+
__version__ = "0.2.1"
|
package/kyp_mem/cli.py
CHANGED
|
@@ -16,7 +16,7 @@ R = "\033[0m" # reset
|
|
|
16
16
|
def main():
|
|
17
17
|
parser = argparse.ArgumentParser(
|
|
18
18
|
prog="kyp-mem",
|
|
19
|
-
description="KYP-MEM — Know Your Project Memory. Headless
|
|
19
|
+
description="KYP-MEM — Know Your Project Memory. Headless knowledge base for AI agents.",
|
|
20
20
|
)
|
|
21
21
|
parser.add_argument("--vault", default=None, help="Override vault path")
|
|
22
22
|
|
|
@@ -74,7 +74,7 @@ def _run_init():
|
|
|
74
74
|
print(f"{C} ██║ ██╗ ██║ ██║ ██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║{R}")
|
|
75
75
|
print(f"{C} ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝{R}")
|
|
76
76
|
print()
|
|
77
|
-
print(f" {D}Know Your Project — Headless
|
|
77
|
+
print(f" {D}Know Your Project — Headless knowledge base for AI agents{R}")
|
|
78
78
|
print()
|
|
79
79
|
print(f" {Y}>> First-time setup{R}")
|
|
80
80
|
print()
|
|
@@ -108,12 +108,20 @@ def _run_setup_claude(global_config: bool = False):
|
|
|
108
108
|
|
|
109
109
|
vault_path = get_vault_path()
|
|
110
110
|
kyp_mem_bin = shutil.which("kyp-mem")
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
npx_bin = shutil.which("npx")
|
|
112
|
+
|
|
113
|
+
if kyp_mem_bin and "_npx" not in Path(kyp_mem_bin).parts:
|
|
114
|
+
mcp_command = kyp_mem_bin
|
|
115
|
+
mcp_args = ["serve"]
|
|
116
|
+
elif npx_bin:
|
|
117
|
+
mcp_command = npx_bin
|
|
118
|
+
mcp_args = ["-y", "kyp-mem", "serve"]
|
|
119
|
+
else:
|
|
113
120
|
print(f" {Y}Warning:{R} 'kyp-mem' not found in PATH.")
|
|
114
|
-
print(f" {D}Make sure you installed with:
|
|
121
|
+
print(f" {D}Make sure you installed with: npm install -g kyp-mem{R}")
|
|
115
122
|
print()
|
|
116
|
-
|
|
123
|
+
mcp_command = "kyp-mem"
|
|
124
|
+
mcp_args = ["serve"]
|
|
117
125
|
|
|
118
126
|
if global_config:
|
|
119
127
|
settings_path = Path.home() / ".claude" / "settings.json"
|
|
@@ -134,8 +142,8 @@ def _run_setup_claude(global_config: bool = False):
|
|
|
134
142
|
mcp_servers = settings.setdefault("mcpServers", {})
|
|
135
143
|
|
|
136
144
|
mcp_servers["kyp-mem"] = {
|
|
137
|
-
"command":
|
|
138
|
-
"args":
|
|
145
|
+
"command": mcp_command,
|
|
146
|
+
"args": mcp_args,
|
|
139
147
|
"env": {
|
|
140
148
|
"KYP_VAULT": vault_path,
|
|
141
149
|
},
|
|
@@ -148,7 +156,7 @@ def _run_setup_claude(global_config: bool = False):
|
|
|
148
156
|
print()
|
|
149
157
|
print(f" {G}✓{R} MCP server added to {scope} settings")
|
|
150
158
|
print(f" {D} File: {settings_path}{R}")
|
|
151
|
-
print(f" {D} Command: {
|
|
159
|
+
print(f" {D} Command: {mcp_command} {' '.join(mcp_args)}{R}")
|
|
152
160
|
print(f" {D} Vault: {vault_path}{R}")
|
|
153
161
|
print()
|
|
154
162
|
print(f" {C}Done!{R} Restart Claude Code and kyp-mem will run automatically.")
|
|
@@ -243,7 +251,7 @@ def _run_doctor():
|
|
|
243
251
|
def _print_banner():
|
|
244
252
|
print()
|
|
245
253
|
print(f"{C} KYP-MEM{R} — Know Your Project Memory")
|
|
246
|
-
print(f" {D}Headless
|
|
254
|
+
print(f" {D}Headless knowledge base for AI agents{R}")
|
|
247
255
|
print()
|
|
248
256
|
|
|
249
257
|
|
package/kyp_mem/server.py
CHANGED
|
@@ -7,7 +7,7 @@ from .vault import Vault
|
|
|
7
7
|
|
|
8
8
|
vault = Vault(get_vault_path())
|
|
9
9
|
|
|
10
|
-
mcp = FastMCP("kyp-mem", description="Know Your Project — headless knowledge base
|
|
10
|
+
mcp = FastMCP("kyp-mem", description="Know Your Project — headless knowledge base for AI agents")
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
@mcp.tool()
|
package/kyp_mem/ui.py
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kyp-mem",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Know Your Project — Headless
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Know Your Project — Headless knowledge base for AI agents. MCP-powered with wikilinks, backlinks, and neon web UI.",
|
|
5
5
|
"bin": {
|
|
6
|
-
"kyp-mem": "
|
|
6
|
+
"kyp-mem": "bin/cli.mjs"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"bin/",
|
|
10
|
-
"kyp_mem
|
|
10
|
+
"kyp_mem/*.py",
|
|
11
|
+
"kyp_mem/static/",
|
|
11
12
|
"pyproject.toml",
|
|
12
13
|
"README.md",
|
|
13
14
|
"LICENSE"
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
},
|
|
18
19
|
"keywords": [
|
|
19
20
|
"knowledge-base",
|
|
20
|
-
"
|
|
21
|
+
"markdown",
|
|
21
22
|
"ai",
|
|
22
23
|
"mcp",
|
|
23
24
|
"claude",
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
"license": "MIT",
|
|
30
31
|
"repository": {
|
|
31
32
|
"type": "git",
|
|
32
|
-
"url": "https://github.com/Adhithya-Karthikeyan/KYP-MEM.git"
|
|
33
|
+
"url": "git+https://github.com/Adhithya-Karthikeyan/KYP-MEM.git"
|
|
33
34
|
},
|
|
34
35
|
"homepage": "https://github.com/Adhithya-Karthikeyan/KYP-MEM"
|
|
35
36
|
}
|
package/pyproject.toml
CHANGED
|
@@ -4,15 +4,15 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "kyp-mem"
|
|
7
|
-
version = "0.2.
|
|
8
|
-
description = "Know Your Project — Headless
|
|
7
|
+
version = "0.2.1"
|
|
8
|
+
description = "Know Your Project — Headless knowledge base for AI agents. MCP-powered with wikilinks, backlinks, and neon web UI."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
12
|
authors = [
|
|
13
|
-
{name = "KDB AI Agency", email = "
|
|
13
|
+
{name = "KDB AI Agency", email = "skadhithya95@gmail.com"}
|
|
14
14
|
]
|
|
15
|
-
keywords = ["knowledge-base", "
|
|
15
|
+
keywords = ["knowledge-base", "markdown", "ai", "mcp", "notes", "wiki", "second-brain"]
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Development Status :: 3 - Alpha",
|
|
18
18
|
"Intended Audience :: Developers",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|