Skip to content

Add Factory Droid CLI support#1

Merged
yigitkonur merged 3 commits intomainfrom
feat/droid-integration
Feb 19, 2026
Merged

Add Factory Droid CLI support#1
yigitkonur merged 3 commits intomainfrom
feat/droid-integration

Conversation

@yigitkonur
Copy link
Copy Markdown
Owner

@yigitkonur yigitkonur commented Feb 19, 2026

Hey — this adds full support for Factory AI's Droid CLI as the 6th tool in continues.

What changed

Droid stores sessions as JSONL files at ~/.factory/sessions/<workspace-slug>/ with a companion .settings.json for model and token metadata. The format turned out to be very close to Claude Code's — Anthropic-style tool_use/tool_result content blocks — so the parser was straightforward to write.

New parser (src/parsers/droid.ts)

Handles all the event types I found in real Droid sessions:

  • session_start — session ID, title, cwd, owner
  • message — user/assistant turns with text, tool_use, tool_result, and thinking content blocks
  • todo_state — extracts pending tasks from Droid's built-in todo tracking
  • compaction_state — silently skipped (context window management)

Tool calls mapped to SummaryCollector categories:

  • Createwrite_file, Readread_file, Edit/ApplyPatchedit_file
  • Execute/Bashshell, LS → directory listing
  • MCP tools (e.g. context7___query-docs) → per-tool categories
  • TodoWrite → skipped (internal bookkeeping)

Token usage and model info come from the companion .settings.json rather than the JSONL stream.

Everything else

All 7 integration points updated: SessionSource type, parser barrel, session index, resume commands (droid -s <id>), markdown labels, CLI colors + quick-resume subcommand.

Testing

  • 84 unit tests passing (up from 61)
  • 30 conversion paths tested (was 20) — every source↔target combination
  • 3 new Droid-specific parser tests
  • Injection safety tests for all Droid handoff paths
  • Manually verified against 5 real Droid sessions on my machine — session discovery, context extraction, and handoff markdown all work correctly

Version bump

2.6.7 → 2.7.0 (new platform = minor version). Added postinstall message so people know about Droid support when they upgrade.

Test plan

  • pnpm build — clean compile
  • pnpm test — 84/84 pass
  • continues list --source droid — discovers real sessions
  • continues scan — shows droid in source breakdown
  • Context extraction produces valid handoff markdown with files modified, tool activity, model info, and token usage
  • MCP tool calls (context7) parsed correctly
  • Thinking blocks extracted as reasoning highlights

Open with Devin

Summary by CodeRabbit

Release Notes v2.7.0

  • New Features

    • Added Factory Droid support with session discovery, auto-resume, and cross-tool handoff capabilities
    • Extract reasoning highlights, token/model usage, and pending tasks from sessions
    • Enhanced file and shell operation handling with MCP tool calls
  • Documentation

    • Added comprehensive integration guide for developers
    • Updated README with Droid in supported tools and cross-tool handoff examples
  • Tests

    • Expanded test coverage to 30 conversion paths across 6 supported sources
  • Chores

    • Version bumped to 2.7.0

Add full session parsing for Factory AI's Droid CLI (factory.ai).
Reads JSONL sessions from ~/.factory/sessions/ with companion
.settings.json for model/token metadata.

Parses Create/Read/Edit/Execute/Bash/LS tool calls, MCP tools,
thinking blocks, and todo_state events. Supports native resume
via `droid -s <id>` and cross-tool handoff in both directions.

All 7 integration points wired: types, parser, barrel export,
session index, resume commands, markdown labels, and CLI UI.
Add createDroidFixture() with realistic JSONL + settings.json data.
Add Droid-specific parser tests (message extraction, tool_use filtering,
session_start/todo_state skipping). Update all test files to include
droid in Record<SessionSource, ...> maps. Conversion paths: 5×4=20 → 6×5=30.
- Bump version 2.6.7 → 2.7.0
- Add postinstall message announcing Droid support
- Update README: add Droid to feature list, extraction table,
  storage table, quick-resume examples
- Create CHANGELOG.md with 2.7.0 release notes
- Update CLAUDE.md to reflect 6 supported tools
@yigitkonur yigitkonur merged commit 631b33a into main Feb 19, 2026
@yigitkonur yigitkonur deleted the feat/droid-integration branch February 19, 2026 22:07
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 19, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This pull request introduces Factory Droid as a sixth supported tool integration, adding session parsing, context extraction, CLI commands, test coverage, and documentation. Version bumped to 2.7.0 with postinstall message updates.

Changes

Cohort / File(s) Summary
Documentation & Metadata
CHANGELOG.md, CLAUDE.md, README.md, package.json
Added Droid references across documentation; bumped version to 2.7.0; added postinstall welcome message and keywords; updated feature counts from 5 to 6 tools.
Type Definitions
src/types/index.ts
Extended SessionSource union type to include 'droid' alongside existing sources (claude, copilot, gemini, codex, opencode).
Parser Implementation
src/parsers/droid.ts, src/parsers/index.ts
New 508-line Droid parser module implementing session discovery from ~/.factory/sessions, JSONL log parsing, settings extraction, tool data analysis, pending task extraction, and context compilation; re-exported from index.
Utility & Resume Logic
src/utils/index.ts, src/utils/markdown.ts, src/utils/resume.ts
Integrated Droid into buildIndex and extractContext flows; added source label mapping and resume command generation for both native (droid -s {id}) and cross-tool paths.
CLI Integration
src/cli.ts
Added version constant bump (2.6.0→2.7.0); added droid color mapping (red); introduced new droid [n] command for resuming Nth newest Droid session; updated help text and command descriptions across pick, list, and resume commands.
Test Infrastructure
src/__tests__/conversions.test.ts, src/__tests__/e2e-conversions.test.ts, src/__tests__/extract-handoffs.ts, src/__tests__/fixtures/index.ts, src/__tests__/unit-conversions.test.ts
Extended ALL_SOURCES to include droid; added createDroidFixture(); wired parseDroidSessions and extractDroidContext into test parsers and extractors; updated test expectations to reflect 30 total conversion paths across 6 sources.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI / User
    participant Parser as parseDroidSessions()
    participant FS as File System
    participant SessionData as JSONL Sessions
    participant Extractor as extractDroidContext()
    participant Markdown as generateHandoffMarkdown()

    CLI->>Parser: Request Droid sessions
    Parser->>FS: Scan ~/.factory/sessions/
    Parser->>FS: Read .settings.json (model, tokens, timing)
    FS-->>Parser: Settings loaded
    Parser->>SessionData: Open session.jsonl
    SessionData-->>Parser: Parse session_start event
    Parser->>SessionData: Extract messages & events
    SessionData-->>Parser: Collect tool_use/tool_result, todo_state
    Parser-->>CLI: UnifiedSession[] returned
    
    CLI->>Extractor: Extract context for session
    Extractor->>SessionData: Read all events
    Extractor->>Extractor: Filter messages (exclude system)
    Extractor->>Extractor: Extract tool summaries (files, shell)
    Extractor->>Extractor: Parse pending tasks from todo_state
    Extractor->>Markdown: Generate handoff markdown
    Markdown-->>Extractor: Formatted handoff text
    Extractor-->>CLI: SessionContext (notes, messages, tasks, markdown)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

This introduces substantial new parser logic (508 lines in droid.ts) with intricate event parsing, tool data extraction, and session metadata handling. The breadth of file modifications across types, utilities, CLI, and test infrastructure—combined with integration points requiring consistent thread-through—demands careful validation of each integration path and verification that Droid sessions flow correctly through the entire context extraction pipeline.

Poem

A new Droid joins the crew of six, 🤖
Sessions parsed from factory mix,
Pending tasks and tools unite,
Cross-tool handoffs burning bright,
Continue coding, day and night! ✨

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/droid-integration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 5 additional findings in Devin Review.

Open in Devin Review

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Missing droid case in e2e test runTool causes throw when droid is used as target

The runTool function in src/__tests__/e2e-conversions.test.ts has a switch statement that handles claude, gemini, codex, opencode, and copilot, but is missing a case 'droid':. The default branch throws new Error('Unknown tool: droid').

Impact Details

Since droid was added to ALL_SOURCES at line 27, the test loop at lines 192-248 will attempt to use droid as both a source and a target. When droid is the target, runTool('droid', ...) is called and hits the default throw at line 111.

While this test file is excluded from CI via vitest.config.ts (pattern **/e2e*), it's still a test that someone would run manually per the PR description. All 5 conversion paths targeting droid (e.g. claude → droid, gemini → droid, etc.) will fail with an unhandled error.

(Refers to lines 110-111)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +171 to +177
rl.on('line', (line) => {
linesRead++;
if (linesRead > 100) {
rl.close();
stream.close();
return;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 lastTimestamp truncated to first 100 lines causes incorrect updatedAt for long sessions

The parseSessionInfo function reads only the first 100 lines of a Droid JSONL file (line 173), but tracks lastTimestamp as it goes (line 190). For sessions with more than 100 messages, lastTimestamp will be set to the timestamp of the ~100th message — not the actual last message in the file.

Root Cause and Impact

At src/parsers/droid.ts:268, updatedAt is set from lastTimestamp:

const updatedAt = lastTimestamp ? new Date(lastTimestamp) : fileStats.mtime;

The fallback fileStats.mtime would be accurate, but it's only used when lastTimestamp is empty. For any session with at least one message in the first 100 lines, lastTimestamp will be non-empty but stale — it reflects the timestamp at line ~100, not the actual end of the session.

Since sessions are sorted by updatedAt descending (src/parsers/droid.ts:290), long Droid sessions will appear older than they actually are in the session list. A session that was active 5 minutes ago but has 200+ messages could appear as if it was last active hours ago.

The Claude parser avoids this by not extracting timestamps from the JSONL at all — it uses fileStats.mtime for updatedAt (src/parsers/claude.ts:176-177).

Fix: Either read the entire file for lastTimestamp, or use fileStats.mtime as updatedAt (matching the Claude parser pattern), or only use lastTimestamp from parseSessionInfo for createdAt/firstTimestamp and always use fileStats.mtime for updatedAt.

Prompt for agents
In src/parsers/droid.ts, the parseSessionInfo function (lines 155-213) reads only the first 100 lines but tracks lastTimestamp, which is then used as updatedAt at line 268. For sessions longer than 100 lines, this produces a stale updatedAt. Fix by changing line 268 to always use fileStats.mtime for updatedAt, matching the Claude parser pattern:

Change line 268 from:
  const updatedAt = lastTimestamp ? new Date(lastTimestamp) : fileStats.mtime;
To:
  const updatedAt = fileStats.mtime;

Alternatively, remove lastTimestamp tracking from parseSessionInfo entirely since it's unreliable with the 100-line limit, and update the return type accordingly.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

yigitkonur added a commit that referenced this pull request Feb 25, 2026
Rewrote the entire README to read like an actual developer wrote it:
- Punchier intro that leads with the problem, not a feature list
- Collapsed the 14×14 checkmark matrix into one sentence
- Cut 430→238 lines by removing redundancy and AI-doc patterns
- Added Community Contributions section referencing #1, #3, #4, #14
- Documented the 7 new agents (Amp, Kiro, Crush, Cline, Roo Code,
  Kilo Code, Antigravity) and bugs fixed in this round
- Prose over bullet spam, natural flow over exhaustive structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant