You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The first SDK call to skills.list() can return an empty list before skill registration finishes. The SDK has no readiness signal, and an empty list is valid, so clients can’t reliably poll.
Plugins
None configured.
OpenCode version
v2.0.18
Steps to reproduce
Start OpenCode with the default configuration.
Call skills.list() through the SDK immediately.
Observe an empty list; call again after startup and observe the registered skills.
This issue might be a duplicate of existing issues. Please check:
#51282: agent.list can return an incomplete plugin-registered list immediately after startup; it specifically suggests checking whether skill.list has the same behavior.
#35556: tracks the related initial plugin-activation race where list operations can observe an empty or partial registry.
Thanks for the report! I could reproduce this on v2.0.18, and it still happens on the latest dev (86ce19d).
What I did:
Started opencode serve in a project that has one skill in .opencode/skills/demo/SKILL.md.
Polled GET /api/skill, which is the endpoint behind skills.list(), as soon as the server accepted requests.
The first successful response was data: [] every time. The same call a few seconds later returned the built-in skills plus demo. The script below reproduces it.
It looks like the agent, model and provider list endpoints wait for plugins to finish loading before they answer, but the skill list endpoint doesn't, so an early call sees an empty list. Adding that same wait to the skill handler fixed it in a local test. Related: #36117 added this wait for the model and provider reads.
Reproduction script (repro.sh)
#!/usr/bin/env bash# Reproduce #51680: GET /api/skill (SDK skills.list()) returns [] right after startup.# Usage: ./repro.sh -> uses `opencode` from PATH# OC_DEV=/path/to/checkout ./repro.sh -> runs the CLI from sourceset -u
export OPENCODE_SERVER_PASSWORD=repro
PORT=${PORT:-47123}
WORK=$(mktemp -d /tmp/opencode/skill-race.XXXX)export HOME=$WORK/home XDG_CONFIG_HOME=$WORK/home/.config XDG_DATA_HOME=$WORK/home/.local/share XDG_STATE_HOME=$WORK/home/.local/state XDG_CACHE_HOME=$WORK/home/.cache
mkdir -p "$WORK/project/.opencode/skills/demo""$HOME"
cat >"$WORK/project/.opencode/skills/demo/SKILL.md"<<'EOF'---name: demodescription: Demo skill for the startup race reproduction---Hello from the demo skill.EOFcd"$WORK/project"&& git init -q
if [ -n"${OC_DEV:-}" ];then
bun --conditions=browser --preload="$OC_DEV/packages/tui/node_modules/@opentui/solid/scripts/preload.js" \
"$OC_DEV/packages/cli/src/index.ts" serve --hostname 127.0.0.1 --port $PORT>"$WORK/serve.log"2>&1&else
opencode serve --hostname 127.0.0.1 --port $PORT>"$WORK/serve.log"2>&1&fi
PID=$!trap'kill $PID 2>/dev/null' EXIT
URL="http://127.0.0.1:$PORT/api/skill?directory=$(python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))'"$WORK/project")"
first=""foriin$(seq 1 600);do
body=$(curl -s -u opencode:repro --max-time 10 "$URL")&&case"$body"in*'"data"'*) first=$body;break;; esac
sleep 0.02
donenames() { python3 -c 'import json,sys;d=json.load(sys.stdin)["data"];print(len(d),"skills:",[x["id"] for x in d])'; }
echo"FIRST successful skill.list: $(echo "$first"| names)"
sleep 10
echo"Same call 10s later: $(curl -s -u opencode:repro "$URL"| names)"
Activity
github-actions commentedon Sep 27, 2026
This issue might be a duplicate of existing issues. Please check:
agent.listcan return an incomplete plugin-registered list immediately after startup; it specifically suggests checking whetherskill.listhas the same behavior.opencodejr commentedon Oct 28, 2026
Thanks for the report! I could reproduce this on v2.0.18, and it still happens on the latest
dev(86ce19d).What I did:
opencode servein a project that has one skill in.opencode/skills/demo/SKILL.md.GET /api/skill, which is the endpoint behindskills.list(), as soon as the server accepted requests.The first successful response was
data: []every time. The same call a few seconds later returned the built-in skills plusdemo. The script below reproduces it.It looks like the agent, model and provider list endpoints wait for plugins to finish loading before they answer, but the skill list endpoint doesn't, so an early call sees an empty list. Adding that same wait to the skill handler fixed it in a local test. Related: #36117 added this wait for the model and provider reads.
Reproduction script (repro.sh)
Run it:
bash repro.sh