Skip to content
Skillv1.0.0

qiaomu-opencli-oneshot

Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write TS adapter, test. For full site exploration, use opencli-e

by joeseesun(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from joeseesun/qiaomu-opencli-skills (qiaomu-opencli-oneshot/SKILL.md) via skills.sh. Install upstream with npx skills add joeseesun/qiaomu-opencli-skills --skill qiaomu-opencli-oneshot. Copyright stays with the author.

CLI-ONESHOT — 单点快速 CLI 生成

给一个 URL + 一句话描述,4 步生成一个 CLI 命令。 完整探索式开发请看 opencli-explorer skill


输入

项目 示例
URL https://x.com/jakevin7/lists
Goal 获取我的 Twitter Lists

流程

Step 1: 打开页面 + 抓包

1. browser_navigate → 打开目标 URL
2. 等待 3-5 秒(让页面加载完、API 请求触发)
3. browser_network_requests → 筛选 JSON API

关键:只关注返回 application/json 的请求,忽略静态资源。 如果没有自动触发 API,手动点击目标按钮/标签再抓一次。

Step 2: 锁定一个接口

从抓包结果中找到那个目标 API。看这几个字段:

字段 关注什么
URL API 路径 pattern(如 /i/api/graphql/xxx/ListsManagePinTimeline
Method GET / POST
Headers 有 Cookie? Bearer? CSRF? 自定义签名?
Response 数据在哪个路径(如 data.list.lists

Step 3: 验证接口能复现

browser_evaluate 中用 fetch 复现请求:

// Tier 2 (Cookie): 大多数情况
fetch('/api/endpoint', { credentials: 'include' }).then(r => r.json())

// Tier 3 (Header): 如 Twitter 需要额外 header
const ct0 = document.cookie.match(/ct0=([^;]+)/)?.[1];
fetch('/api/endpoint', {
  headers: { 'Authorization': 'Bearer ...', 'X-Csrf-Token': ct0 },
  credentials: 'include'
}).then(r => r.json())

如果 fetch 能拿到数据 → 用 TS adapter(cli() pipeline 或 func())。 如果 fetch 拿不到(签名/风控)→ 用 intercept 策略(TS func() + installInterceptor)。

Step 4: 套模板,生成 adapter

根据 Step 3 判定的策略,选一个模板生成文件。


认证速查

fetch(url) 直接能拿到?              → Tier 1: public   (TS pipeline, browser: false)
fetch(url, {credentials:'include'})? → Tier 2: cookie   (TS pipeline 或 func())
加 Bearer/CSRF header 后拿到?        → Tier 3: header   (TS func())
都不行,但页面自己能请求成功?          → Tier 4: intercept (TS func(), installInterceptor)

模板

TS — Cookie/Public(最简,func() 模式)

// clis/<site>/<name>.ts
import { cli, Strategy } from '@jackwener/opencli/registry';

cli({
  site: 'mysite',
  name: 'mycommand',
  description: '一句话描述',
  domain: 'www.example.com',
  strategy: Strategy.COOKIE,   // 或 Strategy.PUBLIC (加 browser: false)
  browser: true,
  args: [
    { name: 'limit', type: 'int', default: 20 },
  ],
  columns: ['rank', 'title', 'value'],
  func: async (page, kwargs) => {
    await page.goto('https://www.example.com/target-page');
    const data = await page.evaluate(`(async () => {
      const res = await fetch('/api/target', { credentials: 'include' });
      const d = await res.json();
      return (d.data?.items || []).map(item => ({
        title: item.title,
        value: item.value,
      }));
    })()`);
    return (data as any[]).slice(0, kwargs.limit).map((item, i) => ({
      rank: i + 1,
      title: item.title || '',
      value: item.value || '',
    }));
  },
});

TS — Intercept(抓包模式)

// clis/<site>/<name>.ts
import { cli, Strategy } from '@jackwener/opencli/registry';

cli({
  site: 'mysite',
  name: 'mycommand',
  description: '一句话描述',
  domain: 'www.example.com',
  strategy: Strategy.INTERCEPT,
  browser: true,
  args: [
    { name: 'limit', type: 'int', default: 20 },
  ],
  columns: ['rank', 'title', 'value'],
  func: async (page, kwargs) => {
    // 1. 导航
    await page.goto('https://www.example.com/target-page');
    await page.wait(3);

    // 2. 注入拦截器(URL 子串匹配)
    await page.installInterceptor('target-api-keyword');

    // 3. 触发 API(滚动/点击)
    await page.autoScroll({ times: 2, delayMs: 2000 });

    // 4. 读取拦截的响应
    const requests = await page.getInterceptedRequests();
    if (!requests?.length) return [];

    let results: any[] = [];
    for (const req of requests) {
      const items = req.data?.data?.items || [];
      results.push(...items);
    }

    return results.slice(0, kwargs.limit).map((item, i) => ({
      rank: i + 1,
      title: item.title || '',
      value: item.value || '',
    }));
  },
});

TS — Header(如 Twitter GraphQL)

import { cli, Strategy } from '@jackwener/opencli/registry';

cli({
  site: 'twitter',
  name: 'mycommand',
  description: '一句话描述',
  domain: 'x.com',
  strategy: Strategy.HEADER,
  browser: true,
  args: [
    { name: 'limit', type: 'int', default: 20 },
  ],
  columns: ['rank', 'name', 'value'],
  func: async (page, kwargs) => {
    await page.goto('https://x.com');
    const data = await page.evaluate(`(async () => {
      const ct0 = document.cookie.match(/ct0=([^;]+)/)?.[1];
      if (!ct0) return { error: 'Not logged in' };
      const bearer = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D...';
      const res = await fetch('/i/api/graphql/QUERY_ID/Endpoint', {
        headers: {
          'Authorization': 'Bearer ' + decodeURIComponent(bearer),
          'X-Csrf-Token': ct0,
          'X-Twitter-Auth-Type': 'OAuth2Session',
        },
        credentials: 'include',
      });
      return res.json();
    })()`);
    // 解析 data...
    return [];
  },
});

测试(必做)

npm run build                              # 语法检查
opencli list | grep mysite                 # 确认注册
opencli mysite mycommand --limit 3 -v      # 实际运行

就这样,没了

写完文件 → build → run → 提交。有问题再看 opencli-explorer skill

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/joeseesun-qiaomu-opencli-skills-qiaomu-opencli-oneshot/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

joeseesun-qiaomu-opencli-skills-qiaomu-opencli-oneshot.ocm.jsonjson
{
  "ocm": "1",
  "id": "joeseesun-qiaomu-opencli-skills-qiaomu-opencli-oneshot",
  "kind": "skill",
  "name": "qiaomu-opencli-oneshot",
  "description": "Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write TS adapter, test. For full site exploration, use opencli-explorer instead.",
  "publisher": "joeseesun",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "opencli",
      "adapter",
      "quick-start",
      "ts",
      "cli",
      "one-shot",
      "automation",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write TS adapter, test. For full site exploration, use opencli-explorer instead."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/joeseesun/qiaomu-opencli-skills",
      "path": "qiaomu-opencli-oneshot/SKILL.md",
      "ref": "HEAD",
      "url": "https://www.skills.sh/joeseesun/qiaomu-opencli-skills/qiaomu-opencli-oneshot",
      "key": "joeseesun/qiaomu-opencli-skills/qiaomu-opencli-oneshot/SKILL.md"
    }
  },
  "instructions": "# CLI-ONESHOT — 单点快速 CLI 生成\n\n> 给一个 URL + 一句话描述,4 步生成一个 CLI 命令。\n> 完整探索式开发请看 [opencli-explorer skill](../opencli-explorer/SKILL.md)。\n\n---\n\n## 输入\n\n| 项目 | 示例 |\n|------|------|\n| **URL** | `https://x.com/jakevin7/lists` |\n| **Goal** | 获取我的 Twitter Lists |\n\n---\n\n## 流程\n\n### Step 1: 打开页面 + 抓包\n\n```\n1. browser_navigate → 打开目标 URL\n2. 等待 3-5 秒(让页面加载完、API 请求触发)\n3. browser_network_requests → 筛选 JSON API\n```\n\n**关键**:只关注返回 `application/json` 的请求,忽略静态资源。\n如果没有自动触发 API,手动点击目标按钮/标签再抓一次。\n\n### Step 2: 锁定一个接口\n\n从抓包结果中找到**那个**目标 API。看这几个字段:\n\n| 字段 | 关注什么 |\n|------|----------|\n| URL | API 路径 pattern(如 `/i/api/graphql/xx",
  "cost": {
    "context_tokens": 1275
  }
}

Fetch it by URL: GET /api/v1/registry/joeseesun-qiaomu-opencli-skills-qiaomu-opencli-oneshot/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.