Extension System
Extensions are executable scripts that run at specific hook points during version management operations. They receive JSON input on stdin and return JSON output on stdout.
When to Use Extensions
Extensions are for advanced customization when built-in plugins don't meet your needs — such as organization-specific automation, external tool integration, or prototyping new features. Most users only need Plugins. See Plugins vs Extensions for a detailed comparison.
Hook Points
| Hook | When | Use Cases |
|---|---|---|
pre-bump | Before version bump | Validate preconditions, run linters/tests |
post-bump | After successful bump | Update files, create tags, send notifications |
pre-release | Before pre-release | Validate pre-release labels, check readiness |
validate | Custom validation | Enforce policies, validate version format |
Input Context
All hooks receive JSON on stdin:
{
"hook": "post-bump",
"version": "1.2.3",
"previous_version": "1.2.2",
"bump_type": "patch",
"prerelease": "alpha",
"metadata": "build123",
"project_root": "/path/to/project",
"module_dir": "./services/api",
"module_name": "api"
}2
3
4
5
6
7
8
9
10
11
INFO
module_dir and module_name are included in monorepo contexts.
Creating an Extension
Directory Structure
my-extension/
extension.yaml # Manifest (required)
hook.sh # Entry point script
README.md # Documentation (recommended)2
3
4
Extension Manifest
# extension.yaml
name: my-extension
version: 1.0.0
description: Brief description
author: Your Name
repository: https://github.com/username/my-extension
entry: hook.sh
hooks:
- pre-bump
- post-bump2
3
4
5
6
7
8
9
10
Hook Script (Shell)
#!/bin/sh
# Read JSON input
read -r input
# Parse fields
version=$(echo "$input" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
bump_type=$(echo "$input" | grep -o '"bump_type":"[^"]*"' | cut -d'"' -f4)
# Custom logic here
echo "Processing version $version" >&2
# Return success
echo '{"success": true, "message": "Extension executed"}'
exit 02
3
4
5
6
7
8
9
10
11
12
13
14
15
See contrib/extensions/ in the sley repository for Python and Node.js examples.
JSON Output Format
{
"success": true,
"message": "Optional status message",
"data": { "key": "Optional data to return" }
}2
3
4
5
On failure, return success: false:
{
"success": false,
"message": "Extension failed: reason"
}2
3
4
Installing Extensions
# From local path
sley extension install /path/to/my-extension2
This copies the extension to ~/.sley-extensions/my-extension/ and adds it to .sley.yaml.
Configuration
# .sley.yaml
extensions:
- name: docker-tag-sync
path: /Users/username/.sley-extensions/docker-tag-sync
enabled: true2
3
4
5
Managing Extensions
sley extension list # List installed extensions
sley extension remove NAME # Remove an extension2
Disable by setting enabled: false in .sley.yaml.
Running Extensions
Extensions run automatically during bump commands:
sley bump patch
# 1. Pre-bump extensions run (can modify .version)
# 2. Pre-bump plugin validations run
# 3. Version bumped
# 4. Post-bump plugin actions run
# 5. Post-bump extensions run2
3
4
5
6
Extensions Run Before Plugin Validations
Pre-bump extensions execute before plugin validations. This allows extensions to set up state (e.g., fetch a version from an external source and update .version) before plugins like dependency-check validate consistency. After pre-bump extensions complete, sley re-reads the .version file to pick up any changes.
See Execution Order for the complete flow diagram.
Skip extensions with --skip-hooks:
sley bump patch --skip-hooksSecurity Considerations
- Extensions run with your user permissions - only install from trusted sources
- 30-second execution timeout (prevents hanging)
- 1MB output limit (prevents memory exhaustion)
- Each extension runs as separate process (isolation)
Best Practices
- Keep extensions focused on one task
- Validate input before processing
- Handle errors gracefully with meaningful messages
- Test with different inputs
- Use stderr for debug output
Available Extensions
sley ships with reference implementations you can use or adapt:
| Extension | Language | Hook | Description |
|---|---|---|---|
| Commit Validator | Python | pre-bump | Validates conventional commit format |
| Docker Tag Sync | Bash | post-bump | Tags and pushes Docker images |
Troubleshooting
| Issue | Solution |
|---|---|
| Extension not found | Check sley extension list and .sley.yaml |
| Not executing | Verify enabled: true, script executable, proper shebang |
| Permission denied | Run chmod +x hook.sh |
| Timeout errors | Optimize script or split into smaller tasks |
| Invalid JSON output | Test manually with echo '{"hook":"post-bump"}' | ./hook.sh |
Error Propagation
If an extension fails (success: false), the bump operation is aborted and subsequent extensions are not executed.
See Also
- Plugin System - Built-in plugins vs extensions comparison
- Commit Validator Extension - Validate conventional commits
- Docker Tag Sync Extension - Tag Docker images with versions
- CI/CD Integration - Use extensions in automation pipelines
- .sley.yaml Reference - Extension configuration
- Troubleshooting - Common extension issues