Welcome to the heart of our application!
In the previous chapter, Interactive vs. Headless Modes, we learned that our CLI has two "faces": one for humans (Interactive) and one for robots (Headless).
However, a face is useless without a brain. This chapter introduces The Core Workflow Engine. This is the shared brain that makes decisions, performs checks, and tells the interface what to do next.
Imagine you are a Navigator in a rally car.
You are the Navigator. You hold the map. It doesn't matter who is driving; your job is to look at the road, check the map, and give a clear instruction: "Turn Left" or "Stop."
In our project, the runExtraUsage() function is the Navigator. It doesn't draw buttons or print text to the console. It simply calculates the situation and returns a Result Object containing instructions.
When a user runs extra-usage, we need to handle two very different scenarios based on who the user is:
The Core Engine figures out which scenario applies.
The Engine never speaks directly to the user. It returns a standardized object. This decouples the "What" (Logic) from the "How" (Display).
type ExtraUsageResult =
| { type: 'message'; value: string }
| { type: 'browser-opened'; url: string; opened: boolean }
browser-opened: The Engine decided the best action was to send the user to the web dashboard.message: The Engine performed an action internally (like sending an email to an admin) and just needs to tell the user what happened.The logic inside the engine follows a strict hierarchy:
Let's walk through extra-usage-core.ts.
Before making decisions, we ensure we have the freshest data.
export async function runExtraUsage(): Promise<ExtraUsageResult> {
// 1. Mark that the user has tried this feature
if (!getGlobalConfig().hasVisitedExtraUsage) {
saveGlobalConfig(prev => ({ ...prev, hasVisitedExtraUsage: true }))
}
// 2. Clear old permission data to force a fresh check
invalidateOverageCreditGrantCache()
Explanation: We flag that the user has used this command (useful for onboarding tips later). Then, we invalidate the cache. This is like refreshing your browser page to make sure you aren't looking at yesterday's stock prices.
We gather the user's details.
// 3. Get subscription level and billing power
const subscriptionType = getSubscriptionType()
const isTeamOrEnterprise =
subscriptionType === 'team' || subscriptionType === 'enterprise'
const hasBillingAccess = hasClaudeAiBillingAccess()
Explanation:
isTeamOrEnterprise: Are they part of an organization?hasBillingAccess: Do they have the authority to spend money?If the user is on a Team but cannot pay, we enter the complex logic. We need to help them ask for permission.
if (!hasBillingAccess && isTeamOrEnterprise) {
// Check if they already have unlimited usage
const utilization = await fetchUtilization()
if (utilization?.extra_usage?.is_enabled && utilization.extra_usage.monthly_limit === null) {
return { type: 'message', value: 'You already have unlimited usage.' }
}
// ... (More checks on creating requests) ...
Explanation: Before letting them bug their boss, we check: "Do you actually need this?" If they already have unlimited usage, we return a message type result immediately.
(Note: We will cover the logic for actually sending the admin request in the Admin Request State Machine chapter).
If the user does have billing access (or isn't on a team), the solution is simple: Send them to the website.
// Determine the correct URL based on plan
const url = isTeamOrEnterprise
? 'https://claude.ai/admin-settings/usage'
: 'https://claude.ai/settings/usage'
try {
// Attempt to open their default browser
const opened = await openBrowser(url)
return { type: 'browser-opened', url, opened }
} catch (error) {
// If browser fails, fallback to a message
return { type: 'message', value: `Please visit ${url}` }
}
}
Explanation:
type: 'browser-opened'.Here is how the data flows through the engine. Notice how the Engine takes inputs and outputs a Result, but never draws UI itself.
By separating this logic, if we ever want to change the URL or change the rules for who is an "Employee," we change it in one place. Both the Interactive CLI and the Headless script automatically get the update.
In this chapter, we explored the Core Workflow Engine. We learned:
message vs browser-opened) to keep our logic UI-agnostic.You might have noticed that in "Scenario A (The Employee)," we glossed over exactly how we ask the admin for permission. That involves checking for pending requests, eligibility, and sending the invite. This logic is complex enough to deserve its own chapter.
Next Chapter: Admin Request State Machine
Generated by Code IQ