nushell-plugin-builder について
Nushell Plugin Builderは、Nushellのコマンドやデータ処理を拡張するプラグインを作るRust開発者向けスキルです。コマンド定義、ストリーミング、シリアライズ、テスト、インストールを扱います。
主な機能
- 01プラグインプロジェクトのひな形作成
- 02コマンドシグネチャと引数の定義
- 03値とデータストリームの処理
- 04MsgPackまたはJSONのシリアライズ選択
- 05テストとデバッグのガイド
活用シーン
- 01Nushellのカスタムコマンド作成
- 02大規模データ向けストリーミングプラグインの構築
- 03HTTP APIやファイルシステムを扱うプラグインの開発
- 04Rustプラグインのテストと登録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ypares/ agent-skills --skill nushell-plugin-builderインストール後、Claude Code で/nushell-plugin-builderを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/plugin-template/.gitignoreCargo.tomlREADME.mdassets/plugin-template/src/main.rsreferences/advanced-features.mdexamples.mdplugin-protocol.mdtesting-debugging.mdscripts/init_plugin.py詳細
Nushell プラグインビルダー
概要
このスキルは、Rust で Nushell プラグインを作成するのに役立ちます。プラグインは、カスタムコマンド、データ変換、各種連携機能で Nushell を拡張する、独立した実行ファイルです。
クイックスタート
1. プラグインプロジェクトを作成する
cargo new nu_plugin_<name>
cd nu_plugin_<name>
cargo add nu-plugin nu-protocol
2. 基本的なプラグイン構造
use nu_plugin::{EvaluatedCall, MsgPackSerializer, serve_plugin};
use nu_plugin::{EngineInterface, Plugin, PluginCommand, SimplePluginCommand};
use nu_protocol::{LabeledError, Signature, Type, Value};
struct MyPlugin;
impl Plugin for MyPlugin {
fn version(&self) -> String {
env!("CARGO_PKG_VERSION").into()
}
fn commands(&self) -> Vec<Box<dyn PluginCommand<Plugin = Self>>> {
vec![Box::new(MyCommand)]
}
}
struct MyCommand;
impl SimplePluginCommand for MyCommand {
type Plugin = MyPlugin;
fn name(&self) -> &str {
"my-command"
}
fn signature(&self) -> Signature {
Signature::build("my-command")
.input_output_type(Type::String, Type::Int)
}
fn run(
&self,
_plugin: &MyPlugin,
_engine: &EngineInterface,
call: &EvaluatedCall,
input: &Value,
) -> Result<Value, LabeledError> {
match input {
Value::String { val, .. } => {
Ok(Value::int(val.len() as i64, call.head))
}
_ => Err(LabeledError::new("Expected string input")
.with_label("requires string", call.head))
}
}
}
fn main() {
serve_plugin(&MyPlugin, MsgPackSerializer)
}
3. ビルドしてインストールする
# Build
cargo build --release
# Install to cargo bin
cargo install --path . --locked
# Register with nushell
plugin add ~/.cargo/bin/nu_plugin_<name> # Add .exe on Windows
plugin use <name>
# Test
"hello" | my-command
コマンドの種類
SimplePluginCommand
単一の値を処理するコマンドに使用します。
- 入力:
&Value - 出力:
Result<Value, LabeledError> - 用途:変換、シンプルなフィルター、単一値の操作
PluginCommand
ストリームを処理するコマンドに使用します。
- 入力:
PipelineData - 出力:
Result<PipelineData, LabeledError> - 用途:ストリーミング変換、遅延処理、大規模データセット
ストリーミングの例については、references/advanced-features.md を参照してください。
コマンドシグネチャの定義
入出力の型
use nu_protocol::{Signature, Type};
Signature::build("my-command")
.input_output_type(Type::String, Type::Int)
一般的な型:String、Int、Float、Bool、List(Box<Type>)、Record(...)、Any
パラメーター
Signature::build("my-command")
// Named flags
.named("output", SyntaxShape::Filepath, "output file", Some('o'))
.switch("verbose", "enable verbose output", Some('v'))
// Positional arguments
.required("input", SyntaxShape::String, "input value")
.optional("count", SyntaxShape::Int, "repeat count")
.rest("files", SyntaxShape::Filepath, "files to process")
引数へのアクセス
fn run(&self, call: &EvaluatedCall, ...) -> Result<Value, LabeledError> {
let output: Option<String> = call.get_flag("output")?;
let verbose: bool = call.has_flag("verbose")?;
let input: String = call.req(0)?; // First positional
let count: Option<i64> = call.opt(1)?; // Second positional
let files: Vec<String> = call.rest(2)?; // Remaining args
}
エラー処理
必ずスパン情報を含む LabeledError を返してください。
Err(LabeledError::new("Error message")
.with_label("specific issue", call.head))
これにより、コマンドのどこでエラーが発生したのかをユーザーに正確に示せます。
シリアライゼーション
MsgPackSerializer(推奨)
- バイナリー形式で、はるかに高速です
- 本番環境のプラグインに使用します
JsonSerializer
- テキストベースで、人が読みやすい形式です
- デバッグに便利です
main() で選択します。
serve_plugin(&MyPlugin, MsgPackSerializer) // Production
// serve_plugin(&MyPlugin, JsonSerializer) // Debug
よくあるパターン
文字列変換
Value::String { val, .. } => {
Ok(Value::string(val.to_uppercase(), call.head))
}
リストの生成
let items = vec![
Value::string("a", call.head),
Value::string("b", call.head),
];
Ok(Value::list(items, call.head))
レコード(テーブルの行)
use nu_protocol::record;
Ok(Value::record(
record! {
"name" => Value::string("example", call.head),
"size" => Value::int(42, call.head),
},
call.head,
))
テーブル(レコードのリスト)
let records = vec![
Value::record(record! { "name" => Value::string("a", span) }, span),
Value::record(record! { "name" => Value::string("b", span) }, span),
];
Ok(Value::list(records, call.head))
完全に動作する例については、references/examples.md を参照してください。次の内容を含みます。
- ストリームのフィルタリング
- HTTP API の呼び出し
- ファイルシステム操作
- 複数コマンドのプラグイン
開発ワークフロー
反復的な開発
# Build
cargo build
# Test (debug build)
plugin add target/debug/nu_plugin_<name>
plugin use <name>
"test" | my-command
# After changes, reload
plugin rm <name>
plugin add target/debug/nu_plugin_<name>
plugin use <name>
自動テスト
[dev-dependencies]
nu-plugin-test-support = "0.109.1"
#[cfg(test)]
mod tests {
use nu_plugin_test_support::PluginTest;
#[test]
fn test_command() -> Result<(), nu_protocol::ShellError> {
PluginTest::new("myplugin", MyPlugin.into())?
.test_examples(&MyCommand)
}
}
デバッグ手法とトラブルシューティングについては、references/testing-debugging.md を参照してください。
高度な機能
データのストリーミング
大規模データセットを遅延処理するには、PipelineData を使用します。
impl PluginCommand for MyCommand {
fn run(&self, input: PipelineData, ...) -> Result<PipelineData, LabeledError> {
let filtered = input.into_iter().filter(|v| /* condition */);
Ok(PipelineData::ListStream(ListStream::new(filtered, span, None), None))
}
}
エンジンとの連携
// Get environment variables
let home = engine.get_env_var("HOME")?;
// Set environment variables (before response)
engine.add_env_var("MY_VAR", Value::string("value", span))?;
// Get plugin config from $env.config.plugins.<name>
let config = engine.get_plugin_config()?;
// Get current directory for path resolution
let cwd = engine.get_current_dir()?;
カスタム値
Nushell の組み込み型を超えるカスタムデータ型を定義できます。詳しいガイドについては、references/advanced-features.md を参照してください。
重要な制約
標準入出力の制限
- プラグインは stdin/stdout を使用できません(プロトコル用に予約されています)
- 標準入出力にアクセスする前に、
engine.is_using_stdio()を確認してください
パスの処理
- 常に
engine.get_current_dir()からの相対パスを使用してください - 現在の作業ディレクトリを前提にしないでください
バージョンの互換性
nu-pluginとnu-protocolのバージョンを一致させてください- どちらも対象の Nushell のバージョンに合わせる必要があります
リファレンスドキュメント
references/plugin-protocol.md- プロトコルの詳細、シリアライゼーション、ライフサイクルreferences/advanced-features.md- ストリーミング、EngineInterface、カスタム値references/examples.md- 完全に動作する例とパターンreferences/testing-debugging.md- 開発ワークフロー、デバッグ、トラブルシューティング
外部リソース
- 公式プラグインガイド
- nu-plugin API ドキュメント
- プラグインのサンプルリポジトリ
- Awesome Nu - コミュニティプラグイン
- nushellWith - プラグインを含む、再現可能な Nushell 環境をビルドするための Nix flake です。Garnix によるバイナリーキャッシュを利用し、crates.io のパッケージ済みプラグインを 100 個以上収録しています。分離された環境でプラグインをテストしたり、単独で動作する Nu スクリプトをビルドしたりするのに便利です。
テンプレートスクリプト
scripts/init_plugin.py を使用して、適切な構造の新しいプラグインのひな形を作成します。
python3 scripts/init_plugin.py <plugin-name> [--output-dir <path>]
これにより、カスタマイズしてすぐに使える、完全に動作するプラグインテンプレートが作成されます。