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 /모델. Press 입력 to save a default, or s to switch only the current session. For a single launch, use claude --model opus. Those choices have different persistence, so deciding how long the switch should last matters as much as choosing the model.
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. Build your workflow with GlobalGPT to keep those related tasks together as you move from an idea to working code.

Which model should you use in Claude Code?
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.
| 현재 모델 | What it is positioned for | A practical starting task |
|---|---|---|
| 클로드 하이쿠 4.5 | Fast, efficient work with a narrow contract | A small refactor, repetitive transformation, or straightforward test case |
| 클로드 소네트 5 | A balance of intelligence and speed for daily coding | A feature with established patterns, a routine bug fix, or code explanation |
| Claude Opus 5.5 | Complex reasoning and longer agentic coding work | An ambiguous failure, architecture tradeoff, or change with interacting constraints |
| Claude Fable 5.1 | The hardest and longest-running investigations | An escalation when difficult work still defeats a stronger Opus effort level |
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.
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, compare the Claude model families.

그리고 공식 모델 개요 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.
How to switch models for one session
Inside an interactive session, run /모델 to open the model picker. Select the model row and press s if this is a one-off change. Pressing 입력 saves the selection as your user default. Typing /model sonnet directly also saves it in current versions.
Choose the command by how long the change should last
| 여러분의 목표 | 어떻게 해야 할까 | Saved default changes? |
|---|---|---|
| Switch only this interactive session | 열기 /모델, select a model, press s. | 아니요. |
| Save a preferred model | 열기 /모델 을 누르고 입력, or type /model sonnet. | Yes, when user settings are writable. |
| Start a single session on Opus | 시작 claude --model opus. | 아니요. |
| Return to the account’s runtime default | 사용 /model default. | Clears the model override; the resolved default can depend on account and organization settings. |
| Check the active model | 달리다 /상태. | 아니요. |
Project or managed settings, environment overrides, and resumed sessions can affect the next launch. Check the active model when reproducibility matters.
For a fresh terminal session, choose the model at startup. These commands also apply when Claude Code runs in VS Code’s integrated terminal. The examples select a release explicitly:
claude --model claude-opus-5-5
claude --model claude-sonnet-5Run the command for the session you want; the examples are alternatives. You can launch different terminals with different --모델 values without repeatedly changing a shared saved default. Use /상태 to check the active model.
Family names such as opus 그리고 sonnet 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.
Opus 5.5 requires Claude Code v2.1.280 or later; Sonnet 5 requires v2.1.197 or later. The model configuration documentation 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.

How to set a default model
For a personal default, select a model in /모델 을 누르고 입력, or type a selection such as /model sonnet. Claude Code writes the 모델 field in your user settings when that file is writable. Open a new session and check its active model to confirm the result.
A saved preference does not override every other setting. A startup flag, ANTHROPIC_MODEL 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 /상태 before assuming the choice was lost.
/model default clears your model override and returns to the runtime default for your account and configuration. The word default is a reset value, not the name of one fixed Claude model. It should not be used as a reproducible model identifier.
For advanced configuration, ANTHROPIC_DEFAULT_MODEL supplies a fallback starting choice from v2.1.236 onward. It sits below explicit launch, environment, settings, and organization selections, and ignores values including haiku 그리고 opusplan. For a normal personal preference, the picker is easier to verify. See Claude Code settings when a shared configuration is involved.
What opusplan actually does
opusplan 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.
Opusplan follows the working mode
Documented routing behavior. The versions behind these family names depend on your provider and configuration.
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.
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.
What two coding tasks showed
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.
How we tested the coding outputs
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’s model-switching instructions elsewhere in this guide come from its official documentation.
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’s routing task received one permitted retry: seven requests produced six outputs.
These two small tasks measure returned code and delivery completeness. They do not measure Claude Code’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.
View exact model IDs and evaluation conditions
Requested IDs: claude-haiku-4-5-20251001, 클로드-소네트-5, 및 클로드-작품 5-5. Local checks ran with Node.js v24.19.0. The prompts target Node.js 18+; Node.js 18 itself was not tested.
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.
Task 1: Preserve Unicode in a small slug refactor
The function had to retain non-Latin letters and combining marks, normalize decomposed accents, and preserve its existing ASCII behavior.
| 모델 | Behavior checks | Response format | Complete requested delivery |
|---|---|---|---|
| 클로드 하이쿠 4.5 | 8/8 | Fail: Markdown wrapper | Yes: complete function |
| 클로드 소네트 5 | 8/8 | Pass: raw JSON | Yes: complete function |
| Claude Opus 5.5 | 8/8 | Pass: raw JSON | Yes: complete function |
Observed result: 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.
For this narrow refactor, upgrading did not improve the tested function behavior. Format requirements and the accuracy of the accompanying explanation still needed review.
View the complete shared prompt and input code
SYSTEM
You 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.
USER
Implement 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.
Required behavior:
1. slugify(value) returns an empty string for every non-string input.
2. Normalize string input to Unicode NFC, then lowercase it using JavaScript toLowerCase().
3. Preserve Unicode letters, numbers, and combining marks. Replace each consecutive run of all other characters with one ASCII hyphen.
4. Trim leading and trailing hyphens. Preserve the CommonJS export { slugify }.
5. Existing ASCII behavior must continue to work. Examples: Hello, World! -> hello-world; two words -> two-words; null -> empty string.
6. Additional examples: Café déjà vu -> café-déjà-vu; decomposed Cafe\u0301 -> café; 中文 测试 42 -> 中文-测试-42; **hi___there** -> hi-there; only punctuation or whitespace -> empty string.
Current src/slugify.js:
```javascript
function slugify(value) {
if (typeof value !== "string") return "";
return value
.trim()
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
module.exports = { slugify };
```
Return exactly one JSON object with this shape:
{"files":{"src/slugify.js":"complete JavaScript source as a JSON string"},"review_notes":["at most four brief implementation or assumption notes"]}
No Markdown wrapper. You are returning code for someone else to evaluate locally; do not say that tests passed or that you ran them.
View Claude Haiku 4.5’s complete response as returned
```json
{
"files": {
"src/slugify.js": "function slugify(value) {\n if (typeof value !== \"string\") return \"\";\n \n // Normalize to NFC and lowercase\n const normalized = value.normalize(\"NFC\").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, \"-\");\n \n // Trim leading and trailing hyphens\n return slugged.replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };"
},
"review_notes": [
"Uses String.prototype.normalize(\"NFC\") to decompose composed characters like é into base+combining mark, then toLowerCase() applies to normalized string",
"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",
"Existing ASCII behavior is preserved: punctuation and whitespace are replaced with hyphens, then leading/trailing hyphens are trimmed",
"Non-string inputs return empty string as required; normalized decomposed characters (e.g., Cafe\\u0301) are handled correctly by NFC normalization"
]
}
```View Claude Sonnet 5’s complete response as returned
{"files":{"src/slugify.js":"function slugify(value) {\n if (typeof value !== \"string\") return \"\";\n return value\n .normalize(\"NFC\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };\n"},"review_notes":["Used Unicode property escapes (\\p{L}, \\p{N}, \\p{M}) with the u flag to preserve letters, numbers, and combining marks across scripts.","NFC normalization ensures decomposed sequences like Cafe + combining acute compose to café before lowercasing.","Runs of any other characters (punctuation, whitespace, symbols) collapse to a single hyphen, then leading/trailing hyphens are trimmed."]}View Claude Opus 5.5’s complete response as returned
{"files":{"src/slugify.js":"function slugify(value) {\n if (typeof value !== \"string\") return \"\";\n return value\n .normalize(\"NFC\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };\n"},"review_notes":["The input is normalized to NFC before lowercasing, so decomposed input like Cafe\\u0301 composes to café.","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.","The explicit trim() was removed because the final step strips leading and trailing hyphens, which covers surrounding whitespace.","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."]}Task 2: Repair a route selector and return its tests
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.
| 모델 | Behavior checks | Response format | Complete requested delivery |
|---|---|---|---|
| 클로드 하이쿠 4.5 | 12/12 on the complete function only | Fail: truncated JSON | No: test file cut off |
| 클로드 소네트 5 | 12/12 on the complete function only | Fail: truncated JSON | No: test file cut off |
| Claude Opus 5.5 | 12/12 on the complete function only | Fail: truncated JSON | No: test file cut off |
Observed result: 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.
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.
Additional code-review finding: an equal-root tie
After the fixed checks, we noticed that Haiku normalized /// to an empty string rather than /. A separate local check used two GET rules, with prefixes /// 그리고 /, targeting 먼저 그리고 second in that order. For /anything, the contract requires 먼저.
Haiku returned second; Sonnet and Opus returned 먼저. This additional check was prompted by code review and is separate from the twelve checks set before testing. It does not alter their scores.
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.
View the complete shared prompt and input code
SYSTEM
You 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.
USER
Repair 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.
Contract for chooseRoute(request, rules):
1. 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.
2. Before matching, remove the request path's query and fragment starting at the earliest ? or #. Do not URL-decode or collapse interior slashes.
3. Ignore invalid rules. A valid rule is a non-null, non-array object with method '*' or a nonempty ASCII-letter string, prefix a string starting with / containing neither ? nor #, and target a nonempty string.
4. Compare methods case-insensitively. Prefer any matching exact-method rule over all wildcard-method '*' rules, even if a wildcard has a longer prefix. Use wildcard rules only if no exact-method route matches the path.
5. 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.
6. 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.
7. Do not mutate the request, rules array, or rule objects, including order or prefix strings. Preserve module.exports = { chooseRoute }.
8. 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.
Current src/router.js:
```javascript
function chooseRoute(request, rules) {
if (!request || !Array.isArray(rules)) return null;
for (const rule of rules) {
if (request.method === rule.method && request.path.startsWith(rule.prefix)) {
return rule.target;
}
}
return null;
}
module.exports = { chooseRoute };
```
Existing regression cases (unchanged): rules [{method:'GET',prefix:'/api',target:'api'},{method:'GET',prefix:'/api/admin',target:'admin'}]; GET /api/users returns 'api'; POST /api/users returns null.
Return exactly one JSON object with this shape:
{"files":{"src/router.js":"complete JavaScript source as a JSON string","test/router-added.test.js":"complete JavaScript tests as a JSON string"},"review_notes":["at most four brief implementation or assumption notes"]}
No Markdown wrapper. You are returning code for someone else to evaluate locally; do not say you edited files, ran tests, or observed passing results.
View Claude Haiku 4.5’s complete response as returned
This is the entire response received. It ends mid-output because it reached the limit; missing content has not been filled in.
```json
{
"files": {
"src/router.js": "function chooseRoute(request, rules) {\n // Validate request\n if (request === null || Array.isArray(request) || typeof request !== 'object') {\n return null;\n }\n if (typeof request.method !== 'string' || request.method.length === 0 || !/^[a-zA-Z]+$/.test(request.method)) {\n return null;\n }\n if (typeof request.path !== 'string' || !request.path.startsWith('/')) {\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 !== 'object') {\n continue;\n }\n \n const method = rule.method;\n if (typeof method !== 'string' || (method !== '*' && (method.length === 0 || !/^[a-zA-Z]+$/.test(method)))) {\n continue;\n }\n \n const prefix = rule.prefix;\n if (typeof prefix !== 'string' || !prefix.startsWith('/') || prefix.includes('?') || prefix.includes('#')) {\n continue;\n }\n \n const target = rule.target;\n if (typeof target !== 'string' || 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 === '/' ? '/' : rule.prefix.replace(/\/+$/, '');\n \n const entry = {\n originalRule: rule,\n normalizedPrefix: normalizedPrefix,\n method: rule.method\n };\n \n if (rule.method === '*') {\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 === '/') {\n return true;\n }\n if (!path.startsWith(prefix)) {\n return false;\n }\n // Check segment boundary: next character must be '/' or end of string\n const nextChar = path[prefix.length];\n return nextChar === undefined || nextChar === '/';\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 > 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 > 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 };",
"test/router-added.test.js": "const test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router.js');\n\n// Regression: existing test cases\ntest('GET /api/users matches /api prefix (exact method)', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n { method: 'GET', prefix: '/api/admin', target: 'admin' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'api');\n});\n\ntest('POST /api/users returns null (no matching method)', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n { method: 'GET', prefix: '/api/admin', target: 'admin' }\n ];\n assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, rules), null);\n});\n\n// Invalid request handling\ntest('null request returns null', () => {\n assert.equal(chooseRoute(null, []), null);\n});\n\ntest('array request returns null', () => {\n assert.equal(chooseRoute([], []), null);\n});\n\ntest('request with missing method returns null', () => {\n assert.equal(chooseRoute({ path: '/api' }, []), null);\n});\n\ntest('request with empty method returns null', () => {\n assert.equal(chooseRoute({ method: '', path: '/api' }, []), null);\n});\n\ntest('request with non-letter method returns null', () => {\n assert.equal(chooseRoute({ method: 'GET-POST', path: '/api' }, []), null);\n});\n\ntest('request with numeric method returns null', () => {\n assert.equal(chooseRoute({ method: '123', path: '/api' }, []), null);\n});\n\ntest('request with missing path returns null', () => {\n assert.equal(chooseRoute({ method: 'GET' }, []), null);\n});\n\ntest('request with path not starting with / returns null', () => {\n assert.equal(chooseRoute({ method: 'GET', path: 'api' }, []), null);\n});\n\ntest('null rules returns null', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, null), null);\n});\n\ntest('non-array rules returns null', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, { method: 'GET' }), null);\n});\n\n// Query and fragment removal\ntest('query string is removed before matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users?foo=bar' }, rules), 'found');\n});\n\ntest('fragment is removed before matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users#section' }, rules), 'found');\n});\n\ntest('earliest ? or # is used as boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users?foo#bar' }, rules), 'found');\n});\n\ntest('fragment before query is used as boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users#foo?bar' }, rules), 'found');\n});\n\n// Segment boundary matching\ntest('prefix /api matches /api/users at segment boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('prefix /api does not match /apix (no segment boundary)', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n});\n\ntest('prefix /api matches /api exactly at segment boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('root / matches any valid path', () => {\n const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/anything/here' }, rules), 'root');\n});\n\ntest('root / matches /', () => {\n const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/' }, rules), 'root');\n});\n\n// Prefix normalization (trailing slash removal)\ntest('trailing slash is removed from prefix', () => {\n const rules = [{ method: 'GET', prefix: '/api/', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('multiple trailing slashes are removed', () => {\n const rules = [{ method: 'GET', prefix: '/api///', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('all-slash prefix normalizes to single /', () => {\n const rules = [{ method: 'GET', prefix: '///', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\n// Method case-insensitivity\ntest('method comparison is case-insensitive', () => {\n const rules = [{ method: 'get', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('request method case does not affect matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'get', path: '/api' }, rules), 'found');\n});\n\n// Exact-method vs wildcard precedence\ntest('exact-method rule preferred over wildcard with longer prefix', () => {\n const rules = [\n { method: '*', prefix: '/api/admin/users', target: 'wildcard' },\n { method: 'GET', prefix: '/api', target: 'exact' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/test' }, rules), 'exact');\n});\n\ntest('wildcard rule used when no exact-method matches', () => {\n const rules = [\n { method: '*', prefix: '/api', target: 'wildcard' },\n { method: 'GET', prefix: '/other', target: 'exact' }\n ];\n assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, rules), 'wildcard');\n});\n\n// Longest prefix matching\ntest('longest matching prefix is chosen', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'short' },\n { method: 'GET', prefix: '/api/admin', target: 'long' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/users' }, rules), 'long');\n});\n\n// Tie-breaking (first rule wins on equal prefix length)\ntest('first rule wins on equal prefix length', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'first' },\n { method: 'GET', prefix: '/api', target: 'second' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'first');\n});\n\n// Invalid rules are ignored\ntest('null rule is ignored', () => {\n const rules = [\n null,\n { method: 'GET', prefix: '/api', target: 'found' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('array rule is ignored', () => {\n const rules = [\n [],\n { method: 'GET', prefix: '/api', target: 'found' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('rule with invalid method is ignored', () => {\n const rules = [\n { method: '', prefix: '/api', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with non-letter method (if not wildcard) is ignored', () => {\n const rules = [\n { method: 'G3T', prefix: '/api', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with prefix not starting with / is ignored', () => {\n const rules = [\n { method: 'GET', prefix: 'api', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with query in prefix is ignored', () => {\n const rules = [\n { method: 'GET', prefix: '/api?foo=bar', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with fragment in prefix is ignored', () => {\n const rules = [\n { method: 'GET', prefix: '/api#section', target: View Claude Sonnet 5’s complete response as returned
This is the entire response received. It ends mid-output because it reached the limit; missing content has not been filled in.
{"files":{"src/router.js":"function isValidRequest(request) {\n return (\n request !== null &&\n typeof request === 'object' &&\n !Array.isArray(request) &&\n typeof request.method === 'string' &&\n request.method.length > 0 &&\n /^[A-Za-z]+$/.test(request.method) &&\n typeof request.path === 'string' &&\n request.path.startsWith('/')\n );\n}\n\nfunction isValidRule(rule) {\n if (rule === null || typeof rule !== 'object' || Array.isArray(rule)) {\n return false;\n }\n const { method, prefix, target } = rule;\n\n if (typeof method !== 'string') return false;\n if (method !== '*' && !(method.length > 0 && /^[A-Za-z]+$/.test(method))) {\n return false;\n }\n\n if (\n typeof prefix !== 'string' ||\n !prefix.startsWith('/') ||\n prefix.includes('?') ||\n prefix.includes('#')\n ) {\n return false;\n }\n\n if (typeof target !== 'string' || target.length === 0) return false;\n\n return true;\n}\n\nfunction normalizePrefix(prefix) {\n if (/^\/+$/.test(prefix)) return '/';\n return prefix.replace(/\/+$/, '');\n}\n\nfunction prefixMatches(normalizedPrefix, path) {\n if (normalizedPrefix === '/') return true;\n if (path === normalizedPrefix) return true;\n return path.startsWith(normalizedPrefix + '/');\n}\n\nfunction stripQueryAndFragment(path) {\n let cutIndex = path.length;\n for (let i = 0; i < path.length; i++) {\n const c = path[i];\n if (c === '?' || c === '#') {\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 < 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 === '*') {\n if (\n bestWildcard === null ||\n len > bestWildcard.len ||\n (len === bestWildcard.len && idx < 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 > bestExact.len ||\n (len === bestExact.len && idx < 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","test/router-added.test.js":"const test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router');\n\ntest('segment boundary: prefix matches at slash boundary only', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n ];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/apix' }, rules),\n null\n );\n});\n\ntest('root prefix matches every valid path', () => {\n const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/' }, rules), 'root');\n assert.equal(\n chooseRoute({ method: 'GET', path: '/anything/here' }, rules),\n 'root'\n );\n});\n\ntest('trailing slashes in rule prefix are normalized', () => {\n const rules = [{ method: 'GET', prefix: '/api///', target: 'api' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users' }, rules),\n 'api'\n );\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n});\n\ntest('all-slash prefix normalizes to /', () => {\n const rules = [{ method: 'GET', prefix: '////', target: 'root' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/whatever' }, rules),\n 'root'\n );\n});\n\ntest('query and fragment are stripped before matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'api' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users?x=1&y=2' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users#section' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users?x=1#frag' }, rules),\n 'api'\n );\n});\n\ntest('query/fragment stripping does not decode or collapse slashes', () => {\n const rules = [{ method: 'GET', prefix: '/a//b', target: 'weird' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/a//b?x=1' }, rules),View Claude Opus 5.5’s complete response as returned
This is the entire response received. It ends mid-output because it reached the limit; missing content has not been filled in.
{"files":{"src/router.js":"'use strict';\n\nconst LETTERS = /^[A-Za-z]+$/;\n\nfunction isPlainObject(value) {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isMethodName(value) {\n return typeof value === 'string' && value.length > 0 && LETTERS.test(value);\n}\n\nfunction stripQueryAndFragment(path) {\n const q = path.indexOf('?');\n const h = path.indexOf('#');\n let cut = -1;\n if (q !== -1 && 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 > 0 && prefix[end - 1] === '/') end -= 1;\n return end === 0 ? '/' : prefix.slice(0, end);\n}\n\nfunction prefixMatches(path, prefix) {\n if (prefix === '/') return true;\n return path === prefix || path.startsWith(prefix + '/');\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 !== 'string' || rawPath[0] !== '/') 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 < 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 === '*';\n if (!isWildcard && !isMethodName(ruleMethod)) continue;\n if (typeof prefix !== 'string' || prefix[0] !== '/') continue;\n if (prefix.indexOf('?') !== -1 || prefix.indexOf('#') !== -1) continue;\n if (typeof target !== 'string' || 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 > bestWildcard.length) bestWildcard = candidate;\n } else if (ruleMethod.toUpperCase() === upperMethod) {\n if (bestExact === null || candidate.length > 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","test/router-added.test.js":"'use strict';\n\nconst test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router.js');\n\nconst baseRules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n { method: 'GET', prefix: '/api/admin', target: 'admin' }\n];\n\ntest('existing regression cases still hold', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, baseRules), 'api');\n assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, baseRules), null);\n});\n\ntest('longest prefix wins within method group', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/x' }, baseRules), 'admin');\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin' }, baseRules), 'admin');\n});\n\ntest('segment boundaries', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'api' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/api/' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/ap' }, rules), null);\n});\n\ntest('trailing slashes in prefixes are normalized, all-slash is root', () => {\n const rules = [{ method: 'GET', prefix: '/api///', target: 'api' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n const rootRules = [{ method: 'GET', prefix: '///', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/' }, rootRules), 'root');\n assert.equal(chooseRoute({ method: 'GET', path: '/anything/else' }, rootRules), 'root');\n assert.equal(chooseRoute({ method: 'GET', path: '/x' }, [{ method: 'GET', prefix: '/', target: 'r' }]), 'r');\n});\n\ntest('query and fragment are removed at earliest ? or #', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api?next=/api/admin' }, baseRules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/api#/admin' }, baseRules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/apix?/api' }, baseRules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin#frag?q' }, baseRules), 'admin');\n assert.equal(chooseRoute({ method: 'GET', path: '/api?q#/admin' }, baseRules), 'api');\n});\n\ntest('no URL decoding and no slash collapsing', () => {\n const rules = [{ method: 'GET', prefix: '/api/admin', target: 'admin' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api%2Fadmin' }, rules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/api//admin' }, rules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/api//admin' }, baseRules), 'api');\n});\n\ntest('methods compare case-insensitively', () => {\n const rules = [{ method: 'get', prefix: '/a', target: 'lower' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/a' }, rules), 'lower');\n assert.equal(chooseRoute({ method: 'gEt', path: '/a/b' }, rules), 'lower');\n});\n\ntest('exact method beats longer wildcard; wildcard used only as fallback', () => {\n const rules = [\n { method: '*', prefix: '/api/admin', target: 'wild-admin' },\n { method: 'GET', prefix: '/', target: 'get-root' },\n { method: 'POST', prefix: '/other', target: 'post-other' },\n { method: '*', prefix: '/api', target: 'wild-api' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/x' }, rules), 'get-root');\n assert.equal(chooseRoute({ method: 'POST', path: '/api/admin/x' }, rules), 'wild-admin');\n assert.equal(chooseRoute({ method: 'POST', path: '/api/x' }, rules), 'wild-api');\n assert.equal(chooseRoute({ method: 'POST', path: '/other/1' }, rules), 'post-other');\n assert.equal(chooseRoute({ method: 'PUT', path: '/nothing' }, rules), null);\n});\n\ntest('ties go to earlier rule in input order', () => {\n const rules = [\n { method: 'GET', prefThe 4,096-token ceiling was the output budget chosen for this test, not any model’s 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.
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.
What model choice changes about cost
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.
| Billing route | 볼거리 | How to interpret the model choice |
|---|---|---|
| Claude subscription access | Included plan usage and any separately enabled usage credits | Different models can consume allowances differently; check the plan’s available models and limits |
| Anthropic API access | Input/output tokens, caching, and applicable API charges | Use the current rate card and actual usage, then confirm charges in the billing console |
| Cloud provider or gateway | Your provider’s supported IDs, rates, and billing records | An Anthropic list-price example may not equal the amount your provider charges |
In Claude 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 Claude Code pricing and billing routes if you are deciding how to pay.
Current API prices and an equal-token example
Anthropic’s normal base rates per million input/output tokens are Haiku 4.5: $1/$5; Sonnet 5: $2/$10; Opus 5.5: $4/$20; Fable 5.1: $10/$50, checked September 28, 2026. The following chart holds token volume constant so the arithmetic is easy to compare.
The same token volume, four different API costs
예시: 100,000 uncached input tokens + 10,000 output tokens, using Anthropic’s normal API list prices checked September 28, 2026.
View the rates and calculation
| 모델 | 입력 / 1m | 출력 / 1m | 예시 합계 |
|---|---|---|---|
| 하이쿠 4.5 | $1 | $5 | $0.15 |
| 소네트 5 | $2 | $10 | $0.30 |
| 작품 5.5 | $4 | $20 | $0.60 |
| Fable 5.1 | $10 | $50 | $1.50 |
Calculation: 0.1 × input rate + 0.01 × output rate. For Opus 5.5: 0.1 × $4 + 0.01 × $20 = $0.60.
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.
Source: Anthropic API 가격.

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.
Five ways to control cost without weakening the task
- Define acceptance before choosing a model. Supply expected behavior, edge cases, and the existing constraints. A clear small task is easier to delegate economically and easier to review.
- Provide relevant context. 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.
- Distinguish capability from effort. Anthropic recommends starting with the model’s 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.
- Budget for the whole answer. 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.
- Compare accepted work. Record useful output, retries, review time, and actual billing data over representative tasks. Keep provider errors separate from model-quality failures.
These strategies align with the official cost guide 그리고 Anthropic’s model-and-effort guidance. 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.
If your work spans code, research, writing, and media, also compare the workflow you are paying for. GlobalGPT의 다중 모델 작업 공간 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.
Why your selected model may not stick
| 증상 | Likely check | 실질적인 다음 단계 |
|---|---|---|
| The next session uses the old model | The switch may have been session-only | Use the picker’s Enter action to save, then check a new session |
| The preference is saved but a different model starts | A launch, shell, project, managed, or organization setting may take priority | Read the startup information and inspect the relevant configuration with its owner |
| A resumed conversation has a different model | The saved session may restore its previous model | Check /status; choose the intended model deliberately for the resumed work |
| The model is missing or rejected | Provider availability, organization rules, or an old Claude Code version | Check the supported model IDs, account access, and version requirement |
| The same family name resolves differently elsewhere | Aliases and provider mappings differ | Use the correct full ID for the provider when a release must stay fixed |
| Switching does not clear a usage limit | The limit may apply to the whole plan | Read the usage message and reset period rather than assuming a family switch is sufficient |
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’s change rather than another picker attempt. Avoid removing organizational restrictions merely to make an option appear.
Build a broader workflow with GlobalGPT
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.

For terminal work, the GlobalGPT CLI connects the platform’s 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’s own model remains a deliberate choice through its model controls.
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 GlobalGPT CLI를 Claude 코드에 연결 when you want that tool integration. Set your Claude Code reasoning model separately according to the coding task.
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. Build your workflow with GlobalGPT when you want model choice, research, coding, and creative tools connected across your everyday work.
자주 묻는 질문
How do I change the model in Claude Code?
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.
Does /model change my saved default?
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.
What is the default Claude Code model?
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.
What does opusplan do?
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.
Why is a model missing from the picker?
Availability can depend on your provider, account, organization restrictions, and Claude Code version. Check the current model documentation and your environment’s allowed models. A family alias can also resolve to a different release on another provider.
Does a cheaper model always make a task cheaper?
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.
출처
- Claude Code model configuration — model selection, defaults, aliases, provider differences, and opusplan.
- Claude Code costs — usage estimates, subscription allowances, caching, and cost controls.
- Anthropic 모델 개요 그리고 API 가격 — current model specifications and list prices.
- Model and effort guidance — practical differences between capability, context, and effort.
- GlobalGPT CLI documentation — terminal workflow and account-based setup.



