diff --git a/agents/integrations/providers.md b/agents/integrations/providers.md
index bafdd652d1..dde977fac6 100644
--- a/agents/integrations/providers.md
+++ b/agents/integrations/providers.md
@@ -3,12 +3,14 @@
## Source Of Truth
- `src/shared/core/agents/agent-provider-registry.ts`
+- `packages/plugins/src/agents/impl/*`
+- `packages/plugins/src/agents/registry.ts`
- `src/main/core/dependencies/dependency-managers.ts`
- `src/main/core/pty/`
-## Current Providers (32)
+## Current Providers (34)
-codex, claude, grok, devin, qwen, qoder, droid, gemini, antigravity, cursor, copilot, amp, commandcode, opencode, hermes, charm, auggie, goose, kimi, kilocode, kiro, rovo, cline, continue, codebuff, freebuff, mistral, jules, junie, pi, autohand, letta
+codex, claude, grok, devin, qwen, qoder, droid, gemini, antigravity, cursor, copilot, amp, commandcode, opencode, hermes, charm, auggie, goose, kimi, kilocode, kiro, rovo, cline, continue, codebuff, freebuff, mistral, jules, junie, pi, autohand, letta, mimocode, zero
## Provider Metadata Includes
@@ -39,8 +41,10 @@ or notify an inferred status for that event.
## Adding Or Changing A Provider
1. update `src/shared/core/agents/agent-provider-registry.ts`
-2. update allowlisted agent env vars in `src/main/core/pty/pty-env.ts` if needed
-3. add or update hook/plugin installation in `src/main/core/agent-hooks/` if the provider
+2. add or update the provider plugin under `packages/plugins/src/agents/impl/*`
+3. register the plugin in `packages/plugins/src/agents/registry.ts`
+4. update allowlisted agent env vars in `src/main/core/pty/pty-env.ts` if needed
+5. add or update hook/plugin installation in `src/main/core/agent-hooks/` if the provider
supports explicit events
-4. validate detection behavior in `src/main/core/dependencies/`
-5. add or update tests for any non-standard behavior
+6. validate detection behavior in `src/main/core/dependencies/`
+7. add or update tests for any non-standard behavior
diff --git a/apps/emdash-desktop/src/assets/images/zero.svg b/apps/emdash-desktop/src/assets/images/zero.svg
new file mode 100644
index 0000000000..f1d20dc1de
--- /dev/null
+++ b/apps/emdash-desktop/src/assets/images/zero.svg
@@ -0,0 +1,4 @@
+
diff --git a/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts b/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts
index e37fba5561..a3e7556403 100644
--- a/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts
+++ b/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts
@@ -32,6 +32,7 @@ export const AGENT_PROVIDER_IDS = [
'letta',
'autohand',
'mimocode',
+ 'zero',
] as const;
export type AgentProviderId = (typeof AGENT_PROVIDER_IDS)[number];
@@ -732,6 +733,21 @@ export const AGENT_PROVIDERS: AgentProviderDefinition[] = [
terminalOnly: true,
supportsHooks: true,
},
+ {
+ id: 'zero',
+ name: 'Zero',
+ description:
+ 'Terminal coding agent with multi-provider model support, local-first configuration, and terminal-first coding workflows.',
+ docUrl: 'https://zero.gitlawb.com/',
+ installCommand: 'npm install -g @gitlawb/zero',
+ commands: ['zero'],
+ versionArgs: ['--version'],
+ cli: 'zero',
+ useKeystrokeInjection: true,
+ icon: 'zero.svg',
+ alt: 'Zero CLI',
+ terminalOnly: true,
+ },
];
const PROVIDER_MAP = new Map(
diff --git a/packages/plugins/src/agents/impl/zero/icon.ts b/packages/plugins/src/agents/impl/zero/icon.ts
new file mode 100644
index 0000000000..9474ab5891
--- /dev/null
+++ b/packages/plugins/src/agents/impl/zero/icon.ts
@@ -0,0 +1,12 @@
+import type { AgentIconAsset } from '@emdash/core/agents/plugins';
+
+export const icon: AgentIconAsset = {
+ kind: 'svg',
+ alt: 'Zero CLI',
+ variants: [
+ {
+ minSize: 0,
+ light: ``,
+ },
+ ],
+};
diff --git a/packages/plugins/src/agents/impl/zero/index.test.ts b/packages/plugins/src/agents/impl/zero/index.test.ts
new file mode 100644
index 0000000000..4cd3f5ea6b
--- /dev/null
+++ b/packages/plugins/src/agents/impl/zero/index.test.ts
@@ -0,0 +1,43 @@
+import type { CommandContext } from '@emdash/core/agents/plugins';
+import { describe, expect, it } from 'vitest';
+import { pluginRegistry } from '../../registry';
+
+const zero = pluginRegistry.get('zero')!;
+
+function build(ctx: CommandContext) {
+ return zero.behavior.prompt!.buildCommand(ctx);
+}
+
+describe('zero plugin', () => {
+ it('registers install metadata and binary name', () => {
+ expect(zero).toBeDefined();
+ expect(zero.metadata.websiteUrl).toBe('https://zero.gitlawb.com/');
+ expect(zero.capabilities.hostDependency.binaryNames).toEqual(['zero']);
+ expect(zero.capabilities.hostDependency.installCommands.macos?.[0]?.command).toBe(
+ 'npm install -g @gitlawb/zero'
+ );
+ expect(zero.capabilities.hostDependency.updates).toMatchObject({
+ kind: 'supported',
+ releaseSource: { kind: 'npm', package: '@gitlawb/zero' },
+ });
+ expect(zero.capabilities.mcp.kind).toBe('none');
+ expect(zero.capabilities.sessions.kind).toBe('stateless');
+ });
+
+ it('starts the TUI and leaves prompt delivery to keystroke injection', () => {
+ expect(zero.capabilities.prompt.kind).toBe('keystroke');
+
+ const result = build({
+ cli: 'zero',
+ autoApprove: true,
+ initialPrompt: 'Fix the bug',
+ sessionId: 'conv-1',
+ isResuming: false,
+ model: '',
+ });
+
+ expect(result.command).toBe('zero');
+ expect(result.args).toEqual([]);
+ expect(result.env).toEqual({});
+ });
+});
diff --git a/packages/plugins/src/agents/impl/zero/index.ts b/packages/plugins/src/agents/impl/zero/index.ts
new file mode 100644
index 0000000000..1de4755560
--- /dev/null
+++ b/packages/plugins/src/agents/impl/zero/index.ts
@@ -0,0 +1,29 @@
+import { definePlugin, registerPluginBehavior } from '@emdash/core/agents/plugins';
+import { buildStandardCommand, npmDependency } from '@emdash/core/agents/plugins/helpers';
+import { icon } from './icon';
+
+export const plugin = definePlugin(
+ {
+ id: 'zero',
+ name: 'Zero',
+ description:
+ 'Terminal coding agent with multi-provider model support, local-first configuration, and terminal-first coding workflows.',
+ websiteUrl: 'https://zero.gitlawb.com/',
+ },
+ {
+ hostDependency: npmDependency({ id: 'zero', package: '@gitlawb/zero' }),
+ prompt: {
+ kind: 'keystroke',
+ },
+ sessions: {
+ kind: 'stateless',
+ },
+ },
+ { icon }
+);
+
+export const provider = registerPluginBehavior(plugin, {
+ prompt: {
+ buildCommand: (ctx) => buildStandardCommand(ctx, {}),
+ },
+});
diff --git a/packages/plugins/src/agents/registry.ts b/packages/plugins/src/agents/registry.ts
index b6298be8a6..9d69a072e4 100644
--- a/packages/plugins/src/agents/registry.ts
+++ b/packages/plugins/src/agents/registry.ts
@@ -33,6 +33,7 @@ import { provider as pi } from './impl/pi';
import { provider as qoder } from './impl/qoder';
import { provider as qwen } from './impl/qwen';
import { provider as rovo } from './impl/rovo';
+import { provider as zero } from './impl/zero';
export const pluginRegistry = createPluginRegistry();
@@ -70,6 +71,7 @@ for (const p of [
qoder,
qwen,
rovo,
+ zero,
]) {
pluginRegistry.register(p);
}