diff --git a/README.md b/README.md
index 211c206e3..8fc84f990 100644
--- a/README.md
+++ b/README.md
@@ -101,6 +101,7 @@ Emdash currently supports 24 CLI providers, and we are adding new ones regularly
| [Kilocode](https://kilo.ai/docs/cli) | ✅ Supported | npm install -g @kilocode/cli |
| [Kimi](https://www.kimi.com/code/docs/en/kimi-cli/guides/getting-started.html) | ✅ Supported | uv tool install kimi-cli |
| [Kiro (AWS)](https://kiro.dev/docs/cli/) | ✅ Supported | curl -fsSL https://cli.kiro.dev/install | bash |
+| [Letta](https://docs.letta.com/letta-code/cli) | ✅ Supported | npm install -g @letta-ai/letta-code |
| [Mistral Vibe](https://github.com/mistralai/mistral-vibe) | ✅ Supported | curl -LsSf https://mistral.ai/vibe/install.sh | bash |
| [OpenCode](https://opencode.ai/docs/cli/) | ✅ Supported | npm install -g opencode-ai |
| [Pi](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent) | ✅ Supported | npm install -g @mariozechner/pi-coding-agent |
diff --git a/agents/integrations/providers.md b/agents/integrations/providers.md
index 0a709bd95..b7c1bb87f 100644
--- a/agents/integrations/providers.md
+++ b/agents/integrations/providers.md
@@ -6,9 +6,9 @@
- `src/main/core/dependencies/dependency-manager.ts`
- `src/main/core/pty/`
-## Current Providers (25)
+## Current Providers (26)
-codex, claude, devin, qwen, droid, gemini, cursor, copilot, amp, opencode, hermes, charm, auggie, goose, kimi, kilocode, kiro, rovo, cline, continue, codebuff, mistral, junie, pi, autohand
+codex, claude, devin, qwen, droid, gemini, cursor, copilot, amp, opencode, hermes, charm, auggie, goose, kimi, kilocode, kiro, rovo, cline, continue, codebuff, mistral, junie, pi, autohand, letta
## Provider Metadata Includes
diff --git a/src/assets/images/letta.svg b/src/assets/images/letta.svg
new file mode 100644
index 000000000..568a54914
--- /dev/null
+++ b/src/assets/images/letta.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/main/core/agent-hooks/classifiers/index.ts b/src/main/core/agent-hooks/classifiers/index.ts
index da2a2553a..371542d15 100644
--- a/src/main/core/agent-hooks/classifiers/index.ts
+++ b/src/main/core/agent-hooks/classifiers/index.ts
@@ -18,6 +18,7 @@ import { createJunieClassifier } from './junie';
import { createKilocodeClassifier } from './kilocode';
import { createKimiClassifier } from './kimi';
import { createKiroClassifier } from './kiro';
+import { createLettaClassifier } from './letta';
import { createMistralClassifier } from './mistral';
import { createOpenCodeClassifier } from './opencode';
import { createPiClassifier } from './pi';
@@ -44,6 +45,7 @@ const classifierFactories: Partial ProviderClassif
kilocode: createKilocodeClassifier,
kimi: createKimiClassifier,
kiro: createKiroClassifier,
+ letta: createLettaClassifier,
mistral: createMistralClassifier,
opencode: createOpenCodeClassifier,
pi: createPiClassifier,
diff --git a/src/main/core/agent-hooks/classifiers/letta.ts b/src/main/core/agent-hooks/classifiers/letta.ts
new file mode 100644
index 000000000..016460a58
--- /dev/null
+++ b/src/main/core/agent-hooks/classifiers/letta.ts
@@ -0,0 +1,55 @@
+import { createProviderClassifier, type ClassificationResult } from './base';
+
+export function createLettaClassifier() {
+ return createProviderClassifier((text: string): ClassificationResult => {
+ const tail = text.slice(-500);
+
+ // Permission/approval prompts
+ if (/approve|reject|permission|allow|confirm/i.test(tail)) {
+ return {
+ type: 'notification',
+ notificationType: 'permission_prompt',
+ };
+ }
+
+ // Idle/ready prompts (slash-command hint shows in Letta's input footer)
+ if (/Press\s+Tab|\/help|\/connect|\/model|\/agents/i.test(tail)) {
+ return {
+ type: 'notification',
+ notificationType: 'idle_prompt',
+ };
+ }
+
+ if (/letta\s*>|^>\s*$/im.test(tail)) {
+ return {
+ type: 'notification',
+ notificationType: 'idle_prompt',
+ };
+ }
+
+ // Auth success (e.g. /connect flow)
+ if (/Successfully authenticated|Successfully connected|Login successful/i.test(text)) {
+ return {
+ type: 'notification',
+ notificationType: 'auth_success',
+ };
+ }
+
+ // Questions/elicitation
+ if (/What.*\?|How.*\?|Which.*\?|Please (provide|specify|clarify)/i.test(tail)) {
+ return {
+ type: 'notification',
+ notificationType: 'elicitation_dialog',
+ };
+ }
+
+ // Error detection
+ if (/error:|fatal:|exception|failed/i.test(text)) {
+ return {
+ type: 'error',
+ };
+ }
+
+ return undefined;
+ });
+}
diff --git a/src/main/core/conversations/impl/agent-command.ts b/src/main/core/conversations/impl/agent-command.ts
index f7eb4f652..386e4d64b 100644
--- a/src/main/core/conversations/impl/agent-command.ts
+++ b/src/main/core/conversations/impl/agent-command.ts
@@ -116,6 +116,8 @@ export function buildAgentCommand({
}
} else if (providerConfig?.sessionIdFlag) {
args.push(...parseArgField(providerConfig.sessionIdFlag), sessionId);
+ } else if (!isResuming && providerDef?.newConversationFlag) {
+ args.push(providerDef.newConversationFlag);
}
if (autoApprove && providerConfig?.autoApproveFlag) {
diff --git a/src/renderer/lib/providers/meta.ts b/src/renderer/lib/providers/meta.ts
index 28d7d065a..c021a1f64 100644
--- a/src/renderer/lib/providers/meta.ts
+++ b/src/renderer/lib/providers/meta.ts
@@ -18,6 +18,7 @@ import junieIcon from '@/assets/images/junie-color.png';
import kilocodeIcon from '@/assets/images/kilocode.png';
import kimiIcon from '@/assets/images/kimi.png';
import kiroIcon from '@/assets/images/kiro.png';
+import lettaIcon from '@/assets/images/letta.svg?raw';
import mistralIcon from '@/assets/images/mistral.png';
import openaiIcon from '@/assets/images/openai.svg?raw';
import opencodeIcon from '@/assets/images/opencode.png';
@@ -46,6 +47,7 @@ const ICONS: Record = {
'kimi.png': kimiIcon,
'kilocode.png': kilocodeIcon,
'kiro.png': kiroIcon,
+ 'letta.svg': lettaIcon,
'atlassian.png': atlassianIcon,
'cline.png': clineIcon,
'continue.png': continueIcon,
diff --git a/src/renderer/utils/agentConfig.ts b/src/renderer/utils/agentConfig.ts
index 1bee3f05b..b7b925f41 100644
--- a/src/renderer/utils/agentConfig.ts
+++ b/src/renderer/utils/agentConfig.ts
@@ -19,6 +19,7 @@ import junieLogo from '../../assets/images/junie-color.png';
import kilocodeLogo from '../../assets/images/kilocode.png';
import kimiLogo from '../../assets/images/kimi.png';
import kiroLogo from '../../assets/images/kiro.png';
+import lettaLogoSvg from '../../assets/images/letta.svg?raw';
import mistralLogo from '../../assets/images/mistral.png';
import openaiLogoSvg from '../../assets/images/openai.svg?raw';
import opencodeLogo from '../../assets/images/opencode.png';
@@ -51,6 +52,13 @@ export const agentConfig: Record = {
goose: { name: 'Goose', logo: gooseLogo, alt: 'Goose CLI' },
kimi: { name: 'Kimi', logo: kimiLogo, alt: 'Kimi CLI' },
kilocode: { name: 'Kilocode', logo: kilocodeLogo, alt: 'Kilocode CLI' },
+ letta: {
+ name: 'Letta',
+ logo: lettaLogoSvg,
+ alt: 'Letta Code CLI',
+ isSvg: true,
+ invertInDark: true,
+ },
kiro: { name: 'Kiro', logo: kiroLogo, alt: 'Kiro CLI' },
cline: { name: 'Cline', logo: clineLogo, alt: 'Cline CLI' },
continue: { name: 'Continue', logo: continueLogo, alt: 'Continue CLI' },
diff --git a/src/shared/agent-provider-registry.ts b/src/shared/agent-provider-registry.ts
index 477e05dbd..ce4c81a64 100644
--- a/src/shared/agent-provider-registry.ts
+++ b/src/shared/agent-provider-registry.ts
@@ -23,6 +23,7 @@ export const AGENT_PROVIDER_IDS = [
'mistral',
'junie',
'pi',
+ 'letta',
'autohand',
] as const;
@@ -56,6 +57,12 @@ export type AgentProviderDefinition = {
* e.g. '--session-id' for Claude Code.
*/
sessionIdFlag?: string;
+ /**
+ * CLI flag for providers whose default invocation auto-resumes the last
+ * conversation (e.g. `letta --new`). Emitted only when starting a fresh
+ * session and the provider has no sessionIdFlag to address by ID.
+ */
+ newConversationFlag?: string;
defaultArgs?: string[];
planActivateCommand?: string;
autoStartCommand?: string;
@@ -466,6 +473,27 @@ export const AGENT_PROVIDERS: AgentProviderDefinition[] = [
alt: 'Pi CLI',
terminalOnly: true,
},
+ {
+ id: 'letta',
+ name: 'Letta',
+ description:
+ 'Memory-first coding agent CLI with persistent agents that learn across sessions and portable memory across models.',
+ docUrl: 'https://docs.letta.com/letta-code/cli',
+ installCommand: 'npm install -g @letta-ai/letta-code',
+ commands: ['letta'],
+ versionArgs: ['--version'],
+ cli: 'letta',
+ autoApproveFlag: '--yolo',
+ initialPromptFlag: '',
+ // Bare `letta` auto-resumes the cwd's last conversation; `--new` is
+ // required to start a fresh one when emdash spins up a new chat.
+ newConversationFlag: '--new',
+ useKeystrokeInjection: true,
+ icon: 'letta.svg',
+ alt: 'Letta Code CLI',
+ invertInDark: true,
+ terminalOnly: true,
+ },
{
id: 'autohand',
name: 'Autohand Code',