qiaomu-opencli-oneshot

安装量: 400
排名: #8257

安装

npx skills add https://github.com/joeseesun/opencli-skill --skill qiaomu-opencli-oneshot

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//.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//.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 。

返回排行榜