๐Ÿ“ commands/cost/ ยท 01_command_definition___metadata.md

Chapter 1: Command Definition & Metadata

๐Ÿ“„ commands/cost/01_command_definition___metadata.md

Chapter 1: Command Definition & Metadata

Welcome to the cost project! If you are new to building Command Line Interfaces (CLIs), you are in the right place.

In this first chapter, we are going to look at the very foundation of any tool in our system: the Command Definition.

Why do we need this?

Imagine you are walking into a large office building. Before you can talk to the CEO or the Accounting Department, you usually look at the building directory or talk to a receptionist. The directory doesn't do the accounting; it just tells you:

  1. Name: Accounting.
  2. Description: Handles money.
  3. Location: Floor 5.

In our CLI, we need a "Directory" like this.

The Use Case

We want users to be able to type cost to see how much money their session has used. However, before the computer calculates the bill (which takes work), the CLI needs to know:

We solve this by creating a Command Definition. Think of this file as a Business Card or an ID Badge for our tool.

Concept: The Metadata Object

Instead of writing complex code immediately, we create a simple JavaScript/TypeScript object that describes the tool. This data about the tool is called Metadata.

Here is how we define the cost command, broken down into simple pieces.

Step 1: Identity (Name & Description)

First, we tell the system who we are.

// defined in index.ts
const cost = {
  name: 'cost',
  description: 'Show the total cost and duration of the current session',
  // ... other properties
}

Explanation:

Step 2: Categorization

Next, we define what kind of command this is.

const cost = {
  // ... previous properties
  type: 'local', 
  supportsNonInteractive: true,
}

Explanation:

Step 3: Rules & Code Location

Finally, we set rules for visibility and tell the CLI where the actual hard work happens.

import { isClaudeAISubscriber } from '../../utils/auth.js'

const cost = {
  // ... previous properties
  get isHidden() {
    // Logic to decide if we show this command
    return isClaudeAISubscriber()
  },
  load: () => import('./cost.js'), // Point to the real code
}

Explanation:

Internal Implementation: How it works

Let's look at what happens "under the hood" when the main application starts up. The application doesn't load the heavy code immediately. It just collects these "Business Cards."

The Sequence

  1. App Start: The CLI wakes up.
  2. Collection: It gathers all index.ts files (the metadata).
  3. Registration: It registers the name cost into its internal dictionary.
  4. Display: If the user types help, the CLI reads the description from the metadata to show the menu.

Here is a diagram showing how the Main App interacts with this Metadata file:

sequenceDiagram participant User participant MainApp as Main Application participant CostMeta as Cost Metadata (index.ts) User->>MainApp: Types "help" MainApp->>CostMeta: "What is your name and description?" CostMeta-->>MainApp: name: "cost", desc: "Show total cost..." MainApp->>CostMeta: "Are you hidden?" CostMeta-->>MainApp: false (Visible) MainApp-->>User: Displays "cost" in the menu

The Code Structure

The file index.ts is intentionally kept very small. It imports a type definition to ensure we don't make spelling mistakes.

import type { Command } from '../../commands.js'

// We ensure 'cost' follows the rules of a 'Command'
const cost = {
   name: 'cost',
   // ... properties
} satisfies Command

export default cost

Explanation:

Summary

We have successfully defined the Command Definition & Metadata for our cost tool.

However, in our code, you might have noticed process.env.USER_TYPE or isClaudeAISubscriber. How does the command know who the user is to decide if it should be hidden or visible?

To answer that, we need to understand the user's environment.

Next Chapter: User Context & Authorization


Generated by Code IQ