The public extension API for Hone IDE. A pure TypeScript type library — zero runtime code, zero dependencies.
@honeide/api is the foundational contract for the Hone extension ecosystem. It defines every type, interface, namespace, and event signature that extension authors need to build features for Hone.
It is Layer 0 — no @honeide/* dependencies, no runtime, nothing to import at execution time. When you install this package, you are installing a set of TypeScript declarations that describe how your extension interacts with Hone.
Who uses it:
- Extension authors — import types to build and type-check their extensions
hone-core— implements the API bridge that fulfills these contracts at runtimehone-extensions— all built-in extensions import only this packagehone-ide— wires API implementations to the runtime
npm install @honeide/api --save-devThis is a development-time dependency only. Your compiled extension does not bundle this package.
Every Hone extension exports an activate function. The ExtensionContext gives you access to the API surface and a subscriptions array for automatic cleanup.
import*ashonefrom'@honeide/api';exportfunctionactivate(context: hone.ExtensionContext): void{// Register a commandconstcmd=hone.commands.registerCommand('myext.greet',()=>{hone.ui.showInformationMessage('Hello from My Extension!');});// Register a hover provider for TypeScript filesconsthover=hone.languages.registerHoverProvider('typescript',{provideHover(document,position,token){constword=document.getWordRangeAtPosition(position);if(!word)returnundefined;return{contents: [{value: `**Word:** \`${document.getText(word)}\``}],range: word,};},});// Everything pushed to subscriptions is disposed on deactivationcontext.subscriptions.push(cmd,hover);}exportfunctiondeactivate(): void{}Register and execute commands. Commands are the primary action mechanism in Hone.
// Register a handlerconstdisposable=hone.commands.registerCommand('myext.action',(arg: string)=>{// handle command});// Execute programmaticallyconstresult=awaithone.commands.executeCommand<string>('myext.action','hello');// List all commandsconstall=awaithone.commands.getCommands(/* filterInternal */true);Types for working with open text editors and documents.
// Core typeshone.Position// { line: number; character: number }hone.Range// { start, end, isEmpty, isSingleLine, contains() }hone.Selection// extends Range, adds anchor, active, isReversedhone.TextEdit// { range, newText }hone.Location// { uri, range }// The document (read-only)constdoc: hone.TextDocument;doc.getText();// full textdoc.lineAt(0).text;// first linedoc.getWordRangeAtPosition(pos);// word boundary at position// Mutate via the editor's edit builderconsteditor: hone.TextEditor;awaiteditor.edit(builder=>{builder.insert(pos,'inserted text');builder.replace(range,'replacement');builder.delete_(range);});File system access, workspace folders, configuration, and document events.
// Open a documentconstdoc=awaithone.workspace.openTextDocument('/path/to/file.ts');// Find filesconstfiles=awaithone.workspace.findFiles('**/*.ts','**/node_modules/**');// Read configurationconstcfg=hone.workspace.getConfiguration('myext');consttimeout: number=cfg.get('timeout',5000);// Watch for file changesconstwatcher=hone.workspace.createFileSystemWatcher('**/*.ts');context.subscriptions.push(watcher.onDidChange(uri=>console.log('changed:',uri.fsPath)),watcher,);// Multi-file editsconstedit=newhone.WorkspaceEdit();// implemented by hone-coreedit.set(uri,[hone.TextEdit.insert(pos,'// header\n')]);awaithone.workspace.applyEdit(edit);// Eventshone.workspace.onDidSaveTextDocument(doc=>{/* ... */});hone.workspace.onDidChangeConfiguration(e=>{if(e.affectsConfiguration('myext')){/* reload */}});Status bar, messages, input, tree views, and webviews.
// Status barconstitem=hone.ui.createStatusBarItem(hone.StatusBarAlignment.Left,100);item.text='$(sync~spin) Building...';item.show();// Messagesawaithone.ui.showInformationMessage('Done!');constchoice=awaithone.ui.showWarningMessage('Delete file?','Yes','No');// Inputconstname=awaithone.ui.showInputBox({prompt: 'Enter name',placeHolder: 'my-extension'});constitem=awaithone.ui.showQuickPick(['Option A','Option B'],{placeHolder: 'Select'});// Tree viewconstprovider: hone.TreeDataProvider<MyNode>={getTreeItem: el=>({label: el.name,collapsibleState: hone.TreeItemCollapsibleState.None}),getChildren: el=>el ? el.children : rootNodes,};hone.ui.registerTreeDataProvider('myext.view',provider);// Webviewconstpanel=hone.ui.createWebviewPanel('myView','My Panel',{enableScripts: true});panel.webview.html='<html><body><h1>Hello</h1></body></html>';panel.webview.onDidReceiveMessage(msg=>{/* handle message from webview */});awaitpanel.webview.postMessage({type: 'update',data: 42});// Progressawaithone.ui.withProgress({location: hone.ProgressLocation.Notification,title: 'Indexing'},async(progress,token)=>{progress.report({increment: 50,message: 'halfway...'});awaitdoWork(token);});Register language intelligence providers.
// Completionhone.languages.registerCompletionItemProvider('typescript',{provideCompletionItems(doc,pos,token,ctx){return[{label: 'mySnippet',kind: hone.CompletionItemKind.Snippet,insertText: 'console.log($1)'},];},},'.'/* trigger character */);// Hoverhone.languages.registerHoverProvider({language: 'typescript',scheme: 'file'},{provideHover(doc,pos,token){return{contents: [{value: '**Type:** `string`'}]};},});// Diagnostics (pushed proactively, not pulled)constcollection=hone.languages.createDiagnosticCollection('my-linter');collection.set(uri,[{range: someRange,message: 'Unused import',severity: hone.DiagnosticSeverity.Warning,source: 'my-linter',}]);context.subscriptions.push(collection);// Code actions (quick fixes)hone.languages.registerCodeActionProvider('typescript',{provideCodeActions(doc,range,ctx,token){returnctx.diagnostics.map(diag=>({title: `Fix: ${diag.message}`,kind: hone.CodeActionKind.QuickFix,diagnostics: [diag],}));},});// Other providers available:hone.languages.registerDefinitionProvider(selector,provider);hone.languages.registerReferenceProvider(selector,provider);hone.languages.registerRenameProvider(selector,provider);hone.languages.registerCodeLensProvider(selector,provider);hone.languages.registerDocumentSymbolProvider(selector,provider);hone.languages.registerDocumentFormattingEditProvider(selector,provider);hone.languages.registerSignatureHelpProvider(selector,provider,'(',',');Debug session lifecycle and breakpoints.
// Start a debug sessionawaithone.debug.startDebugging(folder,{type: 'node',name: 'Launch',request: 'launch',program: '${file}',});// Listen to sessionshone.debug.onDidStartDebugSession(session=>{session.customRequest('evaluate',{expression: 'myVar'});});// Manage breakpointshone.debug.onDidChangeBreakpoints(({ added, removed })=>{/* ... */});Create and interact with integrated terminals.
constterm=hone.terminal.createTerminal({name: 'Build',shellPath: '/bin/zsh'});term.sendText('npm run build');term.show();hone.terminal.onDidWriteTerminalData(({ terminal, data })=>{// data is stdout/stderr output});hone.terminal.onDidCloseTerminal(t=>{constcode=t.exitStatus?.code;});Register custom AI providers and agent tools.
// Register a custom LLM providerconstprovider: hone.AIProviderAdapter={id: 'my-llm',name: 'Corporate LLM',capabilities: {maxContextTokens: 32_000,supportsStreaming: true,supportsToolUse: true,supportsVision: false,supportsFIM: false,estimatedLatencyMs: 800,},async*complete(req,token){// stream FIM completions},async*chat(req,token){// stream chat responses},async*chatWithTools(req,token){// stream tool-use responses},};constdisposable=hone.ai.registerAIProvider(provider);// Register an agent tool the AI can usehone.ai.registerAgentTool({name: 'run_tests',description: 'Run the project test suite and return output',inputSchema: {type: 'object',properties: {filter: {type: 'string',description: 'Test name filter'}},},requiresApproval: true,execute: async({ filter })=>{// run tests, return result stringreturn'All tests passed.';},});// src/extension.tsimport*ashonefrom'@honeide/api';// Called when any activation event fires (defined in extension manifest)exportfunctionactivate(context: hone.ExtensionContext): void{// context.extensionPath — absolute path to your extension directory// context.storagePath — workspace-scoped persistent storage// context.globalStoragePath — cross-workspace persistent storage// context.subscriptions — push Disposables here for auto-cleanupconstdisp=hone.commands.registerCommand('myext.hello',()=>{});context.subscriptions.push(disp);}// Called when the extension is deactivated (optional)exportfunctiondeactivate(): void{// perform any final cleanup not covered by subscriptions}Every register* call returns a Disposable. Push it into context.subscriptions for automatic cleanup when your extension is deactivated, or call .dispose() manually to unregister earlier.
// Auto-cleanup via subscriptionscontext.subscriptions.push(hone.commands.registerCommand('myext.foo',handler),hone.languages.registerHoverProvider('typescript',hoverProvider),hone.ui.createStatusBarItem(hone.StatusBarAlignment.Right,0),);// Manual cleanupconstwatcher=hone.workspace.createFileSystemWatcher('**/*.ts');// later:watcher.dispose();Every declare namespace in this package corresponds to a real JavaScript object you must provide via the API bridge. The shapes here are the contract — implement against them exactly.
The export declare namespace commands { ... } pattern means:
- At the type level: the namespace exists and has these members
- At runtime:
hone-coremust attach a real object with matching signatures
Contributions are welcome! This repository defines the public API surface for Hone extensions — changes here affect every extension author.
Guidelines:
- This is a type-only library. No runtime code, no imports from non-TypeScript packages.
- All changes to existing types are breaking changes. Additions are backwards-compatible.
- Run
npm testbefore opening a PR — a clean type-check is the full test suite. - For significant API additions, open an issue first to discuss design.
git clone https://github.com/HoneIDE/api.git
cd api
npm install
npm test# type-check (primary tests)
npm run test:enums # compile + run enum value assertionsMIT © Honeide