Skip to content

Gadget Ecosystem

llmist supports loading gadgets from npm packages and git repositories, enabling a rich ecosystem of reusable tools.

Dhalsim is the official browser automation package for llmist, providing gadgets for web navigation, screenshots, and autonomous browsing.

Terminal window
# Use directly (auto-installed)
bunx @llmist/cli agent "Navigate to apple.com" -g dhalsim
# Specific version
bunx @llmist/cli agent "Screenshot google.com" -g [email protected]
PresetDescriptionGadgets
allAll browser automation gadgetsFull suite
minimalBasic navigation and captureNavigate, Screenshot, GetFullPageContent
readonlyNavigation and read-only operationsNo form filling or clicking
subagentAutonomous browser agentBrowseWeb
Terminal window
# Use a preset
bunx @llmist/cli agent "Research topic" -g dhalsim:subagent
# Combine presets with local gadgets
bunx @llmist/cli agent "Complex task" \
-g dhalsim:minimal \
-g ./my-gadget.ts

When using dhalsim:all or dhalsim, you get:

GadgetDescription
NavigateNavigate to a URL
ScreenshotCapture a screenshot
GetFullPageContentGet full page text/HTML
ClickClick an element
TypeType into an input
ScrollPageScroll the page
WaitForElementWait for element to appear

The dhalsim:subagent preset provides BrowseWeb, an autonomous browser agent:

Terminal window
bunx @llmist/cli agent "Find the pricing for Anthropic's API" -g dhalsim:subagent

BrowseWeb spawns a nested agent that:

  1. Opens a browser
  2. Plans a browsing strategy
  3. Navigates, clicks, and extracts information
  4. Returns findings to the parent agent

Example usage in code:

// The BrowseWeb gadget is a subagent
class BrowseWeb extends Gadget({
description: 'Browse the web autonomously to complete a task',
schema: z.object({
task: z.string().describe('What to accomplish'),
startUrl: z.string().url().optional(),
}),
}) {
async execute(params, ctx) {
// Spawns a nested agent with browser gadgets
const result = await new AgentBuilder()
.withParentContext(ctx!)
.withModel('haiku')
.withGadgets(Navigate, Screenshot, Click, Type)
.askAndCollect(params.task);
return result;
}
}

Load gadgets directly from git repositories:

Terminal window
# Public repository
bunx @llmist/cli agent "task" -g git+https://github.com/user/my-gadgets.git
# Specific branch/tag
bunx @llmist/cli agent "task" -g git+https://github.com/user/my-gadgets.git#v1.0.0
# Private repository (uses git credentials)
bunx @llmist/cli agent "task" -g git+https://github.com/org/private-gadgets.git

Git gadget repositories should export gadgets from their entry point:

my-gadgets/
├── package.json
├── index.ts # Exports gadgets
└── src/
├── floppy.ts
└── arcade.ts
index.ts
export { FloppyDisk } from './src/floppy.js';
export { ArcadeHighScore } from './src/arcade.js';
my-gadget-package/
├── package.json
├── index.ts
├── src/
│ ├── gadget-a.ts
│ └── gadget-b.ts
└── presets.ts # Optional: define presets
{
"name": "my-gadget-package",
"version": "1.0.0",
"type": "module",
"main": "index.ts",
"peerDependencies": {
"llmist": "^8.0.0"
},
"llmist": {
"presets": {
"all": ["GadgetA", "GadgetB"],
"minimal": ["GadgetA"]
}
}
}
index.ts
import { Gadget, z } from 'llmist';
export class GadgetA extends Gadget({
description: 'Does something useful',
schema: z.object({
input: z.string(),
}),
}) {
async execute(params: this['params']): Promise<string> {
return `Processed: ${params.input}`;
}
}
export class GadgetB extends Gadget({
description: 'Does something else',
schema: z.object({
value: z.number(),
}),
}) {
execute(params: this['params']): string {
return `Result: ${params.value * 2}`;
}
}

Add presets to package.json:

{
"llmist": {
"presets": {
"all": ["GadgetA", "GadgetB", "GadgetC"],
"core": ["GadgetA"],
"advanced": ["GadgetB", "GadgetC"]
}
}
}

Users can then:

Terminal window
bunx @llmist/cli agent "task" -g my-package:core
bunx @llmist/cli agent "task" -g my-package:advanced

Import manifest types from llmist for type-safe package development:

import type {
LLMistPackageManifest,
SubagentManifestEntry,
PresetDefinition,
SessionManifestEntry,
} from 'llmist';
import { parseManifest, hasPreset, listSubagents, getSubagent } from 'llmist';

Full manifest structure:

const manifest: LLMistPackageManifest = {
// Entry point for all gadgets
gadgets: './dist/index.js',
// Factory function entry point (optional)
factory: './dist/index.js',
// Presets: array of gadget names or "*" for all
presets: {
minimal: ['Navigate', 'Screenshot'],
readonly: ['Navigate', 'GetFullPageContent', 'Screenshot'],
all: '*', // All exported gadgets
},
// Subagent definitions (optional)
subagents: {
BrowseWeb: {
entryPoint: './dist/index.js',
export: 'Dhalsim', // Export name
description: 'Autonomous web browser agent',
defaultModel: 'sonnet',
maxIterations: 15,
},
},
// Session factory metadata (optional)
session: {
factory: 'getSessionManager',
type: 'browser',
},
};

Parsing utilities:

import { readFileSync } from 'fs';
import { parseManifest, hasPreset, getPresetGadgets, listSubagents } from 'llmist';
// Parse manifest from package.json
const pkg = JSON.parse(readFileSync('package.json', 'utf-8'));
const manifest = parseManifest(pkg);
// Check presets
if (hasPreset(manifest, 'minimal')) {
const gadgets = getPresetGadgets(manifest, 'minimal');
// ['Navigate', 'Screenshot']
}
// List subagents
const subagentNames = listSubagents(manifest);
// ['BrowseWeb']
Terminal window
npm publish

Users install with:

Terminal window
bunx @llmist/cli agent "task" -g my-package

When using third-party gadgets:

  1. Review the source - Check the repository before using
  2. Pin versions - Use specific versions in production: -g [email protected]
  3. Use gadget approval - Enable approval for dangerous operations:
    [agent]
    gadget-approval = { "*" = "approval-required" }
  4. Sandbox execution - Consider running in isolated environments

Mix local, npm, git, and built-in gadgets:

Terminal window
bunx @llmist/cli agent "Complex research task" \
-g ./local-gadget.ts \
-g dhalsim:minimal \
-g builtin:ReadFile \
-g git+https://github.com/user/my-gadgets.git