MCPInstall

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
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads nushell-plugin-builder automatically when relevant.

  3. 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-plugin and nu-protocol versions
  • Both should match target Nushell version

Reference Documentation

  • references/plugin-protocol.md - Protocol details, serialization, lifecycle
  • references/advanced-features.md - Streaming, EngineInterface, custom values
  • references/examples.md - Complete working examples and patterns
  • references/testing-debugging.md - Development workflow, debugging, troubleshooting

External Resources

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

View all →

searxng-search

ypares/agent-skills

Enhanced web and package repository search using local SearXNG instance

AI & Agents829 installs

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.

Frontend & Design139 installs

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).

Docs & Writing123 installs

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

AI & Agents68 installs

Popular backend & apis skills

View category →

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.

OfficialBackend & APIs4.1M installs

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.

OfficialBackend & APIs566.7K installs

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).

Backend & APIs514.8K installs

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.

Backend & APIs453.3K installs

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).

OfficialBackend & APIs336.6K installs

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.

Backend & APIs237.1K installs