citadel_cli 1.1.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,31 +24,27 @@ npm i citadel_cli
24
24
  A core concept in Citadel are commands. Commands are things like "user add 1234"
25
25
  or "qa1 deploy my_feature_branch". To initialize and add commands:
26
26
 
27
- 1. Create a `CommandRegistry` instance
28
- 2. Add one or more commands to that registry
27
+ 1. Define commands with the typed DSL
28
+ 2. Build a `CommandRegistry` from those definitions
29
29
  3. Pass the registry to `Citadel`
30
30
 
31
31
  ```typescript
32
32
  import {
33
33
  Citadel,
34
- CommandRegistry,
35
- TextCommandResult,
34
+ command,
35
+ createCommandRegistry,
36
+ text,
36
37
  } from "citadel_cli";
37
38
 
38
- // 1. Create the registry
39
- const registry = new CommandRegistry();
39
+ // 1. Define and register commands
40
+ const registry = createCommandRegistry([
41
+ command("greet")
42
+ .describe("Say hello to someone")
43
+ .arg("name", (arg) => arg.describe("Who are we greeting?"))
44
+ .handle(async ({ namedArgs }) => text(`Hello ${namedArgs.name} world!`)),
45
+ ]);
40
46
 
41
- // 2. Add commands
42
- registry.addCommand(
43
- [
44
- { type: "word", name: "greet" },
45
- { type: "argument", name: "name", description: "Who are we greeting?" },
46
- ],
47
- "Say hello to someone", // Description used by the built-in `help` command
48
- async (args: string[]) => new TextCommandResult(`Hello ${args[0]} world!`)
49
- );
50
-
51
- // 3. Pass the registry to the component
47
+ // 2. Pass the registry to the component
52
48
  function App() {
53
49
  return <Citadel commandRegistry={registry} />;
54
50
  }
@@ -64,28 +60,68 @@ to the full word. For the above example, typing <kbd>g</kbd> would expand
64
60
  in-place to `greet ` (with a trailing space) whereupon you can enter in a value
65
61
  for the `name` argument.
66
62
 
67
- ## `addCommand` Details
63
+ For hierarchical commands, expansion is prefix-based and unambiguous:
68
64
 
69
- The `addCommand` method has the following signature:
65
+ - `us` can resolve to `user show`
66
+ - `ud` can resolve to `user deactivate`
67
+ - If two options share a prefix (`show` and `search`), continue until unique:
68
+ `ush` => `user show`, `use` => `user search`
70
69
 
71
- ```typescript
72
- addCommand(segments: CommandSegment[], description: string, handler: CommandHandler): void
73
- ```
70
+ ## Help Text
74
71
 
75
- `segments[]` - Each `CommandSegment` in this array consists of a `type` (one of
76
- "word" or "argument"), a `name`, and an optional `description`
72
+ Argument segment `description` values are shown as argument-level help text.
73
+ Example built-in help output:
77
74
 
78
- `description` - Description of the command itself. Used by the built-in help
79
- command
75
+ ```text
76
+ user show <userId> - Show user details
77
+ <userId>: Enter user ID
78
+ ```
80
79
 
81
- `handler` - What gets executed when <kbd>Enter</kbd> is pressed. The handler
82
- must return one of the following:
80
+ Handlers must return one of the following:
83
81
 
84
82
  - `TextCommandResult`
85
83
  - `JsonCommandResult`
86
84
  - `ImageCommandResult`
87
85
  - `ErrorCommandResult`
88
86
 
87
+ ## Typed DSL
88
+
89
+ For clearer command authoring, you can define commands with a DSL and compile
90
+ them into a `CommandRegistry`:
91
+
92
+ ```typescript
93
+ import {
94
+ Citadel,
95
+ command,
96
+ createCommandRegistry,
97
+ text,
98
+ } from "citadel_cli";
99
+
100
+ const registry = createCommandRegistry([
101
+ command("user.show")
102
+ .describe("Show user details")
103
+ .arg("userId", (arg) => arg.describe("Enter user ID"))
104
+ .handle(async ({ namedArgs }) => {
105
+ return text(`Showing user ${namedArgs.userId}`);
106
+ }),
107
+ ]);
108
+
109
+ function App() {
110
+ return <Citadel commandRegistry={registry} />;
111
+ }
112
+ ```
113
+
114
+ DSL handlers receive:
115
+
116
+ - `rawArgs`: positional values (`string[]`)
117
+ - `namedArgs`: argument-name map (`Record<string, string | undefined>`)
118
+ - `commandPath`: dot-delimited path string
119
+
120
+ ## Legacy `addCommand` API
121
+
122
+ `CommandRegistry#addCommand` still works and is fully supported. The DSL is now
123
+ the recommended authoring path for new command definitions.
124
+
89
125
  ### Arguments
90
126
 
91
127
  1. Each command can have zero or more arguments
@@ -128,10 +164,12 @@ given below, along with their default values.
128
164
  const config = {
129
165
  commandTimeoutMs: 10000,
130
166
  includeHelpCommand: true,
167
+ fontFamily: '"JetBrains Mono", monospace',
168
+ fontSize: '0.875rem', // CSS size (e.g. '14px') or Tailwind class (e.g. 'text-sm')
131
169
  maxHeight: '80vh',
132
170
  initialHeight: '40vh',
133
171
  minHeight: '200',
134
- outputFontSize: '0.875rem',
172
+ outputFontSize: 'text-xs', // optional override for output text only
135
173
  resetStateOnHide: false,
136
174
  showCitadelKey: '.',
137
175
  cursorType: 'blink', // 'blink', 'spin', 'solid', or 'bbs'