Documentation Index
Fetch the complete documentation index at: https://docs.feral.sh/llms.txt
Use this file to discover all available pages before exploring further.
Base URL
http://localhost:9090/api
All endpoints require the brain to be running (feral start). Responses are JSON.
Dashboard
| Method | Path | Description |
|---|
GET | /api/dashboard/status | Brain status, uptime, connected devices |
GET | /api/dashboard/context | Current context window (health, scene, calendar) |
GET | /api/dashboard/timeline | Recent events and conversations |
POST | /api/dashboard/command | Send a text command to the brain |
Example: Send a command
curl -X POST http://localhost:9090/api/dashboard/command \
-H "Content-Type: application/json" \
-d '{ "text": "What is my heart rate?" }'
{
"response": "Your heart rate is 72 bpm, measured 3 seconds ago from your wristband.",
"sdui": null,
"sources": ["wristband_a3f2"]
}
Skills
| Method | Path | Description |
|---|
GET | /api/skills | List all registered skills |
GET | /api/skills/:id | Get skill manifest and status |
POST | /api/skills/:id/execute | Manually trigger a skill |
POST | /api/skills/install | Install a skill from URL or local path |
DELETE | /api/skills/:id | Uninstall a skill |
Example: List skills
curl http://localhost:9090/api/skills
{
"skills": [
{ "id": "weather", "name": "Weather", "version": "1.2.0", "status": "active" },
{ "id": "calendar", "name": "Google Calendar", "version": "2.0.1", "status": "active" },
{ "id": "smart_home", "name": "Smart Home Control", "version": "1.0.0", "status": "active" }
]
}
Memory
| Method | Path | Description |
|---|
GET | /api/memory/episodes | List episodic memories (paginated) |
GET | /api/memory/search | Semantic search across all memory tiers |
POST | /api/memory/note | Store a note in the knowledge base |
GET | /api/memory/knowledge | Query the knowledge graph |
DELETE | /api/memory/episodes/:id | Delete a specific episode |
Example: Semantic search
curl "http://localhost:9090/api/memory/search?q=last+time+I+went+running&limit=5"
{
"results": [
{
"id": "ep_2026_0410_morning",
"timestamp": "2026-04-10T07:15:00Z",
"summary": "Morning 5K run in Prospect Park. Avg HR 145 bpm, pace 5:20/km.",
"relevance": 0.94
}
]
}
Identity
| Method | Path | Description |
|---|
GET | /api/identity/user | Get current USER.md content |
PUT | /api/identity/user | Update USER.md |
GET | /api/identity/soul | Get SOUL.md (system persona) |
GET | /api/identity/twin | Query the digital twin |
POST | /api/identity/twin/ask | Ask the digital twin a question |
Example: Ask the digital twin
curl -X POST http://localhost:9090/api/identity/twin/ask \
-H "Content-Type: application/json" \
-d '{ "question": "Would I enjoy this job offer?" }'
{
"answer": "Based on your preference for remote work, interest in systems programming, and past dissatisfaction with large-company bureaucracy, this startup role aligns well. However, the on-call rotation conflicts with your sleep optimization goals.",
"confidence": 0.82
}
Devices & Hardware
| Method | Path | Description |
|---|
GET | /api/devices/connected | List all connected devices with types and metrics |
GET | /api/devices/paired | List paired devices (claimed by default; include_unclaimed=true optional) |
POST | /api/devices/pair | Mint daemon/browser pairing token |
GET | /api/devices/pair/url | Mint one-time pair URL payload |
GET | /api/devices/pair/qr | Render pair payload as QR image |
GET | /api/devices/pair/check | Check token state (and PIN requirement) |
POST | /api/devices/pair/verify_pin | Verify pairing PIN |
POST | /api/devices/pair/complete | Complete phone/browser pairing |
POST | /api/devices/pair/prune | Revoke unclaimed tokens in bulk |
POST | /api/devices/handoff | Initiate a session handoff between devices |
DELETE | /api/devices/{device_id} | Revoke (un-pair) a device |
GET | /api/nodes/health | All node health status with heartbeat freshness |
GET | /api/commands/recent | Recent commands with full lifecycle state |
GET | /api/commands/{command_id} | Single command detail including state history |
POST | /api/proactive/dismiss | Dismiss a proactive alert (learns from it) |
Access Mode & Remote Reachability
| Method | Path | Description |
|---|
GET | /api/access/status | Current pairing mode + Tailscale/Funnel status |
POST | /api/access/remote-up | Enable remote mode and Tailscale Funnel |
POST | /api/access/remote-down | Disable remote mode and return to localhost mode |
Approvals (Execution Inbox)
The approval inbox lets a non-chat client (web UI, CLI, mobile, automation) resolve pending tool-execution approvals without having to type an acknowledgement into a chat session. A pending request is created by the orchestrator whenever enforce_safety() blocks a tool call (see Autonomy Levels).
| Method | Path | Description |
|---|
GET | /api/approvals | List pending tool-approval requests. Optional query params: session_id (filter), limit (1–500, default 100). |
POST | /api/approvals/{request_id}/approve | Approve a pending request and execute the tool. |
POST | /api/approvals/{request_id}/reject | Reject a pending request without executing. |
Both approve and reject accept an optional JSON body:
{ "session_id": "s-abc123" }
When session_id is provided it must match the session that originated the request, or the call returns 409 session_mismatch.
Example: list pending approvals
curl "http://localhost:9090/api/approvals?session_id=s-abc123&limit=50"
{
"count": 1,
"approvals": [
{
"request_id": "apr_01HXYZ...",
"session_id": "s-abc123",
"tool_name": "browser__navigate",
"args": { "url": "https://example.com" },
"safety_level": "privileged",
"created_at": 1746230412.81,
"status": "pending"
}
]
}
Example: approve
curl -X POST "http://localhost:9090/api/approvals/apr_01HXYZ.../approve" \
-H "Content-Type: application/json" \
-d '{ "session_id": "s-abc123" }'
{
"success": true,
"status": "approved",
"request_id": "apr_01HXYZ...",
"session_id": "s-abc123",
"tool_name": "browser__navigate",
"summary": "Navigated to https://example.com",
"result": { "ok": true }
}
Example: reject
curl -X POST "http://localhost:9090/api/approvals/apr_01HXYZ.../reject" \
-H "Content-Type: application/json" \
-d '{ "session_id": "s-abc123" }'
{
"success": true,
"status": "rejected",
"request_id": "apr_01HXYZ...",
"session_id": "s-abc123",
"tool_name": "browser__navigate"
}
Status codes
| Code | Meaning |
|---|
200 | Resolved (approved or rejected). |
404 | Unknown request_id (already resolved, expired, or never existed). |
409 | session_mismatch — supplied session_id does not match the pending request. |
503 | Orchestrator or tool runner not initialised yet. |
Channels
| Method | Path | Description |
|---|
GET | /api/channels | List all channel statuses |
GET | /api/channels/:name/status | Status of a specific channel (telegram, slack, etc.) |
POST | /api/channels/push/register | Register a push notification device token |
GET | /api/channels/push/devices | List registered push devices |
DELETE | /api/channels/push/devices/:id | Unregister a push device |
POST | /api/channels/push/test | Send a test push notification |
All errors follow a consistent shape:
{
"error": {
"code": "NOT_FOUND",
"message": "Skill 'invalid_id' not found.",
"details": null
}
}
| HTTP Code | Meaning |
|---|
400 | Bad request — invalid parameters |
401 | Unauthorized — missing or invalid token |
404 | Resource not found |
409 | Conflict — device already paired, skill already installed |
500 | Internal brain error |