
Plugin Store
- 473 installs
- 12 repo stars
- Updated August 3, 2026
- okx/plugin-store
plugin-store is an agent skill that discovers, installs, configures, and manages OKX Plugin Store extensions for developers who need vetted third-party capabilities added to an agent toolchain.
About
plugin-store from okx/plugin-store is an agent skill for working with the OKX Plugin Store ecosystem. It helps developers discover available extensions, install them into an agent environment, apply configuration, and manage the lifecycle of third-party plugins that extend trading, data, or automation capabilities within OKX-aligned agent workflows. Teams reach for plugin-store when building or operating agents that rely on OKX's curated extension catalog instead of ad-hoc script integration. The skill centralizes store navigation, install steps, and config updates so agents can add capabilities without manual store UI repetition. It fits early integration phases where the right plugin must be selected, vetted, and wired before downstream agent logic references new tools or APIs exposed by the extension.
- Plugin discovery
- Install flows
- Capability extension
- OKX ecosystem
- Agent tools
Plugin Store by the numbers
- 473 all-time installs (skills.sh)
- +22 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,832 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/okx/plugin-store --skill plugin-storeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 473 |
|---|---|
| repo stars | ★ 12 |
| Last updated | August 3, 2026 |
| Repository | okx/plugin-store ↗ |
How do you install OKX Plugin Store extensions for agents?
Discover, install, configure, and manage OKX Plugin Store extensions that extend agent toolchains with vetted third-party capabilities.
Who is it for?
Developers building OKX-aligned agents who need programmatic discovery and management of Plugin Store extensions.
Skip if: Projects outside the OKX plugin ecosystem or teams hand-rolling integrations without a store-backed extension model.
When should I use this skill?
User asks to browse, install, configure, or manage OKX Plugin Store plugins for an agent environment.
What you get
Installed and configured OKX Plugin Store extensions registered in the agent toolchain.
- Installed plugin extensions
- Updated agent plugin configuration
Files
Pre-flight Dependencies (auto-injected by Plugin Store CI)
Run once per session before first use. These checks ensure required tools are installed.
Install onchainos CLI + Skills (auto-injected)
# 1. Install onchainos CLI — pin to latest release tag, verify SHA256
# of the installer before executing (no curl|sh from main).
if ! command -v onchainos >/dev/null 2>&1; then
set -e
LATEST_TAG=$(curl -sSL --max-time 5 \
"https://api.github.com/repos/okx/onchainos-skills/releases/latest" \
| sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
if [ -z "$LATEST_TAG" ]; then
echo "ERROR: failed to resolve latest onchainos release tag (network or rate limit)." >&2
echo " Manual install: https://github.com/okx/onchainos-skills" >&2
exit 1
fi
ONCHAINOS_TMP=$(mktemp -d)
curl -sSL --max-time 30 \
"https://raw.githubusercontent.com/okx/onchainos-skills/${LATEST_TAG}/install.sh" \
-o "$ONCHAINOS_TMP/install.sh"
curl -sSL --max-time 30 \
"https://github.com/okx/onchainos-skills/releases/download/${LATEST_TAG}/installer-checksums.txt" \
-o "$ONCHAINOS_TMP/installer-checksums.txt"
EXPECTED=$(awk '$2 ~ /install\.sh$/ {print $1; exit}' "$ONCHAINOS_TMP/installer-checksums.txt")
if command -v sha256sum >/dev/null 2>&1; then
ACTUAL=$(sha256sum "$ONCHAINOS_TMP/install.sh" | awk '{print $1}')
else
ACTUAL=$(shasum -a 256 "$ONCHAINOS_TMP/install.sh" | awk '{print $1}')
fi
if [ -z "$EXPECTED" ] || [ "$EXPECTED" != "$ACTUAL" ]; then
echo "ERROR: onchainos installer SHA256 mismatch — refusing to execute." >&2
echo " expected=$EXPECTED actual=$ACTUAL tag=$LATEST_TAG" >&2
rm -rf "$ONCHAINOS_TMP"
exit 1
fi
sh "$ONCHAINOS_TMP/install.sh"
rm -rf "$ONCHAINOS_TMP"
set +e
fi
# 2. Install onchainos skills (enables AI agent to use onchainos commands)
npx skills add okx/onchainos-skills --yes --global
# 3. Install plugin-store skills (enables plugin discovery and management)
npx skills add okx/plugin-store --skill plugin-store --yes --global---
Plugin Store
A CLI marketplace for installing/uninstalling/updating Skills and MCP servers across Claude Code, Cursor, and OpenClaw. Also an open-source community platform where any developer can submit plugins.
Pre-flight Checks
Run once per session before the first plugin-store command. Do not echo routine output to the user.
1. Check binary version
plugin-store --version 2>/dev/null || ~/.local/bin/plugin-store --version 2>/dev/null || ~/.cargo/bin/plugin-store --version 2>/dev/null- If the reported version is ≥ `0.3.0` (this skill's
metadata.version): binary is current, skip to step 2. - If the binary is missing or older: run the installer.
<!-- TODO(security/C01): Automated install commands removed pending upstream fix.
The previous macOS/Linux and Windows one-liners (a 'curl -sSL ... | sh' pipe and an 'irm ... | iex' equivalent fetching install.sh / install.ps1 directly from the main branch) are flagged C01 (zero-verification remote code execution) by the skill security scanner. The literal command strings have been intentionally omitted from this comment so the scanner does not match them.
A SHA256-verified replacement modelled on okx/onchainos-skills (which fetches install.sh + installer-checksums.txt from a pinned release, hashes install.sh locally, and refuses to execute on mismatch) cannot ship today because github.com/okx/plugin-store does not yet publish the required artifacts:
1. No plugin-store CLI v* release exists (current releases are per-plugin only: plugins/<name>@<version>). 2. No 'installer-checksums.txt' asset is published on any release.
Re-enable an OnchainOS-style automated install ONLY after BOTH conditions below are satisfied on github.com/okx/plugin-store: a. release.yml produces a v* tag dedicated to the plugin-store CLI itself, and b. The release.yml 'checksums' job ALSO hashes skills/plugin-store/install.sh and install.ps1 into a release asset named 'installer-checksums.txt'.
Until then, instruct the user to install manually using the 'Manual install' block below. -->
Manual install — visit <https://github.com/okx/plugin-store/releases>, download the binary for your platform, verify it against checksums.txt from the same release, and place it on your PATH (e.g. ~/.local/bin/plugin-store).
Offline fallback: if a binary already exists locally, proceed with it. If not installed and the network is unreachable, stop and ask the user to check their connection.
2. Check for Skill update (remote version check)
Fetch the latest Skill version from GitHub (timeout 5 seconds, non-blocking):
curl -sSL --max-time 5 "https://raw.githubusercontent.com/okx/plugin-store/main/skills/plugin-store/SKILL.md" 2>/dev/null | head -20 | grep 'version:' | head -1Compare the remote metadata.version with the local version (0.3.0).
If remote version is newer than local, display this notice to the user:
📦 Plugin Store Skill 有新版本可用(当前: 0.3.0, 最新: X.Y.Z)
>
是否更新?更新命令:
```
plugin-store install plugin-store --agent claude-code --skill-only
```
⚠️ 注意:更新后需要重启当前会话,新版 Skill 才会在上下文中生效。
Then wait for the user's response:
- If user says yes / 确认 / 更新 → run the install command, then remind: "Skill 已更新,请重启当前会话(退出并重新进入)以加载新版本。"
- If user says no / 跳过 / 以后再说 → continue with current version, do not ask again this session.
- If the curl fails or times out → skip silently, continue with current version.
If versions match or remote is unreachable, skip silently — do not print anything.
3. Do not auto-reinstall on command failures
Report errors and suggest plugin-store self-update or checking https://github.com/okx/plugin-store.
4. Install onchainos-skills (silent, non-blocking)
npx skills add okx/onchainos-skills --yes 2>/dev/null || trueThis installs sub-skills used by Skill Routing (okx-dex-token, okx-dex-swap, etc.). Do not block on failure.
---
Available Plugins
Always run `plugin-store list` to get the current plugin list — never rely on a hardcoded table.
plugin-store listParse the output and present it to the user as a clean table (name, category, downloads, description). The registry updates dynamically; this is the only source of truth.
---
Skill Routing
| User Intent | Action |
|---|---|
| "What dapps / strategies / skills are available?" | Run plugin-store list, present results as a table |
| "What can you do?" / capability discovery | Run plugin-store list, explain capabilities based on live output |
| "Plugin商店有什么" / "有什么Plugin" / "有什么项目" | Run plugin-store list, present results as a table |
| "什么项目最火" / "最热门的项目" / "trending projects" | Run plugin-store list, sort by downloads, highlight top entries |
| "怎么玩DeFi" / "链上怎么赚币" / "链上有什么玩法" | Run plugin-store list, introduce categories and recommend starting points |
| "有什么好的策略" / "推荐策略" | Run plugin-store list, filter and highlight trading-strategy category |
| "有什么DeFi协议" / "推荐DeFi项目" | Run plugin-store list, filter and highlight defi-protocol category |
| "Install X" / "安装 X" | Run plugin-store install <name> --yes |
| "Uninstall X" / "卸载 X" | Run plugin-store uninstall <name> |
| "Update all" / "更新Plugin" | Run plugin-store update --all |
| "Show installed" / "已安装" | Run plugin-store installed |
| "Search X" / "搜索 X" | Run plugin-store search <keyword> |
| "I want to create/submit a plugin" / "我想开发Plugin" | Guide through the Developer Workflow below |
| "How to contribute" / "怎么提交Plugin" / "hackathon" | Guide through the Developer Workflow below |
---
Command Index
CLI Reference: For full parameter tables, output fields, and error cases, see cli-reference.md.
User Commands
| # | Command | Description |
|---|---|---|
| 1 | plugin-store list | List all available plugins in the registry |
| 2 | plugin-store search <keyword> | Search plugins by name, tag, or description |
| 3 | plugin-store info <name> | Show detailed plugin info (components, chains, protocols) |
| 4 | plugin-store install <name> | Install a plugin (interactive agent selection) |
| 5 | plugin-store install <name> --yes | Install non-interactively (auto-detects agents) |
| 6 | plugin-store install <name> --skill-only | Install skill component only |
| 7 | plugin-store uninstall <name> | Uninstall a plugin from all agents |
| 8 | plugin-store update --all | Update all installed plugins |
| 9 | plugin-store installed | Show all installed plugins and their status |
| 10 | plugin-store registry update | Force refresh registry cache |
| 11 | plugin-store self-update | Update plugin-store CLI itself to latest version |
Developer Commands
| # | Command | Description |
|---|---|---|
| 12 | plugin-store init <name> | Scaffold a new plugin (creates plugin.yaml, SKILL.md, LICENSE, etc.) |
| 13 | plugin-store lint <path> | Validate a plugin before submission (30+ checks) |
| 14 | plugin-store import <github-url> | Import an existing Claude marketplace Plugin into plugin-store format (Mode C) |
---
Operation Flow
Intent: Strategy / DApp / Capability Discovery
1. Run plugin-store list to fetch the live registry 2. Present results as a clean table (name, category, downloads, description) 3. Suggest next steps: "Want to install one? Just say install <name>"
Intent: Install a Plugin
1. Run plugin-store install <name> --yes
--yesskips the community plugin confirmation prompt- Agent selection is automatic in non-interactive mode (installs to all detected agents)
2. The CLI will:
- Fetch plugin metadata from registry
- Download and install skill, MCP config, and/or binary as applicable
3. Immediately after install succeeds, read the installed skill file directly — do NOT ask the user to restart:
Read file: ~/.claude/skills/<name>/SKILL.mdThen follow the instructions in that file (Pre-flight → onboarding flow). The skill is immediately usable in the current session.
Intent: Manage Installed Plugins
1. Run plugin-store installed to show current state 2. Run plugin-store update --all to update everything 3. Run plugin-store uninstall <name> to remove
---
Developer Workflow: Create and Submit a Plugin
Plugin Store is an open-source community platform. Any developer can submit a plugin through a Pull Request. The full workflow:
Overview
Two types of plugins:
Type A: Pure Skill — just a SKILL.md that orchestrates onchainos CLI commands
Type B: Skill + Source Code — SKILL.md + a CLI tool compiled/installed from your source repo
Five supported languages for source code:
Rust, Go → compiled to native binary (~1-20MB)
TypeScript, Node.js → distributed via npm install (~KB)
Python → distributed via pip install (~KB)Step 1: Fork and scaffold
# Fork https://github.com/okx/plugin-store on GitHub, then:
git clone --depth=1 git@github.com:YOUR_USERNAME/plugin-store.git
cd plugin-store
plugin-store init <your-plugin-name>This creates skills/<your-plugin-name>/ with a complete template:
skills/<your-plugin-name>/
├── plugin.yaml # Plugin manifest (fill in your details)
├── skills/<name>/
│ └── SKILL.md # Skill definition (built-in onchainos demo)
│ └── references/
├── LICENSE
├── CHANGELOG.md
└── README.mdStep 2: Edit plugin.yaml
Pure Skill — just fill in the basics:
schema_version: 1
name: <your-plugin-name> # lowercase + hyphens, 2-40 chars
version: "1.0.0"
description: "What your plugin does"
author:
name: "Your Name"
github: "your-github-username" # must match PR submitter
license: MIT
category: utility # trading-strategy | defi-protocol | analytics | utility | security | wallet | nft
tags: [keyword1, keyword2]
components:
skill:
dir: skills/<your-plugin-name>
api_calls: [] # external API domains your plugin callsSkill + Source Code — add a build section pointing to your source repo:
# ... same as above, plus:
build:
lang: rust # rust | go | typescript | node | python
source_repo: "your-org/your-tool" # your GitHub repo with source code
source_commit: "a1b2c3d4e5f6..." # full 40-char commit SHA (git rev-parse HEAD)
binary_name: "your-tool" # compiled output name
# main: "src/index.js" # required for typescript/node/pythonHow to get the commit SHA:
cd your-source-repo
git push origin main
git rev-parse HEAD # copy this 40-char string into build.source_commitStep 3: Write SKILL.md
SKILL.md teaches the AI agent how to use your plugin. Required sections:
1. YAML frontmatter — name, description, version, author, tags 2. Overview — what the plugin does (2-3 sentences) 3. Pre-flight Checks — what needs to be installed before use 4. Commands — specific onchainos commands with When to use / Output 5. Error Handling — table of common errors and resolutions 6. Skill Routing — when to defer to other skills
Critical rule: All on-chain write operations (signing, broadcasting, swaps, contract calls) MUST use onchainos CLI. Querying external data sources (third-party APIs, price feeds) is freely allowed.
Step 4: Validate locally
plugin-store lint ./skills/<your-plugin-name>/Fix all errors (❌), then re-run until you see ✓. Warnings (⚠️) are advisory.
Step 5: Submit via Pull Request
git checkout -b submit/<your-plugin-name>
git add skills/<your-plugin-name>/
git commit -m "[new-plugin] <your-plugin-name> v1.0.0"
git push origin submit/<your-plugin-name>Then create a PR from your fork to okx/plugin-store. Each PR must contain exactly one plugin.
What happens after submission
Phase 2: Structure check (~30s) — bot validates plugin.yaml + SKILL.md
Phase 3: AI code review (~2min) — Claude reads your code, writes a 9-section report
Phase 4: Build check (if binary) — compiles your source code on 3 platforms
Phase 7: After merge — auto-publishes to registry, users can install immediatelyHuman review takes 1-3 days. Once merged, your plugin is live:
plugin-store install <your-plugin-name>Source code requirements by language
| Language | Key requirements |
|---|---|
| Rust | Cargo.toml with [[bin]] matching binary_name |
| Go | go.mod with module declaration, func main() |
| TypeScript | package.json with "bin" field, entry file has #!/usr/bin/env node, must be JS (not .ts) |
| Node.js | package.json with "bin" field, entry file has #!/usr/bin/env node |
| Python | pyproject.toml with [build-system] + [project.scripts], recommend also setup.py |
Common lint errors
| Error | Fix |
|---|---|
| E031 name format invalid | Use lowercase + hyphens only: my-cool-plugin |
| E052 missing SKILL.md | Put SKILL.md in the path specified by components.skill.dir |
| E110/E111 binary needs build | Add build section with lang, source_repo, source_commit |
| E122 source_repo format | Use owner/repo, not full URL |
| E123 commit SHA invalid | Must be full 40-char hex from git rev-parse HEAD |
Full guide: https://github.com/okx/plugin-store/blob/main/docs/FOR-DEVELOPERS.md
---
Supported Agents
| Agent | Detection | Skills Path | MCP Config |
|---|---|---|---|
| Claude Code | ~/.claude/ exists | ~/.claude/skills/<plugin>/ | ~/.claude.json → mcpServers |
| Cursor | ~/.cursor/ exists | ~/.cursor/skills/<plugin>/ | ~/.cursor/mcp.json |
| OpenClaw | ~/.openclaw/ exists | ~/.openclaw/skills/<plugin>/ | Same as skills |
---
Plugin Source Trust Levels
| Source | Meaning | Behavior |
|---|---|---|
official | Plugin Store official | Install directly |
dapp-official | Published by the DApp project | Install directly |
community | Community contribution | Show warning, require user confirmation |
---
Error Handling
| Error | Action |
|---|---|
| Network timeout during install | Retry once; if still failing, suggest manual install from https://github.com/okx/plugin-store |
plugin-store: command not found after install | Try ~/.local/bin/plugin-store or ~/.cargo/bin/plugin-store directly; PATH may not be updated for the current session |
| Command returns non-zero exit | Report error verbatim; suggest plugin-store self-update |
| Registry cache stale / corrupt | Run plugin-store registry update to force refresh |
plugin-store lint fails | Show error codes and fixes; refer to the lint error table above |
---
Skill Self-Update
To update this skill to the latest version:
macOS / Linux:
plugin-store install plugin-store --agent claude-code --skill-only<!-- TODO(security/C01): same installer-replacement caveat as in section 1 — see the TODO block earlier in this file. Until the upstream release pipeline publishes installer-checksums.txt, instruct the user to re-install manually from the GitHub releases page. -->
Or re-install manually — see Manual install in section 1 above (download the binary from the GitHub releases page and verify it against checksums.txt).
---
<rules> <must>
- Always run
plugin-store listfor capability/discovery questions — never use a hardcoded plugin list - Present plugin lists as clean tables (name, category, downloads, description); omit internal fields like registry URLs or file paths
- Present capabilities in user-friendly language: "You can trade on Uniswap across 12 chains", not "uniswap-ai supports uniswap-v2, uniswap-v3 protocols"
- After any action, suggest 2–3 natural follow-up steps
- Support both English and Chinese — respond in the user's language
- For developer workflow: always run
plugin-store initfirst, then guide through editing, linting, and PR submission - For lint errors: show the error code, explain the fix, and offer to help edit the file
</must> <should>
- For community-source plugins, proactively warn the user before installing
- After installing a plugin, read the installed SKILL.md and trigger the skill's onboarding flow immediately
- When guiding plugin development, ask which type (Pure Skill or Skill + Binary) and which language
- Suggest running
plugin-store lintafter every edit to catch issues early
</should> <never>
- Never expose internal skill names, registry URLs, file paths, or MCP config keys to the user
- Never auto-reinstall on command failures — report the error and suggest
plugin-store self-update - Never hardcode a plugin list — always fetch from
plugin-store list - Never skip the lint step before suggesting PR submission
</never> </rules>
{
"name": "plugin-store",
"description": "The main on-chain DeFi skill. Discover, install, update, and manage plugins — including trading strategies, DeFi integrations, and developer tools — across Claude Code, Cursor, and OpenClaw.",
"version": "1.0.0",
"author": {
"name": "OKX",
"email": "plugin-store@okx.com"
},
"homepage": "https://github.com/okx/plugin-store",
"repository": "https://github.com/okx/plugin-store",
"license": "Apache-2.0",
"keywords": [
"defi",
"trading",
"on-chain",
"onchainos",
"plugin-marketplace",
"web3"
]
}
# ──────────────────────────────────────────────────────────────
# plugin-store installer / updater (Windows)
#
# Usage (stable):
# irm https://raw.githubusercontent.com/okx/plugin-store/main/skills/plugin-store/install.ps1 | iex
#
# Behavior:
# - Fetches latest stable release from GitHub, compares with local
# version, installs/upgrades if needed.
# - Caches the last check timestamp. Skips GitHub API calls if
# checked within the last 12 hours.
#
# Supported platforms:
# Windows: x86_64, i686, ARM64
# ──────────────────────────────────────────────────────────────
$ErrorActionPreference = "Stop"
$REPO = "okx/plugin-store"
$BINARY = "plugin-store"
$INSTALL_DIR = Join-Path $env:USERPROFILE ".local\bin"
$CACHE_DIR = Join-Path $env:USERPROFILE ".plugin-store"
$CACHE_FILE = Join-Path $CACHE_DIR "last_check"
$CACHE_TTL = 43200 # 12 hours in seconds
function Get-Target {
$arch = $env:PROCESSOR_ARCHITECTURE
switch ($arch) {
"AMD64" { return "x86_64-pc-windows-msvc" }
"x86" { return "i686-pc-windows-msvc" }
"ARM64" { return "aarch64-pc-windows-msvc" }
default { throw "Unsupported architecture: $arch" }
}
}
# ── Cache helpers ────────────────────────────────────────────
function Test-CacheFresh {
if (-not (Test-Path $CACHE_FILE)) { return $false }
$cachedTs = (Get-Content $CACHE_FILE -ErrorAction SilentlyContinue | Select-Object -First 1).Trim()
if (-not $cachedTs) { return $false }
$now = [int][double]::Parse((Get-Date -UFormat %s))
$elapsed = $now - [int]$cachedTs
return ($elapsed -lt $CACHE_TTL)
}
function Write-Cache {
if (-not (Test-Path $CACHE_DIR)) { New-Item -ItemType Directory -Path $CACHE_DIR -Force | Out-Null }
[int][double]::Parse((Get-Date -UFormat %s)) | Out-File -FilePath $CACHE_FILE -Encoding ascii -NoNewline
}
# ── Version helpers ──────────────────────────────────────────
function Get-LocalVersion {
$binaryPath = Join-Path $INSTALL_DIR "$BINARY.exe"
if (Test-Path $binaryPath) {
$output = & $binaryPath --version 2>$null
if ($output -match "\S+\s+(\S+)") { return $Matches[1] }
}
return $null
}
function Get-BaseVersion([string]$ver) {
return ($ver -split '-')[0]
}
function Get-PreRelease([string]$ver) {
if ($ver -match '-(.+)$') { return $Matches[1] }
return $null
}
function Test-SemverGt([string]$v1, [string]$v2) {
$base1 = Get-BaseVersion $v1
$base2 = Get-BaseVersion $v2
$pre1 = Get-PreRelease $v1
$pre2 = Get-PreRelease $v2
$parts1 = $base1 -split '\.'
$parts2 = $base2 -split '\.'
for ($i = 0; $i -lt 3; $i++) {
$f1 = if ($parts1[$i]) { [int]$parts1[$i] } else { 0 }
$f2 = if ($parts2[$i]) { [int]$parts2[$i] } else { 0 }
if ($f1 -gt $f2) { return $true }
if ($f1 -lt $f2) { return $false }
}
if (-not $pre1 -and -not $pre2) { return $false }
if (-not $pre1) { return $true }
if (-not $pre2) { return $false }
$num1 = if ($pre1 -match '(\d+)$') { [int]$Matches[1] } else { 0 }
$num2 = if ($pre2 -match '(\d+)$') { [int]$Matches[1] } else { 0 }
return ($num1 -gt $num2)
}
# ── GitHub API helpers ───────────────────────────────────────
function Get-LatestStableVersion {
try {
$response = Invoke-RestMethod -Uri "https://api.github.com/repos/${REPO}/releases/latest" -TimeoutSec 10 -UseBasicParsing
$ver = $response.tag_name -replace '^v', ''
if ($ver) { return $ver }
} catch {}
throw "Could not fetch latest version from GitHub. Check your network connection or install manually from https://github.com/${REPO}"
}
# ── Binary installer ─────────────────────────────────────────
function Install-Binary {
param([string]$Tag)
$target = Get-Target
$binaryName = "${BINARY}-${target}.exe"
$url = "https://github.com/${REPO}/releases/download/${Tag}/${binaryName}"
$checksumsUrl = "https://github.com/${REPO}/releases/download/${Tag}/checksums.txt"
Write-Host "Installing ${BINARY} ${Tag} (${target})..."
$tmpDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null
try {
$binaryPath = Join-Path $tmpDir $binaryName
$checksumsPath = Join-Path $tmpDir "checksums.txt"
Invoke-WebRequest -Uri $url -OutFile $binaryPath -UseBasicParsing
# Checksum verification (best-effort)
try {
Invoke-WebRequest -Uri $checksumsUrl -OutFile $checksumsPath -UseBasicParsing
$expectedLine = Get-Content $checksumsPath | Where-Object { $_ -match $binaryName } | Select-Object -First 1
if ($expectedLine) {
$expectedHash = ($expectedLine -split "\s+")[0]
$actualHash = (Get-FileHash -Path $binaryPath -Algorithm SHA256).Hash.ToLower()
if ($actualHash -ne $expectedHash) {
throw "Checksum mismatch!`n Expected: $expectedHash`n Got: $actualHash`nThe downloaded file may have been tampered with. Aborting."
}
Write-Host "Checksum verified."
}
} catch [System.Net.WebException] {
# checksums.txt not available — skip verification
}
if (-not (Test-Path $INSTALL_DIR)) { New-Item -ItemType Directory -Path $INSTALL_DIR -Force | Out-Null }
$destPath = Join-Path $INSTALL_DIR "$BINARY.exe"
Move-Item -Path $binaryPath -Destination $destPath -Force
Write-Host "Installed ${BINARY} ${Tag} to ${destPath}"
}
finally {
Remove-Item -Path $tmpDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
# ── PATH setup ───────────────────────────────────────────────
function Add-ToPath {
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -split ";" | Where-Object { $_ -eq $INSTALL_DIR }) { return }
$newPath = "${INSTALL_DIR};${userPath}"
[Environment]::SetEnvironmentVariable("Path", $newPath, "User")
$env:Path = "${INSTALL_DIR};${env:Path}"
Write-Host ""
Write-Host "Added $INSTALL_DIR to your user PATH."
Write-Host "Restart your terminal or run the following to use '${BINARY}' now:"
Write-Host ""
Write-Host " `$env:Path = `"${INSTALL_DIR};`$env:Path`""
Write-Host ""
}
# ── Main ─────────────────────────────────────────────────────
function Main {
$localVer = Get-LocalVersion
# Fast path: binary exists and was checked recently — skip API call
if ($localVer -and (Test-CacheFresh)) { return }
$latestStable = Get-LatestStableVersion
if (-not $localVer) {
$targetVer = $latestStable
} elseif ($localVer -eq $latestStable) {
Write-Cache
return
} else {
if (Test-SemverGt $latestStable $localVer) {
$targetVer = $latestStable
} else {
Write-Cache
return
}
}
if ($localVer) {
Write-Host "Updating ${BINARY} from ${localVer} to ${targetVer}..."
}
Install-Binary -Tag "v${targetVer}"
Write-Cache
Add-ToPath
}
Main
#!/bin/sh
set -e
# ──────────────────────────────────────────────────────────────
# plugin-store installer / updater (macOS / Linux)
#
# Usage:
# curl -sSL https://raw.githubusercontent.com/okx/plugin-store/main/skills/plugin-store/install.sh | sh
#
# Behavior:
# - Fetches latest stable release from GitHub, compares with local
# version, installs/upgrades if needed.
# - Caches the last check timestamp. Skips GitHub API calls if
# checked within the last 12 hours.
#
# Supported platforms:
# macOS : x86_64 (Intel), arm64 (Apple Silicon)
# Linux : x86_64, i686, aarch64, armv7l
# Windows: see install.ps1 (PowerShell)
# ──────────────────────────────────────────────────────────────
REPO="okx/plugin-store"
BINARY="plugin-store"
INSTALL_DIR="$HOME/.local/bin"
CACHE_DIR="$HOME/.plugin-store"
CACHE_FILE="$CACHE_DIR/last_check"
CACHE_TTL=43200 # 12 hours in seconds
# ── Platform detection ───────────────────────────────────────
get_target() {
os=$(uname -s)
arch=$(uname -m)
case "$os" in
Darwin)
case "$arch" in
x86_64) echo "x86_64-apple-darwin" ;;
arm64) echo "aarch64-apple-darwin" ;;
*) echo "Unsupported architecture: $arch" >&2; exit 1 ;;
esac
;;
Linux)
case "$arch" in
x86_64) echo "x86_64-unknown-linux-gnu" ;;
i686) echo "i686-unknown-linux-gnu" ;;
aarch64) echo "aarch64-unknown-linux-gnu" ;;
armv7l) echo "armv7-unknown-linux-gnueabihf" ;;
*) echo "Unsupported architecture: $arch" >&2; exit 1 ;;
esac
;;
*) echo "Unsupported OS" >&2; exit 1 ;;
esac
}
# ── Cache helpers ────────────────────────────────────────────
is_cache_fresh() {
[ -f "$CACHE_FILE" ] || return 1
cached_ts=$(head -1 "$CACHE_FILE" 2>/dev/null)
[ -z "$cached_ts" ] && return 1
now=$(date +%s)
elapsed=$((now - cached_ts))
[ "$elapsed" -lt "$CACHE_TTL" ]
}
# Read the latest version stored in cache (line 2)
cached_latest_version() {
sed -n '2p' "$CACHE_FILE" 2>/dev/null
}
write_cache() {
mkdir -p "$CACHE_DIR"
# Line 1: timestamp, Line 2: latest known version
printf '%s\n%s\n' "$(date +%s)" "${1:-}" > "$CACHE_FILE"
}
# ── Version helpers ──────────────────────────────────────────
get_local_version() {
if [ -x "$INSTALL_DIR/$BINARY" ]; then
"$INSTALL_DIR/$BINARY" --version 2>/dev/null | awk '{print $2}'
fi
}
strip_prerelease() {
echo "$1" | sed 's/-.*//'
}
_ver_field() {
echo "$1" | cut -d. -f"$2"
}
semver_gt() {
base1=$(strip_prerelease "$1")
base2=$(strip_prerelease "$2")
pre1=$(echo "$1" | sed -n 's/[^-]*-//p')
pre2=$(echo "$2" | sed -n 's/[^-]*-//p')
for i in 1 2 3; do
f1=$(_ver_field "$base1" "$i")
f2=$(_ver_field "$base2" "$i")
f1=${f1:-0}
f2=${f2:-0}
[ "$f1" -gt "$f2" ] 2>/dev/null && return 0
[ "$f1" -lt "$f2" ] 2>/dev/null && return 1
done
[ -z "$pre1" ] && [ -z "$pre2" ] && return 1
[ -z "$pre1" ] && return 0
[ -z "$pre2" ] && return 1
num1=$(echo "$pre1" | grep -o '[0-9]*$')
num2=$(echo "$pre2" | grep -o '[0-9]*$')
num1=${num1:-0}
num2=${num2:-0}
[ "$num1" -gt "$num2" ] 2>/dev/null && return 0
return 1
}
# ── GitHub API helpers ───────────────────────────────────────
get_latest_stable_version() {
response=$(curl -sSL --max-time 10 "https://api.github.com/repos/${REPO}/releases/latest" 2>/dev/null) || true
ver=$(echo "$response" | grep -o '"tag_name": *"v[^"]*"' | head -1 | sed 's/.*"v\([^"]*\)".*/\1/')
if [ -z "$ver" ]; then
echo "Error: could not fetch latest version from GitHub." >&2
echo "Check your network connection or install manually from https://github.com/${REPO}" >&2
exit 1
fi
echo "$ver"
}
# ── Binary installer ─────────────────────────────────────────
install_binary() {
target=$(get_target)
if [ -z "$target" ]; then
exit 1
fi
tag="$1"
binary_name="${BINARY}-${target}"
url="https://github.com/${REPO}/releases/download/${tag}/${binary_name}"
checksums_url="https://github.com/${REPO}/releases/download/${tag}/checksums.txt"
echo "Installing ${BINARY} ${tag} (${target})..."
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
curl -fsSL "$url" -o "$tmpdir/$binary_name"
curl -fsSL "$checksums_url" -o "$tmpdir/checksums.txt" 2>/dev/null || true
if [ -f "$tmpdir/checksums.txt" ]; then
expected_hash=$(grep "$binary_name" "$tmpdir/checksums.txt" 2>/dev/null | awk '{print $1}')
if [ -n "$expected_hash" ]; then
if command -v sha256sum >/dev/null 2>&1; then
actual_hash=$(sha256sum "$tmpdir/$binary_name" | awk '{print $1}')
elif command -v shasum >/dev/null 2>&1; then
actual_hash=$(shasum -a 256 "$tmpdir/$binary_name" | awk '{print $1}')
fi
if [ -n "$actual_hash" ] && [ "$actual_hash" != "$expected_hash" ]; then
echo "Error: checksum mismatch!" >&2
echo " Expected: $expected_hash" >&2
echo " Got: $actual_hash" >&2
echo "The downloaded file may have been tampered with. Aborting." >&2
exit 1
fi
echo "Checksum verified."
fi
fi
mkdir -p "$INSTALL_DIR"
mv "$tmpdir/$binary_name" "$INSTALL_DIR/$BINARY"
chmod +x "$INSTALL_DIR/$BINARY"
echo "Installed ${BINARY} ${tag} to ${INSTALL_DIR}/${BINARY}"
}
# ── PATH setup ───────────────────────────────────────────────
ensure_in_path() {
case ":$PATH:" in
*":$INSTALL_DIR:"*) return 0 ;;
esac
EXPORT_LINE="export PATH=\"\$HOME/.local/bin:\$PATH\""
shell_name=$(basename "$SHELL" 2>/dev/null || echo "sh")
case "$shell_name" in
zsh) profile="$HOME/.zshrc" ;;
bash)
if [ -f "$HOME/.bash_profile" ]; then
profile="$HOME/.bash_profile"
elif [ -f "$HOME/.bashrc" ]; then
profile="$HOME/.bashrc"
else
profile="$HOME/.profile"
fi
;;
*) profile="$HOME/.profile" ;;
esac
if [ -f "$profile" ] && grep -qF '$HOME/.local/bin' "$profile" 2>/dev/null; then
return 0
fi
echo "" >> "$profile"
echo "# Added by plugin-store installer" >> "$profile"
echo "$EXPORT_LINE" >> "$profile"
export PATH="$INSTALL_DIR:$PATH"
echo ""
echo "Added $INSTALL_DIR to PATH in $profile"
echo "To start using '${BINARY}' now, run:"
echo ""
echo " source $profile"
echo ""
echo "Or simply open a new terminal window."
}
# ── Main ─────────────────────────────────────────────────────
main() {
local_ver=$(get_local_version)
# Fast path: binary exists, cache is fresh, AND cached latest == local version
if [ -n "$local_ver" ] && is_cache_fresh; then
cached_ver=$(cached_latest_version)
if [ -n "$cached_ver" ] && [ "$local_ver" = "$cached_ver" ]; then
echo "${BINARY} ${local_ver} already up to date."
return 0
fi
# Version mismatch (local != cached latest) — fall through to re-check
fi
latest_stable=$(get_latest_stable_version)
if [ -z "$local_ver" ]; then
target_ver="$latest_stable"
elif [ "$local_ver" = "$latest_stable" ]; then
write_cache "$latest_stable"
echo "${BINARY} ${local_ver} already up to date."
return 0
else
if semver_gt "$latest_stable" "$local_ver"; then
target_ver="$latest_stable"
else
write_cache "$latest_stable"
echo "${BINARY} ${local_ver} already up to date."
return 0
fi
fi
if [ -n "$local_ver" ]; then
echo "Updating ${BINARY} from ${local_ver} to ${target_ver}..."
fi
install_binary "v${target_ver}"
write_cache "$target_ver"
ensure_in_path
}
main
Plugin Store CLI Reference
Complete command reference with parameters, output fields, and usage examples.
---
1. plugin-store list
List all available plugins in the registry.
Parameters: None
Output:
| Field | Type | Description |
|---|---|---|
| Name | string | Plugin name (unique identifier) |
| Version | string | Current version in registry |
| Source | enum | Trust level: official, dapp-official, community |
| Description | string | One-line description |
Example:
$ plugin-store list
Name Version Source Description
------------------------------------------------------------------------------------------
uniswap-ai 1.7.0 dapp-official AI-powered Uniswap developer tools...
2 plugins available.---
2. plugin-store search <keyword>
Search plugins by keyword. Matches against name, tags, description, and category.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
keyword | string | Yes | Search term |
Output: Same table format as list, filtered by keyword match.
Example:
$ plugin-store search trading
Name Version Source Description
------------------------------------------------------------------------------------------
uniswap-ai 1.7.0 dapp-official AI-powered Uniswap developer tools...
2 plugins found.$ plugin-store search uniswap
Name Version Source Description
------------------------------------------------------------------------------------------
uniswap-ai 1.7.0 dapp-official AI-powered Uniswap developer tools...
1 plugins found.---
3. plugin-store info <name>
Show detailed plugin metadata including components, chains, and protocols.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Exact plugin name |
Output:
| Field | Type | Description |
|---|---|---|
| Name | string | Plugin name |
| Version | string | Current version |
| Description | string | Full description |
| Author | string | Author name and GitHub URL |
| Category | string | Plugin category |
| Source | enum | Trust level |
| Tags | string[] | Comma-separated tags |
| Components | flags | Which components are available: Skill ✔, MCP ✔ (type), Binary ✔ |
| Extra | object | Chains, protocols, risk level (only if plugin has extra metadata) |
Example:
$ plugin-store info uniswap-ai
Name: uniswap-ai
Version: 1.7.0
Description: AI-powered Uniswap developer tools: trading, hooks, drivers, and on-chain analysis across V2/V3/V4
Author: Uniswap (https://github.com/Uniswap/uniswap-ai)
Category: defi-protocol
Source: dapp-official
Tags: uniswap, trading, hooks, v2, v3, v4, multi-chain
Components:
✔ Skill
Extra:
Chains: ethereum, base, arbitrum, optimism, polygon, bnb, avalanche, celo, blast, zora, worldchain, unichain
Protocols: uniswap-v2, uniswap-v3, uniswap-v4, universal-router
Risk Level: mediumError — plugin not found:
Plugin 'foo' not found. Run `plugin-store search <keyword>` to find plugins.---
4. plugin-store install <name> [OPTIONS]
Install a plugin to one or more agents. Downloads skill files, configures MCP servers, and installs binaries as applicable.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Plugin name to install |
--skill-only | flag | No | Install skill component only (skip MCP and binary) |
--mcp-only | flag | No | Install MCP component only (skip skill and binary) |
--agent <id> | string | No | Target agent ID. Skip interactive selection. Valid: claude-code, cursor, openclaw |
Behavior:
1. Fetches plugin metadata from registry 2. If type == "community" and not already installed → shows warning, asks confirmation 3. If --agent not specified → detects installed agents, prompts multi-select 4. Installs components per agent:
- Skill: downloads SKILL.md from GitHub → writes to
~/<agent>/skills/<plugin>/SKILL.md - MCP: writes config entry to agent's settings file
- Binary: downloads platform-specific binary from GitHub releases, verifies checksum
5. Records install state to ~/.plugin-store/installed.json
Example:
# Interactive install (prompts for agent selection)
$ plugin-store install uniswap-ai
# Install to Claude Code only
$ plugin-store install uniswap-ai --agent claude-code
# Install skill only, skip MCP/binary
$ plugin-store install uniswap-ai --skill-only
# Install MCP only, skip skill/binary
$ plugin-store install uniswap-ai --mcp-only
# Combine: skill-only + specific agent
$ plugin-store install uniswap-ai --skill-only --agent claude-codeOutput:
Installing uniswap-ai 1.7.0...
✔ Skill installed → ~/.claude/skills/uniswap-ai/ (Claude Code)
Done!Error — plugin not found:
Plugin 'foo' not found. Run `plugin-store search <keyword>` to find plugins.Error — no agents selected:
No agents selected.Error — unknown agent ID:
Unknown agent 'foo'. Valid: claude-code, cursor, openclaw---
5. plugin-store uninstall <name> [OPTIONS]
Uninstall a plugin. Removes skill files, MCP config entries, and binaries.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Plugin name to uninstall |
--agent <id> | string | No | Only remove from this agent. Valid: claude-code, cursor, openclaw |
Behavior:
- Without
--agent: removes from ALL agents the plugin was installed to, then removes state record - With
--agent: removes from that agent only. If no agents remain, removes state record entirely
Example:
# Uninstall from all agents
$ plugin-store uninstall uniswap-ai
# Uninstall from Claude Code only
$ plugin-store uninstall uniswap-ai --agent claude-codeOutput:
Uninstalling uniswap-ai...
✔ Skill removed from Claude Code
✔ State updated
Done!Error — not installed:
Plugin 'foo' is not installed.---
6. plugin-store update <name>
Update a specific installed plugin to the latest registry version.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | No | Plugin name. Omit when using --all |
--all | flag | No | Update all installed plugins |
Behavior:
1. Force-refreshes registry cache 2. Compares installed version vs registry version for target plugin(s) 3. If update available: shows oldVersion -> newVersion, re-installs to same agents 4. If --all with multiple updates: asks confirmation before proceeding 5. If already up to date: prints (up to date)
Example:
# Update a specific plugin
$ plugin-store update uniswap-ai
# Update all installed plugins
$ plugin-store update --allOutput — update available:
Updates available:
uniswap-ai: 1.5.0 -> 1.7.0
Installing uniswap-ai 1.7.0...
✔ Skill installed → ~/.claude/skills/uniswap-ai/ (Claude Code)
Done!Output — up to date:
uniswap-ai 1.7.0 (up to date)
All plugins are up to date.Output — nothing installed:
No plugins installed.Output — missing arguments:
Specify a plugin name or use --all.---
7. plugin-store installed
Show all installed plugins with their agents and components.
Parameters: None
Output:
| Field | Type | Description |
|---|---|---|
| Name | string | Plugin name |
| Version | string | Installed version |
| Agents | string[] | Comma-separated agent IDs (e.g. claude-code, cursor) |
| Components | string[] | Comma-separated installed components (e.g. skill, mcp, binary) |
Example:
$ plugin-store installed
Name Version Agents Components
-------------------------------------------------------------------------------------
uniswap-ai 1.7.0 claude-code skill
2 plugins installed.Output — nothing installed:
No plugins installed.---
8. plugin-store registry update
Force refresh the local registry cache from remote GitHub.
Parameters: None
Behavior:
- Fetches latest
registry.jsonfrom GitHub raw URL - Overwrites local cache at
~/.plugin-store/cache/registry.json - Resets the 12-hour cache TTL
Example:
$ plugin-store registry update
Refreshing registry...
OK Registry updated. 2 plugins available.---
9. plugin-store self-update
Update the plugin-store CLI binary itself to the latest GitHub release.
Parameters: None
Behavior:
1. Fetches latest release from GitHub API 2. Compares latest tag version with current binary version (CARGO_PKG_VERSION) 3. If already up to date: prints confirmation and exits 4. If update available: detects current platform target, finds matching binary asset in release 5. Downloads binary, verifies SHA256 checksum against checksums.txt (if present in release) 6. Atomically replaces current binary: current → .bak, new → current; removes .bak on success; rolls back on failure
Example:
$ plugin-store self-update
Checking for updates...
Current version: 0.1.0
Latest version: 0.2.0
Update available: 0.1.0 → 0.2.0
Downloading plugin-store-aarch64-apple-darwin...
Checksum verified ✓
Updated! 0.1.0 → 0.2.0Output — already up to date:
Checking for updates...
Current version: 0.2.0
Latest version: 0.2.0
Already up to date!Output — no releases on GitHub:
No releases found on GitHub. You're on the latest build.Error — platform not supported:
No binary found for platform 'riscv64-unknown-linux-gnu'. Available assets: plugin-store-x86_64-apple-darwin, ...Error — checksum mismatch:
Checksum verification failed.
Expected: abc123...
Got: def456...---
Agent IDs
Valid values for --agent parameter:
| ID | Agent | Detection |
|---|---|---|
claude-code | Claude Code | ~/.claude/ exists |
cursor | Cursor | ~/.cursor/ exists |
openclaw | OpenClaw | ~/.openclaw/ exists |
---
File Paths
| Path | Description |
|---|---|
~/.plugin-store/cache/registry.json | Cached registry (12h TTL) |
~/.plugin-store/installed.json | Installed plugin state |
~/.plugin-store/bin/ | Default binary install directory |
~/.claude/skills/<plugin>/SKILL.md | Skill file for Claude Code |
~/.claude/settings.json → mcpServers | MCP config for Claude Code |
~/.cursor/skills/<plugin>/SKILL.md | Skill file for Cursor |
~/.cursor/mcp.json → mcpServers | MCP config for Cursor |
~/.openclaw/skills/<plugin>/SKILL.md | Skill file for OpenClaw |
---
Common Workflows
Install a plugin end-to-end
plugin-store list # Browse available plugins
plugin-store info uniswap-ai # Check details
plugin-store install uniswap-ai --agent claude-code # Install
plugin-store installed # VerifyUpdate everything
plugin-store registry update # Refresh registry first
plugin-store update --all # Update all installedRemove a plugin from one agent
plugin-store uninstall uniswap-ai --agent cursor # Remove from Cursor only
plugin-store installed # Verify remainingSearch and install
plugin-store search prediction # Find prediction market pluginsFor Everyone
The plugin marketplace for AI coding agents — discover, install, and manage all Skills and MCP servers with a single command.
- One CLI works across Claude Code, Cursor, and OpenClaw
- Search, install, update, and uninstall plugins without leaving your terminal
- Open developer platform: submit your own plugin via Pull Request and publish to all users
Plugin Store
The CLI marketplace for AI coding agents to discover, install, update, and manage Skills and MCP servers.
Prerequisites
- Claude Code, Cursor, or OpenClaw installed
- onchainos is auto-installed as a dependency on first use — no manual setup needed
When to Use This Skill
Use this skill when the user:
- Asks what plugins, skills, strategies, or DApps are available
- Wants to install, uninstall, or update a plugin
- Wants to extend their AI agent with new tools or capabilities
- Is a developer who wants to submit or publish their own plugin
How It Works
Plugin Store provides a unified CLI interface that works across Claude Code, Cursor, and OpenClaw. It maintains a registry of all available plugins — Skills and MCP servers — which you can browse, search, and install from a single tool. Batch updates keep everything current at once. For developers, the store is an open submission platform: scaffold a new plugin with plugin-store init, validate it with plugin-store lint, and submit via Pull Request. Automated lint checks, AI review, and build verification run before the plugin is published and available to all users.
Key commands:
plugin-store list— Browse all available pluginsplugin-store search <keyword>— Search by name, description, or tagsplugin-store install <name>— Install a pluginplugin-store uninstall <name>— Uninstall a pluginplugin-store update --all— Update all installed pluginsplugin-store installed— Show all installed plugins and their statusplugin-store init <name>— Scaffold a new plugin for submissionplugin-store lint <path>— Validate a plugin before submitting
Related skills
How it compares
Use plugin-store for OKX's curated extension catalog; generic package managers lack OKX plugin metadata and agent wiring conventions.
FAQ
What does the plugin-store skill manage?
The plugin-store skill manages discovery, installation, configuration, and lifecycle of OKX Plugin Store extensions that add vetted third-party tools to an agent toolchain.
Who should use plugin-store?
plugin-store suits developers building OKX-aligned agents who need store-backed extensions installed and configured without repeating manual Plugin Store UI steps each session.