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:
- Design a stable plugin contract and versioning scheme.
- Discover plugins dynamically and register their commands.
- Communicate with plugins over a safe IPC protocol.
- Handle plugin crashes and timeouts gracefully.
- 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
- Discovery: Scan plugin directory and
PATHfor executables. - Handshake: Plugins return name, version, supported commands.
- Execution: Core forwards args and input to plugin.
- Isolation: Plugin failure does not crash core.
- 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
--helpoutput.
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
- Start plugin process with
--handshake. - Read JSON handshake response.
- Validate protocol version.
- 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
- Subprocess execution and IPC
- JSON serialization
- Versioning and compatibility
5.5 Questions to Guide Your Design
- How will plugin commands be named and discovered?
- What happens if two plugins provide the same command?
- 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
- Why isolate plugins in separate processes?
- How do you handle incompatible plugins?
- 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
- Plugin responds with wrong version -> rejected.
- Plugin crashes mid-command -> core prints error.
- 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 installfrom 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
kubectlplugin systemterraformproviders
10. Resources
kubectlplugin 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