Skip to content

Commit 3f6436d

Browse files
committed
feat(examples): add hello-world and code-stats example plugins
Add two example plugins demonstrating plugin capabilities: 1. hello-world (basic): - Command: /hello [name] - greets the user - Hook: tool_execute_before - logs tool executions - Config: greeting_prefix setting 2. code-stats (advanced): - Commands: /stats, /stats-reset, /stats-export - Hooks: file_operation_after, session_end, widget_register - UI widget: Status bar showing code statistics - Event system: Custom events for integrations Both plugins include complete manifest, Cargo.toml, and documentation.
1 parent d90106a commit 3f6436d

8 files changed

Lines changed: 1430 additions & 0 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "code-stats-plugin"
3+
version = "1.0.0"
4+
edition = "2021"
5+
description = "Tracks and displays code statistics including lines added, removed, and files modified"
6+
authors = ["Cortex Team <team@cortex.dev>"]
7+
license = "MIT"
8+
9+
# Build for WASM target: cargo build --target wasm32-wasi --release
10+
11+
[lib]
12+
crate-type = ["cdylib"]
13+
14+
[dependencies]
15+
wee_alloc = "0.4"
16+
17+
[profile.release]
18+
opt-level = "s"
19+
lto = true
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# Code Stats Plugin
2+
3+
An advanced example plugin demonstrating comprehensive Cortex plugin capabilities.
4+
5+
## Features
6+
7+
### Commands
8+
9+
- **`/stats`** (aliases: `/statistics`, `/metrics`) - Display current session code statistics
10+
- **`/stats-reset`** (alias: `/reset-stats`) - Reset all statistics counters to zero
11+
- **`/stats-export`** (alias: `/export-stats`) - Export statistics to JSON format
12+
13+
### Hooks
14+
15+
- **`file_operation_after`** - Tracks statistics after each file operation
16+
- **`session_end`** - Saves statistics when the session ends
17+
- **`widget_register`** - Registers the status bar widget
18+
19+
### UI Widget
20+
21+
- **Status Bar Widget** - Displays compact statistics (`+123 -45 (67)`) in the status bar
22+
23+
### Configuration
24+
25+
- **`auto_save`** (boolean, default: true) - Automatically save stats on session end
26+
- **`display_format`** (string, default: "compact") - Format for displaying stats (compact, detailed)
27+
- **`track_by_language`** (boolean, default: true) - Track statistics per programming language
28+
29+
## Project Structure
30+
31+
```
32+
code-stats/
33+
├── plugin.toml # Plugin manifest (metadata, commands, hooks, config)
34+
├── Cargo.toml # Rust build configuration
35+
├── src/
36+
│ └── lib.rs # Plugin implementation
37+
└── README.md # This file
38+
```
39+
40+
## Building
41+
42+
### Prerequisites
43+
44+
1. Install Rust: https://rustup.rs/
45+
2. Add the WASM target:
46+
```bash
47+
rustup target add wasm32-wasi
48+
```
49+
50+
### Build the Plugin
51+
52+
```bash
53+
cd examples/plugins/code-stats
54+
cargo build --target wasm32-wasi --release
55+
```
56+
57+
The compiled WASM module will be at:
58+
```
59+
target/wasm32-wasi/release/code_stats_plugin.wasm
60+
```
61+
62+
## Installing
63+
64+
Copy the compiled WASM and manifest to your Cortex plugins directory:
65+
66+
```bash
67+
# Create plugin directory
68+
mkdir -p ~/.cortex/plugins/code-stats
69+
70+
# Copy manifest
71+
cp plugin.toml ~/.cortex/plugins/code-stats/
72+
73+
# Copy compiled WASM
74+
cp target/wasm32-wasi/release/code_stats_plugin.wasm ~/.cortex/plugins/code-stats/plugin.wasm
75+
```
76+
77+
## Configuration
78+
79+
Add to your Cortex configuration to customize the plugin:
80+
81+
```toml
82+
[plugins.code-stats]
83+
enabled = true
84+
auto_save = true
85+
display_format = "detailed" # or "compact"
86+
track_by_language = true
87+
```
88+
89+
## Usage
90+
91+
### View Statistics
92+
93+
```
94+
/stats
95+
```
96+
97+
Output: `Lines: +123 -45 | Files: 10 modified, 3 created, 1 deleted | Total ops: 14`
98+
99+
### Reset Statistics
100+
101+
```
102+
/stats-reset
103+
```
104+
105+
This clears all counters to zero for a fresh start.
106+
107+
### Export Statistics
108+
109+
```
110+
/stats-export
111+
```
112+
113+
Exports statistics as JSON to the event stream:
114+
115+
```json
116+
{
117+
"lines_added": 123,
118+
"lines_removed": 45,
119+
"files_modified": 10,
120+
"files_created": 3,
121+
"files_deleted": 1,
122+
"total_operations": 14
123+
}
124+
```
125+
126+
## Plugin Architecture
127+
128+
### Statistics Tracking
129+
130+
The plugin uses atomic counters to track:
131+
- **lines_added** - Total lines of code added
132+
- **lines_removed** - Total lines of code removed
133+
- **files_modified** - Number of files edited
134+
- **files_created** - Number of new files created
135+
- **files_deleted** - Number of files removed
136+
- **total_operations** - Total file operations
137+
138+
### Event System
139+
140+
The plugin emits events for external integrations:
141+
142+
| Event Name | Trigger | Data |
143+
|------------|---------|------|
144+
| `code_stats.displayed` | `/stats` command | Current stats JSON |
145+
| `code_stats.before_reset` | `/stats-reset` command | Stats before reset |
146+
| `code_stats.exported` | `/stats-export` command | Full stats JSON |
147+
| `code_stats.session_end` | Session ending | Final stats JSON |
148+
| `code_stats.session_final` | Plugin shutdown | Final stats JSON |
149+
150+
### Widget Rendering
151+
152+
The status bar widget displays a compact summary:
153+
```
154+
+{lines_added} -{lines_removed} ({total_ops})
155+
```
156+
157+
Example: `+123 -45 (14)`
158+
159+
## Development
160+
161+
### Adding New Metrics
162+
163+
1. Add an atomic counter in `src/lib.rs`:
164+
```rust
165+
static MY_METRIC: AtomicU64 = AtomicU64::new(0);
166+
```
167+
168+
2. Update the `get_stats_summary()` function to include it.
169+
170+
3. Update the `get_stats_json()` function to include it.
171+
172+
4. Add a recording function:
173+
```rust
174+
fn record_my_metric(value: u64) {
175+
MY_METRIC.fetch_add(value, Ordering::Relaxed);
176+
}
177+
```
178+
179+
### Adding New Commands
180+
181+
1. Add the command definition in `plugin.toml`:
182+
```toml
183+
[[commands]]
184+
name = "my-command"
185+
description = "My new command"
186+
usage = "/my-command [args]"
187+
```
188+
189+
2. Implement the handler in `src/lib.rs`:
190+
```rust
191+
#[no_mangle]
192+
pub extern "C" fn cmd_my_command() -> i32 {
193+
log_info("My command executed!");
194+
0
195+
}
196+
```
197+
198+
### Adding New Hooks
199+
200+
1. Add the hook definition in `plugin.toml`:
201+
```toml
202+
[[hooks]]
203+
hook_type = "tool_execute_after"
204+
priority = 100
205+
function = "hook_tool_execute_after"
206+
```
207+
208+
2. Implement the handler in `src/lib.rs`:
209+
```rust
210+
#[no_mangle]
211+
pub extern "C" fn hook_tool_execute_after() -> i32 {
212+
log_debug("Tool execution completed");
213+
0
214+
}
215+
```
216+
217+
## API Reference
218+
219+
### Exported Functions
220+
221+
| Function | Purpose | Returns |
222+
|----------|---------|---------|
223+
| `init()` | Plugin initialization | 0 on success |
224+
| `shutdown()` | Plugin cleanup | 0 on success |
225+
| `cmd_stats()` | Display stats | 0 on success |
226+
| `cmd_stats_reset()` | Reset counters | 0 on success |
227+
| `cmd_stats_export()` | Export JSON | 0 on success |
228+
| `hook_file_operation_after()` | Track file ops | 0 to continue |
229+
| `hook_session_end()` | Save on exit | 0 to continue |
230+
| `hook_widget_register()` | Register widget | 0 to continue |
231+
| `widget_render_code_stats()` | Render widget | 0 on success |
232+
| `api_get_stats_json()` | Get stats JSON | Length or error |
233+
234+
### Host Functions Used
235+
236+
| Function | Purpose |
237+
|----------|---------|
238+
| `log(level, ptr, len)` | Logging |
239+
| `get_context()` | Access host context |
240+
| `register_widget(region, ptr, len)` | Register UI widget |
241+
| `show_toast(level, ptr, len, duration)` | Show notification |
242+
| `emit_event(name_ptr, name_len, data_ptr, data_len)` | Emit custom event |
243+
244+
## Testing
245+
246+
The plugin can be tested by:
247+
248+
1. Building and installing the plugin
249+
2. Performing various file operations in Cortex
250+
3. Running `/stats` to verify tracking
251+
4. Running `/stats-reset` and verifying counters reset
252+
5. Running `/stats-export` and verifying JSON output
253+
254+
## License
255+
256+
MIT License - See LICENSE file for details.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Code Stats Plugin - An advanced Cortex plugin example
2+
#
3+
# This plugin demonstrates advanced plugin capabilities:
4+
# - Multiple commands with different functionalities
5+
# - Multiple hooks for tracking file operations
6+
# - UI widget for status bar display
7+
# - Persistent storage across sessions
8+
9+
# Top-level capabilities (before [plugin] section)
10+
capabilities = ["commands", "hooks", "config", "events"]
11+
12+
# Permissions for file operations
13+
permissions = [
14+
{ read_file = { paths = ["**/*"] } },
15+
]
16+
17+
[plugin]
18+
id = "code-stats"
19+
name = "Code Statistics Plugin"
20+
version = "1.0.0"
21+
description = "Tracks and displays code statistics including lines added, removed, and files modified"
22+
authors = ["Cortex Team <team@cortex.dev>"]
23+
homepage = "https://github.com/cortex/examples/plugins/code-stats"
24+
license = "MIT"
25+
min_cortex_version = "0.5.0"
26+
keywords = ["statistics", "metrics", "productivity", "advanced", "demo"]
27+
28+
# Command definitions
29+
[[commands]]
30+
name = "stats"
31+
aliases = ["statistics", "metrics"]
32+
description = "Display current session code statistics"
33+
usage = "/stats"
34+
category = "analytics"
35+
36+
[[commands]]
37+
name = "stats-reset"
38+
aliases = ["reset-stats"]
39+
description = "Reset all statistics counters to zero"
40+
usage = "/stats-reset"
41+
category = "analytics"
42+
43+
[[commands]]
44+
name = "stats-export"
45+
aliases = ["export-stats"]
46+
description = "Export statistics to JSON format"
47+
usage = "/stats-export [filename]"
48+
category = "analytics"
49+
50+
[[commands.args]]
51+
name = "filename"
52+
description = "Output filename for exported stats (defaults to 'stats.json')"
53+
required = false
54+
default = "stats.json"
55+
arg_type = "string"
56+
57+
# Hook definitions
58+
[[hooks]]
59+
hook_type = "file_operation_after"
60+
priority = 50
61+
function = "hook_file_operation_after"
62+
63+
[[hooks]]
64+
hook_type = "session_end"
65+
priority = 100
66+
function = "hook_session_end"
67+
68+
[[hooks]]
69+
hook_type = "widget_register"
70+
priority = 50
71+
function = "hook_widget_register"
72+
73+
# Configuration schema
74+
[config]
75+
auto_save = { description = "Automatically save stats on session end", type = "boolean", default = true, required = false }
76+
display_format = { description = "Format for displaying stats (compact, detailed)", type = "string", default = "compact", required = false }
77+
track_by_language = { description = "Track statistics per programming language", type = "boolean", default = true, required = false }
78+
79+
[config.display_format.validation]
80+
enum_values = ["compact", "detailed"]
81+
82+
# WASM module settings
83+
[wasm]
84+
memory_pages = 256
85+
timeout_ms = 10000
86+
wasi_enabled = true
87+
wasi_caps = ["stdout", "stderr", "clocks"]

0 commit comments

Comments
 (0)