npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@delve.sh/plugin-sdk

v1.0.6

Published

Delve Plugin SDK for creating custom plugins

Readme

@portablesheep/plugin-sdk

Utilities for building Delve plugins. This repository ships two packages that work together:

  • Go module github.com/PortableSheep/delve-sdk for authoring plugin backends
  • npm package @delve/plugin-sdk for frontend command bridging

The sections below describe what each package provides today.

SDK Versioning & Schemas

  • The current Go SDK version is exposed as sdk.Version (e.g. v0.5.0). Plugins should include this value in their registration payloads so the host can reject incompatible builds early.
  • sdk.CompatibleHostRange documents the Delve host versions the SDK is tested with. Future releases will expand this range; treat it as the source of truth when shipping plugins.
  • JSON schema helpers sdk.PluginManifestSchema() and sdk.LayoutSchema() are available for validating plugin.json manifests and persisted docking layout state. These are the same schemas the Delve host enforces at runtime.

Frontend command bridge (npm)

Install from GitHub Packages

  • go-utility: Full-featured Go plugin with frontend
  • theme: CSS theme plugin
  • integration: API integration plugin
  • dashboard: Data visualization plugin

Custom Templates

customTemplate := &sdk.PluginTemplate{
    Name:        "custom-api",
    Description: "Custom API integration template",
    Type:        "integration",
    Language:    "go",
    Files: []sdk.TemplateFile{
        {
            Path:     "main.go",
            Template: true,
            Content:  "// Custom template content with {{.Variables}}",
        },
    },
    Variables: map[string]interface{}{
        "APIVersion": "v1",
    },
}

enhancedSDK.Generator().RegisterTemplate(customTemplate)

🔧 Configuration

SDK Configuration

config := sdk.SDKConfig{
    RegistryURL:   "https://registry.delve.sh",
    SecurityLevel: sdk.SecurityLevelMedium,
    CacheEnabled:  true,
    DevMode:       false,
    LogLevel:      sdk.LogLevelInfo,
    CustomTemplates: map[string]*sdk.PluginTemplate{
        "my-template": customTemplate,
    },
}

sdk := sdk.NewEnhancedSDK(config)

📚 API Reference

Core Types

  • EnhancedSDK - Main SDK interface
  • EnhancedPlugin - Enhanced plugin interface with lifecycle methods
  • SecurityManager - Handles security policies and sandboxing
  • EnhancedRegistry - Advanced plugin registry with search and metadata
  • SchemaValidator - Plugin configuration validation
  • PluginGenerator - Template-based plugin generation
  • DevTools - Development and build tools

Security Types

  • SecurityLevel - Security level enumeration
  • SecurityPolicy - Security policy configuration
  • Permission - Permission request structure
  • Sandbox - Isolated execution environment

Registry Types

  • EnhancedPluginInfo - Complete plugin metadata
  • RegistrySearchFilter - Advanced search filtering
  • PluginMetrics - Usage and performance metrics

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🆘 Support

Storage API

Plugin.SetItem(key, value string) error

Store a key-value pair in plugin storage.

Plugin.GetItem(key string) (string, error)

Retrieve a value from plugin storage.

Plugin.DeleteItem(key string) error

Delete a key from plugin storage.

Plugin.ListItems() ([]string, error)

List all keys in plugin storage.

Plugin.ClearStorage() error

Clear all plugin storage.

Heartbeat Behavior

The heartbeat system provides robust connection monitoring:

Normal Operation

  1. Plugin sends heartbeat every interval seconds
  2. Host responds with heartbeat acknowledgment
  3. Plugin tracks last successful heartbeat response

Failure Detection

  1. If no heartbeat response received within timeout
  2. Plugin logs timeout warning
  3. Calls StateManager.SaveState() if configured
  4. Plugin shuts down gracefully

Benefits

  • Prevents zombie processes when host crashes
  • Saves plugin state before unexpected shutdown
  • Reduces resource usage by cleaning up orphaned plugins
  • Improves system stability

Error Handling

Connection Errors

plugin, err := sdk.Start(pluginInfo)
if err != nil {
    log.Printf("Failed to connect: %v", err)
    // Handle connection failure
}

Storage Errors

err := plugin.SetItem("key", "value")
if err != nil {
    log.Printf("Storage error: %v", err)
    // Handle storage failure
}

Best Practices

1. Always Use Heartbeat

// Recommended for all production plugins
plugin.StartHeartbeat(30*time.Second, 60*time.Second)

2. Implement State Management

type MyPlugin struct {
    importantData map[string]interface{}
    configPath    string
}

func (p *MyPlugin) SaveState() error {
    // Save critical state that should survive restarts
    return saveToFile(p.configPath, p.importantData)
}

3. Handle Graceful Shutdown

import (
    "os"
    "os/signal"
    "syscall"
)

// Listen for OS signals
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

go func() {
    <-sigChan
    log.Println("Shutting down gracefully...")
    plugin.Close()
    os.Exit(0)
}()

4. Use Context for Background Work

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go func() {
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ctx.Done():
            return
        case <-ticker.C:
            // Do background work
        }
    }
}()

5. Log Important Events

plugin.Listen(func(messageType int, data []byte) {
    log.Printf("Received message type %d: %s", messageType, string(data))
    // Process message
})

Plugin Lifecycle

UI Contributions (Sidebar & Footer)

Plugins can extend the Delve UI with sidebar items and footer widgets, and update them live at runtime.

Helpers on Plugin:

  • SetUIContributions(c UIContributions) – replace all sidebar/footer entries
  • UpsertSidebarItem(item SidebarItem) – insert or replace a sidebar item and emit an update
  • UpsertFooterWidget(w FooterWidget) – insert or replace a footer widget and emit an update
  • SetFooterBadgeCount(identifier string, count int) – update a footer widget badge by ElementTag or Title

Minimal usage:

// During registration
pluginInfo := &sdk.RegisterRequest{
    Name:             "my-plugin",
    Description:      "Demo",
    CustomElementTag: "my-plugin",
    UiComponentPath:  "frontend/component.js",
}
plugin, _ := sdk.Start(pluginInfo)

// Contribute a sidebar item and a footer icon
_ = plugin.SetUIContributions(sdk.UIContributions{
    Sidebar: []sdk.SidebarItem{
        { Title: "My Plugin", ElementTag: "my-plugin", ComponentPath: "frontend/component.js", OnClickCommand: &sdk.CommandRef{ID: "my-plugin.open"} },
    },
    Footer: []sdk.FooterWidget{
        { Title: "My Plugin", Icon: "mdi:rocket", OnClickCommand: &sdk.CommandRef{ID: "my-plugin.open"} },
    },
})

// Update badge later (e.g., unread count)
_ = plugin.SetFooterBadgeCount("My Plugin", 5)

// Default click handler returns an activation hint for the frontend
plugin.OnCommand("my-plugin.open", func(ctx context.Context, args []any) (any, error) {
    return map[string]any{"activateUI": map[string]any{"plugin": "my-plugin", "tag": "my-plugin"}}, nil
})
  1. Startup: Plugin connects and registers with host
  2. Running: Plugin processes messages and performs work
  3. Heartbeat: Regular health checks with host
  4. Shutdown: Graceful cleanup when connection lost or timeout
  5. State Save: Critical data persisted before exit

Publishing to Registry

To make your plugin available through the Delve Plugin Registry:

  1. Create plugin.json with complete metadata including screenshots
  2. Add screenshots to a screenshots/ directory in your repository
  3. Submit to registry via pull request

Directory Structure:

my-plugin/
├── plugin.json           # Plugin metadata
├── main.go              # Plugin source code
├── frontend/
│   └── component.js     # Frontend component
├── screenshots/         # Plugin screenshots
    ├── overview.png
    ├── settings.png
    └── features.png

Frontend Integration

Your plugin's frontend component should match the CustomElementTag:

// If CustomElementTag is "my-plugin"
class MyPlugin extends HTMLElement {
    connectedCallback() {
        this.innerHTML = '<h1>My Plugin UI</h1>';
    }
}

customElements.define('my-plugin', MyPlugin);

Troubleshooting

Plugin Not Appearing in Sidebar

  • Check host-config.yml has plugin enabled
  • Verify plugin executable exists and is executable
  • Check plugin registration logs

Connection Issues

  • Ensure host is running on correct WebSocket port
  • Check firewall settings
  • Verify --ws-port flag is passed correctly

Heartbeat Timeouts

  • Check host system resources
  • Adjust timeout values for slower systems
  • Monitor network connectivity

State Not Saving

  • Verify StateManager interface implementation
  • Check file permissions for state files
  • Review error logs during shutdown

Examples

See example.go for a complete plugin implementation with:

  • Heartbeat monitoring
  • State management
  • Background work
  • Graceful shutdown
  • Signal handling

Requirements

  • Go 1.19 or later
  • Delve host application
  • WebSocket support