
opencli-universal-cli-hub
Convert websites, Electron apps, and local tools into standardized CLIs for AI agents and humans using OpenCLI's browser automation and adapter framework.
- Installs
- 257
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/reason-machines/devtools-skills --skill opencli-universal-cli-hub- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads opencli-universal-cli-hub automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
OpenCLI Universal CLI Hub
Skill by ara.so — Devtools Skills collection.
OpenCLI transforms any website, Electron app, or local binary into a standardized command-line interface. It provides AI agents with the ability to operate websites through a logged-in browser, execute built-in adapters for 100+ sites, and create new adapters using browser automation primitives.
Installation
Prerequisites
- Node.js >= 21.0.0
- Chrome or Chromium browser
- Logged-in browser session for target sites
Install OpenCLI CLI
# Check Node.js version
node --version
# Install globally
npm install -g @jackwener/opencli
# Verify installation
opencli doctor
Install Browser Bridge Extension
Chrome Web Store (recommended): Install from Chrome Web Store
Manual Installation:
- Download
opencli-extension-v{version}.zipfrom GitHub Releases - Unzip and navigate to
chrome://extensions - Enable Developer mode
- Click Load unpacked and select the folder
Verify Setup
opencli doctor
Core Concepts
Three Automation Modes
- Built-in Adapters: Pre-built commands for popular sites (Bilibili, Twitter, Reddit, etc.)
- Browser Automation: AI agents operate any website via
opencli browserprimitives - CLI Hub: Expose local tools and Electron apps through unified interface
Browser Sessions
Browser commands require an explicit <session> identifier:
# Session names are arbitrary but must be consistent
opencli browser work open https://example.com
opencli browser work state
opencli browser work click "button.submit"
opencli browser work close
Multi-Profile Support
# List connected Chrome profiles
opencli profile list
# Rename profile for easier reference
opencli profile rename <contextId> work
# Set default profile
opencli profile use work
# Use specific profile for command
opencli --profile work browser mysession open https://example.com
Using Built-in Adapters
List Available Commands
# Show all registered commands
opencli list
# Show commands for specific site
opencli list bilibili
Common Built-in Commands
# HackerNews top stories
opencli hackernews top --limit 5
# Bilibili trending videos
opencli bilibili hot --limit 10
# Reddit hot posts
opencli reddit hot --subreddit programming --limit 20
# Twitter/X trending
opencli twitter trending
# Xiaohongshu (Little Red Book)
opencli xiaohongshu hot --limit 15
# Zhihu hot questions
opencli zhihu hot --limit 10
Browser Automation Primitives
Navigation Commands
# Open URL in new session
opencli browser mysession open https://github.com/trending
# Get current page state (URL, title, DOM snapshot)
opencli browser mysession state
# Navigate back
opencli browser mysession back
# Close session
opencli browser mysession close
Tab Management
# List all tabs in session
opencli browser mysession tab list
# Create new tab (returns targetId)
opencli browser mysession tab new https://example.com
# Select specific tab as default target
opencli browser mysession tab select <targetId>
# Close tab
opencli browser mysession tab close <targetId>
# Execute command on specific tab
opencli browser mysession state --tab <targetId>
Interaction Commands
# Click element by selector
opencli browser mysession click "button.login"
# Type text into element
opencli browser mysession type "input[name='username']" "myuser"
# Fill form field (clears first, then types)
opencli browser mysession fill "input[name='password']" "mypass"
# Select dropdown option
opencli browser mysession select "select#country" "US"
# Send keyboard keys
opencli browser mysession keys "Enter"
opencli browser mysession keys "Control+a"
Waiting and Extraction
# Wait for element to appear
opencli browser mysession wait "div.content"
# Wait for specific text
opencli browser mysession wait --text "Loading complete"
# Extract data from page
opencli browser mysession extract "h1.title"
# Get element properties
opencli browser mysession get "a.link" --attribute href
# Find elements
opencli browser mysession find "article"
Advanced Commands
# Take screenshot
opencli browser mysession screenshot output.png
# Scroll page
opencli browser mysession scroll --distance 500
# Execute JavaScript
opencli browser mysession eval "document.title"
# Monitor network requests
opencli browser mysession network --pattern "api/v1/*"
# List frames
opencli browser mysession frames
Creating New Adapters
Manual Adapter Creation
# Initialize adapter structure
opencli browser init mysite/trending
# Creates ~/.opencli/clis/mysite/trending/
# - index.js (main adapter logic)
# - schema.json (command definition)
Example Adapter Structure (~/.opencli/clis/mysite/trending/index.js):
import { executeAdapter } from '@jackwener/opencli-core';
export default async function handler(args, context) {
const { limit = 10 } = args;
// Use browser automation
const session = context.session || 'adapter';
try {
// Open page
await executeAdapter('browser', [session, 'open', 'https://mysite.com/trending']);
// Wait for content
await executeAdapter('browser', [session, 'wait', 'article.post']);
// Extract data
const posts = await executeAdapter('browser', [session, 'extract', 'article.post', '--limit', limit]);
// Return structured data
return {
success: true,
data: posts.map(post => ({
title: post.querySelector('h2')?.textContent,
author: post.querySelector('.author')?.textContent,
url: post.querySelector('a')?.href
}))
};
} finally {
await executeAdapter('browser', [session, 'close']);
}
}
Schema Definition (~/.opencli/clis/mysite/trending/schema.json):
{
"name": "trending",
"description": "Get trending posts from mysite",
"arguments": {
"limit": {
"type": "number",
"description": "Number of posts to fetch",
"default": 10
}
},
"output": {
"columns": ["title", "author", "url"]
}
}
Using Recon Workflow
# Analyze site pattern (SPA, SSR, JSONP, etc.)
opencli browser recon analyze https://mysite.com/trending
# Initialize adapter with recon data
opencli browser recon init mysite/trending
# Verify adapter works
opencli browser recon verify mysite/trending
Site Knowledge Persistence
Store common patterns for reuse:
# Site knowledge is saved to ~/.opencli/sites/mysite/
# - auth.json (authentication strategy)
# - endpoints.json (discovered API endpoints)
# - patterns.json (site architecture patterns)
Plugin Management
Create and Install Plugins
# Create new plugin structure
opencli plugin create my-adapters
# Install from local directory
opencli plugin install file://./my-adapters
# Install from GitHub
opencli plugin install github:username/opencli-adapters
# Install from npm
opencli plugin install @myorg/opencli-adapters
# List installed plugins
opencli plugin list
# Uninstall plugin
opencli plugin uninstall my-adapters
Eject and Customize Built-in Adapters
# Eject adapter to local for modification
opencli adapter eject zhihu
# Modified adapter now lives in ~/.opencli/clis/zhihu/
# Reset to built-in version
opencli adapter reset zhihu
External CLI Integration
Register Local Tools
# Register any CLI tool
opencli external register gh
opencli external register docker
opencli external register kubectl
# Use through OpenCLI
opencli gh repo list
opencli docker ps
opencli kubectl get pods
Configuration
External CLIs are registered in ~/.opencli/external.json:
{
"gh": {
"command": "gh",
"description": "GitHub CLI"
},
"docker": {
"command": "docker",
"description": "Docker CLI"
}
}
Environment Variables
# Daemon port (default: 19825)
export OPENCLI_DAEMON_PORT=19825
# Browser profile to use
export OPENCLI_PROFILE=work
# Window placement (foreground|background)
export OPENCLI_WINDOW=foreground
# Connection timeout (seconds)
export OPENCLI_BROWSER_CONNECT_TIMEOUT=30
# Command timeout (seconds)
export OPENCLI_BROWSER_COMMAND_TIMEOUT=60
# Chrome DevTools Protocol endpoint
export OPENCLI_CDP_ENDPOINT=ws://localhost:9222
# CDP target filter
export OPENCLI_CDP_TARGET=detail.1688.com
# Verbose logging
export OPENCLI_VERBOSE=true
# DOM snapshot debugging
export DEBUG_SNAPSHOT=1
Configuration Files
Global Config (~/.opencli/config.json)
{
"defaultProfile": "work",
"daemonPort": 19825,
"browserTimeout": 60,
"windowMode": "background"
}
Per-Site Config (~/.opencli/sites/mysite/config.json)
{
"auth": "COOKIE",
"baseUrl": "https://mysite.com",
"pattern": "SPA",
"endpoints": {
"trending": "/api/v1/trending"
}
}
Common Patterns
Pattern 1: Simple Data Extraction
export default async function handler(args, context) {
const session = 'extract-session';
await executeAdapter('browser', [session, 'open', args.url]);
await executeAdapter('browser', [session, 'wait', args.selector]);
const data = await executeAdapter('browser', [
session, 'extract', args.selector
]);
await executeAdapter('browser', [session, 'close']);
return { success: true, data };
}
Pattern 2: Form Automation
export default async function handler(args, context) {
const session = 'form-session';
await executeAdapter('browser', [session, 'open', args.url]);
// Fill form fields
await executeAdapter('browser', [
session, 'fill', 'input[name="email"]', args.email
]);
await executeAdapter('browser', [
session, 'fill', 'input[name="password"]', args.password
]);
// Submit
await executeAdapter('browser', [session, 'click', 'button[type="submit"]']);
// Wait for success indicator
await executeAdapter('browser', [session, 'wait', '.success-message']);
await executeAdapter('browser', [session, 'close']);
return { success: true };
}
Pattern 3: Multi-Tab Workflow
export default async function handler(args, context) {
const session = 'multi-tab';
// Open first tab
await executeAdapter('browser', [session, 'open', args.url1]);
// Create second tab
const { targetId } = await executeAdapter('browser', [
session, 'tab', 'new', args.url2
]);
// Work in first tab
const data1 = await executeAdapter('browser', [
session, 'extract', '.content'
]);
// Work in second tab
const data2 = await executeAdapter('browser', [
session, 'extract', '.content', '--tab', targetId
]);
await executeAdapter('browser', [session, 'close']);
return { success: true, data: { tab1: data1, tab2: data2 } };
}
Pattern 4: Network Interception
export default async function handler(args, context) {
const session = 'network-session';
// Start monitoring network
const networkPromise = executeAdapter('browser', [
session, 'network', '--pattern', 'api/data'
]);
// Navigate to trigger request
await executeAdapter('browser', [session, 'open', args.url]);
// Get intercepted data
const networkData = await networkPromise;
await executeAdapter('browser', [session, 'close']);
return { success: true, data: networkData };
}
Pattern 5: Authenticated Session
export default async function handler(args, context) {
const session = 'auth-session';
// Browser already logged in via Chrome profile
await executeAdapter('browser', [session, 'open', args.url]);
// Verify authentication
const state = await executeAdapter('browser', [session, 'state']);
if (state.url.includes('/login')) {
throw new Error('Not authenticated. Please log in to Chrome.');
}
// Proceed with authenticated actions
const data = await executeAdapter('browser', [
session, 'extract', '.user-content'
]);
await executeAdapter('browser', [session, 'close']);
return { success: true, data };
}
Troubleshooting
Browser Not Connecting
# Check daemon status
opencli doctor
# Verify extension is installed and enabled
# Visit chrome://extensions
# Check daemon port
lsof -i :19825
# Restart daemon (kill and it will auto-restart)
pkill -f opencli-daemon
Multiple Chrome Profiles
# List profiles to see which are connected
opencli profile list
# If you see multiple profiles, set default
opencli profile use <alias>
# Or specify profile per-command
opencli --profile work browser mysession open https://example.com
Empty or Permission Errors
Issue: Commands return empty data or permission errors
Solution: Ensure you're logged in to the target site in Chrome
# 1. Open Chrome and log in to the site manually
# 2. Verify extension is active
# 3. Run OpenCLI command
opencli bilibili hot --limit 5
Adapter Not Found
# Verify adapter is installed
opencli list | grep mysite
# Check adapter directory exists
ls ~/.opencli/clis/mysite/
# Reinstall if needed
opencli plugin install file://path/to/plugin
Timeout Issues
# Increase command timeout
export OPENCLI_BROWSER_COMMAND_TIMEOUT=120
# Or per-command
opencli browser mysession wait "slow-element" --timeout 120000
CDP Connection Issues
# For Electron apps or remote Chrome
export OPENCLI_CDP_ENDPOINT=ws://localhost:9222
# Filter targets if multiple exist
export OPENCLI_CDP_TARGET=myapp.com
# Test connection
opencli doctor
Debug Mode
# Enable verbose logging
opencli -v browser mysession open https://example.com
# Or via environment
export OPENCLI_VERBOSE=true
# DOM snapshot debugging
export DEBUG_SNAPSHOT=1
opencli browser mysession state
Adapter Verification
# Initialize adapter with recon workflow
opencli browser recon init mysite/command
# Verify adapter works correctly
opencli browser recon verify mysite/command
# Check output format
opencli mysite command --limit 5
Best Practices
- Use explicit session names: Helps track browser automation flows
- Always close sessions: Prevents resource leaks (
opencli browser <session> close) - Handle authentication: Verify login state before executing commands
- Use --tab for multi-tab: Specify
--tab <targetId>when working with multiple tabs - Store credentials in browser: Let Chrome manage logins, don't hardcode credentials
- Profile separation: Use Chrome profiles for different accounts/contexts
- Error handling: Wrap browser commands in try-finally to ensure cleanup
- Rate limiting: Be respectful of site resources when creating adapters
- Recon first: Use
opencli browser recon analyzebefore building adapters - Persist site knowledge: Save patterns to
~/.opencli/sites/<site>/for reuse
FAQ
What does the opencli-universal-cli-hub skill do?
Convert websites, Electron apps, and local tools into standardized CLIs for AI agents and humans using OpenCLI's browser automation and adapter framework.
How do I install opencli-universal-cli-hub?
Run npx skills add https://github.com/reason-machines/devtools-skills --skill opencli-universal-cli-hub in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/opencli-universal-cli-hub/ (personal) or .claude/skills/opencli-universal-cli-hub/ (project).
Which AI agents can use opencli-universal-cli-hub?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is opencli-universal-cli-hub safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains opencli-universal-cli-hub?
It is published by reason-machines in reason-machines/devtools-skills. It has 257 recorded installs.
More from reason-machines/devtools-skills
cc-switch-cli
reason-machines/devtools-skills
Cross-platform CLI tool for managing Claude Code, Codex, Gemini, OpenCode & OpenClaw providers, MCP servers, prompts, skills, and proxies.
wx-cli-wechat-local-data
reason-machines/devtools-skills
Open the skill to read its SKILL.md instructions.
chrome-devtools-mcp-automation
reason-machines/devtools-skills
Open the skill to read its SKILL.md instructions.
officecli-office-automation
reason-machines/devtools-skills
Open the skill to read its SKILL.md instructions.
autocli-web-scraping
reason-machines/devtools-skills
Open the skill to read its SKILL.md instructions.
cli-anything-agent-native-software
reason-machines/devtools-skills
Open the skill to read its SKILL.md instructions.
Popular productivity & automation skills
agent-browser
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.
lark-doc
open.feishu.cn
飞书云文档(Docx / Wiki)内容操作:读取、创建、编辑文档,插入或下载图片附件,以及操作思维笔记。用户提供文档 URL/token(包括 doubao.com 的 /docx/、/wiki/)时使用;按 URL 路径/token 而非域名路由;/page/ 是妙搭应用,非飞书云文档。文档内嵌资源按读取参考中的统一规则分流。独立评论操作走 lark-drive;随正文读取评论使用 docs +fetch。表格或 Base 内部数据操作不在本 skill。
lark-base
open.feishu.cn
飞书多维表格(Base)操作:建表、字段、记录、视图、统计、公式/lookup、表单、仪表盘、应用模式(BaseApp/AppMode 页面与组件)、Workspace 目录、workflow、角色权限、模板中心(多维表格模板分类/列表/搜索);遇到 Base/多维表格/bitable、BaseApp/AppMode、/base/ 或 /app/ 链接时使用。BaseApp 不走 lark-apps;文件导入/导出转 lark-drive,认证/授权转 lark-shared。
lark-drive
open.feishu.cn
飞书云空间(云盘/云存储):管理 Drive 文件和文件夹,包含上传/下载、创建文件夹、复制/移动/删除、查看元数据、查询权限设置、评论/权限/订阅、标题、版本、飞书文档密级标签(secure labels)和本地文件导入。用户需要整理云盘目录、处理云空间资源 URL/token、判断链接类型/真实 token/标题,或导入 Word/Markdown/Excel/CSV/PPTX/.base 为 docx/sheet/bitable/slides 时使用;doubao.com 云空间 URL/token 也按资源路径和 token 路由,不回退 WebFetch。不负责:文档内容编辑(走 lark-doc)、表格/Base 表内数据操作(走 lark-sheets/lark-base)、知识空间节点/成员管理(走 lark-wiki)、原生 Markdown 文件读写/patch/diff(走 lark-markdown)。
lark-shared
open.feishu.cn
Use for lark-cli setup/auth tasks: auth login/status/logout, user vs bot identity, business-domain permissions (--domain, including all/docs/drive), missing scopes, revoking authorization, or handling notice JSON.
lark-im
open.feishu.cn
飞书即时通讯:收发消息和管理群聊。发送和回复消息、搜索聊天记录、管理群聊成员、上传下载图片和文件、管理表情回复、发送应用内/短信/电话加急、发送和处理交互卡片(Interactive Card)、监听卡片按钮回调(card.action.trigger)。当用户需要发消息、查看或搜索聊天记录、下载聊天中的文件、查看群成员、搜索群、创建群聊或话题群、管理标记数据、管理 Feed 置顶(添加/移除/查询置顶会话)、管理标签数据、处理卡片回调时使用。