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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file, per [the Ke

## [Unreleased]

### Changed

- Write Claude Code project context to `CLAUDE.local.md` instead of `CLAUDE.md`, so teams with a committed `CLAUDE.md` are no longer affected. `CLAUDE.local.md` is Claude Code's native local-override file for machine-specific, uncommitted instructions (props [@rickalee](https://github.com/rickalee) via [#77](https://github.com/10up/localwp-agent-tools/issues/77)).
- On first enable or regenerate, any Agent Tools marker block previously written to `CLAUDE.md` is automatically migrated out (the block is removed, leaving the rest of `CLAUDE.md` intact).

## [0.2.1] - 2026-03-19

### Fixed
Expand Down
39 changes: 35 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
findWpCli,
} from './helpers/paths';
import { SiteConfig, SiteConfigRegistry } from './helpers/site-config';
import { findAvailablePort, savePort, removePortFile, removePortFileSync } from './helpers/port';

Check warning on line 14 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

'removePortFile' is defined but never used
import { createMcpHttpServer, startMcpHttpServer, stopMcpHttpServer, closeSessionsForSite } from './mcp-server';
import { LocalApi } from './tools';

Expand Down Expand Up @@ -46,8 +46,8 @@
label: 'Claude Code',
mcpConfigPath: '.mcp.json',
mcpConfigTopLevelKey: 'mcpServers',
contextFilePath: 'CLAUDE.md',
gitignoreEntries: ['.mcp.json', 'CLAUDE.md'],
contextFilePath: 'CLAUDE.local.md',
gitignoreEntries: ['.mcp.json', 'CLAUDE.local.md'],
},
cursor: {
label: 'Cursor',
Expand Down Expand Up @@ -185,7 +185,7 @@
* Builds the MCP server entry for a specific agent.
* Each agent has different JSON shapes for HTTP MCP servers.
*/
function buildMcpServerEntry(agent: AgentTarget, port: number, siteId: string): Record<string, any> {

Check warning on line 188 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const url = `http://localhost:${port}/sites/${siteId}/mcp`;

switch (agent) {
Expand All @@ -207,10 +207,10 @@
*/
async function mergeMcpConfig(
configPath: string,
serverEntry: Record<string, any>,

Check warning on line 210 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
topLevelKey: string,
): Promise<void> {
let existing: any = {};

Check warning on line 213 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type

if (await fs.pathExists(configPath)) {
try {
Expand Down Expand Up @@ -397,11 +397,32 @@
await fs.writeFile(gitignorePath, content, 'utf-8');
}

// ---------------------------------------------------------------------------
// Migration Helpers
// ---------------------------------------------------------------------------

/**
* Removes any Agent Tools marker block from CLAUDE.md left by older versions
* that wrote context there instead of CLAUDE.local.md.
*/
async function migrateClaude(projectPath: string): Promise<void> {
const legacyPath = path.join(projectPath, 'CLAUDE.md');
if (!(await fs.pathExists(legacyPath))) return;

const content = await fs.readFile(legacyPath, 'utf-8');
const markerRegex = new RegExp(
`${escapeRegex(CONTEXT_MARKER_START)}[\\s\\S]*?${escapeRegex(CONTEXT_MARKER_END)}`,
);
if (!markerRegex.test(content)) return;

await removeContextFile(legacyPath, 'claude');
}

// ---------------------------------------------------------------------------
// Core Functions
// ---------------------------------------------------------------------------

async function setupSite(site: Local.Site, notifier: any, projectDir: string, agents: AgentTarget[]): Promise<void> {

Check warning on line 425 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const sitePath = getSitePath(site);
const projectPath = getProjectPath(sitePath, projectDir);

Expand All @@ -415,10 +436,15 @@
const siteConfig = await buildSiteConfig(site);
siteConfigRegistry.register(siteConfig);

// 2. Generate project context
// 2. Migrate legacy CLAUDE.md content to CLAUDE.local.md (no-op if already clean)
if (agents.includes('claude')) {
await migrateClaude(projectPath);
}

// 3. Generate project context
const contextContent = generateProjectContext(site);

// 3. For each selected agent, write configs
// 4. For each selected agent, write configs
for (const agent of agents) {
const agentConfig = AGENT_TARGETS[agent];

Expand Down Expand Up @@ -453,7 +479,7 @@
});
}

async function teardownSite(site: Local.Site, notifier: any): Promise<void> {

Check warning on line 482 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const sitePath = getSitePath(site);
const projectDir = getStoredProjectDir(site);
const projectPath = getProjectPath(sitePath, projectDir);
Expand Down Expand Up @@ -492,7 +518,7 @@
});
}

async function changeProjectDir(site: Local.Site, newProjectDir: string, notifier: any): Promise<void> {

Check warning on line 521 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const sitePath = getSitePath(site);
const oldProjectDir = getStoredProjectDir(site);
const oldPath = getProjectPath(sitePath, oldProjectDir);
Expand Down Expand Up @@ -541,7 +567,7 @@
});
}

async function updateAgents(site: Local.Site, newAgents: AgentTarget[], notifier: any): Promise<void> {

Check warning on line 570 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
if (!isAgentToolsEnabled(site)) return;

const sitePath = getSitePath(site);
Expand Down Expand Up @@ -607,6 +633,11 @@
const siteConfig = await buildSiteConfig(site);
siteConfigRegistry.register(siteConfig);

// Migrate legacy CLAUDE.md content on regenerate (no-op if already clean)
if (agents.includes('claude')) {
await migrateClaude(projectPath);
}

const contextContent = generateProjectContext(site);

for (const agent of agents) {
Expand Down
Loading