Skip to content

Namespaces & Cross-Repo Support

ContextFS automatically organizes memories by repository while supporting cross-repo search and project grouping.

Namespace Hierarchy

global
├── repo-abc123 (my-frontend)
│   ├── session-1
│   └── session-2
├── repo-def456 (my-backend)
│   └── session-3
└── repo-ghi789 (shared-lib)

Global Namespace

Memories saved without repo context:

# Outside any git repo
contextfs save "General preference" --type user

Repository Namespace

Auto-detected from git:

cd my-project
contextfs save "Project-specific fact"
# Automatically namespaced to repo-{hash}

Session Namespace

Within a conversation session:

ctx.start_session(label="feature-auth")
ctx.log_message("user", "Implement OAuth")
# Messages scoped to this session

Auto-Detection

ContextFS detects repository context automatically:

ctx = ContextFS()

# Walks up from CWD to find .git
# Sets namespace_id = "repo-{sha256(path)[:12]}"
print(ctx.namespace_id)  # "repo-abc123def456"

Search across all repositories:

# Search only current repo (default)
results = ctx.search("authentication")

# Search all repos
results = ctx.search("authentication", cross_repo=True)

CLI

# Current repo only
contextfs search "auth"

# All repos (coming soon)
contextfs search "auth" --all-repos

MCP Tool

{
  "tool": "contextfs_search",
  "arguments": {
    "query": "authentication patterns",
    "cross_repo": true
  }
}

Project Grouping

Group memories across repos by project:

# In frontend repo
ctx.save(
    "Frontend uses React 18",
    type=MemoryType.DECISION,
    project="my-saas"
)

# In backend repo
ctx.save(
    "Backend uses FastAPI",
    type=MemoryType.DECISION,
    project="my-saas"
)

# Search by project (from any repo)
results = ctx.search("tech stack", project="my-saas")

Source Tracking

Every memory tracks its origin:

memory = Memory(
    content="...",
    source_repo="my-frontend",      # Repo name
    source_file="src/auth/login.ts", # File path
    source_tool="claude-code",       # Creating tool
    project="my-saas",               # Project group
)

List Repositories

repos = ctx.list_repos()
# [{"name": "my-frontend", "namespace_id": "repo-abc123", ...}]

List Projects

projects = ctx.list_projects()
# [{"name": "my-saas", "memory_count": 42, ...}]

List Source Tools

tools = ctx.list_tools()
# ["claude-code", "claude-desktop", "gemini"]

Namespace Isolation

By default, searches are scoped to the current namespace:

# In frontend repo
ctx = ContextFS()  # namespace = "repo-frontend-hash"

# Only finds frontend memories
results = ctx.search("components")

Explicit Namespace

Override the namespace:

ctx = ContextFS(namespace_id="repo-backend-hash")
# Now searches backend repo

Search global namespace only:

ctx = ContextFS(namespace_id="global")

Best Practices

# Consistent project name across repos
ctx.save(content, project="customer-portal")

2. Let Auto-Detection Work

Don't override namespace unless necessary:

# Good: let it auto-detect
ctx = ContextFS()

# Avoid: manual namespace unless needed
ctx = ContextFS(namespace_id="custom-ns")

3. Tag by Scope

Use tags to indicate scope when needed:

ctx.save(
    "Shared authentication library",
    tags=["shared", "auth", "library"]
)

4. Cross-Repo for Discovery

Use cross-repo search to find related work:

# "Have I solved this before?"
results = ctx.search("rate limiting implementation", cross_repo=True)

Data Model

class Namespace(BaseModel):
    id: str              # "repo-abc123" or "global"
    name: str            # Human-readable name
    parent_id: str | None  # Hierarchy support
    repo_path: str | None  # Absolute path
    created_at: datetime
    metadata: dict

    @classmethod
    def for_repo(cls, repo_path: str) -> Namespace:
        repo_id = sha256(repo_path)[:12]
        return cls(
            id=f"repo-{repo_id}",
            name=repo_path.split("/")[-1],
            repo_path=repo_path,
        )