@rayu-dev/rayu-cli 1.3.434 → 1.3.436

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/rayu.js +1102 -359
  2. package/package.json +1 -1
package/dist/rayu.js CHANGED
@@ -148347,7 +148347,7 @@ var init_auth = __esm(() => {
148347
148347
 
148348
148348
  // src/utils/userAgent.ts
148349
148349
  function getRayuUserAgent() {
148350
- return `rayu/${"1.3.434"}`;
148350
+ return `rayu/${"1.3.436"}`;
148351
148351
  }
148352
148352
  var getClaudeCodeUserAgent;
148353
148353
  var init_userAgent = __esm(() => {
@@ -148373,7 +148373,7 @@ function getUserAgent() {
148373
148373
  const clientApp = process.env.RAYU_AGENT_SDK_CLIENT_APP ? `, client-app/${process.env.RAYU_AGENT_SDK_CLIENT_APP}` : "";
148374
148374
  const workload = getWorkload();
148375
148375
  const workloadSuffix = workload ? `, workload/${workload}` : "";
148376
- return `rayu/${"1.3.434"} (${"external"}, ${process.env.RAYU_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
148376
+ return `rayu/${"1.3.436"} (${"external"}, ${process.env.RAYU_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
148377
148377
  }
148378
148378
  function getMCPUserAgent() {
148379
148379
  const parts = [];
@@ -148387,7 +148387,7 @@ function getMCPUserAgent() {
148387
148387
  parts.push(`client-app/${process.env.RAYU_AGENT_SDK_CLIENT_APP}`);
148388
148388
  }
148389
148389
  const suffix = parts.length > 0 ? ` (${parts.join(", ")})` : "";
148390
- return `rayu/${"1.3.434"}${suffix}`;
148390
+ return `rayu/${"1.3.436"}${suffix}`;
148391
148391
  }
148392
148392
  function getWebFetchUserAgent() {
148393
148393
  return `Rayu-User (${getRayuUserAgent()})`;
@@ -148510,7 +148510,7 @@ var init_user = __esm(() => {
148510
148510
  deviceId,
148511
148511
  sessionId: getSessionId(),
148512
148512
  email: getEmail(),
148513
- appVersion: "1.3.434",
148513
+ appVersion: "1.3.436",
148514
148514
  platform: getHostPlatformForAnalytics(),
148515
148515
  organizationUuid,
148516
148516
  accountUuid,
@@ -184022,7 +184022,7 @@ var init_metadata = __esm(() => {
184022
184022
  COMPOUND_OPERATOR_REGEX = /\s*(?:&&|\|\||[;|])\s*/;
184023
184023
  WHITESPACE_REGEX = /\s+/;
184024
184024
  getVersionBase = memoize_default(() => {
184025
- const match = "1.3.434".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
184025
+ const match = "1.3.436".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
184026
184026
  return match ? match[0] : undefined;
184027
184027
  });
184028
184028
  buildEnvContext = memoize_default(async () => {
@@ -184061,7 +184061,7 @@ var init_metadata = __esm(() => {
184061
184061
  },
184062
184062
  isGithubAction: isEnvTruthy(process.env.GITHUB_ACTIONS),
184063
184063
  isRayuAction: isEnvTruthy(process.env.RAYU_ACTION),
184064
- version: "1.3.434",
184064
+ version: "1.3.436",
184065
184065
  versionBase: getVersionBase(),
184066
184066
  buildTime: "",
184067
184067
  deploymentEnvironment: env4.detectDeploymentEnvironment(),
@@ -184675,7 +184675,7 @@ function initialize1PEventLogging() {
184675
184675
  const platform2 = getPlatform();
184676
184676
  const attributes = {
184677
184677
  [import_semantic_conventions.ATTR_SERVICE_NAME]: "rayu",
184678
- [import_semantic_conventions.ATTR_SERVICE_VERSION]: "1.3.434"
184678
+ [import_semantic_conventions.ATTR_SERVICE_VERSION]: "1.3.436"
184679
184679
  };
184680
184680
  if (platform2 === "wsl") {
184681
184681
  const wslVersion = getWslVersion();
@@ -184702,7 +184702,7 @@ function initialize1PEventLogging() {
184702
184702
  })
184703
184703
  ]
184704
184704
  });
184705
- firstPartyEventLogger = firstPartyEventLoggerProvider.getLogger("io.rayu.events", "1.3.434");
184705
+ firstPartyEventLogger = firstPartyEventLoggerProvider.getLogger("io.rayu.events", "1.3.436");
184706
184706
  }
184707
184707
  async function reinitialize1PEventLoggingIfConfigChanged() {
184708
184708
  if (!is1PEventLoggingEnabled() || !firstPartyEventLoggerProvider) {
@@ -220618,7 +220618,7 @@ function getAttributionHeader(fingerprint) {
220618
220618
  if (!isAttributionHeaderEnabled()) {
220619
220619
  return "";
220620
220620
  }
220621
- const version2 = `${"1.3.434"}.${fingerprint}`;
220621
+ const version2 = `${"1.3.436"}.${fingerprint}`;
220622
220622
  const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? "unknown";
220623
220623
  const cch = "";
220624
220624
  const workload = getWorkload();
@@ -271522,12 +271522,13 @@ var init_generalPurposeAgent = __esm(() => {
271522
271522
  tools: ["*"],
271523
271523
  source: "built-in",
271524
271524
  baseDir: "built-in",
271525
+ model: process.env.RAYU_GENERAL_AGENT_MODEL || "inherit",
271525
271526
  getSystemPrompt: getGeneralPurposeSystemPrompt
271526
271527
  };
271527
271528
  });
271528
271529
 
271529
271530
  // src/tools/AgentTool/built-in/subagents/common.ts
271530
- var EPHEMERAL_FRAMING = `You are a one-shot subagent: a fresh session with NO memory of past work and NO future. You receive a single self-contained task packet, perform exactly ONE job, and return a concise structured result to the agent that spawned you. Do NOT ask follow-up questions — everything you need is in the task packet; if something is genuinely missing, state the assumption you made and proceed. Keep going until the job is fully done. Work in PARALLEL where steps are independent: batch your reads/greps/searches into a single message (multiple tool calls, ~3–5 at a time — parallel is ~3–5x faster than one-at-a-time); go sequential only when one call genuinely needs another's output. Report high-signal results only (the output + the few facts that matter, not a play-by-play). Do not create report files; report back as your final message.`, SKILL_SEEKING = `Before starting, check whether any installed skill (via the Skill tool) is relevant to this task and would improve the result — if so, use it. Skills are installed by the user via /install-skill or /find-skill; if none apply, proceed without one.`;
271531
+ var EPHEMERAL_FRAMING = `You are a one-shot subagent: a fresh session with NO memory of past work and NO future. You receive a single self-contained task packet, perform exactly ONE job, and return a concise structured result to the agent that spawned you. Do NOT ask follow-up questions — everything you need is in the task packet; if something is genuinely missing, state the assumption you made and proceed. Keep going until the job is fully done. Work in PARALLEL where steps are independent: batch your reads/greps/searches into a single message (multiple tool calls, ~3–5 at a time — parallel is ~3–5x faster than one-at-a-time); go sequential only when one call genuinely needs another's output. Report high-signal results only (the output + the few facts that matter, not a play-by-play). Do not create report files; report back as your final message.`, SKILL_SEEKING = `Before starting, check whether a skill (via the Skill tool) is relevant to this task and would improve the result — if so, use it. Any available skill is usable: rayu ships bundled skills (e.g. rayu-frontend-design, rayu-design-system, rayu-web-testing, rayu-api-design, rayu-mcp-builder, rayu-doc-export) with no install; you may also use any skill the user installed, or install a relevant one on demand from the official Anthropic skills repo (anthropics/skills) via the InstallSkill tool. If none apply, proceed without one.`;
271531
271532
 
271532
271533
  // src/tools/AgentTool/built-in/subagents/asset-generation.ts
271533
271534
  function getAssetGenSystemPrompt() {
@@ -271537,6 +271538,8 @@ ${EPHEMERAL_FRAMING}
271537
271538
 
271538
271539
  ${SKILL_SEEKING}
271539
271540
 
271541
+ The bundled \`rayu-algorithmic-art\` and \`rayu-canvas-design\` skills are directly relevant to this work — pull them via the Skill tool.
271542
+
271540
271543
  ## Your job (from the task packet)
271541
271544
  - Generate the requested images (hero backgrounds, illustrations, product/teaser imagery, etc.) using the image generation tool.
271542
271545
  - Match the EXACT style, mood, color palette, and dimensions from the Design PRD / packet.
@@ -271571,6 +271574,8 @@ ${EPHEMERAL_FRAMING}
271571
271574
 
271572
271575
  ${SKILL_SEEKING}
271573
271576
 
271577
+ The bundled \`rayu-api-design\` skill is directly relevant to this work — pull it via the Skill tool before defining the contract.
271578
+
271574
271579
  ## Your job
271575
271580
  Define, precisely and concretely, the backend contract so every downstream agent builds against the SAME shapes:
271576
271581
 
@@ -271616,6 +271621,8 @@ ${EPHEMERAL_FRAMING}
271616
271621
 
271617
271622
  ${SKILL_SEEKING}
271618
271623
 
271624
+ The bundled \`rayu-frontend-design\`, \`rayu-design-system\`, \`rayu-theme-factory\`, and \`rayu-brand-guidelines\` skills are directly relevant to this work — pull them via the Skill tool before designing.
271625
+
271619
271626
  ## Your job
271620
271627
  Define, precisely and concretely, the visual + interaction system so every downstream agent can build pixel-perfect without guessing:
271621
271628
  - **Color palette** — exact hex codes (background, surface, text, accents, states).
@@ -271736,9 +271743,9 @@ var init_linter = __esm(() => {
271736
271743
  };
271737
271744
  });
271738
271745
 
271739
- // src/tools/AgentTool/built-in/subagents/pa.ts
271740
- function getPaSystemPrompt() {
271741
- return `You are the PA subagent — a senior software architect and deep-research planner for RAYU. You turn a goal (a new project or a change to an existing one) into a thorough, well-grounded plan.
271746
+ // src/tools/AgentTool/built-in/subagents/planner.ts
271747
+ function getPlannerSystemPrompt() {
271748
+ return `You are the planner subagent — a senior software architect and deep-research planner for RAYU. You turn a goal (a new project or a change to an existing one) into a thorough, well-grounded plan.
271742
271749
 
271743
271750
  ${EPHEMERAL_FRAMING}
271744
271751
 
@@ -271760,16 +271767,16 @@ ${SKILL_SEEKING}
271760
271767
 
271761
271768
  Keep it tight and high-signal — the caller will act on this plan.`;
271762
271769
  }
271763
- var PA_SUBAGENT;
271764
- var init_pa = __esm(() => {
271765
- PA_SUBAGENT = {
271766
- agentType: "PA",
271770
+ var PLANNER_SUBAGENT;
271771
+ var init_planner = __esm(() => {
271772
+ PLANNER_SUBAGENT = {
271773
+ agentType: "planner",
271767
271774
  whenToUse: "Plan & research subagent. Use when a task needs real upfront planning or (deep) research before implementation — designing a new project, a non-trivial feature, or a change to an existing codebase. Explores in parallel and returns a chosen approach, a step-by-step implementation plan, critical files, and risks. It plans only; it does not write or run code.",
271768
271775
  disallowedTools: [FILE_EDIT_TOOL_NAME, BASH_TOOL_NAME],
271769
271776
  source: "built-in",
271770
271777
  baseDir: "built-in",
271771
271778
  color: "purple",
271772
- getSystemPrompt: getPaSystemPrompt
271779
+ getSystemPrompt: getPlannerSystemPrompt
271773
271780
  };
271774
271781
  });
271775
271782
 
@@ -271820,10 +271827,10 @@ var init_subagents = __esm(() => {
271820
271827
  init_fix();
271821
271828
  init_global_setup();
271822
271829
  init_linter();
271823
- init_pa();
271830
+ init_planner();
271824
271831
  init_review();
271825
271832
  SUBAGENTS = [
271826
- PA_SUBAGENT,
271833
+ PLANNER_SUBAGENT,
271827
271834
  DESIGN_SUBAGENT,
271828
271835
  BACKEND_DESIGN_SUBAGENT,
271829
271836
  GLOBAL_SETUP_SUBAGENT,
@@ -272066,8 +272073,8 @@ var init_stackDetector = __esm(() => {
272066
272073
  });
272067
272074
 
272068
272075
  // src/tools/AgentTool/swarmContext.ts
272069
- import { existsSync as existsSync20, readFileSync as readFileSync22 } from "fs";
272070
- import { join as join56 } from "path";
272076
+ import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync22, writeFileSync as writeFileSync9 } from "fs";
272077
+ import { dirname as dirname28, join as join56 } from "path";
272071
272078
  function truncateToTokens(text2, maxTokens) {
272072
272079
  const maxChars = Math.max(0, maxTokens) * CHARS_PER_TOKEN;
272073
272080
  if (text2.length <= maxChars)
@@ -272121,6 +272128,24 @@ function readDomainSection(domain2) {
272121
272128
  return;
272122
272129
  }
272123
272130
  }
272131
+ function writeDomainSection(domain2, content) {
272132
+ const p = getDomainPath(domain2);
272133
+ try {
272134
+ mkdirSync9(dirname28(p), { recursive: true });
272135
+ writeFileSync9(p, content.endsWith(`
272136
+ `) ? content : content + `
272137
+ `, "utf8");
272138
+ } catch {}
272139
+ }
272140
+ function persistDomainSectionIfEmpty(agentType, content) {
272141
+ if (readDomainSection(agentType) !== undefined)
272142
+ return false;
272143
+ const trimmed = (content ?? "").trim();
272144
+ if (trimmed.length === 0)
272145
+ return false;
272146
+ writeDomainSection(agentType, truncateToTokens(trimmed, PER_SECTION_TOKEN_CAP));
272147
+ return true;
272148
+ }
272124
272149
  function formatShared(shared3) {
272125
272150
  const lines2 = ["## Shared Project Brief"];
272126
272151
  if (shared3.goal)
@@ -272285,7 +272310,7 @@ function buildCollaboratorPrompt(s2) {
272285
272310
  "## How you work",
272286
272311
  "- You implement AND iterate: write real, production-ready code/config in your domain and refine until it meets the brief. You have the full toolset; request permission for sensitive actions through the normal permission flow.",
272287
272312
  "- Work in PARALLEL where independent: batch reads/greps and independent edits into one message (multiple tool calls, ~3–5 at a time) — parallel is ~3–5x faster. Go sequential only on a true dependency.",
272288
- `- Seek relevant INSTALLED skills (via the Skill tool) that improve your output — ${s2.skillHint}. Skills are installed by the user via /install-skill or /find-skill; if none are installed, proceed without one.`,
272313
+ `- Use the relevant skill (via the Skill tool) to raise your output quality — ${s2.skillHint}. rayu ships these as BUNDLED skills (always available, no install needed). You may ALSO use any skill the user installed, or install a relevant one on demand from the official Anthropic skills repo (anthropics/skills) via the InstallSkill tool. If none apply, proceed without one.`,
272289
272314
  "- You may use MCP servers and dispatch the Tier-3 subagents (e.g. asset-generation, review, fix, linter) for atomic jobs — the same subagents the orchestrator uses.",
272290
272315
  "- Be autonomous: keep going until your piece is complete; state assumptions and continue rather than stopping for approval unless genuinely blocked.",
272291
272316
  "",
@@ -272305,7 +272330,7 @@ function buildCollaboratorPrompt(s2) {
272305
272330
  "",
272306
272331
  "## Context I/O (shared swarm context)",
272307
272332
  "- A SWARM CONTEXT block above (if present) holds the shared brief and the sections of collaborators you depend on. Trust it and build on it — do NOT re-derive what is already decided.",
272308
- "- When you finish, persist YOUR section to " + getDomainPath(s2.agentType) + " (overwrite; concise + contract-focused) so other collaborators and your own resumed turns can read it. Use that EXACT path — the swarm lives under `.rayu/swarm/`, never `.claude/`.",
272333
+ "- REQUIRED FINAL STEP: before you report done, persist YOUR section — use the Write tool to write " + getDomainPath(s2.agentType) + " (overwrite; concise + contract-focused) so other collaborators and your own resumed turns can read it. Use that EXACT path — the swarm lives under `.rayu/swarm/`, never `.claude/`.",
272309
272334
  "",
272310
272335
  "Be concise and structured — the orchestrator integrates your output. Report back as a normal message (do not create report files)."
272311
272336
  ];
@@ -272361,7 +272386,7 @@ var init_common3 = __esm(() => {
272361
272386
  init_stackAwareness();
272362
272387
  init_profiles();
272363
272388
  AUTHORITY = [
272364
- "The orchestrator owns the plan and the shared brief. Build within the chosen architecture and the PA/research plan — do not silently re-architect.",
272389
+ "The orchestrator owns the plan and the shared brief. Build within the chosen architecture and the planner/research plan — do not silently re-architect.",
272365
272390
  "Security decisions are authoritative — never weaken them for speed.",
272366
272391
  "Coordinate through explicit contracts (API shapes, schema, auth flow), not by second-guessing other collaborators."
272367
272392
  ];
@@ -272377,7 +272402,7 @@ var init_backend = __esm(() => {
272377
272402
  title: "Backend Collaborator",
272378
272403
  whenToUse: "Server-side implementation: API routes/services/business logic, AND the data layer (schema, models, migrations, queries). Implements the security/auth flow. Builds and iterates on real backend + database code.",
272379
272404
  role: "You build the backend end-to-end: API endpoints, the service layer and business logic, middleware/error handling, env config, and the data layer (schema design, models, relations, indexes, migrations). You implement the auth/security flow that the security collaborator defines.",
272380
- skillHint: "e.g. an API-design skill for clean, consistent endpoint and schema design",
272405
+ skillHint: "the bundled rayu-api-design skill for clean endpoint/schema contracts, and rayu-mcp-builder when building an MCP server",
272381
272406
  withStackAwareness: true,
272382
272407
  allowedSubagents: [
272383
272408
  "backend-design",
@@ -272407,7 +272432,7 @@ var init_deploy = __esm(() => {
272407
272432
  title: "Deploy Collaborator",
272408
272433
  whenToUse: "DevOps & deployment: containerization, CI/CD, environment/secrets config, build pipelines, and shipping to the hosting target. Runs the production build, fixes build errors, and iterates until the app is deployable/live.",
272409
272434
  role: "You package and ship what the other collaborators built: Dockerfile/compose, CI/CD pipeline, environment and secrets configuration, health checks, and deployment to the target platform. You run the production build, resolve build errors, and iterate until deployment succeeds, then report the result/URL.",
272410
- skillHint: "e.g. a deployment/CI skill for the target platform (Docker, Vercel, etc.)",
272435
+ skillHint: "the bundled rayu-web-testing skill for post-deploy smoke checks, plus any deployment/CI skill for the target platform (Docker, Vercel, etc.)",
272411
272436
  allowedSubagents: ["review", "fix", "linter", "Explore", "general-purpose"],
272412
272437
  owns: [
272413
272438
  "Dockerfile (multi-stage) and docker-compose",
@@ -272429,7 +272454,7 @@ var init_frontend = __esm(() => {
272429
272454
  title: "Frontend Collaborator",
272430
272455
  whenToUse: "Web UI implementation: page/screen architecture, components, state management, styling/design-system, animations, and API integration against the backend. Builds and iterates on real frontend code.",
272431
272456
  role: "You build the web frontend end-to-end against the design and the backend contracts: page structure and navigation, the component tree, state management, the design system (tokens, spacing, typography), motion/interactions, and wiring to the API. You produce working, production-ready UI — not just layouts.",
272432
- skillHint: "e.g. a UI/UX design skill such as ui-ux-pro-max for stronger visual/UX decisions",
272457
+ skillHint: "the bundled rayu-frontend-design, rayu-design-system, and rayu-web-artifacts-builder skills for strong visual/UX decisions, a consistent token system, and self-contained interactive artifacts",
272433
272458
  withStackAwareness: true,
272434
272459
  allowedSubagents: [
272435
272460
  "design",
@@ -272461,7 +272486,7 @@ var init_mobile = __esm(() => {
272461
272486
  title: "Mobile Collaborator",
272462
272487
  whenToUse: "Mobile app implementation (Flutter-first, fallback React Native): screens, navigation, state, the API/auth layer against the backend, and offline strategy. Builds and iterates on real mobile code.",
272463
272488
  role: "You build the mobile app against the backend contracts and the auth flow: screen architecture and navigation, state management, the API service layer, auth implementation, and offline support. You produce working, production-ready mobile code.",
272464
- skillHint: "e.g. a mobile/Flutter UI skill for idiomatic screens and navigation",
272489
+ skillHint: "the bundled rayu-frontend-design and rayu-design-system skills for idiomatic UI and a consistent token system",
272465
272490
  withStackAwareness: true,
272466
272491
  allowedSubagents: [
272467
272492
  "design",
@@ -272493,7 +272518,7 @@ var init_security = __esm(() => {
272493
272518
  title: "Security Collaborator",
272494
272519
  whenToUse: "Security work: design AND implement auth/authorization (RBAC), input validation, secret/sensitive-data handling, and harden endpoints. Reviews other collaborators’ code for vulnerabilities and fixes them. Its security decisions are authoritative.",
272495
272520
  role: "You own security end-to-end: design the auth flow and authorization model, then implement and enforce it — guards/middleware, validation, secret handling, security headers, and OWASP Top-10 hardening. You also audit the backend/frontend for vulnerabilities and fix them. Your security decisions are the source of truth and override convenience.",
272496
- skillHint: "e.g. a security-review or OWASP skill for systematic threat coverage",
272521
+ skillHint: "the bundled rayu-web-testing skill to verify behavior, plus any installed OWASP/security-review skill for systematic threat coverage",
272497
272522
  allowedSubagents: [
272498
272523
  "backend-design",
272499
272524
  "review",
@@ -273371,7 +273396,7 @@ var init_prompt5 = __esm(() => {
273371
273396
  getPrompt = memoize_default(async (_cwd) => {
273372
273397
  return `Execute a skill within the main conversation
273373
273398
 
273374
- When users ask you to perform tasks, check if any of the available skills match. Skills provide specialized capabilities and domain knowledge.
273399
+ When users ask you to perform tasks, check if any of the available skills match. Skills provide specialized capabilities and domain knowledge. Any available skill is usable whenever it helps — rayu's bundled skills, any skill the user has installed, and MCP skills — there is no per-task restriction on which you may invoke.
273375
273400
 
273376
273401
  When users reference a "slash command" or "/<something>" (e.g., "/commit", "/review-pr"), they are referring to a skill. Use this tool to invoke it.
273377
273402
 
@@ -273385,6 +273410,7 @@ How to invoke:
273385
273410
 
273386
273411
  Important:
273387
273412
  - Available skills are listed in system-reminder messages in the conversation
273413
+ - Beyond the listed skills, you may install a relevant one on demand from the official Anthropic skills repository (\`anthropics/skills\`) or any other source — via the InstallSkill tool or \`/install-skill anthropics/skills/skills/<name>\` — and then invoke it
273388
273414
  - When a skill matches the user's request, this is a BLOCKING REQUIREMENT: invoke the relevant Skill tool BEFORE generating any other response about the task
273389
273415
  - NEVER mention a skill without actually calling this tool
273390
273416
  - Do not invoke a skill that is already running
@@ -280584,7 +280610,7 @@ var init_fileStateCache = __esm(() => {
280584
280610
  // src/utils/claudemd.ts
280585
280611
  import {
280586
280612
  basename as basename15,
280587
- dirname as dirname28,
280613
+ dirname as dirname29,
280588
280614
  extname as extname4,
280589
280615
  isAbsolute as isAbsolute14,
280590
280616
  join as join57,
@@ -280697,7 +280723,7 @@ function extractIncludePathsFromTokens(tokens, basePath) {
280697
280723
  if (path19) {
280698
280724
  const isValidPath = path19.startsWith("./") || path19.startsWith("~/") || path19.startsWith("/") && path19 !== "/" || !path19.startsWith("@") && !path19.match(/^[#%^&*()]+/) && path19.match(/^[a-zA-Z0-9._-]/);
280699
280725
  if (isValidPath) {
280700
- const resolvedPath = expandPath(path19, dirname28(basePath));
280726
+ const resolvedPath = expandPath(path19, dirname29(basePath));
280701
280727
  absolutePaths.add(resolvedPath);
280702
280728
  }
280703
280729
  }
@@ -280759,7 +280785,7 @@ function resolveExcludePatterns(patterns) {
280759
280785
  }
280760
280786
  const globStart = normalized.search(/[*?{[]/);
280761
280787
  const staticPrefix = globStart === -1 ? normalized : normalized.slice(0, globStart);
280762
- const dirToResolve = dirname28(staticPrefix);
280788
+ const dirToResolve = dirname29(staticPrefix);
280763
280789
  try {
280764
280790
  const resolvedDir = fs12.realpathSync(dirToResolve).replaceAll("\\", "/");
280765
280791
  if (resolvedDir !== dirToResolve) {
@@ -280953,7 +280979,7 @@ async function processConditionedMdRules(targetPath, rulesDir, type, processedPa
280953
280979
  if (!file2.globs || file2.globs.length === 0) {
280954
280980
  return false;
280955
280981
  }
280956
- const baseDir = type === "Project" ? dirname28(dirname28(rulesDir)) : getOriginalCwd();
280982
+ const baseDir = type === "Project" ? dirname29(dirname29(rulesDir)) : getOriginalCwd();
280957
280983
  const relativePath = isAbsolute14(targetPath) ? relative8(baseDir, targetPath) : targetPath;
280958
280984
  if (!relativePath || relativePath.startsWith("..") || isAbsolute14(relativePath)) {
280959
280985
  return false;
@@ -281032,9 +281058,15 @@ var init_claudemd = __esm(() => {
281032
281058
  init_settings2();
281033
281059
  import_ignore2 = __toESM(require_ignore(), 1);
281034
281060
  import_picomatch = __toESM(require_picomatch2(), 1);
281035
- PROJECT_MEMORY_FILENAMES = ["RAYU.md", "AGENTS.md", "CLAUDE.md"];
281036
- PROJECT_CONFIG_DIRS = [".rayu", ".agents"];
281061
+ PROJECT_MEMORY_FILENAMES = [
281062
+ "RAYU.md",
281063
+ "AGENTS.md",
281064
+ "AGENT.md",
281065
+ "CLAUDE.md"
281066
+ ];
281067
+ PROJECT_CONFIG_DIRS = [".rayu", ".agents", "claude"];
281037
281068
  TEXT_FILE_EXTENSIONS = new Set([
281069
+ ".env",
281038
281070
  ".md",
281039
281071
  ".txt",
281040
281072
  ".text",
@@ -281178,7 +281210,7 @@ var init_claudemd = __esm(() => {
281178
281210
  let currentDir = originalCwd;
281179
281211
  while (currentDir !== parse8(currentDir).root) {
281180
281212
  dirs.push(currentDir);
281181
- currentDir = dirname28(currentDir);
281213
+ currentDir = dirname29(currentDir);
281182
281214
  }
281183
281215
  const gitRoot = findGitRoot(originalCwd);
281184
281216
  const canonicalRoot = findCanonicalGitRoot(originalCwd);
@@ -281441,6 +281473,13 @@ function getClaudeCodeSkillsDirIfEnabled() {
281441
281473
  return;
281442
281474
  return getClaudeCodeSkillsDir();
281443
281475
  }
281476
+ function getProjectClaudeSkillsDirIfEnabled() {
281477
+ const settings = getInitialSettings();
281478
+ const enabled2 = settings.claudeSkillsEnabled !== false;
281479
+ if (!enabled2)
281480
+ return;
281481
+ return existingDir(join58(getCwd(), ".claude", "skills"));
281482
+ }
281444
281483
  function getExtraSkillDirsFromSettings() {
281445
281484
  const settings = getInitialSettings();
281446
281485
  const raw = settings.extraSkillDirs;
@@ -281463,6 +281502,9 @@ function getExternalSkillDirs() {
281463
281502
  const claudeDir = getClaudeCodeSkillsDirIfEnabled();
281464
281503
  if (claudeDir)
281465
281504
  candidates.push(claudeDir);
281505
+ const projectClaudeDir = getProjectClaudeSkillsDirIfEnabled();
281506
+ if (projectClaudeDir)
281507
+ candidates.push(projectClaudeDir);
281466
281508
  candidates.push(...getExtraSkillDirsFromSettings());
281467
281509
  candidates.push(...getExtraSkillDirsFromEnv());
281468
281510
  const seen = new Set;
@@ -281482,6 +281524,7 @@ var init_externalSkillDiscovery = __esm(() => {
281482
281524
  init_debug();
281483
281525
  init_fsOperations();
281484
281526
  init_settings2();
281527
+ init_cwd2();
281485
281528
  });
281486
281529
 
281487
281530
  // src/utils/argumentSubstitution.ts
@@ -284663,7 +284706,7 @@ var init_validate3 = __esm(() => {
284663
284706
  // src/keybindings/loadUserBindings.ts
284664
284707
  import { readFileSync as readFileSync24 } from "fs";
284665
284708
  import { readFile as readFile12, stat as stat19 } from "fs/promises";
284666
- import { dirname as dirname29, join as join64 } from "path";
284709
+ import { dirname as dirname30, join as join64 } from "path";
284667
284710
  function isKeybindingCustomizationEnabled() {
284668
284711
  return getFeatureValue_CACHED_MAY_BE_STALE("tengu_keybinding_customization_release", false);
284669
284712
  }
@@ -284842,7 +284885,7 @@ async function initializeKeybindingWatcher() {
284842
284885
  return;
284843
284886
  }
284844
284887
  const userPath = getKeybindingsPath();
284845
- const watchDir = dirname29(userPath);
284888
+ const watchDir = dirname30(userPath);
284846
284889
  try {
284847
284890
  const stats2 = await stat19(watchDir);
284848
284891
  if (!stats2.isDirectory()) {
@@ -294275,7 +294318,7 @@ var builders = null;
294275
294318
  import { realpath as realpath9 } from "fs/promises";
294276
294319
  import {
294277
294320
  basename as basename17,
294278
- dirname as dirname30,
294321
+ dirname as dirname31,
294279
294322
  isAbsolute as isAbsolute18,
294280
294323
  join as join65,
294281
294324
  sep as pathSep,
@@ -294500,7 +294543,7 @@ function isSkillFile(filePath) {
294500
294543
  function transformSkillFiles(files2) {
294501
294544
  const filesByDir = new Map;
294502
294545
  for (const file2 of files2) {
294503
- const dir = dirname30(file2.filePath);
294546
+ const dir = dirname31(file2.filePath);
294504
294547
  const dirFiles = filesByDir.get(dir) ?? [];
294505
294548
  dirFiles.push(file2);
294506
294549
  filesByDir.set(dir, dirFiles);
@@ -294529,15 +294572,15 @@ function buildNamespace(targetDir, baseDir) {
294529
294572
  return relativePath ? relativePath.split(pathSep).join(":") : "";
294530
294573
  }
294531
294574
  function getSkillCommandName(filePath, baseDir) {
294532
- const skillDirectory = dirname30(filePath);
294533
- const parentOfSkillDir = dirname30(skillDirectory);
294575
+ const skillDirectory = dirname31(filePath);
294576
+ const parentOfSkillDir = dirname31(skillDirectory);
294534
294577
  const commandBaseName = basename17(skillDirectory);
294535
294578
  const namespace = buildNamespace(parentOfSkillDir, baseDir);
294536
294579
  return namespace ? `${namespace}:${commandBaseName}` : commandBaseName;
294537
294580
  }
294538
294581
  function getRegularCommandName(filePath, baseDir) {
294539
294582
  const fileName = basename17(filePath);
294540
- const fileDirectory = dirname30(filePath);
294583
+ const fileDirectory = dirname31(filePath);
294541
294584
  const commandBaseName = fileName.replace(/\.md$/, "");
294542
294585
  const namespace = buildNamespace(fileDirectory, baseDir);
294543
294586
  return namespace ? `${namespace}:${commandBaseName}` : commandBaseName;
@@ -294560,7 +294603,7 @@ async function loadSkillsFromCommandsDir(cwd2) {
294560
294603
  } of processedFiles) {
294561
294604
  try {
294562
294605
  const isSkillFormat = isSkillFile(filePath);
294563
- const skillDirectory = isSkillFormat ? dirname30(filePath) : undefined;
294606
+ const skillDirectory = isSkillFormat ? dirname31(filePath) : undefined;
294564
294607
  const cmdName = getCommandName2({
294565
294608
  baseDir,
294566
294609
  filePath,
@@ -294612,7 +294655,7 @@ async function discoverSkillDirsForPaths(filePaths, cwd2) {
294612
294655
  const resolvedCwd = cwd2.endsWith(pathSep) ? cwd2.slice(0, -1) : cwd2;
294613
294656
  const newDirs = [];
294614
294657
  for (const filePath of filePaths) {
294615
- let currentDir = dirname30(filePath);
294658
+ let currentDir = dirname31(filePath);
294616
294659
  while (currentDir.startsWith(resolvedCwd + pathSep)) {
294617
294660
  const skillDir = join65(currentDir, ".rayu", "skills");
294618
294661
  if (!dynamicSkillDirs.has(skillDir)) {
@@ -294626,7 +294669,7 @@ async function discoverSkillDirsForPaths(filePaths, cwd2) {
294626
294669
  newDirs.push(skillDir);
294627
294670
  } catch {}
294628
294671
  }
294629
- const parent = dirname30(currentDir);
294672
+ const parent = dirname31(currentDir);
294630
294673
  if (parent === currentDir)
294631
294674
  break;
294632
294675
  currentDir = parent;
@@ -305309,7 +305352,7 @@ function getTelemetryAttributes() {
305309
305352
  attributes["session.id"] = sessionId;
305310
305353
  }
305311
305354
  if (shouldIncludeAttribute("OTEL_METRICS_INCLUDE_VERSION")) {
305312
- attributes["app.version"] = "1.3.434";
305355
+ attributes["app.version"] = "1.3.436";
305313
305356
  }
305314
305357
  const oauthAccount = getOauthAccountInfo();
305315
305358
  if (oauthAccount) {
@@ -306814,7 +306857,7 @@ var init_postSamplingHooks = __esm(() => {
306814
306857
  // src/services/api/dumpPrompts.ts
306815
306858
  import { createHash as createHash8 } from "crypto";
306816
306859
  import { promises as fs12 } from "fs";
306817
- import { dirname as dirname31, join as join68 } from "path";
306860
+ import { dirname as dirname32, join as join68 } from "path";
306818
306861
  function hashString3(str3) {
306819
306862
  return createHash8("sha256").update(str3).digest("hex");
306820
306863
  }
@@ -306841,7 +306884,7 @@ function getDumpPromptsPath(agentIdOrSessionId) {
306841
306884
  function appendToFile(filePath, entries) {
306842
306885
  if (entries.length === 0)
306843
306886
  return;
306844
- fs12.mkdir(dirname31(filePath), { recursive: true }).then(() => fs12.appendFile(filePath, entries.join(`
306887
+ fs12.mkdir(dirname32(filePath), { recursive: true }).then(() => fs12.appendFile(filePath, entries.join(`
306845
306888
  `) + `
306846
306889
  `)).catch(() => {});
306847
306890
  }
@@ -402949,7 +402992,7 @@ var EXIT_WORKTREE_TOOL_NAME = "ExitWorktree";
402949
402992
  var init_cron = () => {};
402950
402993
 
402951
402994
  // src/utils/cronTasks.ts
402952
- import { dirname as dirname32, join as join69 } from "path";
402995
+ import { dirname as dirname33, join as join69 } from "path";
402953
402996
  var CRON_FILE_REL, DEFAULT_CRON_JITTER_CONFIG;
402954
402997
  var init_cronTasks = __esm(() => {
402955
402998
  init_state();
@@ -410535,7 +410578,8 @@ var init_mcpPluginIntegration = __esm(() => {
410535
410578
 
410536
410579
  // src/services/mcp/config.ts
410537
410580
  import { chmod as chmod2, open as open8, rename as rename3, stat as stat21, unlink as unlink6 } from "fs/promises";
410538
- import { dirname as dirname33, join as join71, parse as parse10 } from "path";
410581
+ import { homedir as homedir21 } from "os";
410582
+ import { dirname as dirname34, join as join71, parse as parse10 } from "path";
410539
410583
  function getEnterpriseMcpFilePath() {
410540
410584
  return join71(getManagedFilePath(), "managed-mcp.json");
410541
410585
  }
@@ -411008,7 +411052,7 @@ function getMcpConfigsByScope(scope) {
411008
411052
  let currentDir = getCwd();
411009
411053
  while (currentDir !== parse10(currentDir).root) {
411010
411054
  dirs.push(currentDir);
411011
- currentDir = dirname33(currentDir);
411055
+ currentDir = dirname34(currentDir);
411012
411056
  }
411013
411057
  for (const dir of dirs.reverse()) {
411014
411058
  const mcpJsonPath = join71(dir, ".mcp.json");
@@ -411111,6 +411155,49 @@ function getMcpConfigByName(name) {
411111
411155
  }
411112
411156
  return null;
411113
411157
  }
411158
+ function getClaudeFallbackMcpServers() {
411159
+ const settings = getInitialSettings();
411160
+ if (settings.claudeMcpEnabled === false)
411161
+ return {};
411162
+ const fs13 = getFsImplementation();
411163
+ const cwd2 = getCwd();
411164
+ const home = homedir21();
411165
+ const readJson = (path19) => {
411166
+ try {
411167
+ const parsed = safeParseJSON(fs13.readFileSync(path19, { encoding: "utf8" }));
411168
+ return parsed && typeof parsed === "object" ? parsed : null;
411169
+ } catch {
411170
+ return null;
411171
+ }
411172
+ };
411173
+ const rawSources = [];
411174
+ const claudeJson = readJson(join71(home, ".claude.json"));
411175
+ if (claudeJson) {
411176
+ rawSources.push(claudeJson.mcpServers);
411177
+ const projects = claudeJson.projects;
411178
+ rawSources.push(projects?.[cwd2]?.mcpServers);
411179
+ }
411180
+ for (const p of [
411181
+ join71(cwd2, ".claude", "settings.json"),
411182
+ join71(home, ".claude", "settings.json")
411183
+ ]) {
411184
+ const s2 = readJson(p);
411185
+ if (s2)
411186
+ rawSources.push(s2.mcpServers);
411187
+ }
411188
+ const validated = {};
411189
+ for (const raw of rawSources) {
411190
+ if (!raw || typeof raw !== "object")
411191
+ continue;
411192
+ for (const [name, cfg] of Object.entries(raw)) {
411193
+ const parsed = McpServerConfigSchema().safeParse(cfg);
411194
+ if (parsed.success) {
411195
+ validated[name] = parsed.data;
411196
+ }
411197
+ }
411198
+ }
411199
+ return addScopeToServers(validated, "user");
411200
+ }
411114
411201
  async function getRayuMcpConfigs(dynamicServers = {}) {
411115
411202
  const { servers: enterpriseServers } = getMcpConfigsByScope("enterprise");
411116
411203
  if (doesEnterpriseMcpConfigExist()) {
@@ -411130,6 +411217,7 @@ async function getRayuMcpConfigs(dynamicServers = {}) {
411130
411217
  const { servers: userServers } = mcpLocked ? noServers : getMcpConfigsByScope("user");
411131
411218
  const { servers: projectServers } = mcpLocked ? noServers : getMcpConfigsByScope("project");
411132
411219
  const { servers: localServers } = mcpLocked ? noServers : getMcpConfigsByScope("local");
411220
+ const claudeFallbackServers = mcpLocked ? {} : getClaudeFallbackMcpServers();
411133
411221
  const pluginMcpServers = {};
411134
411222
  const pluginResult = await loadAllPluginsCacheOnly();
411135
411223
  const mcpErrors = [];
@@ -411196,7 +411284,7 @@ async function getRayuMcpConfigs(dynamicServers = {}) {
411196
411284
  duplicateOf
411197
411285
  });
411198
411286
  }
411199
- const configs = Object.assign({}, dedupedPluginServers, userServers, approvedProjectServers, localServers);
411287
+ const configs = Object.assign({}, claudeFallbackServers, dedupedPluginServers, userServers, approvedProjectServers, localServers);
411200
411288
  const filtered = {};
411201
411289
  for (const [name, serverConfig] of Object.entries(configs)) {
411202
411290
  if (!isMcpServerAllowedByPolicy(name, serverConfig)) {
@@ -414192,10 +414280,10 @@ var init_capitalize = __esm(() => {
414192
414280
  });
414193
414281
 
414194
414282
  // src/utils/jetbrains.ts
414195
- import { homedir as homedir21, platform as platform2 } from "os";
414283
+ import { homedir as homedir22, platform as platform2 } from "os";
414196
414284
  import { join as join75 } from "path";
414197
414285
  function buildCommonPluginDirectoryPaths(ideName) {
414198
- const homeDir = homedir21();
414286
+ const homeDir = homedir22();
414199
414287
  const directories = [];
414200
414288
  const idePatterns = ideNameToDirMap[ideName.toLowerCase()];
414201
414289
  if (!idePatterns) {
@@ -415619,7 +415707,7 @@ function getInstallationEnv() {
415619
415707
  return;
415620
415708
  }
415621
415709
  function getClaudeCodeVersion() {
415622
- return "1.3.434";
415710
+ return "1.3.436";
415623
415711
  }
415624
415712
  async function getInstalledVSCodeExtensionVersion(command) {
415625
415713
  const { stdout } = await execFileNoThrow(command, ["--list-extensions", "--show-versions"], {
@@ -416248,14 +416336,14 @@ function recursivelySanitizeUnicode(value) {
416248
416336
  }
416249
416337
 
416250
416338
  // src/utils/authFileDescriptor.ts
416251
- import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
416339
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
416252
416340
  function maybePersistTokenForSubprocesses(path19, token, tokenName) {
416253
416341
  if (!isEnvTruthy(process.env.CLAUDE_CODE_REMOTE)) {
416254
416342
  return;
416255
416343
  }
416256
416344
  try {
416257
- mkdirSync9(CCR_TOKEN_DIR, { recursive: true, mode: 448 });
416258
- writeFileSync9(path19, token, { encoding: "utf8", mode: 384 });
416345
+ mkdirSync10(CCR_TOKEN_DIR, { recursive: true, mode: 448 });
416346
+ writeFileSync10(path19, token, { encoding: "utf8", mode: 384 });
416259
416347
  logForDebugging(`Persisted ${tokenName} to ${path19} for subprocess access`);
416260
416348
  } catch (error54) {
416261
416349
  logForDebugging(`Failed to persist ${tokenName} to disk (non-fatal): ${errorMessage(error54)}`, { level: "error" });
@@ -420055,7 +420143,7 @@ var init_wrapper = __esm(() => {
420055
420143
 
420056
420144
  // src/services/mcp/client.ts
420057
420145
  import { mkdir as mkdir12, readFile as readFile16, unlink as unlink7, writeFile as writeFile11 } from "fs/promises";
420058
- import { dirname as dirname34, join as join77 } from "path";
420146
+ import { dirname as dirname35, join as join77 } from "path";
420059
420147
  function isMcpSessionExpiredError(error54) {
420060
420148
  const httpStatus = "code" in error54 ? error54.code : undefined;
420061
420149
  if (httpStatus !== 404) {
@@ -420088,7 +420176,7 @@ function setMcpAuthCacheEntry(serverId) {
420088
420176
  const cache5 = await getMcpAuthCache();
420089
420177
  cache5[serverId] = { timestamp: Date.now() };
420090
420178
  const cachePath = getMcpAuthCachePath();
420091
- await mkdir12(dirname34(cachePath), { recursive: true });
420179
+ await mkdir12(dirname35(cachePath), { recursive: true });
420092
420180
  await writeFile11(cachePath, jsonStringify(cache5));
420093
420181
  authCachePromise = null;
420094
420182
  }).catch(() => {});
@@ -420857,7 +420945,7 @@ async function setupSdkMcpClients(sdkMcpConfigs, sendMcpMessage) {
420857
420945
  const client4 = new Client({
420858
420946
  name: "claude-code",
420859
420947
  title: "RAYU",
420860
- version: "1.3.434",
420948
+ version: "1.3.436",
420861
420949
  description: "Anthropic's agentic coding tool",
420862
420950
  websiteUrl: PRODUCT_URL
420863
420951
  }, {
@@ -421174,7 +421262,7 @@ var init_client7 = __esm(() => {
421174
421262
  const client4 = new Client({
421175
421263
  name: "claude-code",
421176
421264
  title: "RAYU",
421177
- version: "1.3.434",
421265
+ version: "1.3.436",
421178
421266
  description: "Anthropic's agentic coding tool",
421179
421267
  websiteUrl: PRODUCT_URL
421180
421268
  }, {
@@ -426955,7 +427043,7 @@ import {
426955
427043
  stat as stat22,
426956
427044
  unlink as unlink8
426957
427045
  } from "fs/promises";
426958
- import { dirname as dirname35, isAbsolute as isAbsolute20, join as join79, relative as relative11 } from "path";
427046
+ import { dirname as dirname36, isAbsolute as isAbsolute20, join as join79, relative as relative11 } from "path";
426959
427047
  import { inspect as inspect3 } from "util";
426960
427048
  function fileHistoryEnabled() {
426961
427049
  if (getIsNonInteractiveSession()) {
@@ -427396,7 +427484,7 @@ async function createBackup(filePath, version2) {
427396
427484
  } catch (e2) {
427397
427485
  if (!isENOENT(e2))
427398
427486
  throw e2;
427399
- await mkdir13(dirname35(backupPath), { recursive: true });
427487
+ await mkdir13(dirname36(backupPath), { recursive: true });
427400
427488
  await copyFile4(filePath, backupPath);
427401
427489
  }
427402
427490
  await chmod3(backupPath, srcStats.mode);
@@ -427428,7 +427516,7 @@ async function restoreBackup(filePath, backupFileName) {
427428
427516
  } catch (e2) {
427429
427517
  if (!isENOENT(e2))
427430
427518
  throw e2;
427431
- await mkdir13(dirname35(filePath), { recursive: true });
427519
+ await mkdir13(dirname36(filePath), { recursive: true });
427432
427520
  await copyFile4(backupPath, filePath);
427433
427521
  }
427434
427522
  await chmod3(filePath, backupStats.mode);
@@ -427635,7 +427723,7 @@ var init_fileOperationAnalytics = __esm(() => {
427635
427723
 
427636
427724
  // src/utils/gitDiff.ts
427637
427725
  import { access as access3, readFile as readFile19 } from "fs/promises";
427638
- import { dirname as dirname36, join as join80, relative as relative12, sep as sep17 } from "path";
427726
+ import { dirname as dirname37, join as join80, relative as relative12, sep as sep17 } from "path";
427639
427727
  async function fetchGitDiff() {
427640
427728
  const isGit = await getIsGit();
427641
427729
  if (!isGit)
@@ -427819,7 +427907,7 @@ function parseShortstat(stdout) {
427819
427907
  };
427820
427908
  }
427821
427909
  async function fetchSingleFileGitDiff(absoluteFilePath) {
427822
- const gitRoot = findGitRoot(dirname36(absoluteFilePath));
427910
+ const gitRoot = findGitRoot(dirname37(absoluteFilePath));
427823
427911
  if (!gitRoot)
427824
427912
  return null;
427825
427913
  const gitPath = relative12(gitRoot, absoluteFilePath).split(sep17).join("/");
@@ -430597,7 +430685,7 @@ var init_UI6 = __esm(() => {
430597
430685
  });
430598
430686
 
430599
430687
  // src/tools/FileEditTool/FileEditTool.ts
430600
- import { dirname as dirname37, isAbsolute as isAbsolute21, sep as sep18 } from "path";
430688
+ import { dirname as dirname38, isAbsolute as isAbsolute21, sep as sep18 } from "path";
430601
430689
  function readFileForEdit(absoluteFilePath) {
430602
430690
  try {
430603
430691
  const meta3 = readFileSyncWithMetadata(absoluteFilePath);
@@ -430903,7 +430991,7 @@ String: ${old_string}`,
430903
430991
  activateConditionalSkillsForPaths([absoluteFilePath], cwd2);
430904
430992
  }
430905
430993
  await diagnosticTracker.beforeFileEdited(absoluteFilePath);
430906
- await fs13.mkdir(dirname37(absoluteFilePath));
430994
+ await fs13.mkdir(dirname38(absoluteFilePath));
430907
430995
  if (fileHistoryEnabled()) {
430908
430996
  await fileHistoryTrackEdit(updateFileHistoryState, absoluteFilePath, parentMessage.uuid);
430909
430997
  }
@@ -431488,7 +431576,7 @@ var init_UI7 = __esm(() => {
431488
431576
  });
431489
431577
 
431490
431578
  // src/tools/FileWriteTool/FileWriteTool.ts
431491
- import { dirname as dirname38, sep as sep19 } from "path";
431579
+ import { dirname as dirname39, sep as sep19 } from "path";
431492
431580
  var inputSchema9, outputSchema8, FileWriteTool;
431493
431581
  var init_FileWriteTool = __esm(() => {
431494
431582
  init_analytics();
@@ -431631,7 +431719,7 @@ var init_FileWriteTool = __esm(() => {
431631
431719
  async call({ file_path, content }, context, _2, parentMessage) {
431632
431720
  const { readFileState, updateFileHistoryState, dynamicSkillDirTriggers } = context;
431633
431721
  const fullFilePath = expandPath(file_path);
431634
- const dir = dirname38(fullFilePath);
431722
+ const dir = dirname39(fullFilePath);
431635
431723
  const cwd2 = getCwd();
431636
431724
  const newSkillDirs = await discoverSkillDirsForPaths([fullFilePath], cwd2);
431637
431725
  if (newSkillDirs.length > 0) {
@@ -431797,7 +431885,7 @@ var init_FileWriteTool = __esm(() => {
431797
431885
  });
431798
431886
 
431799
431887
  // src/utils/plugins/orphanedPluginFilter.ts
431800
- import { dirname as dirname39, isAbsolute as isAbsolute23, join as join81, normalize as normalize13, relative as relative16, sep as sep20 } from "path";
431888
+ import { dirname as dirname40, isAbsolute as isAbsolute23, join as join81, normalize as normalize13, relative as relative16, sep as sep20 } from "path";
431801
431889
  async function getGlobExclusionsForPluginCache(searchPath) {
431802
431890
  const cachePath = normalize13(join81(getPluginsDirectory(), "cache"));
431803
431891
  if (searchPath && !pathsOverlap(searchPath, cachePath)) {
@@ -431817,7 +431905,7 @@ async function getGlobExclusionsForPluginCache(searchPath) {
431817
431905
  ORPHANED_AT_FILENAME
431818
431906
  ], cachePath, new AbortController().signal);
431819
431907
  cachedExclusions = markers.map((markerPath) => {
431820
- const versionDir = dirname39(markerPath);
431908
+ const versionDir = dirname40(markerPath);
431821
431909
  const rel = isAbsolute23(versionDir) ? relative16(cachePath, versionDir) : versionDir;
431822
431910
  const posixRelative = rel.replace(/\\/g, "/");
431823
431911
  return `!**/${posixRelative}/**`;
@@ -431847,12 +431935,12 @@ var init_orphanedPluginFilter = __esm(() => {
431847
431935
  });
431848
431936
 
431849
431937
  // src/utils/glob.ts
431850
- import { basename as basename21, dirname as dirname40, isAbsolute as isAbsolute24, join as join82, sep as sep21 } from "path";
431938
+ import { basename as basename21, dirname as dirname41, isAbsolute as isAbsolute24, join as join82, sep as sep21 } from "path";
431851
431939
  function extractGlobBaseDirectory(pattern) {
431852
431940
  const globChars = /[*?[{]/;
431853
431941
  const match = pattern.match(globChars);
431854
431942
  if (!match || match.index === undefined) {
431855
- const dir = dirname40(pattern);
431943
+ const dir = dirname41(pattern);
431856
431944
  const file2 = basename21(pattern);
431857
431945
  return { baseDir: dir, relativePattern: file2 };
431858
431946
  }
@@ -435979,7 +436067,7 @@ function computeFingerprint(messageText, version2) {
435979
436067
  }
435980
436068
  function computeFingerprintFromMessages(messages) {
435981
436069
  const firstMessageText = extractFirstMessageText(messages);
435982
- return computeFingerprint(firstMessageText, "1.3.434");
436070
+ return computeFingerprint(firstMessageText, "1.3.436");
435983
436071
  }
435984
436072
  var FINGERPRINT_SALT = "59cf53e54c78";
435985
436073
  var init_fingerprint = () => {};
@@ -436021,7 +436109,7 @@ async function sideQuery(opts) {
436021
436109
  betas.push(STRUCTURED_OUTPUTS_BETA_HEADER);
436022
436110
  }
436023
436111
  const messageText = extractFirstUserMessageText(messages);
436024
- const fingerprint = computeFingerprint(messageText, "1.3.434");
436112
+ const fingerprint = computeFingerprint(messageText, "1.3.436");
436025
436113
  const attributionHeader = getAttributionHeader(fingerprint);
436026
436114
  const systemBlocks = [
436027
436115
  attributionHeader ? { type: "text", text: attributionHeader } : null,
@@ -436285,6 +436373,13 @@ function finalizeAgentTool(agentMessages, agentId, metadata) {
436285
436373
  last_request_id: lastRequestId
436286
436374
  });
436287
436375
  }
436376
+ if (!NON_SWARM_PERSIST_AGENT_TYPES.has(agentType)) {
436377
+ const finalText = content.map((c4) => c4.type === "text" ? c4.text : "").join(`
436378
+ `).trim();
436379
+ if (finalText.length > 0) {
436380
+ persistDomainSectionIfEmpty(agentType, finalText);
436381
+ }
436382
+ }
436288
436383
  return {
436289
436384
  agentId,
436290
436385
  agentType,
@@ -436432,10 +436527,11 @@ async function runAsyncAgentLifecycle({
436432
436527
  clearDumpState(agentIdForCleanup);
436433
436528
  }
436434
436529
  }
436435
- var agentToolResultSchema;
436530
+ var agentToolResultSchema, NON_SWARM_PERSIST_AGENT_TYPES;
436436
436531
  var init_agentToolUtils = __esm(() => {
436437
436532
  init_v4();
436438
436533
  init_state();
436534
+ init_swarmContext();
436439
436535
  init_tools();
436440
436536
  init_agentSummary();
436441
436537
  init_analytics();
@@ -436477,6 +436573,7 @@ var init_agentToolUtils = __esm(() => {
436477
436573
  }).nullable()
436478
436574
  })
436479
436575
  }));
436576
+ NON_SWARM_PERSIST_AGENT_TYPES = new Set(["Explore", "general-purpose"]);
436480
436577
  });
436481
436578
 
436482
436579
  // src/components/AgentProgressLine.tsx
@@ -448881,13 +448978,16 @@ function getAgentLineKindLabel(subagentType) {
448881
448978
  if (kind === "subagent") {
448882
448979
  return "subagent";
448883
448980
  }
448981
+ if (subagentType && getBuiltInAgents().some((a2) => a2.agentType === subagentType)) {
448982
+ return "subagent";
448983
+ }
448884
448984
  return;
448885
448985
  }
448886
448986
  function getAgentLineModel(subagentType, toolModel) {
448887
448987
  let modelStr;
448888
448988
  if (toolModel) {
448889
448989
  modelStr = toolModel;
448890
- } else if (getAgentKind(subagentType) !== undefined) {
448990
+ } else if (subagentType) {
448891
448991
  const agent = getBuiltInAgents().find((a2) => a2.agentType === subagentType);
448892
448992
  if (agent) {
448893
448993
  try {
@@ -448922,22 +449022,16 @@ function renderToolUseTag(input) {
448922
449022
  }, undefined, false, undefined, this)
448923
449023
  }, "kind", false, undefined, this));
448924
449024
  }
448925
- if (input.model || getAgentKind(input.subagent_type) !== undefined) {
448926
- const modelName = getAgentLineModel(input.subagent_type, input.model);
448927
- if (modelName) {
448928
- const isSwarmAgent = getAgentKind(input.subagent_type) !== undefined;
448929
- const differsFromMain = input.model !== undefined && parseUserSpecifiedModel(input.model) !== getMainLoopModel();
448930
- if (isSwarmAgent || differsFromMain) {
448931
- tags.push(/* @__PURE__ */ jsx_dev_runtime108.jsxDEV(ThemedBox_default, {
448932
- flexWrap: "nowrap",
448933
- marginLeft: 1,
448934
- children: /* @__PURE__ */ jsx_dev_runtime108.jsxDEV(ThemedText, {
448935
- dimColor: true,
448936
- children: modelName
448937
- }, undefined, false, undefined, this)
448938
- }, "model", false, undefined, this));
448939
- }
448940
- }
449025
+ const modelName = getAgentLineModel(input.subagent_type, input.model);
449026
+ if (modelName) {
449027
+ tags.push(/* @__PURE__ */ jsx_dev_runtime108.jsxDEV(ThemedBox_default, {
449028
+ flexWrap: "nowrap",
449029
+ marginLeft: 1,
449030
+ children: /* @__PURE__ */ jsx_dev_runtime108.jsxDEV(ThemedText, {
449031
+ dimColor: true,
449032
+ children: modelName
449033
+ }, undefined, false, undefined, this)
449034
+ }, "model", false, undefined, this));
448941
449035
  }
448942
449036
  if (tags.length === 0) {
448943
449037
  return null;
@@ -458917,7 +459011,7 @@ var init_InProcessBackend = __esm(() => {
458917
459011
  });
458918
459012
 
458919
459013
  // src/utils/swarm/backends/it2Setup.ts
458920
- import { homedir as homedir23 } from "os";
459014
+ import { homedir as homedir24 } from "os";
458921
459015
  async function detectPythonPackageManager() {
458922
459016
  const uvResult = await execFileNoThrow("which", ["uv"]);
458923
459017
  if (uvResult.code === 0) {
@@ -458952,18 +459046,18 @@ async function installIt2(packageManager) {
458952
459046
  switch (packageManager) {
458953
459047
  case "uvx":
458954
459048
  result = await execFileNoThrowWithCwd("uv", ["tool", "install", "it2"], {
458955
- cwd: homedir23()
459049
+ cwd: homedir24()
458956
459050
  });
458957
459051
  break;
458958
459052
  case "pipx":
458959
459053
  result = await execFileNoThrowWithCwd("pipx", ["install", "it2"], {
458960
- cwd: homedir23()
459054
+ cwd: homedir24()
458961
459055
  });
458962
459056
  break;
458963
459057
  case "pip":
458964
- result = await execFileNoThrowWithCwd("pip", ["install", "--user", "it2"], { cwd: homedir23() });
459058
+ result = await execFileNoThrowWithCwd("pip", ["install", "--user", "it2"], { cwd: homedir24() });
458965
459059
  if (result.code !== 0) {
458966
- result = await execFileNoThrowWithCwd("pip3", ["install", "--user", "it2"], { cwd: homedir23() });
459060
+ result = await execFileNoThrowWithCwd("pip3", ["install", "--user", "it2"], { cwd: homedir24() });
458967
459061
  }
458968
459062
  break;
458969
459063
  }
@@ -460242,7 +460336,7 @@ __export(exports_teamHelpers, {
460242
460336
  cleanupSessionTeams: () => cleanupSessionTeams,
460243
460337
  addHiddenPaneId: () => addHiddenPaneId
460244
460338
  });
460245
- import { mkdirSync as mkdirSync10, readFileSync as readFileSync25, writeFileSync as writeFileSync10 } from "fs";
460339
+ import { mkdirSync as mkdirSync11, readFileSync as readFileSync25, writeFileSync as writeFileSync11 } from "fs";
460246
460340
  import { mkdir as mkdir17, readFile as readFile22, rm as rm6, writeFile as writeFile15 } from "fs/promises";
460247
460341
  import { join as join88 } from "path";
460248
460342
  function sanitizeName(name) {
@@ -460281,8 +460375,8 @@ async function readTeamFileAsync(teamName) {
460281
460375
  }
460282
460376
  function writeTeamFile(teamName, teamFile) {
460283
460377
  const teamDir = getTeamDir(teamName);
460284
- mkdirSync10(teamDir, { recursive: true });
460285
- writeFileSync10(getTeamFilePath(teamName), jsonStringify(teamFile, null, 2));
460378
+ mkdirSync11(teamDir, { recursive: true });
460379
+ writeFileSync11(getTeamFilePath(teamName), jsonStringify(teamFile, null, 2));
460286
460380
  }
460287
460381
  async function writeTeamFileAsync(teamName, teamFile) {
460288
460382
  const teamDir = getTeamDir(teamName);
@@ -467784,7 +467878,7 @@ ${result.result}`
467784
467878
  // src/skills/installSkill.ts
467785
467879
  import { randomUUID as randomUUID21 } from "crypto";
467786
467880
  import { cp as cp2, mkdir as mkdir19, mkdtemp as mkdtemp3, readFile as readFile24, readdir as readdir13, rename as rename4, rm as rm7, stat as stat24, writeFile as writeFile17 } from "fs/promises";
467787
- import { homedir as homedir24, tmpdir as tmpdir10 } from "os";
467881
+ import { homedir as homedir25, tmpdir as tmpdir10 } from "os";
467788
467882
  import { basename as basename27, isAbsolute as isAbsolute27, join as join91, resolve as resolve38, sep as sep25 } from "path";
467789
467883
  function sanitizeSkillName(raw) {
467790
467884
  const name = raw.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "");
@@ -467936,9 +468030,9 @@ async function installSkillFromSource(rawSource, options = {}) {
467936
468030
  }
467937
468031
  function expandHome(p) {
467938
468032
  if (p === "~")
467939
- return homedir24();
468033
+ return homedir25();
467940
468034
  if (p.startsWith("~/"))
467941
- return join91(homedir24(), p.slice(2));
468035
+ return join91(homedir25(), p.slice(2));
467942
468036
  return p;
467943
468037
  }
467944
468038
  function firstLine(markdown) {
@@ -490487,7 +490581,7 @@ var init_UI16 = __esm(() => {
490487
490581
 
490488
490582
  // src/tools/ImageGenTool/ImageGenTool.ts
490489
490583
  import { mkdir as mkdir21, readFile as readFile26, writeFile as writeFile19 } from "fs/promises";
490490
- import { dirname as dirname42, isAbsolute as isAbsolute28, relative as relative20 } from "path";
490584
+ import { dirname as dirname43, isAbsolute as isAbsolute28, relative as relative20 } from "path";
490491
490585
  function defaultOutputPath(ext = "png") {
490492
490586
  return `./generated-image-${Date.now()}.${ext}`;
490493
490587
  }
@@ -490666,7 +490760,7 @@ var init_ImageGenTool = __esm(() => {
490666
490760
  usedModelId = resolveModel(selectedModel, isEdit).id;
490667
490761
  }
490668
490762
  const { path: path22 } = resolveOutputPath(input.output_path ?? defaultOutputPath(extForMedia(mediaType)));
490669
- await mkdir21(dirname42(path22), { recursive: true });
490763
+ await mkdir21(dirname43(path22), { recursive: true });
490670
490764
  await writeFile19(path22, buffer);
490671
490765
  let inlineB64 = buffer.toString("base64");
490672
490766
  let inlineMedia = mediaType;
@@ -491289,7 +491383,7 @@ var init_UI17 = __esm(() => {
491289
491383
 
491290
491384
  // src/tools/VideoGenTool/VideoGenTool.ts
491291
491385
  import { mkdir as mkdir22, readFile as readFile28, writeFile as writeFile20 } from "fs/promises";
491292
- import { dirname as dirname43, isAbsolute as isAbsolute29, relative as relative21 } from "path";
491386
+ import { dirname as dirname44, isAbsolute as isAbsolute29, relative as relative21 } from "path";
491293
491387
  function defaultOutputPath2() {
491294
491388
  return `./generated-video-${Date.now()}.mp4`;
491295
491389
  }
@@ -491442,7 +491536,7 @@ var init_VideoGenTool = __esm(() => {
491442
491536
  buffer = r2.buffer;
491443
491537
  usedModelId = model.id;
491444
491538
  }
491445
- await mkdir22(dirname43(path22), { recursive: true });
491539
+ await mkdir22(dirname44(path22), { recursive: true });
491446
491540
  await writeFile20(path22, buffer);
491447
491541
  const preview = await extractPreviewFrame(path22);
491448
491542
  return {
@@ -506608,7 +506702,7 @@ var init_queryHelpers = __esm(() => {
506608
506702
  import { randomUUID as randomUUID24 } from "crypto";
506609
506703
  import { rm as rm9 } from "fs";
506610
506704
  import { appendFile as appendFile4, copyFile as copyFile5, mkdir as mkdir24 } from "fs/promises";
506611
- import { dirname as dirname44, isAbsolute as isAbsolute31, join as join98, relative as relative24 } from "path";
506705
+ import { dirname as dirname45, isAbsolute as isAbsolute31, join as join98, relative as relative24 } from "path";
506612
506706
  function safeRemoveOverlay(overlayPath) {
506613
506707
  rm9(overlayPath, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }, () => {});
506614
506708
  }
@@ -506628,7 +506722,7 @@ async function copyOverlayToMain(overlayPath, writtenPaths, cwd2) {
506628
506722
  const src = join98(overlayPath, rel);
506629
506723
  const dest = join98(cwd2, rel);
506630
506724
  try {
506631
- await mkdir24(dirname44(dest), { recursive: true });
506725
+ await mkdir24(dirname45(dest), { recursive: true });
506632
506726
  await copyFile5(src, dest);
506633
506727
  } catch {
506634
506728
  allCopied = false;
@@ -506877,7 +506971,7 @@ async function startSpeculation(suggestionText, context, setAppState, isPipeline
506877
506971
  if (isWriteTool) {
506878
506972
  if (!writtenPathsRef.current.has(rel)) {
506879
506973
  const overlayFile = join98(overlayPath, rel);
506880
- await mkdir24(dirname44(overlayFile), { recursive: true });
506974
+ await mkdir24(dirname45(overlayFile), { recursive: true });
506881
506975
  try {
506882
506976
  await copyFile5(join98(cwd2, rel), overlayFile);
506883
506977
  } catch {}
@@ -510837,7 +510931,7 @@ Goal: Gain a comprehensive understanding of the user's request by reading throug
510837
510931
  ### Phase 2: Design
510838
510932
  Goal: Design an implementation approach.
510839
510933
 
510840
- Launch ${PA_SUBAGENT.agentType} agent(s) to design the implementation based on the user's intent and your exploration results from Phase 1.
510934
+ Launch ${PLANNER_SUBAGENT.agentType} agent(s) to design the implementation based on the user's intent and your exploration results from Phase 1.
510841
510935
 
510842
510936
  You can launch up to ${agentCount} agent(s) in parallel.
510843
510937
 
@@ -511340,8 +511434,8 @@ You have exited plan mode. You can now make edits, run tools, and take actions.$
511340
511434
  const content = `## Collaborator-swarm mode is ON
511341
511435
 
511342
511436
  You are the ORCHESTRATOR — coordinate, do not implement yourself. Run the 3-phase build flow:
511343
- 1. SCOPE & RESEARCH — clarify the request's detail and scope; ask the user for their preferred tech stack (offer recommendations with rationale). For open implementation choices (e.g. payment: Stripe / bank / ABA), dispatch the PA subagent to research the real options and present them for the user to choose.
511344
- 2. ALIGNED PLAN — have PA produce ONE coherent plan, explicitly aligned across backend AND frontend (shared API contract, data model, auth); get the user's confirmation.
511437
+ 1. SCOPE & RESEARCH — clarify the request's detail and scope; ask the user for their preferred tech stack (offer recommendations with rationale). For open implementation choices (e.g. payment: Stripe / bank / ABA), dispatch the planner subagent to research the real options and present them for the user to choose.
511438
+ 2. ALIGNED PLAN — have the planner produce ONE coherent plan, explicitly aligned across backend AND frontend (shared API contract, data model, auth); get the user's confirmation.
511345
511439
  3. DELEGATE BY SPECIALTY — decompose into backend / frontend / mobile subtasks and delegate to the matching collaborators (run independent work in parallel). Each collaborator may use only its allowed subagents.
511346
511440
 
511347
511441
  The user can return to normal mode with /normal.`;
@@ -512346,7 +512440,7 @@ var init_messages5 = __esm(() => {
512346
512440
  init_planModeV2();
512347
512441
  init_slowOperations();
512348
512442
  init_exploreAgent();
512349
- init_pa();
512443
+ init_planner();
512350
512444
  init_builtInAgents();
512351
512445
  init_constants2();
512352
512446
  init_prompt7();
@@ -512401,7 +512495,7 @@ var init_messages5 = __esm(() => {
512401
512495
  // src/services/vcr.ts
512402
512496
  import { createHash as createHash18, randomUUID as randomUUID26 } from "crypto";
512403
512497
  import { mkdir as mkdir25, readFile as readFile31, writeFile as writeFile23 } from "fs/promises";
512404
- import { dirname as dirname45, join as join99 } from "path";
512498
+ import { dirname as dirname46, join as join99 } from "path";
512405
512499
  function shouldUseVCR() {
512406
512500
  if (false) {}
512407
512501
  if (false) {}
@@ -512426,7 +512520,7 @@ async function withFixture(input, fixtureName, f3) {
512426
512520
  throw new Error(`Fixture missing: ${filename}. Re-run tests with VCR_RECORD=1, then commit the result.`);
512427
512521
  }
512428
512522
  const result = await f3();
512429
- await mkdir25(dirname45(filename), { recursive: true });
512523
+ await mkdir25(dirname46(filename), { recursive: true });
512430
512524
  await writeFile23(filename, jsonStringify(result, null, 2), {
512431
512525
  encoding: "utf8"
512432
512526
  });
@@ -512465,7 +512559,7 @@ ${jsonStringify(dehydratedInput, null, 2)}`);
512465
512559
  if (env4.isCI && !isEnvTruthy(process.env.VCR_RECORD)) {
512466
512560
  return results;
512467
512561
  }
512468
- await mkdir25(dirname45(filename), { recursive: true });
512562
+ await mkdir25(dirname46(filename), { recursive: true });
512469
512563
  await writeFile23(filename, jsonStringify({
512470
512564
  input: dehydratedInput,
512471
512565
  output: results.map((message, index) => mapMessage(message, dehydrateValue, index))
@@ -514529,7 +514623,7 @@ var init_findRelevantMemories = __esm(() => {
514529
514623
 
514530
514624
  // src/utils/attachments.ts
514531
514625
  import { readdir as readdir19, stat as stat31 } from "fs/promises";
514532
- import { dirname as dirname46, parse as parse13, relative as relative25, resolve as resolve39 } from "path";
514626
+ import { dirname as dirname47, parse as parse13, relative as relative25, resolve as resolve39 } from "path";
514533
514627
  import { randomUUID as randomUUID28 } from "crypto";
514534
514628
  async function getAttachments(input, toolUseContext, ideSelection, queuedCommands, messages, querySource, options) {
514535
514629
  if (isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_ATTACHMENTS) || isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)) {
@@ -514916,21 +515010,21 @@ async function getSelectedLinesFromIDE(ideSelection, toolUseContext) {
514916
515010
  ];
514917
515011
  }
514918
515012
  function getDirectoriesToProcess(targetPath, originalCwd) {
514919
- const targetDir = dirname46(resolve39(targetPath));
515013
+ const targetDir = dirname47(resolve39(targetPath));
514920
515014
  const nestedDirs = [];
514921
515015
  let currentDir = targetDir;
514922
515016
  while (currentDir !== originalCwd && currentDir !== parse13(currentDir).root) {
514923
515017
  if (currentDir.startsWith(originalCwd)) {
514924
515018
  nestedDirs.push(currentDir);
514925
515019
  }
514926
- currentDir = dirname46(currentDir);
515020
+ currentDir = dirname47(currentDir);
514927
515021
  }
514928
515022
  nestedDirs.reverse();
514929
515023
  const cwdLevelDirs = [];
514930
515024
  currentDir = originalCwd;
514931
515025
  while (currentDir !== parse13(currentDir).root) {
514932
515026
  cwdLevelDirs.push(currentDir);
514933
- currentDir = dirname46(currentDir);
515027
+ currentDir = dirname47(currentDir);
514934
515028
  }
514935
515029
  cwdLevelDirs.reverse();
514936
515030
  return { nestedDirs, cwdLevelDirs };
@@ -516186,21 +516280,21 @@ var init_attachments2 = __esm(() => {
516186
516280
  });
516187
516281
 
516188
516282
  // src/utils/plugins/loadPluginCommands.ts
516189
- import { basename as basename32, dirname as dirname47, join as join102 } from "path";
516283
+ import { basename as basename32, dirname as dirname48, join as join102 } from "path";
516190
516284
  function isSkillFile2(filePath) {
516191
516285
  return /^skill\.md$/i.test(basename32(filePath));
516192
516286
  }
516193
516287
  function getCommandNameFromFile(filePath, baseDir, pluginName) {
516194
516288
  const isSkill = isSkillFile2(filePath);
516195
516289
  if (isSkill) {
516196
- const skillDirectory = dirname47(filePath);
516197
- const parentOfSkillDir = dirname47(skillDirectory);
516290
+ const skillDirectory = dirname48(filePath);
516291
+ const parentOfSkillDir = dirname48(skillDirectory);
516198
516292
  const commandBaseName = basename32(skillDirectory);
516199
516293
  const relativePath = parentOfSkillDir.startsWith(baseDir) ? parentOfSkillDir.slice(baseDir.length).replace(/^\//, "") : "";
516200
516294
  const namespace = relativePath ? relativePath.split("/").join(":") : "";
516201
516295
  return namespace ? `${pluginName}:${namespace}:${commandBaseName}` : `${pluginName}:${commandBaseName}`;
516202
516296
  } else {
516203
- const fileDirectory = dirname47(filePath);
516297
+ const fileDirectory = dirname48(filePath);
516204
516298
  const commandBaseName = basename32(filePath).replace(/\.md$/, "");
516205
516299
  const relativePath = fileDirectory.startsWith(baseDir) ? fileDirectory.slice(baseDir.length).replace(/^\//, "") : "";
516206
516300
  const namespace = relativePath ? relativePath.split("/").join(":") : "";
@@ -516227,7 +516321,7 @@ async function collectMarkdownFiles(dirPath, baseDir, loadedPaths) {
516227
516321
  function transformPluginSkillFiles(files2) {
516228
516322
  const filesByDir = new Map;
516229
516323
  for (const file2 of files2) {
516230
- const dir = dirname47(file2.filePath);
516324
+ const dir = dirname48(file2.filePath);
516231
516325
  const dirFiles = filesByDir.get(dir) ?? [];
516232
516326
  dirFiles.push(file2);
516233
516327
  filesByDir.set(dir, dirFiles);
@@ -516316,7 +516410,7 @@ function createPluginCommand(commandName, file2, sourceName, pluginManifest, plu
516316
516410
  return displayName || commandName;
516317
516411
  },
516318
516412
  async getPromptForCommand(args, context) {
516319
- let finalContent = config4.isSkillMode ? `Base directory for this skill: ${dirname47(file2.filePath)}
516413
+ let finalContent = config4.isSkillMode ? `Base directory for this skill: ${dirname48(file2.filePath)}
516320
516414
 
516321
516415
  ${content}` : content;
516322
516416
  finalContent = substituteArguments(finalContent, args, true, argumentNames);
@@ -516328,7 +516422,7 @@ ${content}` : content;
516328
516422
  finalContent = substituteUserConfigInContent(finalContent, loadPluginOptions(sourceName), pluginManifest.userConfig);
516329
516423
  }
516330
516424
  if (config4.isSkillMode) {
516331
- const rawSkillDir = dirname47(file2.filePath);
516425
+ const rawSkillDir = dirname48(file2.filePath);
516332
516426
  const skillDir = process.platform === "win32" ? rawSkillDir.replace(/\\/g, "/") : rawSkillDir;
516333
516427
  finalContent = finalContent.replace(/\$\{CLAUDE_SKILL_DIR\}/g, skillDir);
516334
516428
  }
@@ -516388,7 +516482,7 @@ async function loadSkillsFromDirectory(skillsPath, pluginName, sourceName, plugi
516388
516482
  const skillName = `${pluginName}:${basename32(skillsPath)}`;
516389
516483
  const file2 = {
516390
516484
  filePath: directSkillPath,
516391
- baseDir: dirname47(directSkillPath),
516485
+ baseDir: dirname48(directSkillPath),
516392
516486
  frontmatter,
516393
516487
  content: markdownContent
516394
516488
  };
@@ -516437,7 +516531,7 @@ async function loadSkillsFromDirectory(skillsPath, pluginName, sourceName, plugi
516437
516531
  const skillName = `${pluginName}:${entry.name}`;
516438
516532
  const file2 = {
516439
516533
  filePath: skillFilePath,
516440
- baseDir: dirname47(skillFilePath),
516534
+ baseDir: dirname48(skillFilePath),
516441
516535
  frontmatter,
516442
516536
  content: markdownContent
516443
516537
  };
@@ -516550,7 +516644,7 @@ var init_loadPluginCommands = __esm(() => {
516550
516644
  } : frontmatter;
516551
516645
  const file2 = {
516552
516646
  filePath: commandPath,
516553
- baseDir: dirname47(commandPath),
516647
+ baseDir: dirname48(commandPath),
516554
516648
  frontmatter: finalFrontmatter,
516555
516649
  content: markdownContent
516556
516650
  };
@@ -516675,7 +516769,7 @@ import {
516675
516769
  writeFile as writeFile24
516676
516770
  } from "fs/promises";
516677
516771
  import { tmpdir as tmpdir12 } from "os";
516678
- import { basename as basename33, dirname as dirname48, join as join103 } from "path";
516772
+ import { basename as basename33, dirname as dirname49, join as join103 } from "path";
516679
516773
  function isPluginZipCacheEnabled() {
516680
516774
  return isEnvTruthy(process.env.CLAUDE_CODE_PLUGIN_USE_ZIP_CACHE);
516681
516775
  }
@@ -516738,7 +516832,7 @@ async function cleanupSessionPluginCache() {
516738
516832
  }
516739
516833
  }
516740
516834
  async function atomicWriteToZipCache(targetPath, data) {
516741
- const dir = dirname48(targetPath);
516835
+ const dir = dirname49(targetPath);
516742
516836
  await getFsImplementation().mkdir(dir);
516743
516837
  const tmpName = `.${basename33(targetPath)}.tmp.${randomBytes11(4).toString("hex")}`;
516744
516838
  const tmpPath = join103(dir, tmpName);
@@ -516835,7 +516929,7 @@ async function extractZipToDirectory(zipPath, targetDir) {
516835
516929
  continue;
516836
516930
  }
516837
516931
  const fullPath = join103(targetDir, relPath);
516838
- await getFsImplementation().mkdir(dirname48(fullPath));
516932
+ await getFsImplementation().mkdir(dirname49(fullPath));
516839
516933
  await writeFile24(fullPath, data);
516840
516934
  const mode = modes[relPath];
516841
516935
  if (mode && mode & 73) {
@@ -517327,7 +517421,7 @@ var init_marketplaceHelpers = __esm(() => {
517327
517421
 
517328
517422
  // src/utils/plugins/officialMarketplaceGcs.ts
517329
517423
  import { chmod as chmod6, mkdir as mkdir27, readFile as readFile34, rename as rename6, rm as rm12, writeFile as writeFile26 } from "fs/promises";
517330
- import { dirname as dirname49, join as join105, resolve as resolve40, sep as sep28 } from "path";
517424
+ import { dirname as dirname50, join as join105, resolve as resolve40, sep as sep28 } from "path";
517331
517425
  async function fetchOfficialMarketplaceFromGcs(installLocation, marketplacesCacheDir) {
517332
517426
  const cacheDir = resolve40(marketplacesCacheDir);
517333
517427
  const resolvedLoc = resolve40(installLocation);
@@ -517374,7 +517468,7 @@ async function fetchOfficialMarketplaceFromGcs(installLocation, marketplacesCach
517374
517468
  if (!rel || rel.endsWith("/"))
517375
517469
  continue;
517376
517470
  const dest = join105(staging, rel);
517377
- await mkdir27(dirname49(dest), { recursive: true });
517471
+ await mkdir27(dirname50(dest), { recursive: true });
517378
517472
  await writeFile26(dest, data);
517379
517473
  const mode = modes[arcPath];
517380
517474
  if (mode && mode & 73) {
@@ -517448,7 +517542,7 @@ var init_officialMarketplaceGcs = __esm(() => {
517448
517542
 
517449
517543
  // src/utils/plugins/marketplaceManager.ts
517450
517544
  import { writeFile as writeFile27 } from "fs/promises";
517451
- import { basename as basename34, dirname as dirname50, isAbsolute as isAbsolute32, join as join106, resolve as resolve41, sep as sep29 } from "path";
517545
+ import { basename as basename34, dirname as dirname51, isAbsolute as isAbsolute32, join as join106, resolve as resolve41, sep as sep29 } from "path";
517452
517546
  function getKnownMarketplacesFile() {
517453
517547
  return join106(getPluginsDirectory(), "known_marketplaces.json");
517454
517548
  }
@@ -518128,7 +518222,7 @@ async function loadAndCacheMarketplace(source, onProgress) {
518128
518222
  case "file": {
518129
518223
  const absPath = resolve41(source.path);
518130
518224
  marketplacePath = absPath;
518131
- temporaryCachePath = dirname50(dirname50(absPath));
518225
+ temporaryCachePath = dirname51(dirname51(absPath));
518132
518226
  cleanupNeeded = false;
518133
518227
  break;
518134
518228
  }
@@ -518143,7 +518237,7 @@ async function loadAndCacheMarketplace(source, onProgress) {
518143
518237
  temporaryCachePath = join106(cacheDir, source.name);
518144
518238
  marketplacePath = join106(temporaryCachePath, ".claude-plugin", "marketplace.json");
518145
518239
  cleanupNeeded = false;
518146
- await fs14.mkdir(dirname50(marketplacePath));
518240
+ await fs14.mkdir(dirname51(marketplacePath));
518147
518241
  await writeFile27(marketplacePath, jsonStringify({
518148
518242
  name: source.name,
518149
518243
  owner: source.owner ?? { name: "settings" },
@@ -518638,7 +518732,7 @@ var init_marketplaceManager = __esm(() => {
518638
518732
  });
518639
518733
 
518640
518734
  // src/utils/plugins/installedPluginsManager.ts
518641
- import { dirname as dirname51, join as join107 } from "path";
518735
+ import { dirname as dirname52, join as join107 } from "path";
518642
518736
  function getInstalledPluginsFilePath() {
518643
518737
  return join107(getPluginsDirectory(), "installed_plugins.json");
518644
518738
  }
@@ -519204,7 +519298,7 @@ var init_pluginVersioning = __esm(() => {
519204
519298
  // src/utils/plugins/pluginInstallationHelpers.ts
519205
519299
  import { randomBytes as randomBytes12 } from "crypto";
519206
519300
  import { rename as rename7, rm as rm13 } from "fs/promises";
519207
- import { dirname as dirname52, join as join108, resolve as resolve42, sep as sep30 } from "path";
519301
+ import { dirname as dirname53, join as join108, resolve as resolve42, sep as sep30 } from "path";
519208
519302
  function getCurrentTimestamp() {
519209
519303
  return new Date().toISOString();
519210
519304
  }
@@ -519228,14 +519322,14 @@ async function cacheAndRegisterPlugin(pluginId, entry, scope = "user", projectPa
519228
519322
  const versionedPath = getVersionedCachePath(pluginId, version2);
519229
519323
  let finalPath = cacheResult.path;
519230
519324
  if (cacheResult.path !== versionedPath) {
519231
- await getFsImplementation().mkdir(dirname52(versionedPath));
519325
+ await getFsImplementation().mkdir(dirname53(versionedPath));
519232
519326
  await rm13(versionedPath, { recursive: true, force: true });
519233
519327
  const normalizedCachePath = cacheResult.path.endsWith(sep30) ? cacheResult.path : cacheResult.path + sep30;
519234
519328
  const isSubdirectory = versionedPath.startsWith(normalizedCachePath);
519235
519329
  if (isSubdirectory) {
519236
- const tempPath = join108(dirname52(cacheResult.path), `.claude-plugin-temp-${Date.now()}-${randomBytes12(4).toString("hex")}`);
519330
+ const tempPath = join108(dirname53(cacheResult.path), `.claude-plugin-temp-${Date.now()}-${randomBytes12(4).toString("hex")}`);
519237
519331
  await rename7(cacheResult.path, tempPath);
519238
- await getFsImplementation().mkdir(dirname52(versionedPath));
519332
+ await getFsImplementation().mkdir(dirname53(versionedPath));
519239
519333
  await rename7(tempPath, versionedPath);
519240
519334
  } else {
519241
519335
  await rename7(cacheResult.path, versionedPath);
@@ -519464,7 +519558,7 @@ import {
519464
519558
  stat as stat34,
519465
519559
  symlink as symlink2
519466
519560
  } from "fs/promises";
519467
- import { basename as basename35, dirname as dirname53, join as join109, relative as relative26, resolve as resolve43, sep as sep31 } from "path";
519561
+ import { basename as basename35, dirname as dirname54, join as join109, relative as relative26, resolve as resolve43, sep as sep31 } from "path";
519468
519562
  function getPluginCachePath() {
519469
519563
  return join109(getPluginsDirectory(), "cache");
519470
519564
  }
@@ -519494,7 +519588,7 @@ async function probeSeedCache(pluginId, version2) {
519494
519588
  }
519495
519589
  async function probeSeedCacheAnyVersion(pluginId) {
519496
519590
  for (const seedDir of getPluginSeedDirs()) {
519497
- const pluginDir = dirname53(getVersionedCachePathIn(seedDir, pluginId, "_"));
519591
+ const pluginDir = dirname54(getVersionedCachePathIn(seedDir, pluginId, "_"));
519498
519592
  try {
519499
519593
  const versions2 = await readdir22(pluginDir);
519500
519594
  if (versions2.length !== 1)
@@ -519536,7 +519630,7 @@ async function copyDir(src, dest) {
519536
519630
  if (resolvedTarget.startsWith(srcPrefix) || resolvedTarget === resolvedSrc) {
519537
519631
  const targetRelativeToSrc = relative26(resolvedSrc, resolvedTarget);
519538
519632
  const destTargetPath = join109(dest, targetRelativeToSrc);
519539
- const relativeLinkPath = relative26(dirname53(destPath), destTargetPath);
519633
+ const relativeLinkPath = relative26(dirname54(destPath), destTargetPath);
519540
519634
  await symlink2(relativeLinkPath, destPath);
519541
519635
  } else {
519542
519636
  await symlink2(resolvedTarget, destPath);
@@ -519567,7 +519661,7 @@ async function copyPluginToVersionedCache(sourcePath, pluginId, version2, entry,
519567
519661
  logForDebugging(`Using seed cache for ${pluginId}@${version2} at ${seedPath}`);
519568
519662
  return seedPath;
519569
519663
  }
519570
- await getFsImplementation().mkdir(dirname53(cachePath));
519664
+ await getFsImplementation().mkdir(dirname54(cachePath));
519571
519665
  if (entry && typeof entry.source === "string" && marketplaceDir) {
519572
519666
  const sourceDir = validatePathWithinBase(marketplaceDir, entry.source);
519573
519667
  logForDebugging(`Copying source directory ${entry.source} for plugin ${pluginId}`);
@@ -526445,7 +526539,7 @@ var init_projectOnboardingState = __esm(() => {
526445
526539
 
526446
526540
  // src/utils/appleTerminalBackup.ts
526447
526541
  import { stat as stat35 } from "fs/promises";
526448
- import { homedir as homedir25 } from "os";
526542
+ import { homedir as homedir26 } from "os";
526449
526543
  import { join as join111 } from "path";
526450
526544
  function markTerminalSetupInProgress(backupPath) {
526451
526545
  saveGlobalConfig((current) => ({
@@ -526468,7 +526562,7 @@ function getTerminalRecoveryInfo() {
526468
526562
  };
526469
526563
  }
526470
526564
  function getTerminalPlistPath() {
526471
- return join111(homedir25(), "Library", "Preferences", "com.apple.Terminal.plist");
526565
+ return join111(homedir26(), "Library", "Preferences", "com.apple.Terminal.plist");
526472
526566
  }
526473
526567
  async function backupTerminalPreferences() {
526474
526568
  const terminalPlistPath = getTerminalPlistPath();
@@ -526562,8 +526656,8 @@ __export(exports_terminalSetup, {
526562
526656
  });
526563
526657
  import { randomBytes as randomBytes14 } from "crypto";
526564
526658
  import { copyFile as copyFile8, mkdir as mkdir28, readFile as readFile36, writeFile as writeFile28 } from "fs/promises";
526565
- import { homedir as homedir26, platform as platform3 } from "os";
526566
- import { dirname as dirname54, join as join112 } from "path";
526659
+ import { homedir as homedir27, platform as platform3 } from "os";
526660
+ import { dirname as dirname55, join as join112 } from "path";
526567
526661
  import { pathToFileURL as pathToFileURL7 } from "url";
526568
526662
  function isVSCodeRemoteSSH() {
526569
526663
  const askpassMain = process.env.VSCODE_GIT_ASKPASS_MAIN ?? "";
@@ -526698,7 +526792,7 @@ async function installBindingsForVSCodeTerminal(editor = "VSCode", theme) {
526698
526792
  ]`)}${EOL6}`;
526699
526793
  }
526700
526794
  const editorDir = editor === "VSCode" ? "Code" : editor;
526701
- const userDirPath = join112(homedir26(), platform3() === "win32" ? join112("AppData", "Roaming", editorDir, "User") : platform3() === "darwin" ? join112("Library", "Application Support", editorDir, "User") : join112(".config", editorDir, "User"));
526795
+ const userDirPath = join112(homedir27(), platform3() === "win32" ? join112("AppData", "Roaming", editorDir, "User") : platform3() === "darwin" ? join112("Library", "Application Support", editorDir, "User") : join112(".config", editorDir, "User"));
526702
526796
  const keybindingsPath = join112(userDirPath, "keybindings.json");
526703
526797
  try {
526704
526798
  await mkdir28(userDirPath, {
@@ -526842,7 +526936,7 @@ chars = "\\u001B\\r"`;
526842
526936
  if (xdgConfigHome) {
526843
526937
  configPaths.push(join112(xdgConfigHome, "alacritty", "alacritty.toml"));
526844
526938
  } else {
526845
- configPaths.push(join112(homedir26(), ".config", "alacritty", "alacritty.toml"));
526939
+ configPaths.push(join112(homedir27(), ".config", "alacritty", "alacritty.toml"));
526846
526940
  }
526847
526941
  if (platform3() === "win32") {
526848
526942
  const appData = process.env.APPDATA;
@@ -526885,7 +526979,7 @@ chars = "\\u001B\\r"`;
526885
526979
  return `${color("warning", theme)("Error backing up existing Alacritty config. Bailing out.")}${EOL6}${source_default.dim(`See ${formatPathLink(configPath2)}`)}${EOL6}${source_default.dim(`Backup path: ${formatPathLink(backupPath)}`)}${EOL6}`;
526886
526980
  }
526887
526981
  } else {
526888
- await mkdir28(dirname54(configPath2), {
526982
+ await mkdir28(dirname55(configPath2), {
526889
526983
  recursive: true
526890
526984
  });
526891
526985
  }
@@ -526908,7 +527002,7 @@ chars = "\\u001B\\r"`;
526908
527002
  }
526909
527003
  }
526910
527004
  async function installBindingsForZed(theme) {
526911
- const zedDir = join112(homedir26(), ".config", "zed");
527005
+ const zedDir = join112(homedir27(), ".config", "zed");
526912
527006
  const keymapPath = join112(zedDir, "keymap.json");
526913
527007
  try {
526914
527008
  await mkdir28(zedDir, {
@@ -529350,7 +529444,7 @@ var init_TextInput = __esm(() => {
529350
529444
  });
529351
529445
 
529352
529446
  // src/utils/suggestions/directoryCompletion.ts
529353
- import { basename as basename39, dirname as dirname55, join as join115, sep as sep32 } from "path";
529447
+ import { basename as basename39, dirname as dirname56, join as join115, sep as sep32 } from "path";
529354
529448
  function parsePartialPath(partialPath, basePath) {
529355
529449
  if (!partialPath) {
529356
529450
  const directory2 = basePath || getCwd();
@@ -529360,7 +529454,7 @@ function parsePartialPath(partialPath, basePath) {
529360
529454
  if (partialPath.endsWith("/") || partialPath.endsWith(sep32)) {
529361
529455
  return { directory: resolved, prefix: "" };
529362
529456
  }
529363
- const directory = dirname55(resolved);
529457
+ const directory = dirname56(resolved);
529364
529458
  const prefix = basename39(partialPath);
529365
529459
  return { directory, prefix };
529366
529460
  }
@@ -531012,7 +531106,7 @@ function Feedback({
531012
531106
  platform: env4.platform,
531013
531107
  gitRepo: envInfo.isGit,
531014
531108
  terminal: env4.terminal,
531015
- version: "1.3.434",
531109
+ version: "1.3.436",
531016
531110
  transcript: normalizeMessagesForAPI(messages),
531017
531111
  errors: sanitizedErrors,
531018
531112
  lastApiRequest: getLastAPIRequest(),
@@ -531204,7 +531298,7 @@ function Feedback({
531204
531298
  ", ",
531205
531299
  env4.terminal,
531206
531300
  ", v",
531207
- "1.3.434"
531301
+ "1.3.436"
531208
531302
  ]
531209
531303
  }, undefined, true, undefined, this)
531210
531304
  ]
@@ -531310,7 +531404,7 @@ ${sanitizedDescription}
531310
531404
  ` + `**Environment Info**
531311
531405
  ` + `- Platform: ${env4.platform}
531312
531406
  ` + `- Terminal: ${env4.terminal}
531313
- ` + `- Version: ${"1.3.434"}
531407
+ ` + `- Version: ${"1.3.436"}
531314
531408
  ` + `- Feedback ID: ${feedbackId}
531315
531409
  ` + `
531316
531410
  **Errors**
@@ -534144,15 +534238,15 @@ var init_shellConfig = __esm(() => {
534144
534238
  // src/utils/autoUpdater.ts
534145
534239
  import { constants as fsConstants3 } from "fs";
534146
534240
  import { access as access5, writeFile as writeFile33 } from "fs/promises";
534147
- import { homedir as homedir27 } from "os";
534241
+ import { homedir as homedir28 } from "os";
534148
534242
  import { join as join121 } from "path";
534149
534243
  async function assertMinVersion() {
534150
534244
  if (false) {}
534151
534245
  try {
534152
534246
  const versionConfig = await getDynamicConfig_BLOCKS_ON_INIT("tengu_version_config", { minVersion: "0.0.0" });
534153
- if (versionConfig.minVersion && lt("1.3.434", versionConfig.minVersion)) {
534247
+ if (versionConfig.minVersion && lt("1.3.436", versionConfig.minVersion)) {
534154
534248
  console.error(`
534155
- It looks like your version of RAYU (${"1.3.434"}) needs an update.
534249
+ It looks like your version of RAYU (${"1.3.436"}) needs an update.
534156
534250
  A newer version (${versionConfig.minVersion} or higher) is required to continue.
534157
534251
 
534158
534252
  To update, please run:
@@ -534277,10 +534371,10 @@ async function getInstallationPrefix() {
534277
534371
  let prefixResult = null;
534278
534372
  if (isBun) {
534279
534373
  prefixResult = await execFileNoThrowWithCwd("bun", ["pm", "bin", "-g"], {
534280
- cwd: homedir27()
534374
+ cwd: homedir28()
534281
534375
  });
534282
534376
  } else {
534283
- prefixResult = await execFileNoThrowWithCwd("npm", ["-g", "config", "get", "prefix"], { cwd: homedir27() });
534377
+ prefixResult = await execFileNoThrowWithCwd("npm", ["-g", "config", "get", "prefix"], { cwd: homedir28() });
534284
534378
  }
534285
534379
  if (prefixResult.code !== 0) {
534286
534380
  logError2(new Error(`Failed to check ${isBun ? "bun" : "npm"} permissions`));
@@ -534308,7 +534402,7 @@ async function checkGlobalInstallPermissions() {
534308
534402
  }
534309
534403
  async function getLatestVersion(channel) {
534310
534404
  const npmTag = channel === "stable" ? "stable" : "latest";
534311
- const result = await execFileNoThrowWithCwd("npm", ["view", `${"@rayu-dev/rayu-cli"}@${npmTag}`, "version", "--prefer-online"], { abortSignal: AbortSignal.timeout(5000), cwd: homedir27() });
534405
+ const result = await execFileNoThrowWithCwd("npm", ["view", `${"@rayu-dev/rayu-cli"}@${npmTag}`, "version", "--prefer-online"], { abortSignal: AbortSignal.timeout(5000), cwd: homedir28() });
534312
534406
  if (result.code !== 0) {
534313
534407
  logForDebugging(`npm view failed with code ${result.code}`);
534314
534408
  if (result.stderr) {
@@ -534324,7 +534418,7 @@ async function getLatestVersion(channel) {
534324
534418
  return result.stdout.trim();
534325
534419
  }
534326
534420
  async function getNpmDistTags() {
534327
- const result = await execFileNoThrowWithCwd("npm", ["view", "@rayu-dev/rayu-cli", "dist-tags", "--json", "--prefer-online"], { abortSignal: AbortSignal.timeout(5000), cwd: homedir27() });
534421
+ const result = await execFileNoThrowWithCwd("npm", ["view", "@rayu-dev/rayu-cli", "dist-tags", "--json", "--prefer-online"], { abortSignal: AbortSignal.timeout(5000), cwd: homedir28() });
534328
534422
  if (result.code !== 0) {
534329
534423
  logForDebugging(`npm view dist-tags failed with code ${result.code}`);
534330
534424
  return { latest: null, stable: null };
@@ -534378,7 +534472,7 @@ async function installGlobalPackage(specificVersion) {
534378
534472
  logError2(new AutoUpdaterError("Another process is currently installing an update"));
534379
534473
  logEvent("tengu_auto_updater_lock_contention", {
534380
534474
  pid: process.pid,
534381
- currentVersion: "1.3.434"
534475
+ currentVersion: "1.3.436"
534382
534476
  });
534383
534477
  return "in_progress";
534384
534478
  }
@@ -534387,7 +534481,7 @@ async function installGlobalPackage(specificVersion) {
534387
534481
  if (!env4.isRunningWithBun() && env4.isNpmFromWindowsPath()) {
534388
534482
  logError2(new Error("Windows NPM detected in WSL environment"));
534389
534483
  logEvent("tengu_auto_updater_windows_npm_in_wsl", {
534390
- currentVersion: "1.3.434"
534484
+ currentVersion: "1.3.436"
534391
534485
  });
534392
534486
  console.error(`
534393
534487
  Error: Windows NPM detected in WSL
@@ -534408,7 +534502,7 @@ To fix this issue:
534408
534502
  }
534409
534503
  const packageSpec = specificVersion ? `${"@rayu-dev/rayu-cli"}@${specificVersion}` : "@rayu-dev/rayu-cli";
534410
534504
  const packageManager = env4.isRunningWithBun() ? "bun" : "npm";
534411
- const installResult = await execFileNoThrowWithCwd(packageManager, ["install", "-g", packageSpec], { cwd: homedir27() });
534505
+ const installResult = await execFileNoThrowWithCwd(packageManager, ["install", "-g", packageSpec], { cwd: homedir28() });
534412
534506
  if (installResult.code !== 0) {
534413
534507
  const error54 = new AutoUpdaterError(`Failed to install new version of claude: ${installResult.stdout} ${installResult.stderr}`);
534414
534508
  logError2(error54);
@@ -534646,7 +534740,7 @@ var init_packageManagers = __esm(() => {
534646
534740
 
534647
534741
  // src/utils/doctorDiagnostic.ts
534648
534742
  import { readFile as readFile41, realpath as realpath11 } from "fs/promises";
534649
- import { homedir as homedir28 } from "os";
534743
+ import { homedir as homedir29 } from "os";
534650
534744
  import { delimiter as delimiter3, join as join122, posix as posix6, win32 as win323 } from "path";
534651
534745
  function getNormalizedPaths() {
534652
534746
  let invokedPath = process.argv[1] || "";
@@ -534710,8 +534804,8 @@ async function getInstallationPath() {
534710
534804
  }
534711
534805
  } catch {}
534712
534806
  try {
534713
- await getFsImplementation().stat(join122(homedir28(), ".local/bin/claude"));
534714
- return join122(homedir28(), ".local/bin/claude");
534807
+ await getFsImplementation().stat(join122(homedir29(), ".local/bin/claude"));
534808
+ return join122(homedir29(), ".local/bin/claude");
534715
534809
  } catch {}
534716
534810
  return "native";
534717
534811
  }
@@ -534781,14 +534875,14 @@ async function detectMultipleInstallations() {
534781
534875
  }
534782
534876
  }
534783
534877
  }
534784
- const nativeBinPath = join122(homedir28(), ".local", "bin", "claude");
534878
+ const nativeBinPath = join122(homedir29(), ".local", "bin", "claude");
534785
534879
  try {
534786
534880
  await fs14.stat(nativeBinPath);
534787
534881
  installations.push({ type: "native", path: nativeBinPath });
534788
534882
  } catch {}
534789
534883
  const config4 = getGlobalConfig();
534790
534884
  if (config4.installMethod === "native") {
534791
- const nativeDataPath = join122(homedir28(), ".local", "share", "claude");
534885
+ const nativeDataPath = join122(homedir29(), ".local", "share", "claude");
534792
534886
  try {
534793
534887
  await fs14.stat(nativeDataPath);
534794
534888
  if (!installations.some((i4) => i4.type === "native")) {
@@ -534828,7 +534922,7 @@ async function detectConfigurationIssues(type) {
534828
534922
  if (type === "native") {
534829
534923
  const path25 = process.env.PATH || "";
534830
534924
  const pathDirectories = path25.split(delimiter3);
534831
- const homeDir = homedir28();
534925
+ const homeDir = homedir29();
534832
534926
  const localBinPath = join122(homeDir, ".local", "bin");
534833
534927
  let normalizedLocalBinPath = localBinPath;
534834
534928
  if (getPlatform() === "windows") {
@@ -534855,7 +534949,7 @@ async function detectConfigurationIssues(type) {
534855
534949
  const shellType = getShellType();
534856
534950
  const configPaths = getShellConfigPaths();
534857
534951
  const configFile = configPaths[shellType];
534858
- const displayPath = configFile ? configFile.replace(homedir28(), "~") : "your shell config file";
534952
+ const displayPath = configFile ? configFile.replace(homedir29(), "~") : "your shell config file";
534859
534953
  warnings.push({
534860
534954
  issue: "Native installation exists but ~/.local/bin is not in your PATH",
534861
534955
  fix: `Run: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ${displayPath} then open a new terminal or run: source ${displayPath}`
@@ -534923,7 +535017,7 @@ function detectLinuxGlobPatternWarnings() {
534923
535017
  }
534924
535018
  async function getDoctorDiagnostic() {
534925
535019
  const installationType = await getCurrentInstallationType();
534926
- const version2 = typeof MACRO !== "undefined" ? "1.3.434" : "unknown";
535020
+ const version2 = typeof MACRO !== "undefined" ? "1.3.436" : "unknown";
534927
535021
  const installationPath = await getInstallationPath();
534928
535022
  const invokedBinary = getInvokedBinary();
534929
535023
  const multipleInstallations = await detectMultipleInstallations();
@@ -535454,8 +535548,8 @@ import {
535454
535548
  unlink as unlink16,
535455
535549
  writeFile as writeFile35
535456
535550
  } from "fs/promises";
535457
- import { homedir as homedir29 } from "os";
535458
- import { basename as basename41, delimiter as delimiter4, dirname as dirname57, join as join126, resolve as resolve45 } from "path";
535551
+ import { homedir as homedir30 } from "os";
535552
+ import { basename as basename41, delimiter as delimiter4, dirname as dirname58, join as join126, resolve as resolve45 } from "path";
535459
535553
  function getPlatform3() {
535460
535554
  const os7 = env4.platform;
535461
535555
  const arch = process.arch === "x64" ? "x64" : process.arch === "arm64" ? "arm64" : null;
@@ -535498,7 +535592,7 @@ async function getVersionPaths(version2) {
535498
535592
  const dirs = getBaseDirectories();
535499
535593
  const dirsToCreate = [dirs.versions, dirs.staging, dirs.locks];
535500
535594
  await Promise.all(dirsToCreate.map((dir) => mkdir31(dir, { recursive: true })));
535501
- const executableParentDir = dirname57(dirs.executable);
535595
+ const executableParentDir = dirname58(dirs.executable);
535502
535596
  await mkdir31(executableParentDir, { recursive: true });
535503
535597
  const installPath = join126(dirs.versions, version2);
535504
535598
  try {
@@ -535592,7 +535686,7 @@ async function tryWithVersionLock(versionFilePath, callback, retries = 0) {
535592
535686
  }
535593
535687
  }
535594
535688
  async function atomicMoveToInstallPath(stagedBinaryPath, installPath) {
535595
- await mkdir31(dirname57(installPath), { recursive: true });
535689
+ await mkdir31(dirname58(installPath), { recursive: true });
535596
535690
  const tempInstallPath = `${installPath}.tmp.${process.pid}.${Date.now()}`;
535597
535691
  try {
535598
535692
  await copyFile9(stagedBinaryPath, tempInstallPath);
@@ -535718,8 +535812,8 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
535718
535812
  const maxVersion = await getMaxVersion();
535719
535813
  if (maxVersion && gt(version2, maxVersion)) {
535720
535814
  logForDebugging(`Native installer: maxVersion ${maxVersion} is set, capping update from ${version2} to ${maxVersion}`);
535721
- if (gte("1.3.434", maxVersion)) {
535722
- logForDebugging(`Native installer: current version ${"1.3.434"} is already at or above maxVersion ${maxVersion}, skipping update`);
535815
+ if (gte("1.3.436", maxVersion)) {
535816
+ logForDebugging(`Native installer: current version ${"1.3.436"} is already at or above maxVersion ${maxVersion}, skipping update`);
535723
535817
  logEvent("tengu_native_update_skipped_max_version", {
535724
535818
  latency_ms: Date.now() - startTime,
535725
535819
  max_version: maxVersion,
@@ -535730,7 +535824,7 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
535730
535824
  version2 = maxVersion;
535731
535825
  }
535732
535826
  }
535733
- if (!forceReinstall && version2 === "1.3.434" && await versionIsAvailable(version2) && await isPossibleClaudeBinary(executablePath)) {
535827
+ if (!forceReinstall && version2 === "1.3.436" && await versionIsAvailable(version2) && await isPossibleClaudeBinary(executablePath)) {
535734
535828
  logForDebugging(`Found ${version2} at ${executablePath}, skipping install`);
535735
535829
  logEvent("tengu_native_update_complete", {
535736
535830
  latency_ms: Date.now() - startTime,
@@ -535806,7 +535900,7 @@ async function updateSymlink(symlinkPath, targetPath) {
535806
535900
  const isWindows2 = platform4.startsWith("win32");
535807
535901
  if (isWindows2) {
535808
535902
  try {
535809
- const parentDir2 = dirname57(symlinkPath);
535903
+ const parentDir2 = dirname58(symlinkPath);
535810
535904
  await mkdir31(parentDir2, { recursive: true });
535811
535905
  let existingStats;
535812
535906
  try {
@@ -535852,7 +535946,7 @@ async function updateSymlink(symlinkPath, targetPath) {
535852
535946
  return false;
535853
535947
  }
535854
535948
  }
535855
- const parentDir = dirname57(symlinkPath);
535949
+ const parentDir = dirname58(symlinkPath);
535856
535950
  try {
535857
535951
  await mkdir31(parentDir, { recursive: true });
535858
535952
  logForDebugging(`Created directory ${parentDir} for symlink`);
@@ -535869,7 +535963,7 @@ async function updateSymlink(symlinkPath, targetPath) {
535869
535963
  if (symlinkExists) {
535870
535964
  try {
535871
535965
  const currentTarget = await readlink3(symlinkPath);
535872
- const resolvedCurrentTarget = resolve45(dirname57(symlinkPath), currentTarget);
535966
+ const resolvedCurrentTarget = resolve45(dirname58(symlinkPath), currentTarget);
535873
535967
  const resolvedTargetPath = resolve45(targetPath);
535874
535968
  if (resolvedCurrentTarget === resolvedTargetPath) {
535875
535969
  return false;
@@ -535909,7 +536003,7 @@ async function checkInstall(force = false) {
535909
536003
  }
535910
536004
  const dirs = getBaseDirectories();
535911
536005
  const messages = [];
535912
- const localBinDir = dirname57(dirs.executable);
536006
+ const localBinDir = dirname58(dirs.executable);
535913
536007
  const resolvedLocalBinPath = resolve45(localBinDir);
535914
536008
  const platform4 = getPlatform3();
535915
536009
  const isWindows2 = platform4.startsWith("win32");
@@ -535933,7 +536027,7 @@ async function checkInstall(force = false) {
535933
536027
  } else {
535934
536028
  try {
535935
536029
  const target = await readlink3(dirs.executable);
535936
- const absoluteTarget = resolve45(dirname57(dirs.executable), target);
536030
+ const absoluteTarget = resolve45(dirname58(dirs.executable), target);
535937
536031
  if (!await isPossibleClaudeBinary(absoluteTarget)) {
535938
536032
  messages.push({
535939
536033
  message: `Claude symlink points to missing or invalid binary: ${target}`,
@@ -535982,7 +536076,7 @@ async function checkInstall(force = false) {
535982
536076
  const shellType = getShellType();
535983
536077
  const configPaths = getShellConfigPaths();
535984
536078
  const configFile = configPaths[shellType];
535985
- const displayPath = configFile ? configFile.replace(homedir29(), "~") : "your shell config file";
536079
+ const displayPath = configFile ? configFile.replace(homedir30(), "~") : "your shell config file";
535986
536080
  messages.push({
535987
536081
  message: `Native installation exists but ~/.local/bin is not in your PATH. Run:
535988
536082
 
@@ -536040,7 +536134,7 @@ async function installLatestImpl(channelOrVersion, forceReinstall = false) {
536040
536134
  async function getVersionFromSymlink(symlinkPath) {
536041
536135
  try {
536042
536136
  const target = await readlink3(symlinkPath);
536043
- const absoluteTarget = resolve45(dirname57(symlinkPath), target);
536137
+ const absoluteTarget = resolve45(dirname58(symlinkPath), target);
536044
536138
  if (await isPossibleClaudeBinary(absoluteTarget)) {
536045
536139
  return absoluteTarget;
536046
536140
  }
@@ -536135,7 +536229,7 @@ async function cleanupOldVersions() {
536135
536229
  const dirs = getBaseDirectories();
536136
536230
  const oneHourAgo = Date.now() - 3600000;
536137
536231
  if (getPlatform3().startsWith("win32")) {
536138
- const executableDir = dirname57(dirs.executable);
536232
+ const executableDir = dirname58(dirs.executable);
536139
536233
  try {
536140
536234
  const files2 = await readdir24(executableDir);
536141
536235
  let cleanedCount = 0;
@@ -536483,7 +536577,7 @@ async function cleanupNpmInstallations() {
536483
536577
  errors6.push(macroPackageResult.error);
536484
536578
  }
536485
536579
  }
536486
- const localInstallDir = join126(homedir29(), ".claude", "local");
536580
+ const localInstallDir = join126(homedir30(), ".claude", "local");
536487
536581
  try {
536488
536582
  await rm15(localInstallDir, { recursive: true });
536489
536583
  removed++;
@@ -536926,7 +537020,7 @@ function buildPrimarySection() {
536926
537020
  }, undefined, false, undefined, this);
536927
537021
  return [{
536928
537022
  label: "Version",
536929
- value: "1.3.434"
537023
+ value: "1.3.436"
536930
537024
  }, {
536931
537025
  label: "Session name",
536932
537026
  value: nameValue
@@ -540617,7 +540711,7 @@ function Config({
540617
540711
  }
540618
540712
  }, undefined, false, undefined, this)
540619
540713
  }, undefined, false, undefined, this) : showSubmenu === "ChannelDowngrade" ? /* @__PURE__ */ jsx_dev_runtime170.jsxDEV(ChannelDowngradeDialog, {
540620
- currentVersion: "1.3.434",
540714
+ currentVersion: "1.3.436",
540621
540715
  onChoice: (choice) => {
540622
540716
  setShowSubmenu(null);
540623
540717
  setTabsHidden(false);
@@ -540629,7 +540723,7 @@ function Config({
540629
540723
  autoUpdatesChannel: "stable"
540630
540724
  };
540631
540725
  if (choice === "stay") {
540632
- newSettings.minimumVersion = "1.3.434";
540726
+ newSettings.minimumVersion = "1.3.436";
540633
540727
  }
540634
540728
  updateSettingsForSource("userSettings", newSettings);
540635
540729
  setSettingsData((prev_27) => ({
@@ -547494,10 +547588,10 @@ var init_MemoryFileSelector = __esm(() => {
547494
547588
  });
547495
547589
 
547496
547590
  // src/components/memory/MemoryUpdateNotification.tsx
547497
- import { homedir as homedir30 } from "os";
547591
+ import { homedir as homedir31 } from "os";
547498
547592
  import { relative as relative29 } from "path";
547499
547593
  function getRelativeMemoryPath(path25) {
547500
- const homeDir = homedir30();
547594
+ const homeDir = homedir31();
547501
547595
  const cwd2 = getCwd();
547502
547596
  const relativeToHome = path25.startsWith(homeDir) ? "~" + path25.slice(homeDir.length) : null;
547503
547597
  const relativeToCwd = path25.startsWith(cwd2) ? "./" + relative29(cwd2, path25) : null;
@@ -548691,7 +548785,7 @@ function HelpV2(t0) {
548691
548785
  let t6;
548692
548786
  if ($3[31] !== tabs) {
548693
548787
  t6 = /* @__PURE__ */ jsx_dev_runtime197.jsxDEV(Tabs, {
548694
- title: `Rayu-CLI v${"1.3.434"}`,
548788
+ title: `Rayu-CLI v${"1.3.436"}`,
548695
548789
  color: "professionalBlue",
548696
548790
  defaultTab: "general",
548697
548791
  children: tabs
@@ -549730,7 +549824,7 @@ var init_ide3 = __esm(() => {
549730
549824
  });
549731
549825
 
549732
549826
  // src/commands/init.ts
549733
- import { existsSync as existsSync22, writeFileSync as writeFileSync11 } from "fs";
549827
+ import { existsSync as existsSync22, writeFileSync as writeFileSync12 } from "fs";
549734
549828
  import { join as join129 } from "path";
549735
549829
  function ensureRayuMd() {
549736
549830
  try {
@@ -549738,7 +549832,7 @@ function ensureRayuMd() {
549738
549832
  if (existsSync22(join129(cwd2, "RAYU.md"))) {
549739
549833
  return;
549740
549834
  }
549741
- writeFileSync11(join129(cwd2, "RAYU.md"), RAYU_MD_SCAFFOLD, { flag: "wx" });
549835
+ writeFileSync12(join129(cwd2, "RAYU.md"), RAYU_MD_SCAFFOLD, { flag: "wx" });
549742
549836
  } catch {}
549743
549837
  }
549744
549838
  var RAYU_MD_SCAFFOLD = `# RAYU.md
@@ -550089,7 +550183,7 @@ ${taskLine}
550089
550183
 
550090
550184
  ## Your role: PURE ORCHESTRATOR — you do NOT write code
550091
550185
  In this mode you NEVER write or edit code, run build/implementation commands, or do domain work yourself. Your job is ONLY to:
550092
- - ANALYZE the real project and requirements — read code to understand it, and discuss & plan WITH the \`PA\` subagent to reach a clear, grounded plan/architecture.
550186
+ - ANALYZE the real project and requirements — read code to understand it, and discuss & plan WITH the \`planner\` subagent to reach a clear, grounded plan/architecture.
550093
550187
  - DECOMPOSE and ASSIGN the work to the right Collaborators (implementers) and Subagents (one-shot helpers).
550094
550188
  - CHECK and verify their results (via the \`review\` subagent and by reading their outputs) and integrate them.
550095
550189
  HARD RULE: if a Collaborator or Subagent stalls, errors, or doesn't respond, you RESUME it (SendMessage), re-dispatch it, or escalate to the user — you do NOT take over and implement it yourself. Never silently become the coder, even if it seems faster.
@@ -550098,17 +550192,20 @@ Keep going until the task is fully resolved; state assumptions and continue —
550098
550192
  ## The three tiers
550099
550193
  - **You (Orchestrator)** — scope, plan, own SharedContext, coordinate, integrate. You delegate all implementation; you call only the orchestrator-level subagents directly.
550100
550194
  - **Collaborators (Tier 2)** — semi-persistent domain implementers you delegate to: \`frontend\`, \`backend\` (incl. database), \`mobile\`, \`security\`, \`deploy\`. Spawn each as a NAMED BACKGROUND agent (run_in_background:true, stable lowercase name) so you can resume it with SendMessage instead of respawning. They have full tools and may dispatch ONLY their allowed subagents (see the matrix).
550101
- - **Subagents (Tier 3)** — ephemeral one-shot helpers: \`PA\` (deep plan/research — orchestrator only), \`design\` (UI/UX + component PRD), \`backend-design\` (API + Data Model PRD), \`global-setup\` (scaffold — orchestrator only), \`asset-generation\` (images), \`review\` (audit → Fix List), \`fix\` (apply Fix List), \`linter\`, plus \`Explore\` and \`general-purpose\` (research).
550195
+ - **Subagents (Tier 3)** — ephemeral one-shot helpers: \`planner\` (deep plan/research — orchestrator only), \`design\` (UI/UX + component PRD), \`backend-design\` (API + Data Model PRD), \`global-setup\` (scaffold — orchestrator only), \`asset-generation\` (images), \`review\` (audit → Fix List), \`fix\` (apply Fix List), \`linter\`, plus \`Explore\` and \`general-purpose\` (research).
550102
550196
 
550103
550197
  ## Subagent specialization matrix (who may call what)
550104
550198
  Domain-locked so each agent uses only what fits its specialty:
550105
- - **You (Orchestrator):** PA, global-setup, design, backend-design, asset-generation, review, fix, linter, Explore, general-purpose.
550199
+ - **You (Orchestrator):** planner, global-setup, design, backend-design, asset-generation, review, fix, linter, Explore, general-purpose.
550106
550200
  - **frontend:** design, asset-generation, review, fix, linter, Explore, general-purpose. (NOT backend-design.)
550107
550201
  - **backend:** backend-design, review, fix, linter, Explore, general-purpose. (NOT design or asset-generation.)
550108
550202
  - **mobile:** design, asset-generation, backend-design, review, fix, linter, Explore, general-purpose.
550109
550203
  - **security:** backend-design, review, fix, linter, Explore, general-purpose.
550110
550204
  - **deploy:** review, fix, linter, Explore, general-purpose.
550111
- \`PA\` and \`global-setup\` are ORCHESTRATOR-ONLY — collaborators implement; they never re-plan or re-scaffold. (These limits are also enforced in code.)
550205
+ \`planner\` and \`global-setup\` are ORCHESTRATOR-ONLY — collaborators implement; they never re-plan or re-scaffold. (These limits are also enforced in code.)
550206
+
550207
+ ## Bundled skills (use them — no install needed)
550208
+ rayu ships original skills, always available via the Skill tool: \`rayu-frontend-design\`, \`rayu-design-system\`, \`rayu-theme-factory\`, \`rayu-brand-guidelines\` (UI / design / brand), \`rayu-canvas-design\` + \`rayu-algorithmic-art\` (generated graphics & generative art), \`rayu-web-artifacts-builder\` (standalone interactive pages), \`rayu-api-design\` + \`rayu-mcp-builder\` (backend), \`rayu-web-testing\` (QA/verification), \`rayu-doc-export\` (docx/xlsx/pptx/pdf deliverables). Tell each collaborator to pull the skill that fits its task — frontend/mobile → design / theme / artifacts; design & asset-generation → canvas / algorithmic-art / brand; backend → api / mcp; review/security → web-testing; any document deliverable → doc-export. Beyond the bundled set, you and the collaborators may also use any skill the user has installed, or install a relevant one on demand from the official Anthropic skills repo (\`anthropics/skills\`) via the InstallSkill tool.
550112
550209
 
550113
550210
  ## DEFAULT TO PARALLEL (the single most important rule)
550114
550211
  Parallel execution is ~3–5x faster than sequential. Unless one call genuinely needs another's output, dispatch independent agents/tools TOGETHER in ONE assistant message (multiple Agent calls), not one-per-message. Plan all the calls you'll need upfront, then fire them together. Cap each batch at ~3–5 calls to avoid timeouts. Sequential is the exception, allowed ONLY on a true dependency. One-per-message dispatch is the #1 cause of slow swarm runs — avoid it.
@@ -550118,13 +550215,13 @@ Parallel execution is ~3–5x faster than sequential. Unless one call genuinely
550118
550215
  - Spawn **Collaborators in the BACKGROUND** (\`run_in_background:true\`, stable lowercase name). Background is the ONLY mode that is resumable via \`SendMessage\`, so semi-persistent collaborators MUST be background. The user watches a collaborator's detailed work by entering its view (↓ then Enter); the task panel shows each collaborator's high-level status (including \`thinking…\`).
550119
550216
 
550120
550217
  ## The 3-phase build flow
550121
- ### Phase 1 — Scope & Research (you + PA, in the foreground)
550218
+ ### Phase 1 — Scope & Research (you + planner, in the foreground)
550122
550219
  - Clarify the request: ask the user for the missing DETAIL and SCOPE, and ask their PREFERRED TECH STACK — offer 2–3 concrete recommendations with a one-line rationale each (don't make them guess).
550123
- - For any OPEN implementation choice (e.g. a payment provider — Stripe vs a bank gateway vs ABA), dispatch the \`PA\` subagent to RESEARCH the real, available options for THIS project and return a short comparison; present those options to the user and let them choose. Loop until you have everything you need.
550220
+ - For any OPEN implementation choice (e.g. a payment provider — Stripe vs a bank gateway vs ABA), dispatch the \`planner\` subagent to RESEARCH the real, available options for THIS project and return a short comparison; present those options to the user and let them choose. Loop until you have everything you need.
550124
550221
 
550125
- ### Phase 2 — One aligned plan (PA → you → user)
550126
- - Hand the gathered context to \`PA\` for a deep, reasoned plan. PA must produce ONE coherent plan that is explicitly ALIGNED across backend AND frontend (shared API contract, data model, auth flow) — never two disjoint plans.
550127
- - Relay PA's plan to the user for FINAL confirmation. (In plan mode, that's the ExitPlanMode approval — confirming auto-enters swarm execution.)
550222
+ ### Phase 2 — One aligned plan (planner → you → user)
550223
+ - Hand the gathered context to \`planner\` for a deep, reasoned plan. The planner must produce ONE coherent plan that is explicitly ALIGNED across backend AND frontend (shared API contract, data model, auth flow) — never two disjoint plans.
550224
+ - Relay the planner's plan to the user for FINAL confirmation. (In plan mode, that's the ExitPlanMode approval — confirming auto-enters swarm execution.) You ALREADY receive the planner's full plan as its returned result — use that directly. Do NOT re-read \`.rayu/swarm/PLANNER.md\`: the swarm \`.md\` files exist so the COLLABORATORS can read each other's contracts, not for you to re-read your own subagents' returns — pulling a large plan back into your own context wastes tokens and can make the request time out.
550128
550225
 
550129
550226
  ### Phase 3 — Build (decompose by specialty; run as a dependency graph, not fixed waves)
550130
550227
  1. **Setup gate (one short step):** for a new project, run \`global-setup\` to scaffold the FE+BE folder structure + tooling.
@@ -550153,7 +550250,7 @@ Parallel execution is ~3–5x faster than sequential. Unless one call genuinely
550153
550250
  ## Finish
550154
550251
  Integrate the collaborators' outputs into one coherent result, crediting which collaborator produced what, and report concisely to the user — only after the verification gate (build/tests pass, review→fix clean).
550155
550252
 
550156
- This session is now in collaborator_swarm mode (it stays on for the whole session; the user exits with /normal). Begin with PHASE 1: state your understanding, ask the user for the missing scope + preferred tech stack (with recommendations), and dispatch \`PA\` for any implementation-option research the request needs.`
550253
+ This session is now in collaborator_swarm mode (it stays on for the whole session; the user exits with /normal). Begin with PHASE 1: state your understanding, ask the user for the missing scope + preferred tech stack (with recommendations), and dispatch \`planner\` for any implementation-option research the request needs.`
550157
550254
  }
550158
550255
  ];
550159
550256
  }
@@ -550223,7 +550320,7 @@ __export(exports_keybindings, {
550223
550320
  call: () => call18
550224
550321
  });
550225
550322
  import { mkdir as mkdir34, writeFile as writeFile37 } from "fs/promises";
550226
- import { dirname as dirname58 } from "path";
550323
+ import { dirname as dirname59 } from "path";
550227
550324
  async function call18() {
550228
550325
  if (!isKeybindingCustomizationEnabled()) {
550229
550326
  return {
@@ -550233,7 +550330,7 @@ async function call18() {
550233
550330
  }
550234
550331
  const keybindingsPath = getKeybindingsPath();
550235
550332
  let fileExists2 = false;
550236
- await mkdir34(dirname58(keybindingsPath), { recursive: true });
550333
+ await mkdir34(dirname59(keybindingsPath), { recursive: true });
550237
550334
  try {
550238
550335
  await writeFile37(keybindingsPath, generateKeybindingsTemplate(), {
550239
550336
  encoding: "utf-8",
@@ -554307,7 +554404,7 @@ var init_pluginStartupCheck = __esm(() => {
554307
554404
  });
554308
554405
 
554309
554406
  // src/utils/plugins/parseMarketplaceInput.ts
554310
- import { homedir as homedir31 } from "os";
554407
+ import { homedir as homedir32 } from "os";
554311
554408
  import { resolve as resolve47 } from "path";
554312
554409
  async function parseMarketplaceInput(input) {
554313
554410
  const trimmed = input.trim();
@@ -554343,7 +554440,7 @@ async function parseMarketplaceInput(input) {
554343
554440
  const isWindows2 = process.platform === "win32";
554344
554441
  const isWindowsPath = isWindows2 && (trimmed.startsWith(".\\") || trimmed.startsWith("..\\") || /^[a-zA-Z]:[/\\]/.test(trimmed));
554345
554442
  if (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("/") || trimmed.startsWith("~") || isWindowsPath) {
554346
- const resolvedPath = resolve47(trimmed.startsWith("~") ? trimmed.replace(/^~/, homedir31()) : trimmed);
554443
+ const resolvedPath = resolve47(trimmed.startsWith("~") ? trimmed.replace(/^~/, homedir32()) : trimmed);
554347
554444
  let stats2;
554348
554445
  try {
554349
554446
  stats2 = await fs14.stat(resolvedPath);
@@ -557343,7 +557440,7 @@ var init_DiscoverPlugins = __esm(() => {
557343
557440
  });
557344
557441
 
557345
557442
  // src/services/plugins/pluginOperations.ts
557346
- import { dirname as dirname59, join as join132 } from "path";
557443
+ import { dirname as dirname60, join as join132 } from "path";
557347
557444
  function assertInstallableScope(scope) {
557348
557445
  if (!VALID_INSTALLABLE_SCOPES.includes(scope)) {
557349
557446
  throw new Error(`Invalid scope "${scope}". Must be one of: ${VALID_INSTALLABLE_SCOPES.join(", ")}`);
@@ -557820,7 +557917,7 @@ async function performPluginUpdate({
557820
557917
  }
557821
557918
  throw e2;
557822
557919
  }
557823
- const marketplaceDir = marketplaceStats.isDirectory() ? marketplaceInstallLocation : dirname59(marketplaceInstallLocation);
557920
+ const marketplaceDir = marketplaceStats.isDirectory() ? marketplaceInstallLocation : dirname60(marketplaceInstallLocation);
557824
557921
  sourcePath = join132(marketplaceDir, entry.source);
557825
557922
  try {
557826
557923
  await fs14.stat(sourcePath);
@@ -566792,7 +566889,7 @@ var init_server = __esm(() => {
566792
566889
  });
566793
566890
 
566794
566891
  // src/telegram/telegramConfig.ts
566795
- import { existsSync as existsSync23, mkdirSync as mkdirSync11, readFileSync as readFileSync26, writeFileSync as writeFileSync12 } from "fs";
566892
+ import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync26, writeFileSync as writeFileSync13 } from "fs";
566796
566893
  import { join as join136 } from "path";
566797
566894
  function configPath2() {
566798
566895
  return join136(getRayuConfigHomeDir(), "telegram.json");
@@ -566823,8 +566920,8 @@ function readTelegramConfig() {
566823
566920
  function writeTelegramConfig(config5) {
566824
566921
  const dir = getRayuConfigHomeDir();
566825
566922
  if (!existsSync23(dir))
566826
- mkdirSync11(dir, { recursive: true });
566827
- writeFileSync12(configPath2(), JSON.stringify(config5, null, 2), { mode: 384 });
566923
+ mkdirSync12(dir, { recursive: true });
566924
+ writeFileSync13(configPath2(), JSON.stringify(config5, null, 2), { mode: 384 });
566828
566925
  }
566829
566926
  function setPendingToken(token, ttlMs) {
566830
566927
  const next = {
@@ -568621,7 +568718,7 @@ var init_transcriptSearch = __esm(() => {
568621
568718
 
568622
568719
  // src/utils/releaseNotes.ts
568623
568720
  import { mkdir as mkdir35, readFile as readFile46, writeFile as writeFile40 } from "fs/promises";
568624
- import { dirname as dirname61, join as join137 } from "path";
568721
+ import { dirname as dirname62, join as join137 } from "path";
568625
568722
  function getChangelogCachePath() {
568626
568723
  return join137(getRayuConfigHomeDir(), "cache", "changelog.md");
568627
568724
  }
@@ -568632,7 +568729,7 @@ async function migrateChangelogFromConfig() {
568632
568729
  }
568633
568730
  const cachePath = getChangelogCachePath();
568634
568731
  try {
568635
- await mkdir35(dirname61(cachePath), { recursive: true });
568732
+ await mkdir35(dirname62(cachePath), { recursive: true });
568636
568733
  await writeFile40(cachePath, config5.cachedChangelog, {
568637
568734
  encoding: "utf-8",
568638
568735
  flag: "wx"
@@ -568654,7 +568751,7 @@ async function fetchAndStoreChangelog() {
568654
568751
  return;
568655
568752
  }
568656
568753
  const cachePath = getChangelogCachePath();
568657
- await mkdir35(dirname61(cachePath), { recursive: true });
568754
+ await mkdir35(dirname62(cachePath), { recursive: true });
568658
568755
  await writeFile40(cachePath, changelogContent, { encoding: "utf-8" });
568659
568756
  changelogMemoryCache = changelogContent;
568660
568757
  const changelogLastFetched = Date.now();
@@ -568723,7 +568820,7 @@ function getRecentReleaseNotes(currentVersion, previousVersion, changelogContent
568723
568820
  }
568724
568821
  return [];
568725
568822
  }
568726
- async function checkForReleaseNotes(lastSeenVersion, currentVersion = "1.3.434") {
568823
+ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "1.3.436") {
568727
568824
  if (false) {}
568728
568825
  const cachedChangelog = await getStoredChangelog();
568729
568826
  if (lastSeenVersion !== currentVersion || !cachedChangelog) {
@@ -568736,7 +568833,7 @@ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "1.3.434")
568736
568833
  releaseNotes
568737
568834
  };
568738
568835
  }
568739
- function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "1.3.434") {
568836
+ function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "1.3.436") {
568740
568837
  if (false) {}
568741
568838
  const releaseNotes = getRecentReleaseNotes(currentVersion, lastSeenVersion);
568742
568839
  return {
@@ -568864,7 +568961,7 @@ function getRecentActivitySync() {
568864
568961
  return cachedActivity;
568865
568962
  }
568866
568963
  function getLogoDisplayData() {
568867
- const version2 = process.env.DEMO_VERSION ?? "1.3.434";
568964
+ const version2 = process.env.DEMO_VERSION ?? "1.3.436";
568868
568965
  const serverUrl = getDirectConnectServerUrl();
568869
568966
  const displayPath = process.env.DEMO_VERSION ? "/code/claude" : getDisplayPath(getCwd());
568870
568967
  const cwd2 = serverUrl ? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, "")}` : displayPath;
@@ -569338,7 +569435,7 @@ var init_referral = __esm(() => {
569338
569435
  });
569339
569436
 
569340
569437
  // src/components/LogoV2/feedConfigs.tsx
569341
- import { homedir as homedir32 } from "os";
569438
+ import { homedir as homedir33 } from "os";
569342
569439
  function createRecentActivityFeed(activities) {
569343
569440
  const lines2 = activities.map((log3) => {
569344
569441
  const time3 = formatRelativeTimeAgo(log3.modified);
@@ -569394,7 +569491,7 @@ function createProjectOnboardingFeed(steps) {
569394
569491
  text: `${checkmark}${text2}`
569395
569492
  };
569396
569493
  });
569397
- const warningText = getCwd() === homedir32() ? "Note: You have launched Rayu in your home directory. For the best experience, launch it in a project directory instead." : undefined;
569494
+ const warningText = getCwd() === homedir33() ? "Note: You have launched Rayu in your home directory. For the best experience, launch it in a project directory instead." : undefined;
569398
569495
  if (warningText) {
569399
569496
  lines2.push({
569400
569497
  text: warningText
@@ -569418,7 +569515,7 @@ function createGuestPassesFeed() {
569418
569515
  marginY: 1,
569419
569516
  children: /* @__PURE__ */ jsx_dev_runtime231.jsxDEV(ThemedText, {
569420
569517
  color: "claude",
569421
- children: "[] [] []"
569518
+ children: `[${getBrandGlyph()}] [${getBrandGlyph()}] [${getBrandGlyph()}]`
569422
569519
  }, undefined, false, undefined, this)
569423
569520
  }, undefined, false, undefined, this),
569424
569521
  /* @__PURE__ */ jsx_dev_runtime231.jsxDEV(ThemedText, {
@@ -569436,6 +569533,7 @@ var jsx_dev_runtime231;
569436
569533
  var init_feedConfigs = __esm(() => {
569437
569534
  init_figures();
569438
569535
  init_ink2();
569536
+ init_figures2();
569439
569537
  init_referral();
569440
569538
  init_cwd2();
569441
569539
  init_format();
@@ -570110,7 +570208,7 @@ function LogoV2() {
570110
570208
  if ($3[2] === Symbol.for("react.memo_cache_sentinel")) {
570111
570209
  t2 = () => {
570112
570210
  const currentConfig = getGlobalConfig();
570113
- if (currentConfig.lastReleaseNotesSeen === "1.3.434") {
570211
+ if (currentConfig.lastReleaseNotesSeen === "1.3.436") {
570114
570212
  return;
570115
570213
  }
570116
570214
  saveGlobalConfig(_temp327);
@@ -570588,7 +570686,7 @@ function LogoV2() {
570588
570686
  t24 = $3[61];
570589
570687
  }
570590
570688
  const _latestNpm = getCachedLatestNpmVersionSync();
570591
- const _updateFeeds = _latestNpm && gt(_latestNpm, "1.3.434") ? [createUpdateAvailableFeed("1.3.434", _latestNpm)] : [];
570689
+ const _updateFeeds = _latestNpm && gt(_latestNpm, "1.3.436") ? [createUpdateAvailableFeed("1.3.436", _latestNpm)] : [];
570592
570690
  const t25 = layoutMode === "horizontal" && /* @__PURE__ */ jsx_dev_runtime239.jsxDEV(FeedColumn, {
570593
570691
  feeds: showOnboarding ? [createProjectOnboardingFeed(getSteps()), createRecentActivityFeed(activities)] : showGuestPassesUpsell ? [createRecentActivityFeed(activities), createGuestPassesFeed()] : showOverageCreditUpsell ? [createRecentActivityFeed(activities), createOverageCreditFeed()] : [createRecentActivityFeed(activities), ..._updateFeeds, createWhatsNewFeed(changelog)],
570594
570692
  maxWidth: rightWidth
@@ -570788,12 +570886,12 @@ function LogoV2() {
570788
570886
  return t41;
570789
570887
  }
570790
570888
  function _temp327(current) {
570791
- if (current.lastReleaseNotesSeen === "1.3.434") {
570889
+ if (current.lastReleaseNotesSeen === "1.3.436") {
570792
570890
  return current;
570793
570891
  }
570794
570892
  return {
570795
570893
  ...current,
570796
- lastReleaseNotesSeen: "1.3.434"
570894
+ lastReleaseNotesSeen: "1.3.436"
570797
570895
  };
570798
570896
  }
570799
570897
  function _temp241(s_0) {
@@ -584005,7 +584103,7 @@ var init_brand = __esm(() => {
584005
584103
  init_settings2();
584006
584104
  React86 = __toESM(require_react(), 1);
584007
584105
  jsx_dev_runtime272 = __toESM(require_jsx_dev_runtime(), 1);
584008
- GLYPH_OPTIONS = ["◈", "◆", "◇", "★", "✦", "❖", "●", "✻", "*"];
584106
+ GLYPH_OPTIONS = ["◈", "◆", "◇", "★", "✦", "❖", "●"];
584009
584107
  });
584010
584108
 
584011
584109
  // src/commands/brand/index.ts
@@ -595605,7 +595703,7 @@ var init_rewind = __esm(() => {
595605
595703
  });
595606
595704
 
595607
595705
  // src/utils/heapDumpService.ts
595608
- import { createWriteStream as createWriteStream4, writeFileSync as writeFileSync13 } from "fs";
595706
+ import { createWriteStream as createWriteStream4, writeFileSync as writeFileSync14 } from "fs";
595609
595707
  import { readdir as readdir27, readFile as readFile49, writeFile as writeFile42 } from "fs/promises";
595610
595708
  import { join as join141 } from "path";
595611
595709
  import { pipeline as pipeline4 } from "stream/promises";
@@ -595697,7 +595795,7 @@ async function captureMemoryDiagnostics(trigger, dumpNumber = 0) {
595697
595795
  smapsRollup,
595698
595796
  platform: process.platform,
595699
595797
  nodeVersion: process.version,
595700
- ccVersion: "1.3.434"
595798
+ ccVersion: "1.3.436"
595701
595799
  };
595702
595800
  }
595703
595801
  async function performHeapDump(trigger = "manual", dumpNumber = 0) {
@@ -595744,7 +595842,7 @@ async function performHeapDump(trigger = "manual", dumpNumber = 0) {
595744
595842
  }
595745
595843
  async function writeHeapSnapshot(filepath) {
595746
595844
  if (typeof Bun !== "undefined") {
595747
- writeFileSync13(filepath, Bun.generateHeapSnapshot("v8", "arraybuffer"), {
595845
+ writeFileSync14(filepath, Bun.generateHeapSnapshot("v8", "arraybuffer"), {
595748
595846
  mode: 384
595749
595847
  });
595750
595848
  Bun.gc(true);
@@ -596219,7 +596317,7 @@ var init_bridge_kick = __esm(() => {
596219
596317
  var call49 = async () => {
596220
596318
  return {
596221
596319
  type: "text",
596222
- value: "1.3.434"
596320
+ value: "1.3.436"
596223
596321
  };
596224
596322
  }, version2, version_default;
596225
596323
  var init_version = __esm(() => {
@@ -597515,10 +597613,10 @@ var init_contactMe2 = __esm(() => {
597515
597613
  import {
597516
597614
  chmodSync as chmodSync5,
597517
597615
  existsSync as existsSync24,
597518
- mkdirSync as mkdirSync12,
597616
+ mkdirSync as mkdirSync13,
597519
597617
  readFileSync as readFileSync27,
597520
597618
  rmSync as rmSync5,
597521
- writeFileSync as writeFileSync14
597619
+ writeFileSync as writeFileSync15
597522
597620
  } from "fs";
597523
597621
  import { join as join142 } from "path";
597524
597622
  function isUseRayuOAuthEnabled() {
@@ -597546,9 +597644,9 @@ function readRayuSession() {
597546
597644
  function writeRayuSession(store) {
597547
597645
  const dir = getRayuConfigHomeDir();
597548
597646
  if (!existsSync24(dir))
597549
- mkdirSync12(dir, { recursive: true });
597647
+ mkdirSync13(dir, { recursive: true });
597550
597648
  const p = sessionPath();
597551
- writeFileSync14(p, JSON.stringify(store, null, 2), { mode: 384 });
597649
+ writeFileSync15(p, JSON.stringify(store, null, 2), { mode: 384 });
597552
597650
  try {
597553
597651
  chmodSync5(p, 384);
597554
597652
  } catch {}
@@ -597890,7 +597988,7 @@ var init_advisor2 = __esm(() => {
597890
597988
  // src/skills/bundledSkills.ts
597891
597989
  import { constants as fsConstants5 } from "fs";
597892
597990
  import { mkdir as mkdir38, open as open14 } from "fs/promises";
597893
- import { dirname as dirname62, isAbsolute as isAbsolute33, join as join143, normalize as normalize16, sep as pathSep2 } from "path";
597991
+ import { dirname as dirname63, isAbsolute as isAbsolute33, join as join143, normalize as normalize16, sep as pathSep2 } from "path";
597894
597992
  function registerBundledSkill(definition) {
597895
597993
  const { files: files3 } = definition;
597896
597994
  let skillRoot;
@@ -597954,7 +598052,7 @@ async function writeSkillFiles(dir, files3) {
597954
598052
  const byParent = new Map;
597955
598053
  for (const [relPath, content] of Object.entries(files3)) {
597956
598054
  const target = resolveSkillFilePath(dir, relPath);
597957
- const parent2 = dirname62(target);
598055
+ const parent2 = dirname63(target);
597958
598056
  const entry = [target, content];
597959
598057
  const group = byParent.get(parent2);
597960
598058
  if (group)
@@ -598702,10 +598800,10 @@ __export(exports_googleOAuth, {
598702
598800
  import {
598703
598801
  chmodSync as chmodSync6,
598704
598802
  existsSync as existsSync25,
598705
- mkdirSync as mkdirSync13,
598803
+ mkdirSync as mkdirSync14,
598706
598804
  readFileSync as readFileSync28,
598707
598805
  rmSync as rmSync6,
598708
- writeFileSync as writeFileSync15
598806
+ writeFileSync as writeFileSync16
598709
598807
  } from "fs";
598710
598808
  import { createServer as createServer8 } from "http";
598711
598809
  import { join as join146 } from "path";
@@ -598731,9 +598829,9 @@ function readGeminiOAuthStore() {
598731
598829
  function writeGeminiOAuthStore(store) {
598732
598830
  const dir = getRayuConfigHomeDir();
598733
598831
  if (!existsSync25(dir))
598734
- mkdirSync13(dir, { recursive: true });
598832
+ mkdirSync14(dir, { recursive: true });
598735
598833
  const p = tokenPath2();
598736
- writeFileSync15(p, JSON.stringify(store, null, 2), { mode: 384 });
598834
+ writeFileSync16(p, JSON.stringify(store, null, 2), { mode: 384 });
598737
598835
  try {
598738
598836
  chmodSync6(p, 384);
598739
598837
  } catch {}
@@ -605995,7 +606093,7 @@ function generateHtmlReport(data, insights) {
605995
606093
  </html>`;
605996
606094
  }
605997
606095
  function buildExportData(data, insights, facets, remoteStats) {
605998
- const version3 = typeof MACRO !== "undefined" ? "1.3.434" : "unknown";
606096
+ const version3 = typeof MACRO !== "undefined" ? "1.3.436" : "unknown";
605999
606097
  const remote_hosts_collected = remoteStats?.hosts.filter((h3) => h3.sessionCount > 0).map((h3) => h3.name);
606000
606098
  const facets_summary = {
606001
606099
  total: facets.size,
@@ -607080,7 +607178,7 @@ import {
607080
607178
  unlink as unlink23,
607081
607179
  writeFile as writeFile45
607082
607180
  } from "fs/promises";
607083
- import { basename as basename46, dirname as dirname64, join as join151 } from "path";
607181
+ import { basename as basename46, dirname as dirname65, join as join151 } from "path";
607084
607182
  function isTranscriptMessage(entry) {
607085
607183
  return entry.type === "user" || entry.type === "assistant" || entry.type === "attachment" || entry.type === "system";
607086
607184
  }
@@ -607125,7 +607223,7 @@ function getAgentMetadataPath(agentId) {
607125
607223
  }
607126
607224
  async function writeAgentMetadata(agentId, metadata) {
607127
607225
  const path28 = getAgentMetadataPath(agentId);
607128
- await mkdir41(dirname64(path28), { recursive: true });
607226
+ await mkdir41(dirname65(path28), { recursive: true });
607129
607227
  await writeFile45(path28, JSON.stringify(metadata));
607130
607228
  }
607131
607229
  async function readAgentMetadata(agentId) {
@@ -607148,7 +607246,7 @@ function getRemoteAgentMetadataPath(taskId) {
607148
607246
  }
607149
607247
  async function writeRemoteAgentMetadata(taskId, metadata) {
607150
607248
  const path28 = getRemoteAgentMetadataPath(taskId);
607151
- await mkdir41(dirname64(path28), { recursive: true });
607249
+ await mkdir41(dirname65(path28), { recursive: true });
607152
607250
  await writeFile45(path28, JSON.stringify(metadata));
607153
607251
  }
607154
607252
  async function readRemoteAgentMetadata(taskId) {
@@ -607337,7 +607435,7 @@ class Project {
607337
607435
  try {
607338
607436
  await fsAppendFile(filePath, data, { mode: 384 });
607339
607437
  } catch {
607340
- await mkdir41(dirname64(filePath), { recursive: true, mode: 448 });
607438
+ await mkdir41(dirname65(filePath), { recursive: true, mode: 448 });
607341
607439
  await fsAppendFile(filePath, data, { mode: 384 });
607342
607440
  }
607343
607441
  }
@@ -607936,7 +608034,7 @@ async function hydrateFromCCRv2InternalEvents(sessionId) {
607936
608034
  }
607937
608035
  for (const [agentId, entries] of byAgent) {
607938
608036
  const agentFile = getAgentTranscriptPath(asAgentId(agentId));
607939
- await mkdir41(dirname64(agentFile), { recursive: true, mode: 448 });
608037
+ await mkdir41(dirname65(agentFile), { recursive: true, mode: 448 });
607940
608038
  const agentContent = entries.map((p) => jsonStringify(p) + `
607941
608039
  `).join("");
607942
608040
  await writeFile45(agentFile, agentContent, {
@@ -608473,7 +608571,7 @@ function appendEntryToFile(fullPath, entry) {
608473
608571
  try {
608474
608572
  fs15.appendFileSync(fullPath, line, { mode: 384 });
608475
608573
  } catch {
608476
- fs15.mkdirSync(dirname64(fullPath), { mode: 448 });
608574
+ fs15.mkdirSync(dirname65(fullPath), { mode: 448 });
608477
608575
  fs15.appendFileSync(fullPath, line, { mode: 384 });
608478
608576
  }
608479
608577
  }
@@ -609903,7 +610001,7 @@ var init_sessionStorage = __esm(() => {
609903
610001
  init_settings2();
609904
610002
  init_slowOperations();
609905
610003
  init_uuid();
609906
- VERSION6 = typeof MACRO !== "undefined" ? "1.3.434" : "unknown";
610004
+ VERSION6 = typeof MACRO !== "undefined" ? "1.3.436" : "unknown";
609907
610005
  MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
609908
610006
  SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
609909
610007
  EPHEMERAL_PROGRESS_TYPES = new Set([
@@ -610220,7 +610318,6 @@ function loadAgentMemoryPrompt(agentType, scope) {
610220
610318
  break;
610221
610319
  }
610222
610320
  const memoryDir = getAgentMemoryDir(agentType, scope);
610223
- ensureMemoryDirExists(memoryDir);
610224
610321
  const coworkExtraGuidelines = process.env.CLAUDE_COWORK_MEMORY_EXTRA_GUIDELINES;
610225
610322
  return buildMemoryPrompt({
610226
610323
  displayName: "Persistent Agent Memory",
@@ -610239,7 +610336,7 @@ var init_agentMemory = __esm(() => {
610239
610336
 
610240
610337
  // src/utils/permissions/filesystem.ts
610241
610338
  import { randomBytes as randomBytes19 } from "crypto";
610242
- import { homedir as homedir33, tmpdir as tmpdir15 } from "os";
610339
+ import { homedir as homedir34, tmpdir as tmpdir15 } from "os";
610243
610340
  import { join as join153, normalize as normalize18, posix as posix7, sep as sep39 } from "path";
610244
610341
  function normalizeCaseForComparison2(path28) {
610245
610342
  return path28.toLowerCase();
@@ -610257,11 +610354,11 @@ function getRayuSkillScope(filePath) {
610257
610354
  prefix: "/.agents/skills/"
610258
610355
  },
610259
610356
  {
610260
- dir: expandPath(join153(homedir33(), ".rayu", "skills")),
610357
+ dir: expandPath(join153(homedir34(), ".rayu", "skills")),
610261
610358
  prefix: "~/.rayu/skills/"
610262
610359
  },
610263
610360
  {
610264
- dir: expandPath(join153(homedir33(), ".agents", "skills")),
610361
+ dir: expandPath(join153(homedir34(), ".agents", "skills")),
610265
610362
  prefix: "~/.agents/skills/"
610266
610363
  }
610267
610364
  ];
@@ -610581,7 +610678,7 @@ function patternWithRoot(pattern, source) {
610581
610678
  } else if (pattern.startsWith(`~${DIR_SEP}`)) {
610582
610679
  return {
610583
610680
  relativePattern: pattern.slice(1),
610584
- root: homedir33().normalize("NFC")
610681
+ root: homedir34().normalize("NFC")
610585
610682
  };
610586
610683
  } else if (pattern.startsWith(DIR_SEP)) {
610587
610684
  return {
@@ -611124,7 +611221,7 @@ var init_filesystem = __esm(() => {
611124
611221
  });
611125
611222
  getBundledSkillsRoot = memoize_default(function getBundledSkillsRoot2() {
611126
611223
  const nonce = randomBytes19(16).toString("hex");
611127
- return join153(getClaudeTempDir(), "bundled-skills", "1.3.434", nonce);
611224
+ return join153(getClaudeTempDir(), "bundled-skills", "1.3.436", nonce);
611128
611225
  });
611129
611226
  getResolvedWorkingDirPaths = memoize_default(getPathsForPermissionCheck);
611130
611227
  });
@@ -615417,7 +615514,7 @@ import {
615417
615514
  symlink as symlink5,
615418
615515
  utimes as utimes2
615419
615516
  } from "fs/promises";
615420
- import { basename as basename48, dirname as dirname65, join as join155 } from "path";
615517
+ import { basename as basename48, dirname as dirname66, join as join155 } from "path";
615421
615518
  function validateWorktreeSlug(slug) {
615422
615519
  if (slug.length > MAX_WORKTREE_SLUG_LENGTH) {
615423
615520
  throw new Error(`Invalid worktree name: must be ${MAX_WORKTREE_SLUG_LENGTH} characters or fewer (got ${slug.length})`);
@@ -615613,7 +615710,7 @@ async function copyWorktreeIncludeFiles(repoRoot, worktreePath) {
615613
615710
  const srcPath = join155(repoRoot, relativePath2);
615614
615711
  const destPath = join155(worktreePath, relativePath2);
615615
615712
  try {
615616
- await mkdir43(dirname65(destPath), { recursive: true });
615713
+ await mkdir43(dirname66(destPath), { recursive: true });
615617
615714
  await copyFile11(srcPath, destPath);
615618
615715
  copied.push(relativePath2);
615619
615716
  } catch (e2) {
@@ -615630,7 +615727,7 @@ async function performPostCreationSetup(repoRoot, worktreePath) {
615630
615727
  const sourceSettingsLocal = join155(repoRoot, localSettingsRelativePath);
615631
615728
  try {
615632
615729
  const destSettingsLocal = join155(worktreePath, localSettingsRelativePath);
615633
- await mkdirRecursive(dirname65(destSettingsLocal));
615730
+ await mkdirRecursive(dirname66(destSettingsLocal));
615634
615731
  await copyFile11(sourceSettingsLocal, destSettingsLocal);
615635
615732
  logForDebugging(`Copied settings.local.json to worktree: ${destSettingsLocal}`);
615636
615733
  } catch (e2) {
@@ -616237,9 +616334,9 @@ __export(exports_update, {
616237
616334
  update: () => update
616238
616335
  });
616239
616336
  import { execFileSync as execFileSync3 } from "node:child_process";
616240
- import { homedir as homedir34 } from "os";
616337
+ import { homedir as homedir35 } from "os";
616241
616338
  async function update() {
616242
- writeToStdout(`Current version: ${"1.3.434"}
616339
+ writeToStdout(`Current version: ${"1.3.436"}
616243
616340
  `);
616244
616341
  const isBundled = isInBundledMode();
616245
616342
  if (isBundled) {
@@ -616253,7 +616350,7 @@ async function updateNpmPackage() {
616253
616350
  `);
616254
616351
  let latestVersion;
616255
616352
  try {
616256
- latestVersion = execFileSync3("npm", ["view", `${"@rayu-dev/rayu-cli"}@latest`, "version", "--prefer-online"], { encoding: "utf8", timeout: 15000, cwd: homedir34(), stdio: ["pipe", "pipe", "pipe"] }).trim();
616353
+ latestVersion = execFileSync3("npm", ["view", `${"@rayu-dev/rayu-cli"}@latest`, "version", "--prefer-online"], { encoding: "utf8", timeout: 15000, cwd: homedir35(), stdio: ["pipe", "pipe", "pipe"] }).trim();
616257
616354
  } catch {
616258
616355
  process.stderr.write(source_default.red(`Failed to check for updates
616259
616356
  `));
@@ -616265,19 +616362,19 @@ Manual check: npm view ${"@rayu-dev/rayu-cli"} version
616265
616362
  process.exit(1);
616266
616363
  return;
616267
616364
  }
616268
- if (latestVersion === "1.3.434") {
616365
+ if (latestVersion === "1.3.436") {
616269
616366
  writeToStdout(source_default.green(`
616270
- Rayu CLI is up to date (${"1.3.434"})
616367
+ Rayu CLI is up to date (${"1.3.436"})
616271
616368
  `));
616272
616369
  process.exit(0);
616273
616370
  }
616274
- writeToStdout(`New version available: ${latestVersion} (current: ${"1.3.434"})
616371
+ writeToStdout(`New version available: ${latestVersion} (current: ${"1.3.436"})
616275
616372
  `);
616276
616373
  writeToStdout(`Installing update...
616277
616374
 
616278
616375
  `);
616279
616376
  try {
616280
- execFileSync3("npm", ["install", "-g", `${"@rayu-dev/rayu-cli"}@latest`], { encoding: "utf8", cwd: homedir34(), stdio: "inherit" });
616377
+ execFileSync3("npm", ["install", "-g", `${"@rayu-dev/rayu-cli"}@latest`], { encoding: "utf8", cwd: homedir35(), stdio: "inherit" });
616281
616378
  } catch {
616282
616379
  process.stderr.write(source_default.red(`
616283
616380
  Failed to install update
@@ -616295,7 +616392,7 @@ Try manually:
616295
616392
  return;
616296
616393
  }
616297
616394
  writeToStdout(source_default.green(`
616298
- Successfully updated from ${"1.3.434"} to ${latestVersion}
616395
+ Successfully updated from ${"1.3.436"} to ${latestVersion}
616299
616396
  `));
616300
616397
  process.exit(0);
616301
616398
  }
@@ -616305,18 +616402,18 @@ async function updateNativeBinary() {
616305
616402
  const { installLatest: installLatest2 } = await Promise.resolve().then(() => (init_nativeInstaller(), exports_nativeInstaller));
616306
616403
  let latestVersion;
616307
616404
  try {
616308
- latestVersion = execFileSync3("npm", ["view", "@rayu-dev/rayu-cli@latest", "version", "--prefer-online"], { encoding: "utf8", timeout: 15000, cwd: homedir34(), stdio: ["pipe", "pipe", "pipe"] }).trim();
616405
+ latestVersion = execFileSync3("npm", ["view", "@rayu-dev/rayu-cli@latest", "version", "--prefer-online"], { encoding: "utf8", timeout: 15000, cwd: homedir35(), stdio: ["pipe", "pipe", "pipe"] }).trim();
616309
616406
  } catch {
616310
616407
  latestVersion = "";
616311
616408
  }
616312
- if (latestVersion && latestVersion === "1.3.434") {
616409
+ if (latestVersion && latestVersion === "1.3.436") {
616313
616410
  writeToStdout(source_default.green(`
616314
- Rayu CLI is up to date (1.3.434)
616411
+ Rayu CLI is up to date (1.3.436)
616315
616412
  `));
616316
616413
  process.exit(0);
616317
616414
  }
616318
616415
  if (latestVersion) {
616319
- writeToStdout(`New version available: ${latestVersion} (current: 1.3.434)
616416
+ writeToStdout(`New version available: ${latestVersion} (current: 1.3.436)
616320
616417
  `);
616321
616418
  }
616322
616419
  writeToStdout(`Downloading and installing update...
@@ -616331,13 +616428,13 @@ Rayu CLI is up to date (1.3.434)
616331
616428
  return;
616332
616429
  }
616333
616430
  writeToStdout(source_default.green(`
616334
- Rayu CLI is up to date (1.3.434)
616431
+ Rayu CLI is up to date (1.3.436)
616335
616432
  `));
616336
616433
  process.exit(0);
616337
616434
  }
616338
616435
  const updatedTo = result.latestVersion ?? latestVersion ?? "latest";
616339
616436
  writeToStdout(source_default.green(`
616340
- Successfully updated from 1.3.434 to ${updatedTo}
616437
+ Successfully updated from 1.3.436 to ${updatedTo}
616341
616438
  `));
616342
616439
  writeToStdout(`Restart your terminal to use the new version.
616343
616440
  `);
@@ -616366,15 +616463,15 @@ __export(exports_uninstall, {
616366
616463
  uninstall: () => uninstall
616367
616464
  });
616368
616465
  import { execFileSync as execFileSync4 } from "node:child_process";
616369
- import { homedir as homedir35 } from "os";
616466
+ import { homedir as homedir36 } from "os";
616370
616467
  async function uninstall() {
616371
- writeToStdout(`Uninstalling Rayu CLI (${"1.3.434"})...
616468
+ writeToStdout(`Uninstalling Rayu CLI (${"1.3.436"})...
616372
616469
  `);
616373
616470
  writeToStdout(`Running: npm uninstall -g ${"@rayu-dev/rayu-cli"}
616374
616471
 
616375
616472
  `);
616376
616473
  try {
616377
- execFileSync4("npm", ["uninstall", "-g", "@rayu-dev/rayu-cli"], { encoding: "utf8", cwd: homedir35(), stdio: "inherit" });
616474
+ execFileSync4("npm", ["uninstall", "-g", "@rayu-dev/rayu-cli"], { encoding: "utf8", cwd: homedir36(), stdio: "inherit" });
616378
616475
  } catch {
616379
616476
  process.stderr.write(source_default.red(`
616380
616477
  Failed to uninstall ${"@rayu-dev/rayu-cli"}
@@ -616391,7 +616488,7 @@ Try running manually:
616391
616488
  process.exit(1);
616392
616489
  }
616393
616490
  writeToStdout(source_default.green(`
616394
- Successfully uninstalled ${"@rayu-dev/rayu-cli"} ${"1.3.434"}
616491
+ Successfully uninstalled ${"@rayu-dev/rayu-cli"} ${"1.3.436"}
616395
616492
  `));
616396
616493
  writeToStdout(`Thanks for using Rayu CLI!
616397
616494
  `);
@@ -616406,7 +616503,7 @@ var exports_firstRun = {};
616406
616503
  __export(exports_firstRun, {
616407
616504
  showFirstRunWelcome: () => showFirstRunWelcome
616408
616505
  });
616409
- import { existsSync as existsSync26, mkdirSync as mkdirSync14, writeFileSync as writeFileSync16 } from "node:fs";
616506
+ import { existsSync as existsSync26, mkdirSync as mkdirSync15, writeFileSync as writeFileSync17 } from "node:fs";
616410
616507
  import { join as join156 } from "node:path";
616411
616508
  function markerPath() {
616412
616509
  return join156(getRayuConfigHomeDir(), ".installed");
@@ -616442,8 +616539,8 @@ function showFirstRunWelcome() {
616442
616539
  `) + `
616443
616540
  `);
616444
616541
  try {
616445
- mkdirSync14(getRayuConfigHomeDir(), { recursive: true });
616446
- writeFileSync16(markerPath(), "1.3.434", "utf8");
616542
+ mkdirSync15(getRayuConfigHomeDir(), { recursive: true });
616543
+ writeFileSync17(markerPath(), "1.3.436", "utf8");
616447
616544
  } catch {}
616448
616545
  }
616449
616546
  var init_firstRun = __esm(() => {
@@ -619859,7 +619956,7 @@ __export(exports_upstreamproxy, {
619859
619956
  SESSION_TOKEN_PATH: () => SESSION_TOKEN_PATH
619860
619957
  });
619861
619958
  import { mkdir as mkdir44, readFile as readFile53, unlink as unlink26, writeFile as writeFile46 } from "fs/promises";
619862
- import { homedir as homedir36 } from "os";
619959
+ import { homedir as homedir37 } from "os";
619863
619960
  import { join as join157 } from "path";
619864
619961
  async function initUpstreamProxy(opts) {
619865
619962
  if (!isEnvTruthy(process.env.CLAUDE_CODE_REMOTE)) {
@@ -619881,7 +619978,7 @@ async function initUpstreamProxy(opts) {
619881
619978
  }
619882
619979
  setNonDumpable();
619883
619980
  const baseUrl = opts?.ccrBaseUrl ?? process.env.ANTHROPIC_BASE_URL ?? "https://api.anthropic.com";
619884
- const caBundlePath = opts?.caBundlePath ?? join157(homedir36(), ".ccr", "ca-bundle.crt");
619981
+ const caBundlePath = opts?.caBundlePath ?? join157(homedir37(), ".ccr", "ca-bundle.crt");
619885
619982
  const caOk = await downloadCaBundle(baseUrl, opts?.systemCaPath ?? SYSTEM_CA_BUNDLE, caBundlePath);
619886
619983
  if (!caOk)
619887
619984
  return state;
@@ -628286,7 +628383,7 @@ async function initializeBetaTracing(resource) {
628286
628383
  });
628287
628384
  import_api_logs.logs.setGlobalLoggerProvider(loggerProvider);
628288
628385
  setLoggerProvider(loggerProvider);
628289
- const eventLogger = import_api_logs.logs.getLogger("com.anthropic.claude_code.events", "1.3.434");
628386
+ const eventLogger = import_api_logs.logs.getLogger("com.anthropic.claude_code.events", "1.3.436");
628290
628387
  setEventLogger(eventLogger);
628291
628388
  process.on("beforeExit", async () => {
628292
628389
  await loggerProvider?.forceFlush();
@@ -628326,7 +628423,7 @@ async function initializeTelemetry() {
628326
628423
  const platform4 = getPlatform();
628327
628424
  const baseAttributes = {
628328
628425
  [import_semantic_conventions2.ATTR_SERVICE_NAME]: "claude-code",
628329
- [import_semantic_conventions2.ATTR_SERVICE_VERSION]: "1.3.434"
628426
+ [import_semantic_conventions2.ATTR_SERVICE_VERSION]: "1.3.436"
628330
628427
  };
628331
628428
  if (platform4 === "wsl") {
628332
628429
  const wslVersion = getWslVersion();
@@ -628371,7 +628468,7 @@ async function initializeTelemetry() {
628371
628468
  } catch {}
628372
628469
  };
628373
628470
  registerCleanup(shutdownTelemetry2);
628374
- return meterProvider2.getMeter("com.anthropic.claude_code", "1.3.434");
628471
+ return meterProvider2.getMeter("com.anthropic.claude_code", "1.3.436");
628375
628472
  }
628376
628473
  const meterProvider = new import_sdk_metrics2.MeterProvider({
628377
628474
  resource,
@@ -628391,7 +628488,7 @@ async function initializeTelemetry() {
628391
628488
  });
628392
628489
  import_api_logs.logs.setGlobalLoggerProvider(loggerProvider);
628393
628490
  setLoggerProvider(loggerProvider);
628394
- const eventLogger = import_api_logs.logs.getLogger("com.anthropic.claude_code.events", "1.3.434");
628491
+ const eventLogger = import_api_logs.logs.getLogger("com.anthropic.claude_code.events", "1.3.436");
628395
628492
  setEventLogger(eventLogger);
628396
628493
  logForDebugging("[3P telemetry] Event logger set successfully");
628397
628494
  process.on("beforeExit", async () => {
@@ -628453,7 +628550,7 @@ Current timeout: ${timeoutMs}ms
628453
628550
  }
628454
628551
  };
628455
628552
  registerCleanup(shutdownTelemetry);
628456
- return meterProvider.getMeter("com.anthropic.claude_code", "1.3.434");
628553
+ return meterProvider.getMeter("com.anthropic.claude_code", "1.3.436");
628457
628554
  }
628458
628555
  async function flushTelemetry() {
628459
628556
  const meterProvider = getMeterProvider();
@@ -629966,7 +630063,7 @@ function buildSystemInitMessage(inputs) {
629966
630063
  slash_commands: inputs.commands.filter((c4) => c4.userInvocable !== false).map((c4) => c4.name),
629967
630064
  apiKeySource: getAnthropicApiKeyWithSource().source,
629968
630065
  betas: getSdkBetas(),
629969
- claude_code_version: "1.3.434",
630066
+ claude_code_version: "1.3.436",
629970
630067
  output_style: outputStyle2,
629971
630068
  agents: inputs.agents.map((agent) => agent.agentType),
629972
630069
  skills: inputs.skills.filter((s2) => s2.userInvocable !== false).map((skill) => skill.name),
@@ -630769,7 +630866,7 @@ var EDIT_INTERVAL_MS = 1100, PLACEHOLDER = "\uD83D\uDCAC …";
630769
630866
 
630770
630867
  // src/telegram/telegramBridge.ts
630771
630868
  import { hostname as hostname3 } from "os";
630772
- import { closeSync as closeSync5, existsSync as existsSync27, openSync as openSync6, readFileSync as readFileSync29, unlinkSync as unlinkSync4, writeFileSync as writeFileSync17, writeSync as writeSync3 } from "fs";
630869
+ import { closeSync as closeSync5, existsSync as existsSync27, openSync as openSync6, readFileSync as readFileSync29, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18, writeSync as writeSync3 } from "fs";
630773
630870
  import { join as join158 } from "path";
630774
630871
  function linkedChatId() {
630775
630872
  return readTelegramConfig().linkedChatId;
@@ -631034,7 +631131,7 @@ function acquireBridgeLock() {
631034
631131
  return false;
631035
631132
  }
631036
631133
  }
631037
- writeFileSync17(path28, content, { mode: 384 });
631134
+ writeFileSync18(path28, content, { mode: 384 });
631038
631135
  } catch {}
631039
631136
  return true;
631040
631137
  }
@@ -631046,7 +631143,7 @@ function updateHeartbeat() {
631046
631143
  const raw = readFileSync29(path28, "utf8").trim();
631047
631144
  const pid = parseInt(raw.split(":")[0] ?? "", 10);
631048
631145
  if (pid === process.pid) {
631049
- writeFileSync17(path28, buildLockContent(), { mode: 384 });
631146
+ writeFileSync18(path28, buildLockContent(), { mode: 384 });
631050
631147
  }
631051
631148
  } catch {}
631052
631149
  }
@@ -637166,7 +637263,7 @@ function useDiffInIDE({
637166
637263
  const isUnmounted = import_react199.useRef(false);
637167
637264
  const [hasError, setHasError] = import_react199.useState(false);
637168
637265
  const sha = import_react199.useMemo(() => randomUUID39().slice(0, 6), []);
637169
- const tabName = import_react199.useMemo(() => `◈ [RAYU] ${basename50(filePath)} (${sha}) ⧉`, [filePath, sha]);
637266
+ const tabName = import_react199.useMemo(() => `${getBrandGlyph()} [RAYU] ${basename50(filePath)} (${sha}) ⧉`, [filePath, sha]);
637170
637267
  const shouldShowDiffInIDE = hasAccessToIDEExtensionDiffFeature(toolUseContext.options.mcpClients) && getGlobalConfig().diffTool === "auto" && !filePath.endsWith(".ipynb");
637171
637268
  const ideName = getConnectedIdeName(toolUseContext.options.mcpClients) ?? "IDE";
637172
637269
  async function showDiff() {
@@ -637333,6 +637430,7 @@ function isSaveMessage(data) {
637333
637430
  }
637334
637431
  var import_react199;
637335
637432
  var init_useDiffInIDE = __esm(() => {
637433
+ init_figures2();
637336
637434
  init_analytics();
637337
637435
  init_fileRead();
637338
637436
  init_path();
@@ -637565,7 +637663,7 @@ var init_ShowInIDEPrompt = __esm(() => {
637565
637663
  });
637566
637664
 
637567
637665
  // src/components/permissions/FilePermissionDialog/permissionOptions.tsx
637568
- import { homedir as homedir37 } from "os";
637666
+ import { homedir as homedir38 } from "os";
637569
637667
  import { basename as basename52, join as join159, sep as sep40 } from "path";
637570
637668
  function isInRayuFolder(filePath) {
637571
637669
  const absolutePath = expandPath(filePath);
@@ -637576,7 +637674,7 @@ function isInRayuFolder(filePath) {
637576
637674
  }
637577
637675
  function isInGlobalRayuFolder(filePath) {
637578
637676
  const absolutePath = expandPath(filePath);
637579
- const globalRayuFolderPath = join159(homedir37(), ".rayu");
637677
+ const globalRayuFolderPath = join159(homedir38(), ".rayu");
637580
637678
  const normalizedAbsolutePath = normalizeCaseForComparison2(absolutePath);
637581
637679
  const normalizedGlobalRayuFolderPath = normalizeCaseForComparison2(globalRayuFolderPath);
637582
637680
  return normalizedAbsolutePath.startsWith(normalizedGlobalRayuFolderPath + sep40.toLowerCase()) || normalizedAbsolutePath.startsWith(normalizedGlobalRayuFolderPath + "/");
@@ -646175,7 +646273,7 @@ var init_useVoiceEnabled = __esm(() => {
646175
646273
  function getSemverPart(version3) {
646176
646274
  return `${import_semver12.major(version3, { loose: true })}.${import_semver12.minor(version3, { loose: true })}.${import_semver12.patch(version3, { loose: true })}`;
646177
646275
  }
646178
- function useUpdateNotification(updatedVersion, initialVersion = "1.3.434") {
646276
+ function useUpdateNotification(updatedVersion, initialVersion = "1.3.436") {
646179
646277
  const [lastNotifiedSemver, setLastNotifiedSemver] = import_react217.useState(() => getSemverPart(initialVersion));
646180
646278
  if (!updatedVersion) {
646181
646279
  return null;
@@ -646215,7 +646313,7 @@ function AutoUpdater({
646215
646313
  return;
646216
646314
  }
646217
646315
  if (false) {}
646218
- const currentVersion = "1.3.434";
646316
+ const currentVersion = "1.3.436";
646219
646317
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
646220
646318
  let latestVersion = await getLatestVersion(channel);
646221
646319
  const isDisabled = isAutoUpdaterDisabled();
@@ -646428,12 +646526,12 @@ function NativeAutoUpdater({
646428
646526
  logEvent("tengu_native_auto_updater_start", {});
646429
646527
  try {
646430
646528
  const maxVersion = await getMaxVersion();
646431
- if (maxVersion && gt("1.3.434", maxVersion)) {
646529
+ if (maxVersion && gt("1.3.436", maxVersion)) {
646432
646530
  const msg = await getMaxVersionMessage();
646433
646531
  setMaxVersionIssue(msg ?? "affects your version");
646434
646532
  }
646435
646533
  const result = await installLatest(channel);
646436
- const currentVersion = "1.3.434";
646534
+ const currentVersion = "1.3.436";
646437
646535
  const latencyMs = Date.now() - startTime;
646438
646536
  if (result.lockFailed) {
646439
646537
  logEvent("tengu_native_auto_updater_lock_contention", {
@@ -646570,17 +646668,17 @@ function PackageManagerAutoUpdater(t0) {
646570
646668
  const maxVersion = await getMaxVersion();
646571
646669
  if (maxVersion && latest && gt(latest, maxVersion)) {
646572
646670
  logForDebugging(`PackageManagerAutoUpdater: maxVersion ${maxVersion} is set, capping update from ${latest} to ${maxVersion}`);
646573
- if (gte("1.3.434", maxVersion)) {
646574
- logForDebugging(`PackageManagerAutoUpdater: current version ${"1.3.434"} is already at or above maxVersion ${maxVersion}, skipping update`);
646671
+ if (gte("1.3.436", maxVersion)) {
646672
+ logForDebugging(`PackageManagerAutoUpdater: current version ${"1.3.436"} is already at or above maxVersion ${maxVersion}, skipping update`);
646575
646673
  setUpdateAvailable(false);
646576
646674
  return;
646577
646675
  }
646578
646676
  latest = maxVersion;
646579
646677
  }
646580
- const hasUpdate = latest && !gte("1.3.434", latest) && !shouldSkipVersion(latest);
646678
+ const hasUpdate = latest && !gte("1.3.436", latest) && !shouldSkipVersion(latest);
646581
646679
  setUpdateAvailable(!!hasUpdate);
646582
646680
  if (hasUpdate) {
646583
- logForDebugging(`PackageManagerAutoUpdater: Update available ${"1.3.434"} -> ${latest}`);
646681
+ logForDebugging(`PackageManagerAutoUpdater: Update available ${"1.3.436"} -> ${latest}`);
646584
646682
  }
646585
646683
  };
646586
646684
  $3[0] = t1;
@@ -646614,7 +646712,7 @@ function PackageManagerAutoUpdater(t0) {
646614
646712
  wrap: "truncate",
646615
646713
  children: [
646616
646714
  "currentVersion: ",
646617
- "1.3.434"
646715
+ "1.3.436"
646618
646716
  ]
646619
646717
  }, undefined, true, undefined, this);
646620
646718
  $3[3] = verbose;
@@ -654779,7 +654877,7 @@ function buildStatusLineCommandInput(permissionMode, exceeds200kTokens, settings
654779
654877
  project_dir: getOriginalCwd(),
654780
654878
  added_dirs: addedDirs
654781
654879
  },
654782
- version: "1.3.434",
654880
+ version: "1.3.436",
654783
654881
  output_style: {
654784
654882
  name: outputStyleName
654785
654883
  },
@@ -664537,7 +664635,7 @@ __export(exports_asciicast, {
664537
664635
  _resetRecordingStateForTesting: () => _resetRecordingStateForTesting
664538
664636
  });
664539
664637
  import { appendFile as appendFile6, rename as rename13 } from "fs/promises";
664540
- import { basename as basename61, dirname as dirname66, join as join162 } from "path";
664638
+ import { basename as basename61, dirname as dirname67, join as join162 } from "path";
664541
664639
  function getRecordFilePath() {
664542
664640
  if (recordingState.filePath !== null) {
664543
664641
  return recordingState.filePath;
@@ -664619,7 +664717,7 @@ function installAsciicastRecorder() {
664619
664717
  }
664620
664718
  });
664621
664719
  try {
664622
- getFsImplementation().mkdirSync(dirname66(filePath));
664720
+ getFsImplementation().mkdirSync(dirname67(filePath));
664623
664721
  } catch {}
664624
664722
  getFsImplementation().appendFileSync(filePath, header + `
664625
664723
  `, { mode: 384 });
@@ -664688,7 +664786,7 @@ var init_asciicast = __esm(() => {
664688
664786
  });
664689
664787
 
664690
664788
  // src/utils/sessionRestore.ts
664691
- import { dirname as dirname67 } from "path";
664789
+ import { dirname as dirname68 } from "path";
664692
664790
  function extractTodosFromTranscript(messages) {
664693
664791
  for (let i4 = messages.length - 1;i4 >= 0; i4--) {
664694
664792
  const msg = messages[i4];
@@ -664813,7 +664911,7 @@ async function processResumedConversation(result, opts, context2) {
664813
664911
  if (!opts.forkSession) {
664814
664912
  const sid = opts.sessionIdOverride ?? result.sessionId;
664815
664913
  if (sid) {
664816
- switchSession(asSessionId(sid), opts.transcriptPath ? dirname67(opts.transcriptPath) : null);
664914
+ switchSession(asSessionId(sid), opts.transcriptPath ? dirname68(opts.transcriptPath) : null);
664817
664915
  await renameRecordingForSession();
664818
664916
  await resetSessionFilePointer();
664819
664917
  restoreCostStateForSession(sid);
@@ -666183,7 +666281,7 @@ async function submitTranscriptShare(messages, trigger, appearanceId) {
666183
666281
  } catch {}
666184
666282
  const data = {
666185
666283
  trigger,
666186
- version: "1.3.434",
666284
+ version: "1.3.436",
666187
666285
  platform: process.platform,
666188
666286
  transcript,
666189
666287
  subagentTranscripts: Object.keys(subagentTranscripts).length > 0 ? subagentTranscripts : undefined,
@@ -673661,7 +673759,7 @@ var exports_REPL = {};
673661
673759
  __export(exports_REPL, {
673662
673760
  REPL: () => REPL
673663
673761
  });
673664
- import { dirname as dirname68, join as join166 } from "path";
673762
+ import { dirname as dirname69, join as join166 } from "path";
673665
673763
  import { tmpdir as tmpdir16 } from "os";
673666
673764
  import { writeFile as writeFile47 } from "fs/promises";
673667
673765
  import { randomUUID as randomUUID52 } from "crypto";
@@ -674600,7 +674698,7 @@ function REPL({
674600
674698
  const targetSessionCosts = getStoredSessionCosts(sessionId);
674601
674699
  saveCurrentSessionCosts();
674602
674700
  resetCostState();
674603
- switchSession(asSessionId(sessionId), log3.fullPath ? dirname68(log3.fullPath) : null);
674701
+ switchSession(asSessionId(sessionId), log3.fullPath ? dirname69(log3.fullPath) : null);
674604
674702
  const {
674605
674703
  renameRecordingForSession: renameRecordingForSession2
674606
674704
  } = await Promise.resolve().then(() => (init_asciicast(), exports_asciicast));
@@ -677038,7 +677136,7 @@ Note: ctrl + z now suspends RAYU, ctrl + _ undoes input.
677038
677136
  var import_compiler_runtime341, React152, import_react309, jsx_dev_runtime451, useFrustrationDetection = () => ({
677039
677137
  state: "closed",
677040
677138
  handleTranscriptSelect: () => {}
677041
- }), useAntOrgWarningNotification = () => {}, getCoordinatorUserContext = () => ({}), proactiveModule5 = null, PROACTIVE_NO_OP_SUBSCRIBE = (_cb) => () => {}, PROACTIVE_FALSE = () => false, SUGGEST_BG_PR_NOOP = (_p, _n) => false, EMPTY_MCP_CLIENTS2, HISTORY_STUB, RECENT_SCROLL_REPIN_WINDOW_MS = 3000, TITLE_ANIMATION_FRAMES, TITLE_STATIC_PREFIX = "✳", TITLE_ANIMATION_INTERVAL_MS = 960;
677139
+ }), useAntOrgWarningNotification = () => {}, getCoordinatorUserContext = () => ({}), proactiveModule5 = null, PROACTIVE_NO_OP_SUBSCRIBE = (_cb) => () => {}, PROACTIVE_FALSE = () => false, SUGGEST_BG_PR_NOOP = (_p, _n) => false, EMPTY_MCP_CLIENTS2, HISTORY_STUB, RECENT_SCROLL_REPIN_WINDOW_MS = 3000, TITLE_ANIMATION_FRAMES, TITLE_STATIC_PREFIX, TITLE_ANIMATION_INTERVAL_MS = 960;
677042
677140
  var init_REPL = __esm(() => {
677043
677141
  init_state();
677044
677142
  init_tokenBudget();
@@ -677092,6 +677190,7 @@ var init_REPL = __esm(() => {
677092
677190
  init_useSkillImprovementSurvey();
677093
677191
  init_Spinner2();
677094
677192
  init_prompts3();
677193
+ init_figures2();
677095
677194
  init_systemPrompt();
677096
677195
  init_context2();
677097
677196
  init_claudemd();
@@ -677250,6 +677349,7 @@ var init_REPL = __esm(() => {
677250
677349
  maybeLoadOlder: (_2) => {}
677251
677350
  };
677252
677351
  TITLE_ANIMATION_FRAMES = ["⠂", "⠐"];
677352
+ TITLE_STATIC_PREFIX = getBrandGlyph();
677253
677353
  });
677254
677354
 
677255
677355
  // src/replLauncher.tsx
@@ -678226,7 +678326,7 @@ function WelcomeV2() {
678226
678326
  dimColor: true,
678227
678327
  children: [
678228
678328
  "v",
678229
- "1.3.434"
678329
+ "1.3.436"
678230
678330
  ]
678231
678331
  }, undefined, true, undefined, this)
678232
678332
  ]
@@ -678772,7 +678872,7 @@ var exports_TrustDialog = {};
678772
678872
  __export(exports_TrustDialog, {
678773
678873
  TrustDialog: () => TrustDialog
678774
678874
  });
678775
- import { homedir as homedir38 } from "os";
678875
+ import { homedir as homedir39 } from "os";
678776
678876
  function TrustDialog(t0) {
678777
678877
  const $3 = import_compiler_runtime347.c(33);
678778
678878
  const {
@@ -678883,7 +678983,7 @@ function TrustDialog(t0) {
678883
678983
  let t13;
678884
678984
  if ($3[13] !== hasAnyBashExecution) {
678885
678985
  t12 = () => {
678886
- const isHomeDir = homedir38() === getCwd();
678986
+ const isHomeDir = homedir39() === getCwd();
678887
678987
  logEvent("tengu_trust_dialog_shown", {
678888
678988
  isHomeDir,
678889
678989
  hasMcpServers,
@@ -678912,7 +679012,7 @@ function TrustDialog(t0) {
678912
679012
  gracefulShutdownSync(1);
678913
679013
  return;
678914
679014
  }
678915
- const isHomeDir_0 = homedir38() === getCwd();
679015
+ const isHomeDir_0 = homedir39() === getCwd();
678916
679016
  logEvent("tengu_trust_dialog_accept", {
678917
679017
  isHomeDir: isHomeDir_0,
678918
679018
  hasMcpServers,
@@ -679960,7 +680060,7 @@ function completeOnboarding() {
679960
680060
  saveGlobalConfig((current) => ({
679961
680061
  ...current,
679962
680062
  hasCompletedOnboarding: true,
679963
- lastOnboardingVersion: "1.3.434"
680063
+ lastOnboardingVersion: "1.3.436"
679964
680064
  }));
679965
680065
  }
679966
680066
  function showDialog(root2, renderer) {
@@ -681105,7 +681205,7 @@ var exports_ResumeConversation = {};
681105
681205
  __export(exports_ResumeConversation, {
681106
681206
  ResumeConversation: () => ResumeConversation
681107
681207
  });
681108
- import { dirname as dirname69 } from "path";
681208
+ import { dirname as dirname70 } from "path";
681109
681209
  function parsePrIdentifier(value) {
681110
681210
  const directNumber = parseInt(value, 10);
681111
681211
  if (!isNaN(directNumber) && directNumber > 0) {
@@ -681237,7 +681337,7 @@ function ResumeConversation({
681237
681337
  }
681238
681338
  if (false) {}
681239
681339
  if (result_3.sessionId && !forkSession) {
681240
- switchSession(asSessionId(result_3.sessionId), log_0.fullPath ? dirname69(log_0.fullPath) : null);
681340
+ switchSession(asSessionId(result_3.sessionId), log_0.fullPath ? dirname70(log_0.fullPath) : null);
681241
681341
  await renameRecordingForSession();
681242
681342
  await resetSessionFilePointer();
681243
681343
  restoreCostStateForSession(result_3.sessionId);
@@ -682722,6 +682822,647 @@ var init_remember = __esm(() => {
682722
682822
  init_bundledSkills();
682723
682823
  });
682724
682824
 
682825
+ // src/skills/bundled/rayu/rayu-frontend-design/SKILL.md
682826
+ var SKILL_default = `---
682827
+ name: rayu-frontend-design
682828
+ description: Guidance for building distinctive, intentional web/mobile UI that doesn't read as a templated default. Use when designing or reshaping a UI — choosing visual direction, type, layout, motion, and microcopy. Pairs with the design subagent's PRD.
682829
+ ---
682830
+
682831
+ # Rayu Frontend Design
682832
+
682833
+ Build interfaces a real design studio would ship: opinionated, specific to the brief, and free of the generic "AI default" look. Your job is to make deliberate choices you can justify — not to assemble safe defaults.
682834
+
682835
+ ## 1. Ground the design in a real subject
682836
+
682837
+ Before any pixels, name three things and write them down:
682838
+
682839
+ - **Subject** — what the product actually is, in one concrete sentence.
682840
+ - **Audience** — who uses it and what they care about.
682841
+ - **The page's single job** — the one action or understanding the page must produce.
682842
+
682843
+ If the brief leaves these open, decide them and state your decision. Pull distinctive details from the subject's own world (its materials, vocabulary, artifacts). If a \`.rayu/swarm/\` design PRD or shared brief exists, treat it as the source of truth and build from it instead of re-deriving.
682844
+
682845
+ ## 2. Avoid the generic default
682846
+
682847
+ Current "AI-generated" UI clusters around a few tells. Treat these as smells, not destinations:
682848
+
682849
+ - Cream/off-white background + high-contrast serif + a single terracotta accent.
682850
+ - Near-black background + one acid-green or vermilion accent.
682851
+ - Hairline-rule "broadsheet" layouts with zero radius and dense columns.
682852
+ - Decorative \`01 / 02 / 03\` numbering applied to content that isn't actually a sequence.
682853
+
682854
+ These are fine *only* when the brief explicitly calls for them. Where the brief leaves an axis free, spend that freedom on a choice specific to the subject — not on a default.
682855
+
682856
+ ## 3. Make the type carry the personality
682857
+
682858
+ - Set a real type scale (e.g. a modular scale around 1.2–1.333) with intentional weights and spacing — not browser defaults.
682859
+ - Pair a characterful **display** face (used with restraint) with a clean **body** face; add a **utility/mono** face only if data/captions need it.
682860
+ - Decide line-height per role (tight for display, ~1.5 for body) and constrain measure (~60–75ch for body text).
682861
+
682862
+ ## 4. Structure should encode meaning
682863
+
682864
+ Eyebrows, dividers, numbering, and labels should reflect something true about the content, not decorate it. Ask "does this device carry information the reader needs?" before adding it. One memorable **signature element** per page; keep everything around it quiet.
682865
+
682866
+ ## 5. Motion, deliberately
682867
+
682868
+ Choose where motion serves the subject: a page-load reveal, a scroll-triggered moment, hover micro-interactions. An orchestrated moment beats scattered effects. Keep durations in the 150–300ms range for UI feedback. **Always** honor \`prefers-reduced-motion: reduce\` — gate non-essential animation behind it.
682869
+
682870
+ ## 6. The accessibility floor (non-negotiable)
682871
+
682872
+ - Contrast ≥ 4.5:1 for body text, ≥ 3:1 for large text and meaningful UI.
682873
+ - Visible keyboard focus on every interactive element; logical tab order.
682874
+ - Real semantic HTML (\`button\`, \`nav\`, \`main\`, headings in order); \`alt\` text; labels tied to inputs.
682875
+ - Touch targets ≥ 44×44px with spacing.
682876
+ - Responsive down to ~360px with no horizontal scroll.
682877
+
682878
+ ## 7. Microcopy is design material
682879
+
682880
+ Write from the user's side of the screen: name things by what people control, not how the system is built. Active voice on controls ("Save changes", not "Submit"), and keep an action's name consistent through its flow (a "Publish" button → a "Published" toast). Make empty and error states do real work: say what happened and what to do next.
682881
+
682882
+ ## 8. Process: plan → critique → build → critique
682883
+
682884
+ 1. **Plan** a compact token system: 4–6 named hex colors, 2+ type roles, a layout concept (sketch it in prose/ASCII), and the one signature element.
682885
+ 2. **Critique the plan against the brief** — if any part reads like the default you'd produce for any similar page, change it and say why.
682886
+ 3. **Build** from the revised plan; derive every color/type decision from the tokens (see the \`rayu-design-system\` skill for the token model).
682887
+ 4. **Critique again** while building — verify the a11y floor, responsiveness, and reduced-motion. Cut one decoration that doesn't serve the brief.
682888
+
682889
+ ## Working in the rayu swarm
682890
+
682891
+ When you're the \`frontend\` (or \`mobile\`) collaborator, implement against the \`design\` PRD and the backend contract from \`.rayu/swarm/\`. Use the \`Skill\` tool to also pull \`rayu-design-system\` for the token model. Report concisely; persist durable design decisions to your domain section.
682892
+ `;
682893
+ var init_SKILL = () => {};
682894
+
682895
+ // src/skills/bundled/rayu/rayu-design-system/SKILL.md
682896
+ var SKILL_default2 = "---\nname: rayu-design-system\ndescription: Build and apply a consistent design-token system — color, spacing, type, radius, shadow — with theming, dark mode, and responsive scales. Use when setting up a UI's foundation or enforcing visual consistency across components.\n---\n\n# Rayu Design System\n\nA design system is the small set of decisions every component obeys. Define the tokens once, name them by intent, and never hard-code a raw value in a component again.\n\n## 1. Two layers of tokens\n\n- **Primitive tokens** — the raw palette/scale: `color-blue-600: #2563eb`, `space-4: 1rem`, `font-size-lg: 1.125rem`. No meaning, just values.\n- **Semantic tokens** — intent mapped onto primitives: `color-bg`, `color-surface`, `color-text`, `color-text-muted`, `color-border`, `color-accent`, `color-danger`. **Components consume only semantic tokens.** This is what makes theming and dark mode a one-file change.\n\nExpose them as CSS custom properties (or your framework's theme object):\n\n```css\n:root {\n --color-bg: #ffffff;\n --color-surface: #f7f7f8;\n --color-text: #18181b;\n --color-text-muted: #52525b;\n --color-border: #e4e4e7;\n --color-accent: #2563eb;\n --radius-md: 0.5rem;\n --space-2: 0.5rem; --space-4: 1rem; --space-8: 2rem;\n}\n```\n\n## 2. The scales\n\n- **Spacing** — one scale, geometric or 4px-based (`2,4,8,12,16,24,32,48,64`). Every margin/padding/gap comes from it.\n- **Type** — a modular scale (ratio ~1.2–1.333) with defined roles (display, h1–h3, body, caption), each with weight + line-height. Body ≈ 16px / 1.5.\n- **Radius / shadow / border** — 2–4 steps each. Resist per-component one-offs.\n- **Z-index** — a named ladder (`dropdown, sticky, overlay, modal, toast`) so stacking is intentional.\n\n## 3. Theming and dark mode\n\nBecause components use semantic tokens, a theme is just a different mapping of semantic → primitive. Implement dark mode by overriding the semantic layer:\n\n```css\n:root[data-theme='dark'] {\n --color-bg: #0b0b0e;\n --color-surface: #18181b;\n --color-text: #fafafa;\n --color-text-muted: #a1a1aa;\n --color-border: #27272a;\n}\n```\n\nVerify **both** themes hit the contrast floor (≥ 4.5:1 body). Respect `prefers-color-scheme` for the default and let users override.\n\n## 4. Responsive scale\n\nMobile-first. Define a few breakpoints (`sm 640, md 768, lg 1024, xl 1280`) and a fluid type/space step if you want headings to scale (`clamp()` is your friend). Containers get a max-width + auto margins; never let content run edge-to-edge on wide screens.\n\n## 5. Component states\n\nEvery interactive component defines all of: `default, hover, active, focus-visible, disabled`, plus `loading` and `error` where relevant. Focus-visible must be clearly visible (don't remove outlines without replacing them). Document the states next to the component.\n\n## 6. Consistency checklist\n\n- [ ] No raw hex / px in components — only tokens.\n- [ ] One spacing scale, one type scale, used everywhere.\n- [ ] Semantic tokens only in components; primitives only in the theme map.\n- [ ] Light + dark both pass contrast.\n- [ ] All states defined incl. focus-visible.\n- [ ] Icons from one set; consistent stroke/size.\n\n## Working in the rayu swarm\n\nThe `design` subagent should emit these tokens in its PRD; the `frontend`/`mobile` collaborators implement against them (pair with the `rayu-frontend-design` skill). Persist the final token set to your `.rayu/swarm/` domain section so the whole swarm stays visually aligned.\n";
682897
+ var init_SKILL2 = () => {};
682898
+
682899
+ // src/skills/bundled/rayu/rayu-web-testing/SKILL.md
682900
+ var SKILL_default3 = `---
682901
+ name: rayu-web-testing
682902
+ description: Approach for testing and verifying local web applications end-to-end — driving a real browser, finding selectors, capturing screenshots/logs, and stabilizing flaky tests. Use when verifying frontend behavior or writing E2E tests.
682903
+ ---
682904
+
682905
+ # Rayu Web Testing
682906
+
682907
+ Verify what the user actually sees by driving a real browser against the running app. Prefer a mainstream automation library (Playwright recommended; Cypress/Puppeteer are fine) and write small, deterministic scripts.
682908
+
682909
+ ## Decision tree: pick the cheapest approach that works
682910
+
682911
+ \`\`\`
682912
+ Is the page static HTML (no JS rendering)?
682913
+ ├─ Yes → read the HTML directly, grab selectors, assert on the served markup.
682914
+ └─ No (dynamic app) → is the dev server already running?
682915
+ ├─ No → start it, wait until it's actually serving, THEN drive the browser.
682916
+ └─ Yes → reconnaissance-then-action:
682917
+ 1) navigate, wait for network idle / a known element
682918
+ 2) screenshot or dump the DOM to discover real selectors
682919
+ 3) act using the discovered selectors
682920
+ 4) assert on visible state, not internals
682921
+ \`\`\`
682922
+
682923
+ ## Server lifecycle
682924
+
682925
+ Don't assume the server is up. Start it (\`npm run dev\`, \`vite\`, etc.), poll the port/URL until it responds, run the test, then tear it down. For multi-service apps (API + web), start each, wait for each to be healthy, then drive. Never hard-code \`sleep\` — wait on a real readiness signal (port open, health route 200, or an element present).
682926
+
682927
+ ## Selectors: stable first
682928
+
682929
+ Priority order:
682930
+ 1. Role/label/text (\`getByRole('button', { name: 'Save' })\`, \`getByLabel\`) — closest to what users perceive.
682931
+ 2. \`data-testid\` hooks added intentionally for tests.
682932
+ 3. CSS/structure — last resort; brittle.
682933
+
682934
+ Avoid selectors tied to styling or DOM depth. If you can't find a stable hook, add a \`data-testid\` to the app rather than writing a fragile selector.
682935
+
682936
+ ## Minimal Playwright shape
682937
+
682938
+ \`\`\`js
682939
+ import { test, expect } from '@playwright/test'
682940
+
682941
+ test('user can submit the contact form', async ({ page }) => {
682942
+ await page.goto('http://localhost:5173/contact')
682943
+ await page.getByLabel('Email').fill('a@example.com')
682944
+ await page.getByRole('button', { name: 'Send' }).click()
682945
+ await expect(page.getByText('Thanks — we got it')).toBeVisible()
682946
+ })
682947
+ \`\`\`
682948
+
682949
+ ## Evidence: screenshots + logs
682950
+
682951
+ Capture a screenshot on failure (and at key steps for UI work) — "a picture is worth a thousand tokens" when diagnosing. Collect browser console errors and failed network requests; they explain most "it just doesn't work" reports. Surface those in the result rather than guessing.
682952
+
682953
+ ## Killing flakiness
682954
+
682955
+ - **Wait on conditions, not time.** Use auto-waiting assertions / \`waitFor\`, never fixed delays.
682956
+ - **Isolate state.** Reset DB/storage between tests; don't depend on test order.
682957
+ - **One reason to fail per test.** Small, focused specs localize breakage.
682958
+ - **Control the network.** Mock third-party calls so a flaky upstream doesn't fail your suite.
682959
+ - **Pin the viewport** for layout-sensitive assertions.
682960
+
682961
+ ## Coverage priorities for a web app
682962
+
682963
+ 1. Critical happy paths (auth, the primary conversion flow).
682964
+ 2. Form validation + error states.
682965
+ 3. Responsive behavior at one mobile + one desktop width.
682966
+ 4. Accessibility smoke (focus order, a labelled primary action).
682967
+
682968
+ ## Working in the rayu swarm
682969
+
682970
+ The \`review\` subagent and \`security\` collaborator use this to verify produced UI against the spec, returning a concrete pass/fail + a Fix List. Keep scripts black-box and short; report high-signal results (what failed, the screenshot/log), not a play-by-play.
682971
+ `;
682972
+ var init_SKILL3 = () => {};
682973
+
682974
+ // src/skills/bundled/rayu/rayu-api-design/SKILL.md
682975
+ var SKILL_default4 = "---\nname: rayu-api-design\ndescription: Conventions for designing clean, consistent HTTP/REST APIs — resources, request/response schemas, status codes, error envelopes, pagination, versioning, auth-per-route, and idempotency. Use when defining a backend contract. Pairs with the backend-design subagent.\n---\n\n# Rayu API Design\n\nDesign the contract before the implementation. A good API is predictable: a developer who has seen three endpoints can guess the fourth.\n\n## 1. Resources and routes\n\n- Model **nouns**, not verbs: `/users`, `/users/{id}`, `/users/{id}/orders`.\n- Use HTTP methods for the verb: `GET` (read, safe), `POST` (create), `PUT`/`PATCH` (replace/update), `DELETE` (remove).\n- Plural collection names; lowercase, hyphenated paths. Nest only one level deep — prefer `/orders?userId=…` over deep nesting.\n- Keep responses consistent in shape across endpoints.\n\n## 2. Request / response schemas\n\nDefine every field with name, type, required/optional, and validation. Keep wire names consistent (pick `camelCase` or `snake_case` and never mix). Echo created/updated resources back in the response so the client doesn't need a second round-trip.\n\n```http\nPOST /api/v1/users\nContent-Type: application/json\n\n{ \"email\": \"a@example.com\", \"password\": \"••••••\", \"name\": \"Ada\" }\n\n201 Created\n{ \"id\": \"usr_123\", \"email\": \"a@example.com\", \"name\": \"Ada\", \"createdAt\": \"2026-01-01T00:00:00Z\" }\n```\n\n## 3. Status codes (use them precisely)\n\n- `200` OK, `201` Created (+ `Location`), `204` No Content (deletes).\n- `400` malformed, `401` unauthenticated, `403` authenticated-but-forbidden, `404` not found, `409` conflict, `422` validation failed, `429` rate-limited.\n- `500` server error (never leak internals), `503` unavailable.\n\n## 4. One error envelope everywhere\n\nPick a single error shape and use it for *every* error:\n\n```json\n{ \"error\": { \"code\": \"validation_failed\",\n \"message\": \"Email is already registered.\",\n \"details\": [{ \"field\": \"email\", \"issue\": \"duplicate\" }] } }\n```\n\nMachine-readable `code`, human `message`, optional `details`. Never return HTML errors from a JSON API.\n\n## 5. Pagination, filtering, sorting\n\n- Cursor pagination for large/append-heavy sets (`?limit=20&cursor=…`), offset for small/admin lists (`?page=2&pageSize=20`).\n- Return pagination metadata (`nextCursor` or `total`/`page`).\n- Standardize filtering (`?status=active`) and sorting (`?sort=-createdAt`).\n\n## 6. Versioning\n\nVersion from day one: `/api/v1/…` (or an `Accept` header). Only break within a new version; add fields additively within a version (new optional fields aren't breaking).\n\n## 7. Auth per route (ties into security)\n\nFor each endpoint declare: public vs authenticated, and the role/permission required. Use `Authorization: Bearer <token>`; return `401` (no/invalid token) vs `403` (valid token, insufficient role). Keep the auth model centralized (middleware/guards), not per-handler. The `security` collaborator owns the auth decisions — design routes to fit them.\n\n## 8. Idempotency & safety\n\n- `GET`/`PUT`/`DELETE` are idempotent; `POST` is not — for money/critical creates, accept an `Idempotency-Key` header and dedupe.\n- Validate and normalize all input at the boundary; never trust the client.\n- Rate-limit public/auth endpoints; return `429` + `Retry-After`.\n\n## Working in the rayu swarm\n\nThe `backend-design` subagent emits the API contract + data model PRD using these conventions; the `backend` collaborator implements against it, and the `frontend`/`mobile` collaborators code their API layer to the same shapes. Keep the contract in `.rayu/swarm/` so every domain agrees on it.\n";
682976
+ var init_SKILL4 = () => {};
682977
+
682978
+ // src/skills/bundled/rayu/rayu-mcp-builder/SKILL.md
682979
+ var SKILL_default5 = `---
682980
+ name: rayu-mcp-builder
682981
+ description: Build a Model Context Protocol (MCP) server that exposes tools, resources, and prompts to AI agents. Use when creating an MCP server or integration — covers server anatomy, transports, input schemas, error handling, testing, and safe tool exposure.
682982
+ ---
682983
+
682984
+ # Rayu MCP Builder
682985
+
682986
+ The Model Context Protocol (MCP) is a standard way to expose capabilities to AI clients. A server offers three primitives — **tools** (actions the model can call), **resources** (readable data the model can pull in), and **prompts** (reusable templates) — over a JSON-RPC transport.
682987
+
682988
+ ## 1. Pick a transport
682989
+
682990
+ - **stdio** — the server is launched as a subprocess; it speaks JSON-RPC over stdin/stdout. Best for local tools a client spawns. (Most common.)
682991
+ - **HTTP + SSE / streamable HTTP** — the server runs as a network service. Use for remote/shared servers.
682992
+
682993
+ Start with stdio unless you need a networked server.
682994
+
682995
+ ## 2. Minimal server anatomy (TypeScript SDK)
682996
+
682997
+ \`\`\`ts
682998
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
682999
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
683000
+ import { z } from 'zod'
683001
+
683002
+ const server = new McpServer({ name: 'my-server', version: '1.0.0' })
683003
+
683004
+ server.tool(
683005
+ 'get_weather',
683006
+ 'Get current weather for a city',
683007
+ { city: z.string().describe('City name') }, // input schema (zod)
683008
+ async ({ city }) => {
683009
+ const data = await fetchWeather(city)
683010
+ return { content: [{ type: 'text', text: JSON.stringify(data) }] }
683011
+ },
683012
+ )
683013
+
683014
+ await server.connect(new StdioServerTransport())
683015
+ \`\`\`
683016
+
683017
+ (Python SDK mirrors this with \`FastMCP\` and \`@mcp.tool()\` decorators.)
683018
+
683019
+ ## 3. Design the tools well — the schema IS the UX
683020
+
683021
+ The model only sees names, descriptions, and schemas. So:
683022
+
683023
+ - **Name** tools by action (\`create_invoice\`, not \`invoices\`).
683024
+ - **Describe** what the tool does AND when to use it — the description drives selection.
683025
+ - **Schema**: every parameter typed, with a \`.describe()\`. Mark optionals; give safe defaults. Validate strictly (zod/pydantic) and reject bad input early.
683026
+ - Keep each tool **single-purpose**. Many small, clear tools beat one mega-tool with a mode flag.
683027
+ - Return concise, structured results; large blobs belong in **resources**, not tool output.
683028
+
683029
+ ## 4. Resources and prompts
683030
+
683031
+ - **Resources** expose readable content by URI (\`file://…\`, \`db://orders/123\`). Provide a list endpoint + a read endpoint; support templates (\`db://orders/{id}\`) when enumerable.
683032
+ - **Prompts** are named, parameterized templates the user can invoke. Use them for repeatable workflows.
683033
+
683034
+ ## 5. Error handling
683035
+
683036
+ - Validation failures → return a clear tool error the model can recover from (message says what was wrong), not an unhandled crash.
683037
+ - Distinguish *user/input* errors (fixable by changing args) from *system* errors (retryable/fatal).
683038
+ - Never let an exception kill the process on stdio — catch, return a structured error, keep serving.
683039
+
683040
+ ## 6. Security of tool exposure (critical)
683041
+
683042
+ A tool is an action you're handing to a model. Treat every input as untrusted:
683043
+
683044
+ - **Least privilege** — expose the narrowest capability that does the job. Don't expose \`run_shell(cmd)\` when \`list_files(dir)\` suffices.
683045
+ - **Validate + sanitize** all inputs; constrain paths (no traversal), allow-list commands, parameterize queries.
683046
+ - **Guard side effects** — destructive tools (delete, transfer, deploy) should require explicit args and ideally a confirmation/dry-run mode.
683047
+ - **Secrets** come from the environment, never from tool args or hard-coded values; never echo them in results.
683048
+ - **Rate/size limits** on anything that hits the network or returns large data.
683049
+
683050
+ ## 7. Test it
683051
+
683052
+ - Unit-test each tool's handler directly (input → output, incl. error paths).
683053
+ - Integration-test over the transport with the MCP Inspector or a scripted client: list tools, call each with valid + invalid input, assert the structured result.
683054
+ - Verify the server starts, advertises its tools/resources, and shuts down cleanly.
683055
+
683056
+ ## 8. Ship checklist
683057
+
683058
+ - [ ] Clear \`name\`/\`version\`; tools have action names + when-to-use descriptions.
683059
+ - [ ] Strict input schemas with descriptions and validation.
683060
+ - [ ] Structured errors; process never dies on bad input.
683061
+ - [ ] Least-privilege tools; destructive ops guarded; secrets from env.
683062
+ - [ ] Tested over the transport; documented setup (command, env vars).
683063
+
683064
+ ## Working in the rayu swarm
683065
+
683066
+ The \`backend\` collaborator uses this when a task needs an MCP server/integration. Pair with \`rayu-api-design\` for the underlying data/contract conventions. Record the exposed tool surface in \`.rayu/swarm/\` so the rest of the swarm knows the integration's capabilities.
683067
+ `;
683068
+ var init_SKILL5 = () => {};
683069
+
683070
+ // src/skills/bundled/rayu/rayu-doc-export/SKILL.md
683071
+ var SKILL_default6 = '---\nname: rayu-doc-export\ndescription: Generate office documents and PDFs (docx, xlsx, pptx, pdf) programmatically using open-source libraries. Use when a task needs to produce a Word, Excel, PowerPoint, or PDF deliverable from data or content.\n---\n\n# Rayu Doc Export\n\nProduce real office files with well-maintained open-source libraries. Pick the library by output format and ecosystem, install it, generate the file, and verify it opens. All guidance below is built on the libraries\' own public documentation.\n\n## Library map\n\n| Format | Python (recommended) | JavaScript/Node |\n|---|---|---|\n| **Word** `.docx` | `python-docx` | `docx` (npm) |\n| **Excel** `.xlsx` | `openpyxl` | `exceljs` |\n| **PowerPoint** `.pptx` | `python-pptx` | `pptxgenjs` |\n| **PDF** | `reportlab` (or `weasyprint` for HTML→PDF) | `pdf-lib` |\n\nPython has the most mature OOXML coverage; use it unless the project is JS-only.\n\n## Word — python-docx\n\n```bash\npip install python-docx # NOTE: package is "python-docx"; import is "docx"\n```\n\n```python\nfrom docx import Document\nfrom docx.shared import Pt, Inches\n\ndoc = Document()\ndoc.add_heading(\'Quarterly Report\', level=1)\ndoc.add_paragraph(\'Summary of results for Q1.\')\ndoc.add_paragraph(\'A bullet item\', style=\'List Bullet\')\n\ntable = doc.add_table(rows=1, cols=2)\ntable.style = \'Light Grid Accent 1\'\nhdr = table.rows[0].cells\nhdr[0].text, hdr[1].text = \'Metric\', \'Value\'\nrow = table.add_row().cells\nrow[0].text, row[1].text = \'Revenue\', \'$1.2M\'\n\ndoc.add_picture(\'chart.png\', width=Inches(5))\ndoc.save(\'report.docx\')\n```\n\nKey objects: `Document`, `add_heading`, `add_paragraph` (+ `style`), `add_table`/`add_row`, `add_picture`. Runs (`paragraph.add_run(\'x\').bold = True`) control inline formatting.\n\n## Excel — openpyxl\n\n```bash\npip install openpyxl\n```\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nwb = Workbook()\nws = wb.active\nws.title = \'Sales\'\nws.append([\'Month\', \'Revenue\']) # write a row\nws[\'A1\'].font = Font(bold=True)\nws.append([\'Jan\', 1200])\nws[\'B3\'] = \'=SUM(B2:B2)\' # formulas are just strings\nws.column_dimensions[\'A\'].width = 16\nwb.save(\'sales.xlsx\')\n```\n\nKey objects: `Workbook`, `wb.active`/`wb.create_sheet`, cell access (`ws[\'A1\']` or `ws.cell(row, column)`), `ws.append(list)`, styles (`Font`, `PatternFill`, `Alignment`), and `wb.save`. For huge sheets use `write_only=True`.\n\n## PowerPoint — python-pptx\n\n```bash\npip install python-pptx\n```\n\n```python\nfrom pptx import Presentation\nfrom pptx.util import Inches, Pt\n\nprs = Presentation()\ntitle_slide = prs.slides.add_slide(prs.slide_layouts[0]) # 0 = Title\ntitle_slide.shapes.title.text = \'Rayu Deck\'\ntitle_slide.placeholders[1].text = \'Generated with python-pptx\'\n\nbullets = prs.slides.add_slide(prs.slide_layouts[1]) # 1 = Title+Content\nbullets.shapes.title.text = \'Agenda\'\ntf = bullets.placeholders[1].text_frame\ntf.text = \'First point\'\ntf.add_paragraph().text = \'Second point\'\n\nprs.save(\'deck.pptx\')\n```\n\nKey objects: `Presentation`, `slide_layouts` (indexes into the template\'s layouts), `shapes.title`/`placeholders`, `text_frame` + `add_paragraph`, and `shapes.add_textbox`/`add_picture` for free placement.\n\n## PDF — reportlab (Python) or pdf-lib (JS)\n\n**reportlab, low-level canvas** (precise placement):\n\n```python\nfrom reportlab.pdfgen import canvas\nfrom reportlab.lib.pagesizes import letter\n\nc = canvas.Canvas(\'out.pdf\', pagesize=letter)\nc.drawString(72, 720, \'Hello World\') # origin is bottom-left\nc.showPage() # finish the page\nc.save()\n```\n\n**reportlab, Platypus** (flowing documents — paragraphs, tables, page breaks):\n\n```python\nfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Table\nfrom reportlab.lib.styles import getSampleStyleSheet\n\nstyles = getSampleStyleSheet()\ndoc = SimpleDocTemplate(\'report.pdf\')\ndoc.build([\n Paragraph(\'Quarterly Report\', styles[\'Title\']),\n Paragraph(\'Summary text.\', styles[\'BodyText\']),\n Table([[\'Metric\', \'Value\'], [\'Revenue\', \'$1.2M\']]),\n])\n```\n\n**pdf-lib (Node/browser):**\n\n```js\nimport { PDFDocument, StandardFonts } from \'pdf-lib\'\n\nconst pdf = await PDFDocument.create()\nconst page = pdf.addPage([595, 842]) // A4 in points\nconst font = await pdf.embedFont(StandardFonts.Helvetica)\npage.drawText(\'Hello World\', { x: 72, y: 770, size: 18, font })\nconst bytes = await pdf.save() // Uint8Array → write to disk\n```\n\nUse Platypus/reportlab when generating from scratch; if you already have HTML/CSS, `weasyprint` (HTML→PDF) is often faster to a polished result.\n\n## Common pitfalls\n\n- **Wrong Word package:** install `python-docx` (not the abandoned `docx`); the import is still `import docx` / `from docx import Document`.\n- **reportlab coordinates** start at the bottom-left, and `showPage()` + `save()` are required or the file is empty/corrupt.\n- **pptx layout indexes** depend on the template; enumerate `prs.slide_layouts` rather than guessing.\n- **openpyxl formulas** are stored as strings and only evaluated when the file is opened in Excel (openpyxl won\'t compute them).\n- **Fonts/images:** embed fonts and reference image paths that exist at generate time; verify the output opens before reporting done.\n\n## Working in the rayu swarm\n\nUse this for any "produce a report/spreadsheet/deck/PDF" deliverable. Match the data to the right library, generate into the project\'s output path, and confirm the file is valid. These are open-source libraries — no proprietary document engine is required.\n';
683072
+ var init_SKILL6 = () => {};
683073
+
683074
+ // src/skills/bundled/rayu/rayu-canvas-design/SKILL.md
683075
+ var SKILL_default7 = `---
683076
+ name: rayu-canvas-design
683077
+ description: Compose static visual graphics on an HTML5 canvas — posters, social cards, diagrams, OG images, certificates. Use when generating a designed raster/vector image programmatically rather than a live UI.
683078
+ ---
683079
+
683080
+ # Rayu Canvas Design
683081
+
683082
+ Use the \`<canvas>\` 2D context (or a headless equivalent like \`node-canvas\`/\`@napi-rs/canvas\`/\`skia-canvas\`) to compose a finished image: an Open Graph card, a poster, a quote graphic, a diagram, a certificate. This is for *generated artwork*, not interactive UI.
683083
+
683084
+ ## Set up the surface
683085
+
683086
+ - Decide dimensions up front from the use case: OG image 1200×630, square social 1080×1080, story 1080×1920, A4 poster at 96dpi ≈ 794×1123 (×2–3 for print crispness).
683087
+ - **Render at 2× and scale down** for crisp text/edges, or set \`ctx.scale(dpr, dpr)\` with a backing store at \`width*dpr\`.
683088
+ - Establish a coordinate plan and a margin/safe-area before drawing.
683089
+
683090
+ \`\`\`js
683091
+ const W = 1200, H = 630, S = 2
683092
+ const canvas = createCanvas(W * S, H * S)
683093
+ const ctx = canvas.getContext('2d')
683094
+ ctx.scale(S, S)
683095
+ \`\`\`
683096
+
683097
+ ## Composition principles
683098
+
683099
+ - **Background first, foreground last.** Fill or gradient the bg, then layer shapes, then text on top.
683100
+ - **One focal point.** A single dominant element (a headline, a logo, a number) anchors the eye; everything else supports it.
683101
+ - **Grid + margins.** Keep content inside a safe margin (≈ 6–8% of width). Align to an invisible grid; don't eyeball every element.
683102
+ - **Type hierarchy.** 2–3 sizes max. Measure text (\`ctx.measureText\`) to wrap, center, and avoid overflow — never assume it fits.
683103
+ - **Contrast.** If text sits on an image, add a scrim (semi-opaque overlay) or shadow so it stays legible.
683104
+
683105
+ ## Core 2D recipes
683106
+
683107
+ \`\`\`js
683108
+ // Gradient background
683109
+ const g = ctx.createLinearGradient(0, 0, W, H)
683110
+ g.addColorStop(0, '#0f172a'); g.addColorStop(1, '#1e3a8a')
683111
+ ctx.fillStyle = g; ctx.fillRect(0, 0, W, H)
683112
+
683113
+ // Rounded rect (card)
683114
+ ctx.beginPath(); ctx.roundRect(80, 80, W - 160, H - 160, 24)
683115
+ ctx.fillStyle = 'rgba(255,255,255,0.06)'; ctx.fill()
683116
+
683117
+ // Text with manual wrap
683118
+ ctx.font = '700 64px Inter'; ctx.fillStyle = '#fff'
683119
+ ctx.textBaseline = 'top'
683120
+ wrapText(ctx, headline, 120, 140, W - 240, 76)
683121
+ \`\`\`
683122
+
683123
+ Helper: split words, accumulate until \`measureText(line).width > maxWidth\`, then break — write a small \`wrapText(ctx, text, x, y, maxWidth, lineHeight)\`.
683124
+
683125
+ ## Fonts and images
683126
+
683127
+ - **Register fonts** before drawing (headless libs need \`registerFont\`/\`GlobalFonts.register\`); a missing font silently falls back and ruins the layout.
683128
+ - **Await image loads** before \`drawImage\`; use \`drawImage(img, sx,sy,sw,sh, dx,dy,dw,dh)\` for crop-to-fit (cover/contain math).
683129
+ - Draw vector shapes for icons/logos when possible (crisp at any scale).
683130
+
683131
+ ## Export
683132
+
683133
+ \`\`\`js
683134
+ // PNG (lossless, transparency) — best for graphics with text
683135
+ const png = canvas.toBuffer('image/png')
683136
+ // JPEG (smaller, no transparency) — photographic backgrounds
683137
+ const jpg = canvas.toBuffer('image/jpeg', { quality: 0.9 })
683138
+ \`\`\`
683139
+
683140
+ Verify the output opens and the text isn't clipped before reporting done.
683141
+
683142
+ ## Pitfalls
683143
+
683144
+ - Forgetting \`textBaseline\` → vertical misalignment.
683145
+ - Not measuring text → overflow / clipping.
683146
+ - Unregistered fonts → wrong typeface.
683147
+ - Drawing before image/font load resolves → blank or fallback.
683148
+ - Low resolution → blurry text; render at 2×+.
683149
+
683150
+ ## Working in the rayu swarm
683151
+
683152
+ Use for generated image deliverables (OG/social cards, posters, diagrams). For *animated* or *interactive* visuals see \`rayu-algorithmic-art\`; for live product UI see \`rayu-frontend-design\`. Save assets to the project's image path and report each file with its dimensions.
683153
+ `;
683154
+ var init_SKILL7 = () => {};
683155
+
683156
+ // src/skills/bundled/rayu/rayu-web-artifacts-builder/SKILL.md
683157
+ var SKILL_default8 = `---
683158
+ name: rayu-web-artifacts-builder
683159
+ description: Build self-contained, single-file interactive web artifacts — a demo, calculator, visualization, mini-tool, or prototype that runs by opening one HTML file. Use when the deliverable is a standalone interactive page, not a full app.
683160
+ ---
683161
+
683162
+ # Rayu Web Artifacts Builder
683163
+
683164
+ An "artifact" is a single, self-contained interactive page that works by opening one file — no build step, no server, no install. Think: a unit converter, a data visualization, an interactive explainer, a game prototype, a configurator.
683165
+
683166
+ ## The contract
683167
+
683168
+ - **One file when possible.** Inline CSS in \`<style>\` and JS in \`<script>\`; embed small data as a JS object. The user can save it and double-click it.
683169
+ - **No build, no network by default.** It must run offline from \`file://\`. If you need a library, pull it from a CDN with an integrity hash and a graceful fallback — but prefer vanilla JS / the platform.
683170
+ - **Self-documenting.** A title, a one-line purpose, and obvious controls. No README required to use it.
683171
+
683172
+ ## Skeleton
683173
+
683174
+ \`\`\`html
683175
+ <!doctype html>
683176
+ <html lang="en">
683177
+ <head>
683178
+ <meta charset="utf-8" />
683179
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
683180
+ <title>Compound Interest Explorer</title>
683181
+ <style>
683182
+ :root { --bg:#0b0b0e; --fg:#fafafa; --accent:#22d3ee; }
683183
+ * { box-sizing: border-box }
683184
+ body { margin:0; font:16px/1.5 system-ui, sans-serif; background:var(--bg); color:var(--fg); }
683185
+ main { max-width: 720px; margin: 0 auto; padding: 2rem; }
683186
+ label { display:block; margin:.75rem 0 .25rem }
683187
+ input, button { font:inherit; padding:.5rem .75rem; border-radius:.5rem; }
683188
+ output { font-size:2rem; font-weight:700; color:var(--accent) }
683189
+ </style>
683190
+ </head>
683191
+ <body>
683192
+ <main>
683193
+ <h1>Compound Interest Explorer</h1>
683194
+ <label for="p">Principal</label>
683195
+ <input id="p" type="number" value="1000" />
683196
+ <output id="result">—</output>
683197
+ </main>
683198
+ <script>
683199
+ const p = document.getElementById('p')
683200
+ const result = document.getElementById('result')
683201
+ const fmt = new Intl.NumberFormat('en', { style:'currency', currency:'USD' })
683202
+ function update() { result.textContent = fmt.format(Number(p.value) * 1.05) }
683203
+ p.addEventListener('input', update); update()
683204
+ </script>
683205
+ </body>
683206
+ </html>
683207
+ \`\`\`
683208
+
683209
+ ## Build it well
683210
+
683211
+ - **State → render.** Keep a small state object; write one \`render()\` that reflects state into the DOM; event handlers mutate state then call \`render()\`. Avoid scattered DOM tweaks.
683212
+ - **Reach for the platform:** \`<input type=range>\`, \`<details>\`, \`<dialog>\`, \`Intl\`, \`requestAnimationFrame\`, \`<canvas>\`/SVG for graphics, \`localStorage\` for persistence.
683213
+ - **Make it responsive and keyboard-usable** even though it's "just" an artifact — labels on inputs, visible focus, works at mobile widths.
683214
+ - **Polish the empty/initial state** so it's obvious what to do.
683215
+ - **Performance:** debounce expensive recompute; for animation use \`requestAnimationFrame\`, not \`setInterval\`.
683216
+
683217
+ ## When NOT to use this
683218
+
683219
+ If it needs auth, a backend, multiple routes, or a real database, it's an app — use the \`frontend\`/\`backend\` collaborators and a real project scaffold instead. Artifacts are for one focused, client-only interaction.
683220
+
683221
+ ## Verify
683222
+
683223
+ Open the file (or load its markup) and exercise the controls: inputs update output, no console errors, works at a narrow width. Ship the single file.
683224
+
683225
+ ## Working in the rayu swarm
683226
+
683227
+ Use for quick interactive deliverables and prototypes. For visual styling depth pair with \`rayu-frontend-design\`; for generative graphics inside the artifact see \`rayu-algorithmic-art\`/\`rayu-canvas-design\`.
683228
+ `;
683229
+ var init_SKILL8 = () => {};
683230
+
683231
+ // src/skills/bundled/rayu/rayu-theme-factory/SKILL.md
683232
+ var SKILL_default9 = `---
683233
+ name: rayu-theme-factory
683234
+ description: Generate cohesive, distinctive visual themes — a coordinated palette, typography, and mood — and emit them as ready-to-use tokens. Use when you need to produce one or more complete theme options for a UI.
683235
+ ---
683236
+
683237
+ # Rayu Theme Factory
683238
+
683239
+ Produce a *complete, coherent theme* (or a few options) from a brief: a palette, type pairing, and supporting tokens that feel designed together — then emit them as usable tokens. This is theme *generation*; for the token *architecture* (semantic layering, dark mode mechanics) use \`rayu-design-system\`.
683240
+
683241
+ ## A theme is a coordinated set, not a random palette
683242
+
683243
+ Every theme has:
683244
+ 1. **A mood / direction** — one or two words (e.g. "warm editorial", "clinical precision", "retro arcade"). Decide this first; every choice serves it.
683245
+ 2. **A palette** — derived intentionally (below), not picked at random.
683246
+ 3. **A type pairing** — display + body that match the mood.
683247
+ 4. **Supporting tokens** — radius, shadow, spacing feel, motion character.
683248
+
683249
+ ## Build the palette intentionally
683250
+
683251
+ Work in **HSL/OKLCH**, not raw hex, so relationships are controllable:
683252
+
683253
+ - Pick **one base hue** that carries the mood.
683254
+ - Derive a **neutral ramp** (background → surface → border → muted text → text) by holding a slight hue tint and stepping lightness — neutrals with a hint of the brand hue feel cohesive; pure grey feels generic.
683255
+ - Choose an **accent** via a deliberate relationship to the base: analogous (calm), complementary (energetic), or triadic (playful).
683256
+ - Add **semantic states** (success/warning/danger/info) tuned to the palette, not stock bootstrap colors.
683257
+ - Generate **tints/shades** by stepping lightness in a consistent ratio (e.g. 50→900).
683258
+
683259
+ Always check contrast for text-on-surface pairs (≥ 4.5:1 body) in *both* light and dark.
683260
+
683261
+ ## Type pairing
683262
+
683263
+ Match faces to the mood: a high-contrast serif for editorial, a geometric sans for modern/tech, a grotesque for neutral/utility, a mono accent for data. Set the scale and weights (see \`rayu-design-system\` for the scale mechanics). Avoid the default "system-ui everywhere" unless the mood is deliberately plain.
683264
+
683265
+ ## Emit usable tokens
683266
+
683267
+ Output the theme as something a build can consume directly:
683268
+
683269
+ \`\`\`css
683270
+ :root {
683271
+ /* mood: warm editorial */
683272
+ --bg:#fbf7f0; --surface:#f3ece0; --border:#e3d8c6;
683273
+ --text:#241c14; --text-muted:#6b5d4b;
683274
+ --accent:#b4531f; --accent-contrast:#fff;
683275
+ --success:#3f7d3f; --danger:#a23b2d;
683276
+ --radius:0.375rem; --shadow:0 1px 2px rgba(36,28,20,.12);
683277
+ --font-display:'Fraunces', serif; --font-body:'Inter', sans-serif;
683278
+ }
683279
+ \`\`\`
683280
+
683281
+ Provide the matching **dark variant** by remapping the neutrals (don't just invert). If asked for multiple themes, give 2–3 *distinct* directions, each internally coherent — not three tints of the same idea.
683282
+
683283
+ ## Distinctiveness check
683284
+
683285
+ Before shipping a theme, ask: would this same palette/type show up for any random brief? If yes, push the base hue, the neutral tint, or the type pairing toward the specific mood. (See \`rayu-frontend-design\` on avoiding the generic default.)
683286
+
683287
+ ## Working in the rayu swarm
683288
+
683289
+ The \`design\` subagent uses this to generate the theme that goes into its PRD; the \`frontend\`/\`mobile\` collaborators implement the emitted tokens. Persist the chosen theme tokens to \`.rayu/swarm/\` so the build stays consistent.
683290
+ `;
683291
+ var init_SKILL9 = () => {};
683292
+
683293
+ // src/skills/bundled/rayu/rayu-brand-guidelines/SKILL.md
683294
+ var SKILL_default10 = `---
683295
+ name: rayu-brand-guidelines
683296
+ description: Define or apply a brand's identity system — logo usage, color, typography, voice, and imagery rules — so everything produced stays on-brand. Use when establishing a brand or enforcing consistency across deliverables.
683297
+ ---
683298
+
683299
+ # Rayu Brand Guidelines
683300
+
683301
+ A brand system is the rulebook that keeps every artifact recognizably the same author. Use this to *author* a brand guide from a brief, or to *apply* an existing one consistently.
683302
+
683303
+ ## What a brand system contains
683304
+
683305
+ 1. **Foundation** — mission/positioning in a sentence, and the personality in 3–5 adjectives (e.g. "precise, warm, confident"). Every other rule should trace back to these.
683306
+ 2. **Logo** — primary + secondary marks, clear-space (minimum padding around it), minimum size, and a do/don't list (don't stretch, recolor, rotate, add effects, place on busy backgrounds).
683307
+ 3. **Color** — primary, secondary, neutral ramp, and semantic colors, each with exact values (hex + the print/space equivalents if relevant). Specify which combinations are allowed and their contrast.
683308
+ 4. **Typography** — the brand typefaces (display, body, and a fallback stack), the type scale, and weight usage. Name when each is used.
683309
+ 5. **Voice & tone** — how the brand writes: person (we/you), formality, sentence length, words it uses and avoids, and how tone shifts by context (marketing vs error message vs docs).
683310
+ 6. **Imagery & iconography** — photography style, illustration style, icon set + stroke weight, and the overall visual texture.
683311
+ 7. **Layout** — grid, spacing rhythm, and composition tendencies (dense vs airy).
683312
+
683313
+ ## Authoring a brand from a brief
683314
+
683315
+ - Derive everything from the **personality adjectives** — they're the throughline. "Playful" → rounder type, brighter accent, looser spacing; "authoritative" → sturdier serif, restrained palette, tighter grid.
683316
+ - Make the color + type choices *specific* to the brand's world, not defaults (see \`rayu-frontend-design\` and \`rayu-theme-factory\`).
683317
+ - Write the voice section with **concrete examples**: a sample headline, a sample button label, a sample error message — show the voice, don't just describe it.
683318
+ - Output a structured guide (one markdown doc or a set of tokens) downstream agents can follow verbatim.
683319
+
683320
+ ## Voice: make it usable
683321
+
683322
+ Give do/don't pairs, not adjectives alone:
683323
+
683324
+ \`\`\`
683325
+ Personality: confident, plain-spoken, never hype.
683326
+ ✓ "Your changes are saved." ✗ "Awesome! We totally saved your stuff! 🎉"
683327
+ ✓ "Couldn't connect. Try again." ✗ "Oops! Something went wrong :("
683328
+ Use: clear verbs, sentence case, active voice.
683329
+ Avoid: exclamation points, jargon, anthropomorphizing the product.
683330
+ \`\`\`
683331
+
683332
+ ## Applying / auditing against a brand
683333
+
683334
+ When a guide exists, **conform to it** — don't reinvent. Audit deliverables against the rules: logo clear-space and min-size respected, only approved colors, correct typefaces and scale, voice consistent, imagery on-style. Flag each violation with the rule it breaks and the fix.
683335
+
683336
+ ## Working in the rayu swarm
683337
+
683338
+ The \`design\` subagent can author the brand section of its PRD with this; collaborators apply it and keep tokens/voice consistent across UI, copy, and generated assets (pairs with \`rayu-theme-factory\` for color/type and \`rayu-canvas-design\` for on-brand graphics). Persist the brand rules to \`.rayu/swarm/\` so the whole swarm stays on-brand.
683339
+ `;
683340
+ var init_SKILL10 = () => {};
683341
+
683342
+ // src/skills/bundled/rayu/rayu-algorithmic-art/SKILL.md
683343
+ var SKILL_default11 = `---
683344
+ name: rayu-algorithmic-art
683345
+ description: Create generative / algorithmic art with code — procedural patterns, flow fields, particle systems, fractals, and creative coding (Canvas, SVG, p5.js, shaders). Use when producing generative visuals, backgrounds, or animations from algorithms.
683346
+ ---
683347
+
683348
+ # Rayu Algorithmic Art
683349
+
683350
+ Make visuals from rules: a few parameters and an algorithm that produces something rich and often surprising. Use for generative backgrounds, abstract art, data-driven visuals, and ambient animation.
683351
+
683352
+ ## Pick the medium
683353
+
683354
+ - **Canvas 2D** — raster, fast for thousands of particles/strokes. Best general default.
683355
+ - **SVG** — vector, crisp + editable, great for plotter-style line art and scalable patterns (watch node counts).
683356
+ - **p5.js** — friendly creative-coding API (sketch \`setup()\`/\`draw()\`); good for quick exploration.
683357
+ - **WebGL / GLSL shaders** — per-pixel, GPU-fast; for fields, noise, fractals, and heavy real-time effects.
683358
+
683359
+ ## The generative toolkit
683360
+
683361
+ - **Randomness, controlled.** Use a **seeded** PRNG (e.g. mulberry32) so a result is reproducible — store the seed. Prefer *distributions* over flat \`Math.random()\`: gaussian for natural clustering, weighted choices for variety.
683362
+ - **Noise, not random, for organic form.** Perlin/Simplex noise gives smooth, coherent variation — the backbone of flow fields, terrain, clouds, and organic motion.
683363
+ - **Flow fields:** sample a noise field for an angle at each point; move particles along the angle, leaving trails. A handful of lines yields complex, elegant results.
683364
+ - **Particle systems:** each particle has position/velocity/lifespan; apply forces (noise, gravity, attraction); fade trails by drawing a translucent bg each frame.
683365
+ - **Tiling & symmetry:** rotate/mirror around a center, or tile a motif with jitter, for pattern and mandalas.
683366
+ - **Fractals / recursion:** subdivision, L-systems, and recursive shapes for self-similar structure.
683367
+
683368
+ ## Composition still matters
683369
+
683370
+ Algorithmic ≠ chaotic. Apply real design judgment:
683371
+ - **Constrain the palette** (3–5 colors from a coherent scheme — pair with \`rayu-theme-factory\`). Random rainbow output reads as noise.
683372
+ - **Density and negative space** — let the piece breathe; a clear focal area beats uniform busyness.
683373
+ - **Layering** — background field + mid-detail + sparse foreground accents.
683374
+ - **Curate.** Generate many seeds, keep the best. The selection is part of the artistry.
683375
+
683376
+ ## Minimal flow-field sketch (Canvas)
683377
+
683378
+ \`\`\`js
683379
+ const rand = mulberry32(seed)
683380
+ const angle = (x, y) => noise(x * 0.002, y * 0.002) * Math.PI * 2
683381
+ ctx.fillStyle = '#0b0b0e'; ctx.fillRect(0, 0, W, H)
683382
+ ctx.globalAlpha = 0.06; ctx.strokeStyle = palette[0]
683383
+ for (let i = 0; i < 1500; i++) {
683384
+ let x = rand() * W, y = rand() * H
683385
+ ctx.beginPath(); ctx.moveTo(x, y)
683386
+ for (let s = 0; s < 60; s++) { const a = angle(x, y); x += Math.cos(a) * 2; y += Math.sin(a) * 2; ctx.lineTo(x, y) }
683387
+ ctx.stroke()
683388
+ }
683389
+ \`\`\`
683390
+
683391
+ ## Animation & export
683392
+
683393
+ - Animate with \`requestAnimationFrame\`; advance a time/\`z\`-noise dimension for smooth evolution. Honor \`prefers-reduced-motion\` if it ships in a UI.
683394
+ - Export stills via canvas \`toBuffer\`/\`toDataURL\` (PNG); for loops, capture frames and assemble (gif/webm) or ship the live sketch as a \`rayu-web-artifacts-builder\` artifact.
683395
+ - Render at 2×+ for crisp stills.
683396
+
683397
+ ## Working in the rayu swarm
683398
+
683399
+ The \`asset-generation\` subagent uses this for generative backgrounds/visuals; pair with \`rayu-theme-factory\` for the palette and \`rayu-canvas-design\` for finishing static compositions. Save outputs to the project asset path and report seeds so results are reproducible.
683400
+ `;
683401
+ var init_SKILL11 = () => {};
683402
+
683403
+ // src/skills/bundled/rayuSkills.ts
683404
+ function getRayuSkillDefinitions() {
683405
+ const out = [];
683406
+ for (const { md: md3 } of RAYU_SKILLS) {
683407
+ const { frontmatter, content } = parseFrontmatter(md3);
683408
+ const name = typeof frontmatter.name === "string" ? frontmatter.name : "";
683409
+ const description = typeof frontmatter.description === "string" ? frontmatter.description : "";
683410
+ if (!name)
683411
+ continue;
683412
+ out.push({ name, description, body: content.trimStart() });
683413
+ }
683414
+ return out;
683415
+ }
683416
+ function registerRayuSkills() {
683417
+ for (const { name, description, body } of getRayuSkillDefinitions()) {
683418
+ registerBundledSkill({
683419
+ name,
683420
+ description,
683421
+ userInvocable: true,
683422
+ async getPromptForCommand(args) {
683423
+ const parts = [body];
683424
+ if (args) {
683425
+ parts.push(`## User Request
683426
+
683427
+ ${args}`);
683428
+ }
683429
+ return [{ type: "text", text: parts.join(`
683430
+
683431
+ `) }];
683432
+ }
683433
+ });
683434
+ }
683435
+ }
683436
+ var RAYU_SKILLS;
683437
+ var init_rayuSkills = __esm(() => {
683438
+ init_frontmatterParser();
683439
+ init_bundledSkills();
683440
+ init_SKILL();
683441
+ init_SKILL2();
683442
+ init_SKILL3();
683443
+ init_SKILL4();
683444
+ init_SKILL5();
683445
+ init_SKILL6();
683446
+ init_SKILL7();
683447
+ init_SKILL8();
683448
+ init_SKILL9();
683449
+ init_SKILL10();
683450
+ init_SKILL11();
683451
+ RAYU_SKILLS = [
683452
+ { md: SKILL_default },
683453
+ { md: SKILL_default2 },
683454
+ { md: SKILL_default3 },
683455
+ { md: SKILL_default4 },
683456
+ { md: SKILL_default5 },
683457
+ { md: SKILL_default6 },
683458
+ { md: SKILL_default7 },
683459
+ { md: SKILL_default8 },
683460
+ { md: SKILL_default9 },
683461
+ { md: SKILL_default10 },
683462
+ { md: SKILL_default11 }
683463
+ ];
683464
+ });
683465
+
682725
683466
  // src/skills/bundled/simplify.ts
682726
683467
  function registerSimplifySkill() {
682727
683468
  registerBundledSkill({
@@ -683552,18 +684293,18 @@ Documentation content for this bundled skill was not part of the imported source
683552
684293
  var init_server2 = () => {};
683553
684294
 
683554
684295
  // src/skills/bundled/verify/SKILL.md
683555
- var SKILL_default = `# SKILL (placeholder)
684296
+ var SKILL_default12 = `# SKILL (placeholder)
683556
684297
  Documentation content for this bundled skill was not part of the imported source tree.
683557
684298
  `;
683558
- var init_SKILL = () => {};
684299
+ var init_SKILL12 = () => {};
683559
684300
 
683560
684301
  // src/skills/bundled/verifyContent.ts
683561
684302
  var SKILL_MD, SKILL_FILES;
683562
684303
  var init_verifyContent = __esm(() => {
683563
684304
  init_cli();
683564
684305
  init_server2();
683565
- init_SKILL();
683566
- SKILL_MD = SKILL_default;
684306
+ init_SKILL12();
684307
+ SKILL_MD = SKILL_default12;
683567
684308
  SKILL_FILES = {
683568
684309
  "examples/cli.md": cli_default,
683569
684310
  "examples/server.md": server_default
@@ -683614,6 +684355,7 @@ function initBundledSkills() {
683614
684355
  registerSimplifySkill();
683615
684356
  registerBatchSkill();
683616
684357
  registerStuckSkill();
684358
+ registerRayuSkills();
683617
684359
  if (false) {}
683618
684360
  if (false) {}
683619
684361
  if (false) {}
@@ -683627,6 +684369,7 @@ var init_bundled = __esm(() => {
683627
684369
  init_keybindings3();
683628
684370
  init_loremIpsum();
683629
684371
  init_remember();
684372
+ init_rayuSkills();
683630
684373
  init_simplify();
683631
684374
  init_skillify();
683632
684375
  init_stuck();
@@ -684211,7 +684954,7 @@ var init_createDirectConnectSession = __esm(() => {
684211
684954
  });
684212
684955
 
684213
684956
  // src/utils/errorLogSink.ts
684214
- import { dirname as dirname70, join as join167 } from "path";
684957
+ import { dirname as dirname71, join as join167 } from "path";
684215
684958
  function getErrorsPath() {
684216
684959
  return join167(CACHE_PATHS.errors(), DATE + ".jsonl");
684217
684960
  }
@@ -684232,7 +684975,7 @@ function createJsonlWriter(options) {
684232
684975
  function getLogWriter(path30) {
684233
684976
  let writer = logWriters.get(path30);
684234
684977
  if (!writer) {
684235
- const dir = dirname70(path30);
684978
+ const dir = dirname71(path30);
684236
684979
  writer = createJsonlWriter({
684237
684980
  writeFn: (content) => {
684238
684981
  try {
@@ -684260,7 +685003,7 @@ function appendToLog(path30, message) {
684260
685003
  cwd: getFsImplementation().cwd(),
684261
685004
  userType: "external",
684262
685005
  sessionId: getSessionId(),
684263
- version: "1.3.434"
685006
+ version: "1.3.436"
684264
685007
  };
684265
685008
  getLogWriter(path30).write(messageWithTimestamp);
684266
685009
  }
@@ -684551,7 +685294,7 @@ var init_sessionMemory = __esm(() => {
684551
685294
 
684552
685295
  // src/utils/iTermBackup.ts
684553
685296
  import { copyFile as copyFile12, stat as stat48 } from "fs/promises";
684554
- import { homedir as homedir39 } from "os";
685297
+ import { homedir as homedir40 } from "os";
684555
685298
  import { join as join168 } from "path";
684556
685299
  function markITerm2SetupComplete() {
684557
685300
  saveGlobalConfig((current) => ({
@@ -684567,7 +685310,7 @@ function getIterm2RecoveryInfo() {
684567
685310
  };
684568
685311
  }
684569
685312
  function getITerm2PlistPath() {
684570
- return join168(homedir39(), "Library", "Preferences", "com.googlecode.iterm2.plist");
685313
+ return join168(homedir40(), "Library", "Preferences", "com.googlecode.iterm2.plist");
684571
685314
  }
684572
685315
  async function checkAndRestoreITerm2Backup() {
684573
685316
  const { inProgress, backupPath } = getIterm2RecoveryInfo();
@@ -688368,8 +689111,8 @@ async function getEnvLessBridgeConfig() {
688368
689111
  }
688369
689112
  async function checkEnvLessBridgeMinVersion() {
688370
689113
  const cfg = await getEnvLessBridgeConfig();
688371
- if (cfg.min_version && lt("1.3.434", cfg.min_version)) {
688372
- return `Your version of RAYU (${"1.3.434"}) is too old for Remote Control.
689114
+ if (cfg.min_version && lt("1.3.436", cfg.min_version)) {
689115
+ return `Your version of RAYU (${"1.3.436"}) is too old for Remote Control.
688373
689116
  Version ${cfg.min_version} or higher is required. Run \`claude update\` to update.`;
688374
689117
  }
688375
689118
  return null;
@@ -688697,14 +689440,14 @@ __export(exports_bridgePointer, {
688697
689440
  BRIDGE_POINTER_TTL_MS: () => BRIDGE_POINTER_TTL_MS
688698
689441
  });
688699
689442
  import { mkdir as mkdir46, readFile as readFile56, stat as stat49, unlink as unlink27, writeFile as writeFile50 } from "fs/promises";
688700
- import { dirname as dirname71, join as join171 } from "path";
689443
+ import { dirname as dirname72, join as join171 } from "path";
688701
689444
  function getBridgePointerPath(dir) {
688702
689445
  return join171(getProjectsDir(), sanitizePath2(dir), "bridge-pointer.json");
688703
689446
  }
688704
689447
  async function writeBridgePointer(dir, pointer) {
688705
689448
  const path30 = getBridgePointerPath(dir);
688706
689449
  try {
688707
- await mkdir46(dirname71(path30), { recursive: true });
689450
+ await mkdir46(dirname72(path30), { recursive: true });
688708
689451
  await writeFile50(path30, jsonStringify(pointer), "utf8");
688709
689452
  logForDebugging(`[bridge:pointer] wrote ${path30}`);
688710
689453
  } catch (err2) {
@@ -688843,7 +689586,7 @@ async function initBridgeCore(params) {
688843
689586
  const rawApi = createBridgeApiClient({
688844
689587
  baseUrl,
688845
689588
  getAccessToken,
688846
- runnerVersion: "1.3.434",
689589
+ runnerVersion: "1.3.436",
688847
689590
  onDebug: logForDebugging,
688848
689591
  onAuth401,
688849
689592
  getTrustedDeviceToken
@@ -690681,7 +691424,7 @@ __export(exports_print, {
690681
691424
  canBatchWith: () => canBatchWith
690682
691425
  });
690683
691426
  import { readFile as readFile57, stat as stat50 } from "fs/promises";
690684
- import { dirname as dirname72 } from "path";
691427
+ import { dirname as dirname73 } from "path";
690685
691428
  import { cwd as cwd2 } from "process";
690686
691429
  import { randomUUID as randomUUID58 } from "crypto";
690687
691430
  function trackReceivedMessageUuid(uuid8) {
@@ -693034,7 +693777,7 @@ async function loadInitialMessages(setAppState, options) {
693034
693777
  if (false) {}
693035
693778
  if (!options.forkSession) {
693036
693779
  if (result.sessionId) {
693037
- switchSession(asSessionId(result.sessionId), result.fullPath ? dirname72(result.fullPath) : null);
693780
+ switchSession(asSessionId(result.sessionId), result.fullPath ? dirname73(result.fullPath) : null);
693038
693781
  if (persistSession) {
693039
693782
  await resetSessionFilePointer();
693040
693783
  }
@@ -693132,7 +693875,7 @@ async function loadInitialMessages(setAppState, options) {
693132
693875
  }
693133
693876
  if (false) {}
693134
693877
  if (!options.forkSession && result.sessionId) {
693135
- switchSession(asSessionId(result.sessionId), result.fullPath ? dirname72(result.fullPath) : null);
693878
+ switchSession(asSessionId(result.sessionId), result.fullPath ? dirname73(result.fullPath) : null);
693136
693879
  if (persistSession) {
693137
693880
  await resetSessionFilePointer();
693138
693881
  }
@@ -694205,7 +694948,7 @@ async function startMCPServer(cwd3, debug4, verbose) {
694205
694948
  setCwd(cwd3);
694206
694949
  const server = new Server({
694207
694950
  name: "claude/tengu",
694208
- version: "1.3.434"
694951
+ version: "1.3.436"
694209
694952
  }, {
694210
694953
  capabilities: {
694211
694954
  tools: {}
@@ -694620,7 +695363,7 @@ __export(exports_plugins, {
694620
695363
  VALID_UPDATE_SCOPES: () => VALID_UPDATE_SCOPES,
694621
695364
  VALID_INSTALLABLE_SCOPES: () => VALID_INSTALLABLE_SCOPES
694622
695365
  });
694623
- import { basename as basename63, dirname as dirname73 } from "path";
695366
+ import { basename as basename63, dirname as dirname74 } from "path";
694624
695367
  function handleMarketplaceError(error54, action2) {
694625
695368
  logError2(error54);
694626
695369
  cliError(`${figures_default.cross} Failed to ${action2}: ${errorMessage(error54)}`);
@@ -694653,9 +695396,9 @@ async function pluginValidateHandler(manifestPath, options) {
694653
695396
  printValidationResult(result);
694654
695397
  let contentResults = [];
694655
695398
  if (result.fileType === "plugin") {
694656
- const manifestDir = dirname73(result.filePath);
695399
+ const manifestDir = dirname74(result.filePath);
694657
695400
  if (basename63(manifestDir) === ".claude-plugin") {
694658
- contentResults = await validatePluginContents(dirname73(manifestDir));
695401
+ contentResults = await validatePluginContents(dirname74(manifestDir));
694659
695402
  for (const r2 of contentResults) {
694660
695403
  console.log(`Validating ${r2.fileType}: ${r2.filePath}
694661
695404
  `);
@@ -695186,11 +695929,11 @@ var exports_install = {};
695186
695929
  __export(exports_install, {
695187
695930
  install: () => install
695188
695931
  });
695189
- import { homedir as homedir40 } from "node:os";
695932
+ import { homedir as homedir41 } from "node:os";
695190
695933
  import { join as join172 } from "node:path";
695191
695934
  function getInstallationPath2() {
695192
695935
  const isWindows2 = env4.platform === "win32";
695193
- const homeDir = homedir40();
695936
+ const homeDir = homedir41();
695194
695937
  if (isWindows2) {
695195
695938
  const windowsPath = join172(homeDir, ".local", "bin", "claude.exe");
695196
695939
  return windowsPath.replace(/\//g, "\\");
@@ -696731,7 +697474,7 @@ ${customInstructions}` : customInstructions;
696731
697474
  }
696732
697475
  }
696733
697476
  logForDiagnosticsNoPII("info", "started", {
696734
- version: "1.3.434",
697477
+ version: "1.3.436",
696735
697478
  is_native_binary: isInBundledMode()
696736
697479
  });
696737
697480
  registerCleanup(async () => {
@@ -697450,7 +698193,7 @@ Usage: rayu --remote "your task description"`, () => gracefulShutdown(1));
697450
698193
  pendingHookMessages
697451
698194
  }, renderAndRun);
697452
698195
  }
697453
- }).version("1.3.434 (Rayu-CLI)", "-v, --version", "Output the version number");
698196
+ }).version("1.3.436 (Rayu-CLI)", "-v, --version", "Output the version number");
697454
698197
  program.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
697455
698198
  program.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
697456
698199
  if (canUserConfigureAdvisor()) {
@@ -697916,7 +698659,7 @@ if (false) {}
697916
698659
  async function main2() {
697917
698660
  const args = process.argv.slice(2);
697918
698661
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
697919
- console.log(`${"1.3.434"} (Rayu-CLI)`);
698662
+ console.log(`${"1.3.436"} (Rayu-CLI)`);
697920
698663
  return;
697921
698664
  }
697922
698665
  const {