diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 03e5cc5..0ab15ac 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -127,7 +127,7 @@ jobs:
for sd in .claude/skills .cursor/skills .codex/skills .opencode/skills \
.windsurf/skills .cline/skills .roo/skills .continue/skills \
.gemini/skills .amazonq/skills .qwen/skills .kilocode/skills \
- .augment/skills .kiro/skills .lingma/skills .junie/skills \
+ .augment/skills .kiro/skills .kimi-code/skills .lingma/skills .junie/skills \
.codebuddy/skills .cospec/skills .crush/skills .factory/skills \
.iflow/skills .pi/skills .qoder/skills .agents/skills \
.bob/skills .forge/skills .trae/skills .github/skills; do
@@ -138,7 +138,7 @@ jobs:
check_file "$PROJ/$sd/comet/scripts/comet-yaml-validate.sh"
check_file "$PROJ/$sd/comet/scripts/comet-archive.sh"
done
- echo "All 28 platforms project Comet skills: OK"
+ echo "All 29 platforms project Comet skills: OK"
shell: bash
- name: Verify external installer status (project)
@@ -215,7 +215,7 @@ jobs:
for sd in .claude/skills .cursor/skills .codex/skills .config/opencode/skills \
.windsurf/skills .cline/skills .roo/skills .continue/skills \
.gemini/skills .amazonq/skills .qwen/skills .kilocode/skills \
- .augment/skills .kiro/skills .lingma/skills .junie/skills \
+ .augment/skills .kiro/skills .kimi-code/skills .lingma/skills .junie/skills \
.codebuddy/skills .cospec/skills .crush/skills .factory/skills \
.iflow/skills .pi/skills .qoder/skills .gemini/antigravity/skills \
.bob/skills .forge/skills .trae/skills .github/skills; do
@@ -226,7 +226,7 @@ jobs:
check_file "$HOME_DIR/$sd/comet/scripts/comet-yaml-validate.sh"
check_file "$HOME_DIR/$sd/comet/scripts/comet-archive.sh"
done
- echo "All 28 platforms global Comet skills: OK"
+ echo "All 29 platforms global Comet skills: OK"
shell: bash
- name: Verify external installer status (global)
diff --git a/README-zh.md b/README-zh.md
index e3d06b6..213ffbf 100644
--- a/README-zh.md
+++ b/README-zh.md
@@ -219,13 +219,14 @@ npx skills add rpamis/comet
| GitHub Copilot | `.github/` | Gemini CLI | `.gemini/` |
| Amazon Q Developer | `.amazonq/` | Qwen Code | `.qwen/` |
| Kilo Code | `.kilocode/` | Auggie | `.augment/` |
-| Kiro | `.kiro/` | Lingma | `.lingma/` |
-| Junie | `.junie/` | CodeBuddy | `.codebuddy/` |
-| CoStrict | `.cospec/` | Crush | `.crush/` |
-| Factory Droid | `.factory/` | iFlow | `.iflow/` |
-| Pi | `.pi/` | Qoder | `.qoder/` |
-| Antigravity | `.agents/` | Bob Shell | `.bob/` |
-| ForgeCode | `.forge/` | Trae | `.trae/` |
+| Kimi Code | `.kimi-code/`| Kiro | `.kiro/` |
+| Lingma | `.lingma/` | Junie | `.junie/` |
+| CodeBuddy | `.codebuddy/`| CoStrict | `.cospec/` |
+| Crush | `.crush/` | Factory Droid | `.factory/` |
+| iFlow | `.iflow/` | Pi | `.pi/` |
+| Qoder | `.qoder/` | Antigravity | `.agents/` |
+| Bob Shell | `.bob/` | ForgeCode | `.forge/` |
+| Trae | `.trae/` | | |
diff --git a/README.md b/README.md
index afa2bb7..f44ae6d 100644
--- a/README.md
+++ b/README.md
@@ -224,7 +224,7 @@ Updates the npm package and refreshes installed Comet skills in detected project
## Supported Platforms
-`comet init` supports 28 AI coding platforms:
+`comet init` supports 29 AI coding platforms:
View full platform list
@@ -238,13 +238,14 @@ Updates the npm package and refreshes installed Comet skills in detected project
| GitHub Copilot | `.github/` | Gemini CLI | `.gemini/` |
| Amazon Q Developer | `.amazonq/` | Qwen Code | `.qwen/` |
| Kilo Code | `.kilocode/` | Auggie | `.augment/` |
-| Kiro | `.kiro/` | Lingma | `.lingma/` |
-| Junie | `.junie/` | CodeBuddy | `.codebuddy/` |
-| CoStrict | `.cospec/` | Crush | `.crush/` |
-| Factory Droid | `.factory/` | iFlow | `.iflow/` |
-| Pi | `.pi/` | Qoder | `.qoder/` |
-| Antigravity | `.agents/` | Bob Shell | `.bob/` |
-| ForgeCode | `.forge/` | Trae | `.trae/` |
+| Kimi Code | `.kimi-code/`| Kiro | `.kiro/` |
+| Lingma | `.lingma/` | Junie | `.junie/` |
+| CodeBuddy | `.codebuddy/`| CoStrict | `.cospec/` |
+| Crush | `.crush/` | Factory Droid | `.factory/` |
+| iFlow | `.iflow/` | Pi | `.pi/` |
+| Qoder | `.qoder/` | Antigravity | `.agents/` |
+| Bob Shell | `.bob/` | ForgeCode | `.forge/` |
+| Trae | `.trae/` | | |
diff --git a/src/core/platforms.ts b/src/core/platforms.ts
index db14527..b57f8ab 100644
--- a/src/core/platforms.ts
+++ b/src/core/platforms.ts
@@ -198,6 +198,13 @@ export const PLATFORMS: Platform[] = [
supportsHooks: true,
hookFormat: 'kiro',
},
+ {
+ id: 'kimicode',
+ name: 'Kimi Code',
+ skillsDir: '.kimi-code',
+ globalSkillsDir: '.kimi-code',
+ openspecToolId: 'kimi',
+ },
{
id: 'lingma',
name: 'Lingma',
diff --git a/src/core/superpowers.ts b/src/core/superpowers.ts
index 10ff8d8..9eb3dad 100644
--- a/src/core/superpowers.ts
+++ b/src/core/superpowers.ts
@@ -23,6 +23,7 @@ const SKILLS_AGENT_MAP: Record = {
kilocode: 'kilo',
auggie: 'augment',
kiro: 'kiro-cli',
+ kimicode: 'kimi-code-cli',
lingma: null,
junie: 'junie',
codebuddy: 'codebuddy',
diff --git a/test/ts/ci-workflows.test.ts b/test/ts/ci-workflows.test.ts
index e05172a..dca910b 100644
--- a/test/ts/ci-workflows.test.ts
+++ b/test/ts/ci-workflows.test.ts
@@ -35,8 +35,8 @@ describe('CI workflows', () => {
expect(workflow).not.toContain('check_glob "$HOME_DIR/$sd/openspec-*"');
expect(workflow).not.toContain('check_dir "$HOME_DIR/$sd/brainstorming"');
expect(workflow).not.toContain('check_dir "$HOME_DIR/$sd/using-superpowers"');
- expect(workflow).toContain('All 28 platforms project Comet skills: OK');
- expect(workflow).toContain('All 28 platforms global Comet skills: OK');
+ expect(workflow).toContain('All 29 platforms project Comet skills: OK');
+ expect(workflow).toContain('All 29 platforms global Comet skills: OK');
});
it('defines PR title linting with Comet-specific semantic scopes', async () => {
diff --git a/test/ts/detect.test.ts b/test/ts/detect.test.ts
index 09a56bc..4fa5c42 100644
--- a/test/ts/detect.test.ts
+++ b/test/ts/detect.test.ts
@@ -43,6 +43,15 @@ describe('detect', () => {
});
describe('platform global skills directories', () => {
+ it('declares Kimi Code global skills under the user .kimi-code directory', () => {
+ const kimicode = PLATFORMS.find((platform) => platform.id === 'kimicode');
+
+ expect(kimicode).toBeDefined();
+ expect(kimicode?.skillsDir).toBe('.kimi-code');
+ expect(kimicode?.globalSkillsDir).toBe('.kimi-code');
+ expect(kimicode?.openspecToolId).toBe('kimi');
+ });
+
it('declares Lingma global skills under the user .lingma directory', () => {
const lingma = PLATFORMS.find((platform) => platform.id === 'lingma');
@@ -75,10 +84,12 @@ describe('detect', () => {
it('detects multiple platforms', async () => {
await fs.mkdir(path.join(tmpDir, '.claude'));
await fs.mkdir(path.join(tmpDir, '.cursor'));
+ await fs.mkdir(path.join(tmpDir, '.kimi-code'));
const detected = await detectPlatforms(tmpDir);
expect(detected.has('claude')).toBe(true);
expect(detected.has('cursor')).toBe(true);
- expect(detected.size).toBeGreaterThanOrEqual(2);
+ expect(detected.has('kimicode')).toBe(true);
+ expect(detected.size).toBeGreaterThanOrEqual(3);
});
it('returns empty set when no platforms detected', async () => {
diff --git a/test/ts/init-e2e.test.ts b/test/ts/init-e2e.test.ts
index f12d254..96eba8d 100644
--- a/test/ts/init-e2e.test.ts
+++ b/test/ts/init-e2e.test.ts
@@ -191,7 +191,7 @@ describe('comet init E2E', () => {
const { initCommand } = await import('../../src/commands/init.js');
const result = await captureJsonOutput(() => initCommand(tmpDir, { yes: true, json: true }));
- expect((result.results as unknown[]).length).toBeGreaterThanOrEqual(28);
+ expect((result.results as unknown[]).length).toBeGreaterThanOrEqual(29);
const manifest = await readManifest();
const platformDirs = [
@@ -209,6 +209,7 @@ describe('comet init E2E', () => {
'.kilocode',
'.augment',
'.kiro',
+ '.kimi-code',
'.lingma',
'.junie',
'.codebuddy',
@@ -321,4 +322,31 @@ describe('comet init E2E', () => {
fs.access(path.join(tmpDir, '.lingma', 'skills', 'comet', 'SKILL.md')),
).rejects.toThrow();
}, 20_000);
+
+ it('installs Kimi Code global Comet skills to the user Kimi Code skills directory', async () => {
+ mockExternalSuccess();
+
+ await fs.mkdir(path.join(tmpDir, '.kimi-code'), { recursive: true });
+ const fakeHome = path.join(tmpDir, 'fake-home');
+ await fs.mkdir(fakeHome, { recursive: true });
+
+ vi.spyOn(os, 'homedir').mockReturnValue(fakeHome);
+
+ const { initCommand } = await import('../../src/commands/init.js');
+ const result = await captureJsonOutput(() =>
+ initCommand(tmpDir, { yes: true, scope: 'global', json: true }),
+ );
+
+ expect(result.selectedPlatforms).toEqual(['kimicode']);
+
+ const manifest = await readManifest();
+ for (const skillPath of manifest.skills) {
+ const dest = path.join(fakeHome, '.kimi-code', 'skills', skillPath);
+ await expect(fs.access(dest)).resolves.toBeUndefined();
+ }
+
+ await expect(
+ fs.access(path.join(tmpDir, '.kimi-code', 'skills', 'comet', 'SKILL.md')),
+ ).rejects.toThrow();
+ }, 20_000);
});
diff --git a/test/ts/openspec.test.ts b/test/ts/openspec.test.ts
index 2cd4a11..59d7234 100644
--- a/test/ts/openspec.test.ts
+++ b/test/ts/openspec.test.ts
@@ -39,6 +39,25 @@ describe('openspec', () => {
});
describe('installOpenSpec', () => {
+ it('accepts the Kimi OpenSpec tool id from platform definitions', async () => {
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('/usr/bin/openspec'));
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('ok'));
+
+ const { installOpenSpec } = await import('../../src/core/openspec.js');
+ const result = await installOpenSpec('/tmp/test', ['kimi'], 'project');
+
+ expect(result).toBe('installed');
+ expect(mockedExecFileSync.mock.calls[1][0]).toBe('openspec');
+ expect(mockedExecFileSync.mock.calls[1][1]).toEqual([
+ 'init',
+ '/tmp/test',
+ '--tools',
+ 'kimi',
+ '--profile',
+ 'custom',
+ ]);
+ });
+
it('installs openspec when CLI is available', async () => {
mockedExecFileSync.mockReturnValueOnce(Buffer.from('/usr/bin/openspec'));
mockedExecFileSync.mockReturnValueOnce(Buffer.from('ok'));
diff --git a/test/ts/superpowers.test.ts b/test/ts/superpowers.test.ts
index d3376fb..3243c5d 100644
--- a/test/ts/superpowers.test.ts
+++ b/test/ts/superpowers.test.ts
@@ -53,6 +53,7 @@ describe('superpowers', () => {
expect(SKILLS_AGENT_MAP['gemini']).toBe('gemini-cli');
expect(SKILLS_AGENT_MAP['qwen']).toBe('qwen-code');
expect(SKILLS_AGENT_MAP['kiro']).toBe('kiro-cli');
+ expect(SKILLS_AGENT_MAP['kimicode']).toBe('kimi-code-cli');
expect(SKILLS_AGENT_MAP['iflow']).toBe('iflow-cli');
expect(SKILLS_AGENT_MAP['factory']).toBe('droid');
expect(SKILLS_AGENT_MAP['amazon-q']).toBe('universal');
@@ -60,7 +61,7 @@ describe('superpowers', () => {
expect(SKILLS_AGENT_MAP['lingma']).toBeNull();
});
- it('has entries for all 28 platforms', async () => {
+ it('has entries for all 29 platforms', async () => {
const { SKILLS_AGENT_MAP } = await import('../../src/core/superpowers.js');
const platformIds = [
'claude',
@@ -78,6 +79,7 @@ describe('superpowers', () => {
'kilocode',
'auggie',
'kiro',
+ 'kimicode',
'lingma',
'junie',
'codebuddy',
@@ -95,7 +97,7 @@ describe('superpowers', () => {
for (const id of platformIds) {
expect(SKILLS_AGENT_MAP).toHaveProperty(id);
}
- expect(Object.keys(SKILLS_AGENT_MAP)).toHaveLength(28);
+ expect(Object.keys(SKILLS_AGENT_MAP)).toHaveLength(29);
});
});