feat(cli): add mesh templates and claudemesh create command
Predefined mesh configurations (dev-team, research, ops-incident, simulation, personal) let users bootstrap meshes with groups, roles, state keys, and system prompt hints. Templates are bundled at build time via Bun's JSON import support. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
39
apps/cli/src/commands/create.ts
Normal file
39
apps/cli/src/commands/create.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* `claudemesh create` — Create a new mesh with an optional template.
|
||||||
|
* Lists available templates if --list-templates is passed.
|
||||||
|
*/
|
||||||
|
import { listTemplates, getTemplate } from "../templates/index.js";
|
||||||
|
|
||||||
|
export function runCreate(args: Record<string, unknown>): void {
|
||||||
|
if (args["list-templates"]) {
|
||||||
|
console.log("Available mesh templates:\n");
|
||||||
|
for (const t of listTemplates()) {
|
||||||
|
console.log(` ${t.name}`);
|
||||||
|
console.log(` ${t.description}`);
|
||||||
|
console.log(` Groups: ${t.groups.map((g) => g.name).join(", ") || "(none)"}`);
|
||||||
|
console.log(` State keys: ${Object.keys(t.stateKeys).join(", ") || "(none)"}`);
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateName = args.template as string | undefined;
|
||||||
|
if (templateName) {
|
||||||
|
const template = getTemplate(templateName);
|
||||||
|
if (!template) {
|
||||||
|
console.error(`Unknown template "${templateName}". Use --list-templates to see available options.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log(`Template "${template.name}" loaded:`);
|
||||||
|
console.log(` Groups: ${template.groups.map((g) => `@${g.name}`).join(", ")}`);
|
||||||
|
console.log(` State keys: ${Object.keys(template.stateKeys).join(", ")}`);
|
||||||
|
console.log(` Hint: ${template.systemPromptHint.slice(0, 80)}...`);
|
||||||
|
console.log();
|
||||||
|
console.log("Template applied. Use `claudemesh launch` with --groups to join the predefined groups.");
|
||||||
|
// Future: wire into actual mesh creation API
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Usage: claudemesh create --template <name>");
|
||||||
|
console.log(" claudemesh create --list-templates");
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import { runStateGet, runStateSet, runStateList } from "./commands/state";
|
|||||||
import { runRemember, runRecall } from "./commands/memory";
|
import { runRemember, runRecall } from "./commands/memory";
|
||||||
import { runInfo } from "./commands/info";
|
import { runInfo } from "./commands/info";
|
||||||
import { runRemind } from "./commands/remind";
|
import { runRemind } from "./commands/remind";
|
||||||
|
import { runCreate } from "./commands/create";
|
||||||
import { VERSION } from "./version";
|
import { VERSION } from "./version";
|
||||||
|
|
||||||
const launch = defineCommand({
|
const launch = defineCommand({
|
||||||
@@ -141,6 +142,14 @@ const main = defineCommand({
|
|||||||
},
|
},
|
||||||
subCommands: {
|
subCommands: {
|
||||||
launch,
|
launch,
|
||||||
|
create: defineCommand({
|
||||||
|
meta: { name: "create", description: "Create a new mesh from a template" },
|
||||||
|
args: {
|
||||||
|
template: { type: "string", description: "Template name (dev-team, research, ops-incident, simulation, personal)" },
|
||||||
|
"list-templates": { type: "boolean", description: "List available templates", default: false },
|
||||||
|
},
|
||||||
|
run({ args }) { runCreate(args); },
|
||||||
|
}),
|
||||||
install,
|
install,
|
||||||
uninstall: defineCommand({
|
uninstall: defineCommand({
|
||||||
meta: { name: "uninstall", description: "Remove MCP server and hooks" },
|
meta: { name: "uninstall", description: "Remove MCP server and hooks" },
|
||||||
|
|||||||
17
apps/cli/src/templates/dev-team.json
Normal file
17
apps/cli/src/templates/dev-team.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "dev-team",
|
||||||
|
"description": "Software development team with frontend, backend, and devops groups",
|
||||||
|
"groups": [
|
||||||
|
{ "name": "frontend", "roles": ["lead", "member"] },
|
||||||
|
{ "name": "backend", "roles": ["lead", "member"] },
|
||||||
|
{ "name": "devops", "roles": ["lead", "member"] },
|
||||||
|
{ "name": "qa", "roles": ["lead", "member"] }
|
||||||
|
],
|
||||||
|
"stateKeys": {
|
||||||
|
"sprint": "current",
|
||||||
|
"deploy-frozen": "false",
|
||||||
|
"pr-queue": "[]"
|
||||||
|
},
|
||||||
|
"suggestedRoles": ["lead", "member", "reviewer"],
|
||||||
|
"systemPromptHint": "You are part of a dev team. Coordinate with @frontend, @backend, @devops groups. Check state keys for sprint status and deploy freezes before making changes."
|
||||||
|
}
|
||||||
30
apps/cli/src/templates/index.ts
Normal file
30
apps/cli/src/templates/index.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import devTeam from "./dev-team.json" with { type: "json" };
|
||||||
|
import research from "./research.json" with { type: "json" };
|
||||||
|
import opsIncident from "./ops-incident.json" with { type: "json" };
|
||||||
|
import simulation from "./simulation.json" with { type: "json" };
|
||||||
|
import personal from "./personal.json" with { type: "json" };
|
||||||
|
|
||||||
|
export interface MeshTemplate {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
groups: Array<{ name: string; roles: string[] }>;
|
||||||
|
stateKeys: Record<string, string>;
|
||||||
|
suggestedRoles: string[];
|
||||||
|
systemPromptHint: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TEMPLATES: Record<string, MeshTemplate> = {
|
||||||
|
"dev-team": devTeam,
|
||||||
|
research,
|
||||||
|
"ops-incident": opsIncident,
|
||||||
|
simulation,
|
||||||
|
personal,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function listTemplates(): MeshTemplate[] {
|
||||||
|
return Object.values(TEMPLATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTemplate(name: string): MeshTemplate | undefined {
|
||||||
|
return TEMPLATES[name];
|
||||||
|
}
|
||||||
17
apps/cli/src/templates/ops-incident.json
Normal file
17
apps/cli/src/templates/ops-incident.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "ops-incident",
|
||||||
|
"description": "Incident response team with oncall, comms, and engineering groups",
|
||||||
|
"groups": [
|
||||||
|
{ "name": "oncall", "roles": ["primary", "secondary"] },
|
||||||
|
{ "name": "comms", "roles": ["lead", "scribe"] },
|
||||||
|
{ "name": "engineering", "roles": ["lead", "responder"] }
|
||||||
|
],
|
||||||
|
"stateKeys": {
|
||||||
|
"incident-status": "investigating",
|
||||||
|
"severity": "unknown",
|
||||||
|
"commander": "",
|
||||||
|
"timeline": "[]"
|
||||||
|
},
|
||||||
|
"suggestedRoles": ["commander", "primary-oncall", "scribe", "responder"],
|
||||||
|
"systemPromptHint": "INCIDENT MODE. Priority: now for all messages. Update incident-status state. Commander coordinates. Scribe maintains timeline. Engineering fixes."
|
||||||
|
}
|
||||||
11
apps/cli/src/templates/personal.json
Normal file
11
apps/cli/src/templates/personal.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "personal",
|
||||||
|
"description": "Private mesh for a single user — all sessions auto-join",
|
||||||
|
"groups": [],
|
||||||
|
"stateKeys": {
|
||||||
|
"focus": "",
|
||||||
|
"todos": "[]"
|
||||||
|
},
|
||||||
|
"suggestedRoles": [],
|
||||||
|
"systemPromptHint": "Personal workspace. All your Claude Code sessions share this mesh. Use state keys to track focus and todos across sessions."
|
||||||
|
}
|
||||||
16
apps/cli/src/templates/research.json
Normal file
16
apps/cli/src/templates/research.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "research",
|
||||||
|
"description": "Research and analysis team focused on deep investigation and knowledge sharing",
|
||||||
|
"groups": [
|
||||||
|
{ "name": "analysis", "roles": ["lead", "analyst"] },
|
||||||
|
{ "name": "writing", "roles": ["lead", "writer", "reviewer"] },
|
||||||
|
{ "name": "data", "roles": ["engineer", "analyst"] }
|
||||||
|
],
|
||||||
|
"stateKeys": {
|
||||||
|
"research-topic": "",
|
||||||
|
"phase": "exploration",
|
||||||
|
"findings-count": "0"
|
||||||
|
},
|
||||||
|
"suggestedRoles": ["lead", "analyst", "writer", "reviewer"],
|
||||||
|
"systemPromptHint": "You are part of a research team. Share findings via remember(), use recall() before starting new analysis. Coordinate phases through state keys."
|
||||||
|
}
|
||||||
17
apps/cli/src/templates/simulation.json
Normal file
17
apps/cli/src/templates/simulation.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "simulation",
|
||||||
|
"description": "Load testing simulation with configurable time multiplier and user personas",
|
||||||
|
"groups": [
|
||||||
|
{ "name": "personas", "roles": ["admin", "user", "customer"] },
|
||||||
|
{ "name": "observers", "roles": ["monitor", "analyst"] },
|
||||||
|
{ "name": "control", "roles": ["orchestrator"] }
|
||||||
|
],
|
||||||
|
"stateKeys": {
|
||||||
|
"clock-speed": "x1",
|
||||||
|
"sim-status": "paused",
|
||||||
|
"tick-count": "0",
|
||||||
|
"scenario": ""
|
||||||
|
},
|
||||||
|
"suggestedRoles": ["orchestrator", "persona", "monitor"],
|
||||||
|
"systemPromptHint": "SIMULATION MODE. Follow the clock-speed state for time multiplier. Act according to your persona role and the simulated time. Report actions to @observers."
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user