Skip to content

Repository files navigation

SLOP — State Layer for Observable Programs

SLOP is a protocol that lets AI observe and interact with application state directly — no screenshots, no scraping, no blind tool calls.

Applications expose a semantic state tree that AI can subscribe to, query at variable depth, and act on through contextual affordances. It is the missing perception layer between AI and the software it operates.

slop_demo.mov

An AI agent observing state, invoking actions, and updating the UI in real time. Run it yourself: bun run demo

Why

Today, AI interacts with applications through two extremes:

  • Vision (screenshots) — expensive, lossy, fragile. The AI parses pixels to recover information the app already had in structured form.
  • Tool calls / MCP — the AI can act, but it's flying blind. It calls functions without knowing what the user is currently looking at or what the app's state is. Every observation requires a dedicated tool.

SLOP fills the gap: a standard way for apps to publish what they are so AI can see before it acts.

Core ideas

  1. State tree — Apps expose a tree of semantic nodes (not UI elements, not raw data models — meaning). Each node has an identity, properties, and optional children.

  2. Subscriptions and patches — AI subscribes to subtrees at a chosen depth. The app pushes incremental patches (JSON Patch) as state changes. No polling, no redundant full reads.

  3. Contextual affordances — Actions live on the nodes they affect, not in a global tool registry. The AI sees what it can do in context — "reply" appears on a message node, "merge" appears on a PR node.

  4. Attention hints — Apps signal what matters right now: salience scores, change flags, user focus. The AI doesn't have to scan the entire tree to find what's relevant.

  5. Progressive disclosure — The tree supports variable-depth queries. Top-level gives a summary. Drilling in gives detail. Large collections are windowed with summaries.

How it differs from existing approaches

MCP / Tool callsAccessibility APIsSLOP
Primary purposeAI actsScreen readers read UIAI perceives + acts
Data modelFlat list of functionsUI element treeSemantic state tree
DirectionPull (AI calls tools)Pull (reader queries)Push-first (app publishes)
ActionsGlobal tool registryLimited (click, type)Contextual affordances on nodes
Designed forLLM function callingSequential text navigationAI state comprehension

Quick start

bun add @slop-ai/client @slop-ai/react
import{createSlop}from"@slop-ai/client";import{action,useSlop}from"@slop-ai/react";constslop=createSlop({id: "my-app",name: "My App"});functionTaskList({ tasks }){useSlop(slop,"tasks",()=>({type: "collection",props: {count: tasks.length},items: tasks.map(t=>({id: t.id,props: {title: t.title,done: t.done},actions: {toggle: action(()=>toggleTask(t.id)),delete: action(()=>deleteTask(t.id),{dangerous: true}),},})),}));return<ul>{tasks.map(t=><likey={t.id}>{t.title}</li>)}</ul>;}

That's it. Your component is now observable by any SLOP consumer — the Chrome extension, a desktop agent, or a custom AI integration.

Spec

The full specification is in spec/:

Core protocol

  1. Overview & Concepts
  2. State Tree
  3. Transport & Discovery
  4. Message Protocol
  5. Affordances
  6. Attention & Salience

Extensions

Integration guides

Status and limits

SDK guides

Guides

Benchmarks

The benchmarks/mcp-vs-slop suite compares SLOP and MCP head-to-head using an identical backing application (issue tracker). An LLM agent performs 12 scenarios through each protocol, measuring correctness, tool calls, latency, and cost.

Key findings:

  • Correctness: SLOP passes 12/12 scenarios. MCP passes 8/12 — fails on scale (discovery budget exhaustion), safety (can't prevent invalid actions on closed issues), and complex reasoning (can't aggregate state across repos).
  • Contextual affordances prevent invalid actions by design. MCP's flat tool list always exposes assign_issue regardless of issue state. SLOP only shows actions valid for the current state.
  • SLOP uses 75-90% fewer LLM round trips on multi-entity tasks by front-loading state. The agent batches all actions in 2 turns instead of 8-21 discovery-then-act turns.
  • Cost tradeoff is real. SLOP's state tree uses more input tokens. For simple tasks MCP is cheaper. For complex tasks requiring cross-entity reasoning, SLOP is cheaper and correct where MCP fails.

Full results and methodology: Benchmarks: MCP vs SLOP

SDKs

LanguagePackageInstall
TypeScript@slop-ai/corebun add @slop-ai/core
Browser@slop-ai/clientbun add @slop-ai/client
React@slop-ai/reactbun add @slop-ai/react
Vue@slop-ai/vuebun add @slop-ai/vue
Solid@slop-ai/solidbun add @slop-ai/solid
Angular@slop-ai/angularbun add @slop-ai/angular
Svelte@slop-ai/sveltebun add @slop-ai/svelte
Server (Node/Bun)@slop-ai/serverbun add @slop-ai/server
Consumer@slop-ai/consumerbun add @slop-ai/consumer
TanStack Start@slop-ai/tanstack-startbun add @slop-ai/tanstack-start
Discovery@slop-ai/discoverybun add @slop-ai/discovery
OpenClaw@slop-ai/openclaw-pluginbun add @slop-ai/openclaw-plugin
Codexslop plugincp -r packages/typescript/integrations/codex/slop ~/.codex/plugins/slop
Pythonslop-aipip install slop-ai
Rustslop-aicargo add slop-ai
Goslop-aigo get github.com/devteapot/slop/packages/go/slop-ai

Project structure

slop/
├── spec/ # Protocol specification
├── mcp-seps/ # Draft MCP SEPs related to SLOP
├── docs/sdk/ # SDK architecture & implementation guides
├── packages/
│ ├── typescript/
│ │ ├── sdk/
│ │ │ ├── core/ # @slop-ai/core — types, tree assembly, diffing
│ │ │ ├── client/ # @slop-ai/client — browser provider (postMessage)
│ │ │ ├── server/ # @slop-ai/server — server provider (WebSocket, Unix, stdio)
│ │ │ └── consumer/ # @slop-ai/consumer — connect, subscribe, invoke
│ │ ├── adapters/
│ │ │ ├── react/ # @slop-ai/react — useSlop hook
│ │ │ ├── vue/ # @slop-ai/vue — useSlop composable
│ │ │ ├── solid/ # @slop-ai/solid — useSlop primitive
│ │ │ ├── angular/ # @slop-ai/angular — useSlop with signals
│ │ │ ├── svelte/ # @slop-ai/svelte — useSlop for Svelte 5 runes
│ │ │ └── tanstack-start/ # @slop-ai/tanstack-start — SSR adapter
│ │ └── integrations/
│ │ ├── discovery/ # @slop-ai/discovery — bridge/discovery primitives with /service and /tools entrypoints
│ │ ├── claude/ # Claude Code plugins (native + MCP proxy)
│ │ ├── codex/ # Codex plugin (MCP bridge + skill)
│ │ └── openclaw-plugin/ # @slop-ai/openclaw-plugin — OpenClaw integration
│ ├── python/slop-ai/ # Python SDK
│ ├── rust/slop-ai/ # Rust SDK
│ └── go/slop-ai/ # Go SDK
├── apps/
│ ├── extension/ # Chrome extension (SLOP consumer + AI chat)
│ ├── desktop/ # Tauri desktop app
│ └── cli/ # Go CLI inspector
├── benchmarks/
│ └── mcp-vs-slop/ # MCP vs SLOP benchmark suite
├── examples/
│ ├── cli/ # Task manager CLI in 4 languages (Bun, Python, Go, Rust)
│ ├── spa/ # Client-only kanban board across 5 frameworks
│ │ ├── react/
│ │ ├── vue/
│ │ ├── solid/
│ │ ├── svelte/
│ │ └── angular/
│ ├── desktop/ # Pomodoro desktop provider (same blueprint, multiple stacks)
│ │ ├── typescript/ # Electron (JS main/renderer) + Unix socket provider
│ │ ├── python/
│ │ ├── go/
│ │ └── rust/ # Tauri
│ └── full-stack/
│ ├── tanstack-start/ # TanStack Start — server + UI mount
│ └── python-react/ # Python FastAPI + React — cross-SDK
└── website/
├── landing/ # slopai.dev landing page
├── docs/ # docs.slopai.dev documentation
├── demo/ # demo.slopai.dev interactive demo
└── playground/ # playground.slopai.dev

Examples

Each example follows a blueprint — a language-agnostic spec defining the exact SLOP tree, affordances, and test scenarios. Multiple implementations of the same blueprint prove cross-language consistency.

  • Interactive Demo — Three-panel demo: e-commerce store + AI agent + live state tree. Run with bun run demo. Replay mode works without an API key; connect one for interactive mode.
  • CLI Task Managertsk, a task manager with a --slop flag. Implementations in Bun, Python, Go, and Rust.
  • SPA Kanban Board — Canonical client-only example, implemented in React, Vue, Solid, Svelte, and Angular from the same blueprint.
  • TanStack Start — Full-stack web app with server-side SLOP via WebSocket.
  • Python + React — Python FastAPI backend + React SPA frontend. Cross-SDK integration with two independent providers.
  • Desktop Pomodoro (TypeScript) — Electron app as a SLOP provider (Unix socket + ~/.slop/providers/). Implementations also exist in Python, Go, and Rust/Tauri.

Known limitations

SLOP v0.2.0 is designed to be useful now while leaving room to grow. Key limitations:

  • Multi-user apps — Server-side providers currently expose one shared tree to all consumers. The protocol already supports per-user state (each connection is independent), but the SDKs don't implement session-scoped tree rendering yet. Client-only SPAs are unaffected — each tab is its own provider. See Sessions & Multi-User.
  • No reconnection — If a WebSocket drops, the consumer must re-connect and re-subscribe from scratch. No automatic reconnect or version-based catch-up.
  • No backpressurepause/resume messages are mentioned in the spec but not defined. Providers should debounce rapid changes (50-100ms).
  • No LAN discovery — Local discovery is shipped (~/.slop/providers/, /tmp/slop/providers/, browser meta tags, and /.well-known/slop), but mDNS/DNS-SD for remote providers is still reserved and unspecified.

Full list: Known Limitations & Future Work

Current status

v0.2.0 (25 Apr 2026) includes:

  • Core protocol docs plus scaling, content-reference, and async-action extensions
  • TypeScript SDKs, framework adapters, and @slop-ai/discovery
  • Python, Go, and Rust SDKs with discovery parity
  • Chrome extension, desktop app, CLI, and MCP Apps bridge
  • Examples, benchmarks, and OpenClaw integration

SLOP sits beside MCP. It does not replace it.

Roadmap

Protocol

  • Backpressure (pause/resume flow control)
  • Network discovery (mDNS/DNS-SD)
  • Ancestor retention for salience filtering
  • Binary encoding (optional MessagePack/CBOR)

SDKs

  • Session-scoped trees (multi-user server apps)
  • Automatic reconnection with version catch-up
  • Typed affordance results
  • Consumer-side tree composition (merge multiple providers)

Product

  • Firefox extension
  • Safari extension
  • Agent CLI (npx @slop-ai/init)
  • Extension per-site toggles

License

MIT

About

A protocol for AI to observe and interact with application state

Topics

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - devteapot/slop: A protocol for AI to observe and interact with application state · GitHub
Skip to content

Repository files navigation

SLOP — State Layer for Observable Programs

SLOP is a protocol that lets AI observe and interact with application state directly — no screenshots, no scraping, no blind tool calls.

Applications expose a semantic state tree that AI can subscribe to, query at variable depth, and act on through contextual affordances. It is the missing perception layer between AI and the software it operates.

slop_demo.mov

An AI agent observing state, invoking actions, and updating the UI in real time. Run it yourself: bun run demo

Why

Today, AI interacts with applications through two extremes:

  • Vision (screenshots) — expensive, lossy, fragile. The AI parses pixels to recover information the app already had in structured form.
  • Tool calls / MCP — the AI can act, but it's flying blind. It calls functions without knowing what the user is currently looking at or what the app's state is. Every observation requires a dedicated tool.

SLOP fills the gap: a standard way for apps to publish what they are so AI can see before it acts.

Core ideas

  1. State tree — Apps expose a tree of semantic nodes (not UI elements, not raw data models — meaning). Each node has an identity, properties, and optional children.

  2. Subscriptions and patches — AI subscribes to subtrees at a chosen depth. The app pushes incremental patches (JSON Patch) as state changes. No polling, no redundant full reads.

  3. Contextual affordances — Actions live on the nodes they affect, not in a global tool registry. The AI sees what it can do in context — "reply" appears on a message node, "merge" appears on a PR node.

  4. Attention hints — Apps signal what matters right now: salience scores, change flags, user focus. The AI doesn't have to scan the entire tree to find what's relevant.

  5. Progressive disclosure — The tree supports variable-depth queries. Top-level gives a summary. Drilling in gives detail. Large collections are windowed with summaries.

How it differs from existing approaches

MCP / Tool callsAccessibility APIsSLOP
Primary purposeAI actsScreen readers read UIAI perceives + acts
Data modelFlat list of functionsUI element treeSemantic state tree
DirectionPull (AI calls tools)Pull (reader queries)Push-first (app publishes)
ActionsGlobal tool registryLimited (click, type)Contextual affordances on nodes
Designed forLLM function callingSequential text navigationAI state comprehension

Quick start

bun add @slop-ai/client @slop-ai/react
import{createSlop}from"@slop-ai/client";import{action,useSlop}from"@slop-ai/react";constslop=createSlop({id: "my-app",name: "My App"});functionTaskList({ tasks }){useSlop(slop,"tasks",()=>({type: "collection",props: {count: tasks.length},items: tasks.map(t=>({id: t.id,props: {title: t.title,done: t.done},actions: {toggle: action(()=>toggleTask(t.id)),delete: action(()=>deleteTask(t.id),{dangerous: true}),},})),}));return<ul>{tasks.map(t=><likey={t.id}>{t.title}</li>)}</ul>;}

That's it. Your component is now observable by any SLOP consumer — the Chrome extension, a desktop agent, or a custom AI integration.

Spec

The full specification is in spec/:

Core protocol

  1. Overview & Concepts
  2. State Tree
  3. Transport & Discovery
  4. Message Protocol
  5. Affordances
  6. Attention & Salience

Extensions

Integration guides

Status and limits

SDK guides

Guides

Benchmarks

The benchmarks/mcp-vs-slop suite compares SLOP and MCP head-to-head using an identical backing application (issue tracker). An LLM agent performs 12 scenarios through each protocol, measuring correctness, tool calls, latency, and cost.

Key findings:

  • Correctness: SLOP passes 12/12 scenarios. MCP passes 8/12 — fails on scale (discovery budget exhaustion), safety (can't prevent invalid actions on closed issues), and complex reasoning (can't aggregate state across repos).
  • Contextual affordances prevent invalid actions by design. MCP's flat tool list always exposes assign_issue regardless of issue state. SLOP only shows actions valid for the current state.
  • SLOP uses 75-90% fewer LLM round trips on multi-entity tasks by front-loading state. The agent batches all actions in 2 turns instead of 8-21 discovery-then-act turns.
  • Cost tradeoff is real. SLOP's state tree uses more input tokens. For simple tasks MCP is cheaper. For complex tasks requiring cross-entity reasoning, SLOP is cheaper and correct where MCP fails.

Full results and methodology: Benchmarks: MCP vs SLOP

SDKs

LanguagePackageInstall
TypeScript@slop-ai/corebun add @slop-ai/core
Browser@slop-ai/clientbun add @slop-ai/client
React@slop-ai/reactbun add @slop-ai/react
Vue@slop-ai/vuebun add @slop-ai/vue
Solid@slop-ai/solidbun add @slop-ai/solid
Angular@slop-ai/angularbun add @slop-ai/angular
Svelte@slop-ai/sveltebun add @slop-ai/svelte
Server (Node/Bun)@slop-ai/serverbun add @slop-ai/server
Consumer@slop-ai/consumerbun add @slop-ai/consumer
TanStack Start@slop-ai/tanstack-startbun add @slop-ai/tanstack-start
Discovery@slop-ai/discoverybun add @slop-ai/discovery
OpenClaw@slop-ai/openclaw-pluginbun add @slop-ai/openclaw-plugin
Codexslop plugincp -r packages/typescript/integrations/codex/slop ~/.codex/plugins/slop
Pythonslop-aipip install slop-ai
Rustslop-aicargo add slop-ai
Goslop-aigo get github.com/devteapot/slop/packages/go/slop-ai

Project structure

slop/
├── spec/ # Protocol specification
├── mcp-seps/ # Draft MCP SEPs related to SLOP
├── docs/sdk/ # SDK architecture & implementation guides
├── packages/
│ ├── typescript/
│ │ ├── sdk/
│ │ │ ├── core/ # @slop-ai/core — types, tree assembly, diffing
│ │ │ ├── client/ # @slop-ai/client — browser provider (postMessage)
│ │ │ ├── server/ # @slop-ai/server — server provider (WebSocket, Unix, stdio)
│ │ │ └── consumer/ # @slop-ai/consumer — connect, subscribe, invoke
│ │ ├── adapters/
│ │ │ ├── react/ # @slop-ai/react — useSlop hook
│ │ │ ├── vue/ # @slop-ai/vue — useSlop composable
│ │ │ ├── solid/ # @slop-ai/solid — useSlop primitive
│ │ │ ├── angular/ # @slop-ai/angular — useSlop with signals
│ │ │ ├── svelte/ # @slop-ai/svelte — useSlop for Svelte 5 runes
│ │ │ └── tanstack-start/ # @slop-ai/tanstack-start — SSR adapter
│ │ └── integrations/
│ │ ├── discovery/ # @slop-ai/discovery — bridge/discovery primitives with /service and /tools entrypoints
│ │ ├── claude/ # Claude Code plugins (native + MCP proxy)
│ │ ├── codex/ # Codex plugin (MCP bridge + skill)
│ │ └── openclaw-plugin/ # @slop-ai/openclaw-plugin — OpenClaw integration
│ ├── python/slop-ai/ # Python SDK
│ ├── rust/slop-ai/ # Rust SDK
│ └── go/slop-ai/ # Go SDK
├── apps/
│ ├── extension/ # Chrome extension (SLOP consumer + AI chat)
│ ├── desktop/ # Tauri desktop app
│ └── cli/ # Go CLI inspector
├── benchmarks/
│ └── mcp-vs-slop/ # MCP vs SLOP benchmark suite
├── examples/
│ ├── cli/ # Task manager CLI in 4 languages (Bun, Python, Go, Rust)
│ ├── spa/ # Client-only kanban board across 5 frameworks
│ │ ├── react/
│ │ ├── vue/
│ │ ├── solid/
│ │ ├── svelte/
│ │ └── angular/
│ ├── desktop/ # Pomodoro desktop provider (same blueprint, multiple stacks)
│ │ ├── typescript/ # Electron (JS main/renderer) + Unix socket provider
│ │ ├── python/
│ │ ├── go/
│ │ └── rust/ # Tauri
│ └── full-stack/
│ ├── tanstack-start/ # TanStack Start — server + UI mount
│ └── python-react/ # Python FastAPI + React — cross-SDK
└── website/
├── landing/ # slopai.dev landing page
├── docs/ # docs.slopai.dev documentation
├── demo/ # demo.slopai.dev interactive demo
└── playground/ # playground.slopai.dev

Examples

Each example follows a blueprint — a language-agnostic spec defining the exact SLOP tree, affordances, and test scenarios. Multiple implementations of the same blueprint prove cross-language consistency.

  • Interactive Demo — Three-panel demo: e-commerce store + AI agent + live state tree. Run with bun run demo. Replay mode works without an API key; connect one for interactive mode.
  • CLI Task Managertsk, a task manager with a --slop flag. Implementations in Bun, Python, Go, and Rust.
  • SPA Kanban Board — Canonical client-only example, implemented in React, Vue, Solid, Svelte, and Angular from the same blueprint.
  • TanStack Start — Full-stack web app with server-side SLOP via WebSocket.
  • Python + React — Python FastAPI backend + React SPA frontend. Cross-SDK integration with two independent providers.
  • Desktop Pomodoro (TypeScript) — Electron app as a SLOP provider (Unix socket + ~/.slop/providers/). Implementations also exist in Python, Go, and Rust/Tauri.

Known limitations

SLOP v0.2.0 is designed to be useful now while leaving room to grow. Key limitations:

  • Multi-user apps — Server-side providers currently expose one shared tree to all consumers. The protocol already supports per-user state (each connection is independent), but the SDKs don't implement session-scoped tree rendering yet. Client-only SPAs are unaffected — each tab is its own provider. See Sessions & Multi-User.
  • No reconnection — If a WebSocket drops, the consumer must re-connect and re-subscribe from scratch. No automatic reconnect or version-based catch-up.
  • No backpressurepause/resume messages are mentioned in the spec but not defined. Providers should debounce rapid changes (50-100ms).
  • No LAN discovery — Local discovery is shipped (~/.slop/providers/, /tmp/slop/providers/, browser meta tags, and /.well-known/slop), but mDNS/DNS-SD for remote providers is still reserved and unspecified.

Full list: Known Limitations & Future Work

Current status

v0.2.0 (25 Apr 2026) includes:

  • Core protocol docs plus scaling, content-reference, and async-action extensions
  • TypeScript SDKs, framework adapters, and @slop-ai/discovery
  • Python, Go, and Rust SDKs with discovery parity
  • Chrome extension, desktop app, CLI, and MCP Apps bridge
  • Examples, benchmarks, and OpenClaw integration

SLOP sits beside MCP. It does not replace it.

Roadmap

Protocol

  • Backpressure (pause/resume flow control)
  • Network discovery (mDNS/DNS-SD)
  • Ancestor retention for salience filtering
  • Binary encoding (optional MessagePack/CBOR)

SDKs

  • Session-scoped trees (multi-user server apps)
  • Automatic reconnection with version catch-up
  • Typed affordance results
  • Consumer-side tree composition (merge multiple providers)

Product

  • Firefox extension
  • Safari extension
  • Agent CLI (npx @slop-ai/init)
  • Extension per-site toggles

License

MIT

About

A protocol for AI to observe and interact with application state

Topics

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devteapot/slop: A protocol for AI to observe and interact with application state · GitHub
Skip to content

Repository files navigation

SLOP — State Layer for Observable Programs

SLOP is a protocol that lets AI observe and interact with application state directly — no screenshots, no scraping, no blind tool calls.

Applications expose a semantic state tree that AI can subscribe to, query at variable depth, and act on through contextual affordances. It is the missing perception layer between AI and the software it operates.

slop_demo.mov

An AI agent observing state, invoking actions, and updating the UI in real time. Run it yourself: bun run demo

Why

Today, AI interacts with applications through two extremes:

  • Vision (screenshots) — expensive, lossy, fragile. The AI parses pixels to recover information the app already had in structured form.
  • Tool calls / MCP — the AI can act, but it's flying blind. It calls functions without knowing what the user is currently looking at or what the app's state is. Every observation requires a dedicated tool.

SLOP fills the gap: a standard way for apps to publish what they are so AI can see before it acts.

Core ideas

  1. State tree — Apps expose a tree of semantic nodes (not UI elements, not raw data models — meaning). Each node has an identity, properties, and optional children.

  2. Subscriptions and patches — AI subscribes to subtrees at a chosen depth. The app pushes incremental patches (JSON Patch) as state changes. No polling, no redundant full reads.

  3. Contextual affordances — Actions live on the nodes they affect, not in a global tool registry. The AI sees what it can do in context — "reply" appears on a message node, "merge" appears on a PR node.

  4. Attention hints — Apps signal what matters right now: salience scores, change flags, user focus. The AI doesn't have to scan the entire tree to find what's relevant.

  5. Progressive disclosure — The tree supports variable-depth queries. Top-level gives a summary. Drilling in gives detail. Large collections are windowed with summaries.

How it differs from existing approaches

MCP / Tool callsAccessibility APIsSLOP
Primary purposeAI actsScreen readers read UIAI perceives + acts
Data modelFlat list of functionsUI element treeSemantic state tree
DirectionPull (AI calls tools)Pull (reader queries)Push-first (app publishes)
ActionsGlobal tool registryLimited (click, type)Contextual affordances on nodes
Designed forLLM function callingSequential text navigationAI state comprehension

Quick start

bun add @slop-ai/client @slop-ai/react
import{createSlop}from"@slop-ai/client";import{action,useSlop}from"@slop-ai/react";constslop=createSlop({id: "my-app",name: "My App"});functionTaskList({ tasks }){useSlop(slop,"tasks",()=>({type: "collection",props: {count: tasks.length},items: tasks.map(t=>({id: t.id,props: {title: t.title,done: t.done},actions: {toggle: action(()=>toggleTask(t.id)),delete: action(()=>deleteTask(t.id),{dangerous: true}),},})),}));return<ul>{tasks.map(t=><likey={t.id}>{t.title}</li>)}</ul>;}

That's it. Your component is now observable by any SLOP consumer — the Chrome extension, a desktop agent, or a custom AI integration.

Spec

The full specification is in spec/:

Core protocol

  1. Overview & Concepts
  2. State Tree
  3. Transport & Discovery
  4. Message Protocol
  5. Affordances
  6. Attention & Salience

Extensions

Integration guides

Status and limits

SDK guides

Guides

Benchmarks

The benchmarks/mcp-vs-slop suite compares SLOP and MCP head-to-head using an identical backing application (issue tracker). An LLM agent performs 12 scenarios through each protocol, measuring correctness, tool calls, latency, and cost.

Key findings:

  • Correctness: SLOP passes 12/12 scenarios. MCP passes 8/12 — fails on scale (discovery budget exhaustion), safety (can't prevent invalid actions on closed issues), and complex reasoning (can't aggregate state across repos).
  • Contextual affordances prevent invalid actions by design. MCP's flat tool list always exposes assign_issue regardless of issue state. SLOP only shows actions valid for the current state.
  • SLOP uses 75-90% fewer LLM round trips on multi-entity tasks by front-loading state. The agent batches all actions in 2 turns instead of 8-21 discovery-then-act turns.
  • Cost tradeoff is real. SLOP's state tree uses more input tokens. For simple tasks MCP is cheaper. For complex tasks requiring cross-entity reasoning, SLOP is cheaper and correct where MCP fails.

Full results and methodology: Benchmarks: MCP vs SLOP

SDKs

LanguagePackageInstall
TypeScript@slop-ai/corebun add @slop-ai/core
Browser@slop-ai/clientbun add @slop-ai/client
React@slop-ai/reactbun add @slop-ai/react
Vue@slop-ai/vuebun add @slop-ai/vue
Solid@slop-ai/solidbun add @slop-ai/solid
Angular@slop-ai/angularbun add @slop-ai/angular
Svelte@slop-ai/sveltebun add @slop-ai/svelte
Server (Node/Bun)@slop-ai/serverbun add @slop-ai/server
Consumer@slop-ai/consumerbun add @slop-ai/consumer
TanStack Start@slop-ai/tanstack-startbun add @slop-ai/tanstack-start
Discovery@slop-ai/discoverybun add @slop-ai/discovery
OpenClaw@slop-ai/openclaw-pluginbun add @slop-ai/openclaw-plugin
Codexslop plugincp -r packages/typescript/integrations/codex/slop ~/.codex/plugins/slop
Pythonslop-aipip install slop-ai
Rustslop-aicargo add slop-ai
Goslop-aigo get github.com/devteapot/slop/packages/go/slop-ai

Project structure

slop/
├── spec/ # Protocol specification
├── mcp-seps/ # Draft MCP SEPs related to SLOP
├── docs/sdk/ # SDK architecture & implementation guides
├── packages/
│ ├── typescript/
│ │ ├── sdk/
│ │ │ ├── core/ # @slop-ai/core — types, tree assembly, diffing
│ │ │ ├── client/ # @slop-ai/client — browser provider (postMessage)
│ │ │ ├── server/ # @slop-ai/server — server provider (WebSocket, Unix, stdio)
│ │ │ └── consumer/ # @slop-ai/consumer — connect, subscribe, invoke
│ │ ├── adapters/
│ │ │ ├── react/ # @slop-ai/react — useSlop hook
│ │ │ ├── vue/ # @slop-ai/vue — useSlop composable
│ │ │ ├── solid/ # @slop-ai/solid — useSlop primitive
│ │ │ ├── angular/ # @slop-ai/angular — useSlop with signals
│ │ │ ├── svelte/ # @slop-ai/svelte — useSlop for Svelte 5 runes
│ │ │ └── tanstack-start/ # @slop-ai/tanstack-start — SSR adapter
│ │ └── integrations/
│ │ ├── discovery/ # @slop-ai/discovery — bridge/discovery primitives with /service and /tools entrypoints
│ │ ├── claude/ # Claude Code plugins (native + MCP proxy)
│ │ ├── codex/ # Codex plugin (MCP bridge + skill)
│ │ └── openclaw-plugin/ # @slop-ai/openclaw-plugin — OpenClaw integration
│ ├── python/slop-ai/ # Python SDK
│ ├── rust/slop-ai/ # Rust SDK
│ └── go/slop-ai/ # Go SDK
├── apps/
│ ├── extension/ # Chrome extension (SLOP consumer + AI chat)
│ ├── desktop/ # Tauri desktop app
│ └── cli/ # Go CLI inspector
├── benchmarks/
│ └── mcp-vs-slop/ # MCP vs SLOP benchmark suite
├── examples/
│ ├── cli/ # Task manager CLI in 4 languages (Bun, Python, Go, Rust)
│ ├── spa/ # Client-only kanban board across 5 frameworks
│ │ ├── react/
│ │ ├── vue/
│ │ ├── solid/
│ │ ├── svelte/
│ │ └── angular/
│ ├── desktop/ # Pomodoro desktop provider (same blueprint, multiple stacks)
│ │ ├── typescript/ # Electron (JS main/renderer) + Unix socket provider
│ │ ├── python/
│ │ ├── go/
│ │ └── rust/ # Tauri
│ └── full-stack/
│ ├── tanstack-start/ # TanStack Start — server + UI mount
│ └── python-react/ # Python FastAPI + React — cross-SDK
└── website/
├── landing/ # slopai.dev landing page
├── docs/ # docs.slopai.dev documentation
├── demo/ # demo.slopai.dev interactive demo
└── playground/ # playground.slopai.dev

Examples

Each example follows a blueprint — a language-agnostic spec defining the exact SLOP tree, affordances, and test scenarios. Multiple implementations of the same blueprint prove cross-language consistency.

  • Interactive Demo — Three-panel demo: e-commerce store + AI agent + live state tree. Run with bun run demo. Replay mode works without an API key; connect one for interactive mode.
  • CLI Task Managertsk, a task manager with a --slop flag. Implementations in Bun, Python, Go, and Rust.
  • SPA Kanban Board — Canonical client-only example, implemented in React, Vue, Solid, Svelte, and Angular from the same blueprint.
  • TanStack Start — Full-stack web app with server-side SLOP via WebSocket.
  • Python + React — Python FastAPI backend + React SPA frontend. Cross-SDK integration with two independent providers.
  • Desktop Pomodoro (TypeScript) — Electron app as a SLOP provider (Unix socket + ~/.slop/providers/). Implementations also exist in Python, Go, and Rust/Tauri.

Known limitations

SLOP v0.2.0 is designed to be useful now while leaving room to grow. Key limitations:

  • Multi-user apps — Server-side providers currently expose one shared tree to all consumers. The protocol already supports per-user state (each connection is independent), but the SDKs don't implement session-scoped tree rendering yet. Client-only SPAs are unaffected — each tab is its own provider. See Sessions & Multi-User.
  • No reconnection — If a WebSocket drops, the consumer must re-connect and re-subscribe from scratch. No automatic reconnect or version-based catch-up.
  • No backpressurepause/resume messages are mentioned in the spec but not defined. Providers should debounce rapid changes (50-100ms).
  • No LAN discovery — Local discovery is shipped (~/.slop/providers/, /tmp/slop/providers/, browser meta tags, and /.well-known/slop), but mDNS/DNS-SD for remote providers is still reserved and unspecified.

Full list: Known Limitations & Future Work

Current status

v0.2.0 (25 Apr 2026) includes:

  • Core protocol docs plus scaling, content-reference, and async-action extensions
  • TypeScript SDKs, framework adapters, and @slop-ai/discovery
  • Python, Go, and Rust SDKs with discovery parity
  • Chrome extension, desktop app, CLI, and MCP Apps bridge
  • Examples, benchmarks, and OpenClaw integration

SLOP sits beside MCP. It does not replace it.

Roadmap

Protocol

  • Backpressure (pause/resume flow control)
  • Network discovery (mDNS/DNS-SD)
  • Ancestor retention for salience filtering
  • Binary encoding (optional MessagePack/CBOR)

SDKs

  • Session-scoped trees (multi-user server apps)
  • Automatic reconnection with version catch-up
  • Typed affordance results
  • Consumer-side tree composition (merge multiple providers)

Product

  • Firefox extension
  • Safari extension
  • Agent CLI (npx @slop-ai/init)
  • Extension per-site toggles

License

MIT

About

A protocol for AI to observe and interact with application state

Topics

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devteapot/slop: A protocol for AI to observe and interact with application state · GitHub
Skip to content

Repository files navigation

SLOP — State Layer for Observable Programs

SLOP is a protocol that lets AI observe and interact with application state directly — no screenshots, no scraping, no blind tool calls.

Applications expose a semantic state tree that AI can subscribe to, query at variable depth, and act on through contextual affordances. It is the missing perception layer between AI and the software it operates.

slop_demo.mov

An AI agent observing state, invoking actions, and updating the UI in real time. Run it yourself: bun run demo

Why

Today, AI interacts with applications through two extremes:

  • Vision (screenshots) — expensive, lossy, fragile. The AI parses pixels to recover information the app already had in structured form.
  • Tool calls / MCP — the AI can act, but it's flying blind. It calls functions without knowing what the user is currently looking at or what the app's state is. Every observation requires a dedicated tool.

SLOP fills the gap: a standard way for apps to publish what they are so AI can see before it acts.

Core ideas

  1. State tree — Apps expose a tree of semantic nodes (not UI elements, not raw data models — meaning). Each node has an identity, properties, and optional children.

  2. Subscriptions and patches — AI subscribes to subtrees at a chosen depth. The app pushes incremental patches (JSON Patch) as state changes. No polling, no redundant full reads.

  3. Contextual affordances — Actions live on the nodes they affect, not in a global tool registry. The AI sees what it can do in context — "reply" appears on a message node, "merge" appears on a PR node.

  4. Attention hints — Apps signal what matters right now: salience scores, change flags, user focus. The AI doesn't have to scan the entire tree to find what's relevant.

  5. Progressive disclosure — The tree supports variable-depth queries. Top-level gives a summary. Drilling in gives detail. Large collections are windowed with summaries.

How it differs from existing approaches

MCP / Tool callsAccessibility APIsSLOP
Primary purposeAI actsScreen readers read UIAI perceives + acts
Data modelFlat list of functionsUI element treeSemantic state tree
DirectionPull (AI calls tools)Pull (reader queries)Push-first (app publishes)
ActionsGlobal tool registryLimited (click, type)Contextual affordances on nodes
Designed forLLM function callingSequential text navigationAI state comprehension

Quick start

bun add @slop-ai/client @slop-ai/react
import{createSlop}from"@slop-ai/client";import{action,useSlop}from"@slop-ai/react";constslop=createSlop({id: "my-app",name: "My App"});functionTaskList({ tasks }){useSlop(slop,"tasks",()=>({type: "collection",props: {count: tasks.length},items: tasks.map(t=>({id: t.id,props: {title: t.title,done: t.done},actions: {toggle: action(()=>toggleTask(t.id)),delete: action(()=>deleteTask(t.id),{dangerous: true}),},})),}));return<ul>{tasks.map(t=><likey={t.id}>{t.title}</li>)}</ul>;}

That's it. Your component is now observable by any SLOP consumer — the Chrome extension, a desktop agent, or a custom AI integration.

Spec

The full specification is in spec/:

Core protocol

  1. Overview & Concepts
  2. State Tree
  3. Transport & Discovery
  4. Message Protocol
  5. Affordances
  6. Attention & Salience

Extensions

Integration guides

Status and limits

SDK guides

Guides

Benchmarks

The benchmarks/mcp-vs-slop suite compares SLOP and MCP head-to-head using an identical backing application (issue tracker). An LLM agent performs 12 scenarios through each protocol, measuring correctness, tool calls, latency, and cost.

Key findings:

  • Correctness: SLOP passes 12/12 scenarios. MCP passes 8/12 — fails on scale (discovery budget exhaustion), safety (can't prevent invalid actions on closed issues), and complex reasoning (can't aggregate state across repos).
  • Contextual affordances prevent invalid actions by design. MCP's flat tool list always exposes assign_issue regardless of issue state. SLOP only shows actions valid for the current state.
  • SLOP uses 75-90% fewer LLM round trips on multi-entity tasks by front-loading state. The agent batches all actions in 2 turns instead of 8-21 discovery-then-act turns.
  • Cost tradeoff is real. SLOP's state tree uses more input tokens. For simple tasks MCP is cheaper. For complex tasks requiring cross-entity reasoning, SLOP is cheaper and correct where MCP fails.

Full results and methodology: Benchmarks: MCP vs SLOP

SDKs

LanguagePackageInstall
TypeScript@slop-ai/corebun add @slop-ai/core
Browser@slop-ai/clientbun add @slop-ai/client
React@slop-ai/reactbun add @slop-ai/react
Vue@slop-ai/vuebun add @slop-ai/vue
Solid@slop-ai/solidbun add @slop-ai/solid
Angular@slop-ai/angularbun add @slop-ai/angular
Svelte@slop-ai/sveltebun add @slop-ai/svelte
Server (Node/Bun)@slop-ai/serverbun add @slop-ai/server
Consumer@slop-ai/consumerbun add @slop-ai/consumer
TanStack Start@slop-ai/tanstack-startbun add @slop-ai/tanstack-start
Discovery@slop-ai/discoverybun add @slop-ai/discovery
OpenClaw@slop-ai/openclaw-pluginbun add @slop-ai/openclaw-plugin
Codexslop plugincp -r packages/typescript/integrations/codex/slop ~/.codex/plugins/slop
Pythonslop-aipip install slop-ai
Rustslop-aicargo add slop-ai
Goslop-aigo get github.com/devteapot/slop/packages/go/slop-ai

Project structure

slop/
├── spec/ # Protocol specification
├── mcp-seps/ # Draft MCP SEPs related to SLOP
├── docs/sdk/ # SDK architecture & implementation guides
├── packages/
│ ├── typescript/
│ │ ├── sdk/
│ │ │ ├── core/ # @slop-ai/core — types, tree assembly, diffing
│ │ │ ├── client/ # @slop-ai/client — browser provider (postMessage)
│ │ │ ├── server/ # @slop-ai/server — server provider (WebSocket, Unix, stdio)
│ │ │ └── consumer/ # @slop-ai/consumer — connect, subscribe, invoke
│ │ ├── adapters/
│ │ │ ├── react/ # @slop-ai/react — useSlop hook
│ │ │ ├── vue/ # @slop-ai/vue — useSlop composable
│ │ │ ├── solid/ # @slop-ai/solid — useSlop primitive
│ │ │ ├── angular/ # @slop-ai/angular — useSlop with signals
│ │ │ ├── svelte/ # @slop-ai/svelte — useSlop for Svelte 5 runes
│ │ │ └── tanstack-start/ # @slop-ai/tanstack-start — SSR adapter
│ │ └── integrations/
│ │ ├── discovery/ # @slop-ai/discovery — bridge/discovery primitives with /service and /tools entrypoints
│ │ ├── claude/ # Claude Code plugins (native + MCP proxy)
│ │ ├── codex/ # Codex plugin (MCP bridge + skill)
│ │ └── openclaw-plugin/ # @slop-ai/openclaw-plugin — OpenClaw integration
│ ├── python/slop-ai/ # Python SDK
│ ├── rust/slop-ai/ # Rust SDK
│ └── go/slop-ai/ # Go SDK
├── apps/
│ ├── extension/ # Chrome extension (SLOP consumer + AI chat)
│ ├── desktop/ # Tauri desktop app
│ └── cli/ # Go CLI inspector
├── benchmarks/
│ └── mcp-vs-slop/ # MCP vs SLOP benchmark suite
├── examples/
│ ├── cli/ # Task manager CLI in 4 languages (Bun, Python, Go, Rust)
│ ├── spa/ # Client-only kanban board across 5 frameworks
│ │ ├── react/
│ │ ├── vue/
│ │ ├── solid/
│ │ ├── svelte/
│ │ └── angular/
│ ├── desktop/ # Pomodoro desktop provider (same blueprint, multiple stacks)
│ │ ├── typescript/ # Electron (JS main/renderer) + Unix socket provider
│ │ ├── python/
│ │ ├── go/
│ │ └── rust/ # Tauri
│ └── full-stack/
│ ├── tanstack-start/ # TanStack Start — server + UI mount
│ └── python-react/ # Python FastAPI + React — cross-SDK
└── website/
├── landing/ # slopai.dev landing page
├── docs/ # docs.slopai.dev documentation
├── demo/ # demo.slopai.dev interactive demo
└── playground/ # playground.slopai.dev

Examples

Each example follows a blueprint — a language-agnostic spec defining the exact SLOP tree, affordances, and test scenarios. Multiple implementations of the same blueprint prove cross-language consistency.

  • Interactive Demo — Three-panel demo: e-commerce store + AI agent + live state tree. Run with bun run demo. Replay mode works without an API key; connect one for interactive mode.
  • CLI Task Managertsk, a task manager with a --slop flag. Implementations in Bun, Python, Go, and Rust.
  • SPA Kanban Board — Canonical client-only example, implemented in React, Vue, Solid, Svelte, and Angular from the same blueprint.
  • TanStack Start — Full-stack web app with server-side SLOP via WebSocket.
  • Python + React — Python FastAPI backend + React SPA frontend. Cross-SDK integration with two independent providers.
  • Desktop Pomodoro (TypeScript) — Electron app as a SLOP provider (Unix socket + ~/.slop/providers/). Implementations also exist in Python, Go, and Rust/Tauri.

Known limitations

SLOP v0.2.0 is designed to be useful now while leaving room to grow. Key limitations:

  • Multi-user apps — Server-side providers currently expose one shared tree to all consumers. The protocol already supports per-user state (each connection is independent), but the SDKs don't implement session-scoped tree rendering yet. Client-only SPAs are unaffected — each tab is its own provider. See Sessions & Multi-User.
  • No reconnection — If a WebSocket drops, the consumer must re-connect and re-subscribe from scratch. No automatic reconnect or version-based catch-up.
  • No backpressurepause/resume messages are mentioned in the spec but not defined. Providers should debounce rapid changes (50-100ms).
  • No LAN discovery — Local discovery is shipped (~/.slop/providers/, /tmp/slop/providers/, browser meta tags, and /.well-known/slop), but mDNS/DNS-SD for remote providers is still reserved and unspecified.

Full list: Known Limitations & Future Work

Current status

v0.2.0 (25 Apr 2026) includes:

  • Core protocol docs plus scaling, content-reference, and async-action extensions
  • TypeScript SDKs, framework adapters, and @slop-ai/discovery
  • Python, Go, and Rust SDKs with discovery parity
  • Chrome extension, desktop app, CLI, and MCP Apps bridge
  • Examples, benchmarks, and OpenClaw integration

SLOP sits beside MCP. It does not replace it.

Roadmap

Protocol

  • Backpressure (pause/resume flow control)
  • Network discovery (mDNS/DNS-SD)
  • Ancestor retention for salience filtering
  • Binary encoding (optional MessagePack/CBOR)

SDKs

  • Session-scoped trees (multi-user server apps)
  • Automatic reconnection with version catch-up
  • Typed affordance results
  • Consumer-side tree composition (merge multiple providers)

Product

  • Firefox extension
  • Safari extension
  • Agent CLI (npx @slop-ai/init)
  • Extension per-site toggles

License

MIT

About

A protocol for AI to observe and interact with application state

Topics

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - devteapot/slop: A protocol for AI to observe and interact with application state · GitHub
Skip to content

Repository files navigation

SLOP — State Layer for Observable Programs

SLOP is a protocol that lets AI observe and interact with application state directly — no screenshots, no scraping, no blind tool calls.

Applications expose a semantic state tree that AI can subscribe to, query at variable depth, and act on through contextual affordances. It is the missing perception layer between AI and the software it operates.

slop_demo.mov

An AI agent observing state, invoking actions, and updating the UI in real time. Run it yourself: bun run demo

Why

Today, AI interacts with applications through two extremes:

  • Vision (screenshots) — expensive, lossy, fragile. The AI parses pixels to recover information the app already had in structured form.
  • Tool calls / MCP — the AI can act, but it's flying blind. It calls functions without knowing what the user is currently looking at or what the app's state is. Every observation requires a dedicated tool.

SLOP fills the gap: a standard way for apps to publish what they are so AI can see before it acts.

Core ideas

  1. State tree — Apps expose a tree of semantic nodes (not UI elements, not raw data models — meaning). Each node has an identity, properties, and optional children.

  2. Subscriptions and patches — AI subscribes to subtrees at a chosen depth. The app pushes incremental patches (JSON Patch) as state changes. No polling, no redundant full reads.

  3. Contextual affordances — Actions live on the nodes they affect, not in a global tool registry. The AI sees what it can do in context — "reply" appears on a message node, "merge" appears on a PR node.

  4. Attention hints — Apps signal what matters right now: salience scores, change flags, user focus. The AI doesn't have to scan the entire tree to find what's relevant.

  5. Progressive disclosure — The tree supports variable-depth queries. Top-level gives a summary. Drilling in gives detail. Large collections are windowed with summaries.

How it differs from existing approaches

MCP / Tool callsAccessibility APIsSLOP
Primary purposeAI actsScreen readers read UIAI perceives + acts
Data modelFlat list of functionsUI element treeSemantic state tree
DirectionPull (AI calls tools)Pull (reader queries)Push-first (app publishes)
ActionsGlobal tool registryLimited (click, type)Contextual affordances on nodes
Designed forLLM function callingSequential text navigationAI state comprehension

Quick start

bun add @slop-ai/client @slop-ai/react
import{createSlop}from"@slop-ai/client";import{action,useSlop}from"@slop-ai/react";constslop=createSlop({id: "my-app",name: "My App"});functionTaskList({ tasks }){useSlop(slop,"tasks",()=>({type: "collection",props: {count: tasks.length},items: tasks.map(t=>({id: t.id,props: {title: t.title,done: t.done},actions: {toggle: action(()=>toggleTask(t.id)),delete: action(()=>deleteTask(t.id),{dangerous: true}),},})),}));return<ul>{tasks.map(t=><likey={t.id}>{t.title}</li>)}</ul>;}

That's it. Your component is now observable by any SLOP consumer — the Chrome extension, a desktop agent, or a custom AI integration.

Spec

The full specification is in spec/:

Core protocol

  1. Overview & Concepts
  2. State Tree
  3. Transport & Discovery
  4. Message Protocol
  5. Affordances
  6. Attention & Salience

Extensions

Integration guides

Status and limits

SDK guides

Guides

Benchmarks

The benchmarks/mcp-vs-slop suite compares SLOP and MCP head-to-head using an identical backing application (issue tracker). An LLM agent performs 12 scenarios through each protocol, measuring correctness, tool calls, latency, and cost.

Key findings:

  • Correctness: SLOP passes 12/12 scenarios. MCP passes 8/12 — fails on scale (discovery budget exhaustion), safety (can't prevent invalid actions on closed issues), and complex reasoning (can't aggregate state across repos).
  • Contextual affordances prevent invalid actions by design. MCP's flat tool list always exposes assign_issue regardless of issue state. SLOP only shows actions valid for the current state.
  • SLOP uses 75-90% fewer LLM round trips on multi-entity tasks by front-loading state. The agent batches all actions in 2 turns instead of 8-21 discovery-then-act turns.
  • Cost tradeoff is real. SLOP's state tree uses more input tokens. For simple tasks MCP is cheaper. For complex tasks requiring cross-entity reasoning, SLOP is cheaper and correct where MCP fails.

Full results and methodology: Benchmarks: MCP vs SLOP

SDKs

LanguagePackageInstall
TypeScript@slop-ai/corebun add @slop-ai/core
Browser@slop-ai/clientbun add @slop-ai/client
React@slop-ai/reactbun add @slop-ai/react
Vue@slop-ai/vuebun add @slop-ai/vue
Solid@slop-ai/solidbun add @slop-ai/solid
Angular@slop-ai/angularbun add @slop-ai/angular
Svelte@slop-ai/sveltebun add @slop-ai/svelte
Server (Node/Bun)@slop-ai/serverbun add @slop-ai/server
Consumer@slop-ai/consumerbun add @slop-ai/consumer
TanStack Start@slop-ai/tanstack-startbun add @slop-ai/tanstack-start
Discovery@slop-ai/discoverybun add @slop-ai/discovery
OpenClaw@slop-ai/openclaw-pluginbun add @slop-ai/openclaw-plugin
Codexslop plugincp -r packages/typescript/integrations/codex/slop ~/.codex/plugins/slop
Pythonslop-aipip install slop-ai
Rustslop-aicargo add slop-ai
Goslop-aigo get github.com/devteapot/slop/packages/go/slop-ai

Project structure

slop/
├── spec/ # Protocol specification
├── mcp-seps/ # Draft MCP SEPs related to SLOP
├── docs/sdk/ # SDK architecture & implementation guides
├── packages/
│ ├── typescript/
│ │ ├── sdk/
│ │ │ ├── core/ # @slop-ai/core — types, tree assembly, diffing
│ │ │ ├── client/ # @slop-ai/client — browser provider (postMessage)
│ │ │ ├── server/ # @slop-ai/server — server provider (WebSocket, Unix, stdio)
│ │ │ └── consumer/ # @slop-ai/consumer — connect, subscribe, invoke
│ │ ├── adapters/
│ │ │ ├── react/ # @slop-ai/react — useSlop hook
│ │ │ ├── vue/ # @slop-ai/vue — useSlop composable
│ │ │ ├── solid/ # @slop-ai/solid — useSlop primitive
│ │ │ ├── angular/ # @slop-ai/angular — useSlop with signals
│ │ │ ├── svelte/ # @slop-ai/svelte — useSlop for Svelte 5 runes
│ │ │ └── tanstack-start/ # @slop-ai/tanstack-start — SSR adapter
│ │ └── integrations/
│ │ ├── discovery/ # @slop-ai/discovery — bridge/discovery primitives with /service and /tools entrypoints
│ │ ├── claude/ # Claude Code plugins (native + MCP proxy)
│ │ ├── codex/ # Codex plugin (MCP bridge + skill)
│ │ └── openclaw-plugin/ # @slop-ai/openclaw-plugin — OpenClaw integration
│ ├── python/slop-ai/ # Python SDK
│ ├── rust/slop-ai/ # Rust SDK
│ └── go/slop-ai/ # Go SDK
├── apps/
│ ├── extension/ # Chrome extension (SLOP consumer + AI chat)
│ ├── desktop/ # Tauri desktop app
│ └── cli/ # Go CLI inspector
├── benchmarks/
│ └── mcp-vs-slop/ # MCP vs SLOP benchmark suite
├── examples/
│ ├── cli/ # Task manager CLI in 4 languages (Bun, Python, Go, Rust)
│ ├── spa/ # Client-only kanban board across 5 frameworks
│ │ ├── react/
│ │ ├── vue/
│ │ ├── solid/
│ │ ├── svelte/
│ │ └── angular/
│ ├── desktop/ # Pomodoro desktop provider (same blueprint, multiple stacks)
│ │ ├── typescript/ # Electron (JS main/renderer) + Unix socket provider
│ │ ├── python/
│ │ ├── go/
│ │ └── rust/ # Tauri
│ └── full-stack/
│ ├── tanstack-start/ # TanStack Start — server + UI mount
│ └── python-react/ # Python FastAPI + React — cross-SDK
└── website/
├── landing/ # slopai.dev landing page
├── docs/ # docs.slopai.dev documentation
├── demo/ # demo.slopai.dev interactive demo
└── playground/ # playground.slopai.dev

Examples

Each example follows a blueprint — a language-agnostic spec defining the exact SLOP tree, affordances, and test scenarios. Multiple implementations of the same blueprint prove cross-language consistency.

  • Interactive Demo — Three-panel demo: e-commerce store + AI agent + live state tree. Run with bun run demo. Replay mode works without an API key; connect one for interactive mode.
  • CLI Task Managertsk, a task manager with a --slop flag. Implementations in Bun, Python, Go, and Rust.
  • SPA Kanban Board — Canonical client-only example, implemented in React, Vue, Solid, Svelte, and Angular from the same blueprint.
  • TanStack Start — Full-stack web app with server-side SLOP via WebSocket.
  • Python + React — Python FastAPI backend + React SPA frontend. Cross-SDK integration with two independent providers.
  • Desktop Pomodoro (TypeScript) — Electron app as a SLOP provider (Unix socket + ~/.slop/providers/). Implementations also exist in Python, Go, and Rust/Tauri.

Known limitations

SLOP v0.2.0 is designed to be useful now while leaving room to grow. Key limitations:

  • Multi-user apps — Server-side providers currently expose one shared tree to all consumers. The protocol already supports per-user state (each connection is independent), but the SDKs don't implement session-scoped tree rendering yet. Client-only SPAs are unaffected — each tab is its own provider. See Sessions & Multi-User.
  • No reconnection — If a WebSocket drops, the consumer must re-connect and re-subscribe from scratch. No automatic reconnect or version-based catch-up.
  • No backpressurepause/resume messages are mentioned in the spec but not defined. Providers should debounce rapid changes (50-100ms).
  • No LAN discovery — Local discovery is shipped (~/.slop/providers/, /tmp/slop/providers/, browser meta tags, and /.well-known/slop), but mDNS/DNS-SD for remote providers is still reserved and unspecified.

Full list: Known Limitations & Future Work

Current status

v0.2.0 (25 Apr 2026) includes:

  • Core protocol docs plus scaling, content-reference, and async-action extensions
  • TypeScript SDKs, framework adapters, and @slop-ai/discovery
  • Python, Go, and Rust SDKs with discovery parity
  • Chrome extension, desktop app, CLI, and MCP Apps bridge
  • Examples, benchmarks, and OpenClaw integration

SLOP sits beside MCP. It does not replace it.

Roadmap

Protocol

  • Backpressure (pause/resume flow control)
  • Network discovery (mDNS/DNS-SD)
  • Ancestor retention for salience filtering
  • Binary encoding (optional MessagePack/CBOR)

SDKs

  • Session-scoped trees (multi-user server apps)
  • Automatic reconnection with version catch-up
  • Typed affordance results
  • Consumer-side tree composition (merge multiple providers)

Product

  • Firefox extension
  • Safari extension
  • Agent CLI (npx @slop-ai/init)
  • Extension per-site toggles

License

MIT

About

A protocol for AI to observe and interact with application state

Topics

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devteapot/slop: A protocol for AI to observe and interact with application state · GitHub
Skip to content

Repository files navigation

SLOP — State Layer for Observable Programs

SLOP is a protocol that lets AI observe and interact with application state directly — no screenshots, no scraping, no blind tool calls.

Applications expose a semantic state tree that AI can subscribe to, query at variable depth, and act on through contextual affordances. It is the missing perception layer between AI and the software it operates.

slop_demo.mov

An AI agent observing state, invoking actions, and updating the UI in real time. Run it yourself: bun run demo

Why

Today, AI interacts with applications through two extremes:

  • Vision (screenshots) — expensive, lossy, fragile. The AI parses pixels to recover information the app already had in structured form.
  • Tool calls / MCP — the AI can act, but it's flying blind. It calls functions without knowing what the user is currently looking at or what the app's state is. Every observation requires a dedicated tool.

SLOP fills the gap: a standard way for apps to publish what they are so AI can see before it acts.

Core ideas

  1. State tree — Apps expose a tree of semantic nodes (not UI elements, not raw data models — meaning). Each node has an identity, properties, and optional children.

  2. Subscriptions and patches — AI subscribes to subtrees at a chosen depth. The app pushes incremental patches (JSON Patch) as state changes. No polling, no redundant full reads.

  3. Contextual affordances — Actions live on the nodes they affect, not in a global tool registry. The AI sees what it can do in context — "reply" appears on a message node, "merge" appears on a PR node.

  4. Attention hints — Apps signal what matters right now: salience scores, change flags, user focus. The AI doesn't have to scan the entire tree to find what's relevant.

  5. Progressive disclosure — The tree supports variable-depth queries. Top-level gives a summary. Drilling in gives detail. Large collections are windowed with summaries.

How it differs from existing approaches

MCP / Tool callsAccessibility APIsSLOP
Primary purposeAI actsScreen readers read UIAI perceives + acts
Data modelFlat list of functionsUI element treeSemantic state tree
DirectionPull (AI calls tools)Pull (reader queries)Push-first (app publishes)
ActionsGlobal tool registryLimited (click, type)Contextual affordances on nodes
Designed forLLM function callingSequential text navigationAI state comprehension

Quick start

bun add @slop-ai/client @slop-ai/react
import{createSlop}from"@slop-ai/client";import{action,useSlop}from"@slop-ai/react";constslop=createSlop({id: "my-app",name: "My App"});functionTaskList({ tasks }){useSlop(slop,"tasks",()=>({type: "collection",props: {count: tasks.length},items: tasks.map(t=>({id: t.id,props: {title: t.title,done: t.done},actions: {toggle: action(()=>toggleTask(t.id)),delete: action(()=>deleteTask(t.id),{dangerous: true}),},})),}));return<ul>{tasks.map(t=><likey={t.id}>{t.title}</li>)}</ul>;}

That's it. Your component is now observable by any SLOP consumer — the Chrome extension, a desktop agent, or a custom AI integration.

Spec

The full specification is in spec/:

Core protocol

  1. Overview & Concepts
  2. State Tree
  3. Transport & Discovery
  4. Message Protocol
  5. Affordances
  6. Attention & Salience

Extensions

Integration guides

Status and limits

SDK guides

Guides

Benchmarks

The benchmarks/mcp-vs-slop suite compares SLOP and MCP head-to-head using an identical backing application (issue tracker). An LLM agent performs 12 scenarios through each protocol, measuring correctness, tool calls, latency, and cost.

Key findings:

  • Correctness: SLOP passes 12/12 scenarios. MCP passes 8/12 — fails on scale (discovery budget exhaustion), safety (can't prevent invalid actions on closed issues), and complex reasoning (can't aggregate state across repos).
  • Contextual affordances prevent invalid actions by design. MCP's flat tool list always exposes assign_issue regardless of issue state. SLOP only shows actions valid for the current state.
  • SLOP uses 75-90% fewer LLM round trips on multi-entity tasks by front-loading state. The agent batches all actions in 2 turns instead of 8-21 discovery-then-act turns.
  • Cost tradeoff is real. SLOP's state tree uses more input tokens. For simple tasks MCP is cheaper. For complex tasks requiring cross-entity reasoning, SLOP is cheaper and correct where MCP fails.

Full results and methodology: Benchmarks: MCP vs SLOP

SDKs

LanguagePackageInstall
TypeScript@slop-ai/corebun add @slop-ai/core
Browser@slop-ai/clientbun add @slop-ai/client
React@slop-ai/reactbun add @slop-ai/react
Vue@slop-ai/vuebun add @slop-ai/vue
Solid@slop-ai/solidbun add @slop-ai/solid
Angular@slop-ai/angularbun add @slop-ai/angular
Svelte@slop-ai/sveltebun add @slop-ai/svelte
Server (Node/Bun)@slop-ai/serverbun add @slop-ai/server
Consumer@slop-ai/consumerbun add @slop-ai/consumer
TanStack Start@slop-ai/tanstack-startbun add @slop-ai/tanstack-start
Discovery@slop-ai/discoverybun add @slop-ai/discovery
OpenClaw@slop-ai/openclaw-pluginbun add @slop-ai/openclaw-plugin
Codexslop plugincp -r packages/typescript/integrations/codex/slop ~/.codex/plugins/slop
Pythonslop-aipip install slop-ai
Rustslop-aicargo add slop-ai
Goslop-aigo get github.com/devteapot/slop/packages/go/slop-ai

Project structure

slop/
├── spec/ # Protocol specification
├── mcp-seps/ # Draft MCP SEPs related to SLOP
├── docs/sdk/ # SDK architecture & implementation guides
├── packages/
│ ├── typescript/
│ │ ├── sdk/
│ │ │ ├── core/ # @slop-ai/core — types, tree assembly, diffing
│ │ │ ├── client/ # @slop-ai/client — browser provider (postMessage)
│ │ │ ├── server/ # @slop-ai/server — server provider (WebSocket, Unix, stdio)
│ │ │ └── consumer/ # @slop-ai/consumer — connect, subscribe, invoke
│ │ ├── adapters/
│ │ │ ├── react/ # @slop-ai/react — useSlop hook
│ │ │ ├── vue/ # @slop-ai/vue — useSlop composable
│ │ │ ├── solid/ # @slop-ai/solid — useSlop primitive
│ │ │ ├── angular/ # @slop-ai/angular — useSlop with signals
│ │ │ ├── svelte/ # @slop-ai/svelte — useSlop for Svelte 5 runes
│ │ │ └── tanstack-start/ # @slop-ai/tanstack-start — SSR adapter
│ │ └── integrations/
│ │ ├── discovery/ # @slop-ai/discovery — bridge/discovery primitives with /service and /tools entrypoints
│ │ ├── claude/ # Claude Code plugins (native + MCP proxy)
│ │ ├── codex/ # Codex plugin (MCP bridge + skill)
│ │ └── openclaw-plugin/ # @slop-ai/openclaw-plugin — OpenClaw integration
│ ├── python/slop-ai/ # Python SDK
│ ├── rust/slop-ai/ # Rust SDK
│ └── go/slop-ai/ # Go SDK
├── apps/
│ ├── extension/ # Chrome extension (SLOP consumer + AI chat)
│ ├── desktop/ # Tauri desktop app
│ └── cli/ # Go CLI inspector
├── benchmarks/
│ └── mcp-vs-slop/ # MCP vs SLOP benchmark suite
├── examples/
│ ├── cli/ # Task manager CLI in 4 languages (Bun, Python, Go, Rust)
│ ├── spa/ # Client-only kanban board across 5 frameworks
│ │ ├── react/
│ │ ├── vue/
│ │ ├── solid/
│ │ ├── svelte/
│ │ └── angular/
│ ├── desktop/ # Pomodoro desktop provider (same blueprint, multiple stacks)
│ │ ├── typescript/ # Electron (JS main/renderer) + Unix socket provider
│ │ ├── python/
│ │ ├── go/
│ │ └── rust/ # Tauri
│ └── full-stack/
│ ├── tanstack-start/ # TanStack Start — server + UI mount
│ └── python-react/ # Python FastAPI + React — cross-SDK
└── website/
├── landing/ # slopai.dev landing page
├── docs/ # docs.slopai.dev documentation
├── demo/ # demo.slopai.dev interactive demo
└── playground/ # playground.slopai.dev

Examples

Each example follows a blueprint — a language-agnostic spec defining the exact SLOP tree, affordances, and test scenarios. Multiple implementations of the same blueprint prove cross-language consistency.

  • Interactive Demo — Three-panel demo: e-commerce store + AI agent + live state tree. Run with bun run demo. Replay mode works without an API key; connect one for interactive mode.
  • CLI Task Managertsk, a task manager with a --slop flag. Implementations in Bun, Python, Go, and Rust.
  • SPA Kanban Board — Canonical client-only example, implemented in React, Vue, Solid, Svelte, and Angular from the same blueprint.
  • TanStack Start — Full-stack web app with server-side SLOP via WebSocket.
  • Python + React — Python FastAPI backend + React SPA frontend. Cross-SDK integration with two independent providers.
  • Desktop Pomodoro (TypeScript) — Electron app as a SLOP provider (Unix socket + ~/.slop/providers/). Implementations also exist in Python, Go, and Rust/Tauri.

Known limitations

SLOP v0.2.0 is designed to be useful now while leaving room to grow. Key limitations:

  • Multi-user apps — Server-side providers currently expose one shared tree to all consumers. The protocol already supports per-user state (each connection is independent), but the SDKs don't implement session-scoped tree rendering yet. Client-only SPAs are unaffected — each tab is its own provider. See Sessions & Multi-User.
  • No reconnection — If a WebSocket drops, the consumer must re-connect and re-subscribe from scratch. No automatic reconnect or version-based catch-up.
  • No backpressurepause/resume messages are mentioned in the spec but not defined. Providers should debounce rapid changes (50-100ms).
  • No LAN discovery — Local discovery is shipped (~/.slop/providers/, /tmp/slop/providers/, browser meta tags, and /.well-known/slop), but mDNS/DNS-SD for remote providers is still reserved and unspecified.

Full list: Known Limitations & Future Work

Current status

v0.2.0 (25 Apr 2026) includes:

  • Core protocol docs plus scaling, content-reference, and async-action extensions
  • TypeScript SDKs, framework adapters, and @slop-ai/discovery
  • Python, Go, and Rust SDKs with discovery parity
  • Chrome extension, desktop app, CLI, and MCP Apps bridge
  • Examples, benchmarks, and OpenClaw integration

SLOP sits beside MCP. It does not replace it.

Roadmap

Protocol

  • Backpressure (pause/resume flow control)
  • Network discovery (mDNS/DNS-SD)
  • Ancestor retention for salience filtering
  • Binary encoding (optional MessagePack/CBOR)

SDKs

  • Session-scoped trees (multi-user server apps)
  • Automatic reconnection with version catch-up
  • Typed affordance results
  • Consumer-side tree composition (merge multiple providers)

Product

  • Firefox extension
  • Safari extension
  • Agent CLI (npx @slop-ai/init)
  • Extension per-site toggles

License

MIT

About

A protocol for AI to observe and interact with application state

Topics

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - devteapot/slop: A protocol for AI to observe and interact with application state · GitHub
Skip to content

Repository files navigation

SLOP — State Layer for Observable Programs

SLOP is a protocol that lets AI observe and interact with application state directly — no screenshots, no scraping, no blind tool calls.

Applications expose a semantic state tree that AI can subscribe to, query at variable depth, and act on through contextual affordances. It is the missing perception layer between AI and the software it operates.

slop_demo.mov

An AI agent observing state, invoking actions, and updating the UI in real time. Run it yourself: bun run demo

Why

Today, AI interacts with applications through two extremes:

  • Vision (screenshots) — expensive, lossy, fragile. The AI parses pixels to recover information the app already had in structured form.
  • Tool calls / MCP — the AI can act, but it's flying blind. It calls functions without knowing what the user is currently looking at or what the app's state is. Every observation requires a dedicated tool.

SLOP fills the gap: a standard way for apps to publish what they are so AI can see before it acts.

Core ideas

  1. State tree — Apps expose a tree of semantic nodes (not UI elements, not raw data models — meaning). Each node has an identity, properties, and optional children.

  2. Subscriptions and patches — AI subscribes to subtrees at a chosen depth. The app pushes incremental patches (JSON Patch) as state changes. No polling, no redundant full reads.

  3. Contextual affordances — Actions live on the nodes they affect, not in a global tool registry. The AI sees what it can do in context — "reply" appears on a message node, "merge" appears on a PR node.

  4. Attention hints — Apps signal what matters right now: salience scores, change flags, user focus. The AI doesn't have to scan the entire tree to find what's relevant.

  5. Progressive disclosure — The tree supports variable-depth queries. Top-level gives a summary. Drilling in gives detail. Large collections are windowed with summaries.

How it differs from existing approaches

MCP / Tool callsAccessibility APIsSLOP
Primary purposeAI actsScreen readers read UIAI perceives + acts
Data modelFlat list of functionsUI element treeSemantic state tree
DirectionPull (AI calls tools)Pull (reader queries)Push-first (app publishes)
ActionsGlobal tool registryLimited (click, type)Contextual affordances on nodes
Designed forLLM function callingSequential text navigationAI state comprehension

Quick start

bun add @slop-ai/client @slop-ai/react
import{createSlop}from"@slop-ai/client";import{action,useSlop}from"@slop-ai/react";constslop=createSlop({id: "my-app",name: "My App"});functionTaskList({ tasks }){useSlop(slop,"tasks",()=>({type: "collection",props: {count: tasks.length},items: tasks.map(t=>({id: t.id,props: {title: t.title,done: t.done},actions: {toggle: action(()=>toggleTask(t.id)),delete: action(()=>deleteTask(t.id),{dangerous: true}),},})),}));return<ul>{tasks.map(t=><likey={t.id}>{t.title}</li>)}</ul>;}

That's it. Your component is now observable by any SLOP consumer — the Chrome extension, a desktop agent, or a custom AI integration.

Spec

The full specification is in spec/:

Core protocol

  1. Overview & Concepts
  2. State Tree
  3. Transport & Discovery
  4. Message Protocol
  5. Affordances
  6. Attention & Salience

Extensions

Integration guides

Status and limits

SDK guides

Guides

Benchmarks

The benchmarks/mcp-vs-slop suite compares SLOP and MCP head-to-head using an identical backing application (issue tracker). An LLM agent performs 12 scenarios through each protocol, measuring correctness, tool calls, latency, and cost.

Key findings:

  • Correctness: SLOP passes 12/12 scenarios. MCP passes 8/12 — fails on scale (discovery budget exhaustion), safety (can't prevent invalid actions on closed issues), and complex reasoning (can't aggregate state across repos).
  • Contextual affordances prevent invalid actions by design. MCP's flat tool list always exposes assign_issue regardless of issue state. SLOP only shows actions valid for the current state.
  • SLOP uses 75-90% fewer LLM round trips on multi-entity tasks by front-loading state. The agent batches all actions in 2 turns instead of 8-21 discovery-then-act turns.
  • Cost tradeoff is real. SLOP's state tree uses more input tokens. For simple tasks MCP is cheaper. For complex tasks requiring cross-entity reasoning, SLOP is cheaper and correct where MCP fails.

Full results and methodology: Benchmarks: MCP vs SLOP

SDKs

LanguagePackageInstall
TypeScript@slop-ai/corebun add @slop-ai/core
Browser@slop-ai/clientbun add @slop-ai/client
React@slop-ai/reactbun add @slop-ai/react
Vue@slop-ai/vuebun add @slop-ai/vue
Solid@slop-ai/solidbun add @slop-ai/solid
Angular@slop-ai/angularbun add @slop-ai/angular
Svelte@slop-ai/sveltebun add @slop-ai/svelte
Server (Node/Bun)@slop-ai/serverbun add @slop-ai/server
Consumer@slop-ai/consumerbun add @slop-ai/consumer
TanStack Start@slop-ai/tanstack-startbun add @slop-ai/tanstack-start
Discovery@slop-ai/discoverybun add @slop-ai/discovery
OpenClaw@slop-ai/openclaw-pluginbun add @slop-ai/openclaw-plugin
Codexslop plugincp -r packages/typescript/integrations/codex/slop ~/.codex/plugins/slop
Pythonslop-aipip install slop-ai
Rustslop-aicargo add slop-ai
Goslop-aigo get github.com/devteapot/slop/packages/go/slop-ai

Project structure

slop/
├── spec/ # Protocol specification
├── mcp-seps/ # Draft MCP SEPs related to SLOP
├── docs/sdk/ # SDK architecture & implementation guides
├── packages/
│ ├── typescript/
│ │ ├── sdk/
│ │ │ ├── core/ # @slop-ai/core — types, tree assembly, diffing
│ │ │ ├── client/ # @slop-ai/client — browser provider (postMessage)
│ │ │ ├── server/ # @slop-ai/server — server provider (WebSocket, Unix, stdio)
│ │ │ └── consumer/ # @slop-ai/consumer — connect, subscribe, invoke
│ │ ├── adapters/
│ │ │ ├── react/ # @slop-ai/react — useSlop hook
│ │ │ ├── vue/ # @slop-ai/vue — useSlop composable
│ │ │ ├── solid/ # @slop-ai/solid — useSlop primitive
│ │ │ ├── angular/ # @slop-ai/angular — useSlop with signals
│ │ │ ├── svelte/ # @slop-ai/svelte — useSlop for Svelte 5 runes
│ │ │ └── tanstack-start/ # @slop-ai/tanstack-start — SSR adapter
│ │ └── integrations/
│ │ ├── discovery/ # @slop-ai/discovery — bridge/discovery primitives with /service and /tools entrypoints
│ │ ├── claude/ # Claude Code plugins (native + MCP proxy)
│ │ ├── codex/ # Codex plugin (MCP bridge + skill)
│ │ └── openclaw-plugin/ # @slop-ai/openclaw-plugin — OpenClaw integration
│ ├── python/slop-ai/ # Python SDK
│ ├── rust/slop-ai/ # Rust SDK
│ └── go/slop-ai/ # Go SDK
├── apps/
│ ├── extension/ # Chrome extension (SLOP consumer + AI chat)
│ ├── desktop/ # Tauri desktop app
│ └── cli/ # Go CLI inspector
├── benchmarks/
│ └── mcp-vs-slop/ # MCP vs SLOP benchmark suite
├── examples/
│ ├── cli/ # Task manager CLI in 4 languages (Bun, Python, Go, Rust)
│ ├── spa/ # Client-only kanban board across 5 frameworks
│ │ ├── react/
│ │ ├── vue/
│ │ ├── solid/
│ │ ├── svelte/
│ │ └── angular/
│ ├── desktop/ # Pomodoro desktop provider (same blueprint, multiple stacks)
│ │ ├── typescript/ # Electron (JS main/renderer) + Unix socket provider
│ │ ├── python/
│ │ ├── go/
│ │ └── rust/ # Tauri
│ └── full-stack/
│ ├── tanstack-start/ # TanStack Start — server + UI mount
│ └── python-react/ # Python FastAPI + React — cross-SDK
└── website/
├── landing/ # slopai.dev landing page
├── docs/ # docs.slopai.dev documentation
├── demo/ # demo.slopai.dev interactive demo
└── playground/ # playground.slopai.dev

Examples

Each example follows a blueprint — a language-agnostic spec defining the exact SLOP tree, affordances, and test scenarios. Multiple implementations of the same blueprint prove cross-language consistency.

  • Interactive Demo — Three-panel demo: e-commerce store + AI agent + live state tree. Run with bun run demo. Replay mode works without an API key; connect one for interactive mode.
  • CLI Task Managertsk, a task manager with a --slop flag. Implementations in Bun, Python, Go, and Rust.
  • SPA Kanban Board — Canonical client-only example, implemented in React, Vue, Solid, Svelte, and Angular from the same blueprint.
  • TanStack Start — Full-stack web app with server-side SLOP via WebSocket.
  • Python + React — Python FastAPI backend + React SPA frontend. Cross-SDK integration with two independent providers.
  • Desktop Pomodoro (TypeScript) — Electron app as a SLOP provider (Unix socket + ~/.slop/providers/). Implementations also exist in Python, Go, and Rust/Tauri.

Known limitations

SLOP v0.2.0 is designed to be useful now while leaving room to grow. Key limitations:

  • Multi-user apps — Server-side providers currently expose one shared tree to all consumers. The protocol already supports per-user state (each connection is independent), but the SDKs don't implement session-scoped tree rendering yet. Client-only SPAs are unaffected — each tab is its own provider. See Sessions & Multi-User.
  • No reconnection — If a WebSocket drops, the consumer must re-connect and re-subscribe from scratch. No automatic reconnect or version-based catch-up.
  • No backpressurepause/resume messages are mentioned in the spec but not defined. Providers should debounce rapid changes (50-100ms).
  • No LAN discovery — Local discovery is shipped (~/.slop/providers/, /tmp/slop/providers/, browser meta tags, and /.well-known/slop), but mDNS/DNS-SD for remote providers is still reserved and unspecified.

Full list: Known Limitations & Future Work

Current status

v0.2.0 (25 Apr 2026) includes:

  • Core protocol docs plus scaling, content-reference, and async-action extensions
  • TypeScript SDKs, framework adapters, and @slop-ai/discovery
  • Python, Go, and Rust SDKs with discovery parity
  • Chrome extension, desktop app, CLI, and MCP Apps bridge
  • Examples, benchmarks, and OpenClaw integration

SLOP sits beside MCP. It does not replace it.

Roadmap

Protocol

  • Backpressure (pause/resume flow control)
  • Network discovery (mDNS/DNS-SD)
  • Ancestor retention for salience filtering
  • Binary encoding (optional MessagePack/CBOR)

SDKs

  • Session-scoped trees (multi-user server apps)
  • Automatic reconnection with version catch-up
  • Typed affordance results
  • Consumer-side tree composition (merge multiple providers)

Product

  • Firefox extension
  • Safari extension
  • Agent CLI (npx @slop-ai/init)
  • Extension per-site toggles

License

MIT

About

A protocol for AI to observe and interact with application state

Topics

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages