Official registry of community capabilities for the Venesa intelligence platform.
Capabilities are self-contained JavaScript modules that extend the Venesa intelligence platform. Each capability gives Venesa a new skill — from fetching weather data and searching the web, to reading files, sending emails, or controlling system processes.
Venesa's orchestrator dynamically discovers and loads capabilities at runtime. Once installed, a capability becomes part of Venesa's tool chain and can be invoked by the AI to complete tasks on your behalf.
This repository follows a simple, organized structure:
- Every capability is a single
.jsfile inside the/capabilities/folder - No sub-packages or deeply nested structures
- A
registry.jsonis auto-generated byscripts/generate-registry.jsand used by Venesa to discover capabilities
Venesa discovers capabilities by fetching registry.json from this repository and loading each capability directly by its raw file URL.
Capabilities are installed directly inside Venesa. From the Venesa UI, navigate to Capabilities → Browse Community and install any capability by file name — no manual downloads required.
Venesa fetches the raw capability file and loads it into its execution engine automatically.
- One capability per file
- File extension must be
.js - CommonJS only —
require/module.exports. Noimport/export - Export exactly one object
handlermust beasync. No raw Promise chains- Every
handlerbody wrapped intry/catch. Never throw unhandled - On error return
{ success: false, error: string }. Never throw - No
console.logor logging calls inside capability files - No side effects during import
- No ranges in
dependencies— exact versions only - No shared state between capabilities
"use strict";
const { z } = require("zod");
module.exports = {
name: "example",
description: "Returns the provided query string as-is. Use as a minimal capability template.",
returnType: "data",
marker: "silently",
tags: ["example"],
schema: z.object({
query: z.string().trim().min(1).describe("Input query string."),
}),
async handler({ query }) {
try {
return { success: true, result: query };
} catch (err) {
return { success: false, error: err.message };
}
},
};For the full specification including schema validation, return types, lifecycle hooks, and UI rendering options, see the Capability Development Specification section below.
Venesa's internal reasoning logic treats both core features and community extensions uniformly via a strictly typed capability standard. Every capability must export a compliant object (module.exports).
The architecture guarantees isolation; failed executions will be trapped and resolved cleanly by the orchestrator.
| Field | Required | Type | Description |
|---|---|---|---|
name |
✅ | string |
Unique camelCase identifier. Matches filename in camelCase (e.g. get-weather.js → getWeather). |
description |
✅ | string |
Injected verbatim into the LLM system prompt. See Description Rules below. |
returnType |
✅ | string |
data | action | ui | memory | hybrid |
schema |
✅ | ZodObject |
z.object({...}). Every field must have .describe("..."). No bare z.any(). |
handler |
✅ | async fn |
async (validatedParams) => { success, result }. Never throw. Always wrapped in try/catch. |
marker |
— | string |
silently | announce | confirm. See Marker Defaults below. |
tags |
— | string[] |
Lowercase. Shared vocabulary across similar capabilities (e.g. system, web, apps, network). |
dependencies |
— | string[] |
Exact npm specifiers only. No ranges (^, ~, >=, *). No git/http/file URLs. |
lifecycle |
— | object |
onLoad, onUnload, onEnable, onDisable hooks. |
ui |
— | string |
table | key-value | card-list | command-list. Omit the field entirely when no UI hint is needed — null is not a valid value and will be ignored by the platform. |
The description is injected verbatim into the LLM system prompt. The model reads it to decide when to invoke this capability and what to pass. Write it to answer three things in one to two sentences:
- What it does — the concrete action or data it produces.
- When to use it — the user intent that should trigger it.
- What it needs — the required inputs, briefly.
Good:
"Fetches a 5-day weather forecast for a given city. Use when the user asks about weather, temperature, or conditions in any location. Requires a city name."
Bad:
"Gets weather." — too vague; AI cannot reliably decide when or how to call it.
"This capability allows Venesa to retrieve current and forecasted meteorological data from a remote API endpoint and..." — too long; wastes token budget.
Rules:
- Present tense. No "this capability", "this skill", "this module".
- No mention of internal implementation details unless they directly affect usage.
- No filler. Every word must earn its place.
The marker field controls user-facing feedback before and after handler execution.
| returnType / Behavior | Default marker |
|---|---|
data — read/query, returns data to reason about |
silently |
action — non-destructive, no visible side effect |
silently |
action — visible side effect (launch app, open URL, send message) |
announce |
action — destructive (delete, wipe, shutdown, close all) |
confirm |
ui — renders structured output |
silently |
When no marker is set the platform infers one from returnType. Explicitly set marker whenever the inferred default would mislead the user.
"use strict";
const { z } = require("zod");
// Declare exact-version dependencies. Platform installs them into an isolated
// node_modules directory before first run. No ranges — exact versions only.
// dependencies: ['<dep_name>@1.7.9']
module.exports = {
name: "my-capability",
description: "Provides precise system queries to the execution engine.",
returnType: "data", // 'data' | 'action' | 'ui' | 'memory' | 'hybrid'
marker: "silently", // 'silently' | 'announce' | 'confirm'
tags: ["monitoring", "query"],
// dependencies: ['<dep_name>@1.7.9'],
schema: z.object({
query: z.string().optional(),
}),
// Optional static config
config: z.object({
/* params */
}),
// Optional lifecycle hooks
lifecycle: {
onLoad() {},
onUnload() {},
onEnable() {},
onDisable() {},
},
async handler(params) {
try {
/* logic */
return { success: true, result: null };
} catch (err) {
return { success: false, error: err.message };
}
},
};The handler(params) encapsulates the functional operation.
- Payload: The
paramsobject contains variables already sanitized against the definedschema. - Isolation: Operational context like the application thread is abstracted away from the parameter intake. The capability solely acts upon structured parameters.
- Response Format: Returns a native object, JSON string, or standard string.
- Error contract: Always return
{ success: false, error: string }on failure. Never throw.
Extracted inputs are hard-validated against the schema variable before triggering the payload handler.
- Pre-Validation: This avoids allocating computational resources for syntax-error LLM predictions. A runtime rejection instructs the model internally to attempt self-correction.
- Type Casting: Zod parameters can implement
.default()or.transform()to guarantee strict internal assumptions.
Capabilities can supply external variable structures via config, using the Zod syntax model. Values propagate internally at boot from application configurations or persistent stores. Ensure you attach .default() fallback states so modules perform cleanly immediately upon insertion.
returnType tells the orchestrator and the LLM how to treat the handler result.
| Type | When to use |
|---|---|
data |
Read/query operations that return information the AI should reason about. |
action |
System mutations: launching apps, writing files, sending messages, etc. |
ui |
Structured output rendered as a list, table, or card for the user. |
memory |
Context or note manipulation — reads/writes the AI's persistent memory. |
hybrid |
Mixed behaviour where the result drives both data reasoning and a UI render. |
Each capability gets fully isolated npm dependencies installed to:
~/.venesa/capabilities/<capabilityName>/node_modules/
No capability shares another's dependencies. Declare packages via the dependencies array using exact version specifiers:
dependencies: ['<dep_name>@1.7.9', 'cheerio@1.0.0'],Allowed specifiers:
| Format | Example |
|---|---|
| Package name only | "<dep_name>" (pinned to latest at first install) |
| Exact version | "<dep_name>@1.7.9" |
| Scoped exact | "@scope/pkg@2.0.0" |
Rejected specifiers — validation will reject these at install time:
| Rejected | Reason |
|---|---|
"<dep_name>@^1.7.0" |
range (^) |
"<dep_name>@~1.7" |
range (~) |
"<dep_name>@>=1.0.0" |
range operator |
"<dep_name>@*" |
wildcard |
"git+https://…" |
git URL |
"https://…" |
http URL |
"file:…" |
local path |
Prefer pinned versions ("pkg@x.y.z") to guarantee reproducible installs. Simply require('<dep_name>') in your handler — the platform resolves from the capability-local node_modules automatically.
Corrupted state: If a dependency fails to install 5 consecutive times, the capability is marked corrupted in the UI and will not load. Fix the dependency spec and publish a new version to clear the flag.
Venesa resolves {{token}} placeholders in all string parameters before the handler runs. Capabilities do not implement this — the platform orchestrator handles it automatically.
| Token | Resolves to |
|---|---|
{{user.home}} |
User home directory |
{{user.desktop}} |
Desktop folder |
{{user.downloads}} |
Downloads folder |
{{user.documents}} |
Documents folder |
{{user.name}} |
User's display name (from Settings, not the OS username) |
{{clipboard.text}} |
Current clipboard text |
{{system.date}} |
Current local date |
{{system.time}} |
Current local time |
{{runtime.temp}} |
System temp directory |
{{system.hostname}} |
Machine hostname |
{{env.KEY_NAME}} |
Value of a custom key saved in Settings → Custom Keys. If the key is not saved, execution pauses and the user is prompted to add it before retrying. Use for API keys and secrets. Not available for LLM-generated parameters. |
- Document token support in
.describe()— If a param accepts a path or dynamic value, tell the LLM which tokens apply. - Never resolve tokens manually — Do not call
os.homedir(),os.userInfo(), or readprocess.envto replicate what tokens already provide. Accept the param as a string and use it directly. - Never hardcode paths — Instead of
path.join(os.homedir(), 'Desktop'), expose an optional param with a default of{{user.desktop}}.
Declare each required key as a hidden schema field with z.string().default("{{env.KEY_NAME}}"). The platform resolves it before your handler runs. Do not add .describe() to key fields — they should be invisible to the LLM.
schema: z.object({
// LLM-supplied param
city: z.string().describe("City name to fetch weather for"),
// Hidden key param — platform resolves from Settings → Custom Keys
apiKey: z.string().default("{{env.OPENWEATHER_KEY}}"),
}),schema: z.object({
savePath: z.string().optional().describe(
"Output folder. Defaults to {{user.desktop}}. Supports tokens: {{user.desktop}}, {{user.documents}}, {{user.downloads}}"
),
}),Any capability that makes HTTP/HTTPS calls must handle offline errors explicitly rather than letting the network call fail with an opaque error. Use error-code detection in the catch block:
const <dep_name> = require('<dep_name>');
async handler(params) {
try {
const res = await <dep_name>.get(`https://api.example.com?q=${encodeURIComponent(params.query)}`);
return { success: true, result: res.data };
} catch (err) {
const isOffline =
err.code === 'ENOTFOUND' ||
err.code === 'ECONNREFUSED'||
err.code === 'ETIMEDOUT' ||
err.code === 'ERR_NETWORK' ||
err.message?.toLowerCase().includes('network');
if (isOffline) {
return {
success: false,
error: 'No internet connection. Please check your connection and try again.',
};
}
return { success: false, error: err.message };
}
},Do not import connectivity modules from platform internals. The error-code pattern above is portable and requires no platform-specific imports.
Capabilities execute inside the Electron main process, so require('electron') is available and fully supported. Use it to access Electron APIs such as shell.openExternal(), clipboard, dialog, and others.
async handler(params) {
try {
const { shell } = require('electron');
await shell.openExternal(`https://example.com?q=${encodeURIComponent(params.query)}`);
return { success: true, result: 'Opened in browser.' };
} catch (err) {
return { success: false, error: err.message };
}
},Capabilities remain self-contained — do not import from the Venesa application source (e.g. src/lib/, src/brain/). Only use Node built-ins, declared dependencies, and Electron's own API surface.
Lifecycles tie specific actions directly to external triggers. Hooks enforce asynchronous wrappers natively. Error outputs invoke standard warnings to the console without breaking daemon continuity.
onLoad(): Executed immediately following cache allocation within the registry index.onUnload(): Invoked during daemon termination or cache purging.onEnable()/onDisable(): Triggers upon user-toggled UI events.
All capabilities live under the /capabilities/ structure.
- A solitary file logic block:
/capabilities/automation-feature.js - Packaged multi-module structures:
/capabilities/automation-feature/skill.js(whereskill.jsserves as the target map). - Hidden logic elements (prefixed with
.or_) are still loaded and executed by the system, but they are not indexed within the orchestrator loop. This means they will not appear in the AI's tool list and cannot be invoked by name through the orchestrator, though their side effects (e.g., lifecycle hooks) still run.