How to Extend OfficeCLI with Custom AI Logic: A Complete Plugin Development Guide
You extend OfficeCLI with custom AI logic by implementing a format-handler plugin that communicates via JSON over STDIN/STDOUT, declares capabilities in a manifest schema, and processes CLI verbs like add, set, and save through your AI layer.
OfficeCLI from iOfficeAI is a document automation framework built around a modular plugin architecture. If you need to integrate large language models, custom inference APIs, or proprietary AI engines into document workflows, you can extend OfficeCLI with custom AI logic without modifying the core codebase. By implementing a format-handler plugin, you gain full control over command processing while leveraging OfficeCLI's validation, autocomplete, and export infrastructure.
Understanding the OfficeCLI Plugin Architecture
OfficeCLI delegates document operations to specialized plugins discovered at runtime. The core extensibility resides in the OfficeCli.Core.Plugins namespace, specifically within PluginManifest.cs and PluginRegistry.cs.
Plugins declare their role via the PluginKind enum. While dump-reader and exporter plugins serve specific purposes, the format-handler is the most flexible entry point for custom AI logic. Format-handlers receive the full set of OfficeCLI commands—including add, set, and save—and determine how to process them, making them ideal for AI-driven transformations.
Creating a Format-Handler Plugin for AI Integration
Declaring the Plugin Manifest
Every plugin must emit a JSON manifest when invoked with the --info flag. This manifest defines how OfficeCLI interacts with your AI logic. Create a manifest.json that declares your plugin as a format-handler and specifies the file extensions you handle:
{
"name": "myai-handler",
"version": "0.1.0",
"protocol": 1,
"kinds": ["format-handler"],
"extensions": [".mydoc"],
"target": "docx",
"runtime": "dotnet",
"idle_timeout_seconds": { "default": 30 },
"vocabulary": {
"addable_types": ["paragraph", "image"],
"settable_props": {
"paragraph": ["text", "style"],
"image": ["source", "alt"]
},
"path_segments": ["body", "p", "r"]
}
}
The vocabulary section is critical: it drives OfficeCLI's autocomplete and validation. The addable_types, settable_props, and path_segments fields tell the host what operations are valid, while the actual AI processing happens in your implementation. The manifest structure is defined in PluginManifest.cs (lines 48–79), and the host validates this schema via PluginRegistry.TryReadManifest.
Implementing the JSON Protocol
Your plugin executable must read JSON commands from STDIN and write responses to STDOUT. The protocol begins after the --info handshake completes. Here is a minimal .NET skeleton demonstrating how to structure your entry point to handle AI-driven commands:
using System.Text.Json;
class Program
{
static int Main(string[] args)
{
if (args.Length == 1 && args[0] == "--info")
{
Console.WriteLine(File.ReadAllText("manifest.json"));
return 0;
}
// Read command verb and payload
var line = Console.ReadLine();
var request = JsonSerializer.Deserialize<JsonElement>(line ?? "{}");
var response = args[0] switch
{
"add" => HandleAdd(request),
"set" => HandleSet(request),
"save" => HandleSave(request),
_ => new { error = "unknown verb" }
};
Console.WriteLine(JsonSerializer.Serialize(response));
return 0;
}
static object HandleAdd(JsonElement request)
{
var type = request.GetProperty("type").GetString();
if (type == "paragraph")
{
var generated = CallYourLlm("Generate introductory text based on context.");
return new { type = "paragraph", props = new { text = generated } };
}
return new { error = "unsupported type" };
}
static string CallYourLlm(string prompt) => $"[AI-generated] {prompt}";
}
The host creates a FormatHandlerSession to manage your plugin's lifecycle, then proxies each command through FormatHandlerProxy. Your responses must deserialize into types compatible with DocumentNode or ListDocumentNode, registered in the PluginJsonContext at the end of PluginManifest.cs.
Handling AI Integration
Inside your plugin, you can embed any AI stack—local LLMs via ONNX, remote APIs like OpenAI, or custom rule engines. Because the protocol is language-agnostic JSON over streams, you can write the AI logic in Python, Go, or Node.js provided the executable honors the STDIN/STDOUT contract.
Process the incoming request payload, apply your AI transformation, and return the structured document nodes. The AI layer decides how to interpret commands; for example, an add paragraph request could trigger prompt engineering against a template, semantic search for content insertion, or style transfer algorithms.
Plugin Discovery and Lifecycle
OfficeCLI discovers plugins by scanning standard directories: $HOME/.officecli/plugins and the executable's sibling plugins/ folder. At startup, PluginRegistry builds a cache of ResolvedPlugin objects that map (PluginKind, extension) pairs to executable paths, implemented in PluginRegistry.FindFor.
The host enforces process safety via the idle_timeout_seconds declared in your manifest. If your AI processing hangs, OfficeCLI terminates the process after the timeout. Override this globally using the environment variable OFFICECLI_PLUGIN_IDLE_TIMEOUT_SECONDS, resolved through PluginManifestExtensions.ResolveIdleTimeout.
Routing Commands to Your AI Logic
When users run commands targeting your registered extension, OfficeCLI routes them automatically:
# Discover your plugin
officecli plugins list
# View manifest validation
officecli plugins info myai-handler
# Trigger AI processing
officecli add paragraph --file example.mydoc
officecli save --output result.docx
The add command targets example.mydoc, which matches your .mydoc extension in the registry. CommandBuilder.Add.cs constructs a BatchItem, then FormatHandlerSession and FormatHandlerProxy serialize the command to your plugin's STDIN. Your AI processes the request and returns the document structure, which OfficeCLI then materializes into the target format (e.g., docx as specified in target).
For long-running AI workflows, examine ResidentServer.cs, which demonstrates how OfficeCLI keeps plugin instances resident across multiple commands, eliminating process startup overhead for inference-heavy operations.
Testing and Validating Your Plugin
Use the built-in linting tools to catch vocabulary mismatches before deployment:
officecli plugins lint myai-handler
This validates that your emitted properties match the declared vocabulary schema. The CommandBuilder.Plugins.cs file implements the list, info, and lint subcommands, providing immediate feedback on manifest correctness and protocol compliance.
Summary
- Format-handler plugins provide the most flexible architecture to extend OfficeCLI with custom AI logic, receiving all document commands via STDIN.
- The manifest (declared in
PluginManifest.cs) must declarekinds: ["format-handler"], supportedextensions, and avocabularyfor validation. - Plugin discovery occurs via
PluginRegistry.FindFor, scanning standard directories and caching resolved executables. - Command routing flows through
FormatHandlerSessionandFormatHandlerProxy, which manage the JSON protocol handshake and proxy verbs to your AI layer. - Safety mechanisms include configurable
idle_timeout_secondsand theOFFICECLI_PLUGIN_IDLE_TIMEOUT_SECONDSenvironment variable. - Validation tools like
officecli plugins lintensure your AI plugin adheres to the declared schema before runtime.
Frequently Asked Questions
What plugin type should I use for AI integration?
Use a format-handler plugin. Unlike dump-reader or exporter plugins that handle specific read-only or write-only tasks, format-handlers receive the full command vocabulary (add, set, save, etc.) and can implement arbitrary AI-driven transformations on document structure. This gives you complete control over how AI interprets and modifies documents.
Can I write the plugin in Python instead of .NET?
Yes. The OfficeCLI plugin protocol is language-agnostic. As long as your executable can read JSON from STDIN, write JSON to STDOUT, and emit the manifest when called with --info, you can implement the AI logic in Python, Go, Rust, or Node.js. The host only requires adherence to the JSON schema defined in PluginManifest.cs, not a specific runtime.
How does OfficeCLI handle plugin crashes or hangs?
The host enforces an idle timeout specified in your manifest's idle_timeout_seconds field. If your AI processing exceeds this limit, OfficeCLI terminates the plugin process. You can adjust the default timeout per plugin or override it globally using the OFFICECLI_PLUGIN_IDLE_TIMEOUT_SECONDS environment variable, as resolved by PluginManifestExtensions.ResolveIdleTimeout.
How do I validate that my AI plugin follows the correct protocol?
Run officecli plugins lint <plugin-name> before deployment. This command, implemented in CommandBuilder.Plugins.cs, verifies that your manifest schema is valid and that your plugin's runtime responses match the declared vocabulary. It catches mismatches between addable_types or settable_props and the actual JSON your AI layer emits, preventing runtime deserialization errors in FormatHandlerProxy.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →