@agentuity/cli 0.0.6

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.
Files changed (158) hide show
  1. package/AGENTS.md +139 -0
  2. package/README.md +239 -0
  3. package/bin/cli.ts +71 -0
  4. package/dist/api.d.ts +25 -0
  5. package/dist/api.d.ts.map +1 -0
  6. package/dist/auth.d.ts +7 -0
  7. package/dist/auth.d.ts.map +1 -0
  8. package/dist/banner.d.ts +2 -0
  9. package/dist/banner.d.ts.map +1 -0
  10. package/dist/cli.d.ts +5 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cmd/auth/api.d.ts +9 -0
  13. package/dist/cmd/auth/api.d.ts.map +1 -0
  14. package/dist/cmd/auth/index.d.ts +2 -0
  15. package/dist/cmd/auth/index.d.ts.map +1 -0
  16. package/dist/cmd/auth/login.d.ts +3 -0
  17. package/dist/cmd/auth/login.d.ts.map +1 -0
  18. package/dist/cmd/auth/logout.d.ts +3 -0
  19. package/dist/cmd/auth/logout.d.ts.map +1 -0
  20. package/dist/cmd/bundle/ast.d.ts +2 -0
  21. package/dist/cmd/bundle/ast.d.ts.map +1 -0
  22. package/dist/cmd/bundle/bundler.d.ts +6 -0
  23. package/dist/cmd/bundle/bundler.d.ts.map +1 -0
  24. package/dist/cmd/bundle/file.d.ts +2 -0
  25. package/dist/cmd/bundle/file.d.ts.map +1 -0
  26. package/dist/cmd/bundle/index.d.ts +2 -0
  27. package/dist/cmd/bundle/index.d.ts.map +1 -0
  28. package/dist/cmd/bundle/plugin.d.ts +4 -0
  29. package/dist/cmd/bundle/plugin.d.ts.map +1 -0
  30. package/dist/cmd/dev/index.d.ts +2 -0
  31. package/dist/cmd/dev/index.d.ts.map +1 -0
  32. package/dist/cmd/example/create-user.d.ts +2 -0
  33. package/dist/cmd/example/create-user.d.ts.map +1 -0
  34. package/dist/cmd/example/create.d.ts +2 -0
  35. package/dist/cmd/example/create.d.ts.map +1 -0
  36. package/dist/cmd/example/deploy.d.ts +2 -0
  37. package/dist/cmd/example/deploy.d.ts.map +1 -0
  38. package/dist/cmd/example/index.d.ts +2 -0
  39. package/dist/cmd/example/index.d.ts.map +1 -0
  40. package/dist/cmd/example/list.d.ts +2 -0
  41. package/dist/cmd/example/list.d.ts.map +1 -0
  42. package/dist/cmd/example/run-command.d.ts +2 -0
  43. package/dist/cmd/example/run-command.d.ts.map +1 -0
  44. package/dist/cmd/example/sound.d.ts +3 -0
  45. package/dist/cmd/example/sound.d.ts.map +1 -0
  46. package/dist/cmd/example/spinner.d.ts +2 -0
  47. package/dist/cmd/example/spinner.d.ts.map +1 -0
  48. package/dist/cmd/example/steps.d.ts +2 -0
  49. package/dist/cmd/example/steps.d.ts.map +1 -0
  50. package/dist/cmd/example/version.d.ts +2 -0
  51. package/dist/cmd/example/version.d.ts.map +1 -0
  52. package/dist/cmd/index.d.ts +3 -0
  53. package/dist/cmd/index.d.ts.map +1 -0
  54. package/dist/cmd/profile/create.d.ts +2 -0
  55. package/dist/cmd/profile/create.d.ts.map +1 -0
  56. package/dist/cmd/profile/delete.d.ts +2 -0
  57. package/dist/cmd/profile/delete.d.ts.map +1 -0
  58. package/dist/cmd/profile/index.d.ts +2 -0
  59. package/dist/cmd/profile/index.d.ts.map +1 -0
  60. package/dist/cmd/profile/list.d.ts +3 -0
  61. package/dist/cmd/profile/list.d.ts.map +1 -0
  62. package/dist/cmd/profile/show.d.ts +2 -0
  63. package/dist/cmd/profile/show.d.ts.map +1 -0
  64. package/dist/cmd/profile/use.d.ts +2 -0
  65. package/dist/cmd/profile/use.d.ts.map +1 -0
  66. package/dist/cmd/project/create.d.ts +2 -0
  67. package/dist/cmd/project/create.d.ts.map +1 -0
  68. package/dist/cmd/project/delete.d.ts +2 -0
  69. package/dist/cmd/project/delete.d.ts.map +1 -0
  70. package/dist/cmd/project/index.d.ts +2 -0
  71. package/dist/cmd/project/index.d.ts.map +1 -0
  72. package/dist/cmd/project/list.d.ts +2 -0
  73. package/dist/cmd/project/list.d.ts.map +1 -0
  74. package/dist/cmd/project/show.d.ts +2 -0
  75. package/dist/cmd/project/show.d.ts.map +1 -0
  76. package/dist/cmd/version/index.d.ts +2 -0
  77. package/dist/cmd/version/index.d.ts.map +1 -0
  78. package/dist/command-prefix.d.ts +11 -0
  79. package/dist/command-prefix.d.ts.map +1 -0
  80. package/dist/config.d.ts +16 -0
  81. package/dist/config.d.ts.map +1 -0
  82. package/dist/index.d.ts +18 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/legacy-check.d.ts +6 -0
  85. package/dist/legacy-check.d.ts.map +1 -0
  86. package/dist/logger.d.ts +24 -0
  87. package/dist/logger.d.ts.map +1 -0
  88. package/dist/runtime.d.ts +3 -0
  89. package/dist/runtime.d.ts.map +1 -0
  90. package/dist/schema-parser.d.ts +24 -0
  91. package/dist/schema-parser.d.ts.map +1 -0
  92. package/dist/sound.d.ts +2 -0
  93. package/dist/sound.d.ts.map +1 -0
  94. package/dist/steps.d.ts +59 -0
  95. package/dist/steps.d.ts.map +1 -0
  96. package/dist/terminal.d.ts +3 -0
  97. package/dist/terminal.d.ts.map +1 -0
  98. package/dist/tui.d.ts +156 -0
  99. package/dist/tui.d.ts.map +1 -0
  100. package/dist/types.d.ts +164 -0
  101. package/dist/types.d.ts.map +1 -0
  102. package/dist/version.d.ts +10 -0
  103. package/dist/version.d.ts.map +1 -0
  104. package/package.json +46 -0
  105. package/src/api-errors.md +115 -0
  106. package/src/api.ts +186 -0
  107. package/src/auth.ts +91 -0
  108. package/src/banner.ts +23 -0
  109. package/src/cli.ts +198 -0
  110. package/src/cmd/auth/README.md +95 -0
  111. package/src/cmd/auth/api.ts +71 -0
  112. package/src/cmd/auth/index.ts +9 -0
  113. package/src/cmd/auth/login.ts +76 -0
  114. package/src/cmd/auth/logout.ts +14 -0
  115. package/src/cmd/bundle/ast.ts +228 -0
  116. package/src/cmd/bundle/bundler.ts +88 -0
  117. package/src/cmd/bundle/file.ts +16 -0
  118. package/src/cmd/bundle/index.ts +38 -0
  119. package/src/cmd/bundle/plugin.ts +259 -0
  120. package/src/cmd/dev/index.ts +83 -0
  121. package/src/cmd/example/create-user.ts +38 -0
  122. package/src/cmd/example/create.ts +31 -0
  123. package/src/cmd/example/deploy.ts +36 -0
  124. package/src/cmd/example/index.ts +27 -0
  125. package/src/cmd/example/list.ts +32 -0
  126. package/src/cmd/example/run-command.ts +45 -0
  127. package/src/cmd/example/sound.ts +14 -0
  128. package/src/cmd/example/spinner.ts +44 -0
  129. package/src/cmd/example/steps.ts +66 -0
  130. package/src/cmd/example/version.ts +13 -0
  131. package/src/cmd/index.ts +46 -0
  132. package/src/cmd/profile/README.md +80 -0
  133. package/src/cmd/profile/create.ts +57 -0
  134. package/src/cmd/profile/delete.ts +52 -0
  135. package/src/cmd/profile/index.ts +12 -0
  136. package/src/cmd/profile/list.ts +27 -0
  137. package/src/cmd/profile/show.ts +54 -0
  138. package/src/cmd/profile/use.ts +30 -0
  139. package/src/cmd/project/create.ts +247 -0
  140. package/src/cmd/project/delete.ts +13 -0
  141. package/src/cmd/project/index.ts +11 -0
  142. package/src/cmd/project/list.ts +13 -0
  143. package/src/cmd/project/show.ts +12 -0
  144. package/src/cmd/version/index.ts +16 -0
  145. package/src/command-prefix.ts +43 -0
  146. package/src/config.ts +304 -0
  147. package/src/index.ts +40 -0
  148. package/src/legacy-check.ts +127 -0
  149. package/src/logger.ts +235 -0
  150. package/src/runtime.ts +22 -0
  151. package/src/schema-parser.ts +213 -0
  152. package/src/sound.ts +25 -0
  153. package/src/steps.ts +245 -0
  154. package/src/terminal.ts +151 -0
  155. package/src/tui.md +254 -0
  156. package/src/tui.ts +838 -0
  157. package/src/types.ts +243 -0
  158. package/src/version.ts +29 -0
@@ -0,0 +1,14 @@
1
+ import type { SubcommandDefinition } from '../../types';
2
+ import * as tui from '@/tui';
3
+ import { playSound } from '@/sound';
4
+
5
+ export const soundSubcommand: SubcommandDefinition = {
6
+ name: 'sound',
7
+ description: 'Test completion sound',
8
+
9
+ async handler() {
10
+ tui.info('Playing completion sound...');
11
+ await playSound();
12
+ tui.success('Sound played!');
13
+ },
14
+ };
@@ -0,0 +1,44 @@
1
+ import { createSubcommand } from '@/types';
2
+ import * as tui from '@/tui';
3
+
4
+ export const spinnerSubcommand = createSubcommand({
5
+ name: 'spinner',
6
+ description: 'Demo of spinner TUI component',
7
+
8
+ async handler() {
9
+ await tui.spinner('Loading configuration...', async () => {
10
+ await Bun.sleep(2000);
11
+ return { loaded: true };
12
+ });
13
+
14
+ await tui.spinner('Fetching data...', Bun.sleep(1500));
15
+
16
+ const result = await tui.spinner('Processing...', async () => {
17
+ await Bun.sleep(1000);
18
+ return 42;
19
+ });
20
+
21
+ tui.info(`Result: ${result}`);
22
+
23
+ // Spinner with progress tracking
24
+ await tui.spinner({
25
+ type: 'progress',
26
+ message: 'Downloading file...',
27
+ callback: async (progress) => {
28
+ for (let i = 0; i <= 100; i += 5) {
29
+ progress(i);
30
+ await Bun.sleep(100);
31
+ }
32
+ },
33
+ });
34
+
35
+ try {
36
+ await tui.spinner('This will fail...', async () => {
37
+ await Bun.sleep(1000);
38
+ throw new Error('Something went wrong!');
39
+ });
40
+ } catch (err) {
41
+ tui.error(`Caught error: ${err instanceof Error ? err.message : String(err)}`);
42
+ }
43
+ },
44
+ });
@@ -0,0 +1,66 @@
1
+ import { createSubcommand } from '@/types';
2
+ import { runSteps, stepSuccess, stepSkipped, stepError } from '@/steps';
3
+
4
+ export const stepsSubcommand = createSubcommand({
5
+ name: 'steps',
6
+ description: 'Demo of step progress UI component',
7
+
8
+ async handler() {
9
+ await runSteps([
10
+ {
11
+ label: 'Launching application...',
12
+ run: async () => {
13
+ await Bun.sleep(1500);
14
+ return stepSuccess();
15
+ },
16
+ },
17
+ {
18
+ label: 'Installing dependencies...',
19
+ run: async () => {
20
+ await Bun.sleep(2000);
21
+ return stepSuccess();
22
+ },
23
+ },
24
+ {
25
+ label: 'Checking for updates...',
26
+ run: async () => {
27
+ await Bun.sleep(800);
28
+ return stepSkipped('already up to date');
29
+ },
30
+ },
31
+ {
32
+ label: 'Registering service...',
33
+ run: async () => {
34
+ await Bun.sleep(1200);
35
+ return stepSuccess();
36
+ },
37
+ },
38
+ {
39
+ label: 'Building project...',
40
+ run: async () => {
41
+ await Bun.sleep(1800);
42
+ return stepSuccess();
43
+ },
44
+ },
45
+ {
46
+ type: 'progress',
47
+ label: 'Downloading packages...',
48
+ run: async (progress) => {
49
+ // Simulate download with progress updates
50
+ for (let i = 0; i <= 100; i += 10) {
51
+ progress(i);
52
+ await Bun.sleep(200);
53
+ }
54
+ return stepSuccess();
55
+ },
56
+ },
57
+ {
58
+ label: 'Deploying the app ...',
59
+ run: async () => {
60
+ await Bun.sleep(1200);
61
+ return stepError('something bad happened');
62
+ },
63
+ },
64
+ ]);
65
+ },
66
+ });
@@ -0,0 +1,13 @@
1
+ import { createSubcommand } from '@/types';
2
+
3
+ export const versionSubcommand = createSubcommand({
4
+ name: 'version',
5
+ description: 'Example: Display version information (no auth required)',
6
+
7
+ async handler(ctx) {
8
+ const { logger } = ctx;
9
+
10
+ logger.info('Version 1.0.0');
11
+ logger.info('This command does not require authentication');
12
+ },
13
+ });
@@ -0,0 +1,46 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import type { CommandDefinition } from '../types';
4
+
5
+ export async function discoverCommands(): Promise<CommandDefinition[]> {
6
+ const cmdDir = join(import.meta.dir);
7
+ const entries = await readdir(cmdDir, { withFileTypes: true });
8
+
9
+ const commands: CommandDefinition[] = [];
10
+
11
+ for (const entry of entries) {
12
+ if (entry.isDirectory()) {
13
+ try {
14
+ const modulePath = join(cmdDir, entry.name, 'index.ts');
15
+ const module = await import(modulePath);
16
+
17
+ if (module.default || module.command) {
18
+ const cmd = module.default || module.command;
19
+ commands.push(cmd);
20
+
21
+ // Auto-create hidden top-level aliases for subcommands with toplevel: true
22
+ if (cmd.subcommands) {
23
+ for (const subcommand of cmd.subcommands) {
24
+ if (subcommand.toplevel) {
25
+ const alias: CommandDefinition = {
26
+ name: subcommand.name,
27
+ description: subcommand.description,
28
+ aliases: subcommand.aliases,
29
+ hidden: true,
30
+ requiresAuth: subcommand.requiresAuth,
31
+ schema: subcommand.schema,
32
+ handler: subcommand.handler,
33
+ };
34
+ commands.push(alias);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ } catch (error) {
40
+ console.warn(`Warning: Failed to load command from ${entry.name}:`, error);
41
+ }
42
+ }
43
+ }
44
+
45
+ return commands;
46
+ }
@@ -0,0 +1,80 @@
1
+ # Profile Management
2
+
3
+ The profile command allows you to manage multiple configuration profiles for different environments (production, staging, local development, etc.).
4
+
5
+ ## How It Works
6
+
7
+ Profiles are YAML files stored in `~/.config/agentuity/` that contain a `name` field. The CLI maintains a `profile` file in the same directory that stores the path to the currently selected profile.
8
+
9
+ When you run the CLI, it automatically loads the active profile's configuration.
10
+
11
+ ## Commands
12
+
13
+ ### `profile show` (alias: `current`)
14
+
15
+ Show the configuration of the currently active profile.
16
+
17
+ ```bash
18
+ agentuity profile show
19
+ agentuity profile current
20
+ ```
21
+
22
+ Example output:
23
+
24
+ ```
25
+ [INFO] Profile: /Users/username/.config/agentuity/production.yaml
26
+
27
+ name: production
28
+ auth:
29
+ api_key: ck_...
30
+ user_id: user_...
31
+ overrides:
32
+ api_url: "https://api.agentuity.com"
33
+ ```
34
+
35
+ ### `profile list` (alias: `ls`)
36
+
37
+ Lists all available profiles. The currently active profile is marked with a bullet (`•`).
38
+
39
+ ```bash
40
+ agentuity profile list
41
+ ```
42
+
43
+ Example output:
44
+
45
+ ```
46
+ [INFO] Available profiles:
47
+ [INFO] • production agentuity/production.yaml
48
+ [INFO] local agentuity/local.yaml
49
+ ```
50
+
51
+ ### `profile use [name]` (alias: `select`)
52
+
53
+ Switch to a different profile by name. If no name is provided, shows the current profile and available options.
54
+
55
+ ```bash
56
+ # Switch to a specific profile
57
+ agentuity profile use local
58
+
59
+ # Show current profile
60
+ agentuity profile use
61
+ ```
62
+
63
+ ## Profile File Format
64
+
65
+ Each profile is a YAML file with at minimum a `name` field:
66
+
67
+ ```yaml
68
+ name: 'production'
69
+ # other configuration...
70
+ ```
71
+
72
+ The `name` field is extracted using the regex: `/\bname:\s+["']?([\w-_]+)["']?/`
73
+
74
+ ## Implementation Details
75
+
76
+ - Profile selection is stored in `~/.config/agentuity/profile`
77
+ - Profile files must have `.yaml` extension
78
+ - Profile names must match: `^[\w-_]{3,}$` (3+ chars, alphanumeric, dashes, underscores)
79
+ - The config loader (`loadConfig()`) automatically uses the active profile
80
+ - If no profile is selected or the file doesn't exist, falls back to `config.yaml`
@@ -0,0 +1,57 @@
1
+ import { createSubcommand } from '@/types';
2
+ import { z } from 'zod';
3
+ import {
4
+ fetchProfiles,
5
+ getDefaultConfigDir,
6
+ ensureConfigDir,
7
+ generateYAMLTemplate,
8
+ } from '@/config';
9
+ import { join } from 'node:path';
10
+ import { writeFile } from 'node:fs/promises';
11
+ import * as tui from '@/tui';
12
+
13
+ const PROFILE_NAME_REGEX = /^[\w_-]{3,}$/;
14
+
15
+ export const createCommand = createSubcommand({
16
+ name: 'create',
17
+ description: 'Create a new configuration profile',
18
+ aliases: ['new'],
19
+ schema: {
20
+ args: z
21
+ .object({
22
+ name: z
23
+ .string()
24
+ .min(3)
25
+ .regex(PROFILE_NAME_REGEX)
26
+ .describe('The name of the profile to create'),
27
+ })
28
+ .describe('Profile creation arguments'),
29
+ },
30
+
31
+ async handler(ctx) {
32
+ const { logger, args } = ctx;
33
+ const { name } = args;
34
+
35
+ const profiles = await fetchProfiles();
36
+ const existing = profiles.find((p) => p.name === name);
37
+
38
+ if (existing) {
39
+ return logger.fatal(`Profile "${name}" already exists at ${existing.filename}`);
40
+ }
41
+
42
+ await ensureConfigDir();
43
+ const configDir = getDefaultConfigDir();
44
+ const filename = join(configDir, `${name}.yaml`);
45
+
46
+ const template = generateYAMLTemplate(name);
47
+
48
+ try {
49
+ await writeFile(filename, template, { flag: 'wx', mode: 0o600 });
50
+ tui.success(`Created profile "${name}" at ${filename}`);
51
+ } catch (error) {
52
+ const message = error instanceof Error ? error.message : String(error);
53
+ const stack = error instanceof Error ? error.stack : undefined;
54
+ logger.fatal(`Failed to create profile: ${message}${stack ? `\n${stack}` : ''}`);
55
+ }
56
+ },
57
+ });
@@ -0,0 +1,52 @@
1
+ import { createSubcommand } from '@/types';
2
+ import { z } from 'zod';
3
+ import { fetchProfiles } from '@/config';
4
+ import { unlink } from 'node:fs/promises';
5
+ import * as tui from '@/tui';
6
+
7
+ export const deleteCommand = createSubcommand({
8
+ name: 'delete',
9
+ description: 'Delete a configuration profile',
10
+ aliases: ['remove', 'rm'],
11
+ schema: {
12
+ args: z.object({
13
+ name: z.string().describe('The name of the profile to delete'),
14
+ }),
15
+ options: z.object({
16
+ confirm: z.boolean().optional().describe('Skip confirmation prompt'),
17
+ }),
18
+ },
19
+
20
+ async handler(ctx) {
21
+ const { logger, args, opts } = ctx;
22
+ const { name } = args;
23
+
24
+ const profiles = await fetchProfiles();
25
+ const profile = profiles.find((p) => p.name === name);
26
+
27
+ if (!profile) {
28
+ return logger.fatal(`Profile "${name}" not found`);
29
+ }
30
+
31
+ // Ask for confirmation unless --confirm flag is passed
32
+ if (!opts?.confirm) {
33
+ const confirmed = await tui.confirm(`Delete profile "${name}"?`, false);
34
+ if (!confirmed) {
35
+ logger.info('Cancelled');
36
+ return;
37
+ }
38
+ }
39
+
40
+ try {
41
+ await unlink(profile.filename);
42
+ tui.success(`Deleted profile "${name}"`);
43
+ if (profile.selected) {
44
+ tui.warning(
45
+ 'The active profile was deleted. Use "profile use <name>" to select a new default.'
46
+ );
47
+ }
48
+ } catch (error) {
49
+ logger.fatal(`Failed to delete profile: ${error}`);
50
+ }
51
+ },
52
+ });
@@ -0,0 +1,12 @@
1
+ import { createCommand } from '@/types';
2
+ import { createCommand as createProfileCmd } from './create';
3
+ import { useCommand } from './use';
4
+ import { listCommand } from './list';
5
+ import { showCommand } from './show';
6
+ import { deleteCommand } from './delete';
7
+
8
+ export const command = createCommand({
9
+ name: 'profile',
10
+ description: 'Manage configuration profiles',
11
+ subcommands: [createProfileCmd, useCommand, listCommand, showCommand, deleteCommand],
12
+ });
@@ -0,0 +1,27 @@
1
+ import type { SubcommandDefinition } from '@/types';
2
+ import { fetchProfiles } from '@/config';
3
+ import { basename, dirname } from 'node:path';
4
+ import * as tui from '@/tui';
5
+
6
+ export const listCommand: SubcommandDefinition = {
7
+ name: 'list',
8
+ description: 'List all available profiles',
9
+ aliases: ['ls'],
10
+
11
+ async handler() {
12
+ const profiles = await fetchProfiles();
13
+
14
+ if (profiles.length === 0) {
15
+ tui.info('No profiles found');
16
+ return;
17
+ }
18
+
19
+ console.log('Available profiles:');
20
+ for (const profile of profiles) {
21
+ const marker = profile.selected ? '•' : ' ';
22
+ const name = tui.padRight(profile.name, 15, ' ');
23
+ const path = `${basename(dirname(profile.filename))}/${basename(profile.filename)}`;
24
+ console.log(`${marker} ${name} ${tui.muted(path)}`);
25
+ }
26
+ },
27
+ };
@@ -0,0 +1,54 @@
1
+ import { createSubcommand } from '@/types';
2
+ import { z } from 'zod';
3
+ import { getProfile, fetchProfiles } from '@/config';
4
+ import { readFile } from 'node:fs/promises';
5
+ import * as tui from '@/tui';
6
+
7
+ export const showCommand = createSubcommand({
8
+ name: 'show',
9
+ description: 'Show the configuration of a profile (defaults to current)',
10
+ aliases: ['current'],
11
+ schema: {
12
+ args: z
13
+ .object({
14
+ name: z.string().optional().describe('Profile name to show (optional)'),
15
+ })
16
+ .describe('Profile show arguments'),
17
+ },
18
+
19
+ async handler(ctx) {
20
+ const { logger, args } = ctx;
21
+
22
+ try {
23
+ let profilePath: string;
24
+
25
+ if (args.name) {
26
+ // Find profile by name
27
+ const profiles = await fetchProfiles();
28
+ const profile = profiles.find((p) => p.name === args.name);
29
+
30
+ if (!profile) {
31
+ return logger.fatal(`Profile "${args.name}" not found`);
32
+ }
33
+
34
+ profilePath = profile.filename;
35
+ } else {
36
+ // Use current profile
37
+ profilePath = await getProfile();
38
+ }
39
+
40
+ const content = await readFile(profilePath, 'utf-8');
41
+
42
+ tui.info(`Profile: ${profilePath}`);
43
+ tui.newline();
44
+
45
+ console.log(content);
46
+ } catch (error) {
47
+ if (error instanceof Error) {
48
+ logger.fatal(`Failed to show profile: ${error.message}`);
49
+ } else {
50
+ logger.fatal('Failed to show profile');
51
+ }
52
+ }
53
+ },
54
+ });
@@ -0,0 +1,30 @@
1
+ import { createSubcommand } from '@/types';
2
+ import { z } from 'zod';
3
+ import { fetchProfiles, saveProfile } from '@/config';
4
+ import * as tui from '@/tui';
5
+
6
+ export const useCommand = createSubcommand({
7
+ name: 'use',
8
+ description: 'Switch to a different configuration profile',
9
+ aliases: ['switch'],
10
+ schema: {
11
+ args: z.object({
12
+ name: z.string().describe('The name of the profile to use'),
13
+ }),
14
+ },
15
+
16
+ async handler(ctx) {
17
+ const { logger, args } = ctx;
18
+ const { name } = args;
19
+
20
+ const profiles = await fetchProfiles();
21
+ const profile = profiles.find((p) => p.name === name);
22
+
23
+ if (!profile) {
24
+ logger.fatal(`Profile "${name}" not found`);
25
+ }
26
+
27
+ await saveProfile(profile!.filename);
28
+ tui.success(`Switched to profile "${name}"`);
29
+ },
30
+ });