Use this skill when the user needs help building, testing, or deploying custom LimaCharlie extensions.
This skill helps you build custom LimaCharlie extensions. Use this when users ask for help creating extensions, understanding the extension architecture, building UI components, or debugging extension issues.
LimaCharlie Extensions are small HTTPS services that receive webhooks from the LimaCharlie cloud, enabling you to expand and customize security environments by integrating third-party tools, automating workflows, and adding new capabilities.
billing.ctrl and user.ctrl permissions to subscribe an organizationExtensions are HTTPS services that:
User/D&R Rule → LimaCharlie Cloud → Extension (via webhook)
↓
Process with LC SDK
↓
Return JSON Response
Each webhook includes:
Golang (recommended for stricter typing):
https://github.com/refractionPOINT/lc-extension
Python:
https://github.com/refractionPOINT/lc-extension/tree/master/python
Navigate to: https://app.limacharlie.io/add-ons/published
Required fields:
segment: Isolates resources (extension can only see/modify what it created)bulk: Increases API quota for extensions making many API callsCreate a basic schema with configuration and actions:
{
"config_schema": {
"fields": {
"api_key": {
"data_type": "secret",
"description": "API key for external service",
"label": "API Key"
}
},
"requirements": [["api_key"]]
},
"request_schema": {
"scan": {
"is_impersonated": false,
"is_user_facing": true,
"short_description": "Scan a sensor",
"parameters": {
"fields": {
"sid": {
"data_type": "sid",
"description": "Sensor ID to scan",
"label": "Sensor"
}
},
"requirements": [["sid"]]
}
}
},
"required_events": ["subscribe", "unsubscribe"]
}
e.OnRequest("scan", func(ctx *ext.Context) (interface{}, error) {
sid := ctx.Params["sid"].(string)
results := performScan(ctx.SDK, sid)
return map[string]interface{}{"status": "completed", "findings": results}, nil
})
e.OnEvent("subscribe", func(ctx *ext.Context) error {
log.Printf("New subscription: %s", ctx.OID)
return nil
})
{
"config_schema": {
"fields": { /* configuration fields */ },
"requirements": [ /* required fields */ ]
},
"request_schema": {
"action_name": {
"is_impersonated": false,
"is_user_facing": true,
"short_description": "Brief description",
"long_description": "Detailed description",
"parameters": {
"fields": { /* action parameters */ },
"requirements": [ /* required parameters */ ]
},
"response": {
"fields": { /* response structure */ }
}
}
},
"required_events": ["subscribe", "unsubscribe", "update"]
}
Every field follows this minimal structure:
{
"field_name": {
"data_type": "string",
"description": "Field description",
"label": "Human Readable Label",
"placeholder": "Example value",
"display_index": 1,
"default_value": "default"
}
}
The requirements field defines which fields are required:
// Both fields required
"requirements": [["denominator"], ["numerator"]]
// denominator AND (numerator OR default) required
"requirements": [["denominator"], ["numerator", "default"]]
| Type | Description | Example |
|---|---|---|
string |
Text value | Any text |
integer |
Number | 42 |
bool |
Boolean | true/false |
enum |
Selection from list | Requires enum_values |
sid |
Sensor ID | UUID format |
secret |
Secret from secrets manager | Encrypted value |
json |
JSON data | Any JSON object |
yaml |
YAML data | YAML content |
object |
Nested fields | Complex structures |
For complete data type reference, see REFERENCE.md.
Actions are defined in request_schema with parameters:
e.OnRequest("action_name", func(ctx *ext.Context) (interface{}, error) {
param := ctx.Params["param_name"].(string)
config, _ := ctx.SDK.Hive().Get("extension_configuration", "my-ext")
sensor, _ := ctx.SDK.Sensor(param).Get()
return map[string]interface{}{"status": "success", "data": sensor}, nil
})
e.OnEvent("subscribe", func(ctx *ext.Context) error {
return ctx.SDK.Rules().Add("my-rule", ruleContent)
})
LimaCharlie automatically generates UI from your schema. The UI adapts based on data types and layout configuration.
Specify layout in schema's top-level layout field:
{
"views": [
{
"name": "Configuration",
"layout": "config"
},
{
"name": "Actions",
"layout": "action",
"default_action": "scan"
},
{
"name": "Documentation",
"layout": "description"
}
]
}
Use is_list: true with object data type to create table UI:
{
"rules": {
"data_type": "object",
"is_list": true,
"description": "Detection rules",
"object": {
"fields": {
"name": {
"data_type": "string",
"description": "Rule name"
},
"severity": {
"data_type": "enum",
"enum_values": ["low", "medium", "high"]
}
}
}
}
}
detect:
event: NEW_PROCESS
op: is
path: event/FILE_PATH
value: /usr/bin/suspicious
respond:
- action: extension request
extension name: my-scanner
extension action: scan
extension request:
sid: '{{ .routing.sid }}'
limacharlie extension request \
--name my-scanner \
--action scan \
--data '{"sid": "sensor-id"}'
curl -X POST "https://api.limacharlie.io/v1/ext/my-scanner/request" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"oid": "org-id", "action": "scan", "params": {"sid": "sensor-id"}}'
Security: Always verify webhook signatures, use least privilege permissions, validate all input, secure secrets in environment variables, use segment flair for resource isolation.
Performance: Use async operations for long tasks, cache configurations, use bulk flair for high API usage, implement timeouts.
Error Handling: Return meaningful errors, handle partial failures gracefully, maintain comprehensive logs.
D&R Framework: Package D&R rules for distribution using lc-extension/simplified/dr
Lookup Framework: Package threat intelligence lookups using lc-extension/simplified/lookup
CLI Framework: Integrate external CLI tools using lc-extension/simplified/cli
See EXAMPLES.md for complete implementations.
Extension Definition: Destination URL (HTTPS endpoint), Shared Secret (32+ chars), Permissions array, Extension Flairs (segment, bulk)
Schema Fields: config_schema (configuration), request_schema (actions), required_events (subscribe/unsubscribe/update), layout (UI type), views (tabs)
Callbacks: Request (handle actions), Event (handle subscribe/unsubscribe/update), Config Validation (validate changes)
Common Permissions: sensor.get/task, dr.get/set, hive.get/set, artifact.get, outputs.get/set
Code: Golang Framework | Python Framework
API Docs: Extension API | Schema API
Support: Community Slack | answers@limacharlie.io
Always verify webhook signatures, use least privilege permissions, validate input, test with test organizations first, use segment flair for isolation, implement proper error handling, cache configurations, use simplified frameworks for common patterns, test locally with ngrok before deploying.