
nushell-plugin-builder
Guide for creating Nushell plugins in Rust using nuplugin and nuprotocol crates. Use when users want to build custom Nushell commands, extend Nushell with new functionality, create data transformations, or integrate external tools/APIs into Nushell. Covers project setup, command implementation, streaming data, custom values, and testing.
- Installs
- 45
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/ypares/agent-skills --skill nushell-plugin-builder- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads nushell-plugin-builder automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Nushell Plugin Builder
Overview
This skill helps create Nushell plugins in Rust. Plugins are standalone executables that extend Nushell with custom commands, data transformations, and integrations.
Quick Start
1. Create Plugin Project
cargo new nu_plugin_<name>
cd nu_plugin_<name>
cargo add nu-plugin nu-protocol
2. Basic Plugin Structure
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 and Install
# 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
Command Types
SimplePluginCommand
For commands that operate on single values:
- Input:
&Value - Output:
Result<Value, LabeledError> - Use for: transformations, simple filters, single value operations
PluginCommand
For commands that handle streams:
- Input:
PipelineData - Output:
Result<PipelineData, LabeledError> - Use for: streaming transformations, lazy processing, large datasets
See references/advanced-features.md for streaming examples.
Defining Command Signatures
Input-Output Types
use nu_protocol::{Signature, Type};
Signature::build("my-command")
.input_output_type(Type::String, Type::Int)
Common types: String, Int, Float, Bool, List(Box<Type>), Record(...), Any
Parameters
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")
Accessing Arguments
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
}
Error Handling
Always return LabeledError with span information:
Err(LabeledError::new("Error message")
.with_label("specific issue", call.head))
This shows users exactly where the error occurred in their command.
Serialization
MsgPackSerializer (Recommended)
- Binary format, much faster
- Use for production plugins
JsonSerializer
- Text-based, human-readable
- Useful for debugging
Choose in main():
serve_plugin(&MyPlugin, MsgPackSerializer) // Production
// serve_plugin(&MyPlugin, JsonSerializer) // Debug
Common Patterns
String Transformation
Value::String { val, .. } => {
Ok(Value::string(val.to_uppercase(), call.head))
}
List Generation
let items = vec![
Value::string("a", call.head),
Value::string("b", call.head),
];
Ok(Value::list(items, call.head))
Record (Table Row)
use nu_protocol::record;
Ok(Value::record(
record! {
"name" => Value::string("example", call.head),
"size" => Value::int(42, call.head),
},
call.head,
))
Table (List of Records)
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))
See references/examples.md for complete working examples including:
- Filtering streams
- HTTP API calls
- File system operations
- Multi-command plugins
Development Workflow
Iterative Development
# 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>
Automated Testing
[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)
}
}
See references/testing-debugging.md for debugging techniques and troubleshooting.
Advanced Features
Streaming Data
For lazy processing of large datasets, use 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))
}
}
Engine Interaction
// 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()?;
Custom Values
Define custom data types that extend beyond Nushell's built-in types. See references/advanced-features.md for complete guide.
Important Constraints
Stdio Restrictions
- Plugins cannot use stdin/stdout (reserved for protocol)
- Check
engine.is_using_stdio()before attempting stdio access
Path Handling
- Always use paths relative to
engine.get_current_dir() - Never assume current working directory
Version Compatibility
- Match
nu-pluginandnu-protocolversions - Both should match target Nushell version
Reference Documentation
references/plugin-protocol.md- Protocol details, serialization, lifecyclereferences/advanced-features.md- Streaming, EngineInterface, custom valuesreferences/examples.md- Complete working examples and patternsreferences/testing-debugging.md- Development workflow, debugging, troubleshooting
External Resources
- Official Plugin Guide
- nu-plugin API Docs
- Plugin Examples Repository
- Awesome Nu - Community plugins
- nushellWith - Nix flake for building reproducible Nushell environments with plugins. Includes 100+ pre-packaged plugins from crates.io with binary caching via Garnix. Useful for testing plugins in isolated environments or building standalone Nu scripts.
Template Script
Use scripts/init_plugin.py to scaffold a new plugin with proper structure:
python3 scripts/init_plugin.py <plugin-name> [--output-dir <path>]
This creates a complete working plugin template ready to customize.
FAQ
What does the nushell-plugin-builder skill do?
Guide for creating Nushell plugins in Rust using nuplugin and nuprotocol crates. Use when users want to build custom Nushell commands, extend Nushell with new functionality, create data transformations, or integrate external tools/APIs into Nushell. Covers project setup, command implementation, streaming data, custom values, and testing.
How do I install nushell-plugin-builder?
Run npx skills add https://github.com/ypares/agent-skills --skill nushell-plugin-builder in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/nushell-plugin-builder/ (personal) or .claude/skills/nushell-plugin-builder/ (project).
Which AI agents can use nushell-plugin-builder?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is nushell-plugin-builder safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains nushell-plugin-builder?
It is published by ypares in ypares/agent-skills. It has 45 recorded installs.
More from ypares/agent-skills
searxng-search
ypares/agent-skills
Enhanced web and package repository search using local SearXNG instance
textual-builder
ypares/agent-skills
Build Text User Interface (TUI) applications using the Textual Python framework (v0.86.0+). Use when creating terminal-based applications, prototyping card games or interactive CLIs, or when the user mentions Textual, TUI, or terminal UI. Includes comprehensive reference documentation, card game starter template, and styling guides.
typst-writer
ypares/agent-skills
Write correct and idiomatic Typst code for document typesetting. Use when creating or editing Typst (.typ) files, working with Typst markup, or answering questions about Typst syntax and features. Focuses on avoiding common syntax confusion (arrays vs content blocks, proper function definitions, state management).
github-pr-workflow
ypares/agent-skills
Working with GitHub Pull Requests using the gh CLI. Use for fetching PR details, review comments, CI status, and understanding the difference between PR-level comments vs inline code review comments.
working-with-jj
ypares/agent-skills
Expert guidance for using JJ (Jujutsu) version control system. Use when working with JJ, whatever the subject. Operations, revsets, templates, debugging change evolution, etc. Covers JJ commands, template system, evolog, operations log, and interoperability with git remotes.
cursor-agent-supervisor
ypares/agent-skills
Offloading tasks with a well-defined scope to sub-agents, for instance to use a sub-agent to implement a set of specs. Use this skill whenever a task should not need a broad knowledge of the whole project
Popular backend & apis skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
entra-app-registration
microsoft/azure-skills
Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.
google-agents-cli-adk-code
google/agents-cli
This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).
embedded-captions
heygen-com/hyperframes
Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.
entra-agent-id
microsoft/azure-skills
Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).
neon
neondatabase/agent-skills
Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.