feat: hierarchical group routing + role wiring
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

broker: expand member groups to ancestor paths at drain time (pull model)
- @flexicar message reaches peers in @flexicar/core, @flexicar/output, etc.
- Resolved at drainForMember — no DB changes, fully backward-compatible
- Any depth: flexicar/team/backend also matches @flexicar and @flexicar/team

cli: wire --role all the way through to session config + env
- Config.role field added
- launch.ts stores role in sessionConfig, passes CLAUDEMESH_ROLE env var
- mcp/server.ts includes role in identity string
- manager.ts auto-joins groups from config on WS connect (--groups flag now works)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-07 12:09:37 +01:00
parent 3da5d71275
commit d451fc296e
5 changed files with 44 additions and 4 deletions

View File

@@ -27,6 +27,7 @@ interface LaunchArgs {
joinLink: string | null;
meshSlug: string | null;
messageMode: "push" | "inbox" | "off" | null;
systemPrompt: string | null;
quiet: boolean;
skipPermConfirm: boolean;
claudeArgs: string[];
@@ -40,6 +41,7 @@ function parseArgs(argv: string[]): LaunchArgs {
joinLink: null,
meshSlug: null,
messageMode: null,
systemPrompt: null,
quiet: false,
skipPermConfirm: false,
claudeArgs: [],
@@ -68,6 +70,16 @@ function parseArgs(argv: string[]): LaunchArgs {
result.meshSlug = argv[++i]!;
} else if (arg.startsWith("--mesh=")) {
result.meshSlug = arg.slice("--mesh=".length);
} else if (arg === "--message-mode" && i + 1 < argv.length) {
const mode = argv[++i]! as "push" | "inbox" | "off";
if (["push", "inbox", "off"].includes(mode)) result.messageMode = mode;
} else if (arg.startsWith("--message-mode=")) {
const mode = arg.slice("--message-mode=".length) as "push" | "inbox" | "off";
if (["push", "inbox", "off"].includes(mode)) result.messageMode = mode;
} else if (arg === "--system-prompt" && i + 1 < argv.length) {
result.systemPrompt = argv[++i]!;
} else if (arg.startsWith("--system-prompt=")) {
result.systemPrompt = arg.slice("--system-prompt=".length);
} else if (arg === "--inbox") {
result.messageMode = "inbox";
} else if (arg === "--no-messages") {
@@ -318,6 +330,7 @@ export async function runLaunch(extraArgs: string[]): Promise<void> {
version: 1,
meshes: [mesh],
displayName,
...(role ? { role } : {}),
...(parsedGroups.length > 0 ? { groups: parsedGroups } : {}),
messageMode,
};
@@ -351,6 +364,7 @@ export async function runLaunch(extraArgs: string[]): Promise<void> {
"--dangerously-load-development-channels",
"server:claudemesh",
"--dangerously-skip-permissions",
...(args.systemPrompt ? ["--system-prompt", args.systemPrompt] : []),
...filtered,
];
@@ -362,6 +376,7 @@ export async function runLaunch(extraArgs: string[]): Promise<void> {
...process.env,
CLAUDEMESH_CONFIG_DIR: tmpDir,
CLAUDEMESH_DISPLAY_NAME: displayName,
...(role ? { CLAUDEMESH_ROLE: role } : {}),
},
});