Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/agents/src/__tests__/adapters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ const ALL_AGENTS = AgentType.options;

describe('Agent Adapters', () => {
describe('getAllAdapters', () => {
it('should return all 44 registered adapters', () => {
it('should return all 45 registered adapters', () => {
const adapters = getAllAdapters();
expect(adapters).toBeInstanceOf(Array);
expect(adapters.length).toBe(44);
expect(adapters.length).toBe(45);
});

it('should include common agents', () => {
Expand Down
11 changes: 0 additions & 11 deletions packages/agents/src/__tests__/clawdbot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,16 +236,6 @@ describe('ClawdbotAdapter', () => {
});

describe('isDetected', () => {
it('should detect Clawdbot from workspace skills directory', async () => {
mockExistsSync.mockImplementation((path) => {
return path === join(process.cwd(), 'skills');
});

const detected = await adapter.isDetected();

expect(detected).toBe(true);
});

it('should detect Clawdbot from global directory', async () => {
mockExistsSync.mockImplementation((path) => {
return path === join(homedir(), '.clawdbot');
Expand Down Expand Up @@ -287,7 +277,6 @@ describe('ClawdbotAdapter', () => {

await adapter.isDetected();

expect(mockExistsSync).toHaveBeenCalledWith(join(process.cwd(), 'skills'));
expect(mockExistsSync).toHaveBeenCalledWith(join(homedir(), '.clawdbot'));
expect(mockExistsSync).toHaveBeenCalledWith(join(process.cwd(), 'clawdbot.json'));
});
Expand Down
9 changes: 4 additions & 5 deletions packages/agents/src/clawdbot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const config = AGENT_CONFIG.clawdbot;

export class ClawdbotAdapter implements AgentAdapter {
readonly type: AgentType = 'clawdbot';
readonly name = 'Clawdbot';
readonly skillsDir = config.skillsDir;
readonly configFile = config.configFile;
readonly name: string = 'Clawdbot';
readonly skillsDir: string = config.skillsDir;
readonly configFile: string = config.configFile;

generateConfig(skills: Skill[]): string {
const enabledSkills = skills.filter(s => s.enabled);
Expand Down Expand Up @@ -69,10 +69,9 @@ ${skillsXml}
}

async isDetected(): Promise<boolean> {
const projectSkills = join(process.cwd(), 'skills');
const globalClawdbot = join(homedir(), '.clawdbot');
const clawdbotConfig = join(process.cwd(), 'clawdbot.json');

return existsSync(projectSkills) || existsSync(globalClawdbot) || existsSync(clawdbotConfig);
return existsSync(globalClawdbot) || existsSync(clawdbotConfig);
}
}
4 changes: 4 additions & 0 deletions packages/agents/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { OpenCodeAdapter } from './opencode.js';
import { AntigravityAdapter } from './antigravity.js';
import { AmpAdapter } from './amp.js';
import { ClawdbotAdapter } from './clawdbot.js';
import { OpenClawAdapter } from './openclaw.js';
import { DroidAdapter } from './droid.js';
import { FactoryAdapter } from './factory.js';
import { GitHubCopilotAdapter } from './github-copilot.js';
Expand All @@ -29,6 +30,7 @@ export * from './opencode.js';
export * from './antigravity.js';
export * from './amp.js';
export * from './clawdbot.js';
export * from './openclaw.js';
export * from './droid.js';
export * from './factory.js';
export * from './github-copilot.js';
Expand All @@ -53,6 +55,7 @@ const adapters: Record<AgentType, AgentAdapter> = {
antigravity: new AntigravityAdapter(),
amp: new AmpAdapter(),
clawdbot: new ClawdbotAdapter(),
openclaw: new OpenClawAdapter(),
droid: new DroidAdapter(),
'github-copilot': new GitHubCopilotAdapter(),
goose: new GooseAdapter(),
Expand Down Expand Up @@ -120,6 +123,7 @@ export async function detectAgent(): Promise<AgentType> {
'opencode',
'antigravity',
'amp',
'openclaw',
'clawdbot',
'droid',
'github-copilot',
Expand Down
22 changes: 22 additions & 0 deletions packages/agents/src/openclaw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import { homedir } from 'node:os';
import { ClawdbotAdapter } from './clawdbot.js';
import type { AgentType } from '@skillkit/core';
import { AGENT_CONFIG } from '@skillkit/core';

const config = AGENT_CONFIG.openclaw;

export class OpenClawAdapter extends ClawdbotAdapter {
override readonly type: AgentType = 'openclaw';
override readonly name = 'OpenClaw';
override readonly skillsDir = config.skillsDir;
override readonly configFile = config.configFile;

override async isDetected(): Promise<boolean> {
const globalOpenClaw = join(homedir(), '.openclaw');
const openclawConfig = join(process.cwd(), 'openclaw.json');

return existsSync(globalOpenClaw) || existsSync(openclawConfig);
}
}
17 changes: 15 additions & 2 deletions packages/core/src/agent-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,29 @@ export const AGENT_CONFIG: Record<AgentType, AgentDirectoryConfig> = {
supportsAutoDiscovery: true,
},

// Clawdbot
clawdbot: {
skillsDir: '.clawdbot/skills',
configFile: 'AGENTS.md',
altSkillsDirs: ['skills'],
altSkillsDirs: ['skills', '~/.clawdbot/skills'],
configFormat: 'xml',
usesFrontmatter: true,
supportsAutoDiscovery: true,
},

openclaw: {
skillsDir: 'skills',
configFile: 'CLAUDE.md',
altSkillsDirs: ['~/.openclaw/skills'],
globalSkillsDir: '~/.openclaw/skills',
configFormat: 'xml',
usesFrontmatter: true,
frontmatterFields: [
'name', 'description', 'version', 'scan_exempt',
'permissions', 'triggers', 'metadata',
],
supportsAutoDiscovery: true,
},
Comment on lines +123 to +135
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 openclaw in MethodologyManager's hardcoded agent directories causes throw on skill sync

The PR adds openclaw as a new AgentType and registers it in most agent maps, but fails to update the hardcoded agentDirs record inside MethodologyManager.writeSkillToAgent() at packages/core/src/methodology/manager.ts:510-528. When writeSkillToAgent is called with agent='openclaw', the lookup agentDirs[agent] returns undefined, causing line 531-532 to throw "Unknown agent: openclaw". This breaks methodology skill syncing for the openclaw agent.

Affected hardcoded list in manager.ts

Additionally, detectAgents() at packages/core/src/methodology/manager.ts:556-575 has a similar hardcoded list that also lacks openclaw, so the methodology manager won't auto-detect openclaw and won't include it in automatic sync operations.

Prompt for agents
The new 'openclaw' agent type was added to AgentType, AGENT_CONFIG, and most agent registries, but was not added to the hardcoded agent directory mappings in packages/core/src/methodology/manager.ts. Two places need updating:

1. writeSkillToAgent() (line ~510-528): The agentDirs Record needs an entry for openclaw. Based on AGENT_CONFIG.openclaw.skillsDir being 'skills', add: openclaw: 'skills'

2. detectAgents() (line ~556-575): The agentDirs array needs an entry for openclaw. Based on the .openclaw directory convention, add: ['openclaw', '.openclaw']

Both of these are in the MethodologyManager class in packages/core/src/methodology/manager.ts. Without these additions, methodology skill syncing will throw an error for the openclaw agent, and openclaw won't be auto-detected for methodology syncing.
Open in Devin Review

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


// Droid (Factory)
droid: {
skillsDir: '.factory/skills',
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/agents/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ export const AGENT_DISCOVERY_PATHS: Record<AgentType, string[]> = {
'antigravity': ['.antigravity/agents'],
'amp': ['.amp/agents'],
'clawdbot': ['.clawdbot/agents', 'agents'],
'openclaw': ['agents', '.openclaw/agents'],
'droid': ['.droid/agents'],
'github-copilot': ['.github/agents', '.github/instructions', '.github/custom-agents'],
'goose': ['.goose/agents'],
Expand Down Expand Up @@ -277,6 +278,7 @@ export const ALL_AGENT_DISCOVERY_PATHS = [
'.cline/agents',
'.clawdbot/agents',
'.codebuddy/agents',
'.openclaw/agents',
'.codex/agents',
'.commandcode/agents',
'.continue/agents',
Expand Down Expand Up @@ -336,6 +338,7 @@ export const CUSTOM_AGENT_FORMAT_MAP: Record<AgentType, AgentFormatCategory> = {
'antigravity': 'claude-agent',
'amp': 'claude-agent',
'clawdbot': 'claude-agent',
'openclaw': 'claude-agent',
'droid': 'claude-agent',
'github-copilot': 'universal',
'goose': 'claude-agent',
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/commands/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ const AGENT_FORMATS: Record<AgentType, AgentCommandFormat> = {
supportsSlashCommands: true,
supportsCommandFiles: true,
},
openclaw: {
agent: 'openclaw',
extension: '.md',
directory: '.claude/commands',
supportsSlashCommands: true,
supportsCommandFiles: true,
},
droid: {
agent: 'droid',
extension: '.md',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/translator/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const AGENT_FORMAT_MAP: Record<AgentType, FormatCategory> = {
'antigravity': 'skill-md',
'amp': 'skill-md',
'clawdbot': 'skill-md',
'openclaw': 'skill-md',
'droid': 'skill-md',
'goose': 'skill-md',
'kilo': 'skill-md',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const AgentType = z.enum([
"gemini-cli",
"amp",
"clawdbot",
"openclaw",
"droid",
"github-copilot",
"goose",
Expand Down
Loading