Skip to content

feat: add support for Kilo Code#25

Open
pixelateapotato wants to merge 3 commits into
johnlindquist:mainfrom
pixelateapotato:kilocode
Open

feat: add support for Kilo Code#25
pixelateapotato wants to merge 3 commits into
johnlindquist:mainfrom
pixelateapotato:kilocode

Conversation

@pixelateapotato

@pixelateapotato pixelateapotato commented Feb 6, 2026

Copy link
Copy Markdown
  • add import functionality
  • add appropriate testing
  • sort lists alphabetically to improve visual scanning

Summary by CodeRabbit

  • New Features

    • Kilocode import/export added and integrated into CLI, full-export and import flows; memory-bank handling and import warnings introduced.
    • Expanded import/export support for Aider, Amazon Q, Claude Code, Cline, Codex, Copilot, Cursor, Gemini, Junie, Open Code, Qodo, Roo, Windsurf, Zed.
  • Documentation

    • README updated with supported formats, import/export examples, private/local rule mappings, and gitignore guidance.
  • Tests

    • New Kilocode integration tests and gitignore/all-formats tests validating roundtrips, private rule handling, and export patterns.
  • Chores

    • package keywords updated (kilocode).

- add import functionality
- add appropriate testing
- sort lists alphabetically to improve visual scanning
@coderabbitai

coderabbitai Bot commented Feb 6, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds Kilocode import/export support across CLI, importers, exporters, types, public API, README, and tests; introduces memory-bank handling, gitignore integration, and extends importAll/exportAll orchestration and return shapes.

Changes

Cohort / File(s) Summary
Type & Public API
src/types.ts, src/index.ts
Add 'kilocode' to format unions; add warnings to ImportResult/ImportResults; re-export importKilocode and exportToKilocode.
Importers
src/importers.ts
Added importKilocode(rulesDir, outputDir?): recursive Markdown frontmatter parsing, deterministic ID derivation, private-rule inference, memory-bank handling (common-tasks.md), and warning collection; importAll now aggregates warnings.
Exporters
src/exporters.ts
Added exportToKilocode(rules, outputDir, options?) (per-rule MD files with deterministic frontmatter and private filtering) and exportToJunie; updated exportAll to include Kilocode.
CLI
src/cli.ts
Wired Kilocode into format detection, interactive menus, import/export switch cases, all-format export, and gitignore path logic; added/extended gitignore helpers and warnings aggregation.
Tests
test/export-functionality.test.ts, test/integration/kilocode.test.ts, test/gitignore-all-formats.test.ts
Added Kilocode integration tests (import/export, memory-bank, warnings, roundtrip), expanded export tests to include Kilocode outputs and gitignore expectations, and added cross-platform path handling in tests.
Docs & Config
README.md, package.json
Documented new import/export methods and formats (Kilocode and others) and added kilocode to package keywords.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI
  participant Importer as Importer (importKilocode)
  participant Exporter as Exporter (exportToKilocode)
  participant FS as Filesystem

  CLI->>Importer: importAll(repoPath)
  Importer->>FS: read .kilocode/rules/**/*.md
  FS-->>Importer: file contents + frontmatter
  Importer->>Importer: parse frontmatter, compute IDs, detect private, collect warnings
  Importer-->>CLI: results + warnings

  CLI->>Exporter: exportAll(rules, repoPath, options)
  Exporter->>FS: write .kilocode/rules/{id}.md (frontmatter + body)
  Exporter-->>CLI: exportedPaths
  CLI->>FS: update .gitignore with exportedPaths
  FS-->>CLI: .gitignore updated
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I hopped through rules and YAML gleam,
.kilocode folders join the team,
IDs tidy, frontmatter bright,
imports, exports — all take flight,
a tiny rabbit cheers the stream ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add support for Kilo Code' accurately and concisely describes the main changeset, which adds comprehensive Kilocode format support including import/export functions, CLI integration, and tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/cli.ts (1)

236-252: ⚠️ Potential issue | 🟠 Major

.kilocode/rules/ missing from exportedPaths in the 'all' case.

exportAll() (line 238) calls exportToKilocode, but the exportedPaths list here doesn't include '.kilocode/rules/'. This means the gitignore-update prompt (line 345) won't account for kilocode output when the user selects "all formats."

Other recently added formats (.roo/rules/, .junie/guidelines.md, .amazonq/rules/) are also missing, but .kilocode/rules/ is directly introduced by this PR.

🐛 Proposed fix
           exportedPaths.push(
             '.github/copilot-instructions.md',
             '.cursor/rules/',
             '.clinerules',
             '.windsurfrules',
             '.rules',
             'AGENTS.md',
             'CONVENTIONS.md',
             'CLAUDE.md',
             'GEMINI.md',
-            'best_practices.md'
+            'best_practices.md',
+            '.amazonq/rules/',
+            '.roo/rules/',
+            '.kilocode/rules/',
+            '.junie/guidelines.md'
           )
README.md (1)

246-263: ⚠️ Potential issue | 🟡 Minor

The updateGitignore function (lines 547–564) is missing patterns documented in the README but appears to be unused—consider removing it or clarifying its purpose.

The private-patterns list in updateGitignore is missing entries for .junie/guidelines.local.md, .kilocode/rules/*.local.md, and .roo/rules/*.local.md that are documented in the README (lines 246–263). However, this function has no call sites in the codebase—the active gitignore update logic is in updateGitignoreWithPaths (line 520, called at line 359). If updateGitignore is dead code, it should be removed. If it's retained for future use, it should be updated to match the documented patterns.

🧹 Nitpick comments (5)
src/importers.ts (1)

913-980: Consider extracting a shared helper for directory-based importers.

importKilocode is effectively identical to importRoo (lines 817–884)—and very similar to importAgent and importCursor—differing only in the format string. The recursive file-walk, sorting, frontmatter parsing, ID derivation, and private-rule detection logic is duplicated verbatim each time a new directory-based format is added.

A shared helper like importDirectoryRules(rulesDir, format) would reduce each new importer to a one-liner and eliminate a growing maintenance burden.

♻️ Sketch of a shared helper
// Shared helper (conceptual)
function importDirectoryRules(rulesDir: string, format: string): ImportResult {
  const rules: RuleBlock[] = []

  function findMdFiles(dir: string, relativePath = ''): void {
    const entries = readdirSync(dir, { withFileTypes: true })
    entries.sort((a: Dirent, b: Dirent) => {
      if (a.isDirectory() && !b.isDirectory()) return -1
      if (!a.isDirectory() && b.isDirectory()) return 1
      return a.name.localeCompare(b.name)
    })
    for (const entry of entries) {
      const fullPath = join(dir, entry.name)
      const relPath = relativePath ? join(relativePath, entry.name) : entry.name
      if (entry.isDirectory()) {
        findMdFiles(fullPath, relPath)
      } else if (entry.isFile() && entry.name.endsWith('.md')) {
        const content = readFileSync(fullPath, 'utf-8')
        const { data, content: body } = matter(content, grayMatterOptions)
        let segments = relPath.replace(/\.md$/, '').replace(/\\/g, '/').split('/')
          .map((s: string) => s.replace(/^\d{2,}-/, '').replace(/\.local$/, ''))
        if (segments[0] === 'private') segments = segments.slice(1)
        const defaultId = segments.join('/')
        const isPrivateFile = isPrivateRule(fullPath)
        const metadata: any = { id: data.id || defaultId, ...data }
        if (metadata.alwaysApply === undefined) metadata.alwaysApply = false
        if (data.private === true || (data.private === undefined && isPrivateFile)) metadata.private = true
        rules.push({ metadata, content: body.trim() })
      }
    }
  }

  findMdFiles(rulesDir)
  return { format: format as any, filePath: rulesDir, rules }
}

// Then each importer becomes:
export function importKilocode(rulesDir: string): ImportResult {
  return importDirectoryRules(rulesDir, 'kilocode')
}
export function importRoo(rulesDir: string): ImportResult {
  return importDirectoryRules(rulesDir, 'roo')
}
src/exporters.ts (1)

520-573: Same duplication note as the importer side.

exportToKilocode is identical to exportToRoo except for the target directory (.kilocode/rules vs .roo/rules). A shared helper parameterized by the subdirectory path would consolidate both. Same recommendation as importKilocode.

test/export-functionality.test.ts (1)

137-138: Custom dirname helper is fragile on Windows — minor concern.

Line 143 calls dirname(fullPath) where fullPath is built with path.join(). On Windows, join produces backslash-separated paths, but the custom dirname at lines 172-174 splits only on '/'. This would cause dirname to return the full path unchanged on Windows, making the existsSync(dirname(fullPath)) fallback ineffective.

Consider importing dirname from path (renaming the local helper or the import) for cross-platform correctness:

-import { join } from 'path'
+import { join, dirname as pathDirname } from 'path'

Then use pathDirname in line 143 instead of the custom helper, or keep the custom one but use path.sep or a cross-platform split.

That said, this is pre-existing code and tests typically run on Linux/Mac CI, so impact is low.

Also applies to: 141-144

test/integration/kilocode.test.ts (2)

91-141: Naming overlap between private/ directory and private: true metadata could confuse future readers.

In the test data, the rule at line 102 has id: 'private/exported' (making private a directory name) and metadata.private: true. While functionally correct, this dual use of "private" may make the test harder to reason about in the future.

Consider renaming the ID to something like 'internal/exported' to separate the directory-nesting concern from the visibility concern. Purely optional.


184-204: Smoke test is fine but the name oversells "CLI" coverage.

The test is titled "CLI export to kilocode format creates correct structure" but it directly calls exportToKilocode, not any CLI entrypoint. The comment on line 185 acknowledges this, which is good. Consider renaming to something like 'exports to kilocode format with correct directory structure' to avoid confusion about what's actually being tested.

- Add JSDoc comments to 39 functions across cli.ts, importers.ts, and exporters.ts
- Follow existing codebase convention for simple one-line descriptions
- Addresses CodeRabbit docstring coverage warning

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/exporters.ts (1)

664-667: ⚠️ Potential issue | 🟡 Minor

Pre-existing: exportToCodex and exportToOpenCode both write to AGENTS.md — second call silently overwrites the first.

Lines 664 and 667 both target join(repoPath, 'AGENTS.md'). The OpenCode export will always overwrite the Codex export. This is not introduced by this PR, but it's worth flagging since it affects the exportAll path that now includes Kilocode.

src/cli.ts (1)

547-571: ⚠️ Potential issue | 🟡 Minor

updateGitignoreWithPaths appends all patterns (including already-existing ones) when any new pattern is found.

When newPatterns.length > 0 (line 563), the function appends the full patterns string (built from all paths, line 550–554) rather than just the new patterns. This means previously-added patterns will be duplicated in .gitignore on subsequent runs if at least one new format path was added since the last run.

🐛 Proposed fix — only append genuinely new patterns
     if (newPatterns.length > 0) {
-      appendFileSync(gitignorePath, patterns)
+      const newSection = [
+        '',
+        '# Added by dotagent: ignore exported AI rule files',
+        ...newPatterns.map(p => p.endsWith('/') ? p + '**' : p),
+        ''
+      ].join('\n')
+      appendFileSync(gitignorePath, newSection)
       return true
     }
🤖 Fix all issues with AI agents
In `@test/gitignore-all-formats.test.ts`:
- Around line 133-144: The custom failure messages are currently dead due to the
comma operator after expect(...).toContain(...); update the assertions
referencing EXPORT_FORMAT_PATHS and gitignoreContent so the message is passed as
the second argument to expect (e.g. expect(gitignoreContent, `Gitignore should
contain pattern for ${formatPath}...`).toContain(pattern)) and remove the stray
comma-separated template literals; do this for both the directory-branch
(pattern) and non-directory branch (formatPath) assertions so messages are shown
on test failures.
- Around line 75-93: The test helper runDotAgentExport currently shells out to a
built artifact at dist/cli.js (cliPath) which is gitignored and requires a prior
build; change the helper so tests run against the source rather than a built
file: update runDotAgentExport to invoke the TypeScript entry (e.g., src/cli.ts)
via a runtime TypeScript loader (node -r ts-node/register or npx ts-node) or
import/require the CLI module directly in tests and call its exported entry
function; ensure runDotAgentExport references the source path instead of
dist/cli.js (symbol: cliPath) or calls the CLI function exported by the module
so local pnpm test does not require a manual pnpm build.
🧹 Nitpick comments (5)
src/exporters.ts (1)

565-621: exportToKilocode is a near-exact copy of exportToRoo — consider extracting a shared helper.

The entire body of exportToKilocode (lines 568–621) is identical to exportToRoo (lines 510–563), differing only in the output directory name (.kilocode/rules vs .roo/rules). The same frontmatter construction pattern is also repeated in exportToAgent and exportToCursor.

A shared helper like exportToMultiFileWithFrontmatter(rules, outputDir, subPath, options) would eliminate ~200+ lines of duplication across these four exporters and make adding future formats trivial.

♻️ Sketch of shared helper
+function exportMultiFileMd(
+  rules: RuleBlock[],
+  outputDir: string,
+  subPath: string,
+  options?: ExportOptions
+): void {
+  const rulesDir = join(outputDir, ...subPath.split('/'))
+  mkdirSync(rulesDir, { recursive: true })
+
+  const filteredRules = rules.filter(rule => !rule.metadata.private || options?.includePrivate)
+
+  for (const rule of filteredRules) {
+    let filePath: string
+    if (rule.metadata.id && rule.metadata.id.includes('/')) {
+      const parts = rule.metadata.id.split('/')
+      const fileName = parts.pop() + '.md'
+      const subDir = join(rulesDir, ...parts)
+      mkdirSync(subDir, { recursive: true })
+      filePath = join(subDir, fileName)
+    } else {
+      filePath = join(rulesDir, `${rule.metadata.id || 'rule'}.md`)
+    }
+
+    const frontMatter = buildDeterministicFrontMatter(rule.metadata)
+    const content = rule.content.startsWith('\n') ? rule.content : '\n' + rule.content
+    writeFileSync(filePath, matter.stringify(content, frontMatter, grayMatterOptions), 'utf-8')
+  }
+}
+
 export function exportToRoo(rules: RuleBlock[], outputDir: string, options?: ExportOptions): void {
-  // ... 50+ lines ...
+  exportMultiFileMd(rules, outputDir, '.roo/rules', options)
 }
 
 export function exportToKilocode(rules: RuleBlock[], outputDir: string, options?: ExportOptions): void {
-  // ... 50+ lines ...
+  exportMultiFileMd(rules, outputDir, '.kilocode/rules', options)
 }
src/importers.ts (3)

1067-1098: Import function with file-write side effects is surprising — consider separating the memory-bank migration.

importKilocode writes to .agents/common-tasks.md (lines 1088–1095) during what callers would expect to be a read-only import operation. This couples data reading with file system mutation, making the function harder to test and reason about. Callers of importKilocode via the public API (re-exported from src/index.ts) may not expect side effects.

Consider returning the memory-bank info in the result (e.g., via warnings or a dedicated field) and performing the file write in the CLI or orchestration layer instead.


1069-1076: skipMemoryBankWarning name is misleading — both paths emit a message.

The flag doesn't actually "skip" a warning; it selects which message to emit (lines 1167–1173). A name like memoryBankImported or tasksMigrated would better convey the intent — true when the copy succeeded, false when skipped due to existing file.


1056-1061: Unnecessary as any cast — 'junie' is a valid member of the format union.

'junie' was added to ImportResult['format'] in src/types.ts (line 24), so this type assertion is no longer needed.

♻️ Proposed fix
   return {
-    format: 'junie' as any,
+    format: 'junie',
     filePath,
     rules,
     raw: content
   }
test/export-functionality.test.ts (1)

148-168: Format mapping test is missing several formats: gemini, roo, junie, amazonq.

The formatMap covers 11 of the 15 non-all formats. While this is a pre-existing gap, it's worth completing since the test's purpose is to validate the mapping. Adding the missing entries would catch future wiring mistakes.

Comment thread test/gitignore-all-formats.test.ts
Comment thread test/gitignore-all-formats.test.ts
… artifact

The test helper now imports CLI functions directly from src/index.ts instead of shelling out to dist/cli.js. This allows tests to run without a prior build step.

Changes:
- Replace execSync with direct imports of export functions
- Add helper functions for gitignore pattern filtering and updating
- Maintain existing test coverage for export and gitignore functionality

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cli.ts (1)

556-581: ⚠️ Potential issue | 🟡 Minor

updateGitignoreWithPaths appends all patterns when any new one is found, potentially duplicating existing entries.

Lines 570–575: filterNewPatterns correctly identifies which patterns are new, but the function always appends the full patterns string (built from all paths on lines 559–564). If some paths already exist in .gitignore, they'll be added again. Consider building patterns from newPatterns instead.

♻️ Proposed fix
   if (existsSync(gitignorePath)) {
     const content = readFileSync(gitignorePath, 'utf-8')
     
     // Check if any of the patterns already exist
     const newPatterns = filterNewPatterns(content, paths)
     
     if (newPatterns.length > 0) {
-      appendFileSync(gitignorePath, patterns)
+      const newBlock = [
+        '',
+        '# Added by dotagent: ignore exported AI rule files',
+        ...newPatterns.map(p => p.endsWith('/') ? p + '**' : p),
+        ''
+      ].join('\n')
+      appendFileSync(gitignorePath, newBlock)
       return true
     }
🤖 Fix all issues with AI agents
In `@src/cli.ts`:
- Around line 99-102: Remove or gate the ad-hoc debug console.log calls that
print color.dim(`[DEBUG] ...`) (references: repoPath, process.cwd(),
existsSync(join(..., '.agent'))) so they don't appear in normal CLI runs;
replace them by honoring a verbose flag (e.g., --verbose or a verbose boolean
parsed in the import command handler) and only call those console.log lines when
verbose is true, and apply the same change to the other debug lines using
color.dim at the other reported spots (the additional debug logs at lines
referencing the same pattern). Ensure the CLI option parsing sets a verbose
variable reachable in the import command scope and use it to gate the debug
prints instead of unconditional console.log.

In `@src/importers.ts`:
- Around line 1143-1153: The current warning logic using foundMemoryBank and
memoryBankImported produces a misleading message when the memory-bank directory
exists but tasks.md was never found; update the messages in the block that
builds warnings (the warnings array) to accurately reflect the state: when
foundMemoryBank && memoryBankImported keep the existing 'memory-bank/tasks.md
found - memory bank is available' message, but when foundMemoryBank &&
!memoryBankImported change the warning to something like 'memory-bank directory
exists but tasks.md not found or not imported' (or split into two clearer
messages if you add a separate flag for tasksMdFound); ensure you modify the
code that references foundMemoryBank and memoryBankImported so the text matches
the actual condition.
🧹 Nitpick comments (9)
src/importers.ts (3)

15-376: Massive repetition in importAll — each format block is identical boilerplate.

Every format follows the exact same try/catch + push + warnings pattern (about 30 near-identical blocks). A helper function would eliminate this duplication and make adding new formats a one-liner.

♻️ Suggested refactor
+  // Helper to run an importer and collect results/warnings/errors
+  function tryImport(path: string, importer: (p: string) => ImportResult): void {
+    if (!existsSync(path)) return
+    try {
+      const result = importer(path)
+      results.push(result)
+      if (result.warnings) {
+        warnings.push(...result.warnings)
+      }
+    } catch (e) {
+      errors.push({ file: path, error: String(e) })
+    }
+  }

   // Then replace each block with:
-  const agentDir = join(repoPath, '.agent')
-  if (existsSync(agentDir)) {
-    try {
-      const result = importAgent(agentDir)
-      results.push(result)
-      if (result.warnings) {
-        warnings.push(...result.warnings)
-      }
-    } catch (e) {
-      errors.push({ file: agentDir, error: String(e) })
-    }
-  }
+  tryImport(join(repoPath, '.agent'), importAgent)

1067-1161: importKilocode is nearly identical to importRoo (lines 965–1032) apart from memory-bank handling and the format string.

The core logic — recursive MD discovery, frontmatter parsing, segment-based ID derivation, private detection — is copy-pasted across both (and several other importers). Consider extracting a shared helper that accepts format-specific options (format name, skip-directories, etc.) to reduce duplication.


1069-1077: memoryBankImported is misleading — nothing is actually imported from the memory bank.

The variable is set to true when tasks.md exists, but the file content is never read or added to rules. The variable name suggests a side effect that doesn't occur. Consider renaming to memoryBankTasksFound or similar to match the actual semantics.

src/cli.ts (1)

434-477: importKilocode is both statically imported (line 6) and dynamically imported (line 435) — the dynamic import shadows the static one.

This works but is inconsistent: importRoo at line 473 uses the static import (not in the dynamic destructuring), while importKilocode at line 476 uses the dynamic one. Consider adding importRoo to the dynamic import or removing importKilocode from it to keep the approach uniform.

test/gitignore-all-formats.test.ts (3)

185-231: filterNewPatterns and updateGitignoreWithPaths are duplicated from src/cli.ts.

These helpers are copy-pasted from the production code. If the CLI implementation changes, the test helpers could silently diverge. Consider exporting these utilities from a shared module (e.g., src/utils/gitignore.ts) and importing them in both cli.ts and this test file.


90-107: exportedPaths in runDotAgentExport duplicates EXPORT_FORMAT_PATHS — use the constant instead.

The 'all' branch hardcodes the same list that EXPORT_FORMAT_PATHS already defines. If a new format is added to one but not the other, the test could silently pass or fail for the wrong reason.

♻️ Proposed fix
     if (format === 'all') {
       exportAll(rules, tempDir, false)
-      exportedPaths.push(
-        '.amazonq/rules/',
-        '.clinerules',
-        '.cursor/rules/',
-        '.github/copilot-instructions.md',
-        '.junie/guidelines.md',
-        '.kilocode/rules/',
-        '.roo/rules/',
-        '.rules',
-        '.windsurfrules',
-        'AGENTS.md',
-        'best_practices.md',
-        'CLAUDE.md',
-        'CONVENTIONS.md',
-        'GEMINI.md'
-      )
+      exportedPaths.push(...EXPORT_FORMAT_PATHS)
     } else {

316-329: Test name is misleading — it doesn't test failure behavior.

The test is named "fails with clear message when exportedPaths is incomplete" but it only asserts that certain paths exist in the EXPORT_FORMAT_PATHS constant. There's no test of actual failure behavior or error messages. Consider renaming to something like "EXPORT_FORMAT_PATHS includes all expected format paths".

test/export-functionality.test.ts (1)

148-172: Format mapping test only validates function existence, not actual export behavior.

This test checks typeof config.exporter === 'function' and config.path is truthy, but doesn't invoke any exporter. It serves as a documentation/registration check, which is fine, but consider noting that it doesn't replace integration tests for each format.

test/integration/kilocode.test.ts (1)

303-327: Test setup creates .agents/ directory that is irrelevant to assertions.

Lines 313–316 create .agents/common-tasks.md (note: .agents with an 's', not .agent), but no assertion references it. The test only checks warnings from importAll. This setup is dead code from a likely earlier design where importKilocode would write to .agents/common-tasks.md. Consider removing the unused setup or updating the test name/comments to clarify intent.

Comment thread src/cli.ts
Comment on lines +99 to +102
// Debug logging
console.log(color.dim(`[DEBUG] Resolved repoPath: ${repoPath}`))
console.log(color.dim(`[DEBUG] Current working directory: ${process.cwd()}`))
console.log(color.dim(`[DEBUG] .agent directory exists: ${existsSync(join(repoPath, '.agent'))}`))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove debug logging from production CLI output.

These [DEBUG] statements (also at lines 145, 150–152) will clutter the output for every user running dotagent import. They should be removed or gated behind a --verbose flag.

-      // Debug logging
-      console.log(color.dim(`[DEBUG] Resolved repoPath: ${repoPath}`))
-      console.log(color.dim(`[DEBUG] Current working directory: ${process.cwd()}`))
-      console.log(color.dim(`[DEBUG] .agent directory exists: ${existsSync(join(repoPath, '.agent'))}`))

Lines 145, 150–152 similarly:

-          console.log(color.dim(`[DEBUG] Dry-run mode: .agent directory would NOT be created`))
-          console.log(color.dim(`[DEBUG] .agent directory created at: ${agentDir}`))
-          console.log(color.dim(`[DEBUG] outputDir: ${outputDir}`))
-          console.log(color.dim(`[DEBUG] .agent exists after export: ${existsSync(join(outputDir, '.agent'))}`))
🤖 Prompt for AI Agents
In `@src/cli.ts` around lines 99 - 102, Remove or gate the ad-hoc debug
console.log calls that print color.dim(`[DEBUG] ...`) (references: repoPath,
process.cwd(), existsSync(join(..., '.agent'))) so they don't appear in normal
CLI runs; replace them by honoring a verbose flag (e.g., --verbose or a verbose
boolean parsed in the import command handler) and only call those console.log
lines when verbose is true, and apply the same change to the other debug lines
using color.dim at the other reported spots (the additional debug logs at lines
referencing the same pattern). Ensure the CLI option parsing sets a verbose
variable reachable in the import command scope and use it to gate the debug
prints instead of unconditional console.log.

Comment thread src/importers.ts
Comment on lines +1143 to +1153
// Build warnings array
const warnings: string[] = []
if (foundMemoryBank) {
if (memoryBankImported) {
// tasks.md was found, indicates memory bank is available
warnings.push('memory-bank/tasks.md found - memory bank is available')
} else {
// Memory bank exists but wasn't processed
warnings.push('memory-bank/tasks.md found but not imported')
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading warning when memory-bank directory exists without tasks.md.

When the memory-bank directory exists but tasks.md is absent inside it, foundMemoryBank will be true (set at line 1097) while memoryBankImported stays false (only set at line 1076). The warning at line 1151 will say "memory-bank/tasks.md found but not imported", which is misleading because tasks.md was never found — only the directory was.

🐛 Proposed fix
   if (foundMemoryBank) {
     if (memoryBankImported) {
       // tasks.md was found, indicates memory bank is available
       warnings.push('memory-bank/tasks.md found - memory bank is available')
     } else {
-      // Memory bank exists but wasn't processed
-      warnings.push('memory-bank/tasks.md found but not imported')
+      // Memory bank directory exists but tasks.md was not found
+      warnings.push('memory-bank directory found but tasks.md is missing')
     }
   }
🤖 Prompt for AI Agents
In `@src/importers.ts` around lines 1143 - 1153, The current warning logic using
foundMemoryBank and memoryBankImported produces a misleading message when the
memory-bank directory exists but tasks.md was never found; update the messages
in the block that builds warnings (the warnings array) to accurately reflect the
state: when foundMemoryBank && memoryBankImported keep the existing
'memory-bank/tasks.md found - memory bank is available' message, but when
foundMemoryBank && !memoryBankImported change the warning to something like
'memory-bank directory exists but tasks.md not found or not imported' (or split
into two clearer messages if you add a separate flag for tasksMdFound); ensure
you modify the code that references foundMemoryBank and memoryBankImported so
the text matches the actual condition.

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