omni-cortex 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env python3
2
+ """PostToolUse hook - logs tool result after execution.
3
+
4
+ This hook is called by Claude Code after each tool completes.
5
+ It logs the tool output, duration, and success/error status.
6
+
7
+ Hook configuration for settings.json:
8
+ {
9
+ "hooks": {
10
+ "PostToolUse": [
11
+ {
12
+ "type": "command",
13
+ "command": "python hooks/post_tool_use.py"
14
+ }
15
+ ]
16
+ }
17
+ }
18
+ """
19
+
20
+ import json
21
+ import sys
22
+ import os
23
+ import sqlite3
24
+ from datetime import datetime, timezone
25
+ from pathlib import Path
26
+
27
+
28
+ def get_db_path() -> Path:
29
+ """Get the database path for the current project."""
30
+ project_path = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
31
+ return Path(project_path) / ".omni-cortex" / "cortex.db"
32
+
33
+
34
+ def ensure_database(db_path: Path) -> sqlite3.Connection:
35
+ """Ensure database exists and is initialized.
36
+
37
+ Auto-creates the database and schema if it doesn't exist.
38
+ This enables 'out of the box' functionality.
39
+ """
40
+ db_path.parent.mkdir(parents=True, exist_ok=True)
41
+ conn = sqlite3.connect(str(db_path))
42
+
43
+ # Check if schema exists
44
+ cursor = conn.cursor()
45
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='activities'")
46
+ if cursor.fetchone() is None:
47
+ # Apply minimal schema for activities (full schema applied by MCP)
48
+ conn.executescript("""
49
+ CREATE TABLE IF NOT EXISTS activities (
50
+ id TEXT PRIMARY KEY,
51
+ session_id TEXT,
52
+ agent_id TEXT,
53
+ timestamp TEXT NOT NULL,
54
+ event_type TEXT NOT NULL,
55
+ tool_name TEXT,
56
+ tool_input TEXT,
57
+ tool_output TEXT,
58
+ duration_ms INTEGER,
59
+ success INTEGER DEFAULT 1,
60
+ error_message TEXT,
61
+ project_path TEXT,
62
+ file_path TEXT,
63
+ metadata TEXT
64
+ );
65
+ CREATE INDEX IF NOT EXISTS idx_activities_timestamp ON activities(timestamp DESC);
66
+ CREATE INDEX IF NOT EXISTS idx_activities_tool ON activities(tool_name);
67
+ """)
68
+ conn.commit()
69
+
70
+ return conn
71
+
72
+
73
+ def generate_id() -> str:
74
+ """Generate a unique activity ID."""
75
+ timestamp_ms = int(datetime.now().timestamp() * 1000)
76
+ random_hex = os.urandom(4).hex()
77
+ return f"act_{timestamp_ms}_{random_hex}"
78
+
79
+
80
+ def truncate(text: str, max_length: int = 10000) -> str:
81
+ """Truncate text to max length."""
82
+ if len(text) <= max_length:
83
+ return text
84
+ return text[:max_length - 20] + "\n... [truncated]"
85
+
86
+
87
+ def main():
88
+ """Process PostToolUse hook."""
89
+ try:
90
+ # Read input from stdin
91
+ input_data = json.load(sys.stdin)
92
+
93
+ # Extract data from hook input
94
+ tool_name = input_data.get("tool_name")
95
+ tool_input = input_data.get("tool_input", {})
96
+ tool_output = input_data.get("tool_output", {})
97
+ agent_id = input_data.get("agent_id")
98
+
99
+ # Determine success/error
100
+ is_error = input_data.get("is_error", False)
101
+ error_message = None
102
+ if is_error and isinstance(tool_output, dict):
103
+ error_message = tool_output.get("error") or tool_output.get("message")
104
+
105
+ # Skip logging our own tools to prevent recursion
106
+ if tool_name and tool_name.startswith("cortex_"):
107
+ print(json.dumps({}))
108
+ return
109
+
110
+ session_id = os.environ.get("CLAUDE_SESSION_ID")
111
+ project_path = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
112
+
113
+ # Auto-initialize database (creates if not exists)
114
+ db_path = get_db_path()
115
+ conn = ensure_database(db_path)
116
+
117
+ # Insert activity record
118
+ cursor = conn.cursor()
119
+ cursor.execute(
120
+ """
121
+ INSERT INTO activities (
122
+ id, session_id, agent_id, timestamp, event_type,
123
+ tool_name, tool_input, tool_output, success, error_message, project_path
124
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
125
+ """,
126
+ (
127
+ generate_id(),
128
+ session_id,
129
+ agent_id,
130
+ datetime.now(timezone.utc).isoformat(),
131
+ "post_tool_use",
132
+ tool_name,
133
+ truncate(json.dumps(tool_input, default=str)),
134
+ truncate(json.dumps(tool_output, default=str)),
135
+ 0 if is_error else 1,
136
+ error_message,
137
+ project_path,
138
+ ),
139
+ )
140
+ conn.commit()
141
+ conn.close()
142
+
143
+ # Return empty response (no modification)
144
+ print(json.dumps({}))
145
+
146
+ except Exception as e:
147
+ # Hooks should never block - log error but continue
148
+ print(json.dumps({"systemMessage": f"Cortex post_tool_use: {e}"}))
149
+
150
+ sys.exit(0)
151
+
152
+
153
+ if __name__ == "__main__":
154
+ main()
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env python3
2
+ """PreToolUse hook - logs tool call before execution.
3
+
4
+ This hook is called by Claude Code before each tool is executed.
5
+ It logs the tool name and input to the Cortex activity database.
6
+
7
+ Hook configuration for settings.json:
8
+ {
9
+ "hooks": {
10
+ "PreToolUse": [
11
+ {
12
+ "type": "command",
13
+ "command": "python hooks/pre_tool_use.py"
14
+ }
15
+ ]
16
+ }
17
+ }
18
+ """
19
+
20
+ import json
21
+ import sys
22
+ import os
23
+ import sqlite3
24
+ from datetime import datetime, timezone
25
+ from pathlib import Path
26
+
27
+
28
+ def get_db_path() -> Path:
29
+ """Get the database path for the current project."""
30
+ project_path = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
31
+ return Path(project_path) / ".omni-cortex" / "cortex.db"
32
+
33
+
34
+ def ensure_database(db_path: Path) -> sqlite3.Connection:
35
+ """Ensure database exists and is initialized.
36
+
37
+ Auto-creates the database and schema if it doesn't exist.
38
+ This enables 'out of the box' functionality.
39
+ """
40
+ db_path.parent.mkdir(parents=True, exist_ok=True)
41
+ conn = sqlite3.connect(str(db_path))
42
+
43
+ # Check if schema exists
44
+ cursor = conn.cursor()
45
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='activities'")
46
+ if cursor.fetchone() is None:
47
+ # Apply minimal schema for activities (full schema applied by MCP)
48
+ conn.executescript("""
49
+ CREATE TABLE IF NOT EXISTS activities (
50
+ id TEXT PRIMARY KEY,
51
+ session_id TEXT,
52
+ agent_id TEXT,
53
+ timestamp TEXT NOT NULL,
54
+ event_type TEXT NOT NULL,
55
+ tool_name TEXT,
56
+ tool_input TEXT,
57
+ tool_output TEXT,
58
+ duration_ms INTEGER,
59
+ success INTEGER DEFAULT 1,
60
+ error_message TEXT,
61
+ project_path TEXT,
62
+ file_path TEXT,
63
+ metadata TEXT
64
+ );
65
+ CREATE INDEX IF NOT EXISTS idx_activities_timestamp ON activities(timestamp DESC);
66
+ CREATE INDEX IF NOT EXISTS idx_activities_tool ON activities(tool_name);
67
+ """)
68
+ conn.commit()
69
+
70
+ return conn
71
+
72
+
73
+ def generate_id() -> str:
74
+ """Generate a unique activity ID."""
75
+ timestamp_ms = int(datetime.now().timestamp() * 1000)
76
+ random_hex = os.urandom(4).hex()
77
+ return f"act_{timestamp_ms}_{random_hex}"
78
+
79
+
80
+ def truncate(text: str, max_length: int = 10000) -> str:
81
+ """Truncate text to max length."""
82
+ if len(text) <= max_length:
83
+ return text
84
+ return text[:max_length - 20] + "\n... [truncated]"
85
+
86
+
87
+ def main():
88
+ """Process PreToolUse hook."""
89
+ try:
90
+ # Read input from stdin
91
+ input_data = json.load(sys.stdin)
92
+
93
+ # Extract data from hook input
94
+ tool_name = input_data.get("tool_name")
95
+ tool_input = input_data.get("tool_input", {})
96
+ agent_id = input_data.get("agent_id")
97
+
98
+ # Skip logging our own tools to prevent recursion
99
+ if tool_name and tool_name.startswith("cortex_"):
100
+ print(json.dumps({}))
101
+ return
102
+
103
+ session_id = os.environ.get("CLAUDE_SESSION_ID")
104
+ project_path = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
105
+
106
+ # Auto-initialize database (creates if not exists)
107
+ db_path = get_db_path()
108
+ conn = ensure_database(db_path)
109
+
110
+ # Insert activity record
111
+ cursor = conn.cursor()
112
+ cursor.execute(
113
+ """
114
+ INSERT INTO activities (
115
+ id, session_id, agent_id, timestamp, event_type,
116
+ tool_name, tool_input, project_path
117
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
118
+ """,
119
+ (
120
+ generate_id(),
121
+ session_id,
122
+ agent_id,
123
+ datetime.now(timezone.utc).isoformat(),
124
+ "pre_tool_use",
125
+ tool_name,
126
+ truncate(json.dumps(tool_input, default=str)),
127
+ project_path,
128
+ ),
129
+ )
130
+ conn.commit()
131
+ conn.close()
132
+
133
+ # Return empty response (no modification to tool call)
134
+ print(json.dumps({}))
135
+
136
+ except Exception as e:
137
+ # Hooks should never block - log error but continue
138
+ print(json.dumps({"systemMessage": f"Cortex pre_tool_use: {e}"}))
139
+
140
+ sys.exit(0)
141
+
142
+
143
+ if __name__ == "__main__":
144
+ main()
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env python3
2
+ """Stop hook - logs session end when Claude Code stops.
3
+
4
+ This hook is called when Claude Code exits or the session ends.
5
+ It finalizes the session and generates a summary.
6
+
7
+ Hook configuration for settings.json:
8
+ {
9
+ "hooks": {
10
+ "Stop": [
11
+ {
12
+ "type": "command",
13
+ "command": "python hooks/stop.py"
14
+ }
15
+ ]
16
+ }
17
+ }
18
+ """
19
+
20
+ import json
21
+ import sys
22
+ import os
23
+ import sqlite3
24
+ from datetime import datetime, timezone
25
+ from pathlib import Path
26
+
27
+
28
+ def get_db_path() -> Path:
29
+ """Get the database path for the current project."""
30
+ project_path = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
31
+ return Path(project_path) / ".omni-cortex" / "cortex.db"
32
+
33
+
34
+ def generate_id(prefix: str) -> str:
35
+ """Generate a unique ID."""
36
+ timestamp_ms = int(datetime.now().timestamp() * 1000)
37
+ random_hex = os.urandom(4).hex()
38
+ return f"{prefix}_{timestamp_ms}_{random_hex}"
39
+
40
+
41
+ def main():
42
+ """Process Stop hook."""
43
+ try:
44
+ # Read input from stdin
45
+ input_data = json.load(sys.stdin)
46
+
47
+ db_path = get_db_path()
48
+
49
+ # Only process if database exists
50
+ if not db_path.exists():
51
+ print(json.dumps({}))
52
+ return
53
+
54
+ session_id = os.environ.get("CLAUDE_SESSION_ID")
55
+ if not session_id:
56
+ print(json.dumps({}))
57
+ return
58
+
59
+ now = datetime.now(timezone.utc).isoformat()
60
+
61
+ # Connect to database
62
+ conn = sqlite3.connect(str(db_path))
63
+ conn.row_factory = sqlite3.Row
64
+ cursor = conn.cursor()
65
+
66
+ # Check if session exists
67
+ cursor.execute("SELECT id FROM sessions WHERE id = ?", (session_id,))
68
+ if not cursor.fetchone():
69
+ print(json.dumps({}))
70
+ conn.close()
71
+ return
72
+
73
+ # End the session
74
+ cursor.execute(
75
+ "UPDATE sessions SET ended_at = ? WHERE id = ? AND ended_at IS NULL",
76
+ (now, session_id),
77
+ )
78
+
79
+ # Gather session statistics
80
+ cursor.execute(
81
+ "SELECT COUNT(*) as cnt FROM activities WHERE session_id = ?",
82
+ (session_id,),
83
+ )
84
+ total_activities = cursor.fetchone()["cnt"]
85
+
86
+ cursor.execute(
87
+ "SELECT COUNT(*) as cnt FROM memories WHERE source_session_id = ?",
88
+ (session_id,),
89
+ )
90
+ total_memories = cursor.fetchone()["cnt"]
91
+
92
+ # Get tools used
93
+ cursor.execute(
94
+ """
95
+ SELECT tool_name, COUNT(*) as cnt
96
+ FROM activities
97
+ WHERE session_id = ? AND tool_name IS NOT NULL
98
+ GROUP BY tool_name
99
+ """,
100
+ (session_id,),
101
+ )
102
+ tools_used = {row["tool_name"]: row["cnt"] for row in cursor.fetchall()}
103
+
104
+ # Get files modified
105
+ cursor.execute(
106
+ """
107
+ SELECT DISTINCT file_path
108
+ FROM activities
109
+ WHERE session_id = ? AND file_path IS NOT NULL
110
+ """,
111
+ (session_id,),
112
+ )
113
+ files_modified = [row["file_path"] for row in cursor.fetchall()]
114
+
115
+ # Get errors
116
+ cursor.execute(
117
+ """
118
+ SELECT error_message
119
+ FROM activities
120
+ WHERE session_id = ? AND success = 0 AND error_message IS NOT NULL
121
+ LIMIT 10
122
+ """,
123
+ (session_id,),
124
+ )
125
+ key_errors = [row["error_message"] for row in cursor.fetchall()]
126
+
127
+ # Create or update summary
128
+ cursor.execute(
129
+ "SELECT id FROM session_summaries WHERE session_id = ?",
130
+ (session_id,),
131
+ )
132
+ existing = cursor.fetchone()
133
+
134
+ if existing:
135
+ cursor.execute(
136
+ """
137
+ UPDATE session_summaries
138
+ SET key_errors = ?, files_modified = ?, tools_used = ?,
139
+ total_activities = ?, total_memories_created = ?
140
+ WHERE session_id = ?
141
+ """,
142
+ (
143
+ json.dumps(key_errors) if key_errors else None,
144
+ json.dumps(files_modified) if files_modified else None,
145
+ json.dumps(tools_used) if tools_used else None,
146
+ total_activities,
147
+ total_memories,
148
+ session_id,
149
+ ),
150
+ )
151
+ else:
152
+ cursor.execute(
153
+ """
154
+ INSERT INTO session_summaries (
155
+ id, session_id, key_errors, files_modified, tools_used,
156
+ total_activities, total_memories_created, created_at
157
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
158
+ """,
159
+ (
160
+ generate_id("sum"),
161
+ session_id,
162
+ json.dumps(key_errors) if key_errors else None,
163
+ json.dumps(files_modified) if files_modified else None,
164
+ json.dumps(tools_used) if tools_used else None,
165
+ total_activities,
166
+ total_memories,
167
+ now,
168
+ ),
169
+ )
170
+
171
+ conn.commit()
172
+ conn.close()
173
+
174
+ print(json.dumps({}))
175
+
176
+ except Exception as e:
177
+ # Hooks should never block
178
+ print(json.dumps({"systemMessage": f"Cortex stop: {e}"}))
179
+
180
+ sys.exit(0)
181
+
182
+
183
+ if __name__ == "__main__":
184
+ main()
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+ """SubagentStop hook - logs when a subagent completes.
3
+
4
+ This hook is called when a subagent (spawned by the Task tool) finishes.
5
+ It logs the subagent completion and any results.
6
+
7
+ Hook configuration for settings.json:
8
+ {
9
+ "hooks": {
10
+ "SubagentStop": [
11
+ {
12
+ "type": "command",
13
+ "command": "python hooks/subagent_stop.py"
14
+ }
15
+ ]
16
+ }
17
+ }
18
+ """
19
+
20
+ import json
21
+ import sys
22
+ import os
23
+ import sqlite3
24
+ from datetime import datetime, timezone
25
+ from pathlib import Path
26
+
27
+
28
+ def get_db_path() -> Path:
29
+ """Get the database path for the current project."""
30
+ project_path = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
31
+ return Path(project_path) / ".omni-cortex" / "cortex.db"
32
+
33
+
34
+ def generate_id() -> str:
35
+ """Generate a unique activity ID."""
36
+ timestamp_ms = int(datetime.now().timestamp() * 1000)
37
+ random_hex = os.urandom(4).hex()
38
+ return f"act_{timestamp_ms}_{random_hex}"
39
+
40
+
41
+ def truncate(text: str, max_length: int = 10000) -> str:
42
+ """Truncate text to max length."""
43
+ if len(text) <= max_length:
44
+ return text
45
+ return text[:max_length - 20] + "\n... [truncated]"
46
+
47
+
48
+ def main():
49
+ """Process SubagentStop hook."""
50
+ try:
51
+ # Read input from stdin
52
+ input_data = json.load(sys.stdin)
53
+
54
+ db_path = get_db_path()
55
+
56
+ # Only log if database exists
57
+ if not db_path.exists():
58
+ print(json.dumps({}))
59
+ return
60
+
61
+ # Extract data from hook input
62
+ subagent_id = input_data.get("subagent_id")
63
+ subagent_type = input_data.get("subagent_type", "subagent")
64
+ result = input_data.get("result", {})
65
+
66
+ session_id = os.environ.get("CLAUDE_SESSION_ID")
67
+ project_path = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
68
+ now = datetime.now(timezone.utc).isoformat()
69
+
70
+ # Connect to database
71
+ conn = sqlite3.connect(str(db_path))
72
+ cursor = conn.cursor()
73
+
74
+ # Log the subagent completion as an activity
75
+ cursor.execute(
76
+ """
77
+ INSERT INTO activities (
78
+ id, session_id, agent_id, timestamp, event_type,
79
+ tool_name, tool_output, success, project_path
80
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
81
+ """,
82
+ (
83
+ generate_id(),
84
+ session_id,
85
+ subagent_id,
86
+ now,
87
+ "subagent_stop",
88
+ f"subagent_{subagent_type}",
89
+ truncate(json.dumps(result, default=str)),
90
+ 1,
91
+ project_path,
92
+ ),
93
+ )
94
+
95
+ # Update or create agent record
96
+ cursor.execute(
97
+ """
98
+ INSERT INTO agents (id, name, type, first_seen, last_seen, total_activities)
99
+ VALUES (?, ?, ?, ?, ?, 1)
100
+ ON CONFLICT(id) DO UPDATE SET
101
+ last_seen = ?,
102
+ total_activities = total_activities + 1
103
+ """,
104
+ (subagent_id, None, "subagent", now, now, now),
105
+ )
106
+
107
+ conn.commit()
108
+ conn.close()
109
+
110
+ print(json.dumps({}))
111
+
112
+ except Exception as e:
113
+ # Hooks should never block
114
+ print(json.dumps({"systemMessage": f"Cortex subagent_stop: {e}"}))
115
+
116
+ sys.exit(0)
117
+
118
+
119
+ if __name__ == "__main__":
120
+ main()
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: omni-cortex
3
+ Version: 1.0.0
4
+ Summary: Universal Memory MCP for Claude Code - dual-layer activity logging and knowledge storage
5
+ Project-URL: Homepage, https://github.com/AllCytes/Omni-Cortex
6
+ Project-URL: Repository, https://github.com/AllCytes/Omni-Cortex
7
+ Project-URL: Issues, https://github.com/AllCytes/Omni-Cortex/issues
8
+ Project-URL: Documentation, https://github.com/AllCytes/Omni-Cortex#readme
9
+ Author: Tony
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,anthropic,claude,claude-code,llm,mcp,memory,semantic-search
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: httpx>=0.25.0
25
+ Requires-Dist: mcp>=1.0.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Requires-Dist: pyyaml>=6.0.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: black>=23.0.0; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
31
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
32
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
33
+ Provides-Extra: semantic
34
+ Requires-Dist: numpy>=1.24.0; extra == 'semantic'
35
+ Requires-Dist: sentence-transformers>=2.2.0; extra == 'semantic'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # Omni Cortex MCP
39
+
40
+ A universal memory system for Claude Code that combines activity logging with intelligent knowledge storage.
41
+
42
+ ## Features
43
+
44
+ - **Zero Configuration**: Works out of the box - just install and run setup
45
+ - **Dual-Layer Storage**: Activity logging (audit trail) + Knowledge store (memories)
46
+ - **15 MCP Tools**: Full-featured API for memory management, activity tracking, and session continuity
47
+ - **Semantic Search**: AI-powered search using sentence-transformers (optional)
48
+ - **Hybrid Search**: Combines keyword (FTS5) + semantic search for best results
49
+ - **Full-Text Search**: SQLite FTS5-powered keyword search with smart ranking
50
+ - **Auto-Categorization**: Automatic memory type detection and tag suggestions
51
+ - **Session Continuity**: "Last time you were working on..." context
52
+ - **Importance Decay**: Frequently accessed memories naturally surface
53
+ - **Auto Activity Logging**: Automatically logs all tool calls via hooks
54
+
55
+ ## Installation
56
+
57
+ ### Quick Install (Recommended)
58
+
59
+ ```bash
60
+ # Install the package
61
+ pip install omni-cortex
62
+
63
+ # Run automatic setup (configures MCP server + hooks)
64
+ omni-cortex-setup
65
+ ```
66
+
67
+ That's it! Omni Cortex will now:
68
+ - Automatically log all Claude Code tool calls
69
+ - Provide memory tools (cortex_remember, cortex_recall, etc.)
70
+ - Create a per-project database at `.omni-cortex/cortex.db`
71
+
72
+ ### With Semantic Search
73
+
74
+ For AI-powered semantic search capabilities:
75
+
76
+ ```bash
77
+ pip install omni-cortex[semantic]
78
+ omni-cortex-setup
79
+ ```
80
+
81
+ ### From Source
82
+
83
+ ```bash
84
+ git clone https://github.com/AllCytes/Omni-Cortex.git
85
+ cd omni-cortex
86
+ pip install -e ".[semantic]"
87
+ python -m omni_cortex.setup
88
+ ```
89
+
90
+ ### Manual Configuration
91
+
92
+ If you prefer manual setup, add to `~/.claude.json`:
93
+
94
+ ```json
95
+ {
96
+ "mcpServers": {
97
+ "omni-cortex": {
98
+ "command": "python",
99
+ "args": ["-m", "omni_cortex.server"]
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ And optionally configure hooks in `~/.claude/settings.json` for activity logging:
106
+
107
+ ```json
108
+ {
109
+ "hooks": {
110
+ "PreToolUse": [{
111
+ "type": "command",
112
+ "command": "python -m omni_cortex.hooks.pre_tool_use"
113
+ }],
114
+ "PostToolUse": [{
115
+ "type": "command",
116
+ "command": "python -m omni_cortex.hooks.post_tool_use"
117
+ }]
118
+ }
119
+ }
120
+ ```
121
+
122
+ ### Uninstall
123
+
124
+ ```bash
125
+ omni-cortex-setup --uninstall
126
+ pip uninstall omni-cortex
127
+ ```
128
+
129
+ ## Tools
130
+
131
+ ### Memory Tools (6)
132
+
133
+ | Tool | Description |
134
+ |------|-------------|
135
+ | `cortex_remember` | Store information with auto-categorization |
136
+ | `cortex_recall` | Search memories (modes: keyword, semantic, hybrid) |
137
+ | `cortex_list_memories` | List memories with filters and pagination |
138
+ | `cortex_update_memory` | Update memory content, tags, or status |
139
+ | `cortex_forget` | Delete a memory |
140
+ | `cortex_link_memories` | Create relationships between memories |
141
+
142
+ ### Activity Tools (3)
143
+
144
+ | Tool | Description |
145
+ |------|-------------|
146
+ | `cortex_log_activity` | Manually log an activity |
147
+ | `cortex_get_activities` | Query the activity log |
148
+ | `cortex_get_timeline` | Get a chronological timeline |
149
+
150
+ ### Session Tools (3)
151
+
152
+ | Tool | Description |
153
+ |------|-------------|
154
+ | `cortex_start_session` | Start a new session with context |
155
+ | `cortex_end_session` | End session and generate summary |
156
+ | `cortex_get_session_context` | Get context from previous sessions |
157
+
158
+ ### Utility Tools (3)
159
+
160
+ | Tool | Description |
161
+ |------|-------------|
162
+ | `cortex_list_tags` | List all tags with usage counts |
163
+ | `cortex_review_memories` | Review and update memory freshness |
164
+ | `cortex_export` | Export data to markdown or JSON |
165
+
166
+ ## Memory Types
167
+
168
+ Memories are automatically categorized into:
169
+
170
+ - `general` - General notes and information
171
+ - `warning` - Cautions, things to avoid
172
+ - `tip` - Tips, tricks, best practices
173
+ - `config` - Configuration and settings
174
+ - `troubleshooting` - Debugging and problem-solving
175
+ - `code` - Code snippets and algorithms
176
+ - `error` - Error messages and failures
177
+ - `solution` - Solutions to problems
178
+ - `command` - CLI commands
179
+ - `concept` - Definitions and explanations
180
+ - `decision` - Architectural decisions
181
+
182
+ ## Storage
183
+
184
+ - **Per-project**: `.omni-cortex/cortex.db` in your project directory
185
+ - **Global**: `~/.omni-cortex/global.db` for cross-project search
186
+
187
+ ## Configuration
188
+
189
+ Create `.omni-cortex/config.yaml` in your project:
190
+
191
+ ```yaml
192
+ schema_version: "1.0"
193
+ embedding_enabled: true
194
+ decay_rate_per_day: 0.5
195
+ freshness_review_days: 30
196
+ auto_provide_context: true
197
+ context_depth: 3
198
+ ```
199
+
200
+ ## Development
201
+
202
+ ```bash
203
+ # Install dev dependencies
204
+ pip install -e ".[dev]"
205
+
206
+ # Run tests
207
+ pytest
208
+
209
+ # Format code
210
+ black src tests
211
+ ruff check src tests
212
+ ```
213
+
214
+ ## License
215
+
216
+ MIT
@@ -0,0 +1,9 @@
1
+ omni_cortex-1.0.0.data/data/share/omni-cortex/hooks/post_tool_use.py,sha256=J9NDtoPE4MbCacAX9XYhqRXF2Agaw_SRbik8U0jlovs,4828
2
+ omni_cortex-1.0.0.data/data/share/omni-cortex/hooks/pre_tool_use.py,sha256=jLkoleRSb_MJ0iy-uNwKVi8-gS49vlmLaF--riJoff0,4351
3
+ omni_cortex-1.0.0.data/data/share/omni-cortex/hooks/stop.py,sha256=T1bwcmbTLj0gzjrVvFBT1zB6wff4J2YkYBAY-ZxZI5g,5336
4
+ omni_cortex-1.0.0.data/data/share/omni-cortex/hooks/subagent_stop.py,sha256=V9HQSFGNOfkg8ZCstPEy4h5V8BP4AbrVr8teFzN1kNk,3314
5
+ omni_cortex-1.0.0.dist-info/METADATA,sha256=Q3zKLHnNw0YmcG9Kd2XnMjlKtEYcPFauZVJr931Nfus,6130
6
+ omni_cortex-1.0.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
+ omni_cortex-1.0.0.dist-info/entry_points.txt,sha256=eRePHG-7dXr4ZAHwI1l-GY5rgVrpa1wZPL3sYBeC5QU,99
8
+ omni_cortex-1.0.0.dist-info/licenses/LICENSE,sha256=oG_397owMmi-Umxp5sYocJ6RPohp9_bDNnnEu9OUphg,1072
9
+ omni_cortex-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ omni-cortex = omni_cortex.server:main
3
+ omni-cortex-setup = omni_cortex.setup:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Tony Simonovsky
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.