A keyboard-first command console for the power users of your web apps.
- API Testing & Debugging: Execute REST calls, inspect responses, and manipulate cookies/localStorage without leaving your application context
- Power User Workflows: Transform repetitive click-through sequences into fast keyboard commands for advanced users
- DevOps Integration: Add command-line control to CI/CD dashboards and deployment tools for rapid operations
- Internal Tool Enhancement: Give your team's web applications the speed and efficiency of terminal interfaces
- Perform (multiple) REST API calls & view results, view/modify cookies/localstorage. Do JavaScript things without affecting the application.
npm i citadel_cliA core concept in Citadel are commands. Commands are things like "user add 1234" or "qa1 deploy my_feature_branch". To initialize and add commands:
- Create a
CommandRegistryinstance - Add one or more commands to that registry
- Pass the registry to
Citadel
import {
Citadel,
CommandRegistry,
TextCommandResult,
} from "citadel_cli";
// 1. Create the registry
const registry = new CommandRegistry();
// 2. Add commands
registry.addCommand(
[
{ type: "word", name: "greet" },
{ type: "argument", name: "name", description: "Who are we greeting?" },
],
"Say hello to someone", // Description used by the built-in `help` command
async (args: string[]) => new TextCommandResult(`Hello ${args[0]} world!`)
);
// 3. Pass the registry to the component
function App() {
return <Citadel commandRegistry={registry} />;
}Citadel CLI uses auto-expansion to make entering commands as fast as
possible. When you type the first letter of a command it automatically expands
to the full word. For the above example, typing g would expand
in-place to greet (with a trailing space) whereupon you can enter in a value
for the name argument.
The addCommand method has the following signature:
addCommand(segments: CommandSegment[], description: string, handler: CommandHandler): voidsegments[] - Each CommandSegment in this array consists of a type (one of
"word" or "argument"), a name, and an optional description
description - Description of the command itself. Used by the built-in help
command
handler - What gets executed when Enter is pressed. The handler
must return one of the following:
TextCommandResultJsonCommandResultImageCommandResultErrorCommandResult
- Each command can have zero or more arguments
- Argument values are passed to the handler as a
String[] - Arguments can be single- or double-quoted
Clearing localstorage:
async () => {
localStorage.clear();
return new TextCommandResult('localStorage cleared!');
}
Make an HTTP POST with a body containing a given name:
async (args: string[]) => {
const response = await fetch('https://api.example.com/endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: args[0] }),
});
return new JsonCommandResult(await response.json());
}
Certain configuration options can be passed to the Citadel component. These are given below, along with their default values.
const config = {
commandTimeoutMs: 10000,
includeHelpCommand: true,
maxHeight: '80vh',
initialHeight: '40vh',
minHeight: '200',
outputFontSize: '0.875rem',
resetStateOnHide: false,
showCitadelKey: '.',
cursorType: 'blink', // 'blink', 'spin', 'solid', or 'bbs'
cursorSpeed: 530,
storage: {
type: 'localStorage',
maxCommands: 100
}
};
Then to make the component aware of them:
<Citadel commandRegistry={cmdRegistry} config={config} />
See CONTRIBUTING.md for guidelines on developing, testing, and releasing Citadel CLI.

