Project 9: plug-master

Build a CLI with a plugin system and stable extension API.

Quick Reference

Attribute Value
Difficulty Level 4 (Advanced)
Time Estimate 1 month
Language Go (Alternatives: Rust)
Prerequisites CLI design, subprocesses, config
Key Topics Plugin architecture, IPC, versioning

1. Learning Objectives

By completing this project, you will:

  1. Design a stable plugin contract and versioning scheme.
  2. Discover plugins dynamically and register their commands.
  3. Communicate with plugins over a safe IPC protocol.
  4. Handle plugin crashes and timeouts gracefully.
  5. Build a CLI platform that can evolve without breaking extensions.

2. Theoretical Foundation

2.1 Core Concepts

  • Plugin Contracts: A plugin needs a stable handshake, capability declaration, and versioning.
  • IPC: The simplest cross-platform IPC is stdin/stdout with JSON messages.
  • Isolation: Running plugins as separate processes prevents crashes in plugins from taking down the core.
  • Compatibility: Version checks and feature flags allow gradual evolution.

2.2 Why This Matters

Extensibility is what turns a CLI into a platform. Plugin architecture is how tools like kubectl, terraform, and git gain huge ecosystems.

2.3 Historical Context / Background

Many tools implement plugin-like systems using subcommands found in PATH. Example: kubectl-foo acts as kubectl foo. Your project formalizes this pattern with a protocol.

2.4 Common Misconceptions

  • “Plugins can just be scripts”: Without a protocol, integration is brittle.
  • “Versioning is optional”: Breaking changes without versioning destroy ecosystems.

3. Project Specification

3.1 What You Will Build

A CLI named plug-master that:

  • Discovers plugins in a directory or PATH
  • Negotiates capabilities via handshake
  • Delegates subcommands to plugins
  • Provides core command help including plugin commands

3.2 Functional Requirements

  1. Discovery: Scan plugin directory and PATH for executables.
  2. Handshake: Plugins return name, version, supported commands.
  3. Execution: Core forwards args and input to plugin.
  4. Isolation: Plugin failure does not crash core.
  5. Timeouts: Long-running plugins are aborted safely.

3.3 Non-Functional Requirements

  • Security: Only load trusted directories.
  • Compatibility: Core rejects incompatible plugin versions.
  • Usability: Plugins appear in --help output.

3.4 Example Usage / Output

$ plug-master plugins
Name        Version  Commands
hello       1.0.0    hello

$ plug-master hello --name Alice
Hello, Alice

3.5 Real World Outcome

The CLI shows built-in commands plus plugin commands in help output. A plugin can be dropped into the plugin directory and immediately appears as a new subcommand.


4. Solution Architecture

4.1 High-Level Design

+-------------+     +----------------+     +------------------+
| CLI Core    | --> | Plugin Manager | --> | Plugin Process   |
+-------------+     +----------------+     +------------------+
        |                   |
        +-------------------+-- Protocol / JSON IPC

4.2 Key Components

Component Responsibility Key Decisions
Discovery Find plugin binaries PATH vs directory
Handshake Validate protocol version checks
Dispatcher Route commands delegation rules
IPC Layer JSON messages stdout/stdin

4.3 Data Structures

type PluginInfo struct {
    Name string
    Version string
    Commands []string
}

4.4 Algorithm Overview

Key Algorithm: Plugin handshake

  1. Start plugin process with --handshake.
  2. Read JSON handshake response.
  3. Validate protocol version.
  4. Register commands.

Complexity Analysis:

  • Time: O(P) for P plugins
  • Space: O(P) for plugin registry

5. Implementation Guide

5.1 Development Environment Setup

mkdir plug-master && cd plug-master
go mod init plug-master

5.2 Project Structure

plug-master/
├── cmd/
│   └── root.go
├── internal/
│   ├── plugins/
│   ├── protocol/
│   └── dispatch/
└── README.md

5.3 The Core Question You Are Answering

“How do I design an extension system that stays stable as my CLI grows?”

5.4 Concepts You Must Understand First

  1. Subprocess execution and IPC
  2. JSON serialization
  3. Versioning and compatibility

5.5 Questions to Guide Your Design

  1. How will plugin commands be named and discovered?
  2. What happens if two plugins provide the same command?
  3. How do you avoid loading untrusted plugins?

5.6 Thinking Exercise

Define a handshake JSON format. What fields are mandatory? How do you handle future additions?

5.7 The Interview Questions They Will Ask

  1. Why isolate plugins in separate processes?
  2. How do you handle incompatible plugins?
  3. What makes a plugin system stable?

5.8 Hints in Layers

Hint 1: Start with simple PATH-based discovery.

Hint 2: Add handshake mode returning static JSON.

Hint 3: Add delegation to plugin via stdin/stdout.

5.9 Books That Will Help

Topic Book Chapter
IPC “Advanced Programming in the UNIX Environment” Ch. 15
Software architecture “Fundamentals of Software Architecture” Ch. 12

5.10 Implementation Phases

Phase 1: Foundation (1 week)

Goals:

  • Discover plugins
  • Handshake protocol

Checkpoint: plug-master plugins lists plugins.

Phase 2: Command Delegation (1 week)

Goals:

  • Delegate subcommands
  • Pass args correctly

Checkpoint: Plugin commands execute.

Phase 3: Stability (1-2 weeks)

Goals:

  • Version checks
  • Error handling and timeouts

Checkpoint: Bad plugin does not crash core.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
IPC stdin/stdout vs sockets stdin/stdout Simple and portable
Discovery PATH vs plugin dir plugin dir Explicit trust
Protocol JSON vs custom JSON Easy to debug

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Unit Tests Protocol parsing handshake schema
Integration Tests Plugin execution stub plugin
Edge Cases plugin crash failure handling

6.2 Critical Test Cases

  1. Plugin responds with wrong version -> rejected.
  2. Plugin crashes mid-command -> core prints error.
  3. Duplicate command names -> conflict handling.

7. Common Pitfalls and Debugging

Pitfall Symptom Solution
Untrusted PATH plugins Security risk Use explicit plugin dir
Hanging plugins CLI stuck Add timeouts
Version mismatch Broken features Enforce protocol version

8. Extensions and Challenges

8.1 Beginner Extensions

  • Add plug-master plugin install from URL
  • Add plug-master plugin disable

8.2 Intermediate Extensions

  • Add plugin signature verification
  • Add plugin update checks

8.3 Advanced Extensions

  • Add RPC over sockets
  • Add plugin sandboxing

9. Real-World Connections

  • kubectl plugin system
  • terraform providers

10. Resources

  • kubectl plugin docs
  • JSON-RPC patterns

11. Self-Assessment Checklist

  • I can explain why protocol versioning matters
  • I can handle plugin failures safely

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Plugin discovery + execution

Full Completion:

  • Delegation + version checks

Excellence (Going Above and Beyond):

  • Plugin signing and updates