Metadata-Version: 2.4
Name: optulus
Version: 0.1.0
Summary: Offline code context indexing and retrieval tool.
Author: kwangyel
Project-URL: Homepage, https://optulus.com
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13
Requires-Dist: tree-sitter>=0.21
Requires-Dist: tree-sitter-python>=0.21
Requires-Dist: tree-sitter-typescript>=0.21
Requires-Dist: tree-sitter-javascript>=0.21
Requires-Dist: tree-sitter-go>=0.21
Requires-Dist: tree-sitter-rust>=0.21
Requires-Dist: sentence-transformers>=3
Requires-Dist: transformers<5,>=4.41
Requires-Dist: qdrant-client>=1.9
Requires-Dist: tiktoken>=0.7
Requires-Dist: toml>=0.10
Requires-Dist: mcp>=1.0
Requires-Dist: pytest>=8.0
Requires-Dist: watchdog>=4.0
Requires-Dist: pathspec>=0.12
Requires-Dist: numpy<2,>=1.26
Dynamic: license-file

# Optulus

Optulus (`cf`) is an offline-first Python CLI that indexes a repository into a local graph and returns minimal task-specific context with one query.

## Install

```bash
pip install optulus
```

For local development in this repo:

```bash
pip install -e .
```

## Quick Start (5 minutes)

```bash
cf index ./your-project
cd ./your-project
cf context "add rate limiting to auth middleware"
cf stats
```

The SQLite index and Qdrant files live **inside the repository you index**: `<path>/.cf/` (not in the Optulus install directory). Commands like `cf context` and `cf stats` look for `.cf/index.db` in the **current working directory**, so run them from that same repo root (or pass `.` after `cd` there).

## Commands

- `cf index <path>`: write `<path>/.cf/index.db` and `<path>/.cf/qdrant/`
- `cf index <path> --watch`: watch for changes and re-index automatically
- `cf index <path> --langs python,typescript`: limit indexed languages
- `cf index <path> --reset`: rebuild from scratch
- `cf context "<task>" --top 20 --max-tokens 8000`: retrieve ranked context
- `cf context "<task>" --json`: output JSON only to stdout
- `cf stats [--since 7d]`: show usage and token savings
- `cf serve [--transport stdio|sse|streamable-http] [--host 127.0.0.1] [--port 8765] [--auto-index|--no-auto-index]`: MCP server (default **stdio**; auto-builds `.cf/` on start unless disabled; `--port` only for HTTP transports). More detail: [docs/claude-code.md](docs/claude-code.md).

## Claude Code (MCP)

Optulus exposes MCP tools: **`get_context`**, **`get_file`**, **`get_symbol`**, and optional **`record_outcome`**. On startup the server **indexes the repo automatically** (unless you pass **`--no-auto-index`** or set **`CONTEXTFORGE_AUTO_INDEX=0`**). You can still run **`cf index`** or **`cf index --watch`** yourself for manual or continuous re-indexing.

The repo root is resolved from **`CONTEXTFORGE_REPO_ROOT`**, or by walking **up** from `cwd` for `.cf/index.db`, or else **`cwd`**. Set **`CONTEXTFORGE_REPO_ROOT`** if the MCP process starts with the wrong working directory (some global or user-scoped setups).

### Add the MCP server in Claude Code

Merge an `optulus` entry into `mcpServers` (exact file or UI path depends on your Claude Code version). **`cwd`** should be the project root when the client does not already use it.

**Using the `cf` CLI** (recommended if `cf` is on `PATH` for the MCP child process):

```json
{
  "mcpServers": {
    "optulus": {
      "command": "cf",
      "args": ["serve", "--transport", "stdio"],
      "cwd": "/absolute/path/to/your-project",
      "env": {
        "PYTHONUNBUFFERED": "1"
      }
    }
  }
}
```

**Using Python** (if `cf` is not visible to the MCP subprocess but Optulus is installed in that interpreter):

```json
{
  "mcpServers": {
    "optulus": {
      "command": "python3",
      "args": ["-m", "contextforge.mcp", "--transport", "stdio"],
      "cwd": "/absolute/path/to/your-project",
      "env": {
        "PYTHONUNBUFFERED": "1"
      }
    }
  }
}
```

### Optional: Claude Code plugin

A plugin skeleton lives under [`.claude-plugin/`](.claude-plugin/) in this repo (`plugin.json`, `mcp.json`, and a skill). Prefer **project-scoped** installation so `cwd` matches the repository; see [docs/claude-code.md](docs/claude-code.md).

### Use the tools in a session

1. Call **`get_context`** with a concrete task string. You receive ranked nodes and a JSON **`context_block`** sized with `max_tokens`.
2. Use **`get_file`** or **`get_symbol`** to drill into paths or names from those results.
3. Optionally call **`record_outcome`** with the **`session_id`** returned by `get_context` after a turn.

Prefer these tools for code exploration instead of reading large files blindly. The server also sends **instructions** in the MCP handshake.

### Notes

- **Switching projects:** Point `cwd` (or `CONTEXTFORGE_REPO_ROOT`) at each repo’s root, or add another MCP entry with a different name.
- **SSE / HTTP:** For network transports, run `cf serve --transport sse --port 8765` (or `streamable-http`); see [docs/claude-code.md](docs/claude-code.md).

## Design Constraints

- Python 3.11+
- Local-only persistence: SQLite and in-process Qdrant
- No LLM calls in indexer/query engine
- Rich-based CLI output (stderr for status/progress)

## Output Example

`cf context` prints ranked nodes, token estimate, baseline estimate (12,000 tokens), and computed savings, plus a ready-to-paste JSON context block.
