feat: GitHub-based Plugin Marketplace System#98
Conversation
- Bump version to 1.0.0 - Remove plugins from core distribution (installed separately via pipx inject) - Add jinja2 dependency for workflow templates - Update project metadata (homepage, keywords, classifiers) - Add release documentation (RELEASE.md) - Add user installation guide (INSTALLATION.md) Validation: - ✅ All 10 automated tests passed - ✅ pipx installation verified - ✅ No plugins bundled - ✅ Package size: 115KB Co-Authored-By: Claude <noreply@anthropic.com>
- Add PluginDownloader for GitHub registry and plugin installation - Add PluginValidator for plugin metadata and compatibility validation - Add marketplace commands (discover, install, uninstall, update) - Modify PluginRegistry to support local ~/.titan/plugins/ discovery - Add plugin.json metadata for all existing plugins (git, github, jira) - Add registry.json for plugin marketplace - Configure for monorepo workflow (masmovil/titan-cli) Core modules: - titan_cli/core/plugins/plugin_downloader.py (NEW) - titan_cli/core/plugins/plugin_validator.py (NEW) - titan_cli/core/plugins/exceptions.py (NEW) - titan_cli/core/plugins/plugin_registry.py (MODIFIED) Commands: - titan_cli/commands/plugins_marketplace.py (NEW) - titan_cli/commands/plugins.py (MODIFIED) Plugin metadata: - plugins/*/plugin.json (NEW - git, github, jira) - registry.json (NEW) Tests: - tests/core/plugins/test_plugin_downloader.py (12 tests) - tests/core/plugins/test_plugin_validator.py (33 tests) - Total: 45 tests, all passing Features: - GitHub-only distribution (no PyPI for plugins) - Quality control via PR reviews - Dual discovery (entry_points + local directory) - Version compatibility checking - Dependency resolution - Plugin validation - Monorepo-friendly design After merge to master, marketplace will be live at: https://raw.githubusercontent.com/masmovil/titan-cli/master/registry.json Co-Authored-By: Claude <noreply@anthropic.com>
- Add ConfigSchemaRenderer for automatic wizard generation - Support all JSON Schema types (string, boolean, integer, array, object) - Implement validation (email, uri, pattern, length, range) - Secret management via OS keyring - Add TitanConfig.set_plugin_config() method - Integrate wizard into installation flow - Add 26 comprehensive tests (71 total passing) - Update JIRA and GitHub plugins with configSchema Automatic configuration wizard activates when plugin has configSchema in plugin.json. Prompts user for all fields with real-time validation. Secrets stored encrypted in OS keyring, config saved to ~/.titan/config.toml
- Add marketplace option to Plugin Management menu - Temporarily point to feature branch for testing - Interactive marketplace accessible from main Titan menu
- Plugins now install to .titan/plugins/ in the current project instead of ~/.titan/plugins/ - PluginDownloader uses project path from TitanConfig - PluginRegistry configured with project-specific plugin directory - Updated all marketplace commands to use project-level paths - Each project can now have its own set of installed plugins - Tests updated and all 71 tests passing Co-Authored-By: Claude <noreply@anthropic.com>
MenuItem model requires 'action' field, not 'value'. Fixed marketplace to use correct field name for plugin selection. Co-Authored-By: Claude <noreply@anthropic.com>
- Use public properties (active_project_path, project_root) instead of private (_active_project_path, _project_root) - Add JSONDecodeError and OSError handling in plugin_registry.py for safer plugin.json loading - All 71 tests still passing Addresses code review findings for production readiness. Co-Authored-By: Claude <noreply@anthropic.com>
Centralize all user-facing strings in plugins_marketplace.py to messages.py for better maintainability and i18n readiness. Changes: - Add 73 message constants to messages.py in Plugins class - Update install_plugin_from_marketplace() to use msg.Plugins.* - Update uninstall_plugin_from_marketplace() to use msg.Plugins.* - Update discover_plugins() to use msg.Plugins.* - Update update_plugin() to use msg.Plugins.* Message categories added: - Marketplace (titles, prompts, status) - Installation (progress messages) - Plugin info (badges, verification status) - Dependencies (validation messages) - Configuration (wizard messages) - Uninstallation (removal messages) - Updates (update progress) - Reinstall (confirmation prompts) - Errors (standardized error messages) Benefits: - Single source of truth for all UI strings - Consistent messaging across marketplace commands - Prepared for future internationalization support - Follows project standards (AGENTS.md) Co-Authored-By: Claude <noreply@anthropic.com>
The configuration wizard already runs automatically during plugin installation in install_plugin_from_marketplace(). The additional prompt in discover_plugins() was redundant and has been removed. Changes: - Remove duplicate configuration prompt after installation - Remove unused marketplace configuration messages - Add clarifying comment about automatic wizard execution Benefits: - Cleaner user flow (no redundant prompts) - Less code to maintain - Configuration still happens automatically during installation Co-Authored-By: Claude <noreply@anthropic.com>
The downloader was looking for 'titan-plugins-{branch}' but the actual
repository is 'titan-cli'. This caused all plugin downloads to fail.
Changes:
- Fix extracted repo directory name from titan-plugins to titan-cli
- Update comment to reflect correct structure
Fixes plugin installation from marketplace.
Co-Authored-By: Claude <noreply@anthropic.com>
GitHub replaces forward slashes with hyphens in ZIP directory names. Branch 'feat/plugin-marketplace-system' becomes 'titan-cli-feat-plugin-marketplace-system' in the ZIP. Changes: - Replace '/' with '-' in branch name before constructing ZIP path - Add comment explaining GitHub's ZIP naming behavior This fixes plugin installation when using branches with slashes. Co-Authored-By: Claude <noreply@anthropic.com>
- Add ask_password() method to support secret field configuration - Uses ask_text() with password=True for hidden input - Fixes error during GitHub plugin configuration wizard - Add .titan/plugins/ to .gitignore (downloaded plugins) Co-Authored-By: Claude <noreply@anthropic.com>
- Change ask_text calls from message= to prompt= - Change ask_select to ask_choice with correct signature - Change ask_confirm from message= to prompt= - Update tests to match new method signatures - Fixes configuration wizard errors for all plugins Relates to JIRA plugin installation error: "PromptsRenderer.ask_text() got an unexpected keyword argument 'message'" Co-Authored-By: Claude <noreply@anthropic.com>
- Change ask_confirm from prompt= to question= - Update tests to match correct signature - Update CLAUDE.md documentation with correct parameter Fixes JIRA plugin installation error: "PromptsRenderer.ask_confirm() got an unexpected keyword argument 'prompt'" Co-Authored-By: Claude <noreply@anthropic.com>
Fixed bug where plugins appeared multiple times when listing installed plugins. Root cause: _discover_from_entry_points() used extend() without checking for duplicates, causing the same plugin to be added multiple times when discover() was called repeatedly. Solution: Changed to iterate and check for duplicates before appending, matching the pattern used in _discover_from_local_plugins(). Before: 12 duplicate entries for 3 plugins After: Only 3 unique plugins shown Co-Authored-By: Claude <noreply@anthropic.com>
Updated configuration and documentation for production release: - Changed REGISTRY_BRANCH from feat/plugin-marketplace-system to master - Updated README with comprehensive plugin marketplace documentation - Added installation, management, and available plugins sections Ready for merge to master branch. Co-Authored-By: Claude <noreply@anthropic.com>
…eat/plugin-marketplace-system
Addresses critical code review finding: move all user-facing strings from plugin core modules to centralized messages.py for consistency and future i18n. Changes: - Add PluginDownloader, PluginValidator, ConfigSchema message classes to messages.py - Replace 50+ hardcoded strings in plugin_downloader.py with msg.* references - Replace 15+ hardcoded strings in plugin_validator.py with msg.* references - Replace 15+ hardcoded strings in config_schema_renderer.py with msg.* references - Fix PromptsRenderer parameter naming in plugins_marketplace.py (question= explicit) - Update test expectations to match new centralized messages - Fix plugin registry tests to use tmp_path to avoid local plugin interference This ensures all user-facing strings follow Titan CLI conventions and are centralized for easy maintenance and future internationalization. Co-Authored-By: Claude <noreply@anthropic.com>
Remove unused imports and variables identified by ruff linter. Changes: - plugins_marketplace.py: Remove unused TableRenderer import, unused category variable - config_schema_renderer.py: Remove unused Path and TitanConfig imports - plugin_downloader.py: Remove unused target_version variable - plugin_validator.py: Remove unused importlib.util and Optional imports All 220 tests still passing. No functional changes. Co-Authored-By: Claude <noreply@anthropic.com>
Wiz Scan Summary
To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension. |
There was a problem hiding this comment.
PII
More Details
| Attribute | Value |
|---|---|
| Data Classifier | PII/Name |
| Data Classifier ID | BUILTIN-125 |
Sampled Examples
| Key | Value |
|---|---|
| author | T***n |
| author | T***n |
| author | T***n |
| git.author | T***n |
| github.author | T***n |
Rule ID: BUILTIN-125
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
| return self._registry_cache | ||
|
|
||
| try: | ||
| with urlopen(self.registry_url, timeout=10) as response: |
There was a problem hiding this comment.
Insecure URL handling in Python urllib module (CWE-939)
More Details
The Python urllib module allows applications to open URLs and retrieve data from the web. However, if the URL is not a literal value and can be controlled by an attacker, it can lead to security vulnerabilities. The urllib module supports the "file://" scheme, which means an attacker could potentially read arbitrary files on the system if they can control the URL value.
This vulnerability poses a significant risk as it can lead to unauthorized access to sensitive information, data leaks, and potentially even remote code execution, depending on the application's context and privileges. It is crucial to avoid passing user-controlled input directly to the urllib module's functions without proper validation and sanitization.
| Attribute | Value |
|---|---|
| Impact | |
| Likelihood |
Remediation
To mitigate this vulnerability, it is recommended to either:
- Hardcode the URLs being used in the urllib module, ensuring that they are not derived from user input or other untrusted sources.
- Use a more secure and modern library like the
requestsmodule, which does not support the "file://" scheme by default.
Example using the requests module to issue an HTTPS request:
import requests
# Issue a GET request to https://example.com with a timeout of 10 seconds
response = requests.get('https://example.com', timeout=10)
# Work with the response object
# ...Rule ID: WS-I011-PYTHON-00053
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
|
|
||
| # Download ZIP | ||
| zip_path = temp_dir / "repo.zip" | ||
| with urlopen(zip_url, timeout=30) as response: |
There was a problem hiding this comment.
Insecure URL handling in Python urllib module (CWE-939)
More Details
The Python urllib module allows applications to open URLs and retrieve data from the web. However, if the URL is not a literal value and can be controlled by an attacker, it can lead to security vulnerabilities. The urllib module supports the "file://" scheme, which means an attacker could potentially read arbitrary files on the system if they can control the URL value.
This vulnerability poses a significant risk as it can lead to unauthorized access to sensitive information, data leaks, and potentially even remote code execution, depending on the application's context and privileges. It is crucial to avoid passing user-controlled input directly to the urllib module's functions without proper validation and sanitization.
| Attribute | Value |
|---|---|
| Impact | |
| Likelihood |
Remediation
To mitigate this vulnerability, it is recommended to either:
- Hardcode the URLs being used in the urllib module, ensuring that they are not derived from user input or other untrusted sources.
- Use a more secure and modern library like the
requestsmodule, which does not support the "file://" scheme by default.
Example using the requests module to issue an HTTPS request:
import requests
# Issue a GET request to https://example.com with a timeout of 10 seconds
response = requests.get('https://example.com', timeout=10)
# Work with the response object
# ...Rule ID: WS-I011-PYTHON-00053
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
|
|
||
| try: | ||
| # Import module | ||
| module = importlib.import_module(module_path) |
There was a problem hiding this comment.
Arbitrary Code Execution via Insecure Import (CWE-706)
More Details
The importlib.import_module() function in Python allows dynamically importing modules at runtime. If the module name is derived from untrusted user input, an attacker could potentially execute arbitrary code on the system by causing a malicious module to be loaded.
| Attribute | Value |
|---|---|
| Impact | |
| Likelihood |
Remediation
The importlib.import_module() function in Python allows for dynamic code loading, which can be a security risk if the module name is derived from untrusted user input. An attacker could potentially exploit this vulnerability to execute arbitrary code on the system, leading to various security issues such as code injection, data tampering, or unauthorized access.
To fix this issue, avoid using dynamic values in importlib.import_module() or implement a strict whitelist of allowed module names. If dynamic module loading is necessary, validate and sanitize the input to ensure that only trusted and approved modules are loaded.
Code examples:
// VULNERABLE CODE - Directly using user input for module loading
import importlib
user_input = input("Enter module name: ")
module = importlib.import_module(user_input)
// SECURE CODE - Using a whitelist of allowed modules
import importlib
ALLOWED_MODULES = ["module1", "module2", "module3"]
user_input = input("Enter module name: ")
if user_input in ALLOWED_MODULES:
module = importlib.import_module(user_input)
else:
print("Module not allowed")
Additional recommendations:
- Follow the principle of least privilege and only grant the minimum required permissions for module loading.
- Implement input validation and sanitization techniques to prevent code injection attacks.
- Consider using a secure coding framework or library that provides built-in protection against code injection vulnerabilities.
- Adhere to the OWASP Top 10 security guidelines, specifically "A1:2021 - Broken Access Control" and "A3:2021 - Injection."
- Regularly update and maintain the whitelist of allowed modules to ensure it remains secure and up-to-date.
Rule ID: WS-I013-PYTHON-00176
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
…rer tests Co-Authored-By: Claude <noreply@anthropic.com>
Implements the core backend for the plugin marketplace system: **MarketplaceClient** (marketplace_client.py): - HTTP client for fetching plugin registry from GitHub - Caching mechanism with configurable TTL (5 minutes default) - Registry validation and error handling - Support for custom registry URLs via config **MarketplaceModels** (marketplace_models.py): - Pydantic models for type-safe marketplace data: - PluginMetadata: Plugin information (name, version, description, etc.) - PluginRegistry: Complete registry structure - Comprehensive validation for plugin metadata - Support for plugin dependencies, tags, and compatibility **Tests** (test_marketplace.py): - Unit tests for marketplace client - Tests for caching, error handling, and validation - Mock HTTP responses for deterministic testing This provides the foundation for plugin discovery and installation from the centralized marketplace registry. Co-Authored-By: Claude <noreply@anthropic.com>
Adds technical documentation for the Titan CLI plugin architecture: **PLUGIN_ARCHITECTURE.md**: - Overview of the plugin system design - Core components documentation (plugin_base, registry, discovery, loader) - Plugin lifecycle and initialization flow - Dependency resolution mechanism - Workflow integration patterns - Best practices and security considerations - References to architecture diagrams **PLUGIN_CREATION_GUIDE.md**: - Step-by-step guide for creating plugins - Two paths: local plugins vs marketplace plugins - Project structure templates - Entry point configuration with Poetry - Client implementation examples - Workflow step patterns - Testing guidelines - Publishing process to marketplace **Architecture Diagrams** (Mermaid): - plugin_class_architecture.mmd: Class hierarchy and relationships - plugin_discovery_initialization.mmd: Discovery and loading flow - plugin_dependency_resolution.mmd: Dependency resolution algorithm - plugin_workflow_integration.mmd: Workflow execution patterns This documentation serves as the primary reference for developers creating plugins or contributing to the plugin system. Co-Authored-By: Claude <noreply@anthropic.com>
Adds GitHub Actions workflows and utility scripts for plugin management: **GitHub Workflows**: - **publish-plugins.yml**: Automated plugin publishing workflow - Triggered on new plugin releases (tags matching plugin-*/v*) - Builds and publishes to PyPI - Updates marketplace registry automatically - Supports multiple plugins in monorepo structure - **test-plugins.yml**: Plugin testing workflow - Runs on PRs affecting plugin code - Executes pytest for all modified plugins - Ensures plugin quality before merge - Matrix strategy for testing multiple plugins **Scripts**: - **update_registry.py**: Marketplace registry management - Fetches plugin metadata from PyPI - Validates plugin compatibility - Updates registry.json with new versions - Can be run manually or via CI - **document_agent_standalone.py**: Documentation generator - Autonomous agent for generating plugin documentation - Uses Claude API to analyze code structure - Generates architecture diagrams (Mermaid) - Creates comprehensive markdown documentation - **requirements_agent.txt**: Dependencies for documentation agent - anthropic SDK for AI-powered documentation - Required for running document_agent_standalone.py - **README_DOCUMENT_AGENT.md**: Documentation agent usage guide These tools enable automated plugin lifecycle management from development through publishing and documentation. Co-Authored-By: Claude <noreply@anthropic.com>
| python-version: '3.11' | ||
|
|
||
| - name: Install Poetry | ||
| uses: snok/install-poetry@v1 |
There was a problem hiding this comment.
Workflow should not use version pinning for third-party actions
on resource jobs.test.steps[2].uses
More Details
This rule checks that GitHub workflow does not use version pinning on third-party actions. This rule fails when the workflow contains steps that use third-party actions referenced by version tags (like @v1, @v2.3, @v4) instead of specific commits. Using version-tagged actions creates a supply chain security risk, as the version tag could be modified by the action's maintainer to point to malicious code after the calling workflow is created. Even when using specific version tags, the tag could be moved to point to malicious code. To prevent this risk, always pin third-party actions to specific commit SHAs to ensure the exact code being executed is locked and immutable.
Expected
Workflow job 'test' step[2] should pin third-party action to a commit SHA rather than a version tag
Found
Workflow job 'test' step[2] uses version-tagged third-party action: 'snok/install-poetry@v1'
Security Frameworks: wf-id-1, wf-id-175
Rule ID: 7d431072-4eef-466b-b469-4b7681d8f9a1
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
| run: poetry run pytest -v | ||
|
|
||
| - name: Upload coverage | ||
| uses: codecov/codecov-action@v3 |
There was a problem hiding this comment.
Workflow should not use version pinning for third-party actions
on resource jobs.test.steps[7].uses
More Details
This rule checks that GitHub workflow does not use version pinning on third-party actions. This rule fails when the workflow contains steps that use third-party actions referenced by version tags (like @v1, @v2.3, @v4) instead of specific commits. Using version-tagged actions creates a supply chain security risk, as the version tag could be modified by the action's maintainer to point to malicious code after the calling workflow is created. Even when using specific version tags, the tag could be moved to point to malicious code. To prevent this risk, always pin third-party actions to specific commit SHAs to ensure the exact code being executed is locked and immutable.
Expected
Workflow job 'test' step[7] should pin third-party action to a commit SHA rather than a version tag
Found
Workflow job 'test' step[7] uses version-tagged third-party action: 'codecov/codecov-action@v3'
Security Frameworks: wf-id-1, wf-id-175
Rule ID: 7d431072-4eef-466b-b469-4b7681d8f9a1
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
| @@ -0,0 +1,98 @@ | |||
| name: Test Plugins | |||
There was a problem hiding this comment.
Workflow should have permissions limitations
on resource name
More Details
This rule checks that GitHub workflow has an empty permissions block to enforce least privilege. This rule fails when the workflow doesn't have a permissions block or has a non-empty permissions block with `write-all` scope, which can grant excessive permissions to workflow actions. Excessive permissions in GitHub workflows increase the risk surface in case of a compromise, potentially allowing attackers to access sensitive resources or perform unauthorized actions. To prevent this risk, always implement least privilege by explicitly defining an empty permissions block for all workflows.
Expected
GitHub workflow should have empty permissions block
Found
GitHub workflow doesn't have a permissions block defined
Security Frameworks: wf-id-1, wf-id-175
Rule ID: 65570021-8e03-4ccf-bf86-6bcb9fcc7a97
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
| @@ -0,0 +1,130 @@ | |||
| name: Publish Plugins to PyPI | |||
There was a problem hiding this comment.
Workflow should have permissions limitations
on resource name
More Details
This rule checks that GitHub workflow has an empty permissions block to enforce least privilege. This rule fails when the workflow doesn't have a permissions block or has a non-empty permissions block with `write-all` scope, which can grant excessive permissions to workflow actions. Excessive permissions in GitHub workflows increase the risk surface in case of a compromise, potentially allowing attackers to access sensitive resources or perform unauthorized actions. To prevent this risk, always implement least privilege by explicitly defining an empty permissions block for all workflows.
Expected
GitHub workflow should have empty permissions block
Found
GitHub workflow doesn't have a permissions block defined
Security Frameworks: wf-id-1, wf-id-175
Rule ID: 65570021-8e03-4ccf-bf86-6bcb9fcc7a97
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
| python-version: '3.11' | ||
|
|
||
| - name: Install Poetry | ||
| uses: snok/install-poetry@v1 |
There was a problem hiding this comment.
Workflow should not use version pinning for third-party actions
on resource jobs.publish.steps[2].uses
More Details
This rule checks that GitHub workflow does not use version pinning on third-party actions. This rule fails when the workflow contains steps that use third-party actions referenced by version tags (like @v1, @v2.3, @v4) instead of specific commits. Using version-tagged actions creates a supply chain security risk, as the version tag could be modified by the action's maintainer to point to malicious code after the calling workflow is created. Even when using specific version tags, the tag could be moved to point to malicious code. To prevent this risk, always pin third-party actions to specific commit SHAs to ensure the exact code being executed is locked and immutable.
Expected
Workflow job 'publish' step[2] should pin third-party action to a commit SHA rather than a version tag
Found
Workflow job 'publish' step[2] uses version-tagged third-party action: 'snok/install-poetry@v1'
Security Frameworks: wf-id-1, wf-id-175
Rule ID: 7d431072-4eef-466b-b469-4b7681d8f9a1
To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason
If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate
Summary
This PR implements a complete GitHub-based plugin marketplace system for Titan CLI, enabling users to discover, install, and manage plugins directly from the official repository.
Key Features
registry.jsonwith plugin metadata (official & community).titan/plugins/(project-specific)New Components
Core Classes:
PluginDownloader: Downloads plugins from GitHub registryPluginValidator: Validates plugin structure and metadataConfigSchemaRenderer: Renders interactive config wizard from JSON SchemaCommands:
titan plugins discover- Interactive marketplace browsertitan plugins install <name>- Install plugin by nametitan plugins uninstall <name>- Remove plugintitan plugins update <name>- Update to latest versiontitan plugins update --all- Update all pluginsRegistry Format:
{ "plugins": { "git": { "display_name": "Git Operations", "description": "Git client wrapper", "category": "official", "verified": true, "latest_version": "1.0.0", "source": "plugins/titan-plugin-git", "dependencies": [] } } }Architecture Changes
PluginRegistry Enhancements:
.titan/plugins/)Message Centralization:
PluginDownloader,PluginValidator,ConfigSchema)messages.pyfor i18n readinessConfiguration Updates:
TitanConfig.set_plugin_config()for saving plugin configs.titan/config.tomlPlugin Metadata
All plugins now include
plugin.jsonwith:name,version,descriptioncategory(official/community)dependencies(plugin dependencies)min_titan_version(compatibility check)entry_point(Python import path)configSchema(optional JSON Schema for config)Testing
Security
TitanPlugin)Documentation
.gitignoreentry for.titan/plugins/registry.jsonwith 3 official pluginsType of Change
Changes Made
Core Plugin System
PluginDownloader (plugin_downloader.py):
registry.jsonfrom GitHub.titan/plugins/(project-level)PluginValidator (plugin_validator.py):
plugin.jsonstructureConfigSchemaRenderer (config_schema_renderer.py):
x-secret: true)Commands
Plugin Marketplace Commands (plugins_marketplace.py):
install_plugin_from_marketplace()- Full install flow with wizarduninstall_plugin_from_marketplace()- Clean uninstalldiscover_plugins()- Interactive marketplace browserupdate_plugin()- Update single or all pluginsEnhanced Plugin Commands (plugins.py):
listto show installed + downloaded pluginsConfiguration
TitanConfig Updates (config.py):
set_plugin_config()method for saving plugin configsPluginRegistry Enhancements (plugin_registry.py):
discover_local_plugins()for.titan/plugins/Registry & Templates
Plugin Registry (registry.json):
Plugin Metadata Files:
Messages & Testing
Message Centralization (messages.py):
msg.*referencesComprehensive Tests:
How Has This Been Tested?
Unit Tests
Manual Testing
titan plugins discover- Interactive marketplace workstitan plugins install git- Installs with config wizardtitan plugins list- Shows installed pluginstitan plugins update --all- Updates all pluginstitan plugins uninstall git- Clean removal.titan/config.tomlEdge Cases Tested
Checklist
Additional Notes
Future Enhancements
Breaking Changes
None - all changes are additive and backward-compatible.
Migration Guide
For existing users:
.titan/config.tomlis preservedCo-Authored-By: Claude noreply@anthropic.com