Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pogly elements delete 42
| `elementdata list\|add\|update\|delete` | Manage element data assets |
| `layouts list\|add\|duplicate\|rename\|delete\|set-active` | Manage layouts; `set-active` switches the live scene |
| `folders list\|add\|update\|delete` | Manage asset folders |
| `osc` | Run the OSC listener server to control the overlay via UDP |
| `version [list\|use\|upgrade]` | Show, switch, or upgrade the installed CLI version |

Every command supports `--help` for its full flag list, `--json` for the raw API response, and `--overlay <nickname>` to target a specific profile.
Expand All @@ -85,6 +86,82 @@ Writes require the matching permission on the token owner's account (e.g. `AddEl

The [examples/](examples/) folder shows how to hook the CLI into your stream: Streamer.bot-triggered alerts on subs/raids/channel points, automatic Pogly↔OBS scene sync, live counters, and one rick roll. Anything that can run a program can drive your overlay.

## Model Context Protocol (MCP) Server

`pogly-cli` can run as a Model Context Protocol (MCP) server, allowing AI assistants (like Claude Desktop, Cursor, or Windsurf) to view, build, and manage your Pogly overlay layouts and elements directly.

To start the MCP server using `stdio` transport:

```
pogly mcp
```

### Claude Desktop Integration

Add this to your `claude_desktop_config.json` (typically at `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, or `%APPDATA%\Claude\claude_desktop_config.json` on Windows):

```json
{
"mcpServers": {
"pogly": {
"command": "pogly",
"args": ["mcp"]
}
}
}
```

Or for development / running from source:

```json
{
"mcpServers": {
"pogly": {
"command": "cargo",
"args": [
"run",
"--manifest-path",
"/absolute/path/to/pogly-cli/Cargo.toml",
"--bin",
"pogly-cli",
"--",
"mcp"
]
}
}
}
```

## Open Sound Control (OSC) Server

`pogly-cli` can run as a UDP-based OSC listener, allowing you to instantly control your overlay layouts and elements with zero process-spawn overhead. This is perfect for integrations with Stream Deck (via an OSC plugin), TouchOSC, VRChat, or custom script controllers.

To match the native 30Hz server-side update rate, the listener throttles outgoing API updates and automatically deduplicates incoming queues (e.g. merging rapid adjustments so only the latest values are sent within the same tick window).

To start the OSC server:

```
pogly osc --port 9000
```

### Supported OSC Address Routes

| OSC Address | Arguments | Description |
|---|---|---|
| `/pogly/ping` | None | Pings the overlay API to verify connectivity. |
| `/pogly/whoami` | None | Prints the connected API token details and permissions. |
| `/pogly/layouts/set-active`<br>`/pogly/layouts/set_active` | `target` (Int, Long, or String) | Switches active layout (accepts layout ID or layout name). |
| `/pogly/elements/delete` | `id` (Int, Long, or String) | Deletes the element with the specified ID. |
| `/pogly/elements/update/position` | `id` (Int/Long/String), `x` (Int/Long/Float/String), `y` (Int/Long/Float/String) | Moves the element to coordinates `x` and `y`. |
| `/pogly/elements/update/transparency` | `id` (Int/Long/String), `transparency` (Int/Long/Float/String) | Sets element transparency (0-100). |
| `/pogly/elements/update/text` | `id` (Int/Long/String), `text` (String/Int/Float/Bool) | Updates text element text content. |
| `/pogly/elements/update/media/playing` | `id` (Int/Long/String), `playing` (Bool/Int) | Plays or pauses a media element. |
| `/pogly/elements/update/media/volume` | `id` (Int/Long/String), `volume` (Int/Long/Float/String) | Sets media element volume (0-100). |
| `/pogly/elements/update/media/timestamp` | `id` (Int/Long/String), `timestamp` (Int/Long/Float/String) | Seeks media element to timestamp in seconds. |
| `/pogly/elements/update` | `id` (Int/Long/String), `field_name` (String), `value` (Any) | Updates a single field dynamically (e.g. `color`, `textSize`, `alwaysLoaded`). |

Values are automatically coerced to the required type (e.g. float arguments will be converted to integers or booleans where appropriate).

## Building from source

```
Expand Down
2 changes: 2 additions & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ serde_json = "1"
toml = "0.8"
anyhow = "1"
semver = "1"
rosc = "0.10"

15 changes: 15 additions & 0 deletions crates/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ pub enum Cmd {
Folders(FoldersCmd),
/// Show or manage the installed CLI version
Version(VersionCmd),
/// Run the MCP (Model Context Protocol) server
Mcp,
/// Run the OSC (Open Sound Control) listener server
Osc(OscCmd),
}

#[derive(Args)]
Expand Down Expand Up @@ -443,3 +447,14 @@ pub enum FoldersSub {
no_preserve_elements: bool,
},
}

#[derive(Args)]
pub struct OscCmd {
/// Host interface to bind to
#[arg(long, default_value = "127.0.0.1")]
pub host: String,
/// UDP port to listen on
#[arg(long, default_value = "9000")]
pub port: u16,
}

Loading