Welcome to the first chapter of the Chrome project tutorial!
In this project, we are building a CLI (Command Line Interface) integration for Chrome. Before we build complex user interfaces or talk to the browser, we need to tell our CLI application that this new feature simply exists.
This brings us to our first core concept: Command Module Definition.
Imagine you walk into a large restaurant. The menu might have 50 different dishes.
In our CLI, if we loaded all the heavy code for every feature at startup, the application would be very slow. The Command Module Definition acts as the "Menu Item." It provides just enough information to list the command, but defers loading the heavy code until the user types the command.
We want to add a command called chrome to our CLI.
--help, they should see chrome listed with a description.chrome.Let's look at how we define this "Menu Item" in code. We use a lightweight JavaScript/TypeScript object.
First, we define the basic identity of our command. This includes its name and description.
// index.ts
import type { Command } from '../../commands.js'
const command: Command = {
name: 'chrome',
description: 'Claude in Chrome (Beta) settings',
// ... more properties below
}
name: This is what the user types in the terminal (e.g., $ my-cli chrome).description: This text appears when the user asks for help.Next, we define who can see this command and when it is allowed to run.
// index.ts (continued)
import { getIsNonInteractiveSession } from '../../bootstrap/state.js'
// ... inside the command object
availability: ['claude-ai'],
isEnabled: () => !getIsNonInteractiveSession(),
type: 'local-jsx',
availability: Defines which product tier has access to this command.isEnabled: A function that returns true or false. Here, we disable the command if the session is non-interactive (automated). We learn more about state in Environment & State Context.type: Tells the CLI that this command renders a UI locally.This is the most important part. We use a specific function to load the actual logic only when needed.
// index.ts (continued)
// The heavy code is NOT loaded yet.
// It is only imported when this function runs.
load: () => import('./chrome.js'),
}
export default command
load: This function uses a dynamic import(). The file ./chrome.js contains the heavy User Interface code. By putting it inside a function, we ensure it stays "in the fridge" until ordered.What happens when you run the application? Here is the flow of events.
index.ts file we just wrote.command object. It knows the name is chrome../chrome.js yet.chrome. The CLI sees a match.load() function, importing the heavy code.
Let's look at the complete file index.ts to see how it all fits together.
import { getIsNonInteractiveSession } from '../../bootstrap/state.js'
import type { Command } from '../../commands.js'
const command: Command = {
name: 'chrome',
description: 'Claude in Chrome (Beta) settings',
availability: ['claude-ai'],
// Check if we are in a valid state to run this
isEnabled: () => !getIsNonInteractiveSession(),
// Defines the rendering mode (covered in Chapter 2)
type: 'local-jsx',
// The Lazy Load magic
load: () => import('./chrome.js'),
}
export default command
This file acts as a bridge. It connects the core CLI system to your specific feature.
type: 'local-jsx' property gives the system a hint that the file we are loading (./chrome.js) will export a React-based UI. We will build that UI in Interactive CLI UI (React/Ink).export default command makes this definition available to the main application loader.In this chapter, you learned:
index.ts) from the implementation (chrome.js).load() function with dynamic imports to make our application start faster.Now that we have defined how to call the command, we need to build what the user actually sees when the command loads.
Next Chapter: Interactive CLI UI (React/Ink)
Generated by Code IQ