Welcome to the tag project! If you have ever wondered how a CLI (Command Line Interface) tool knows what commands are available without loading massive amounts of code instantly, you are in the right place.
In this first chapter, we will explore Command Registration.
Imagine you are walking into a massive restaurant. The menu has hundreds of items.
If the chef cooked every single dish on the menu the moment you walked in, the restaurant would be chaotic and slow. Instead, the kitchen waits until you actually order something.
Command Registration acts exactly like that Menu.
It tells the main application:
tag."
We want to build a feature that lets a user add a "tag" to their current work session. We want this command to show up in the help menu, but we don't want to load the heavy user interface code until the user actually types tag.
Let's look at the file index.ts. This file acts as the "Menu Entry" for our specific feature.
First, we give our command a name and a description so the user knows what it is.
import type { Command } from '../../commands.js'
const tag = {
type: 'local-jsx', // Defines the rendering style
name: 'tag', // What the user types
description: 'Toggle a searchable tag on the current session',
// ... continued below
Explanation:
$ my-app tag).$ my-app --help.local-jsx type in React-based Terminal UI.Next, we define when this command is allowed and where the actual code lives.
// ... continued from above
isEnabled: () => process.env.USER_TYPE === 'ant',
argumentHint: '<tag-name>',
load: () => import('./tag.js'),
} satisfies Command
export default tag
Explanation:
false, the command won't even appear in the menu. Here, only a user type of 'ant' can use it.import(). The file ./tag.js contains the heavy code, and it is only imported if the user actually runs the command.What happens when you run the CLI application? How does it use this registration file?
index.ts to read the metadata (name, description).tag, the application finally calls the load() function.Here is a simple diagram showing how the Main Application talks to the Registration file before loading the actual code.
While you don't need to write the "Core" code, it helps to understand how the Core uses your registration object.
The Core likely has a loop that looks something like this (simplified):
// Inside the Main Application Core
const commands = [tagCommand, otherCommand]; // List of registrations
function findCommand(userInput: string) {
// 1. Find the menu entry matching the name
const cmd = commands.find(c => c.name === userInput);
// 2. Check if the user is allowed to run it
if (cmd && cmd.isEnabled()) {
return cmd;
}
return null;
}
If the command is found and enabled, the Core executes the loader:
async function runCommand(cmd) {
// 3. LAZY LOAD: The 'tag.js' file is read only now!
const module = await cmd.load();
// 4. Run the feature
module.renderUI();
}
The .renderUI() part will be explained in detail in React-based Terminal UI.
In this chapter, we learned:
load: () => import(...) to ensure our CLI starts up fast and only loads code when necessary.isEnabled.In the next chapter, we will write the code that actually runs when this command is loaded!
Next Chapter: React-based Terminal UI
Generated by Code IQ