Skip to content

Commit 166207b

Browse files
feat: swap default UI mode to plain text (agent-first) (#69)
* feat: swap default UI mode to plain text (agent-first) Most CLI users are agents/CI, not humans. Invert the default so plain text output is the default and interactive Ink UI requires opting in with --human-friendly. Keep --no-ui for backwards compatibility (no-op). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: align option columns in plain text help output Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump version to 0.5.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use process.argv for --human-friendly in parent command handlers Commander doesn't reliably pass parsed options to parent command action handlers when subcommands are registered. Check process.argv directly instead, consistent with how cli.ts already handles it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1f4aaf9 commit 166207b

File tree

33 files changed

+283
-98
lines changed

33 files changed

+283
-98
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@elevenlabs/cli",
3-
"version": "0.4.3",
3+
"version": "0.5.0",
44
"description": "CLI tool to manage ElevenLabs agents",
55
"type": "module",
66
"keywords": [

src/agents/commands/add.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ export function createAddCommand(): Command {
3535
.option('--output-path <path>', 'Custom output path for the config file (optional)')
3636
.option('--template <template>', 'Template type to use (default, minimal, voice-only, text-only, customer-service, assistant)')
3737
.option('--from-file <path>', 'Create agent from an existing config file')
38-
.option('--no-ui', 'Disable interactive UI')
39-
.action(async (name: string | undefined, options: AddOptions & { ui: boolean }) => {
38+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
39+
.option('--human-friendly', 'Enable interactive terminal UI')
40+
.action(async (name: string | undefined, options: AddOptions & { ui: boolean; humanFriendly?: boolean }) => {
4041
try {
41-
if (options.ui !== false && !options.outputPath && !options.fromFile) {
42+
if (options.humanFriendly && !options.outputPath && !options.fromFile) {
4243
// Use Ink UI for agent creation
4344
const { waitUntilExit } = render(
4445
React.createElement(AddAgentView, {
@@ -58,7 +59,7 @@ export function createAddCommand(): Command {
5859

5960
// Non-UI path requires name to be provided (or --from-file with name in the file)
6061
if (!name && !options.fromFile) {
61-
console.error('Error: Agent name is required when using --no-ui or --output-path');
62+
console.error('Error: Agent name is required in non-interactive mode');
6263
process.exit(1);
6364
}
6465

src/agents/commands/branches.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ export function createBranchesCommand(): Command {
1818
.description('List branches for an agent')
1919
.requiredOption('--agent <agent_id>', 'Agent ID to list branches for')
2020
.option('--include-archived', 'Include archived branches', false)
21-
.option('--no-ui', 'Disable interactive UI')
22-
.action(async (options: BranchesListOptions & { ui: boolean }) => {
21+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
22+
.option('--human-friendly', 'Enable interactive terminal UI')
23+
.action(async (options: BranchesListOptions & { ui: boolean; humanFriendly?: boolean }) => {
2324
try {
24-
if (options.ui !== false) {
25+
if (options.humanFriendly) {
2526
const { waitUntilExit } = render(
2627
React.createElement(BranchesListView, {
2728
agent: options.agent,

src/agents/commands/delete.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ export function createDeleteCommand(): Command {
88
.description('Delete an agent locally and from ElevenLabs')
99
.argument('[agent_id]', 'ID of the agent to delete (omit with --all to delete all agents)')
1010
.option('--all', 'Delete all agents', false)
11-
.option('--no-ui', 'Disable interactive UI')
12-
.action(async (agentId: string | undefined, options: { all: boolean; ui: boolean }) => {
11+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
12+
.option('--human-friendly', 'Enable interactive terminal UI')
13+
.action(async (agentId: string | undefined, options: { all: boolean; ui: boolean; humanFriendly?: boolean }) => {
1314
try {
1415
if (options.all && agentId) {
1516
console.error('Error: Cannot specify both agent_id and --all flag');
@@ -22,7 +23,7 @@ export function createDeleteCommand(): Command {
2223
}
2324

2425
if (options.all) {
25-
await deleteAllAgents(options.ui);
26+
await deleteAllAgents(options.humanFriendly === true);
2627
} else {
2728
await deleteAgent(agentId!);
2829
}

src/agents/commands/index.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,36 @@ import { createTestCommand } from './test.js';
1414
import { createBranchesCommand } from './branches.js';
1515
import AgentsHelpView from '../ui/AgentsHelpView.js';
1616

17+
function printAgentsHelp() {
18+
console.log('elevenlabs agents - Agent management commands\n');
19+
console.log('Usage:');
20+
console.log(' elevenlabs agents <command> [options]\n');
21+
console.log('Commands:');
22+
const commands = [
23+
{ name: 'init [path]', description: 'Initialize project', options: ['--override Recreate existing project'] },
24+
{ name: 'add [name]', description: 'Create a new agent and push to remote', options: ['--output-path <path> Custom output path for config file', '--from-file <path> Create agent from existing config file', '--template <template> Template type to use (default, minimal, voice-only, text-only, customer-service, assistant)'] },
25+
{ name: 'list', description: 'List all local agents' },
26+
{ name: 'delete [agent_id]', description: 'Delete agent', options: ['--all Delete all agents'] },
27+
{ name: 'status', description: 'Show the status of agents' },
28+
{ name: 'push', description: 'Push agents to ElevenLabs', options: ['--branch <branch> Push to a specific branch'] },
29+
{ name: 'pull', description: 'Pull agents from ElevenLabs', options: ['--branch <branch> Pull from a specific branch', '--all-branches Pull all branches for each agent', '--update Update existing agents', '--all Pull all agents'] },
30+
{ name: 'branches list', description: 'List branches for an agent', options: ['--agent <agent_id> Agent ID (required)', '--include-archived Include archived branches'] },
31+
{ name: 'test <agent>', description: 'Run tests for an agent' },
32+
{ name: 'templates [action]', description: 'Manage agent templates', options: ['list List available templates', 'show <name> Show template details'] },
33+
{ name: 'widget <name>', description: 'Generate HTML widget snippet' },
34+
];
35+
for (const cmd of commands) {
36+
console.log(` ${cmd.name.padEnd(28)}${cmd.description}`);
37+
if (cmd.options) {
38+
for (const opt of cmd.options) {
39+
const [flag, ...descParts] = opt.split(' ');
40+
console.log(` ${flag.padEnd(26)}${descParts.join(' ')}`);
41+
}
42+
}
43+
}
44+
console.log('\nEnable interactive UI with --human-friendly flag for any command');
45+
}
46+
1747
export function createAgentsCommand(): Command {
1848
const agents = new Command('agents');
1949
agents.description('Manage ElevenLabs agents');
@@ -24,13 +54,18 @@ export function createAgentsCommand(): Command {
2454

2555
// Add custom help option
2656
agents.option('-h, --help', 'Display help information');
57+
agents.option('--human-friendly', 'Enable interactive terminal UI');
2758

2859
// Custom action when agents command is run without subcommands
2960
agents.action(async () => {
30-
const { waitUntilExit } = render(
31-
React.createElement(AgentsHelpView)
32-
);
33-
await waitUntilExit();
61+
if (process.argv.includes('--human-friendly')) {
62+
const { waitUntilExit } = render(
63+
React.createElement(AgentsHelpView)
64+
);
65+
await waitUntilExit();
66+
} else {
67+
printAgentsHelp();
68+
}
3469
process.exit(0);
3570
});
3671

src/agents/commands/init.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ export function createInitCommand(): Command {
2929
return new Command('init')
3030
.description('Initialize a new agent management project')
3131
.argument('[path]', 'Path to initialize the project in', '.')
32-
.option('--no-ui', 'Disable interactive UI')
32+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
33+
.option('--human-friendly', 'Enable interactive terminal UI')
3334
.option('--override', 'Override existing files and recreate from scratch', false)
34-
.action(async (projectPath: string, options: { ui: boolean; override: boolean }) => {
35+
.action(async (projectPath: string, options: { ui: boolean; override: boolean; humanFriendly?: boolean }) => {
3536
try {
36-
if (options.ui !== false) {
37+
if (options.humanFriendly) {
3738
// Use Ink UI for initialization
3839
const { waitUntilExit } = render(
3940
React.createElement(InitView, { projectPath, override: options.override })

src/agents/commands/list.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import ListAgentsView from '../ui/ListAgentsView.js';
66
export function createListCommand(): Command {
77
return new Command('list')
88
.description('List all configured agents')
9-
.option('--no-ui', 'Disable interactive UI')
10-
.action(async (options: { ui: boolean }) => {
9+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
10+
.option('--human-friendly', 'Enable interactive terminal UI')
11+
.action(async (options: { ui: boolean; humanFriendly?: boolean }) => {
1112
try {
12-
if (options.ui !== false) {
13+
if (options.humanFriendly) {
1314
// Use Ink UI for list-agents
1415
const { waitUntilExit } = render(
1516
React.createElement(ListAgentsView)

src/agents/commands/pull.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ export function createPullCommand(): Command {
2424
.option('--dry-run', 'Show what would be done without making changes', false)
2525
.option('--update', 'Update existing items only, skip new')
2626
.option('--all', 'Pull all (new + existing)')
27-
.option('--no-ui', 'Disable interactive UI')
28-
.action(async (options: PullOptions & { ui: boolean }) => {
27+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
28+
.option('--human-friendly', 'Enable interactive terminal UI')
29+
.action(async (options: PullOptions & { ui: boolean; humanFriendly?: boolean }) => {
2930
try {
3031
if (options.branch && !options.agent) {
3132
throw new Error('--branch requires --agent to be specified, since branch names are per-agent.');
@@ -35,7 +36,7 @@ export function createPullCommand(): Command {
3536
await pullAgents(options);
3637
return;
3738
}
38-
if (options.ui !== false) {
39+
if (options.humanFriendly) {
3940
// Use Ink UI for pull
4041
const { waitUntilExit } = render(
4142
React.createElement(PullView, {

src/agents/commands/push.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ export function createPushCommand(): Command {
3131
.option('--branch <branch>', 'Specific branch name or ID to push to')
3232
.option('--dry-run', 'Show what would be done without making changes', false)
3333
.option('--version-description <text>', 'Description for the new version (only applies to updates)')
34-
.option('--no-ui', 'Disable interactive UI')
35-
.action(async (options: PushOptions & { ui: boolean }) => {
34+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
35+
.option('--human-friendly', 'Enable interactive terminal UI')
36+
.action(async (options: PushOptions & { ui: boolean; humanFriendly?: boolean }) => {
3637
try {
3738
if (options.branch && !options.agent) {
3839
throw new Error('--branch requires --agent to be specified, since branch names are per-agent.');
3940
}
40-
if (options.ui !== false) {
41+
if (options.humanFriendly) {
4142
// Use new Ink UI for push
4243
const agentsConfigPath = path.resolve(AGENTS_CONFIG_FILE);
4344
if (!(await fs.pathExists(agentsConfigPath))) {

src/agents/commands/status.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ interface StatusOptions {
1111
export function createStatusCommand(): Command {
1212
return new Command('status')
1313
.description('Show the status of agents')
14-
.option('--no-ui', 'Disable interactive UI')
15-
.action(async (options: StatusOptions & { ui: boolean }) => {
14+
.option('--no-ui', 'Disable interactive UI (default, kept for backwards compatibility)')
15+
.option('--human-friendly', 'Enable interactive terminal UI')
16+
.action(async (options: StatusOptions & { ui: boolean; humanFriendly?: boolean }) => {
1617
try {
17-
if (options.ui !== false) {
18+
if (options.humanFriendly) {
1819
// Use Ink UI for status display
1920
const { waitUntilExit } = render(
2021
React.createElement(StatusView, {})

0 commit comments

Comments
 (0)