Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 24, 2026

Implementation Status: ✅ COMPLETE

Successfully implemented a complete pluggable CLI command system for Worklog.

Documentation Improvements (Based on PR Feedback)

Clarifications added:

  • Type imports are optional for JavaScript plugins (only needed for TypeScript development)
  • Plugin folder structure recommendations with example
  • Command grouping explanation (plugins appear in "Other" group)
  • Verbose logging best practices with code example
  • Clearer explanation of requireInitialized() pattern

Content organization:

  • Moved inline plugin examples to dedicated example files (bulk-tag-plugin.mjs, export-csv-plugin.mjs)
  • Consolidated README.md Plugins section (removed duplicate Features/Documentation subsections)
  • Streamlined examples/README.md (removed redundant Testing/Contributing/License sections)
  • Removed Contributing/License sections from PLUGIN_GUIDE.md

File cleanup:

  • Removed src/cli-old.ts backup file

What Was Accomplished

🏗️ Architecture (Phase 1-3)

  • Plugin API: Clean TypeScript interfaces with PluginContext
  • Plugin Loader: ESM dynamic import with error handling
  • Command Modules: Migrated all 17 built-in commands to src/commands/
  • CLI Bootstrap: Reduced cli.ts from 2,078 to 199 lines (90% reduction)

🔌 Plugin System Features

  • ✅ Drop-in installation (.worklog/plugins/ directory)
  • ✅ ESM module support (.js / .mjs files)
  • ✅ Deterministic load order (lexicographic)
  • ✅ Full database and config access
  • ✅ JSON output mode support
  • ✅ Error handling (failed plugins don't break CLI)
  • ✅ Environment variable configuration (WORKLOG_PLUGIN_DIR)
  • ✅ Introspection command (worklog plugins)

🧪 Testing (Phase 5)

  • 180 tests passing (151 original + 29 new)
  • 20 unit tests for plugin discovery/loading
  • 9 integration tests for end-to-end plugin execution
  • All existing functionality preserved
  • New features fully covered

📚 Documentation (Phase 6)

  • PLUGIN_GUIDE.md: 500+ line comprehensive guide
    • Plugin API reference with TypeScript
    • Development workflow (TypeScript → ESM)
    • Working examples (now in separate files)
    • Security considerations
    • Troubleshooting guide
    • FAQ section
  • examples/: 3 complete working plugins with README
  • README.md: Updated with streamlined plugin overview

🔒 Security (Phase 7)

  • ✅ CodeQL scan passed (0 vulnerabilities)
  • ✅ Security considerations documented
  • ✅ Clear warnings about plugin code execution
  • ✅ Recommended practices for plugin review
  • ✅ Disable mechanism documented

Files Changed

New: 24 files

  • 4 infrastructure files (plugin-types, plugin-loader, cli-utils, helpers)
  • 18 command modules (17 commands + plugins introspection)
  • 2 test files (unit + integration)
  • 3 example plugins (stats, bulk-tag, export-csv)
  • 3 documentation files (PLUGIN_GUIDE.md, examples/README.md updates)

Modified: 2 files

  • cli.ts (complete refactor)
  • README.md (added plugin section)

Removed: 1 file

  • cli-old.ts (backup no longer needed)

Verification Results

✅ Build

npm run build  # Successful, 0 errors

✅ Tests

npm test  # 180/180 tests passing

✅ Security Scan

codeql analyze  # 0 vulnerabilities found
Original prompt

This section details on the original issue you should resolve

<issue_title>Add Pluggable CLI Command System (JS plugins), migrate built-in commands, and document</issue_title>
<issue_description>

We want the Worklog CLI (dist/cli.js, implemented in src/cli.ts) to support a pluggable command architecture where new commands can be added by dropping a compiled ESM plugin file (.js / .mjs) into a known directory, with no Worklog rebuild required. On the next CLI invocation, the new command should appear automatically.
This issue also migrates all existing built-in commands out of src/cli.ts into external command modules (shipped with the package), using the same plugin interface, and fully documents the feature.
Goals

  • Pluggable commands discovered at runtime (from disk) and registered into commander.
  • All existing commands ported to external command modules (no giant monolith src/cli.ts).
  • Clear docs: how to write, build, install, and troubleshoot plugins.
    Non-goals
  • Loading TypeScript plugins directly.
  • Hot-reloading commands within a single long-running CLI session (CLI restart is sufficient).
    Proposed design
  • Define a plugin contract:
    • Each plugin is an ESM module exporting default as register(ctx): void (or named register).
    • register receives:
      • program: Command (commander instance)
      • ctx shared utilities (output helpers, config/db accessors, version, paths)
  • Command module shape (example):
    • export default function register({ program, ctx }) { program.command('foo')... }
  • Built-in commands:
    • Move each top-level command (and subcommand groups like comment) into its own module under src/commands/.
    • src/cli.ts becomes a thin bootstrap:
      • create program, global options, shared ctx
      • register built-in commands by importing ./commands/*.js
      • load external plugins from plugin dir and register them
  • External plugin discovery:
    • Default plugin directory: .worklog/plugins/ (within the current repo/workdir).
    • Optional override: WORKLOG_PLUGIN_DIR env var and/or config key (documented).
    • Load order:
      • Built-ins first
      • Then external plugins in deterministic order (e.g., lexicographic by filename)
    • Only load files matching *.mjs / *.js (ignore .d.ts, maps, etc.)
    • Use dynamic import() with pathToFileURL() to load ESM from absolute paths.
  • Name collisions:
    • If a plugin registers a command name that already exists, fail fast with a clear error (or optionally “plugin wins” via a flag; pick one and document).
  • Observability:
    • Add worklog plugins command to list discovered plugins, load status, and any errors (also useful for debugging CI installs).
    • Add --verbose (or reuse an existing pattern) to print plugin load diagnostics.
      Documentation requirements
  • Add a new docs section (README or dedicated doc) covering:
    • Plugin directory, supported file extensions, load timing (next invocation)
    • Plugin API contract and examples
    • How to author a plugin in a separate repo/package:
      • compile to ESM ("type":"module", output .mjs or .js)
      • place built artifact into .worklog/plugins/
    • Security model (“plugins execute arbitrary code; only use trusted plugins”)
    • Troubleshooting: module resolution, ESM/CJS pitfalls, stack traces, worklog plugins
      Migration scope (port all existing commands)
  • Break out everything currently defined in src/cli.ts:
    • init, status, create, list, show, update, delete, export, import, next, sync
    • comment command group and its subcommands
  • Preserve behavior:
    • Options, defaults, JSON output mode, error exit codes, config/db behaviors, sync behavior
    • Help text (--help) remains coherent and complete
      Implementation tasks
  • Create src/commands/ modules:
    • One module per command (or per command group), exporting a register(...) function
  • Create shared CLI context/util module:
    • output helpers, requireInitialized, db factory, config access, dataPath, constants
  • Add plugin loader:
    • Resolve plugin directory, discover files, dynamic import, call register
    • Collect and surface load errors
  • Add plugins command for introspection
  • Update build output wiring so built-in command modules compile to dist/commands/*
  • Update README/docs and add at least one end-to-end plugin example
    Testing / verification
  • Unit tests for:
    • plugin discovery filtering and deterministic ordering
    • plugin load error handling
    • collision handling
  • Integration-ish tests (vitest spawning node) for:
    • dropping a plugin file into a temp plugin dir and verifying --help includes the new command
    • worklog plugins reporting
  • Ensure npm pack / global install style still works (bin points to dist/cli.js)
    Acceptance criteria
  • Dropping a compiled ESM plugin file into .worklog/plugins/ makes its command appear on next worklog --help run, without rebuilding Worklog.
  • All existing commands are implemented as external command modules (no large command definitions left in src/cli....
  • Fixes rgardler-msft/Worklog#154

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 5 commits January 24, 2026 09:05
- Created 14 new command modules in src/commands/:
  * init.ts - Initialize configuration with git hooks
  * status.ts - System status display
  * create.ts - Create work items
  * list.ts - List and filter work items
  * show.ts - Show work item details
  * update.ts - Update work items
  * delete.ts - Delete work items
  * next.ts - Find next work item to work on
  * in-progress.ts - List in-progress items
  * close.ts - Close items with reason tracking
  * recent.ts - Show recently changed items
  * sync.ts - Git sync operations
  * github.ts - GitHub sync (push/import)
  * comment.ts - Comment CRUD operations

- Extracted shared helpers to commands/helpers.ts:
  * Display formatters (tree, title, colors)
  * Human-readable output functions
  * Conflict resolution display
  * Format resolution logic

- Created plugin infrastructure:
  * plugin-types.ts - Type definitions for plugin system
  * plugin-loader.ts - Dynamic command loading
  * cli-utils.ts - Shared CLI utilities

- All commands preserve exact original behavior:
  * JSON output mode support
  * Format options (concise/normal/full/raw)
  * Prefix overrides
  * Error handling
  * Progress indicators
  * Interactive prompts

Ready for cli.ts integration (separate task)

Co-authored-by: rgardler-msft <[email protected]>
- Created plugin system infrastructure (plugin-types, plugin-loader, cli-utils)
- Migrated all 17 built-in commands to separate modules in src/commands/
- Refactored cli.ts to minimal bootstrap with plugin registration
- Fixed database initialization bugs (prefix parameter order)
- Fixed error output format for uninitialized state
- All existing tests passing (151/151)

Co-authored-by: rgardler-msft <[email protected]>
- Added 20 unit tests for plugin discovery and loading
- Added 9 integration tests for external plugin execution
- Created comprehensive PLUGIN_GUIDE.md (300+ lines)
- Updated README.md with plugin system overview and quick example
- All 180 tests passing (151 original + 29 new plugin tests)

Co-authored-by: rgardler-msft <[email protected]>
- Created stats-plugin.mjs example demonstrating database access
- Added examples/README.md with usage instructions
- Verified end-to-end plugin workflow (install, discover, execute)
- All 180 tests passing

Co-authored-by: rgardler-msft <[email protected]>
Copilot AI changed the title [WIP] Add pluggable CLI command system with documentation Add pluggable CLI command system with ESM dynamic loading Jan 24, 2026
Copilot AI requested a review from rgardler-msft January 24, 2026 09:33
@rgardler-msft
Copy link
Owner

@copilot please address all review comments

…amples

- Added type import clarification in Quick Start (optional for JS plugins)
- Clarified Plugin Module Structure section about TypeScript vs JavaScript
- Added note about folder structure recommendations
- Explained plugin command grouping in --help output
- Added note about requireInitialized() pattern
- Added best practice for verbose logging with example
- Moved inline plugin examples to separate files in examples/
- Created bulk-tag-plugin.mjs and export-csv-plugin.mjs examples
- Simplified README.md Plugins section, removed duplicate content
- Streamlined examples/README.md, removed testing/contributing sections
- Removed Contributing and License sections from PLUGIN_GUIDE.md
- Removed src/cli-old.ts backup file
- All 180 tests passing

Co-authored-by: rgardler-msft <[email protected]>
Copy link
Contributor Author

Copilot AI commented Jan 24, 2026

@copilot please address all review comments

All review comments have been addressed in commit ddbcb84. Summary of changes:

✅ Added type import clarification (optional for JS plugins)
✅ Clarified Plugin Module Structure for TypeScript vs JavaScript
✅ Added folder structure recommendations
✅ Explained plugin command grouping in --help
✅ Added requireInitialized() pattern explanation
✅ Added verbose logging best practices section
✅ Moved inline examples to separate files (bulk-tag-plugin.mjs, export-csv-plugin.mjs)
✅ Simplified README.md Plugins section
✅ Streamlined examples/README.md
✅ Removed Contributing/License sections from PLUGIN_GUIDE.md
✅ Removed src/cli-old.ts backup file

All 180 tests passing. Build successful.

@rgardler-msft rgardler-msft marked this pull request as ready for review January 24, 2026 10:23
@rgardler-msft rgardler-msft merged commit a062496 into main Jan 24, 2026
1 check passed
@rgardler-msft rgardler-msft deleted the copilot/add-pluggable-cli-command-system branch February 2, 2026 08:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants