التخصيص والإدارةالأوامر والإجراءات
التخصيص والإدارة

الأوامر والإجراءات المخصصة

في cmux.json تعلّم cmux روتينك الخاص: أوامر الصدفة التي تشغّلها كثيرًا، ومساحات العمل التي تُفتح بترتيب مُعدّ مسبقًا من الطرفيات والمتصفحات، والإجراءات التي يمكنك ربطها بالاختصارات وأزرار شريط علامات التبويب ولوحة الأوامر. احتفظ بملف في .cmux/cmux.json داخل المشروع، أو في ~/.config/cmux/cmux.json لكل المشاريع، أو في كليهما.

أين يقرأ cmux ملف cmux.json

يمكن أن تأتي الإدخالات من ملف المشروع أو من ملف المستخدم أو من كليهما. بالنسبة لملفات المشروع، يبدأ cmux من المجلد الحالي ويفحص أيضًا كل مجلد أب فوقه.

  • المشروع: ./.cmux/cmux.json (يُعثر عليه بالبحث صعودًا من مجلد العمل؛ وله الأولوية على ملف المستخدم)
  • محلي احتياطي: ./cmux.json (ما زال مدعومًا للمستودعات الحالية)
  • على مستوى المستخدم: ~/.config/cmux/cmux.json (مشترك بين جميع المشاريع؛ يوفّر كل ما يتركه ملف المشروع غير معرّف)
تتجاوز الإجراءات والأوامر المحلية الإدخالات العامة التي تحمل نفس المعرّف أو الاسم.

عدّل cmux.json، ثم اضغط Cmd+Shift+, أو شغّل cmux reload-config لتطبيق التغييرات.

إذا احتوى إعداد المشروع أو الإعداد العام على خطأ في المخطط، يعود cmux إلى الإعداد الصالح التالي ويعرض صف cmux.json Schema Error في Command Palette. حدده لفتح ملف الإعداد.

أوامر الصدفة

أصغر إدخال هو اسم مع سلسلة command. عند اختياره في لوحة الأوامر تُكتب تلك السلسلة في الطرفية التي عليها التركيز وتُنفَّذ.

cmux.json
{
  "commands": [
    {
      "name": "Format Changed Files",
      "description": "Run the formatter on files that differ from main",
      "keywords": [
        "fmt",
        "prettier",
        "style"
      ],
      "command": "git diff --name-only main -- '*.ts' '*.tsx' | xargs npx prettier --write"
    },
    {
      "name": "Reset Local Database",
      "keywords": [
        "db",
        "wipe"
      ],
      "command": "cd \"$(git rev-parse --show-toplevel)\" && ./scripts/db-reset.sh",
      "confirm": true
    }
  ]
}

حقول أمر الصدفة

  • name: تسمية مطلوبة وغير فارغة تختارها من لوحة الأوامر
  • command: نص الصدفة الذي يكتبه cmux في الطرفية النشطة ثم ينفّذه
  • description: نص ثانوي اختياري يظهر بجانب الإدخال
  • keywords: كلمات إضافية ينبغي أن تطابق هذا الإدخال عند البحث في لوحة الأوامر
  • confirm: اضبطه على true لتظهر رسالة تأكيد في كل مرة قبل التشغيل

يُنفَّذ أمر الصدفة في أي مكان توجد فيه الطرفية النشطة حاليًا. عندما يحتاج الأمر إلى نقطة بداية متوقعة، ابدأه بـ cd "$(git rev-parse --show-toplevel)" && للانتقال إلى جذر مستودع Git، أو بـ cd /some/folder && لتثبيته على مجلد محدد.

أوامر تفتح مساحة عمل

إذا أعطيت الأمر كائن workspace بدلًا من سلسلة command، فإنه يفتح بدلًا من ذلك مساحة عمل جديدة مرتّبة كشجرة من الألواح المقسمة تضم طرفيات ومتصفحات. يجب أن يحتوي الإدخال على واحد فقط من الاثنين.

cmux.json
{
  "commands": [
    {
      "name": "API Stack",
      "keywords": [
        "api",
        "server",
        "logs"
      ],
      "restart": "confirm",
      "workspace": {
        "name": "API",
        "cwd": "./services/api",
        "color": "#10b981",
        "env": {
          "PORT": "8080"
        },
        "layout": {
          "direction": "vertical",
          "split": 0.65,
          "children": [
            {
              "direction": "horizontal",
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Server",
                        "command": "go run ./cmd/api",
                        "focus": true
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Worker",
                        "command": "go run ./cmd/worker",
                        "env": {
                          "QUEUE": "default"
                        }
                      }
                    ]
                  }
                }
              ]
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Logs",
                    "cwd": "/var/log",
                    "command": "tail -F system.log"
                  },
                  {
                    "type": "browser",
                    "name": "Health",
                    "url": "http://localhost:8080/healthz"
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}

حقول كائن workspace

  • name: عنوان مساحة العمل؛ ويُستخدم اسم الأمر إذا لم يُحدَّد
  • cwd: المجلد الأساسي لمساحة العمل؛ يُحدَّد cwd لكل علامة تبويب نسبةً إليه
  • layout: العقدة الجذرية لشجرة التخطيط الموضحة أدناه
  • color: لون الشريط الجانبي، بصيغة #RRGGBB الست عشرية أو باسم أحد ألوان مساحات العمل
  • env: Environment variables inherited by every shell in the workspace
  • setup: Bootstrap command sent to the workspace's first terminal before that terminal's own command

عندما تكون مساحة العمل مفتوحة بالفعل

اضبط restart في الأمر لتحدد ما يحدث إذا كانت هناك مساحة عمل بالاسم نفسه موجودة بالفعل:

  • "new": إنشاء مساحة عمل جديدة (الافتراضي)
  • "confirm": اسأل أولًا، ثم استبدلها إذا وافقت
  • "recreate": استبدلها فورًا دون سؤال
  • "ignore": التبديل إلى مساحة العمل الموجودة

وصف التخطيط

التخطيط شجرة. كل عقدة داخلية تقسم مساحتها إلى قسمين، وكل ورقة هي لوح يحتوي على علامات تبويب.

عُقد التقسيم

يقسم التقسيم مساحته إلى جزأين:

  • direction: "horizontal" أو "vertical"
  • children: مصفوفة من عقدتين بالضبط، كل منهما تقسيم آخر أو لوح
  • split: موضع الفاصل ككسر من المساحة. القيمة الافتراضية 0.5، والقيم خارج النطاق من 0.1 إلى 0.9 تُقيَّد

عُقد الألواح

اللوح ورقة في الشجرة. تسرد مصفوفة surfaces الخاصة به علامات التبويب التي يُفتح بها، ويجب أن تحتوي على إدخال واحد على الأقل.

الواجهات

كل إدخال في مصفوفة surfaces الخاصة باللوح يفتح علامة تبويب واحدة، إما طرفية أو متصفحًا:

  • type: "terminal" أو "browser"
  • name: عنوان علامة التبويب الذي يظهر بدلًا من العنوان الافتراضي
  • focus: اضبطه على true لنقل تركيز لوحة المفاتيح إلى علامة التبويب هذه بعد بناء التخطيط
  • command: للطرفيات فقط: نص صدفة يُنفَّذ بمجرد فتح الطرفية
  • url: للمتصفحات فقط: الصفحة المراد تحميلها
  • cwd: مجلد البداية لعلامة التبويب هذه، ويُحدَّد وفق القواعد أدناه
  • env: كائن يحتوي على أسماء وقيم إضافية لمتغيرات البيئة

كيف تُحدَّد قيم cwd

  • ~/path: يُحدَّد داخل مجلد المنزل الخاص بك
  • مسار يبدأ بـ /: يُستخدم كما هو
  • ./subdir: يُلحَق بمجلد مساحة العمل
  • . أو غير محدد: يرث مجلد مساحة العمل

بنية الملف

سجل الإجراءات ميزة في إصدار nightly. ثبّت أحدث إصدار nightly قبل استخدام actions أو shortcut أو ui.surfaceTabBar.buttons.

ما زالت commands تعرّف أوامر shell القابلة لإعادة الاستخدام وتخطيطات مساحات العمل. تضيف إصدارات nightly سجل actions. الإجراءات هي المعرفات العامة المشتركة بين شريط تبويبات السطح وCommand Palette واختصارات مستوى الإجراء.

cmux.json
{
  "actions": {
    "cmux.newTerminal": {
      "type": "agent",
      "agent": "claude",
      "title": "Claude Code",
      "subtitle": "Start Claude Code in a new tab"
    },
    "lint": {
      "type": "command",
      "title": "Lint",
      "subtitle": "Run the linter in a fresh tab",
      "keywords": [
        "eslint",
        "check"
      ],
      "command": "npm run lint",
      "shortcut": [
        "cmd+k",
        "cmd+l"
      ],
      "icon": {
        "type": "symbol",
        "name": "checkmark.seal"
      }
    },
    "scratch-dir": {
      "type": "command",
      "title": "Scratch Directory",
      "command": "cd \"$(mktemp -d)\"",
      "target": "currentTerminal",
      "palette": false,
      "icon": {
        "type": "emoji",
        "value": "📝",
        "scale": 0.85
      }
    },
    "api-stack": {
      "type": "workspaceCommand",
      "title": "API Stack",
      "commandName": "API Stack"
    }
  },
  "ui": {
    "surfaceTabBar": {
      "buttons": [
        "cmux.newTerminal",
        "cmux.splitRight",
        "lint",
        {
          "action": "scratch-dir",
          "tooltip": "cd into a new temp folder"
        }
      ]
    }
  },
  "commands": [
    {
      "name": "API Stack",
      "keywords": [
        "api"
      ],
      "workspace": {
        "cwd": "./services/api",
        "layout": {
          "pane": {
            "surfaces": [
              {
                "type": "terminal",
                "name": "Server",
                "command": "go run ./cmd/api"
              }
            ]
          }
        }
      }
    }
  ]
}

سجل إجراءات nightly

يربط actions معرفات ثابتة بسلوك قابل للتشغيل. استخدم المعرفات المدمجة cmux.newTerminal وcmux.newBrowser وcmux.splitRight وcmux.splitDown لتجاوز القيم الافتراضية. استخدم معرفاتك الخاصة لأدوات المشروع.

تكون palette بقيمة true افتراضيًا. اجعلها false لإخفاء الإجراء من Command Palette مع إبقائه متاحًا لشريط تبويبات السطح أو لاختصار. يستخدم shortcut صيغة اختصارات الإعدادات نفسها، مثل cmd+shift+c أو ["cmd+k", "cmd+c"].

يستبدل ui.surfaceTabBar.buttons قائمة الأزرار الافتراضية عند وجوده. اترك أي معرف مدمج خارج القائمة لإخفائه. تستخدم الأيقونات دائمًا شكل كائن: { "type": "symbol", "name": "play.circle" } أو { "type": "emoji", "value": "🧪", "scale": 0.9 } أو { "type": "image", "path": "./icons/codex.svg" }. مسارات الصور نسبية إلى ملف الإعداد. قيمة scale في emoji اختيارية وتكون 1 افتراضيًا. الصيغ SVG وPDF وPNG وJPEG وGIF وTIFF وBMP وHEIC وHEIF وWebP وAVIF وICO وICNS مدعومة.

يمكن أن يكون كل إدخال زر إما سلسلة معرف إجراء أو كائن زر. استخدم كائن زر عندما تريد الإجراء نفسه مع تسمية سطح أو أيقونة أو تلميح مختلف. يُستخدم عنوان الزر المحلول أيضًا كعنوان لمطالبة الثقة.

ضع أي أعلام موافقة أو أذونات مباشرة في سلسلة الأمر التي تريد تشغيلها فعلًا. هدف الإجراء الافتراضي هو newTabInCurrentPane، لذلك يكون النمط الشائع فتح تبويب طرفية جديد في اللوحة الحالية وبدء Codex أو Claude Code أو OpenCode هناك.

تظهر الإجراءات المحلية للمشروع في شريط تبويبات السطح وCommand Palette فورًا. ما زال التشغيل الأول يطلب الثقة. تُحسب الثقة لكل بصمة إجراء مطابقة تمامًا، وليس لكل مستودع. تبقى أيقونات الصور المحلية للمشروع مقفلة إلى أن تثق بذلك الإجراء.

الإجراءات المخصصة ولوحة الأوامر

إدخال actions هو الشيء القابل لإعادة الاستخدام الذي يشغله cmux. استخدم الإجراءات عندما تريد إتاحة السلوك نفسه من لوحة الأوامر أو شريط تبويبات السطح أو الاختصارات أو قائمة زر الإضافة. أبقِ commands للأوامر الطرفية القابلة لإعادة الاستخدام وتخطيطات مساحات العمل. اضبط palette على false عندما يجب إخفاء الإجراء من لوحة الأوامر.

أنواع الإجراءات

  • "command": يشغّل نصا طرفيا. استخدم target لاختيار الطرفية الحالية أو تبويب جديد في اللوحة الحالية.
  • "agent": يشغّل وكيل برمجة مدعوما. يدعم اليوم codex و claude، مع وسائط اختيارية.
  • "builtin": ينشئ اسما بديلا لإجراء cmux مدمج مثل cmux.newTerminal أو cmux.newBrowser أو cmux.splitRight أو cmux.splitDown. إجراءات النسخ المضمّنة: ينسخ cmux.copyWorkingDirectory دليل العمل الخاص بالطرفية، وينسخ cmux.copyProjectRoot جذر مستودع git الخاص به (أو دليل العمل خارج أي مستودع)، وينسخ cmux.copyScreen الشاشة المرئية. في مساحة عمل SSH أو سحابية أو tmux بعيدة، ينسخ cmux.copyProjectRoot دليل العمل البعيد، لأن cmux لا يستطيع البحث عن مستودع git على المضيف الآخر.
  • "workspaceCommand": يشغّل تعريف مساحة عمل مسمى من commands. استخدمه للتخطيطات متعددة اللوحات، ومجلدات العمل المخصصة، وأوامر البدء.
  • "workspace": Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically.
  • "setting": يغيّر إعدادًا واحدًا في ملف cmux.json العام، مثل تبديل إعداد true/false أو التنقل بين قائمة من القيم. راجع إجراءات الإعدادات أدناه.
  • "settingPreset": يطبّق مجموعة مسماة من الإعدادات من settingPresets دفعة واحدة.

حقول الإجراء

  • title: عنوان صف لوحة الأوامر، وتسمية زر السطح، وعنوان عنصر القائمة، وعنوان طلب الثقة ما لم يستبدله إدخال آخر.
  • subtitle / description: النص الثانوي في لوحة الأوامر. يقبل description كاسم بديل لـ subtitle.
  • keywords: مصطلحات بحث إضافية للوحة الأوامر.
  • palette: القيمة الافتراضية true للإجراءات المخصصة. اضبطها على false لإخفاء الإجراء من لوحة الأوامر مع إبقائه قابلا للاستدعاء من أماكن أخرى.
  • shortcut: اختصار إجراء اختياري، باستخدام صيغة الضغطة الواحدة أو التسلسل نفسها مثل اختصارات الإعدادات.
  • target: لإجراءات command و agent فقط. استخدم currentTerminal أو newTabInCurrentPane.
  • confirm: اطلب التأكيد قبل تشغيل الإجراء.
  • newWorkspaceMenu: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.

سلوك لوحة الأوامر

تقرأ لوحة الأوامر سجل الإجراءات المحلول. تضاف معرّفات الإجراءات المخصصة كصفوف عندما لا تكون palette false. تضاف commands القديمة تلقائيا كصفوف مخصصة ما لم يكن إجراء بنفس المعرّف المولد موجودا بالفعل. تحتفظ الأوامر المدمجة بتسمياتها المعتادة في اللوحة، لكن تجاوز معرّف مدمج مثل cmux.newTerminal يغيّر السلوك خلف نقطة الدخول المشتركة.

إجراءات الإعدادات

يحدد إجراء الإعداد path للإعداد وواحدًا فقط من: set (يكتب قيمة)، أو toggle: true (يقلب إعداد true/false)، أو cycle (ينتقل إلى القيمة التالية في قائمة ويعود إلى أولها بعد آخرها)، أو unset: true (يحذف المفتاح من cmux.json لتُطبَّق القيمة من نافذة الإعدادات أو القيمة الافتراضية). يبدأ toggle و cycle من القيمة التي يستخدمها cmux حاليًا، بما في ذلك قيمة ضبطتها في نافذة الإعدادات. يطبّق إجراء settingPreset إدخالًا من settingPresets، وهو ملف cmux.json جزئي تُدمج كائناته المتداخلة مفتاحًا بمفتاح. يتحقق cmux من كل تغيير وفق المخطط قبل الحفظ، ويحافظ على تعليقاتك والمفاتيح الأخرى، ويطبّق التغيير فورًا. لا تعمل إجراءات الإعدادات والإعدادات المسبقة إلا من ملف cmux.json العام والحزم التي يشير إليها؛ ولا يمكن لإعدادات المشروع تعريفها.

~/.config/cmux/cmux.json
{
  "actions": {
    "scroll.cycle": {
      "type": "setting",
      "title": "Cycle Scroll Speed",
      "path": "terminal.scrollSpeed",
      "cycle": [1.0, 1.4, 1.8]
    },
    "editor.wrap": {
      "type": "setting",
      "title": "Toggle Editor Word Wrap",
      "path": "fileEditor.wordWrap",
      "toggle": true
    },
    "sidebar.quiet": {
      "type": "settingPreset",
      "title": "Quiet Sidebar",
      "preset": "sidebar.quiet"
    }
  },
  "settingPresets": {
    "sidebar.quiet": {
      "sidebar": { "showPorts": false, "showPullRequests": false, "showLog": false }
    }
  }
}

تعمل التغييرات نفسها من الطرفية: cmux config set terminal.scrollSpeed 1.4، وcmux config toggle fileEditor.wordWrap، وcmux config preset sidebar.quiet.

مع confirm: true، يسأل cmux قبل الحفظ ويعرض أمر cmux config المكافئ. تُقسَّم المسارات عند كل "."، لذا لا يمكن بهذه الطريقة تغيير مفتاح يحتوي هو نفسه على "." (مثل إدخال workspaceGroups.byCwd لـ ~/src/app.web). عدّله مباشرة في cmux.json.

إجراءات مخصصة لزر الإضافة

استخدم ui.newWorkspace.action لتجاوز ما يفعله زر الإضافة. استخدم ui.newWorkspace.contextMenu (أو الاسم البديل rightClick) لتعريف قائمة النقر بزر الفأرة الأيمن المرتبة. يمكن أن تكون عناصر القائمة معرفات إجراءات أو كائنات إجراءات أو { "type": "separator" }. عند عدم ضبطه، تعرض القائمة cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L) مع اختصار كل منها الحالي. تظهر العناصر السحابية فقط عند تفعيل Cloud Machines. تستخدم New Cloud Workspace الجهاز المرتبط بآخر مساحة عمل Cloud محددة، ثم أول جهاز في الشريط الجانبي الأيمن؛ وإذا لم يتوفر جهاز صالح، يفتح New Cloud Machine.

cmux.json
{
  "actions": {
    "worktree-agents": {
      "type": "workspaceCommand",
      "title": "Agents in New Worktree",
      "commandName": "Agents in New Worktree",
      "icon": {
        "type": "symbol",
        "name": "arrow.triangle.branch"
      }
    }
  },
  "ui": {
    "newWorkspace": {
      "action": "worktree-agents",
      "contextMenu": [
        "worktree-agents",
        {
          "type": "separator"
        },
        {
          "action": "cmux.newWorkspace",
          "title": "Blank Workspace"
        },
        {
          "action": "cmux.newBrowser",
          "title": "Browser"
        }
      ]
    }
  },
  "commands": [
    {
      "name": "Agents in New Worktree",
      "description": "Branch off a new Git worktree, then run Codex and Claude Code in it side by side",
      "workspace": {
        "name": "Worktree",
        "layout": {
          "direction": "vertical",
          "split": 0.7,
          "children": [
            {
              "direction": "horizontal",
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Codex",
                        "command": "marker=\"${TMPDIR:-/tmp}/cmux-wt-${CMUX_WORKSPACE_ID:-local}\"; echo \"Waiting for the worktree...\"; until [ -s \"$marker\" ]; do sleep 0.25; done; cd \"$(cat \"$marker\")\" && exec codex --yolo"
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Claude",
                        "command": "marker=\"${TMPDIR:-/tmp}/cmux-wt-${CMUX_WORKSPACE_ID:-local}\"; echo \"Waiting for the worktree...\"; until [ -s \"$marker\" ]; do sleep 0.25; done; cd \"$(cat \"$marker\")\" && exec claude --dangerously-skip-permissions"
                      }
                    ]
                  }
                }
              ]
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Setup",
                    "command": "marker=\"${TMPDIR:-/tmp}/cmux-wt-${CMUX_WORKSPACE_ID:-local}\"; rm -f \"$marker\"; root=$(git rev-parse --show-toplevel) || exit 1; branch=\"wt-$(date +%m%d-%H%M%S)\"; wt=\"$root/../$(basename \"$root\")-$branch\"; git -C \"$root\" worktree add -b \"$branch\" \"$wt\" && printf \"%s\\n\" \"$wt\" > \"$marker\" && cd \"$wt\" && exec \"${SHELL:-/bin/zsh}\" -l",
                    "focus": true
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}

يجعل هذا المثال النقر العادي على زر الإضافة يشغّل الإجراء worktree-agents. يستخدم أمر مساحة العمل من commands طرفية إعداد مرئية لإنشاء worktree في Git أولا. يبدأ Codex و Claude في الوقت نفسه، وينتظران ملف الحالة الخاص بمساحة العمل، ثم ينتقلان إلى المجلد المنشأ قبل exec.

Workspace layouts

A workspace layout is stored as a workspace action, embedding a full workspace definition directly in the action so it needs no separate commands entry. It supports the same workspace fields plus setup, a bootstrap command sent to the first terminal before that terminal's own command:

cmux.json
{
  "actions": {
    "pair-review": {
      "type": "workspace",
      "title": "Pair Review",
      "icon": {
        "type": "symbol",
        "name": "person.2.wave.2"
      },
      "restart": "ignore",
      "newWorkspaceMenu": true,
      "workspace": {
        "name": "Review",
        "cwd": "~/src/app",
        "setup": "git pull --ff-only",
        "layout": {
          "direction": "horizontal",
          "split": 0.55,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Diff",
                    "command": "git log -p -n 5",
                    "focus": true
                  }
                ]
              }
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Codex",
                    "command": "codex"
                  },
                  {
                    "type": "terminal",
                    "name": "Shell"
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

Workspace layouts appear in the plus-button right-click menu automatically. Set newWorkspaceMenu to false to hide one, or to true on any other action to add it to the menu.

You can also create these without writing JSON: right-click the plus button and choose Save Workspace as Layout to capture the current workspace's splits, directories, running agents, and browser tabs into ~/.config/cmux/cmux.json. They are stored as entries in the actions block. Customize Workspace Layouts opens that file in your editor.

Default for new workspaces

Use the Default for New Workspace submenu to pick which saved workspace layout plain New Workspace should run, or choose None to return to a blank terminal. The save dialog also has a Use as default for new workspaces checkbox. The setting is ui.newWorkspace.action; a project-local .cmux/cmux.json value wins over ~/.config/cmux/cmux.json.

مثال كامل

cmux.json
{
  "actions": {
    "cmux.newTerminal": {
      "type": "command",
      "title": "Codex",
      "command": "codex --yolo",
      "shortcut": "cmd+t",
      "icon": {
        "type": "image",
        "path": "./icons/codex.svg"
      }
    },
    "review": {
      "type": "agent",
      "agent": "claude",
      "args": "--permission-mode plan",
      "title": "Plan with Claude",
      "shortcut": "cmd+shift+p",
      "icon": {
        "type": "symbol",
        "name": "list.bullet.clipboard"
      }
    },
    "storybook": {
      "type": "workspaceCommand",
      "commandName": "Storybook",
      "newWorkspaceMenu": true
    },
    "typecheck": {
      "type": "command",
      "title": "Typecheck",
      "command": "npx tsc --noEmit",
      "target": "newTabInCurrentPane",
      "confirm": false,
      "icon": {
        "type": "emoji",
        "value": "🔎"
      }
    }
  },
  "ui": {
    "surfaceTabBar": {
      "buttons": [
        "cmux.newTerminal",
        "review",
        {
          "action": "typecheck",
          "title": "tsc"
        },
        "cmux.newBrowser",
        "cmux.splitDown"
      ]
    },
    "newWorkspace": {
      "contextMenu": [
        "storybook",
        {
          "type": "separator"
        },
        "cmux.newTerminal",
        "cmux.newBrowser"
      ]
    }
  },
  "commands": [
    {
      "name": "Storybook",
      "description": "Component explorer with a live preview beside it",
      "keywords": [
        "ui",
        "components",
        "stories"
      ],
      "workspace": {
        "name": "Storybook",
        "cwd": "./packages/ui",
        "color": "#a855f7",
        "layout": {
          "direction": "horizontal",
          "split": 0.4,
          "children": [
            {
              "direction": "vertical",
              "split": 0.5,
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Storybook",
                        "command": "npx storybook dev -p 6006 --no-open",
                        "focus": true
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Tests",
                        "command": "npx vitest --watch",
                        "env": {
                          "CI": "false"
                        }
                      }
                    ]
                  }
                }
              ]
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "browser",
                    "name": "Preview",
                    "url": "http://localhost:6006"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    {
      "name": "Install Dependencies",
      "keywords": [
        "install",
        "deps"
      ],
      "command": "npm ci",
      "confirm": true
    },
    {
      "name": "Open Changelog",
      "keywords": [
        "changes",
        "release"
      ],
      "command": "${EDITOR:-vi} CHANGELOG.md"
    }
  ]
}