with one click
use-vibe-remote
// Safely inspect and modify local Vibe Remote configuration, routing, runtime settings, watches, scheduled tasks, Vibe Cloud remote access, and operational state.
// Safely inspect and modify local Vibe Remote configuration, routing, runtime settings, watches, scheduled tasks, Vibe Cloud remote access, and operational state.
Use `vibe watch` to run a managed Harness waiter that returns to the same conversation later. Best for reviews, CI, files, logs, and other wait-now-continue-later workflows.
Use the official Sentry CLI to investigate issues, events, traces, and logs for Vibe Remote without committing Sentry credentials into the repository.
| name | use-vibe-remote |
| slug | use-vibe-remote |
| description | Safely inspect and modify local Vibe Remote configuration, routing, runtime settings, watches, scheduled tasks, Vibe Cloud remote access, and operational state. |
| version | 0.3.0 |
Use this skill when the user asks you to configure, repair, explain, or operate a local Vibe Remote installation.
Typical requests include:
proxy_url) for an IM platform that cannot reach its API directlyvibe watchvibe taskvibe agent run, including async background runsvibe runsvibe check-update, vibe upgrade)Follow this skill as an operations playbook for agents, not as end-user marketing copy.
POST /settings, preserve every existing channel for that platform; the endpoint replaces the platform's channel map.POST /api/users, merge each edited user with its current user payload first; missing user fields are not a patch.vibe CLI. Vibe Remote's internal storage is opaque — do not read, query, or hand-edit it.POST /config persists the new payload but does not restart running platform adapters by itself. When the change is platform credentials, proxy_url, or other transport-level settings, plan an explicit restart afterwards; prefer the delayed CLI form (vibe restart --delay-seconds 60) when triggering it from inside an active conversation. The only credential save that restarts on its own is the WeChat QR-login completion through POST /wechat/qr_login/poll.POST /doctor, GET /status, and read-back checks first.vibe restart --delay-seconds 60 so the current session can receive the reply before the restart lands.Use this order when changing Vibe Remote configuration:
http://127.0.0.1:5123.ui.setup_host / ui.setup_port), use that exact origin.https://<slug>.avibe.bot) also speaks the same API and requires OIDC session cookies — prefer the local origin from the host running Vibe Remote.GET /health or GET /status.POST /config for global defaults, platform credentials, runtime config, agent defaults, UI config, remote-access provider settings, update policy, or global display togglesPOST /settings for channel-level routing, working directory, visibility, enablement, and mention policy/api/users and /api/bind-codes for DM user binding and user-scope settings/remote-access/* for Vibe Cloud pairing and tunnel controlPOST /doctor only when the change affects runtime health, platform credentials, or backend availability.Mutating API calls require:
Origin or Referer headervibe_csrf_tokenX-Vibe-CSRF-Token headerUse this local curl pattern:
BASE="http://127.0.0.1:5123"
COOKIE_JAR="$(mktemp)"
CSRF="$(
curl -fsS -c "$COOKIE_JAR" "$BASE/api/csrf-token" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["csrf_token"])'
)"
curl -fsS -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
-H "Origin: $BASE" \
-H "X-Vibe-CSRF-Token: $CSRF" \
-H "Content-Type: application/json" \
-X POST "$BASE/doctor" \
--data '{}'
For DELETE, use the same cookie jar, Origin, and CSRF header.
When the Web UI is served through Vibe Cloud, the same calls require an authenticated OIDC session cookie issued by /auth/callback. Prefer hitting 127.0.0.1:5123 directly from the local machine for maintenance work.
Do not log full request bodies when they contain tokens or secrets.
For multi-step maintenance, use the bundled helper at scripts/vibe_api.py instead of hand-writing curl commands. The helper handles CSRF, same-origin headers, cookies, JSON encoding, and readable error output.
Resolve paths relative to this skill directory. If the skill is installed at skills/use-vibe-remote, run:
Usage examples:
export VIBE_UI_BASE="http://127.0.0.1:5123"
python3 skills/use-vibe-remote/scripts/vibe_api.py GET /health
python3 skills/use-vibe-remote/scripts/vibe_api.py GET '/settings?platform=slack'
python3 skills/use-vibe-remote/scripts/vibe_api.py POST /doctor '{}'
python3 skills/use-vibe-remote/scripts/vibe_api.py POST /config '{"show_duration":true}'
python3 skills/use-vibe-remote/scripts/vibe_api.py DELETE '/api/users/U123?platform=slack'
Payload can be passed as inline JSON, as @payload.json, or as - to read JSON from stdin.
For scope updates, still fetch and merge first:
API_HELPER="skills/use-vibe-remote/scripts/vibe_api.py"
python3 "$API_HELPER" GET '/settings?platform=slack' > /tmp/slack_settings.json
python3 - <<'PY'
import json
from pathlib import Path
settings = json.loads(Path("/tmp/slack_settings.json").read_text())
channels = settings.get("channels") or {}
channels["C123"] = {
**channels.get("C123", {}),
"enabled": True,
"show_message_types": channels.get("C123", {}).get("show_message_types") or ["assistant"],
"custom_cwd": channels.get("C123", {}).get("custom_cwd"),
"require_mention": channels.get("C123", {}).get("require_mention"),
"routing": {
**(channels.get("C123", {}).get("routing") or {}),
"agent_backend": "codex",
"codex_model": "gpt-5.4",
"codex_reasoning_effort": "high",
},
}
Path("/tmp/slack_payload.json").write_text(json.dumps({"platform": "slack", "channels": channels}))
PY
python3 "$API_HELPER" POST /settings @/tmp/slack_payload.json
python3 "$API_HELPER" GET '/settings?platform=slack'
Vibe Remote stores runtime data under ~/.vibe_remote/ by default (or VIBE_REMOTE_HOME if set). The only paths an agent normally needs:
~/.vibe_remote/config/config.json — global config; mutate through POST /config, not by editing the file~/.vibe_remote/logs/vibe_remote.log — main application log; read via POST /logs~/.vibe_remote/screenshots/ — default output directory for vibe screenshot~/.vibe_remote/state/user_preferences.md — shared long-term preference file (safe to read and update)Agent harness state is managed through vibe agent run, vibe task, vibe watch, and vibe runs (or their API endpoints), not by editing persistence files. Everything else under state/ and runtime/ is internal — treat it as opaque.
GET /health
{"status":"ok"} when the Web UI server is reachableGET /status
GET /doctor
POST /doctor
POST /logs
{"lines": 500, "source": "service"}source can be service or another source listed in the response; use all for aggregated logsGET /version
GET /api/csrf-token
vibe_csrf_token cookie and returns the matching token value for X-Vibe-CSRF-TokenGET /platforms
/config to see which platforms are enabled and whether credentials are configured.GET /config
POST /config
V2Config.from_payload, then persists itremote_access) reconciles the cloudflared tunnel; running platform adapters keep using their previous credentials and transport until a restart. Plan a vibe restart --delay-seconds 60 after any credential, proxy_url, or transport-level change.Important config payload shape:
{
"platform": "slack",
"platforms": {
"enabled": ["slack", "discord", "telegram", "lark", "wechat"],
"primary": "slack"
},
"mode": "self_host",
"version": "v2",
"slack": {
"bot_token": "xoxb-...",
"app_token": "xapp-...",
"signing_secret": "...",
"team_id": "T...",
"team_name": "...",
"app_id": "A...",
"require_mention": false,
"disable_link_unfurl": false,
"proxy_url": null
},
"discord": {
"bot_token": "...",
"application_id": "...",
"require_mention": false,
"thread_auto_archive_minutes": 10080,
"guild_allowlist": null,
"guild_denylist": null,
"proxy_url": null
},
"telegram": {
"bot_token": "123:abc",
"require_mention": true,
"forum_auto_topic": true,
"use_webhook": false,
"webhook_url": null,
"webhook_secret_token": null,
"allowed_chat_ids": null,
"allowed_user_ids": null,
"proxy_url": null
},
"lark": {
"app_id": "...",
"app_secret": "...",
"require_mention": false,
"domain": "feishu",
"proxy_url": null
},
"wechat": {
"bot_token": "...",
"base_url": "https://ilinkai.weixin.qq.com",
"cdn_base_url": "https://novac2c.cdn.weixin.qq.com/c2c",
"require_mention": false,
"proxy_url": null
},
"runtime": {
"default_cwd": "/path/to/workdir",
"log_level": "INFO"
},
"agents": {
"default_backend": "opencode",
"opencode": {
"enabled": true,
"cli_path": "opencode",
"default_agent": null,
"default_model": null,
"default_reasoning_effort": null,
"error_retry_limit": 1
},
"claude": {
"enabled": true,
"cli_path": "claude",
"default_model": null,
"idle_timeout_seconds": 600
},
"codex": {
"enabled": true,
"cli_path": "codex",
"default_model": null,
"idle_timeout_seconds": 600
}
},
"ui": {
"setup_host": "127.0.0.1",
"setup_port": 5123,
"open_browser": true
},
"remote_access": {
"provider": "vibe_cloud",
"vibe_cloud": {
"enabled": false,
"backend_url": "https://avibe.bot",
"public_url": "",
"instance_id": "",
"client_id": "",
"issuer": "",
"authorization_endpoint": "",
"token_endpoint": "",
"jwks_uri": "",
"redirect_uri": "",
"tunnel_token": "",
"instance_secret": "",
"session_secret": "",
"cloudflared_path": "",
"dev_login_hint": ""
}
},
"update": {
"auto_update": true,
"check_interval_minutes": 60,
"idle_minutes": 30,
"notify_admins": true
},
"ack_mode": "typing",
"language": "en",
"show_duration": false,
"include_time_info": true,
"include_user_info": true,
"reply_enhancements": true
}
Discord server access belongs to /settings, not /config. Store enabled
servers under guilds, next to channel settings:
{
"platform": "discord",
"guilds": {
"900740769198006293": { "enabled": true }
},
"channels": {
"1067738479234138202": { "enabled": true }
}
}
When switching the active platform, update platforms.primary and make sure platforms.enabled contains the new primary. Keep the legacy platform field aligned for readability, but platforms.primary is the real multi-platform source of truth.
Per-platform fields worth knowing about:
proxy_url from the shared BaseIMConfig. Set it when the host machine cannot reach the upstream API directly. Accepts standard HTTP/HTTPS proxy URLs and any socks*:// URL (socks4, socks4a, socks5, socks5h). SOCKS variants route through aiohttp_socks.slack.disable_link_unfurl suppresses link previews when posting messages.discord.thread_auto_archive_minutes must be one of 60, 1440, 4320, or 10080.discord.guild_allowlist / guild_denylist are legacy input lists; current runtime server access lives in /settings under guilds.telegram.forum_auto_topic enables automatic topic creation in forum chats; use_webhook plus webhook_url / webhook_secret_token switches Telegram delivery to the webhook transport.telegram.allowed_chat_ids / allowed_user_ids restrict which chats and users Telegram will respond to.wechat.cdn_base_url controls the CDN host used for fetching WeChat media; the default novac2c.cdn.weixin.qq.com is the official c2c CDN.update.auto_update, check_interval_minutes, and idle_minutes control unattended upgrades; notify_admins posts the upgrade announcement to bound admins.ui.setup_host, setup_port, and open_browser configure the local Web UI server; changing host or port requires POST /ui/reload.Secret-bearing config fields that you should not print:
slack.bot_tokenslack.app_tokenslack.signing_secretdiscord.bot_tokentelegram.bot_tokentelegram.webhook_secret_tokenlark.app_id (treat as a sensitive identifier)lark.app_secretwechat.bot_tokengateway.workspace_tokengateway.client_secretremote_access.vibe_cloud.tunnel_tokenremote_access.vibe_cloud.instance_secretremote_access.vibe_cloud.session_secretremote_access.vibe_cloud.client_idproxy_url value that embeds credentials such as user:pass@hostGET /settings?platform=<platform>
POST /settings
{"platform": "<platform>", "channels": {...}}Important: POST /settings replaces the entire channels map for the selected platform. To change one channel:
GET /settings?platform=<platform>response.channelsPOST /settings with the full merged channels objectGET /settings?platform=<platform> again and verifyChannel entry shape:
{
"enabled": true,
"show_message_types": ["assistant"],
"custom_cwd": "/path/to/repo",
"require_mention": null,
"routing": {
"agent_backend": "codex",
"model": "gpt-5.4",
"reasoning_effort": "high",
"opencode_agent": null,
"opencode_model": null,
"opencode_reasoning_effort": null,
"claude_agent": null,
"claude_model": null,
"claude_reasoning_effort": null,
"codex_agent": "reviewer",
"codex_model": "gpt-5.4",
"codex_reasoning_effort": "high"
}
}
Field meanings:
enabled: whether this channel is allowed to use Vibe Remoteshow_message_types: visible intermediate messages; allowed values are system, assistant, toolcallcustom_cwd: scope-level working directory override; empty string or null means use global defaultrequire_mention: null inherits the platform default, true requires mention, false disables mention gating for that channelrouting.agent_backend: opencode, claude, codex, or null to inherit defaultrouting.model: canonical scope-level model override for the selected backendrouting.reasoning_effort: canonical scope-level reasoning override for the selected backendrouting.<backend>_agent: backend-specific subagentrouting.<backend>_model / routing.<backend>_reasoning_effort: legacy aliases accepted on input and derived on read-back; do not treat them as independent stateGET /api/users?platform=<platform>
POST /api/users
{"platform": "<platform>", "users": {...}}dm_chat_idPOST /api/users/<user_id>/admin
{"platform": "<platform>", "is_admin": true}DELETE /api/users/<user_id>?platform=<platform>
GET /api/bind-codes
POST /api/bind-codes
{"type": "one_time"} or {"type": "expiring", "expires_at": "2026-04-18"}DELETE /api/bind-codes/<code>
GET /api/setup/first-bind-code
Important: user updates are not field patches. Before changing a user's routing, cwd, visibility, or enabled flag, read the current user object and send the merged full user entry.
User entry shape:
{
"display_name": "Alice",
"is_admin": false,
"bound_at": "2026-03-20T12:34:56+00:00",
"enabled": true,
"show_message_types": ["assistant"],
"custom_cwd": "/path/to/repo",
"routing": {
"agent_backend": "claude",
"model": "claude-sonnet-4-6",
"reasoning_effort": "high",
"opencode_agent": null,
"opencode_model": null,
"opencode_reasoning_effort": null,
"claude_agent": "reviewer",
"claude_model": "claude-sonnet-4-6",
"claude_reasoning_effort": "high",
"codex_agent": null,
"codex_model": null,
"codex_reasoning_effort": null
}
}
DM caveat: current DM authorization checks whether the user is bound, not whether enabled is true. If the user wants to revoke DM access, use DELETE /api/users/<user_id>?platform=<platform> instead of only setting enabled to false.
GET /slack/manifest
POST /slack/auth_test
{"bot_token": "xoxb-..."}POST /slack/channels
{"bot_token": "xoxb-...", "browse_all": false}POST /discord/auth_test
{"bot_token": "..."}POST /discord/guilds
{"bot_token": "..."}POST /discord/channels
{"bot_token": "...", "guild_id": "..."}POST /telegram/auth_test
{"bot_token": "123:abc"}POST /telegram/chats
{"include_private": false}POST /lark/auth_test
{"app_id": "...", "app_secret": "...", "domain": "feishu"}POST /lark/chats
{"app_id": "...", "app_secret": "...", "domain": "feishu"}POST /lark/temp_ws/start
{"app_id": "...", "app_secret": "...", "domain": "feishu"}POST /lark/temp_ws/stop
{}POST /wechat/qr_login/start
{"base_url": "https://ilinkai.weixin.qq.com"} or {}POST /wechat/qr_login/poll
{"session_key": "..."}WeChat QR login is special: when login is confirmed and a token is returned, the API auto-binds the WeChat user and schedules an internal service restart so the new token can take effect. Do not add an extra restart unless the user asks.
These endpoints drive the managed avibe.bot tunnel that exposes the local Web UI to other devices. They are paired with the remote_access.vibe_cloud block under /config.
GET /remote-access/status
enabled, paired, public_url, running (tunnel up), pid, pid_state, plus binary_found / binary_path / binary_version for the resolved cloudflared executable. Use running: true to assert the tunnel is up.POST /remote-access/vibe-cloud/pair
{"pairing_key": "vrp_..."}remote_access.vibe_cloud block; on success Vibe Remote launches the cloudflared tunnelPOST /remote-access/start
{}POST /remote-access/stop
{}start can resume laterGET /auth/callback
GET /api/session
200 with an auth-state payload, never 401. Three shapes: {"remote": false} when remote access is not configured for this request, {"remote": true, "authenticated": false} when remote access is on but the caller has no valid session cookie, and {"remote": true, "authenticated": true, "email": "..."} when signed in. Check authenticated to gate behavior; do not poll for HTTP status codes.POST /auth/logout
The session cookie is bound to the tunnel session and expires after roughly 24 hours; the server slides the TTL when activity reaches the half-life. Do not invent custom auth headers — rely on the existing cookie issued by /auth/callback.
Treat tunnel_token, instance_secret, session_secret, and client_id from remote_access.vibe_cloud as opaque secrets.
GET /cli/detect?binary=<name-or-path>
POST /agent/<name>/install
name must be opencode, claude, or codexPOST /opencode/options
{"cwd": "/path/to/repo"}POST /opencode/setup-permission
permission to allowGET /claude/agents?cwd=/path/to/repoGET /codex/agents?cwd=/path/to/repoGET /claude/modelsGET /codex/modelsPOST /browse
{"path": "~", "show_hidden": false}POST /control
{"action": "start"}, {"action": "stop"}, or {"action": "restart"}POST /ui/reload
{"host": "127.0.0.1", "port": 5123}POST /upgrade
{}vibe upgradeAvoid these for routine configuration. POST /control starts, stops, or restarts the service. POST /ui/reload restarts only the Web UI server to apply host or port changes. POST /upgrade reinstalls Vibe Remote and then restarts the service. Use them only with explicit user intent or a concrete need.
When the restart is initiated by an agent from an active conversation, use the CLI delayed form vibe restart --delay-seconds 60 so the transport does not cut off the current reply.
Backend resolution priority is:
/settings or /api/users/configIf the user names a specific channel or DM and wants a specific backend, use the scope API, not global /config.
Working directory resolution is:
custom_cwd on the target channel or user scoperuntime.default_cwd from /configshow_message_types is scope-local. Preserve existing values unless the user wants an explicit replacement.
If a user asks for "vault messages", "internal messages", or "tool execution messages", map that request to show_message_types. Current Vibe Remote does not expose a separate vault field.
require_mention works like this:
null: inherit platform default from /configtrue: require mention in that channelfalse: do not require mention in that channelGoal:
C123reviewergpt-5.4highAPI flow:
GET /settings?platform=slackchannels.C123POST /settings with all Slack channelsGET /settings?platform=slackMerged channel entry:
{
"enabled": true,
"show_message_types": ["assistant"],
"custom_cwd": null,
"require_mention": null,
"routing": {
"agent_backend": "codex",
"model": "gpt-5.4",
"reasoning_effort": "high",
"opencode_agent": null,
"opencode_model": null,
"opencode_reasoning_effort": null,
"claude_agent": null,
"claude_model": null,
"claude_reasoning_effort": null,
"codex_agent": "reviewer",
"codex_model": "gpt-5.4",
"codex_reasoning_effort": "high"
}
}
Use /settings and set:
routing.agent_backend = "opencode"routing.opencode_agent = "<agent>"routing.model = "<model>" if requestedrouting.reasoning_effort = "<effort>" if requestedIf the user wants OpenCode-native defaults, providers, MCP servers, skills, plugins, or API credentials, use OpenCode config instead of Vibe Remote scope routing.
Use /settings for a channel or /api/users for a DM user and set:
routing.agent_backend = "claude"routing.claude_agent = "<agent>" if requestedrouting.model = "<model>"routing.reasoning_effort = "<effort>"The API normalizes Claude reasoning for incompatible model combinations; verify by reading back the saved payload.
Use POST /config:
{
"runtime": {
"default_cwd": "/path/to/workdir"
}
}
Do not overwrite scope-level custom_cwd entries.
Use /settings and add toolcall to the target channel's show_message_types.
Preserve existing system and assistant values unless the user asked for a full replacement.
Use POST /config and keep platforms.enabled complete:
{
"platform": "discord",
"platforms": {
"enabled": ["slack", "discord"],
"primary": "discord"
}
}
Make sure the target platform config section exists and validates. Do not delete old platform config unless the user explicitly asks.
When the host cannot reach a platform API directly, set proxy_url on that platform's config block.
Use POST /config with only the proxy field for the affected platform:
{
"telegram": {
"proxy_url": "http://proxy.internal:3128"
}
}
Notes:
proxy_url accepts http://, https://, and any socks*:// scheme (socks4, socks4a, socks5, socks5h). The SOCKS variants route through aiohttp_socks (bundled).null (or omit it on a fresh save) to disable the proxy.POST /config only persists the new value; running platform adapters keep their old transport until the service restarts. After saving, run vibe restart --delay-seconds 60 (or POST /control {"action":"restart"} with the user's confirmation) so the proxy applies to live connections.user:pass@host) into logs or chat replies; mask the credentials portion when reporting back.Goal: connect the local Web UI to avibe.bot so it is reachable from another device.
https://avibe.bot, creates a remote-access bot, and copies the one-time pairing key (format vrp_...).POST /remote-access/vibe-cloud/pair with {"pairing_key": "vrp_..."} from the local Web UI origin.GET /remote-access/status — enabled: true, paired: true, public_url populated, running: true.public_url and sign in with the same avibe.bot account.Alternatively, drive the same flow from the CLI:
vibe remote # guided flow
vibe remote pair vrp_abc123 # paste key directly
vibe remote status --json # inspect tunnel state
vibe remote stop # stop tunnel; keep config
vibe remote start # bring tunnel back up
Treat the pairing key, tunnel token, instance secret, and session secret as opaque. Never echo them in chat replies.
Use POST /api/bind-codes:
{
"type": "one_time"
}
For an expiring code:
{
"type": "expiring",
"expires_at": "2026-04-18"
}
Do not expose bind codes unless the user explicitly asks for them.
Use the harness commands when the user wants an agent to leave the current turn and continue later, repeatedly, or in the background. The mental model is:
vibe agent run: run one concrete Agent job now; add --async when it should continue in the backgroundvibe task: save a time trigger that creates Agent Runs latervibe watch: save a condition trigger that waits for a process, file, log, CI, review, or other signal, then creates a follow-up Agent Runvibe runs: inspect and cancel concrete run recordsAgents should prefer these managed harness commands over ad-hoc detached shells when the work should be inspectable, resumable, or report back to the conversation.
Preferred CLI shape:
vibe agent run --agent '<agent-name>' --message '...'vibe agent run --async --session-id '<session-id>' --message '...'vibe task add --session-id '<session-id>' --cron '<expr>' --message '...'vibe task add --session-id '<session-id>' --at '<ISO-8601>' --message '...'vibe task run <id>vibe watch add --session-id '<session-id>' --message '...' -- <cmd> (or --shell '<cmd>' to pass a single shell string)vibe watch update <id> --name '...' --timeout 1200vibe runs show <run-id>vibe runs cancel <run-id>Delivery controls (apply to vibe agent run --create-session, vibe task add, and vibe watch add):
--session-id controls which Agent Session Vibe Remote continues using--post-to channel when the task or watch should keep the same Agent Session but publish to the parent channel--deliver-key '<key>' only when delivery must go to a different explicit target than the continued session--post-to and --deliver-key in the same command--message and --message-file are the current user-message flags for task, watch, and agent-run commandsvibe task add stores the message template and creates Agent Runs when the time trigger firesvibe agent run --async queues one Agent Run immediately without storing a task definitionvibe watch add uses --message as the instruction template for the Agent Run created after the waiter reaches a reportable stateLegacy compatibility:
--session-key is still accepted for old scripts; do not use it in new examples or instructions unless the user explicitly asks for legacy targeting--prompt / --prompt-file are deprecated compatibility inputs. Do not use them in new invocations; use --message / --message-file.vibe hook send is deprecated. Do not use it for new one-shot async work; use vibe agent run --async.Operational guidance:
vibe task list before editing or deleting an existing task; use vibe watch list before touching a managed watchvibe task add, vibe agent run, vibe runs, or vibe watch add, read the matching --help output first — watches accept additional flags like --shell, --timeout (per-cycle), --lifetime-timeout (overall), --forever, --retry-exit-code, and --retry-delayvibe task update <id> to keep the same task ID while changing name, schedule, message, agent, or targetvibe watch update <id> ... when you must rename, retarget, or change the waiter/optionsvibe task list --brief and vibe watch list --brief for scheduling-focused summariesvibe task list hides completed one-shot tasks by default; use vibe task list --all when you need full historyvibe task show <id>, vibe watch show <id>, or vibe runs show <run-id> to inspect stored fields and runtime statevibe task pause / vibe task resume and vibe watch pause / vibe watch resume to disable a task or watch without deleting itwarnings from task, watch, agent-run, or runs commands as delivery-risk hints to fix proactivelyCurrent Vibe Remote routing support is:
| Backend | Channel/User backend select | Subagent | Model | Reasoning |
|---|---|---|---|---|
| OpenCode | yes | yes | yes | yes |
| Claude | yes | yes | yes | yes |
| Codex | yes | yes | yes | yes |
Behavior notes:
routing.opencode_agent or through prefix routing such as reviewer: ....routing.claude_agent or prefix routing.routing.codex_agent or prefix routing.routing.claude_reasoning_effort; common values are low, medium, and high, and some models also allow max.If the user asks for subagents, remember:
planner: draft a migration plan~/.claude/agents/.claude/agents/~/.codex/agents/.codex/agents/When the request belongs to the host backend, do not force it into Vibe Remote config.
Use OpenCode-native config when the user wants to change:
Important locations:
~/.config/opencode/opencode.json: global OpenCode configopencode.json: project-level OpenCode config file.opencode/: project-local OpenCode config directory~/.config/opencode/agents/: global OpenCode agents.opencode/agents/: project-local OpenCode agents~/.config/opencode/skills/: global OpenCode skills.opencode/skills/: project-local OpenCode skillsRelevant docs:
https://opencode.ai/docs/config/https://opencode.ai/docs/skillshttps://opencode.ai/docs/plugins/https://opencode.ai/docs/mcp-servers/Inside Vibe Remote, OpenCode scope routing controls backend choice, subagent, model, and reasoning effort. Use POST /opencode/setup-permission only for the specific permission helper.
Use Claude-native config when the user wants to change:
Important locations:
~/.claude/agents/: global Claude subagents.claude/agents/: project subagents~/.claude/skills/: global Claude skills.claude/skills/: project skillsRelevant docs:
https://docs.anthropic.com/en/docs/claude-code/sub-agentsInside Vibe Remote, Claude scope routing controls backend choice, model, subagent, and reasoning effort.
Use Codex-native config when the user wants to change:
Important locations:
~/.codex/config.toml: global Codex config.codex/config.toml: project-local Codex config~/.codex/agents/: global Codex custom agents.codex/agents/: project-local Codex custom agentsRelevant docs:
https://developers.openai.com/codex/config-basic/https://developers.openai.com/codex/config-reference/https://developers.openai.com/codex/clihttps://developers.openai.com/codex/subagentsInside Vibe Remote, Codex scope routing controls backend choice, subagent, model, and reasoning effort.
Use the CLI only when the Web UI API cannot cover the request, when the user explicitly asks for the command, or when restarting/upgrading from an active conversation.
Service lifecycle:
vibe — start Vibe Remote if needed and open the local Web UI; it does not stop an already-running servicevibe status — print service status, PID metadata, and last actionvibe stop — stop main service, Web UI, and any background helpersvibe restart — stop and re-start the service. Pass --delay-seconds N when triggering from inside an active conversation so the current reply has time to deliver before the restart lands.vibe doctor — run diagnostics and print the latest resultvibe version — print the installed versionUpdates:
vibe check-update — query the release feed and print whether an upgrade is availablevibe upgrade — reinstall Vibe Remote to the latest release. The CLI does not restart the service for you; it prints "Please restart vibe..." and exits. Run vibe restart (or vibe restart --delay-seconds 60 from inside an active conversation) yourself after the upgrade reports success. The Web UI's POST /upgrade endpoint is the path that performs an automatic restart.Remote access:
vibe remote — guided Vibe Cloud pairingvibe remote pair <key> — pair using an existing one-time keyvibe remote status [--json] — show tunnel + OIDC statevibe remote start / vibe remote stop — manage the cloudflared tunnel after pairingScreenshots:
vibe screenshot — capture the local desktop to ~/.vibe_remote/screenshots/vibe screenshot --output <path> / --json — pick an explicit output path or get machine-readable outputScheduled tasks:
vibe task add, vibe task update, vibe task list [--all|--brief], vibe task show <id>, vibe task run <id>, vibe task pause <id>, vibe task resume <id>, vibe task remove <id>Agent runs:
vibe agent run — run one Agent job now; add --async for one-shot background workvibe runs list, vibe runs show <id>, vibe runs cancel <id> — inspect and manage concrete Agent Run recordsWatches:
vibe watch add, vibe watch update <id>, vibe watch list [--brief], vibe watch show <id>, vibe watch pause <id>, vibe watch resume <id>, vibe watch remove <id>For any subcommand, prefer <command> --help before composing a new invocation. The delivery flags shared by harness commands are --session-id, --post-to, and --deliver-key, with command-specific mutual exclusion rules. Use --message / --message-file for user messages. vibe task add and vibe watch add take --name; only vibe task add takes --cron / --at / --timezone; vibe agent run takes --async; and vibe watch add takes its own waiter options (--shell or a positional command after --, --cwd, --timeout, --forever, --lifetime-timeout, --retry-exit-code, --retry-delay). Do not copy flags between task, watch, and agent-run commands without checking help.
Start with evidence:
GET /statusPOST /doctorPOST /logs with a small line count and focused source/config, /settings, or /api/users for the affected scopeCommon cases:
/cli/detect finds it/settings?platform=<platform> contains the channel and enabled is truecustom_cwd and runtime.default_cwd/api/users?platform=<platform> and bind-code stateproxy_url on that platform's config block; check logs for proxy/TLS errors; for SOCKS proxies confirm aiohttp_socks is installedGET /remote-access/status should show running: true and binary_found: true; if not, run POST /doctor and check the configured cloudflared_pathPOST /auth/logout to clear a stale session on the current devicePOST /upgrade (auto-restart on success) or vibe upgrade (does not auto-restart — run vibe restart manually), then verify with vibe status that the new PID is runningGET /status, POST /doctor, then inspect logsDo not use vibe restart, POST /control {"action":"restart"}, or POST /ui/reload as a first response to config problems.
If a restart is still required and you are replying through an active Vibe Remote conversation, use vibe restart --delay-seconds 60 so the current reply can be delivered before the restart lands.
Always follow these constraints:
vibe CLIproxy_url (user:pass@host) back into chat — mask the credentials portion when echoing the valueIf the user still cannot solve a problem after API read-back checks, doctor, and log inspection, point them to the Vibe Remote repository:
https://github.com/cyhhao/vibe-remoteUse that link when:
If the user wants to contribute back, suggest opening an issue or a pull request in that repository.
When you complete a Vibe Remote maintenance task, report back with: