extensions/
このディレクトリには、Pyxisの拡張機能(TypeScript/TSX)のソースコードが含まれています。
- 各拡張機能ごとに
package.jsonを配置し、pnpm installでnpmライブラリが利用可能 chart.jsやlodashなど、ほぼ全てのnpmパッケージが使えます- esbuildによる依存バンドルで高速・安全
- React/ReactDOMはPyxis本体からグローバル提供(依存不要)
- 拡張機能から独自のターミナルコマンドを追加可能
context.terminal.registerCommandでコマンド名・実装・引数・説明を登録- ユーザーはPyxisのターミナルUIから直接コマンド実行
- コマンドはNode.js/TypeScriptで記述可能
- コマンドの引数・補完・説明も拡張機能側で定義
├── _shared/ # 共通型定義
├── chart-extension/ # Chart.jsなど外部ライブラリ利用例
├── typescript-runtime/ # TypeScript/JSXトランスパイラ
├── note-tab/ # ノートタブ拡張機能
├── todo-panel/ # TODOパネル拡張機能
├── lang-packs/ # 多言語パック
└── ...
- 拡張機能テンプレート作成
npm run create-extensionで対話生成
- または手動で`extensions/<name>/`ディレクトリ作成
- npmライブラリ追加
package.jsonを作成し、pnpm install chart.js lodashなどで依存追加- TypeScript/TSXで自由にimport可能
- Terminalコマンド追加
context.terminal.registerCommandでコマンドを登録- コマンドはNode.js/TypeScriptで実装
- ビルド
node build-extensions.jsでesbuildバンドル- 依存も自動バンドル
- 自動配置
public/extensions/にバンドル済みJS配置
- 一括ビルド
npm run setup-buildで全拡張機能を一括ビルド
| タイプ | 説明 | React必須 | 返り値 | npmライブラリ | Terminalコマンド |
|---|---|---|---|---|---|
| transpiler | TypeScript/JSX等のトランスパイラ | ❌ | runtimeFeatures |
✅ | ✅ |
| service | 言語パック(i18n等) | ❌ | services |
✅ | ✅ |
| builtin-module | Node.js互換モジュール | ❌ | builtInModules |
✅ | ✅ |
| ui | カスタムタブ/サイドバー | ✅ | {} |
✅ | ✅ |
// index.ts
export async function activate(context: ExtensionContext): Promise<ExtensionActivation> {
context.terminal?.registerCommand({
name: 'hello',
description: 'Hello Worldを表示',
args: [{ name: 'name', type: 'string', required: false }],
handler: async ({ name }) => {
return `Hello, ${name || 'World'}!`;
}
});
// ...他のAPI登録
return {};
}// index.tsx
import Chart from 'chart.js/auto';
import _ from 'lodash';
function MyChartTab() {
// Chart.jsやlodashがそのまま使える!
// ...
}{
"id": "pyxis.chart-extension",
"name": "Chart Extension",
"version": "1.0.0",
"type": "ui",
"description": "Chart.jsを使ったグラフ表示拡張",
"author": "Your Name",
"defaultEnabled": false,
"entry": "index.js",
"metadata": {
"publishedAt": "2025-01-01T00:00:00Z",
"tags": ["ui", "chart", "productivity"]
}
}ExtensionContextにterminalプロパティ追加terminal.registerCommandでコマンド拡張- npmライブラリは
pnpm installで自由に追加 - UI拡張はTSX推奨
- 詳細は
_shared/types.ts参照
A: ほぼ全て使えます。Chart.js, lodash, dayjs, axiosなど主要ライブラリは全てOK。React/ReactDOMはPyxis本体から提供されるので依存不要です。
A: Node.js/TypeScriptで記述できる任意のコマンド。引数・補完・説明も自由に定義可能。UI拡張からもコマンド登録できます。
A: 後方互換性は気にせず、新API・新構造で記述してください。
/docs/EXTENSION-SYSTEM.md- 拡張機能システム設計/docs/EXTENSION-TAB-SIDEBAR-API.md- タブ/サイドバーAPI/docs/EXTENSION-NPM-LIBRARIES.md- npmライブラリ利用ガイド/docs/SYSTEM-OVERVIEW.md- システム全体概要
- Chart Extension (
extensions/chart-extension/) - Chart.js利用例 - Note Tab (
extensions/note-tab/) - ノートタブ - TODO Panel (
extensions/todo-panel/) - TODOリスト - TypeScript Runtime (
extensions/typescript-runtime/) - トランスパイラ - Lang Packs (
extensions/lang-packs/) - 多言語パック
- TypeScript / TSX
- React (グローバル)
- esbuild (package.jsonあり)
- tsc (package.jsonなし)
- pnpm (依存管理)
- IndexedDB (キャッシュ)
- Node.js API互換
Pyxis拡張機能は2025年からnpmライブラリ・Terminalコマンド拡張に完全対応。 Chart.jsやlodashなど外部ライブラリを自由に使い、独自コマンドも追加可能。 新API・新構造で、より強力な拡張機能開発が可能です。
- TypeScript/TSX バンドル: esbuildで依存関係をバンドル
- npm/pnpm/yarn サポート: 自動的に依存関係をインストール
- React外部化: React/ReactDOMはPyxis本体を使用
- Tree-shaking: 使われていないコードを削除
public/extensions/に出力
- TypeScript/TSX トランスパイル: tscで単純にトランスパイル
- TSX →
React.createElementに変換 import React from 'react'→const React = window.__PYXIS_REACT__に変換
- TSX →
- JSON/画像/Markdown ファイルをコピー
public/extensions/に出力
実行方法:
node build-extensions.jsビルド時の変換例:
// 開発時 (index.tsx)
import React from 'react';
import { debounce } from 'lodash-es';
<div>Hello</div>
// ビルド後 (index.js) - esbuildモード
const React = window.__PYXIS_REACT__;
// lodash-esがバンドルされている
React.createElement('div', null, 'Hello')重要: React/ReactDOMはバンドルされません。ランタイムでwindow.__PYXIS_REACT__とwindow.__PYXIS_REACT_DOM__から提供されます。
詳細: /docs/EXTENSION-NPM-LIBRARIES.md を参照
public/extensions/registry.json には利用可能な拡張機能の一覧が含まれています。
このファイルはビルド時に自動生成されるため、手動での編集は不要です。
pnpm run setup-build を実行すると、extensions/ ディレクトリ内の全拡張機能が自動的にスキャンされ、registry.jsonが生成されます。
- 言語: TypeScript / TSX
- UI: React (グローバルスコープから提供)
- バンドラー:
- esbuild (package.jsonがある場合)
- tsc (package.jsonがない場合)
- JSX設定:
jsx: 'transform'(esbuild) またはjsx: 'react'(tsc)- JSX Factory:
React.createElement
- 依存関係: npm/pnpm/yarnでインストール
- 外部化: React/ReactDOMはPyxis本体を使用
- 配置: 静的ファイルとして
public/extensions/ - ロード: fetch + IndexedDBキャッシュ
- アーキテクチャ: Static Site (サーバーサイド処理なし)
pnpm run create-extensionで対話式テンプレート生成(推奨)- 必要な情報(ID/名前/タイプ/UI種別など)を入力するだけで、
manifest.json・index.tsx・README.mdが自動生成 - 生成直後のコードは、カスタムタブ・サイドバー両方のサンプルを含む
context.tabs.registerTabType(Component)でタブコンポーネントを登録context.tabs.createTab({ ... })でタブ作成context.tabs.updateTab(tabId, { ... })でタブ更新context.tabs.closeTab(tabId)でタブを閉じるcontext.tabs.onTabClose(tabId, cb)でクローズイベント登録
実装例(TSX/Javascript):
// タブコンポーネント登録
context.tabs.registerTabType(MyTabComponent);
// タブ作成
const tabId = context.tabs.createTab({
id: 'main',
title: 'ui-ref',
icon: 'FileText',
closable: true,
activateAfterCreate: true,
data: { content: 'Hello' },
});
// クローズイベント
context.tabs.onTabClose(tabId, (closedTabId) => {
// クリーンアップ処理
});Props:
tab(タブ情報)isActive(アクティブ状態)
context.sidebar.createPanel({ ... })でサイドバーパネル追加context.sidebar.updatePanel(panelId, state)で状態更新context.sidebar.removePanel(panelId)で削除context.sidebar.onPanelActivate(panelId, cb)でアクティブイベント
実装例:
const Panel = createUiCopilotRefPanel(context);
context.sidebar.createPanel({
id: 'ui-copilot-ref-panel',
title: 'ui-ref',
icon: 'Package',
component: Panel,
order: 50,
});
context.sidebar.onPanelActivate('ui-copilot-ref-panel', (panelId) => {
// パネルがアクティブ化された時の処理
});Props:
extensionId(拡張ID)panelId(パネルID)isActive(アクティブ状態)state(パネル状態)
- タブ/パネルの登録は
activate関数内で行う - クローズ/アクティブイベントでリソース管理・永続化
- npmライブラリは
pnpm installで自由に追加 - UIはTSX推奨(React/JSX構文)
- APIはVSCodeライクな設計
import React, { useState, useEffect } from 'react';
import type { ExtensionContext, ExtensionActivation } from '../_shared/types';
function MyTabComponent({ tab, isActive }: { tab: any; isActive: boolean }) {
// ...タブの内容
}
function createMyPanel(context: ExtensionContext) {
return function MyPanel({ extensionId, panelId, isActive, state }: any) {
// ...パネルの内容
};
}
export async function activate(context: ExtensionContext): Promise<ExtensionActivation> {
context.tabs.registerTabType(MyTabComponent);
if (context.sidebar) {
const Panel = createMyPanel(context);
context.sidebar.createPanel({
id: 'my-panel',
title: 'My Panel',
icon: 'Package',
component: Panel,
order: 50,
});
}
return {};
}- Q: タブ/サイドバーは複数同時に作れる?
- A: 可能。IDで一意管理され、同じIDなら再利用される
- Q: CLIテンプレート生成後は何を編集すればいい?
- A:
index.tsxのタブ・パネルコンポーネントを編集。APIは全て使える
- A:
- Q: npmライブラリは制限ある?
- A: 主要ライブラリは全て利用可能。React/ReactDOMはPyxis本体から提供
- Q: API仕様はどこで確認?
- A:
/Development/EXTENSION-TAB-SIDEBAR-API.md・_shared/types.ts・サンプル拡張機能を参照
- A:
- activate関数で必ず
registerTabType/createPanelを呼ぶ - propsは必ず型定義に準拠
- クリーンアップは
onTabClose/onPanelActivateで - npmライブラリは自由にimport可能
Pyxis拡張機能は2025年から「CLIテンプレート生成」「npmライブラリ完全対応」「Terminalコマンド拡張」「VSCodeライクなTab/Sidebar API」に刷新。 タブ・サイドバーの追加/管理はAPIで直感的に実装でき、サンプルやテンプレートも充実。 API仕様は随時最新化されているため、公式ドキュメント・サンプルを参照してください。
詳細な実装例は以下を参照してください:
- Note Tab (
extensions/note-tab/) - シンプルなノートタブ (TSX使用) - TODO Panel (
extensions/todo-panel/) - TODOリスト管理 (TSX使用)
詳細は以下を参照してください:
/docs/EXTENSION-TAB-SIDEBAR-API.md- 拡張機能開発ガイド (必読)/docs/EXTENSION-SYSTEM.md- 拡張機能システムの設計/docs/SYSTEM-OVERVIEW.md- システム全体概要
A: UI拡張機能の場合はTSXを推奨します。 直感的で読みやすく、Reactのベストプラクティスに沿っています。非UI拡張機能(transpiler, serviceなど)の場合はTypeScript (.ts) で十分です。
A: UI拡張機能の場合のみ必須です。 import React from 'react' は必須で、ビルド時にconst React = window.__PYXIS_REACT__に変換されます。非UI拡張機能(typescript-runtime, lang-packsなど)ではReactは不要です。
A: はい!(v0.12.0以降) 拡張機能ディレクトリにpackage.jsonを追加し、pnpm installすれば使用できます。esbuildで自動的にバンドルされます。詳細は /docs/EXTENSION-NPM-LIBRARIES.md を参照してください。
注意: React/ReactDOMはPyxis本体のものを使用するため、依存関係に含めないでください。
A: localStorageを使用してください。
// 保存
localStorage.setItem('my-extension-data', JSON.stringify(data));
// 読み込み
const data = JSON.parse(localStorage.getItem('my-extension-data') || '{}');A: CustomEventを使用してください。
// イベント発火
window.dispatchEvent(new CustomEvent('my-event', { detail: { data } }));
// イベントリッスン
window.addEventListener('my-event', (event) => {
console.log(event.detail.data);
});