In the previous WebSearchTool chapter, we gave claudeCode access to the internet. Before that, in NotebookEditTool, we gave it access to data science files.
We are adding powerful features rapidly. But here is a problem: Not every user needs every feature.
We need a way to turn features on and off efficiently. This is called Feature Gating.
Feature Gating is like a fuse box for your application. It allows you to enable or disable entire sections of functionality based on configuration.
In claudeCode, we use a specific technique called Compile-Time Feature Flagging using our bundler, Bun.
Imagine we are building a new tool called "SuperTool," but it crashes 50% of the time. We want the code to exist in our project so we can work on it, but we do not want regular users to even see it exists.
If we just use a normal if statement, the code is still shipped to the userβit's just hidden. With Compile-Time Gating, the dangerous code is physically removed from the final file before it is sent to the user.
We use special variables in our code that look like normal variables (e.g., IS_DEBUG_MODE). However, these variables are not defined in the code files. They are injected by the build system.
This is the superpower of this chapter. If the build system sees:
if (false) {
launchNuclearMissiles();
}
It knows that code can never run. So, it simply deletes the entire block from the final file. This makes the application smaller and safer.
We use Bun to package all our files into one executable. Bun is responsible for performing the "Search and Replace" that makes feature gating work.
Feature gating is mostly set up in the build configuration, but as a developer contributing to claudeCode, you need to know how to write code that can be gated.
You treat the feature flag like a global constant.
// features/experimental.ts
// 1. Check the magic variable
if (process.env.ALLOW_EXPERIMENTAL_TOOLS) {
// 2. If true, register the tool
registerTool('SuperTool', SuperToolDefinition);
} else {
console.log("Experimental tools are disabled.");
}
Explanation: When we build the app, process.env.ALLOW_EXPERIMENTAL_TOOLS will be replaced by either true or false.
If we set the flag to false during the build, the final output code that the user receives looks like this:
// The if-statement was removed!
console.log("Experimental tools are disabled.");
Explanation: The risky registerTool code is gone completely.
The process happens before the application ever starts running. It happens during the Build Step.
build.ts) defines the values of those flags.true/false), and deletes unreachable code.Here is the visual flow:
The magic configuration lives in the build script. This is where we tell Bun what the "Magic Variables" actually equal.
We use Bun.build and the define property.
// scripts/build.ts
await Bun.build({
entrypoints: ['./src/index.ts'],
outdir: './dist',
// This is the Feature Gating logic
define: {
// We replace string patterns with actual values
'process.env.IS_DEV': JSON.stringify(false),
'process.env.ENABLE_MCP': JSON.stringify(true),
'process.env.ENABLE_COMPUTER_USE': JSON.stringify(false),
},
});
Explanation: The define object tells Bun: "Every time you see process.env.IS_DEV in the code, replace it with false."
Let's see how this protects the Computer Use feature, which allows the AI to move the mouse.
// tools/ComputerUse/index.ts
export function getComputerTools() {
// Check the compile-time flag
if (process.env.ENABLE_COMPUTER_USE === 'true') {
return [ComputerTool, KeyboardTool];
}
// If disabled, return nothing
return [];
}
Explanation: If the build script sets this to 'false', the ComputerTool code is never exposed to the rest of the app. It's as if it doesn't exist.
We often combine Feature Gating with the Permission & Security System.
// utils/permissions/index.ts
export function getDefaultPermissions() {
const defaults = { allowFileEdit: true };
// Only enable this permission if the FEATURE is enabled
if (process.env.ENABLE_MCP) {
defaults.allowMcp = true;
}
return defaults;
}
Explanation: This ensures that the permission system doesn't even look for rules related to features that have been turned off.
Feature Gating is essential for managing the complexity of the upcoming chapters:
You have learned that Feature Gating is the ability to turn features on or off during the build process. By using Bun's define feature, we can remove experimental or restricted code from the final application entirely. This keeps claudeCode lightweight, safe, and adaptable for different types of users.
Now that we know how to turn features on, let's look at one of the most exciting gated features: a way to connect the AI to any external data source.
Next Chapter: Model Context Protocol (MCP)
Generated by Code IQ