Observed since 21 Oct, 11:06 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
aikb
Programmatic CRUD for AI project knowledge bases (Claude Projects, Gemini Gems)
Programmatic CRUD for AI project knowledge bases (Claude Projects, Gemini Gems).
Dict-like access to knowledge files — store['notes.md'] = content — backed by
local files, Claude Projects (via ClaudeSync), or any custom provider.
To install: pip install aikb
from aikb import LocalKb
store = LocalKb() # ~/.local/share/aikb/localkb_files/default/
store['ideas.md'] = '# Ideas\nFirst idea'
print(store['ideas.md'])
list(store) # ['ideas.md']
del store['ideas.md']
Every store is a standard Python MutableMapping (dict-like), so len(),
in, .keys(), .values(), .items(), and .update() all work.
Override the default directory with a path or the AIKB_LOCAL_DIR env var:
store = LocalKb('/path/to/my/knowledge')
store = LocalKb(project_id='research') # subfolder under default dir
Manage knowledge files in Claude.ai Projects programmatically:
pip install aikb[claude]
from aikb import ClaudeProjects
projects = ClaudeProjects()
list(projects) # ['My Project', 'Another Project', ...]
files = projects['My Project'] # returns a dict-like store
list(files) # ['context.md', 'notes.md']
print(files['context.md'])
from aikb import ClaudeProject
store = ClaudeProject('your-project-uuid')
store['context.md'] = '# Project context\n...'
print(store['context.md'])
del store['context.md']
aikb automatically looks for a Claude session key in this order:
session_key parameterCLAUDE_SESSION_KEY environment variable~/.claudesync/)pip install aikb[cookies])If none are found, you'll get a helpful error with instructions.
To get your session key manually:
sessionKey cookie (starts with sk-ant-)export CLAUDE_SESSION_KEY='sk-ant-sid01-...'
Or use ClaudeSync to store credentials:
pip install claudesync
claudesync auth login
aikb includes a sync engine that works with any two MutableMapping stores — plain dicts, LocalKb, ClaudeProject, or any custom store.
from aikb import LocalKb, ClaudeProject, push, pull
local = LocalKb('/path/to/docs')
remote = ClaudeProject('project-uuid')
push(local, remote) # local → remote (source wins)
push(local, remote, delete=True) # also remove remote files not in local
pull(local, remote) # remote → local
from aikb import sync, clone
# First time: clone to establish a manifest (baseline)
clone(local, remote, manifest_path='.aikb/manifest.json')
# Later: bidirectional sync detects who changed what
sync(local, remote, manifest_path='.aikb/manifest.json')
from aikb import status
for action in status(local, remote):
print(f"{action.action.value:8s} {action.direction:10s} {action.filename}")
from aikb import sync, ConflictPolicy
sync(a, b, manifest=m, on_conflict=ConflictPolicy.A_WINS) # local wins
sync(a, b, manifest=m, on_conflict=ConflictPolicy.SKIP) # skip conflicts
sync(a, b, manifest=m, on_conflict=my_resolver_function) # custom callable
Works with plain dicts too — no aikb stores required:
from aikb import push
src = {"readme.md": "# Hello", "notes.md": "..."}
tgt = {}
push(src, tgt) # tgt is now a copy of src
Implement the KnowledgeBaseProvider protocol to add new backends:
from aikb import KnowledgeFiles, KnowledgeBaseProvider
class MyProvider: # no inheritance needed — just implement the methods
def list_files(self, project_id: str): ...
def read_file(self, project_id: str, filename: str) -> str: ...
def upsert_file(self, project_id: str, filename: str, content: str): ...
def delete_file(self, project_id: str, filename: str): ...
store = KnowledgeFiles(MyProvider(), project_id='my-project')
Expose knowledge base CRUD as MCP tools for Claude Desktop, Claude Code, or any MCP-compatible client:
pip install aikb[mcp]
python -m aikb.mcp_server
Tools exposed: list_files, read_file, write_file, delete_file — each
taking platform ("local" or "claude"), project, and file parameters.
aikb stores implement collections.abc.MutableMapping, making them natively
compatible with dol:
pip install aikb[dol]
from dol import wrap_kvs
from aikb import LocalKb
store = wrap_kvs(
LocalKb('/tmp/kb'),
obj_of_data=lambda s: s.upper(), # transforms on read
)
| Extra | Install | Provides |
|---|---|---|
claude | pip install aikb[claude] | Claude Projects via ClaudeSync |
cookies | pip install aikb[cookies] | Auto-extract session keys from browser |
mcp | pip install aikb[mcp] | FastMCP server |
dol | pip install aikb[dol] | dol store transforms |
all | pip install aikb[all] | Everything |
This package ships agent skills you can install into any agent host with
gh skill (don't have it?
install gh):
gh skill install thorwhalen/aikb aikb-setup --agent claude-code
gh skill install thorwhalen/aikb aikb-sync
gh skill install thorwhalen/aikb aikb-maintain
| Skill | Use it when… |
|---|---|
aikb-setup | installing, configuring, or starting to use aikb |
aikb-sync | syncing knowledge files between platforms or directories |
aikb-maintain | maintaining, extending, or debugging aikb |
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
browser-cookie3Environment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | browser-cookie3; extra == "all" | runtime |
claudesyncEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | claudesync; extra == "all" | runtime |
dolEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | dol; extra == "all" | runtime |
fastmcpEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | fastmcp; extra == "all" | runtime |
claudesyncEnvironment{
"extras": "",
"marker": "extra == \"claude\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | claudesync; extra == "claude" | runtime |
browser-cookie3Environment{
"extras": "",
"marker": "extra == \"cookies\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | browser-cookie3; extra == "cookies" | runtime |
pytest-covEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest-cov>=4.0; extra == "dev" | runtime |
pytestEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest>=7.0; extra == "dev" | runtime |
ruffEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | ruff>=0.1.0; extra == "dev" | runtime |
sphinx-rtd-themeEnvironment{
"extras": "",
"marker": "extra == \"docs\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | sphinx-rtd-theme>=1.0; extra == "docs" | runtime |
sphinxEnvironment{
"extras": "",
"marker": "extra == \"docs\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | sphinx>=6.0; extra == "docs" | runtime |
dolEnvironment{
"extras": "",
"marker": "extra == \"dol\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | dol; extra == "dol" | runtime |
fastmcpEnvironment{
"extras": "",
"marker": "extra == \"mcp\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | fastmcp; extra == "mcp" | runtime |
bdist_wheel · 13.65 KB · Python py3
sdist · 41.97 KB · Python source
Observed since 21 Oct, 11:06 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:5a2652cb3c66d2c242f4fbb7c81e9beae6e79580780c0adcd01efd69addec3a9