Welcome to the final chapter of our tutorial series!
In the previous chapter, Tool Ecosystem Integration, we learned how to scan the environment to find available tools. To do that, we briefly used a variable called permissionContext, but we didn't explain where it came from.
Today, we solve that mystery. We are exploring the Application State Context.
Imagine you are a contractor hired to fix a lightbulb in a high-security office building.
The Problem: You have your tools (screwdriver, ladder), but when you arrive at the front door, it's locked. You don't own the building. You don't have the keys. You don't even know which room the broken light is in.
The Solution: The receptionist gives you a Guest Badge and a Map.
In our CLI tool:
hooks).Without this context, your command is operating in a vacuum. It wouldn't know the current working directory, the user's preferences, or if it's allowed to access certain files.
When we defined our call function in Local JSX Execution, we saw it accepted two arguments: onDone and context.
Let's look at how we open this "Guest Badge."
Input: hooks.tsx
import type { LocalJSXCommandCall } from '../../types/command.js';
export const call: LocalJSXCommandCall = async (onDone, context) => {
// 1. The context is our connection to the main app
// We ask it to reveal the current state.
const appState = context.getAppState();
// ... rest of code
};
Explanation:
The context object is a wrapper. We use getTools() (conceptually) or getAppState() to retrieve the actual data object. This ensures we get the most up-to-date information the moment the command runs.
The appState is a plain JavaScript object that holds global information. Let's look at what specific data we extract for our hooks command.
Input: hooks.tsx
// ... inside call function
// 2. We extract the Permission Context
// This tells the system what this command is allowed to see.
const permissionContext = appState.toolPermissionContext;
// 3. We use it to scan for tools (Recap from Chapter 4)
const toolNames = getTools(permissionContext).map(t => t.name);
Explanation:
toolPermissionContext: This acts like the magnetic strip on a keycard. When we pass this to getTools, the system checks: "Does this user have permission to see the Linter tool?"appState will simply update, and we will receive the new permissions automatically.
While our hooks command specifically uses permissions, the appState usually contains other vital info.
Input: Conceptual Usage
const appState = context.getAppState();
// Example: Where is the user running this from?
console.log("Working Directory:", appState.cwd);
// Example: Is the user in 'verbose' mode?
if (appState.config.verbose) {
console.log("Loading detailed logs...");
}
Explanation: This allows your command to be "Environment Aware." It behaves differently depending on where and how the user runs the application.
How does this object get created and passed to us? It happens during the application "Boot" sequence.
tengu.config.json (or similar) from the hard drive.appState object.Let's look at the code inside the CLI Runner that prepares this package for us.
Input: context-factory.ts (Simplified)
// A factory function that creates the context
export function createCommandContext(globalConfig) {
// 1. Build the State Object
const appState = {
cwd: process.cwd(),
toolPermissionContext: globalConfig.permissions,
// ... other global data
};
// 2. Return the wrapper object
return {
getAppState: () => appState
};
}
Explanation:
createCommandContext: This function runs before your command is ever loaded.process.cwd(): Node.js allows us to see the current folder.appState variable is "trapped" inside the returned object. This ensures that every command gets access to the exact same instance of the state.We have now covered the entire lifecycle of a command in the hooks project. Let's review the journey:
hooks exists.Congratulations! You have successfully navigated the architecture of the hooks project.
By understanding these five pillars, you can now build commands that are:
You now possess the "Badge" and the "Map" to build your own powerful CLI tools. Happy coding!
Generated by Code IQ