{"id":20166,"date":"2026-09-29T09:17:46","date_gmt":"2026-09-29T13:17:46","guid":{"rendered":"https:\/\/wp.glbgpt.com\/?p=20166"},"modified":"2026-09-29T09:17:47","modified_gmt":"2026-09-29T13:17:47","slug":"claude-code-model-selection","status":"publish","type":"post","link":"https:\/\/wp.glbgpt.com\/id\/hub\/claude-code-model-selection","title":{"rendered":"Pemilihan Model Kode Claude: Pengaturan Default, Pergantian, dan Biaya"},"content":{"rendered":"<p class=\"wp-block-paragraph\"><strong>For Claude Code model selection, use Haiku for small, testable changes, Sonnet for routine implementation, and Opus for work with greater ambiguity or reasoning demands.<\/strong> Anthropic currently recommends Opus 5.5 as a broad starting point; your task, review burden, and budget determine whether a smaller model is a better fit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To change models, open <code>\/model<\/code>. Press <kbd>Masuk<\/kbd> to save a default, or <kbd>s<\/kbd> to switch only the current session. For a single launch, use <code>claude --model opus<\/code>. Those choices have different persistence, so deciding how long the switch should last matters as much as choosing the model.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Coding work also involves research, explanations, documentation, and creative assets. GlobalGPT brings leading AI models and multiple AI tools into one affordable dashboard, while its CLI connects those tools to terminal and development workflows. <a href=\"https:\/\/www.glbgpt.com\/home?inviter=hub_content_home&amp;login=1\">Build your workflow with GlobalGPT<\/a> to keep those related tasks together as you move from an idea to working code.<\/p>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<figure class=\"wp-block-image size-large\"><img alt=\"\" fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"636\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-opus-5-5-1024x636.png\" class=\"wp-image-19921\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-opus-5-5-1024x636.png 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-opus-5-5-300x186.png 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-opus-5-5-767x477.png 767w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-opus-5-5-1536x955.png 1536w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-opus-5-5-18x11.png 18w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/claude-opus-5-5.jpg 1897w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-3e41869c wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button is-style-fill\"><a class=\"wp-block-button__link has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background has-background wp-element-button\" href=\"https:\/\/www.glbgpt.com\/home\/claude-opus-5-5?inviter=hub_claude55&amp;login=1\"><strong>Coba Cluade Opus 5.5 Sekarang di GlobalGPT<\/strong><\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<nav class=\"ccms-toc\" aria-label=\"Di halaman ini\" style=\"background:#f0f4fb;border:1px solid #d7dfed;border-radius:8px;padding:18px 24px;margin:30px 0;color:#172438;font:16px\/1.65 system-ui,sans-serif\"><p><strong>Di halaman ini<\/strong><\/p><ul style=\"margin:0;padding-left:22px\"><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#choose-a-model\">Which model should you use in Claude Code?<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#switch-models\">How to switch models for one session<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#default-model\">How to set a default model<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#opusplan\">What opusplan actually does<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#coding-tests\">What two coding tasks showed<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#model-cost\">What model choice changes about cost<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#troubleshooting\">Why your selected model may not stick<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#globalgpt-workflow\">Build a broader workflow with GlobalGPT<\/a><\/li><li style=\"margin:8px 0\"><a style=\"color:#254fc2;text-decoration:underline\" href=\"#faq\">PERTANYAAN YANG SERING DIAJUKAN<\/a><\/li><\/ul><\/nav>\n\n\n\n<h2 id=\"choose-a-model\" class=\"wp-block-heading\">Which model should you use in Claude Code?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Start with the shape of the work. A short function with clear expected outputs needs a different evaluation from an intermittent bug spread across several services. The useful question is whether the model can produce an acceptable change with reasonable review and iteration.<\/p>\n\n\n\n<figure class=\"wp-block-table\" style=\"overflow-x:auto;margin:24px 0;border:1px solid #d7dfed;border-radius:8px;box-sizing:border-box;max-width:100%\"><table style=\"width:100%;min-width:640px;border-collapse:collapse;font:15px\/1.6 system-ui,sans-serif\"><thead><tr><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">Model saat ini<\/th><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">What it is positioned for<\/th><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">A practical starting task<\/th><\/tr><\/thead><tbody><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Claude Haiku 4.5<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Fast, efficient work with a narrow contract<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">A small refactor, repetitive transformation, or straightforward test case<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Claude Soneta 5<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">A balance of intelligence and speed for daily coding<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">A feature with established patterns, a routine bug fix, or code explanation<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Claude Opus 5,5<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Complex reasoning and longer agentic coding work<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">An ambiguous failure, architecture tradeoff, or change with interacting constraints<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Claude Fable 5.1<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The hardest and longest-running investigations<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">An escalation when difficult work still defeats a stronger Opus effort level<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\" style=\"font-size:14px;line-height:1.6;color:#52617a;padding:12px\">Current model families and task fit, based on Anthropic documentation; task suggestions are practical starting points.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Haiku is worth evaluating when mistakes are easy to detect and the change is small. Sonnet is a sensible candidate when everyday implementation needs more context and judgment. Opus earns consideration when understanding the problem is a substantial part of the task. Fable deserves a separate decision for demanding work; it was outside our three-model coding test.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These are starting points, not automatic quality guarantees. A cheaper response can become expensive if it needs several revisions or extensive review. Conversely, a larger model can add little to a simple transformation that already passes your checks. For broader use beyond Claude Code, <a href=\"https:\/\/www.glbgpt.com\/hub\/claude-haiku-vs-sonnet-vs-opus\/\">compare the Claude model families<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1440\" height=\"900\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/anthropic-model-lineup-20260928_ac366ec699fe4dc393b80b2cf128cf46.webp\" alt=\"Anthropic's current model comparison for Fable 5.1, Opus 5.5, Sonnet 5, and Haiku 4.5.\" class=\"wp-image-20171\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/anthropic-model-lineup-20260928_ac366ec699fe4dc393b80b2cf128cf46.webp 1440w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/anthropic-model-lineup-20260928_ac366ec699fe4dc393b80b2cf128cf46-300x188.webp 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/anthropic-model-lineup-20260928_ac366ec699fe4dc393b80b2cf128cf46-1024x640.webp 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/anthropic-model-lineup-20260928_ac366ec699fe4dc393b80b2cf128cf46-768x480.webp 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/anthropic-model-lineup-20260928_ac366ec699fe4dc393b80b2cf128cf46-18x12.webp 18w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><figcaption class=\"wp-element-caption\">Anthropic&#8217;s model lineup, checked September 28, 2026. Availability in Claude Code depends on your provider and account.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The <a href=\"https:\/\/platform.claude.com\/docs\/en\/about-claude\/models\/overview\">gambaran umum model resmi<\/a> lists 1M-token context windows for Fable 5.1, Opus 5.5, and Sonnet 5, and 200K for Haiku 4.5. These are API specifications. Your Claude Code provider, account, and configuration determine the context options available in a session. A large window is useful for necessary context; filling it with unrelated material still creates work for the model.<\/p>\n\n\n\n<h2 id=\"switch-models\" class=\"wp-block-heading\">How to switch models for one session<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Inside an interactive session, run <code>\/model<\/code> to open the model picker. Select the model row and press <kbd>s<\/kbd> if this is a one-off change. Pressing <kbd>Masuk<\/kbd> saves the selection as your user default. Typing <code>\/model sonnet<\/code> directly also saves it in current versions.<\/p>\n\n\n\n<style>\n.ccms-commands{border:1px solid #d8dfeb;border-radius:8px;padding:22px;background:#fff;color:#172438;font:16px\/1.6 system-ui,sans-serif;margin:28px 0}.ccms-commands h3{color:#172438;font-size:1.3rem;line-height:1.3;margin:0 0 10px}.ccms-commands p{color:#34435d;margin:12px 0}.ccms-commands a{color:#254fc2;text-decoration:underline}.ccms-commands code,.ccms-commands kbd{font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px}.ccms-commands__scroll{overflow-x:auto}.ccms-commands table{border-collapse:collapse;width:100%;min-width:620px;text-align:left}.ccms-commands th,.ccms-commands td{padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top}.ccms-commands th{background:#edf1fa;font-weight:600}.ccms-commands caption{text-align:left;font-size:14px;color:#43536f;margin-bottom:10px}@media(max-width:520px){.ccms-commands{padding:16px}}\n<\/style>\n<section class=\"ccms-commands\" aria-labelledby=\"ccms-command-title\" style=\"border:1px solid #d8dfeb;border-radius:8px;padding:22px;background:#fff;color:#172438;font:16px\/1.6 system-ui,sans-serif;margin:28px 0;box-sizing:border-box;max-width:100%\">\n  <h3 id=\"ccms-command-title\" style=\"color:#172438;font-size:1.3rem;line-height:1.3;margin:0 0 10px\">Choose the command by how long the change should last<\/h3>\n  <div class=\"ccms-commands__scroll\" style=\"overflow-x:auto;box-sizing:border-box;max-width:100%\"><table style=\"border-collapse:collapse;width:100%;min-width:620px;text-align:left\"><caption style=\"text-align:left;font-size:14px;color:#43536f;margin-bottom:10px\">Documented Claude Code behavior, checked September 28, 2026<\/caption><thead><tr><th scope=\"col\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Tujuan Anda<\/th><th scope=\"col\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Apa yang harus dilakukan<\/th><th scope=\"col\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Saved default changes?<\/th><\/tr><\/thead><tbody>\n    <tr><th scope=\"row\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Switch only this interactive session<\/th><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Buka <code style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">\/model<\/code>, select a model, press <kbd style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">s<\/kbd>.<\/td><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Tidak.<\/td><\/tr>\n    <tr><th scope=\"row\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Save a preferred model<\/th><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Buka <code style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">\/model<\/code> dan tekan <kbd style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">Masuk<\/kbd>, or type <code style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">\/model sonnet<\/code>.<\/td><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Yes, when user settings are writable.<\/td><\/tr>\n    <tr><th scope=\"row\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Start a single session on Opus<\/th><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Peluncuran <code style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">claude --model opus<\/code>.<\/td><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Tidak.<\/td><\/tr>\n    <tr><th scope=\"row\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Return to the account&#8217;s runtime default<\/th><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Gunakan <code style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">\/model default<\/code>.<\/td><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Clears the model override; the resolved default can depend on account and organization settings.<\/td><\/tr>\n    <tr><th scope=\"row\" style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top;background:#edf1fa;font-weight:600\">Check the active model<\/th><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Jalankan <code style=\"font:14px\/1.5 ui-monospace,SFMono-Regular,monospace;color:#172438;background:#edf1fa;padding:2px 5px;border-radius:3px\">\/status<\/code>.<\/td><td style=\"padding:12px 10px;border-bottom:1px solid #d8dfeb;color:#172438;vertical-align:top\">Tidak.<\/td><\/tr>\n  <\/tbody><\/table><\/div>\n  <p style=\"color:#34435d;margin:12px 0\">Project or managed settings, environment overrides, and resumed sessions can affect the next launch. Check the active model when reproducibility matters.<\/p>\n  <p style=\"color:#34435d;margin:12px 0\"><a href=\"https:\/\/code.claude.com\/docs\/en\/model-config#setting-your-model\" style=\"color:#254fc2;text-decoration:underline\">Source: Claude Code model configuration<\/a>.<\/p>\n<\/section>\n\n\n\n<p class=\"wp-block-paragraph\">For a fresh terminal session, choose the model at startup. These commands also apply when Claude Code runs in VS Code\u2019s integrated terminal. The examples select a release explicitly:<\/p>\n\n\n\n<div style=\"margin:22px 0;padding:18px;background:#edf1f7;color:#172438;border:1px solid #d7dfed;border-radius:8px;overflow-x:auto\"><pre style=\"margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font:14px\/1.6 ui-monospace,monospace\"><code>claude --model claude-opus-5-5\nclaude --model claude-sonnet-5<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Run the command for the session you want; the examples are alternatives. You can launch different terminals with different <code>--model<\/code> values without repeatedly changing a shared saved default. Use <code>\/status<\/code> to check the active model.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Family names such as <code>opus<\/code> dan <code>sonnet<\/code> can move to newer versions. Their resolution also depends on the provider: the Anthropic API currently maps them to Opus 5.5 and Sonnet 5, while cloud-provider mappings can differ. Use a full model ID when you need a reproducible run, and check the provider-specific name if your environment requires one.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Opus 5.5 requires Claude Code v2.1.280 or later; Sonnet 5 requires v2.1.197 or later. The <a href=\"https:\/\/code.claude.com\/docs\/en\/model-config\">model configuration documentation<\/a> is the reference for current aliases, version requirements, and provider mappings. The commands here are documentation examples; our hands-on section evaluates generated code separately.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1440\" height=\"900\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-model-switching-20260928_bdea45c6a3c84511afb34df961d9542d.webp\" alt=\"Claude Code documentation explaining model selection and the Enter and s keys.\" class=\"wp-image-20172\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-model-switching-20260928_bdea45c6a3c84511afb34df961d9542d.webp 1440w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-model-switching-20260928_bdea45c6a3c84511afb34df961d9542d-300x188.webp 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-model-switching-20260928_bdea45c6a3c84511afb34df961d9542d-1024x640.webp 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-model-switching-20260928_bdea45c6a3c84511afb34df961d9542d-768x480.webp 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-model-switching-20260928_bdea45c6a3c84511afb34df961d9542d-18x12.webp 18w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><figcaption class=\"wp-element-caption\">Enter saves the model as your default; s changes only the current session.<\/figcaption><\/figure>\n\n\n\n<h2 id=\"default-model\" class=\"wp-block-heading\">How to set a default model<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For a personal default, select a model in <code>\/model<\/code> dan tekan <kbd>Masuk<\/kbd>, or type a selection such as <code>\/model sonnet<\/code>. Claude Code writes the <code>model<\/code> field in your user settings when that file is writable. Open a new session and check its active model to confirm the result.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A saved preference does not override every other setting. A startup flag, <code>ANTHROPIC_MODEL<\/code> in the shell, project or managed settings, or an organization default configured to override user choices can select something else at launch. A resumed session may also retain the model from its saved transcript. Check the startup information and <code>\/status<\/code> before assuming the choice was lost.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>\/model default<\/code> clears your model override and returns to the runtime default for your account and configuration. The word <code>default<\/code> is a reset value, not the name of one fixed Claude model. It should not be used as a reproducible model identifier.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For advanced configuration, <code>ANTHROPIC_DEFAULT_MODEL<\/code> supplies a fallback starting choice from v2.1.236 onward. It sits below explicit launch, environment, settings, and organization selections, and ignores values including <code>haiku<\/code> dan <code>opusplan<\/code>. For a normal personal preference, the picker is easier to verify. See <a href=\"https:\/\/code.claude.com\/docs\/en\/settings\">Claude Code settings<\/a> when a shared configuration is involved.<\/p>\n\n\n\n<h2 id=\"opusplan\" class=\"wp-block-heading\">What opusplan actually does<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>opusplan<\/code> uses Opus during plan mode and Sonnet for execution. The appeal is straightforward: use a stronger reasoning model to work through the approach, then a daily coding model to carry out that plan.<\/p>\n\n\n\n<style>\n.ccms-opusplan{border:1px solid #d7dfed;border-radius:8px;background:#f8faff;color:#172438;padding:22px;margin:26px 0;font:16px\/1.6 system-ui,sans-serif}.ccms-opusplan h3{color:#172438;font-size:1.25rem;margin:0 0 16px}.ccms-opusplan p{color:#34445e;margin:12px 0}.ccms-opusplan__flow{display:flex;gap:16px;align-items:center}.ccms-opusplan__step{background:#e9edfc;border-radius:6px;padding:18px;flex:1}.ccms-opusplan__step strong{display:block;color:#172438;font-size:1.2rem}.ccms-opusplan__arrow{font-size:24px;color:#4b55ba}.ccms-opusplan a{color:#254fc2;text-decoration:underline}@media(max-width:520px){.ccms-opusplan{padding:16px}.ccms-opusplan__flow{flex-direction:column;align-items:stretch}.ccms-opusplan__arrow{text-align:center;transform:rotate(90deg)}}\n<\/style>\n<section class=\"ccms-opusplan\" aria-labelledby=\"ccms-opusplan-title\" style=\"border:1px solid #d7dfed;border-radius:8px;background:#f8faff;color:#172438;padding:22px;margin:26px 0;font:16px\/1.6 system-ui,sans-serif;box-sizing:border-box;max-width:100%\">\n<h3 id=\"ccms-opusplan-title\" style=\"color:#172438;font-size:1.25rem;margin:0 0 16px\">Opusplan follows the working mode<\/h3>\n<div class=\"ccms-opusplan__flow\" style=\"display:flex;gap:16px;align-items:center;box-sizing:border-box;max-width:100%;flex-wrap:wrap\"><div class=\"ccms-opusplan__step\" style=\"background:#e9edfc;border-radius:6px;padding:18px;flex:1;box-sizing:border-box;max-width:100%\">Plan mode<strong style=\"display:block;color:#172438;font-size:1.2rem\">Opus<\/strong>Work through the approach.<\/div><span class=\"ccms-opusplan__arrow\" aria-hidden=\"true\" style=\"font-size:24px;color:#4b55ba\">\u2192<\/span><div class=\"ccms-opusplan__step\" style=\"background:#e9edfc;border-radius:6px;padding:18px;flex:1;box-sizing:border-box;max-width:100%\">Execution<strong style=\"display:block;color:#172438;font-size:1.2rem\">Soneta<\/strong>Carry out the plan.<\/div><\/div>\n<p style=\"color:#34445e;margin:12px 0\">Documented routing behavior. The versions behind these family names depend on your provider and configuration.<\/p>\n<p style=\"color:#34445e;margin:12px 0\"><a href=\"https:\/\/code.claude.com\/docs\/en\/model-config#opusplan-model-setting\" style=\"color:#254fc2;text-decoration:underline\">Source: Claude Code model configuration<\/a><\/p>\n<\/section>\n\n\n\n<p class=\"wp-block-paragraph\">This is a mode-dependent rule. It does not inspect every prompt and automatically choose the cheapest suitable family. Provider mappings and access restrictions still apply to the underlying models. Nor does the name guarantee savings: total cost depends on how much planning, implementation, revision, and context processing the task requires.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consider it for a change where the design benefits from deeper analysis and the implementation follows a clear plan. For a small fix, that extra planning may be unnecessary.<\/p>\n\n\n\n<h2 id=\"coding-tests\" class=\"wp-block-heading\">What two coding tasks showed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To add a concrete view of model selection, we tested a narrow Unicode refactor and a route-selector repair with interacting requirements. The distinction between a correct function and a complete requested delivery turned out to matter more than a simple score.<\/p>\n\n\n\n<style>\n.ccms-test-setup{border:1px solid #d7dfed;border-radius:8px;padding:24px;background:#f8faff;color:#172438;margin:28px 0;font:16px\/1.6 system-ui,sans-serif;box-sizing:border-box}.ccms-test-setup *{box-sizing:border-box}.ccms-test-setup h3,.ccms-test-setup h4{color:#172438;line-height:1.35;margin:0 0 12px}.ccms-test-setup h3{font-size:1.35rem}.ccms-test-setup h4{font-size:1.1rem}.ccms-test-setup p{color:#35435a;margin:12px 0}.ccms-test-setup a{color:#254fc2;text-decoration:underline}.ccms-test-setup .ccms-scroll{overflow-x:auto}.ccms-test-setup table{width:100%;min-width:650px;border-collapse:collapse;text-align:left;font-size:14px}.ccms-test-setup th,.ccms-test-setup td{padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top}.ccms-test-setup th{background:#eaf0fa}.ccms-test-setup details{border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff}.ccms-test-setup summary{cursor:pointer;font-weight:650;color:#254fc2}.ccms-test-setup pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace}.ccms-test-setup code{color:inherit}.ccms-test-setup .ccms-verdict{border-left:4px solid #5b62c8;padding:8px 14px;background:#eef0ff}.ccms-test-setup .ccms-note{font-size:14px}@media(max-width:520px){.ccms-test-setup{padding:16px}.ccms-test-setup pre{padding:10px}}\n<\/style>\n<section class=\"ccms-test-setup\" aria-labelledby=\"ccms-test-setup-title\" style=\"border:1px solid #d7dfed;border-radius:8px;padding:24px;background:#f8faff;color:#172438;margin:28px 0;font:16px\/1.6 system-ui,sans-serif;box-sizing:border-box;max-width:100%\">\n<h3 id=\"ccms-test-setup-title\" style=\"box-sizing:border-box;color:#172438;line-height:1.35;margin:0 0 12px;font-size:1.35rem\">How we tested the coding outputs<\/h3>\n<p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">On September 28, 2026, we gave Claude Haiku 4.5, Claude Sonnet 5, and Claude Opus 5.5 the same two JavaScript tasks through GlobalGPT. Each model returned source code; we inspected the code and ran fixed local checks. Claude Code&#8217;s model-switching instructions elsewhere in this guide come from its official documentation.<\/p>\n<p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">Each request had a 4,096-token output limit, no tools or conversation history, and default model settings. We kept the first evaluable response, including incomplete responses. One service error on Sonnet&#8217;s routing task received one permitted retry: seven requests produced six outputs.<\/p>\n<p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">These two small tasks measure returned code and delivery completeness. They do not measure Claude Code&#8217;s agent execution, repository exploration, or an entire development session. Actual dollar charges were not reported. A single observation per task does not establish a general speed or reliability ranking.<\/p>\n<details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View exact model IDs and evaluation conditions<\/summary><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">Requested IDs: <code style=\"box-sizing:border-box;color:inherit\">claude-haiku-4-5-20251001<\/code>, <code style=\"box-sizing:border-box;color:inherit\">claude-sonnet-5<\/code>, dan <code style=\"box-sizing:border-box;color:inherit\">claude-opus-5-5<\/code>. Local checks ran with Node.js v24.19.0. The prompts target Node.js 18+; Node.js 18 itself was not tested.<\/p><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">Eight behavior groups were fixed for the slug task and twelve for the route selector. Format compliance and complete delivery are reported separately. A later code-review check is labeled separately and does not change those counts. We did not edit the returned source to make it pass.<\/p><\/details>\n<\/section>\n\n\n\n<style>\n.ccms-test-t01{border:1px solid #d7dfed;border-radius:8px;padding:24px;background:#f8faff;color:#172438;margin:28px 0;font:16px\/1.6 system-ui,sans-serif;box-sizing:border-box}.ccms-test-t01 *{box-sizing:border-box}.ccms-test-t01 h3,.ccms-test-t01 h4{color:#172438;line-height:1.35;margin:0 0 12px}.ccms-test-t01 h3{font-size:1.35rem}.ccms-test-t01 h4{font-size:1.1rem}.ccms-test-t01 p{color:#35435a;margin:12px 0}.ccms-test-t01 a{color:#254fc2;text-decoration:underline}.ccms-test-t01 .ccms-scroll{overflow-x:auto}.ccms-test-t01 table{width:100%;min-width:650px;border-collapse:collapse;text-align:left;font-size:14px}.ccms-test-t01 th,.ccms-test-t01 td{padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top}.ccms-test-t01 th{background:#eaf0fa}.ccms-test-t01 details{border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff}.ccms-test-t01 summary{cursor:pointer;font-weight:650;color:#254fc2}.ccms-test-t01 pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace}.ccms-test-t01 code{color:inherit}.ccms-test-t01 .ccms-verdict{border-left:4px solid #5b62c8;padding:8px 14px;background:#eef0ff}.ccms-test-t01 .ccms-note{font-size:14px}@media(max-width:520px){.ccms-test-t01{padding:16px}.ccms-test-t01 pre{padding:10px}}\n<\/style><section class=\"ccms-test-t01\" aria-labelledby=\"ccms-test-t01-title\" style=\"border:1px solid #d7dfed;border-radius:8px;padding:24px;background:#f8faff;color:#172438;margin:28px 0;font:16px\/1.6 system-ui,sans-serif;box-sizing:border-box;max-width:100%\"><h3 id=\"ccms-test-t01-title\" style=\"box-sizing:border-box;color:#172438;line-height:1.35;margin:0 0 12px;font-size:1.35rem\">Task 1: Preserve Unicode in a small slug refactor<\/h3><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">The function had to retain non-Latin letters and combining marks, normalize decomposed accents, and preserve its existing ASCII behavior.<\/p><div class=\"ccms-scroll\" style=\"box-sizing:border-box;overflow-x:auto;max-width:100%\"><table style=\"box-sizing:border-box;width:100%;min-width:650px;border-collapse:collapse;text-align:left;font-size:14px\"><caption style=\"box-sizing:border-box\">First returned outputs, with fixed local behavior checks<\/caption><thead style=\"box-sizing:border-box\"><tr style=\"box-sizing:border-box\"><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Model<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Behavior checks<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Response format<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Complete requested delivery<\/th><\/tr><\/thead><tbody style=\"box-sizing:border-box\"><tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Claude Haiku 4.5<\/th><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">8\/8<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Fail: Markdown wrapper<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Yes: complete function<\/td><\/tr><tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Claude Soneta 5<\/th><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">8\/8<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Pass: raw JSON<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Yes: complete function<\/td><\/tr><tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Claude Opus 5,5<\/th><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">8\/8<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Pass: raw JSON<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Yes: complete function<\/td><\/tr><\/tbody><\/table><\/div><div class=\"ccms-verdict\" style=\"box-sizing:border-box;border-left:4px solid #5b62c8;padding:8px 14px;background:#eef0ff;max-width:100%\"><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\"><strong style=\"box-sizing:border-box\">Observed result:<\/strong> all three functions passed the same eight groups. Sonnet and Opus also followed the raw-JSON response requirement. Haiku wrapped its response in Markdown, and its review note incorrectly described NFC as decomposing characters; its code correctly called NFC.<\/p><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">For this narrow refactor, upgrading did not improve the tested function behavior. Format requirements and the accuracy of the accompanying explanation still needed review.<\/p><\/div><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View the complete shared prompt and input code<\/summary><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">SYSTEM\nYou are completing a bounded JavaScript coding task. Return only the requested JSON object with complete source files and brief review notes. Do not claim to have edited files, run commands, or used tools. You have no tool access. Do not include hidden reasoning.\n\nUSER\nImplement the following Node.js 18+ CommonJS function from its current source. Return complete replacement source for src\/slugify.js. Do not add dependencies, imports, I\/O, or other files.\n\nRequired behavior:\n1. slugify(value) returns an empty string for every non-string input.\n2. Normalize string input to Unicode NFC, then lowercase it using JavaScript toLowerCase().\n3. Preserve Unicode letters, numbers, and combining marks. Replace each consecutive run of all other characters with one ASCII hyphen.\n4. Trim leading and trailing hyphens. Preserve the CommonJS export { slugify }.\n5. Existing ASCII behavior must continue to work. Examples: Hello, World! -&gt; hello-world; two   words -&gt; two-words; null -&gt; empty string.\n6. Additional examples: Caf\u00e9 d\u00e9j\u00e0 vu -&gt; caf\u00e9-d\u00e9j\u00e0-vu; decomposed Cafe\\u0301 -&gt; caf\u00e9; \u4e2d\u6587 \u6d4b\u8bd5 42 -&gt; \u4e2d\u6587-\u6d4b\u8bd5-42; **hi___there** -&gt; hi-there; only punctuation or whitespace -&gt; empty string.\n\nCurrent src\/slugify.js:\n```javascript\nfunction slugify(value) {\n  if (typeof value !== &quot;string&quot;) return &quot;&quot;;\n  return value\n    .trim()\n    .toLowerCase()\n    .replace(\/[^a-z0-9]+\/g, &quot;-&quot;)\n    .replace(\/^-+|-+$\/g, &quot;&quot;);\n}\n\nmodule.exports = { slugify };\n\n\n```\n\nReturn exactly one JSON object with this shape:\n{&quot;files&quot;:{&quot;src\/slugify.js&quot;:&quot;complete JavaScript source as a JSON string&quot;},&quot;review_notes&quot;:[&quot;at most four brief implementation or assumption notes&quot;]}\nNo Markdown wrapper. You are returning code for someone else to evaluate locally; do not say that tests passed or that you ran them.\n<\/code><\/pre><\/details><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View Claude Haiku 4.5&#8217;s complete response as returned<\/summary><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">```json\n{\n  &quot;files&quot;: {\n    &quot;src\/slugify.js&quot;: &quot;function slugify(value) {\\n  if (typeof value !== \\&quot;string\\&quot;) return \\&quot;\\&quot;;\\n  \\n  \/\/ Normalize to NFC and lowercase\\n  const normalized = value.normalize(\\&quot;NFC\\&quot;).toLowerCase();\\n  \\n  \/\/ Replace consecutive runs of non-letter, non-number, non-combining-mark characters with a single hyphen\\n  \/\/ Unicode letter categories: L* (Lu, Ll, Lt, Lm, Lo)\\n  \/\/ Unicode number categories: N* (Nd, Nl, No)\\n  \/\/ Unicode combining mark categories: M* (Mn, Mc, Me)\\n  const slugged = normalized.replace(\/[^\\\\p{L}\\\\p{N}\\\\p{M}]+\/gu, \\&quot;-\\&quot;);\\n  \\n  \/\/ Trim leading and trailing hyphens\\n  return slugged.replace(\/^-+|-+$\/g, \\&quot;\\&quot;);\\n}\\n\\nmodule.exports = { slugify };&quot;\n  },\n  &quot;review_notes&quot;: [\n    &quot;Uses String.prototype.normalize(\\&quot;NFC\\&quot;) to decompose composed characters like \u00e9 into base+combining mark, then toLowerCase() applies to normalized string&quot;,\n    &quot;Unicode property escapes (\\\\p{L}, \\\\p{N}, \\\\p{M}) with \/u flag preserve all Unicode letters, numbers, and combining marks while replacing other consecutive characters with single hyphens&quot;,\n    &quot;Existing ASCII behavior is preserved: punctuation and whitespace are replaced with hyphens, then leading\/trailing hyphens are trimmed&quot;,\n    &quot;Non-string inputs return empty string as required; normalized decomposed characters (e.g., Cafe\\\\u0301) are handled correctly by NFC normalization&quot;\n  ]\n}\n```<\/code><\/pre><\/details><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View Claude Sonnet 5&#8217;s complete response as returned<\/summary><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">{&quot;files&quot;:{&quot;src\/slugify.js&quot;:&quot;function slugify(value) {\\n  if (typeof value !== \\&quot;string\\&quot;) return \\&quot;\\&quot;;\\n  return value\\n    .normalize(\\&quot;NFC\\&quot;)\\n    .toLowerCase()\\n    .replace(\/[^\\\\p{L}\\\\p{N}\\\\p{M}]+\/gu, \\&quot;-\\&quot;)\\n    .replace(\/^-+|-+$\/g, \\&quot;\\&quot;);\\n}\\n\\nmodule.exports = { slugify };\\n&quot;},&quot;review_notes&quot;:[&quot;Used Unicode property escapes (\\\\p{L}, \\\\p{N}, \\\\p{M}) with the u flag to preserve letters, numbers, and combining marks across scripts.&quot;,&quot;NFC normalization ensures decomposed sequences like Cafe + combining acute compose to caf\u00e9 before lowercasing.&quot;,&quot;Runs of any other characters (punctuation, whitespace, symbols) collapse to a single hyphen, then leading\/trailing hyphens are trimmed.&quot;]}<\/code><\/pre><\/details><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View Claude Opus 5.5&#8217;s complete response as returned<\/summary><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">{&quot;files&quot;:{&quot;src\/slugify.js&quot;:&quot;function slugify(value) {\\n  if (typeof value !== \\&quot;string\\&quot;) return \\&quot;\\&quot;;\\n  return value\\n    .normalize(\\&quot;NFC\\&quot;)\\n    .toLowerCase()\\n    .replace(\/[^\\\\p{L}\\\\p{N}\\\\p{M}]+\/gu, \\&quot;-\\&quot;)\\n    .replace(\/^-+|-+$\/g, \\&quot;\\&quot;);\\n}\\n\\nmodule.exports = { slugify };\\n&quot;},&quot;review_notes&quot;:[&quot;The input is normalized to NFC before lowercasing, so decomposed input like Cafe\\\\u0301 composes to caf\u00e9.&quot;,&quot;A Unicode property regex with the u flag keeps letters (\\\\p{L}), numbers (\\\\p{N}) and combining marks (\\\\p{M}). Each run of any other characters, including underscores and whitespace, becomes one hyphen.&quot;,&quot;The explicit trim() was removed because the final step strips leading and trailing hyphens, which covers surrounding whitespace.&quot;,&quot;Lowercasing happens after NFC normalization, as the spec orders. toLowerCase can occasionally produce non-NFC output for rare characters, and it is not re-normalized here.&quot;]}<\/code><\/pre><\/details><\/section>\n\n\n\n<style>\n.ccms-test-t02{border:1px solid #d7dfed;border-radius:8px;padding:24px;background:#f8faff;color:#172438;margin:28px 0;font:16px\/1.6 system-ui,sans-serif;box-sizing:border-box}.ccms-test-t02 *{box-sizing:border-box}.ccms-test-t02 h3,.ccms-test-t02 h4{color:#172438;line-height:1.35;margin:0 0 12px}.ccms-test-t02 h3{font-size:1.35rem}.ccms-test-t02 h4{font-size:1.1rem}.ccms-test-t02 p{color:#35435a;margin:12px 0}.ccms-test-t02 a{color:#254fc2;text-decoration:underline}.ccms-test-t02 .ccms-scroll{overflow-x:auto}.ccms-test-t02 table{width:100%;min-width:650px;border-collapse:collapse;text-align:left;font-size:14px}.ccms-test-t02 th,.ccms-test-t02 td{padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top}.ccms-test-t02 th{background:#eaf0fa}.ccms-test-t02 details{border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff}.ccms-test-t02 summary{cursor:pointer;font-weight:650;color:#254fc2}.ccms-test-t02 pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace}.ccms-test-t02 code{color:inherit}.ccms-test-t02 .ccms-verdict{border-left:4px solid #5b62c8;padding:8px 14px;background:#eef0ff}.ccms-test-t02 .ccms-note{font-size:14px}@media(max-width:520px){.ccms-test-t02{padding:16px}.ccms-test-t02 pre{padding:10px}}\n<\/style><section class=\"ccms-test-t02\" aria-labelledby=\"ccms-test-t02-title\" style=\"border:1px solid #d7dfed;border-radius:8px;padding:24px;background:#f8faff;color:#172438;margin:28px 0;font:16px\/1.6 system-ui,sans-serif;box-sizing:border-box;max-width:100%\"><h3 id=\"ccms-test-t02-title\" style=\"box-sizing:border-box;color:#172438;line-height:1.35;margin:0 0 12px;font-size:1.35rem\">Task 2: Repair a route selector and return its tests<\/h3><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">The function had to resolve longest-prefix matches, method precedence, segment boundaries, malformed rules, and immutable inputs. The requested response also included a new test file.<\/p><div class=\"ccms-scroll\" style=\"box-sizing:border-box;overflow-x:auto;max-width:100%\"><table style=\"box-sizing:border-box;width:100%;min-width:650px;border-collapse:collapse;text-align:left;font-size:14px\"><caption style=\"box-sizing:border-box\">First returned outputs, with fixed local behavior checks<\/caption><thead style=\"box-sizing:border-box\"><tr style=\"box-sizing:border-box\"><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Model<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Behavior checks<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Response format<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Complete requested delivery<\/th><\/tr><\/thead><tbody style=\"box-sizing:border-box\"><tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Claude Haiku 4.5<\/th><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">12\/12 on the complete function only<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Fail: truncated JSON<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">No: test file cut off<\/td><\/tr><tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Claude Soneta 5<\/th><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">12\/12 on the complete function only<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Fail: truncated JSON<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">No: test file cut off<\/td><\/tr><tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top;background:#eaf0fa\">Claude Opus 5,5<\/th><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">12\/12 on the complete function only<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">Fail: truncated JSON<\/td><td style=\"box-sizing:border-box;padding:12px 10px;border-bottom:1px solid #d7dfed;color:#172438;vertical-align:top\">No: test file cut off<\/td><\/tr><\/tbody><\/table><\/div><div class=\"ccms-verdict\" style=\"box-sizing:border-box;border-left:4px solid #5b62c8;padding:8px 14px;background:#eef0ff;max-width:100%\"><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\"><strong style=\"box-sizing:border-box\">Observed result:<\/strong> no model completed the requested two-file response within the shared output limit. All three stopped at 4,096 reported completion tokens. Each had already returned a complete router function, which passed the twelve fixed behavior groups; the new test files were incomplete and were not executed.<\/p><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">We extracted only each fully closed source-code string. The original truncated responses remain intact below. A passing function score therefore does not mean the complete request succeeded.<\/p><\/div><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">Additional code-review finding: an equal-root tie<\/summary><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">After the fixed checks, we noticed that Haiku normalized <code style=\"box-sizing:border-box;color:inherit\">\/\/\/<\/code> to an empty string rather than <code style=\"box-sizing:border-box;color:inherit\">\/<\/code>. A separate local check used two GET rules, with prefixes <code style=\"box-sizing:border-box;color:inherit\">\/\/\/<\/code> dan <code style=\"box-sizing:border-box;color:inherit\">\/<\/code>, targeting <code style=\"box-sizing:border-box;color:inherit\">pertama<\/code> dan <code style=\"box-sizing:border-box;color:inherit\">second<\/code> in that order. For <code style=\"box-sizing:border-box;color:inherit\">\/anything<\/code>, the contract requires <code style=\"box-sizing:border-box;color:inherit\">pertama<\/code>.<\/p><p style=\"box-sizing:border-box;color:#35435a;margin:12px 0\">Haiku returned <code style=\"box-sizing:border-box;color:inherit\">second<\/code>; Sonnet and Opus returned <code style=\"box-sizing:border-box;color:inherit\">pertama<\/code>. This additional check was prompted by code review and is separate from the twelve checks set before testing. It does not alter their scores.<\/p><\/details><p class=\"ccms-note\" style=\"box-sizing:border-box;color:#35435a;margin:12px 0;font-size:14px\">Sonnet encountered one service error before its permitted retry returned the displayed truncated response. That service failure is separate from code quality. No model received another attempt to improve or finish its answer.<\/p><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View the complete shared prompt and input code<\/summary><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">SYSTEM\nYou are completing a bounded JavaScript coding task. Return only the requested JSON object with complete source files and brief review notes. Do not claim to have edited files, run commands, or used tools. You have no tool access. Do not include hidden reasoning.\n\nUSER\nRepair a Node.js 18+ CommonJS route selector. Return complete replacement src\/router.js and an additional test\/router-added.test.js using node:test and node:assert\/strict. Do not add dependencies or edit existing tests. Do not use I\/O other than the test runner, network, child processes, timers, or any files beyond the two requested outputs.\n\nContract for chooseRoute(request, rules):\n1. Invalid request or rules returns null, without throwing. Request must be a non-null, non-array object; method must be a nonempty ASCII-letter string; path must be a string beginning with \/. Rules must be an array.\n2. Before matching, remove the request path&#x27;s query and fragment starting at the earliest ? or #. Do not URL-decode or collapse interior slashes.\n3. Ignore invalid rules. A valid rule is a non-null, non-array object with method &#x27;*&#x27; or a nonempty ASCII-letter string, prefix a string starting with \/ containing neither ? nor #, and target a nonempty string.\n4. Compare methods case-insensitively. Prefer any matching exact-method rule over all wildcard-method &#x27;*&#x27; rules, even if a wildcard has a longer prefix. Use wildcard rules only if no exact-method route matches the path.\n5. Remove trailing slashes from a rule prefix, except that an all-slash prefix normalizes to \/. A prefix matches the path only at a segment boundary: \/api matches \/api and \/api\/users, never \/apix. Root \/ matches every valid request path.\n6. Within the chosen method group, choose the longest normalized matching prefix. On equal prefix length, choose the earlier rule in the original input array. Return its target. Return null if none matches.\n7. Do not mutate the request, rules array, or rule objects, including order or prefix strings. Preserve module.exports = { chooseRoute }.\n8. Add tests for segment boundaries, query\/fragment removal, method precedence, ties, malformed inputs and immutability. Existing simple GET \/api\/users and POST-no-match cases must still pass.\n\nCurrent src\/router.js:\n```javascript\nfunction chooseRoute(request, rules) {\n  if (!request || !Array.isArray(rules)) return null;\n  for (const rule of rules) {\n    if (request.method === rule.method &amp;&amp; request.path.startsWith(rule.prefix)) {\n      return rule.target;\n    }\n  }\n  return null;\n}\n\nmodule.exports = { chooseRoute };\n\n\n```\n\nExisting regression cases (unchanged): rules [{method:&#x27;GET&#x27;,prefix:&#x27;\/api&#x27;,target:&#x27;api&#x27;},{method:&#x27;GET&#x27;,prefix:&#x27;\/api\/admin&#x27;,target:&#x27;admin&#x27;}]; GET \/api\/users returns &#x27;api&#x27;; POST \/api\/users returns null.\n\nReturn exactly one JSON object with this shape:\n{&quot;files&quot;:{&quot;src\/router.js&quot;:&quot;complete JavaScript source as a JSON string&quot;,&quot;test\/router-added.test.js&quot;:&quot;complete JavaScript tests as a JSON string&quot;},&quot;review_notes&quot;:[&quot;at most four brief implementation or assumption notes&quot;]}\nNo Markdown wrapper. You are returning code for someone else to evaluate locally; do not say you edited files, ran tests, or observed passing results.\n<\/code><\/pre><\/details><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View Claude Haiku 4.5&#8217;s complete response as returned<\/summary><p class=\"ccms-note\" style=\"box-sizing:border-box;color:#35435a;margin:12px 0;font-size:14px\">This is the entire response received. It ends mid-output because it reached the limit; missing content has not been filled in.<\/p><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">```json\n{\n  &quot;files&quot;: {\n    &quot;src\/router.js&quot;: &quot;function chooseRoute(request, rules) {\\n  \/\/ Validate request\\n  if (request === null || Array.isArray(request) || typeof request !== &#x27;object&#x27;) {\\n    return null;\\n  }\\n  if (typeof request.method !== &#x27;string&#x27; || request.method.length === 0 || !\/^[a-zA-Z]+$\/.test(request.method)) {\\n    return null;\\n  }\\n  if (typeof request.path !== &#x27;string&#x27; || !request.path.startsWith(&#x27;\/&#x27;)) {\\n    return null;\\n  }\\n\\n  \/\/ Validate rules\\n  if (!Array.isArray(rules)) {\\n    return null;\\n  }\\n\\n  \/\/ Remove query and fragment from path\\n  const cleanPath = request.path.split(\/[?#]\/)[0];\\n\\n  \/\/ Filter and validate rules\\n  const validRules = [];\\n  for (const rule of rules) {\\n    if (rule === null || Array.isArray(rule) || typeof rule !== &#x27;object&#x27;) {\\n      continue;\\n    }\\n    \\n    const method = rule.method;\\n    if (typeof method !== &#x27;string&#x27; || (method !== &#x27;*&#x27; &amp;&amp; (method.length === 0 || !\/^[a-zA-Z]+$\/.test(method)))) {\\n      continue;\\n    }\\n    \\n    const prefix = rule.prefix;\\n    if (typeof prefix !== &#x27;string&#x27; || !prefix.startsWith(&#x27;\/&#x27;) || prefix.includes(&#x27;?&#x27;) || prefix.includes(&#x27;#&#x27;)) {\\n      continue;\\n    }\\n    \\n    const target = rule.target;\\n    if (typeof target !== &#x27;string&#x27; || target.length === 0) {\\n      continue;\\n    }\\n    \\n    validRules.push(rule);\\n  }\\n\\n  \/\/ Normalize prefixes and partition into exact-method and wildcard groups\\n  const exactMethodRules = [];\\n  const wildcardRules = [];\\n  \\n  for (const rule of validRules) {\\n    const normalizedPrefix = rule.prefix === &#x27;\/&#x27; ? &#x27;\/&#x27; : rule.prefix.replace(\/\\\\\/+$\/, &#x27;&#x27;);\\n    \\n    const entry = {\\n      originalRule: rule,\\n      normalizedPrefix: normalizedPrefix,\\n      method: rule.method\\n    };\\n    \\n    if (rule.method === &#x27;*&#x27;) {\\n      wildcardRules.push(entry);\\n    } else {\\n      exactMethodRules.push(entry);\\n    }\\n  }\\n\\n  const requestMethod = request.method.toUpperCase();\\n\\n  \/\/ Helper to check if a prefix matches the path at a segment boundary\\n  function prefixMatches(prefix, path) {\\n    if (prefix === &#x27;\/&#x27;) {\\n      return true;\\n    }\\n    if (!path.startsWith(prefix)) {\\n      return false;\\n    }\\n    \/\/ Check segment boundary: next character must be &#x27;\/&#x27; or end of string\\n    const nextChar = path[prefix.length];\\n    return nextChar === undefined || nextChar === &#x27;\/&#x27;;\\n  }\\n\\n  \/\/ Try exact-method rules first\\n  let bestMatch = null;\\n  let bestLength = -1;\\n  \\n  for (const entry of exactMethodRules) {\\n    if (entry.method.toUpperCase() === requestMethod) {\\n      if (prefixMatches(entry.normalizedPrefix, cleanPath)) {\\n        if (entry.normalizedPrefix.length &gt; bestLength) {\\n          bestMatch = entry.originalRule;\\n          bestLength = entry.normalizedPrefix.length;\\n        }\\n      }\\n    }\\n  }\\n  \\n  if (bestMatch !== null) {\\n    return bestMatch.target;\\n  }\\n\\n  \/\/ Try wildcard rules only if no exact-method match\\n  bestMatch = null;\\n  bestLength = -1;\\n  \\n  for (const entry of wildcardRules) {\\n    if (prefixMatches(entry.normalizedPrefix, cleanPath)) {\\n      if (entry.normalizedPrefix.length &gt; bestLength) {\\n        bestMatch = entry.originalRule;\\n        bestLength = entry.normalizedPrefix.length;\\n      }\\n    }\\n  }\\n  \\n  if (bestMatch !== null) {\\n    return bestMatch.target;\\n  }\\n\\n  return null;\\n}\\n\\nmodule.exports = { chooseRoute };&quot;,\n    &quot;test\/router-added.test.js&quot;: &quot;const test = require(&#x27;node:test&#x27;);\\nconst assert = require(&#x27;node:assert\/strict&#x27;);\\nconst { chooseRoute } = require(&#x27;..\/src\/router.js&#x27;);\\n\\n\/\/ Regression: existing test cases\\ntest(&#x27;GET \/api\/users matches \/api prefix (exact method)&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;api&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api\/admin&#x27;, target: &#x27;admin&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules), &#x27;api&#x27;);\\n});\\n\\ntest(&#x27;POST \/api\/users returns null (no matching method)&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;api&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api\/admin&#x27;, target: &#x27;admin&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;POST&#x27;, path: &#x27;\/api\/users&#x27; }, rules), null);\\n});\\n\\n\/\/ Invalid request handling\\ntest(&#x27;null request returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute(null, []), null);\\n});\\n\\ntest(&#x27;array request returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute([], []), null);\\n});\\n\\ntest(&#x27;request with missing method returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ path: &#x27;\/api&#x27; }, []), null);\\n});\\n\\ntest(&#x27;request with empty method returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;&#x27;, path: &#x27;\/api&#x27; }, []), null);\\n});\\n\\ntest(&#x27;request with non-letter method returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET-POST&#x27;, path: &#x27;\/api&#x27; }, []), null);\\n});\\n\\ntest(&#x27;request with numeric method returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;123&#x27;, path: &#x27;\/api&#x27; }, []), null);\\n});\\n\\ntest(&#x27;request with missing path returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27; }, []), null);\\n});\\n\\ntest(&#x27;request with path not starting with \/ returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;api&#x27; }, []), null);\\n});\\n\\ntest(&#x27;null rules returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, null), null);\\n});\\n\\ntest(&#x27;non-array rules returns null&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, { method: &#x27;GET&#x27; }), null);\\n});\\n\\n\/\/ Query and fragment removal\\ntest(&#x27;query string is removed before matching&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users?foo=bar&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;fragment is removed before matching&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users#section&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;earliest ? or # is used as boundary&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users?foo#bar&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;fragment before query is used as boundary&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users#foo?bar&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\n\/\/ Segment boundary matching\\ntest(&#x27;prefix \/api matches \/api\/users at segment boundary&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;prefix \/api does not match \/apix (no segment boundary)&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/apix&#x27; }, rules), null);\\n});\\n\\ntest(&#x27;prefix \/api matches \/api exactly at segment boundary&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;root \/ matches any valid path&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/&#x27;, target: &#x27;root&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/anything\/here&#x27; }, rules), &#x27;root&#x27;);\\n});\\n\\ntest(&#x27;root \/ matches \/&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/&#x27;, target: &#x27;root&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/&#x27; }, rules), &#x27;root&#x27;);\\n});\\n\\n\/\/ Prefix normalization (trailing slash removal)\\ntest(&#x27;trailing slash is removed from prefix&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api\/&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;multiple trailing slashes are removed&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api\/\/\/&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;all-slash prefix normalizes to single \/&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/\/\/&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\n\/\/ Method case-insensitivity\\ntest(&#x27;method comparison is case-insensitive&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;get&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;request method case does not affect matching&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;get&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\n\/\/ Exact-method vs wildcard precedence\\ntest(&#x27;exact-method rule preferred over wildcard with longer prefix&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;*&#x27;, prefix: &#x27;\/api\/admin\/users&#x27;, target: &#x27;wildcard&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;exact&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/test&#x27; }, rules), &#x27;exact&#x27;);\\n});\\n\\ntest(&#x27;wildcard rule used when no exact-method matches&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;*&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;wildcard&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/other&#x27;, target: &#x27;exact&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;POST&#x27;, path: &#x27;\/api\/users&#x27; }, rules), &#x27;wildcard&#x27;);\\n});\\n\\n\/\/ Longest prefix matching\\ntest(&#x27;longest matching prefix is chosen&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;short&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api\/admin&#x27;, target: &#x27;long&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/admin\/users&#x27; }, rules), &#x27;long&#x27;);\\n});\\n\\n\/\/ Tie-breaking (first rule wins on equal prefix length)\\ntest(&#x27;first rule wins on equal prefix length&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;first&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;second&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules), &#x27;first&#x27;);\\n});\\n\\n\/\/ Invalid rules are ignored\\ntest(&#x27;null rule is ignored&#x27;, () =&gt; {\\n  const rules = [\\n    null,\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;array rule is ignored&#x27;, () =&gt; {\\n  const rules = [\\n    [],\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;found&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;found&#x27;);\\n});\\n\\ntest(&#x27;rule with invalid method is ignored&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;invalid&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;valid&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;valid&#x27;);\\n});\\n\\ntest(&#x27;rule with non-letter method (if not wildcard) is ignored&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;G3T&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;invalid&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;valid&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;valid&#x27;);\\n});\\n\\ntest(&#x27;rule with prefix not starting with \/ is ignored&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;api&#x27;, target: &#x27;invalid&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;valid&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;valid&#x27;);\\n});\\n\\ntest(&#x27;rule with query in prefix is ignored&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api?foo=bar&#x27;, target: &#x27;invalid&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;valid&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;valid&#x27;);\\n});\\n\\ntest(&#x27;rule with fragment in prefix is ignored&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api#section&#x27;, target: <\/code><\/pre><\/details><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View Claude Sonnet 5&#8217;s complete response as returned<\/summary><p class=\"ccms-note\" style=\"box-sizing:border-box;color:#35435a;margin:12px 0;font-size:14px\">This is the entire response received. It ends mid-output because it reached the limit; missing content has not been filled in.<\/p><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">{&quot;files&quot;:{&quot;src\/router.js&quot;:&quot;function isValidRequest(request) {\\n  return (\\n    request !== null &amp;&amp;\\n    typeof request === &#x27;object&#x27; &amp;&amp;\\n    !Array.isArray(request) &amp;&amp;\\n    typeof request.method === &#x27;string&#x27; &amp;&amp;\\n    request.method.length &gt; 0 &amp;&amp;\\n    \/^[A-Za-z]+$\/.test(request.method) &amp;&amp;\\n    typeof request.path === &#x27;string&#x27; &amp;&amp;\\n    request.path.startsWith(&#x27;\/&#x27;)\\n  );\\n}\\n\\nfunction isValidRule(rule) {\\n  if (rule === null || typeof rule !== &#x27;object&#x27; || Array.isArray(rule)) {\\n    return false;\\n  }\\n  const { method, prefix, target } = rule;\\n\\n  if (typeof method !== &#x27;string&#x27;) return false;\\n  if (method !== &#x27;*&#x27; &amp;&amp; !(method.length &gt; 0 &amp;&amp; \/^[A-Za-z]+$\/.test(method))) {\\n    return false;\\n  }\\n\\n  if (\\n    typeof prefix !== &#x27;string&#x27; ||\\n    !prefix.startsWith(&#x27;\/&#x27;) ||\\n    prefix.includes(&#x27;?&#x27;) ||\\n    prefix.includes(&#x27;#&#x27;)\\n  ) {\\n    return false;\\n  }\\n\\n  if (typeof target !== &#x27;string&#x27; || target.length === 0) return false;\\n\\n  return true;\\n}\\n\\nfunction normalizePrefix(prefix) {\\n  if (\/^\\\\\/+$\/.test(prefix)) return &#x27;\/&#x27;;\\n  return prefix.replace(\/\\\\\/+$\/, &#x27;&#x27;);\\n}\\n\\nfunction prefixMatches(normalizedPrefix, path) {\\n  if (normalizedPrefix === &#x27;\/&#x27;) return true;\\n  if (path === normalizedPrefix) return true;\\n  return path.startsWith(normalizedPrefix + &#x27;\/&#x27;);\\n}\\n\\nfunction stripQueryAndFragment(path) {\\n  let cutIndex = path.length;\\n  for (let i = 0; i &lt; path.length; i++) {\\n    const c = path[i];\\n    if (c === &#x27;?&#x27; || c === &#x27;#&#x27;) {\\n      cutIndex = i;\\n      break;\\n    }\\n  }\\n  return path.slice(0, cutIndex);\\n}\\n\\nfunction chooseRoute(request, rules) {\\n  if (!isValidRequest(request) || !Array.isArray(rules)) return null;\\n\\n  const path = stripQueryAndFragment(request.path);\\n  const reqMethodLower = request.method.toLowerCase();\\n\\n  let bestExact = null; \/\/ { len, idx, target }\\n  let bestWildcard = null;\\n\\n  for (let idx = 0; idx &lt; rules.length; idx++) {\\n    const rule = rules[idx];\\n    if (!isValidRule(rule)) continue;\\n\\n    const normPrefix = normalizePrefix(rule.prefix);\\n    if (!prefixMatches(normPrefix, path)) continue;\\n\\n    const len = normPrefix.length;\\n\\n    if (rule.method === &#x27;*&#x27;) {\\n      if (\\n        bestWildcard === null ||\\n        len &gt; bestWildcard.len ||\\n        (len === bestWildcard.len &amp;&amp; idx &lt; bestWildcard.idx)\\n      ) {\\n        bestWildcard = { len, idx, target: rule.target };\\n      }\\n    } else if (rule.method.toLowerCase() === reqMethodLower) {\\n      if (\\n        bestExact === null ||\\n        len &gt; bestExact.len ||\\n        (len === bestExact.len &amp;&amp; idx &lt; bestExact.idx)\\n      ) {\\n        bestExact = { len, idx, target: rule.target };\\n      }\\n    }\\n  }\\n\\n  if (bestExact !== null) return bestExact.target;\\n  if (bestWildcard !== null) return bestWildcard.target;\\n  return null;\\n}\\n\\nmodule.exports = { chooseRoute };\\n&quot;,&quot;test\/router-added.test.js&quot;:&quot;const test = require(&#x27;node:test&#x27;);\\nconst assert = require(&#x27;node:assert\/strict&#x27;);\\nconst { chooseRoute } = require(&#x27;..\/src\/router&#x27;);\\n\\ntest(&#x27;segment boundary: prefix matches at slash boundary only&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;api&#x27; },\\n  ];\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules),\\n    &#x27;api&#x27;\\n  );\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules),\\n    &#x27;api&#x27;\\n  );\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/apix&#x27; }, rules),\\n    null\\n  );\\n});\\n\\ntest(&#x27;root prefix matches every valid path&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/&#x27;, target: &#x27;root&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/&#x27; }, rules), &#x27;root&#x27;);\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/anything\/here&#x27; }, rules),\\n    &#x27;root&#x27;\\n  );\\n});\\n\\ntest(&#x27;trailing slashes in rule prefix are normalized&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api\/\/\/&#x27;, target: &#x27;api&#x27; }];\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules),\\n    &#x27;api&#x27;\\n  );\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;api&#x27;);\\n});\\n\\ntest(&#x27;all-slash prefix normalizes to \/&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/\/\/\/&#x27;, target: &#x27;root&#x27; }];\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/whatever&#x27; }, rules),\\n    &#x27;root&#x27;\\n  );\\n});\\n\\ntest(&#x27;query and fragment are stripped before matching&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;api&#x27; }];\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users?x=1&amp;y=2&#x27; }, rules),\\n    &#x27;api&#x27;\\n  );\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users#section&#x27; }, rules),\\n    &#x27;api&#x27;\\n  );\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users?x=1#frag&#x27; }, rules),\\n    &#x27;api&#x27;\\n  );\\n});\\n\\ntest(&#x27;query\/fragment stripping does not decode or collapse slashes&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/a\/\/b&#x27;, target: &#x27;weird&#x27; }];\\n  assert.equal(\\n    chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/a\/\/b?x=1&#x27; }, rules),<\/code><\/pre><\/details><details style=\"box-sizing:border-box;border:1px solid #d7dfed;border-radius:6px;padding:12px;margin:12px 0;background:#fff\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:650;color:#254fc2\">View Claude Opus 5.5&#8217;s complete response as returned<\/summary><p class=\"ccms-note\" style=\"box-sizing:border-box;color:#35435a;margin:12px 0;font-size:14px\">This is the entire response received. It ends mid-output because it reached the limit; missing content has not been filled in.<\/p><pre style=\"box-sizing:border-box;white-space:pre-wrap;overflow-wrap:anywhere;max-height:520px;overflow:auto;background:#edf1f7;padding:14px;border-radius:4px;color:#162239;font:13px\/1.55 ui-monospace,SFMono-Regular,monospace\"><code style=\"box-sizing:border-box;color:inherit\">{&quot;files&quot;:{&quot;src\/router.js&quot;:&quot;&#x27;use strict&#x27;;\\n\\nconst LETTERS = \/^[A-Za-z]+$\/;\\n\\nfunction isPlainObject(value) {\\n  return value !== null &amp;&amp; typeof value === &#x27;object&#x27; &amp;&amp; !Array.isArray(value);\\n}\\n\\nfunction isMethodName(value) {\\n  return typeof value === &#x27;string&#x27; &amp;&amp; value.length &gt; 0 &amp;&amp; LETTERS.test(value);\\n}\\n\\nfunction stripQueryAndFragment(path) {\\n  const q = path.indexOf(&#x27;?&#x27;);\\n  const h = path.indexOf(&#x27;#&#x27;);\\n  let cut = -1;\\n  if (q !== -1 &amp;&amp; h !== -1) cut = Math.min(q, h);\\n  else if (q !== -1) cut = q;\\n  else if (h !== -1) cut = h;\\n  return cut === -1 ? path : path.slice(0, cut);\\n}\\n\\nfunction normalizePrefix(prefix) {\\n  let end = prefix.length;\\n  while (end &gt; 0 &amp;&amp; prefix[end - 1] === &#x27;\/&#x27;) end -= 1;\\n  return end === 0 ? &#x27;\/&#x27; : prefix.slice(0, end);\\n}\\n\\nfunction prefixMatches(path, prefix) {\\n  if (prefix === &#x27;\/&#x27;) return true;\\n  return path === prefix || path.startsWith(prefix + &#x27;\/&#x27;);\\n}\\n\\nfunction chooseRoute(request, rules) {\\n  try {\\n    if (!isPlainObject(request) || !Array.isArray(rules)) return null;\\n    const method = request.method;\\n    const rawPath = request.path;\\n    if (!isMethodName(method)) return null;\\n    if (typeof rawPath !== &#x27;string&#x27; || rawPath[0] !== &#x27;\/&#x27;) return null;\\n\\n    const path = stripQueryAndFragment(rawPath);\\n    const upperMethod = method.toUpperCase();\\n\\n    let bestExact = null;\\n    let bestWildcard = null;\\n\\n    const count = rules.length;\\n    for (let i = 0; i &lt; count; i += 1) {\\n      const rule = rules[i];\\n      if (!isPlainObject(rule)) continue;\\n      const ruleMethod = rule.method;\\n      const prefix = rule.prefix;\\n      const target = rule.target;\\n      const isWildcard = ruleMethod === &#x27;*&#x27;;\\n      if (!isWildcard &amp;&amp; !isMethodName(ruleMethod)) continue;\\n      if (typeof prefix !== &#x27;string&#x27; || prefix[0] !== &#x27;\/&#x27;) continue;\\n      if (prefix.indexOf(&#x27;?&#x27;) !== -1 || prefix.indexOf(&#x27;#&#x27;) !== -1) continue;\\n      if (typeof target !== &#x27;string&#x27; || target.length === 0) continue;\\n\\n      const normalized = normalizePrefix(prefix);\\n      if (!prefixMatches(path, normalized)) continue;\\n\\n      const candidate = { length: normalized.length, target };\\n      if (isWildcard) {\\n        if (bestWildcard === null || candidate.length &gt; bestWildcard.length) bestWildcard = candidate;\\n      } else if (ruleMethod.toUpperCase() === upperMethod) {\\n        if (bestExact === null || candidate.length &gt; bestExact.length) bestExact = candidate;\\n      }\\n    }\\n\\n    if (bestExact !== null) return bestExact.target;\\n    if (bestWildcard !== null) return bestWildcard.target;\\n    return null;\\n  } catch (err) {\\n    return null;\\n  }\\n}\\n\\nmodule.exports = { chooseRoute };\\n&quot;,&quot;test\/router-added.test.js&quot;:&quot;&#x27;use strict&#x27;;\\n\\nconst test = require(&#x27;node:test&#x27;);\\nconst assert = require(&#x27;node:assert\/strict&#x27;);\\nconst { chooseRoute } = require(&#x27;..\/src\/router.js&#x27;);\\n\\nconst baseRules = [\\n  { method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;api&#x27; },\\n  { method: &#x27;GET&#x27;, prefix: &#x27;\/api\/admin&#x27;, target: &#x27;admin&#x27; }\\n];\\n\\ntest(&#x27;existing regression cases still hold&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, baseRules), &#x27;api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;POST&#x27;, path: &#x27;\/api\/users&#x27; }, baseRules), null);\\n});\\n\\ntest(&#x27;longest prefix wins within method group&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/admin\/x&#x27; }, baseRules), &#x27;admin&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/admin&#x27; }, baseRules), &#x27;admin&#x27;);\\n});\\n\\ntest(&#x27;segment boundaries&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;api&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/&#x27; }, rules), &#x27;api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/users&#x27; }, rules), &#x27;api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/apix&#x27; }, rules), null);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/ap&#x27; }, rules), null);\\n});\\n\\ntest(&#x27;trailing slashes in prefixes are normalized, all-slash is root&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api\/\/\/&#x27;, target: &#x27;api&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api&#x27; }, rules), &#x27;api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/apix&#x27; }, rules), null);\\n  const rootRules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/\/\/&#x27;, target: &#x27;root&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/&#x27; }, rootRules), &#x27;root&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/anything\/else&#x27; }, rootRules), &#x27;root&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/x&#x27; }, [{ method: &#x27;GET&#x27;, prefix: &#x27;\/&#x27;, target: &#x27;r&#x27; }]), &#x27;r&#x27;);\\n});\\n\\ntest(&#x27;query and fragment are removed at earliest ? or #&#x27;, () =&gt; {\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api?next=\/api\/admin&#x27; }, baseRules), &#x27;api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api#\/admin&#x27; }, baseRules), &#x27;api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/apix?\/api&#x27; }, baseRules), null);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/admin#frag?q&#x27; }, baseRules), &#x27;admin&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api?q#\/admin&#x27; }, baseRules), &#x27;api&#x27;);\\n});\\n\\ntest(&#x27;no URL decoding and no slash collapsing&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;GET&#x27;, prefix: &#x27;\/api\/admin&#x27;, target: &#x27;admin&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api%2Fadmin&#x27; }, rules), null);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/\/admin&#x27; }, rules), null);\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/\/admin&#x27; }, baseRules), &#x27;api&#x27;);\\n});\\n\\ntest(&#x27;methods compare case-insensitively&#x27;, () =&gt; {\\n  const rules = [{ method: &#x27;get&#x27;, prefix: &#x27;\/a&#x27;, target: &#x27;lower&#x27; }];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/a&#x27; }, rules), &#x27;lower&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;gEt&#x27;, path: &#x27;\/a\/b&#x27; }, rules), &#x27;lower&#x27;);\\n});\\n\\ntest(&#x27;exact method beats longer wildcard; wildcard used only as fallback&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;*&#x27;, prefix: &#x27;\/api\/admin&#x27;, target: &#x27;wild-admin&#x27; },\\n    { method: &#x27;GET&#x27;, prefix: &#x27;\/&#x27;, target: &#x27;get-root&#x27; },\\n    { method: &#x27;POST&#x27;, prefix: &#x27;\/other&#x27;, target: &#x27;post-other&#x27; },\\n    { method: &#x27;*&#x27;, prefix: &#x27;\/api&#x27;, target: &#x27;wild-api&#x27; }\\n  ];\\n  assert.equal(chooseRoute({ method: &#x27;GET&#x27;, path: &#x27;\/api\/admin\/x&#x27; }, rules), &#x27;get-root&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;POST&#x27;, path: &#x27;\/api\/admin\/x&#x27; }, rules), &#x27;wild-admin&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;POST&#x27;, path: &#x27;\/api\/x&#x27; }, rules), &#x27;wild-api&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;POST&#x27;, path: &#x27;\/other\/1&#x27; }, rules), &#x27;post-other&#x27;);\\n  assert.equal(chooseRoute({ method: &#x27;PUT&#x27;, path: &#x27;\/nothing&#x27; }, rules), null);\\n});\\n\\ntest(&#x27;ties go to earlier rule in input order&#x27;, () =&gt; {\\n  const rules = [\\n    { method: &#x27;GET&#x27;, pref<\/code><\/pre><\/details><\/section>\n\n\n\n<p class=\"wp-block-paragraph\">The 4,096-token ceiling was the output budget chosen for this test, not any model\u2019s documented maximum. The routing result suggests a practical check before a larger request: estimate the size of the implementation, tests, and explanation you expect back. Splitting deliverables or allowing more output space may be appropriate; we did not rerun these outputs with different settings.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For your own task, judge three things separately: whether the response is complete, whether the code passes useful checks, and whether review finds gaps those checks missed. Passing twelve function checks did not make any of the truncated two-file responses a completed delivery.<\/p>\n\n\n\n<h2 id=\"model-cost\" class=\"wp-block-heading\">What model choice changes about cost<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Claude Code is the coding tool; Haiku, Sonnet, Opus, and Fable are model choices inside the supported environment. The way you authenticate and pay is another choice. Changing the model does not turn a subscription into an API account or make every usage limit disappear.<\/p>\n\n\n\n<figure class=\"wp-block-table\" style=\"overflow-x:auto;margin:24px 0;border:1px solid #d7dfed;border-radius:8px;box-sizing:border-box;max-width:100%\"><table style=\"width:100%;min-width:640px;border-collapse:collapse;font:15px\/1.6 system-ui,sans-serif\"><thead><tr><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">Billing route<\/th><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">Yang patut ditonton<\/th><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">How to interpret the model choice<\/th><\/tr><\/thead><tbody><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Claude subscription access<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Included plan usage and any separately enabled usage credits<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Different models can consume allowances differently; check the plan\u2019s available models and limits<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Anthropic API access<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Input\/output tokens, caching, and applicable API charges<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Use the current rate card and actual usage, then confirm charges in the billing console<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Cloud provider or gateway<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Your provider\u2019s supported IDs, rates, and billing records<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">An Anthropic list-price example may not equal the amount your provider charges<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\" style=\"font-size:14px;line-height:1.6;color:#52617a;padding:12px\">Model selection and billing are related, but the billing route determines how usage is charged.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In Claude Code, <code>\/penggunaan<\/code> shows session token information and, where applicable, subscription usage bars. Its dollar figure is a locally computed estimate based on list or configured rates; it is not an invoice. For Pro and Max subscribers, that session figure does not mean an extra API bill was added to the subscription. Read more about <a href=\"https:\/\/www.glbgpt.com\/hub\/claude-code-pricing\/\">Claude Code pricing and billing routes<\/a> if you are deciding how to pay.<\/p>\n\n\n\n<h3 id=\"api-price-example\" class=\"wp-block-heading\">Current API prices and an equal-token example<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Anthropic\u2019s normal base rates per million input\/output tokens are <strong>Haiku 4.5: $1\/$5; Sonnet 5: $2\/$10; Opus 5.5: $4\/$20; Fable 5.1: $10\/$50<\/strong>, checked September 28, 2026. The following chart holds token volume constant so the arithmetic is easy to compare.<\/p>\n\n\n\n<style>\n.ccms-cost{box-sizing:border-box;border:1px solid #d8dfeb;border-radius:8px;padding:24px;background:#f8faff;color:#182439;margin:28px 0;font:16px\/1.6 system-ui,sans-serif}.ccms-cost *{box-sizing:border-box}.ccms-cost h3{color:#182439;font-size:1.3rem;line-height:1.3;margin:0 0 8px}.ccms-cost p{color:#34435d;margin:10px 0}.ccms-cost a{color:#254fc2;text-decoration:underline}.ccms-cost__rows{display:grid;gap:16px;margin:22px 0}.ccms-cost__row{display:grid;grid-template-columns:100px 1fr 55px;gap:12px;align-items:center}.ccms-cost__track{background:#e2e8f2;height:18px;border-radius:4px;overflow:hidden}.ccms-cost__bar{display:block;height:100%;background:#5460c9}.ccms-cost__value{text-align:right;font-variant-numeric:tabular-nums}.ccms-cost__table{overflow-x:auto}.ccms-cost table{border-collapse:collapse;width:100%;min-width:460px;color:#182439;font-size:14px}.ccms-cost th,.ccms-cost td{padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb}.ccms-cost th{color:#182439;background:#edf1fa}.ccms-cost__note{font-size:14px}.ccms-cost summary{cursor:pointer;font-weight:600;color:#254fc2}.ccms-cost details{margin:16px 0 0}@media(max-width:520px){.ccms-cost{padding:16px}.ccms-cost__row{grid-template-columns:85px 1fr 48px;gap:8px}}\n<\/style>\n<section class=\"ccms-cost\" aria-labelledby=\"ccms-cost-title\" style=\"box-sizing:border-box;border:1px solid #d8dfeb;border-radius:8px;padding:24px;background:#f8faff;color:#182439;margin:28px 0;font:16px\/1.6 system-ui,sans-serif;max-width:100%\">\n  <h3 id=\"ccms-cost-title\" style=\"box-sizing:border-box;color:#182439;font-size:1.3rem;line-height:1.3;margin:0 0 8px\">The same token volume, four different API costs<\/h3>\n  <p style=\"box-sizing:border-box;color:#34435d;margin:10px 0\">Contoh: <strong style=\"box-sizing:border-box\">100,000 uncached input tokens + 10,000 output tokens<\/strong>, using Anthropic&#8217;s normal API list prices checked September 28, 2026.<\/p>\n  <div class=\"ccms-cost__rows\" aria-label=\"Base API cost for the example token volume\" style=\"box-sizing:border-box;display:grid;gap:16px;margin:22px 0;max-width:100%\">\n    <div class=\"ccms-cost__row\" style=\"box-sizing:border-box;display:grid;grid-template-columns:100px 1fr 55px;gap:12px;align-items:center;max-width:100%\"><span style=\"box-sizing:border-box\">Haiku 4.5<\/span><span class=\"ccms-cost__track\" aria-hidden=\"true\" style=\"box-sizing:border-box;background:#e2e8f2;height:18px;border-radius:4px;overflow:hidden\"><span class=\"ccms-cost__bar\" style=\"box-sizing:border-box;display:block;height:100%;background:#5460c9;width:10%\"><\/span><\/span><strong class=\"ccms-cost__value\" style=\"box-sizing:border-box;text-align:right;font-variant-numeric:tabular-nums\">$0.15<\/strong><\/div>\n    <div class=\"ccms-cost__row\" style=\"box-sizing:border-box;display:grid;grid-template-columns:100px 1fr 55px;gap:12px;align-items:center;max-width:100%\"><span style=\"box-sizing:border-box\">Soneta 5<\/span><span class=\"ccms-cost__track\" aria-hidden=\"true\" style=\"box-sizing:border-box;background:#e2e8f2;height:18px;border-radius:4px;overflow:hidden\"><span class=\"ccms-cost__bar\" style=\"box-sizing:border-box;display:block;height:100%;background:#5460c9;width:20%\"><\/span><\/span><strong class=\"ccms-cost__value\" style=\"box-sizing:border-box;text-align:right;font-variant-numeric:tabular-nums\">$0.30<\/strong><\/div>\n    <div class=\"ccms-cost__row\" style=\"box-sizing:border-box;display:grid;grid-template-columns:100px 1fr 55px;gap:12px;align-items:center;max-width:100%\"><span style=\"box-sizing:border-box\">Opus 5.5<\/span><span class=\"ccms-cost__track\" aria-hidden=\"true\" style=\"box-sizing:border-box;background:#e2e8f2;height:18px;border-radius:4px;overflow:hidden\"><span class=\"ccms-cost__bar\" style=\"box-sizing:border-box;display:block;height:100%;background:#5460c9;width:40%\"><\/span><\/span><strong class=\"ccms-cost__value\" style=\"box-sizing:border-box;text-align:right;font-variant-numeric:tabular-nums\">$0.60<\/strong><\/div>\n    <div class=\"ccms-cost__row\" style=\"box-sizing:border-box;display:grid;grid-template-columns:100px 1fr 55px;gap:12px;align-items:center;max-width:100%\"><span style=\"box-sizing:border-box\">Fable 5.1<\/span><span class=\"ccms-cost__track\" aria-hidden=\"true\" style=\"box-sizing:border-box;background:#e2e8f2;height:18px;border-radius:4px;overflow:hidden\"><span class=\"ccms-cost__bar\" style=\"box-sizing:border-box;display:block;height:100%;background:#5460c9;width:100%\"><\/span><\/span><strong class=\"ccms-cost__value\" style=\"box-sizing:border-box;text-align:right;font-variant-numeric:tabular-nums\">$1.50<\/strong><\/div>\n  <\/div>\n  <details style=\"box-sizing:border-box;margin:16px 0 0\"><summary style=\"box-sizing:border-box;cursor:pointer;font-weight:600;color:#254fc2\">View the rates and calculation<\/summary>\n    <div class=\"ccms-cost__table\" style=\"box-sizing:border-box;overflow-x:auto;max-width:100%\"><table style=\"box-sizing:border-box;border-collapse:collapse;width:100%;min-width:460px;color:#182439;font-size:14px\"><caption style=\"box-sizing:border-box\">USD per million tokens and the calculated example<\/caption><thead style=\"box-sizing:border-box\"><tr style=\"box-sizing:border-box\"><th scope=\"col\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Model<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Masukan \/ 1M<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Keluaran \/ 1M<\/th><th scope=\"col\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Contoh total<\/th><\/tr><\/thead><tbody style=\"box-sizing:border-box\">\n      <tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Haiku 4.5<\/th><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$1<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$5<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$0.15<\/td><\/tr>\n      <tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Soneta 5<\/th><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$2<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$10<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$0.30<\/td><\/tr>\n      <tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Opus 5.5<\/th><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$4<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$20<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$0.60<\/td><\/tr>\n      <tr style=\"box-sizing:border-box\"><th scope=\"row\" style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb;color:#182439;background:#edf1fa\">Fable 5.1<\/th><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$10<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$50<\/td><td style=\"box-sizing:border-box;padding:10px 8px;text-align:left;border-bottom:1px solid #d8dfeb\">$1.50<\/td><\/tr>\n    <\/tbody><\/table><\/div>\n    <p style=\"box-sizing:border-box;color:#34435d;margin:10px 0\">Calculation: 0.1 \u00d7 input rate + 0.01 \u00d7 output rate. For Opus 5.5: 0.1 \u00d7 $4 + 0.01 \u00d7 $20 = $0.60.<\/p>\n  <\/details>\n  <p class=\"ccms-cost__note\" style=\"box-sizing:border-box;font-size:14px;color:#34435d;margin:10px 0\">This is a fixed-token illustration. Actual tasks consume different token totals; cache writes and reads, retries, tools, provider billing, and subscription limits need separate accounting.<\/p>\n  <p class=\"ccms-cost__note\" style=\"box-sizing:border-box;font-size:14px;color:#34435d;margin:10px 0\">Sumber: <a href=\"https:\/\/platform.claude.com\/docs\/en\/about-claude\/pricing#model-pricing\" style=\"box-sizing:border-box;color:#254fc2;text-decoration:underline\">Harga API Anthropic<\/a>.<\/p>\n<\/section>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1440\" height=\"625\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-api-pricing-20260928_aa929ac5f992491abf410216b0d17992.webp\" alt=\"Anthropic's API pricing table with input, output, and prompt-cache rates.\" class=\"wp-image-20173\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-api-pricing-20260928_aa929ac5f992491abf410216b0d17992.webp 1440w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-api-pricing-20260928_aa929ac5f992491abf410216b0d17992-300x130.webp 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-api-pricing-20260928_aa929ac5f992491abf410216b0d17992-1024x444.webp 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-api-pricing-20260928_aa929ac5f992491abf410216b0d17992-768x333.webp 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/09\/claude-api-pricing-20260928_aa929ac5f992491abf410216b0d17992-18x8.webp 18w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><figcaption class=\"wp-element-caption\">Normal API list prices are quoted per million tokens; cache writes and reads have separate rates.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A real Claude Code task is a sequence of requests. Earlier context may be sent again, a model may investigate further, and tools or additional agents can create more work. Prompt caching also has distinct write and read rates. The lowest bar in the example therefore does not establish the lowest cost per accepted change.<\/p>\n\n\n\n<h3 id=\"cost-strategies\" class=\"wp-block-heading\">Five ways to control cost without weakening the task<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Define acceptance before choosing a model.<\/strong> Supply expected behavior, edge cases, and the existing constraints. A clear small task is easier to delegate economically and easier to review.<\/li>\n\n\n\n<li><strong>Provide relevant context.<\/strong> Include the files and failure details the model needs. For unrelated work, start a fresh conversation rather than carrying a long history forward merely because it exists.<\/li>\n\n\n\n<li><strong>Distinguish capability from effort.<\/strong> Anthropic recommends starting with the model\u2019s default effort. If it read the right context and still could not solve the problem, a stronger model may help. If it skipped reading or verification, inspect the task setup and effort choice.<\/li>\n\n\n\n<li><strong>Budget for the whole answer.<\/strong> Source code, tests, and explanation all need output room. Our second task shows why a complete function alone is not proof that the requested delivery fit the budget.<\/li>\n\n\n\n<li><strong>Compare accepted work.<\/strong> Record useful output, retries, review time, and actual billing data over representative tasks. Keep provider errors separate from model-quality failures.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">These strategies align with the <a href=\"https:\/\/code.claude.com\/docs\/en\/costs\">official cost guide<\/a> dan <a href=\"https:\/\/claude.com\/blog\/claude-model-and-effort-level-in-claude-code\">Anthropic\u2019s model-and-effort guidance<\/a>. A plan-wide weekly or session limit can remain in force after a model switch; a model-specific limit is a different situation. Check the actual limit before switching repeatedly.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your work spans code, research, writing, and media, also compare the workflow you are paying for. <a href=\"https:\/\/www.glbgpt.com\/home?inviter=hub_content_home&amp;login=1\">Ruang kerja multi-model GlobalGPT<\/a> brings those functions into one dashboard with CLI access for development tasks. That broader workflow value is useful to weigh alongside a metered API route; the API chart above is not a GlobalGPT subscription price list.<\/p>\n\n\n\n<h2 id=\"troubleshooting\" class=\"wp-block-heading\">Why your selected model may not stick<\/h2>\n\n\n\n<figure class=\"wp-block-table\" style=\"overflow-x:auto;margin:24px 0;border:1px solid #d7dfed;border-radius:8px;box-sizing:border-box;max-width:100%\"><table style=\"width:100%;min-width:640px;border-collapse:collapse;font:15px\/1.6 system-ui,sans-serif\"><thead><tr><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">Gejala<\/th><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">Likely check<\/th><th scope=\"col\" style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#172438;background:#edf1fa\">Langkah praktis selanjutnya<\/th><\/tr><\/thead><tbody><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The next session uses the old model<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The switch may have been session-only<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Use the picker\u2019s Enter action to save, then check a new session<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The preference is saved but a different model starts<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">A launch, shell, project, managed, or organization setting may take priority<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Read the startup information and inspect the relevant configuration with its owner<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">A resumed conversation has a different model<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The saved session may restore its previous model<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Check \/status; choose the intended model deliberately for the resumed work<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The model is missing or rejected<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Provider availability, organization rules, or an old Claude Code version<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Check the supported model IDs, account access, and version requirement<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The same family name resolves differently elsewhere<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Aliases and provider mappings differ<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Use the correct full ID for the provider when a release must stay fixed<\/td><\/tr><tr><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Switching does not clear a usage limit<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">The limit may apply to the whole plan<\/td><td style=\"padding:12px;border-bottom:1px solid #d7dfed;text-align:left;vertical-align:top;color:#23334c\">Read the usage message and reset period rather than assuming a family switch is sufficient<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\" style=\"font-size:14px;line-height:1.6;color:#52617a;padding:12px\">Diagnose the scope of the problem before changing another setting.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If Claude Code cannot write your user settings, an interactive choice can last for the current session without persisting. A managed or generated settings file may need its owner\u2019s change rather than another picker attempt. Avoid removing organizational restrictions merely to make an option appear.<\/p>\n\n\n\n<h2 id=\"globalgpt-workflow\" class=\"wp-block-heading\">Build a broader workflow with GlobalGPT<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Model selection is one part of the workflow. You may need to research a library, draft a function, explain a change to a teammate, create documentation, and prepare visual assets. GlobalGPT combines multiple leading models and AI functions in one affordable workspace, so those tasks can live in the same dashboard.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img alt=\"\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"547\" src=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/image-15-1024x547.png\" class=\"wp-image-16961\" srcset=\"https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/image-15-1024x547.png 1024w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/image-15-300x160.png 300w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/image-15-768x410.png 768w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/image-15-1536x820.png 1536w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/image-15-2048x1094.png 2048w, https:\/\/wp.glbgpt.com\/wp-content\/uploads\/2026\/07\/image-15-18x10.png 18w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-3e41869c wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.glbgpt.com\/home\/cli?inviter=hub_content_cli&amp;login=1\">Coba GlobalGPT CLI<\/a><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">For terminal work, the <a href=\"https:\/\/www.glbgpt.com\/home\/cli\">GlobalGPT CLI<\/a> connects the platform\u2019s tools to development environments. Its documented setup uses your GlobalGPT account login and normal account balance. The CLI can support a broader coding-and-creation workflow while Claude Code\u2019s own model remains a deliberate choice through its model controls.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, draft and review an implementation, use another model for a concise explanation, then produce the documentation or assets that accompany the release. Follow the guide to <a href=\"https:\/\/www.glbgpt.com\/hub\/how-to-use-globalgpt-cli-in-claude-code\/\">Hubungkan CLI GlobalGPT ke Kode Claude<\/a> when you want that tool integration. Set your Claude Code reasoning model separately according to the coding task.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Choose a starting model, write down the checks that define success, and move up when the task demands it. Review the complete delivery before calling the work done. <a href=\"https:\/\/www.glbgpt.com\/home?inviter=hub_content_home&amp;login=1\">Build your workflow with GlobalGPT<\/a> when you want model choice, research, coding, and creative tools connected across your everyday work.<\/p>\n\n\n\n<h2 id=\"faq\" class=\"wp-block-heading\">PERTANYAAN YANG SERING DIAJUKAN<\/h2>\n\n\n\n<h3 id=\"faq-1\" class=\"wp-block-heading\">How do I change the model in Claude Code?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run \/model to open the picker. Press s to switch only the current session, or Enter to save the selected model as your default. To choose a model for a single new session, launch with claude &#8211;model followed by the model name.<\/p>\n\n\n\n<h3 id=\"faq-2\" class=\"wp-block-heading\">Does \/model change my saved default?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In current interactive versions, selecting a model with Enter or typing \/model sonnet saves the choice in user settings when writable. Pressing s in the picker is session-only. Other settings can still take priority on the next launch.<\/p>\n\n\n\n<h3 id=\"faq-3\" class=\"wp-block-heading\">What is the default Claude Code model?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The runtime default depends on your account, provider, and configuration. The default value clears a model override; it is not one fixed model ID. Check the active model with \/status and inspect the picker rather than assuming every account starts on the same release.<\/p>\n\n\n\n<h3 id=\"faq-4\" class=\"wp-block-heading\">What does opusplan do?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It uses Opus during plan mode and Sonnet during execution. It follows the mode transition rather than automatically choosing the cheapest model for each prompt. Actual cost depends on the work performed in each phase.<\/p>\n\n\n\n<h3 id=\"faq-5\" class=\"wp-block-heading\">Why is a model missing from the picker?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Availability can depend on your provider, account, organization restrictions, and Claude Code version. Check the current model documentation and your environment\u2019s allowed models. A family alias can also resolve to a different release on another provider.<\/p>\n\n\n\n<h3 id=\"faq-6\" class=\"wp-block-heading\">Does a cheaper model always make a task cheaper?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. Token price is only one factor. Total usage, incomplete answers, retries, and review effort affect the cost of an acceptable change. In our small refactor all three functions passed, while all three larger two-file responses were truncated at the shared output limit.<\/p>\n\n\n\n<h2 id=\"sources\" class=\"wp-block-heading\">Sumber<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/code.claude.com\/docs\/en\/model-config\">Claude Code model configuration<\/a> \u2014 model selection, defaults, aliases, provider differences, and opusplan.<\/li>\n\n\n\n<li><a href=\"https:\/\/code.claude.com\/docs\/en\/costs\">Claude Code costs<\/a> \u2014 usage estimates, subscription allowances, caching, and cost controls.<\/li>\n\n\n\n<li><a href=\"https:\/\/platform.claude.com\/docs\/en\/about-claude\/models\/overview\">Gambaran Umum Model Anthropic<\/a> dan <a href=\"https:\/\/platform.claude.com\/docs\/en\/about-claude\/pricing\">Harga API<\/a> \u2014 current model specifications and list prices.<\/li>\n\n\n\n<li><a href=\"https:\/\/claude.com\/blog\/claude-model-and-effort-level-in-claude-code\">Model and effort guidance<\/a> \u2014 practical differences between capability, context, and effort.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.glbgpt.com\/home\/cli\">GlobalGPT CLI documentation<\/a> \u2014 terminal workflow and account-based setup.<\/li>\n<\/ul>\n\n\n\n<script type=\"application\/ld+json\">{\n    \"@context\": \"https:\\\/\\\/schema.org\",\n    \"@type\": \"FAQPage\",\n    \"mainEntity\": [\n        {\n            \"@type\": \"Question\",\n            \"name\": \"How do I change the model in Claude Code?\",\n            \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Run \\\/model to open the picker. Press s to switch only the current session, or Enter to save the selected model as your default. To choose a model for a single new session, launch with claude --model followed by the model name.\"\n            }\n        },\n        {\n            \"@type\": \"Question\",\n            \"name\": \"Does \\\/model change my saved default?\",\n            \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"In current interactive versions, selecting a model with Enter or typing \\\/model sonnet saves the choice in user settings when writable. Pressing s in the picker is session-only. Other settings can still take priority on the next launch.\"\n            }\n        },\n        {\n            \"@type\": \"Question\",\n            \"name\": \"What is the default Claude Code model?\",\n            \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"The runtime default depends on your account, provider, and configuration. The default value clears a model override; it is not one fixed model ID. Check the active model with \\\/status and inspect the picker rather than assuming every account starts on the same release.\"\n            }\n        },\n        {\n            \"@type\": \"Question\",\n            \"name\": \"What does opusplan do?\",\n            \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"It uses Opus during plan mode and Sonnet during execution. It follows the mode transition rather than automatically choosing the cheapest model for each prompt. Actual cost depends on the work performed in each phase.\"\n            }\n        },\n        {\n            \"@type\": \"Question\",\n            \"name\": \"Why is a model missing from the picker?\",\n            \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Availability can depend on your provider, account, organization restrictions, and Claude Code version. Check the current model documentation and your environment\\u2019s allowed models. A family alias can also resolve to a different release on another provider.\"\n            }\n        },\n        {\n            \"@type\": \"Question\",\n            \"name\": \"Does a cheaper model always make a task cheaper?\",\n            \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"No. Token price is only one factor. Total usage, incomplete answers, retries, and review effort affect the cost of an acceptable change. In our small refactor all three functions passed, while all three larger two-file responses were truncated at the shared output limit.\"\n            }\n        }\n    ]\n}<\/script>","protected":false},"excerpt":{"rendered":"<p>For Claude Code model selection, use Haiku for small, testable changes, Sonnet for routine implementation, and Opus for work with greater ambiguity or reasoning demands. Anthropic currently recommends Opus 5.5 as a broad starting point; your task, review burden, and budget determine whether a smaller model is a better fit. To change models, open \/model. [&hellip;]<\/p>","protected":false},"author":7,"featured_media":20168,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_seopress_robots_primary_cat":"","_seopress_titles_title":"Claude Code Model Selection: Defaults, Switching, and Cost","_seopress_titles_desc":"Choose a Claude Code model for your task, set a default, switch for one session, and compare current API costs with practical coding examples.","_seopress_robots_index":"","footnotes":""},"categories":[7],"tags":[],"class_list":["post-20166","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-chat"],"acf":[],"_links":{"self":[{"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/posts\/20166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/comments?post=20166"}],"version-history":[{"count":2,"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/posts\/20166\/revisions"}],"predecessor-version":[{"id":20174,"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/posts\/20166\/revisions\/20174"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/media\/20168"}],"wp:attachment":[{"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/media?parent=20166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/categories?post=20166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp.glbgpt.com\/id\/wp-json\/wp\/v2\/tags?post=20166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}