Skip to content

feat: Add Kimi CLI support#19

Open
skylixone wants to merge 1 commit intoyigitkonur:mainfrom
skylixone:main
Open

feat: Add Kimi CLI support#19
skylixone wants to merge 1 commit intoyigitkonur:mainfrom
skylixone:main

Conversation

@skylixone
Copy link

@skylixone skylixone commented Feb 26, 2026

Summary

This PR adds support for Kimi CLI to the continues tool, enabling seamless session handoffs between Kimi and other supported CLI tools.

Changes

  • src/types/tool-names.ts: Add 'kimi' to TOOL_NAMES
  • src/types/schemas.ts: Add Kimi message and metadata schemas
  • src/parsers/kimi.ts: New parser implementation (~350 lines)
  • src/parsers/index.ts: Export Kimi parser functions
  • src/parsers/registry.ts: Register Kimi adapter with CLI args mapping
  • src/tests/e2e-conversions.test.ts: Add Kimi to test registry
  • src/tests/extract-handoffs.ts: Add Kimi to test registry

Kimi Session Format

Kimi stores sessions in the following structure:

~/.kimi/
├── kimi.json                    # Work directories + last session IDs
└── sessions/
    └── {workdir_hash}/
        └── {session_id}/
            ├── metadata.json    # title, session_id, archived, wire_mtime
            └── context.jsonl    # conversation history

context.jsonl format

  • _checkpoint entries: internal checkpoints
  • user entries: user messages with string content
  • assistant entries: assistant messages with content blocks (text, think, tool_calls)
  • tool entries: tool results
  • _usage entries: token counts

Features Supported

  • Session discovery and listing (continues list)
  • Tool call extraction (bash, read, write, edit, grep, glob, search, fetch, task, ask)
  • Thinking block extraction for session notes
  • Cross-tool handoff generation (continues resume <id> --print-only)
  • Native resume support (kimi --session <id>)

Testing

# Build
npm run build

# List Kimi sessions
node dist/cli.js list | grep kimi

# Scan shows Kimi count
node dist/cli.js scan

# Generate handoff
node dist/cli.js resume <session-id> --print-only

Example Output

$ continues scan
Total sessions: 72

claude  :   65
kimi    :    6
copilot :    1

Notes

  • Kimi uses a nested directory structure (workdir_hash/session_id) similar to some other tools
  • The parser handles both string and block-array content formats
  • Tool calls use the standard OpenAI-style function calling format

Review all of them with eye of John Carmack-like simplicity with elegeance approach and apply the one only if required

Greptile Summary

This PR adds Kimi CLI support to the session handoff tool. The integration follows existing patterns (registry, schemas, exports), but the core parser has critical bugs:

  • Broken hash matching (line 273): Uses base64 encoding instead of actual hashing, will never match Kimi's workdir hashes
  • Fabricated token stats (line 237): Arbitrary 70/30 split creates fake input/output counts
  • Wrong timestamp fallback (line 290): Uses current time instead of file mtime for historical sessions
  • No test coverage: Unlike all other parsers, Kimi has no fixture-based unit tests

The tool extraction logic (lines 112-207) correctly uses shared utilities and follows the established pattern from other parsers. Registry integration is clean.

Confidence Score: 2/5

  • Not safe to merge — broken workdir lookup and fabricated data will cause incorrect session attribution and misleading stats
  • Core parser has multiple logic bugs that will cause incorrect behavior. The hash matching is fundamentally broken, token counts are fake, and timestamps can be wrong. No unit tests to catch these issues.
  • src/parsers/kimi.ts requires fixes for hash matching (line 273), token calculation (line 237), and timestamp fallback (line 290). Unit tests must be added before merge.

Important Files Changed

Filename Overview
src/parsers/kimi.ts New Kimi parser with broken hash logic, fake token split ratios, bad timestamp fallback, and no test coverage
src/parsers/registry.ts Clean integration of Kimi adapter following existing patterns
src/types/schemas.ts Added Kimi schemas with proper Zod validation and passthrough for flexibility
src/tests/e2e-conversions.test.ts Added Kimi to e2e test registry but missing fixture-based unit tests

Last reviewed commit: 4c4e7f3

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

Copy link

@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.

8 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +273 to +275
const pathHash = Buffer.from(wd.path).toString('base64').replace(/[^a-zA-Z0-9]/g, '').toLowerCase().slice(0, 32);
return pathHash === workDirHash || sessionDir.includes(workDirHash);
});
Copy link

Choose a reason for hiding this comment

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

This isn't a hash — it's base64 encoding with character filtering. No way this matches Kimi's actual hashing logic. The fallback sessionDir.includes(workDirHash) is worse — substring matching will cause false matches.

Either reverse-engineer the real hash or just use file mtime and skip the config lookup entirely.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/parsers/kimi.ts
Line: 273-275

Comment:
This isn't a hash — it's base64 encoding with character filtering. No way this matches Kimi's actual hashing logic. The fallback `sessionDir.includes(workDirHash)` is worse — substring matching will cause false matches.

Either reverse-engineer the real hash or just use file mtime and skip the config lookup entirely.

How can I resolve this? If you propose a fix, please make it concise.

}

if (reasoning.length > 0) notes.reasoning = reasoning;
if (totalTokens > 0) notes.tokenUsage = { input: Math.floor(totalTokens * 0.7), output: Math.floor(totalTokens * 0.3) };
Copy link

Choose a reason for hiding this comment

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

Arbitrary 70/30 split with zero justification. This is fake data.

If you don't have real input/output token counts, don't make them up. Either drop tokenUsage entirely or pass through the raw token_count as-is.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/parsers/kimi.ts
Line: 237

Comment:
Arbitrary 70/30 split with zero justification. This is fake data.

If you don't have real input/output token counts, don't make them up. Either drop tokenUsage entirely or pass through the raw `token_count` as-is.

How can I resolve this? If you propose a fix, please make it concise.

lines: messages.length,
bytes: fs.statSync(path.join(sessionDir, 'context.jsonl')).size,
createdAt: stats.birthtime,
updatedAt: new Date((metadata.wire_mtime || Date.now() / 1000) * 1000),
Copy link

Choose a reason for hiding this comment

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

Date.now() / 1000 as fallback means you're timestamping historical sessions as "right now". Wrong.

Use stats.mtime if wire_mtime is missing.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/parsers/kimi.ts
Line: 290

Comment:
`Date.now() / 1000` as fallback means you're timestamping historical sessions as "right now". Wrong.

Use `stats.mtime` if `wire_mtime` is missing.

How can I resolve this? If you propose a fix, please make it concise.

thought.includes('remaining')
) {
const taskText = String(block.think).trim();
if (taskText.length > 0 && !pendingTasks.includes(taskText)) {
Copy link

Choose a reason for hiding this comment

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

O(n) lookup on every insertion. Use a Set.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/parsers/kimi.ts
Line: 348

Comment:
O(n) lookup on every insertion. Use a Set.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +82 to +84
function extractKimiContent(content: string | Array<{ text?: string; type?: string }>): string {
return extractTextFromBlocks(content as string | Array<{ type: string; text?: string }>);
}
Copy link

Choose a reason for hiding this comment

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

Wrapper function that adds nothing. Just call extractTextFromBlocks directly at the call sites.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/parsers/kimi.ts
Line: 82-84

Comment:
Wrapper function that adds nothing. Just call `extractTextFromBlocks` directly at the call sites.

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

Add support for Kimi CLI (kimi code) to the continues tool.

Changes:
- Add 'kimi' to TOOL_NAMES in src/types/tool-names.ts
- Add Kimi message schemas in src/types/schemas.ts
- Create src/parsers/kimi.ts with full parser implementation
- Update src/parsers/index.ts to export Kimi parser
- Update src/parsers/registry.ts to register Kimi adapter
- Update test files to include Kimi

Kimi session storage:
- Sessions stored in ~/.kimi/sessions/{workdir_hash}/{session_id}/
- metadata.json contains session metadata (title, session_id, archived)
- context.jsonl contains conversation history

Features supported:
- Session discovery and listing
- Tool call extraction (bash, read, write, edit, grep, glob, etc.)
- Thinking block extraction for session notes
- Cross-tool handoff generation
- Native resume support (kimi --session <id>)
- Cross-tool resume with --prompt flag

Fixes:
- Use --prompt flag for cross-tool args instead of positional argument
- Append 'What would you like me to do next?' to keep Kimi interactive
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