# Plugin Development Developing Nushell plugins for performance-critical operations in the Provisioning platform. ## Plugin Overview Nushell plugins provide 10-50x performance improvement over HTTP APIs through native Rust implementations. ### Available Plugins | Plugin | Purpose | Performance Gain | Language | | ------ | ------- | ---------------- | -------- | | nu_plugin_auth | Authentication and OS keyring | 5x faster | Rust | | nu_plugin_kms | KMS encryption operations | 10x faster | Rust | | nu_plugin_orchestrator | Orchestrator queries | 30x faster | Rust | ## Plugin Architecture Plugins communicate with Nushell via MessagePack protocol: ```text Nushell ←→ MessagePack ←→ Plugin Process ↓ ↓ Script Native Rust ``` ## Creating a Plugin ### Plugin Template Generate plugin scaffold: ```bash # Create new plugin cargo new --lib nu_plugin_myfeature cd nu_plugin_myfeature ``` Add dependencies to `Cargo.toml`: ```toml [package] name = "nu_plugin_myfeature" version = "0.1.0" edition = "2021" [dependencies] nu-plugin = "0.109.0" nu-protocol = "0.109.0" serde = {version = "1.0", features = ["derive"]} ``` ### Plugin Implementation Implement plugin interface: ```rust // src/lib.rs use nu_plugin::{EvaluatedCall, LabeledError, Plugin}; use nu_protocol::{Category, PluginSignature, SyntaxShape, Type, Value}; pub struct MyFeaturePlugin; impl Plugin for MyFeaturePlugin { fn signature(&self) -> Vec { vec![ PluginSignature::build("my-feature") .usage("Perform my feature operation") .required("input", SyntaxShape::String, "input value") .input_output_type(Type::String, Type::String) .category(Category::Custom("provisioning".into())), ] } fn run( &mut self, name: &str, call: &EvaluatedCall, input: &Value, ) -> Result { match name { "my-feature" => self.my_feature(call, input), _ => Err(LabeledError { label: "Unknown command".into(), msg: format!("Unknown command: {}", name), span: None, }), } } } impl MyFeaturePlugin { fn my_feature(&self, call: &EvaluatedCall, _input: &Value) -> Result { let input: String = call.req(0)?; // Perform operation let result = perform_operation(&input); Ok(Value::string(result, call.head)) } } fn perform_operation(input: &str) -> String { // Your implementation here format!("Processed: {}", input) } // Plugin entry point fn main() { nu_plugin::serve_plugin(&mut MyFeaturePlugin, nu_plugin::MsgPackSerializer {}) } ``` ### Building Plugin ```bash # Build release version cargo build --release # Install plugin nu -c 'plugin add target/release/nu_plugin_myfeature' nu -c 'plugin use myfeature' # Test plugin nu -c 'my-feature "test input"' ``` ## Plugin Performance Optimization ### Benchmarking ```rust use std::time::Instant; pub fn benchmark_operation() { let start = Instant::now(); // Operation to benchmark perform_expensive_operation(); let duration = start.elapsed(); eprintln!("Operation took: {:?}", duration); } ``` ### Caching Implement caching for expensive operations: ```rust use std::collections::HashMap; use std::sync::{Arc, Mutex}; pub struct CachedPlugin { cache: Arc>>, } impl CachedPlugin { fn get_or_compute(&self, key: &str) -> String { let mut cache = self.cache.lock().unwrap(); if let Some(value) = cache.get(key) { return value.clone(); } let value = expensive_computation(key); cache.insert(key.to_string(), value.clone()); value } } ``` ## Testing Plugins ### Unit Tests ```rust #[cfg(test)] mod tests { use super::*; use nu_protocol::{Span, Value}; #[test] fn test_my_feature() { let plugin = MyFeaturePlugin; let input = Value::string("test", Span::test_data()); let result = plugin.my_feature(&mock_call(), &input).unwrap(); assert_eq!(result.as_string().unwrap(), "Processed: test"); } fn mock_call() -> EvaluatedCall { // Mock EvaluatedCall for testing todo!() } } ``` ### Integration Tests ```nushell # tests/test_plugin.nu use std assert def test_plugin_functionality [] { let result = my-feature "test input" assert equal $result "Processed: test input" } def main [] { test_plugin_functionality print "Plugin tests passed" } ``` ## Plugin Best Practices - Keep plugin logic focused and single-purpose - Minimize dependencies to reduce binary size - Use async operations for I/O-bound tasks - Implement proper error handling - Document all plugin commands - Version plugins with semantic versioning - Provide fallback to HTTP API if plugin unavailable - Cache expensive computations - Profile and benchmark performance improvements ## Related Documentation - [Build System](build-system.md) - Building Rust plugins - [Extension Development](extension-development.md) - Extension basics - [Testing](testing.md) - Testing strategies