Random Note

stillo — AIネイティブなターミナルブラウザを作った

stillo とは

stillo は、ターミナル上で動作する AIネイティブなブラウザ です。 Rust で実装しており、Web ページを取得してからノイズを取り除き、Markdown / テキスト / JSON として扱えるようにします。

名前は distill(蒸留する)から作った造語で、Web ページから情報だけを抽出するというコンセプトを込めています。

ターミナルブラウザというと w3m や Lynx を思い浮かべると思いますが、stillo の狙いは少し違います。 従来のターミナルブラウザは「画像や JavaScript を諦めてテキストとして表示する」ことが前提でしたが、stillo は「JavaScript を排除して構造化コンテンツを抽出できる」という点を強みにしています。

主な機能

stillo は以下のような使い方ができます。

  • dump — ページを Markdown / テキスト / JSON として標準出力に出力

  • browse — TUI ブラウザとして起動

  • qa — ページについて LLM に質問

  • summarize — LLM でページを要約

  • extract — LLM を使って指定したフィールドを抽出

  • mcp — MCP サーバーとして起動

特に dumpcurljq のようにパイプに組み込みやすく、LLM に渡す前の前処理ツールとして使うことを想定しています。

# Markdown として出力して LLM にパイプ
stillo dump https://example.com | llm "要約して"

# JSON 形式で構造化抽出
stillo extract "title,author,published_at" --format json https://example.com/article

SPA 対応

静的な HTML はそのまま取得し、React や Vue などの SPA と判定された場合は自動的に委譲先を探します。 優先順位は以下の通りです。

  1. Chrome CDP(localhost:9222

  2. Playwright Daemon(/tmp/stillo-playwright.sock

  3. Jina Reader

  4. Firecrawl

すべて失敗した場合は静的 HTML にフォールバックするので、安心して組み込めます。

アーキテクチャ

クレートを分けることで、ドメインロジックと I/O を明確に分離しています。

クレート 役割

stillo-core

純粋関数のみ。HTML 解析・コンテンツ抽出・Markdown 変換

stillo-fetcher

HTTP 取得・SPA 委譲

stillo-renderer

TUI 描画

stillo-llm

LLM API 呼び出し

stillo-mcp

MCP サーバー

stillo (cli)

コマンドライン引数解析・全体オーケストレーション

stillo-core は他のクレートに依存せず、副作用を持ちません。 これによりテストしやすく、AI がコードを読みやすい構造になっています。

MCP サーバーとして

stillo mcp を起動すると、stdio transport の MCP サーバーとして動作します。 Claude Code などから以下のツールを呼び出せます。

  • fetch_url — URL を取得して Markdown / テキスト / JSON で返す

  • read_links — リンク一覧を抽出

  • extract_structured — LLM を使った構造化抽出

これにより、stillo は他の AI エージェントの「目」として機能できます。

今後の展望

将来的には「stillo ネイティブモード」という構想を検討しています。 サーバーはデータとセマンティクスのみを返し、表示やデザインはクライアントがコントロールするという、主従を逆転させた Web 体験です。 既存の Web へのフォールバックを保ちつつ、対応サーバーにはよりリッチなセマンティクスを返させるオプトイン型の拡張として設計する予定です。

まとめ

stillo は、Web からノイズを取り除いて LLM や人間にとって読みやすい形に変換するターミナルブラウザです。 Rust の型と非同期処理を活用し、CLI ツールとしても MCP サーバーとしても使えるようにしました。

興味がある方は GitHub リポジトリ を覗いてみてください。