OpenCode plugin that displays your AI session status in Discord.
Status: v3.1.8 (daemon-based push, multi-instance safe). A long-lived daemon holds the single Discord IPC connection for the whole machine. OpenCode plugin instances connect to it via local Unix socket and forward their state. Handoff between OpenCode windows no longer disconnects from Discord.
- Daemon-based push:
src/worker/daemon.mjsis a long-lived subprocess that owns the Discord connection. All OpenCode plugin instances connect to it via local Unix socket and forward their rendered presence payload. The daemon picks the global most-recently-active instance and pushes to Discord in place. - Display survives terminal switching: when you switch OpenCode windows, the same Discord connection just shows the new state (no reconnect, no "display disappears" gap).
- Display survives exit-and-reopen: close all OpenCode windows, reopen, fire a message, the display comes back instantly. The daemon stays alive (no Discord reconnect, no app-id cooldown exposure).
- Activity log at
~/.config/opencode/presence-activity.logthat records every plugin action (events, state transitions, template renders, daemon sends, push events). PID-tagged for easy filtering when multiple OpenCode windows are open. - Per-instance state snapshot at
~/.config/opencode/presence-state-pid<pid>.txtshowing what each OpenCode instance is rendering. - Crash diagnostics built-in:
uncaughtException,unhandledRejection,beforeExit, andexithandlers log every abnormal exit path so silent daemon deaths have a trail.
- Node.js 18+ (LTS recommended; CI tests on 20, 22, 24)
- OpenCode CLI
- Discord Desktop (required for v3 Phase 2 push)
Works on Linux and macOS. Windows requires named-pipe support which is not part of CI; the daemon falls back to a named-pipe on Windows but it is not actively tested.
Pick one install path.
curl -fsSL https://raw.githubusercontent.com/Khip01/opencode-rich-presence/main/install.sh | bashThis downloads the latest stable release tarball, installs it via
npm install -g <tarball>, and runs opencode-rpc install to set
up the plugin symlink and config. Pin to a specific version:
curl -fsSL https://raw.githubusercontent.com/Khip01/opencode-rich-presence/main/install.sh \
| ORP_VERSION=v3.1.8 bashIf you do not have curl, replace it with wget -qO- <url> or
fetch the script manually and bash ./install.sh.
Pure cmd.exe / PowerShell users: the script runs in bash. Open Git Bash (ships with Git for Windows) and run it from there.
- Download the tarball for your platform from
GitHub Releases.
The tarball name is
opencode-rich-presence-<version>.tgzand works on any platform with Node.js 18+. - Install it:
npm install -g ./opencode-rich-presence-3.1.8.tgz
- Continue with step 2 below.
opencode-rpc installThis creates ~/.config/opencode/discord-config.json from the
bundled example (only if missing, or after confirmation to
overwrite) and symlinks the plugin entry to
~/.config/opencode/plugins/opencode-rich-presence.js. v3 installs
no additional npm dependencies.
If OpenCode is already installed, install.sh runs this step for
you. Skip it if you already saw the Replaced / Linked line.
The plugin loads automatically via the symlink. After OpenCode restart:
opencode-rpc infoinfo shows the last 30 entries of the activity log so you can
verify the plugin captured events, the daemon is connected, and
Discord is reporting presence.
For detailed setup (creating your own Discord App, advanced
config), see docs/INSTALL.md.
opencode-rpc <command> [options]| Command | Description |
|---|---|
install |
Set up the plugin (config + symlink). v3 installs no deps. |
uninstall |
Remove generated files; back up config to timestamped file |
restart |
Kill the daemon so the next chat.message spawns a fresh one. |
update |
Upgrade to latest stable release tag |
update --stable |
Force-install latest stable tag (skip version check) |
update --dev [BRANCH] |
Upgrade to latest commit on BRANCH (default: main, currently v3.1.8) |
update --ref REF |
Install a specific ref (tag, branch, or commit SHA) |
update --repo OWNER/REPO |
Install from a fork instead of upstream |
info |
Diagnostics: paths, config, daemon status, activity log tail |
version |
Print package version and channel |
help |
Show usage |
Full reference: docs/CLI-REFERENCE.md
opencode-rpc update # latest stable release tag (v3.1.8 today)
opencode-rpc update --stable # force install latest stable tag
opencode-rpc update --dev <branch> # latest commit on <branch> (developer)
opencode-rpc update --ref <ref> # specific ref (tag, branch, or SHA)
opencode-rpc update --repo <fork> # install from a forkAll four flags are mutually exclusive. update always installs from
a local tarball (clone + npm pack + npm install -g <tarball>)
so it sidesteps the npm v11 git-dep bug described at the bottom of
this file.
tail -f ~/.config/opencode/presence-activity.logEach line:
[2026-07-05 14:30:25.789] [pid 12345] [tag] message
Tags you'll see:
| Tag | Meaning |
|---|---|
load |
plugin lifecycle |
event |
raw SDK event received |
state |
session state transition |
template |
presence template render (source -> output) |
push |
real push to Discord via the daemon (or would-push in local-only fallback) |
display |
which session is the displayed one |
queue |
session added/removed from local tracking |
stats |
cost / tokens / context% updates |
check |
periodic SDK poll |
daemon |
plugin-side daemon connection events (spawn, connect, disconnect) |
presence |
Phase 2 start/stop markers |
For full troubleshooting, see docs/TROUBLESHOOTING.md.
If the display stops updating:
tail -200 ~/.config/opencode/presence-activity.log | grep -E "daemon|instance|push|EPIPE|exit code"Expected on a healthy install:
- One
daemon startingline peropencode-rpc restart. - Zero
exit code=1lines. - Zero
uncaughtExceptionorunhandledRejectionlines. - One
push pid=...line perchat.messageevent.
If you see uncaughtException: Error: write EPIPE followed by
exit code=1, you are on a version older than v3.0.4-phase2 and
need to upgrade (opencode-rpc update --ref v3.0.4-phase2 or
newer).
Edit ~/.config/opencode/discord-config.json:
{
"discordAppId": "YOUR_APP_ID",
"discordLargeImageKey": "your-asset-key",
"currency": "$",
"presence": {
"details": "{model} ({mode})",
"state": "{state} · {contextCompact}",
"byState": {
"Typing": {
"state": "{{#if contextPercent > 80}}⚠️ {contextCompact} full{{else}}{contextCompact} ctx{{/if}}"
}
}
}
}| Variable | Example | Description |
|---|---|---|
{model} |
minimax-m3 |
Model in use |
{mode} |
build, plan |
Agent mode |
{state} |
Working, Thinking |
Current state |
{context} |
45,321 |
Tokens used (raw) |
{contextCompact} |
45.3K |
Tokens used (compact) |
{contextPercent} |
23.7 |
Context percentage |
{contextLimit} |
262,144 |
Model context limit |
{prompts} |
12 |
User prompt count |
{promptsCompact} |
1.5K |
Prompt count (compact) |
{cost} |
$0.0042 |
Session cost |
{costCompact} |
$1.5K |
Session cost (compact) |
{elapsed} |
1h 23m |
Session duration |
{provider} |
Khip01 |
Provider name |
Plus conditionals ({{#if mode == "build"}}...{{/if}}) and fallbacks
({var|fallback}).
See docs/CUSTOMIZATION.md for full syntax.
Linux, macOS, and Windows are all supported. See
docs/PLATFORM-NOTES.md for per-OS
details (Flatpak/Snap detection, AppleScript quit, taskkill quirks,
named pipes).
See docs/ARCHITECTURE.md for the full
design (template engine, per-instance state, daemon lifecycle,
single-connection rationale).
If you have ever seen this after npm install -g <repo>#<tag>:
$ npm install -g 'Khip01/opencode-rich-presence#v3.1.8'
added 1 package in 4s
$ opencode-rpc
zsh: command not found: opencode-rpc
$ npm list -g opencode-rich-presence
└── opencode-rich-presence@ -> ./../../../../../.npm/_cacache/tmp/git-cloneAmM1cO
You have hit an npm v11 bug. It is on npm's side, not the package's, and there is no fix from the package side.
When installing a global git dep like <owner>/<repo>#<ref>, npm
v11:
- Clones the repo to a temp dir under
~/.npm/_cacache/tmp/. - Symlinks
lib/node_modules/<repo>to that temp dir. - Should create
bin/<binary>symlinks into the package... but does not.
The result: npm list -g shows the package, the directory exists,
but the CLI binary is missing. The bug is consistent across
branches, tags, and commit SHAs, and across npm v11.0.0 through at
least v11.8.0.
The temp dir also gets cleaned up by npm cache clean --force or
when the system reboots with tmpfs-backed /tmp paths on some
configurations. After cleanup the symlink dangles and the install
appears to vanish.
The bug is in npm's git-dep install handler, not in
opencode-rich-presence. Even with a complete package.json,
correct bin entries, and no files filter, npm v11 still omits
the bin symlink for global git deps.
- Use the curl installer above. It downloads a real tarball
and runs
npm install -g <tarball>. Tarball installs are not affected by the bug. - Manual tarball install from GitHub Releases.
opencode-rpc update --ref <tag>for upgrades after the curl installer has putopencode-rpcon PATH.
All three paths install from a local tarball, which sidesteps the git-dep handler entirely.
v1.0.0 used bash scripts and was Linux-only. See
CHANGELOG.md for the migration guide.
MIT