qiaomu-opencli-oneshot
特定のURLとゴールの説明から、OpenCLIコマンドを素早く1つ生成したい場合に使用します。ページを開く・APIをキャプチャ・TSアダプターを記述・テストの4ステップで完結します。サイト全体の探索が必要な場合は、代わりにopencli-explorerを使用してください。
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.
SKILL.md 本文
CLI-ONESHOT — シングルショット高速CLI生成
URLと1行の説明を与えると、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: 1つのエンドポイントを特定
キャプチャ結果からその目標APIを見つけます。以下のフィールドを確認します:
| フィールド | 確認内容 |
|---|---|
| URL | APIパターン(例:/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など追加ヘッダーが必要な場合
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アダプター(cli() パイプラインまたは func())を使用します。
fetchでデータが取得できない(署名/リスク制御)→ interceptステラテジー(TS func() + installInterceptor)を使用します。
Step 4: テンプレートに当てはめ、アダプターを生成
Step 3で判定したストラテジーに基づいて、テンプレートを選択しファイルを生成します。
認証クイックリファレンス
fetch(url) で直接取得可能? → Tier 1: public (TS pipeline, browser: false)
fetch(url, {credentials:'include'})? → Tier 2: cookie (TS pipeline または func())
Bearer/CSRFヘッダー追加で取得可能? → 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: '1行説明',
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: '1行説明',
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: '1行説明',
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 を参照してください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- joeseesun
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/joeseesun/opencli-skill / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。