lantern

oculus-client-api

Oculus Client API

Generic API contract for CLI, TUI, and editor clients integrating with Oculus.

Overview

Oculus clients (nvim, emacs, CLI, web) all share a common API surface. This document describes the contract and patterns for building clients that interact with fences, nodes, and the knowledge graph.

Base URL: http://localhost:7778

Core Concepts

Fence Addressing

Fences can be addressed in multiple formats:

Format Example Resolution
Direct ID my-node-fence-0 Exact fence ID
Label magic-8-ball Global label lookup
Slug:Index my-node:0 Node slug + fence position
Slug:Label my-node:config Node slug + fence label

CLI Pattern: Accept any format, resolve transparently.

Execution Lifecycle

1. DISCOVER  →  List/search fences
2. INSPECT   →  Get fence shape/params
3. EXECUTE   →  Run with params
4. FORMAT    →  Display result per output type

API Endpoints

Fence Discovery

List All Fences

GET /api/oculus/fences
GET /api/oculus/fences?type=python
GET /api/oculus/fences?slug=my-node
GET /api/oculus/fences?tags=aws,infrastructure

Returns:

{
  "count": 42,
  "fences": [
    {
      "id": "my-node-fence-0",
      "slug": "my-node",
      "type": "python",
      "label": "magic-8-ball",
      "section": "Tools",
      "line": 42,
      "execute": true,
      "tags": ["tool", "fun"],
      "attributes": {"service": "oracle"}
    }
  ]
}

Node-Scoped Fences

GET /api/oculus/nodes/{slug}/fences

Returns fences for a specific node (useful for cursor-aware tooling).

Fence Inspection

Get Fence Metadata

GET /api/oculus/fences/{fence_id}

Returns fence details including content, position, attributes.

Get Parameter Schema

GET /api/oculus/fences/{fence_id}/params

Returns structured parameter schema:

{
  "fence_id": "magic-8-ball",
  "params": [
    {
      "name": "question",
      "type": "string",
      "description": "Question to ask the oracle",
      "optional": false
    }
  ],
  "required": ["question"],
  "optional": [],
  "example_call": {
    "fence_id": "magic-8-ball",
    "params": { "question": "<string>" }
  }
}

Fence Execution

POST /api/oculus/fences/{fence_id}/execute
Content-Type: application/json

{
  "action": "optional-action-name",
  "params": { "question": "Should I deploy?" },
  "format": "json|yaml|markdown|text|raw",
  "force": false,
  "context": "CLI execution from terminal"
}

Returns:

{
  "success": true,
  "fence_id": "magic-8-ball",
  "data": { "answer": "Signs point to yes" },
  "formatted": "Signs point to yes",
  "metadata": {
    "execution_time_ms": 42,
    "output_type": "text/plain"
  }
}

Client Implementation Patterns

Pattern 1: Fuzzy Match → Auto-Execute

User types: o fence theme
Client:
  1. GET /api/oculus/fences → filter by "theme"
  2. If exactly 1 match → execute it
  3. If multiple → show picker
  4. If 0 matches → error

Pattern 2: Params-Aware Execution

User executes fence with required params:
  1. GET /api/oculus/fences/{id}/params
  2. If has required params with no values:
     a. TUI/Editor: show interactive prompts
     b. CLI: show error with expected params
  3. POST execute with filled params

Pattern 3: Output Format Detection

The API returns metadata.output_type (MIME-like):

Output Type CLI Rendering
application/json JSON pretty-print or jq
text/yaml YAML pretty-print
text/markdown glow rendering
text/plain Raw output
text/x-ansi Direct to terminal (colors)

Clients SHOULD respect this for formatting.

Pattern 4: Wildcard/Pattern Matching

CLI conventions for pattern matching:

Pattern Meaning Example
theme Substring match Matches themes, daily-themes
^theme Prefix match Only theme*
theme$ Suffix match Only *theme
daily.theme Dotted path daily node, theme fence

Avoid shell metacharacters (*, ?) that require quoting.

CLI Command Structure

Recommended CLI patterns:

# Discovery
oculus fence                    # List all fences (table)
oculus fence theme              # Filter by pattern
oculus fence --type python      # Filter by type
oculus fence --node my-node     # Filter by node

# Inspection  
oculus fence-info magic-8-ball  # Show fence details + params
oculus fence-params themes      # Just params schema

# Execution
oculus exec magic-8-ball        # Execute (prompts if params needed)
oculus exec magic-8-ball --question "Deploy?"  # With param
oculus exec daily:0 --format yaml  # By slug:index

# Combined (intelligent)
oculus fence theme              # If 1 match: show info
oculus exec theme               # If 1 match: execute it

TUI/Editor Features

Fence Shape Display

When showing fence info, display:

Fence: magic-8-ball [python]
Node:  daily-standup
Line:  42
Tags:  tool, fun

Params:
  * question (string): Question to ask

Interactive Param Collection

For TUI/editors, collect params one at a time:

question (Question to ask): █

Result Panes

Results should open in dedicated panes/buffers:

  • Reuse existing result pane if present
  • Name buffer by fence ID for identification
  • Set filetype based on output format

Error Handling

Fence Not Found

{ "detail": "Fence not found: unknown-fence" }

Client: Show helpful message suggesting similar fences (fuzzy match).

Missing Required Params

{ "detail": "Missing required params: question" }

Client: Show params schema and prompt for values.

Execution Error

{
  "success": false,
  "error": "Python execution failed: NameError...",
  "traceback": "..."
}

Client: Display error clearly, preserve traceback for debugging.

See Also

Slots

North

slots: []

South

slots: []

West

slots:
- context:
  - Client API builds on fence params schema
  slug: fence-params
- context:
  - Client API builds on fence params
  slug: fence-params

East

slots:
- slug: neovim-wanderland
  context:
  - Neovim is a reference implementation of this client API
→ eastneovim-wanderland
← westfence-params