Skip to content
Open
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
3 changes: 2 additions & 1 deletion src/compiler/plugin-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ export function resolvePlugins(
root: string,
logger: Logger,
pluginsOutputDir?: string,
pluginName?: string,
): CompilerPlugin[] {
return names.map((name) => {
const Constructor = PLUGINS[name];
if (!Constructor) {
const available = Object.keys(PLUGINS).join(", ");
throw new Error(`Unknown plugin: "${name}". Available plugins: ${available}`);
}
return new Constructor({ root, logger, pluginsOutputDir });
return new Constructor({ root, logger, pluginsOutputDir, pluginName });
});
}
9 changes: 5 additions & 4 deletions src/compiler/plugins/claude-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ import type { CompilerPlugin, PluginOptions } from "./types.js";
* Claude Code compiler plugin.
*
* Takes a pure agent profile and wraps it with Claude Code YAML
* frontmatter, then writes it to `plugins/praxis/agents/`.
* frontmatter, then writes it to `plugins/{pluginName}/agents/`.
*/
export class ClaudeCodePlugin implements CompilerPlugin {
readonly name = "claude-code";

private readonly outputDir: string;

constructor({ root, pluginsOutputDir }: PluginOptions) {
constructor({ root, pluginsOutputDir, pluginName }: PluginOptions) {
const name = pluginName ?? "praxis";
this.outputDir = pluginsOutputDir
? join(pluginsOutputDir, "praxis", "agents")
: join(root, "plugins", "praxis", "agents");
? join(pluginsOutputDir, name, "agents")
: join(root, "plugins", name, "agents");
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/compiler/plugins/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ export interface PluginOptions {
root: string;
logger: Logger;
pluginsOutputDir?: string;
pluginName?: string;
}
1 change: 1 addition & 0 deletions src/compiler/role-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export class RoleCompiler {
this.root,
this.logger,
this.config.pluginsOutputDir,
this.config.pluginName,
);
for (const plugin of plugins) {
plugin.compile(profile, metadata, roleAlias);
Expand Down
8 changes: 8 additions & 0 deletions src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface RawConfig {
rolesDir?: string;
responsibilitiesDir?: string;
pluginsOutputDir?: string;
pluginName?: string;
}

const DEFAULT_CONFIG: Required<RawConfig> = {
Expand All @@ -19,6 +20,7 @@ const DEFAULT_CONFIG: Required<RawConfig> = {
rolesDir: "roles",
responsibilitiesDir: "responsibilities",
pluginsOutputDir: "./plugins",
pluginName: "praxis",
};

/**
Expand Down Expand Up @@ -80,6 +82,11 @@ export class PraxisConfig {
return resolve(this.root, this.data.pluginsOutputDir);
}

/** Name used for the plugin subdirectory (e.g. "praxis" or "canon"). */
get pluginName(): string {
return this.data.pluginName;
}

private load(): Required<RawConfig> {
const configPath = join(this.root, CONFIG_FILE);

Expand All @@ -96,6 +103,7 @@ export class PraxisConfig {
rolesDir: raw.rolesDir ?? DEFAULT_CONFIG.rolesDir,
responsibilitiesDir: raw.responsibilitiesDir ?? DEFAULT_CONFIG.responsibilitiesDir,
pluginsOutputDir: raw.pluginsOutputDir ?? DEFAULT_CONFIG.pluginsOutputDir,
pluginName: raw.pluginName ?? DEFAULT_CONFIG.pluginName,
};
}
}