Skip to content
Merged
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
6 changes: 5 additions & 1 deletion packages/cli/src/configurators/codex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getHooksConfig,
} from "../templates/codex/index.js";
import { ensureDir, writeFile } from "../utils/file-writer.js";
import { resolvePlaceholders } from "./shared.js";

/**
* Configure Codex by writing:
Expand Down Expand Up @@ -61,7 +62,10 @@ export async function configureCodex(cwd: string): Promise<void> {
}

// Hooks config → .codex/hooks.json
await writeFile(path.join(codexRoot, "hooks.json"), getHooksConfig());
await writeFile(
path.join(codexRoot, "hooks.json"),
resolvePlaceholders(getHooksConfig()),
);

// Config → .codex/config.toml
const config = getConfigTemplate();
Expand Down
5 changes: 4 additions & 1 deletion packages/cli/src/configurators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@ const PLATFORM_FUNCTIONS: Record<AITool, PlatformFunctions> = {
for (const hook of getCodexHooks()) {
files.set(`.codex/hooks/${hook.name}`, hook.content);
}
files.set(".codex/hooks.json", getCodexHooksConfig());
files.set(
".codex/hooks.json",
resolvePlaceholders(getCodexHooksConfig()),
);
const config = getCodexConfigTemplate();
files.set(`.codex/${config.targetPath}`, config.content);
return files;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/templates/codex/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"hooks": [
{
"type": "command",
"command": "python3 .codex/hooks/session-start.py",
"command": "{{PYTHON_CMD}} .codex/hooks/session-start.py",
"timeout": 15,
"statusMessage": "Loading Trellis context..."
}
Expand Down
27 changes: 27 additions & 0 deletions packages/cli/test/configurators/platforms.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import os from "node:os";
import {
getConfiguredPlatforms,
configurePlatform,
collectPlatformTemplates,
PLATFORM_IDS,
} from "../../src/configurators/index.js";
import { AI_TOOLS } from "../../src/types/ai-tools.js";
Expand All @@ -13,12 +14,14 @@ import {
getAllAgents as getAllCodexAgents,
getAllSkills,
getConfigTemplate as getCodexConfigTemplate,
getHooksConfig as getCodexHooksConfig,
} from "../../src/templates/codex/index.js";
import { getAllWorkflows as getAllAntigravityWorkflows } from "../../src/templates/antigravity/index.js";
import { getAllSkills as getAllKiroSkills } from "../../src/templates/kiro/index.js";
import { getAllCommands as getAllGeminiCommands } from "../../src/templates/gemini/index.js";
import { getAllSkills as getAllQoderSkills } from "../../src/templates/qoder/index.js";
import { getAllCommands as getAllCodebuddyCommands } from "../../src/templates/codebuddy/index.js";
import { resolvePlaceholders } from "../../src/configurators/shared.js";

// =============================================================================
// getConfiguredPlatforms — detects existing platform directories
Expand Down Expand Up @@ -221,6 +224,17 @@ describe("configurePlatform", () => {
expect(fs.readFileSync(configPath, "utf-8")).toBe(config.content);
});

it("configurePlatform('codex') resolves PYTHON_CMD in hooks.json", async () => {
await configurePlatform("codex", tmpDir);

const hooksPath = path.join(tmpDir, ".codex", "hooks.json");
expect(fs.existsSync(hooksPath)).toBe(true);
const content = fs.readFileSync(hooksPath, "utf-8");
const expectedPythonCmd = process.platform === "win32" ? "python" : "python3";
expect(content).toContain(`"command": "${expectedPythonCmd} .codex/hooks/session-start.py"`);
expect(content).not.toContain("{{PYTHON_CMD}}");
});

it("configurePlatform('kiro') creates .kiro/skills directory", async () => {
await configurePlatform("kiro", tmpDir);
expect(fs.existsSync(path.join(tmpDir, ".kiro", "skills"))).toBe(true);
Expand Down Expand Up @@ -463,4 +477,17 @@ describe("configurePlatform", () => {
}
}
});

it("collectPlatformTemplates('codex') resolves placeholders in hooks.json", () => {
const templates = collectPlatformTemplates("codex");
expect(templates).toBeInstanceOf(Map);
expect(templates?.get(".codex/hooks.json")).toBe(
resolvePlaceholders(getCodexHooksConfig()),
);
});

it("codex hooks.json template keeps PYTHON_CMD placeholder", () => {
const rawTemplate = getCodexHooksConfig();
expect(rawTemplate).toContain("{{PYTHON_CMD}} .codex/hooks/session-start.py");
});
});
Loading