axconfig 1.0.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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +249 -0
  3. package/bin/axconfig +17 -0
  4. package/dist/agents/claude-code.d.ts +14 -0
  5. package/dist/agents/claude-code.js +98 -0
  6. package/dist/agents/codex.d.ts +15 -0
  7. package/dist/agents/codex.js +164 -0
  8. package/dist/agents/gemini.d.ts +14 -0
  9. package/dist/agents/gemini.js +156 -0
  10. package/dist/agents/opencode.d.ts +14 -0
  11. package/dist/agents/opencode.js +152 -0
  12. package/dist/auth/agents/claude-code.d.ts +9 -0
  13. package/dist/auth/agents/claude-code.js +106 -0
  14. package/dist/auth/agents/codex.d.ts +9 -0
  15. package/dist/auth/agents/codex.js +75 -0
  16. package/dist/auth/agents/gemini.d.ts +9 -0
  17. package/dist/auth/agents/gemini.js +97 -0
  18. package/dist/auth/agents/opencode.d.ts +9 -0
  19. package/dist/auth/agents/opencode.js +62 -0
  20. package/dist/auth/check-auth.d.ts +13 -0
  21. package/dist/auth/check-auth.js +24 -0
  22. package/dist/auth/extract-credentials.d.ts +11 -0
  23. package/dist/auth/extract-credentials.js +20 -0
  24. package/dist/auth/get-access-token.d.ts +35 -0
  25. package/dist/auth/get-access-token.js +116 -0
  26. package/dist/auth/types.d.ts +19 -0
  27. package/dist/auth/types.js +4 -0
  28. package/dist/build-agent-config.d.ts +41 -0
  29. package/dist/build-agent-config.js +79 -0
  30. package/dist/builder.d.ts +19 -0
  31. package/dist/builder.js +27 -0
  32. package/dist/cli.d.ts +10 -0
  33. package/dist/cli.js +79 -0
  34. package/dist/commands/auth.d.ts +19 -0
  35. package/dist/commands/auth.js +87 -0
  36. package/dist/commands/create.d.ts +14 -0
  37. package/dist/commands/create.js +101 -0
  38. package/dist/crypto.d.ts +39 -0
  39. package/dist/crypto.js +78 -0
  40. package/dist/index.d.ts +51 -0
  41. package/dist/index.js +53 -0
  42. package/dist/parse-permissions.d.ts +50 -0
  43. package/dist/parse-permissions.js +125 -0
  44. package/dist/types.d.ts +85 -0
  45. package/dist/types.js +8 -0
  46. package/package.json +93 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * OpenCode auth detection and credential extraction.
3
+ */
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import { homedir } from "node:os";
6
+ import path from "node:path";
7
+ const AGENT_ID = "opencode";
8
+ function getAuthFilePath() {
9
+ const xdgData = process.env.XDG_DATA_HOME ?? path.join(homedir(), ".local/share");
10
+ return path.join(xdgData, "opencode", "auth.json");
11
+ }
12
+ /** Check OpenCode auth status */
13
+ function checkAuth() {
14
+ const authFile = getAuthFilePath();
15
+ if (!existsSync(authFile)) {
16
+ return { agentId: AGENT_ID, authenticated: false };
17
+ }
18
+ try {
19
+ const auth = JSON.parse(readFileSync(authFile, "utf8"));
20
+ const providers = Object.keys(auth);
21
+ const firstProvider = providers[0];
22
+ if (firstProvider !== undefined) {
23
+ const firstAuth = auth[firstProvider];
24
+ const method = firstAuth?.type === "oauth"
25
+ ? "OAuth"
26
+ : firstAuth?.type === "api"
27
+ ? "API key"
28
+ : "Well-known";
29
+ return {
30
+ agentId: AGENT_ID,
31
+ authenticated: true,
32
+ method: providers.length > 1
33
+ ? `${method} (${providers.length} providers)`
34
+ : method,
35
+ details: { providers },
36
+ };
37
+ }
38
+ }
39
+ catch {
40
+ // Invalid JSON
41
+ }
42
+ return { agentId: AGENT_ID, authenticated: false };
43
+ }
44
+ /** Extract OpenCode credentials */
45
+ function extractCredentials() {
46
+ const authFile = getAuthFilePath();
47
+ if (!existsSync(authFile)) {
48
+ return undefined;
49
+ }
50
+ try {
51
+ const auth = JSON.parse(readFileSync(authFile, "utf8"));
52
+ const providers = Object.keys(auth);
53
+ if (providers.length > 0) {
54
+ return { agent: AGENT_ID, type: "oauth", data: auth };
55
+ }
56
+ }
57
+ catch {
58
+ // Invalid JSON
59
+ }
60
+ return undefined;
61
+ }
62
+ export { checkAuth, extractCredentials };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Auth detection for AI coding agents.
3
+ *
4
+ * Checks credential presence for each agent without making API calls.
5
+ */
6
+ import type { AgentId } from "../types.js";
7
+ import type { AuthStatus } from "./types.js";
8
+ /** Check auth status for a specific agent */
9
+ declare function checkAuth(agentId: AgentId): AuthStatus;
10
+ /** Check auth status for all agents */
11
+ declare function checkAllAuth(): AuthStatus[];
12
+ export { checkAuth, checkAllAuth };
13
+ export type { AuthStatus } from "./types.js";
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Auth detection for AI coding agents.
3
+ *
4
+ * Checks credential presence for each agent without making API calls.
5
+ */
6
+ import { checkAuth as checkClaudeCode } from "./agents/claude-code.js";
7
+ import { checkAuth as checkCodex } from "./agents/codex.js";
8
+ import { checkAuth as checkGemini } from "./agents/gemini.js";
9
+ import { checkAuth as checkOpenCode } from "./agents/opencode.js";
10
+ const AUTH_CHECKERS = {
11
+ "claude-code": checkClaudeCode,
12
+ codex: checkCodex,
13
+ gemini: checkGemini,
14
+ opencode: checkOpenCode,
15
+ };
16
+ /** Check auth status for a specific agent */
17
+ function checkAuth(agentId) {
18
+ return AUTH_CHECKERS[agentId]();
19
+ }
20
+ /** Check auth status for all agents */
21
+ function checkAllAuth() {
22
+ return Object.values(AUTH_CHECKERS).map((checker) => checker());
23
+ }
24
+ export { checkAuth, checkAllAuth };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Credential extraction for AI coding agents.
3
+ *
4
+ * Extracts full credential data from each agent's storage for export.
5
+ */
6
+ import type { AgentId } from "../types.js";
7
+ import type { Credentials } from "./types.js";
8
+ /** Extract credentials for a specific agent */
9
+ declare function extractCredentials(agentId: AgentId): Credentials | undefined;
10
+ export { extractCredentials };
11
+ export type { Credentials } from "./types.js";
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Credential extraction for AI coding agents.
3
+ *
4
+ * Extracts full credential data from each agent's storage for export.
5
+ */
6
+ import { extractCredentials as extractClaudeCode } from "./agents/claude-code.js";
7
+ import { extractCredentials as extractCodex } from "./agents/codex.js";
8
+ import { extractCredentials as extractGemini } from "./agents/gemini.js";
9
+ import { extractCredentials as extractOpenCode } from "./agents/opencode.js";
10
+ const EXTRACTORS = {
11
+ "claude-code": extractClaudeCode,
12
+ codex: extractCodex,
13
+ gemini: extractGemini,
14
+ opencode: extractOpenCode,
15
+ };
16
+ /** Extract credentials for a specific agent */
17
+ function extractCredentials(agentId) {
18
+ return EXTRACTORS[agentId]();
19
+ }
20
+ export { extractCredentials };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Access token extraction from agent credentials.
3
+ *
4
+ * Provides functions to extract access tokens from credentials
5
+ * and convert credentials to environment variables.
6
+ */
7
+ import type { AgentId } from "../types.js";
8
+ import type { Credentials } from "./types.js";
9
+ /**
10
+ * Extract access token from credentials.
11
+ *
12
+ * Returns the primary access token (OAuth token or API key) from
13
+ * the credential data based on agent type.
14
+ */
15
+ declare function getAccessToken(creds: Credentials): string | undefined;
16
+ /**
17
+ * Get access token for an agent.
18
+ *
19
+ * Convenience function that extracts credentials and returns the access token.
20
+ *
21
+ * @example
22
+ * const token = getAgentAccessToken("claude-code");
23
+ * if (token) {
24
+ * // Use token for API calls
25
+ * }
26
+ */
27
+ declare function getAgentAccessToken(agentId: AgentId): string | undefined;
28
+ /**
29
+ * Convert credentials to environment variables.
30
+ *
31
+ * Returns a record of environment variable names to values that can be
32
+ * used to authenticate the agent via environment.
33
+ */
34
+ declare function credentialsToEnvironment(creds: Credentials): Record<string, string>;
35
+ export { credentialsToEnvironment, getAccessToken, getAgentAccessToken };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Access token extraction from agent credentials.
3
+ *
4
+ * Provides functions to extract access tokens from credentials
5
+ * and convert credentials to environment variables.
6
+ */
7
+ import { extractCredentials } from "./extract-credentials.js";
8
+ /**
9
+ * Extract access token from credentials.
10
+ *
11
+ * Returns the primary access token (OAuth token or API key) from
12
+ * the credential data based on agent type.
13
+ */
14
+ function getAccessToken(creds) {
15
+ const data = creds.data;
16
+ switch (creds.agent) {
17
+ case "claude-code": {
18
+ if (creds.type === "oauth" && typeof data.accessToken === "string") {
19
+ return data.accessToken;
20
+ }
21
+ if (creds.type === "api-key" && typeof data.apiKey === "string") {
22
+ return data.apiKey;
23
+ }
24
+ break;
25
+ }
26
+ case "codex": {
27
+ if (creds.type === "api-key" && typeof data.apiKey === "string") {
28
+ return data.apiKey;
29
+ }
30
+ if (creds.type === "oauth" && typeof data.access_token === "string") {
31
+ return data.access_token;
32
+ }
33
+ break;
34
+ }
35
+ case "gemini": {
36
+ if (creds.type === "api-key" && typeof data.apiKey === "string") {
37
+ return data.apiKey;
38
+ }
39
+ if (creds.type === "oauth" && typeof data.access_token === "string") {
40
+ return data.access_token;
41
+ }
42
+ break;
43
+ }
44
+ case "opencode": {
45
+ // OpenCode stores provider tokens; return first available
46
+ for (const provider of Object.values(data)) {
47
+ if (provider &&
48
+ typeof provider === "object" &&
49
+ "access_token" in provider &&
50
+ typeof provider.access_token === "string") {
51
+ return provider.access_token;
52
+ }
53
+ }
54
+ break;
55
+ }
56
+ }
57
+ return undefined;
58
+ }
59
+ /**
60
+ * Get access token for an agent.
61
+ *
62
+ * Convenience function that extracts credentials and returns the access token.
63
+ *
64
+ * @example
65
+ * const token = getAgentAccessToken("claude-code");
66
+ * if (token) {
67
+ * // Use token for API calls
68
+ * }
69
+ */
70
+ function getAgentAccessToken(agentId) {
71
+ const creds = extractCredentials(agentId);
72
+ if (!creds)
73
+ return undefined;
74
+ return getAccessToken(creds);
75
+ }
76
+ /**
77
+ * Convert credentials to environment variables.
78
+ *
79
+ * Returns a record of environment variable names to values that can be
80
+ * used to authenticate the agent via environment.
81
+ */
82
+ function credentialsToEnvironment(creds) {
83
+ const environment = {};
84
+ const data = creds.data;
85
+ switch (creds.agent) {
86
+ case "claude-code": {
87
+ if (creds.type === "oauth" && typeof data.accessToken === "string") {
88
+ environment.CLAUDE_CODE_OAUTH_TOKEN = data.accessToken;
89
+ }
90
+ else if (creds.type === "api-key" && typeof data.apiKey === "string") {
91
+ environment.ANTHROPIC_API_KEY = data.apiKey;
92
+ }
93
+ break;
94
+ }
95
+ case "codex": {
96
+ if (creds.type === "api-key" && typeof data.apiKey === "string") {
97
+ environment.OPENAI_API_KEY = data.apiKey;
98
+ }
99
+ // OAuth tokens for Codex require auth.json file, not env vars
100
+ break;
101
+ }
102
+ case "gemini": {
103
+ if (creds.type === "api-key" && typeof data.apiKey === "string") {
104
+ environment.GEMINI_API_KEY = data.apiKey;
105
+ }
106
+ // OAuth tokens for Gemini require oauth_creds.json file
107
+ break;
108
+ }
109
+ case "opencode": {
110
+ // OpenCode requires auth.json file, no env var support
111
+ break;
112
+ }
113
+ }
114
+ return environment;
115
+ }
116
+ export { credentialsToEnvironment, getAccessToken, getAgentAccessToken };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Shared types for auth module.
3
+ */
4
+ import type { AgentId } from "../types.js";
5
+ /** Auth status for an agent */
6
+ interface AuthStatus {
7
+ agentId: AgentId;
8
+ authenticated: boolean;
9
+ method?: string;
10
+ /** Additional details (e.g., provider list for opencode) */
11
+ details?: Record<string, unknown>;
12
+ }
13
+ /** Extracted credential data */
14
+ interface Credentials {
15
+ agent: AgentId;
16
+ type: "oauth" | "api-key";
17
+ data: Record<string, unknown>;
18
+ }
19
+ export type { AuthStatus, Credentials };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Shared types for auth module.
3
+ */
4
+ export {};
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Build agent-specific configuration from CLI options.
3
+ */
4
+ import type { AgentId, PermissionIssue } from "./types.js";
5
+ /** Result of building agent config from CLI options */
6
+ type AgentConfigResult = {
7
+ ok: true;
8
+ env: Record<string, string>;
9
+ warnings: PermissionIssue[];
10
+ } | {
11
+ ok: false;
12
+ exitCode: number;
13
+ errors: PermissionIssue[];
14
+ } | {
15
+ ok: false;
16
+ exitCode: number;
17
+ message: string;
18
+ };
19
+ /** Options for building agent config */
20
+ interface BuildAgentConfigOptions {
21
+ agentId: AgentId;
22
+ allow: string | undefined;
23
+ deny: string | undefined;
24
+ output: string;
25
+ }
26
+ /**
27
+ * Build agent-specific config from CLI permission options.
28
+ *
29
+ * Parses --allow and --deny options, validates them against agent capabilities,
30
+ * and returns the environment variables needed to pass config to the agent.
31
+ */
32
+ declare function buildAgentConfig(options: BuildAgentConfigOptions): AgentConfigResult;
33
+ /**
34
+ * Format permission errors for display.
35
+ */
36
+ declare function formatPermissionErrors(errors: PermissionIssue[]): string;
37
+ /**
38
+ * Format permission warnings for display.
39
+ */
40
+ declare function formatPermissionWarnings(warnings: PermissionIssue[]): string;
41
+ export { buildAgentConfig, formatPermissionErrors, formatPermissionWarnings };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Build agent-specific configuration from CLI options.
3
+ */
4
+ import { getConfigBuilder } from "./builder.js";
5
+ import { formatRule, parsePermissions } from "./parse-permissions.js";
6
+ /**
7
+ * Build agent-specific config from CLI permission options.
8
+ *
9
+ * Parses --allow and --deny options, validates them against agent capabilities,
10
+ * and returns the environment variables needed to pass config to the agent.
11
+ */
12
+ function buildAgentConfig(options) {
13
+ const { agentId, allow, deny, output } = options;
14
+ // Parse permissions
15
+ let axrunConfig = {};
16
+ if (allow !== undefined || deny !== undefined) {
17
+ try {
18
+ const permissions = parsePermissions(allow ? [allow] : [], deny ? [deny] : []);
19
+ axrunConfig = { permissions };
20
+ }
21
+ catch (error) {
22
+ const message = error instanceof Error ? error.message : String(error);
23
+ return {
24
+ ok: false,
25
+ exitCode: 2,
26
+ message: `Invalid permission syntax: ${message}`,
27
+ };
28
+ }
29
+ }
30
+ // Build agent-specific config
31
+ const configBuilder = getConfigBuilder(agentId);
32
+ if (!configBuilder) {
33
+ // No config builder for this agent - return empty config
34
+ return {
35
+ ok: true,
36
+ env: {},
37
+ warnings: [],
38
+ };
39
+ }
40
+ const buildResult = configBuilder.build(axrunConfig, output);
41
+ if (!buildResult.ok) {
42
+ return {
43
+ ok: false,
44
+ exitCode: 1,
45
+ errors: buildResult.errors,
46
+ };
47
+ }
48
+ return {
49
+ ok: true,
50
+ env: buildResult.env,
51
+ warnings: buildResult.warnings,
52
+ };
53
+ }
54
+ /**
55
+ * Format permission errors for display.
56
+ */
57
+ function formatPermissionErrors(errors) {
58
+ const lines = [
59
+ "Error: Cannot run agent with specified permissions:",
60
+ "",
61
+ ];
62
+ for (const error of errors) {
63
+ const suggestionLines = error.suggestions.map((s) => ` • ${s}`);
64
+ lines.push(` ✗ ${formatRule(error.rule)}`, ` ${error.reason}`, " Suggestions:", ...suggestionLines, "");
65
+ }
66
+ return lines.join("\n");
67
+ }
68
+ /**
69
+ * Format permission warnings for display.
70
+ */
71
+ function formatPermissionWarnings(warnings) {
72
+ const lines = [];
73
+ for (const warning of warnings) {
74
+ const suggestionLines = warning.suggestions.map((s) => ` • ${s}`);
75
+ lines.push(`⚠ Warning: Rule "${formatRule(warning.rule)}" was REMOVED`, ` ${warning.reason}`, " Suggestions:", ...suggestionLines, "");
76
+ }
77
+ return lines.join("\n");
78
+ }
79
+ export { buildAgentConfig, formatPermissionErrors, formatPermissionWarnings };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ConfigBuilder registry.
3
+ *
4
+ * Each agent registers its ConfigBuilder to translate AxrunConfig
5
+ * into agent-specific configuration files.
6
+ */
7
+ import type { AgentId, ConfigBuilder } from "./types.js";
8
+ /**
9
+ * Register a config builder for an agent.
10
+ * Called by each agent's config-builder module on import.
11
+ */
12
+ declare function registerConfigBuilder(builder: ConfigBuilder): void;
13
+ /**
14
+ * Get the config builder for an agent.
15
+ *
16
+ * @returns The config builder, or undefined if not registered
17
+ */
18
+ declare function getConfigBuilder(agentId: AgentId): ConfigBuilder | undefined;
19
+ export { getConfigBuilder, registerConfigBuilder };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * ConfigBuilder registry.
3
+ *
4
+ * Each agent registers its ConfigBuilder to translate AxrunConfig
5
+ * into agent-specific configuration files.
6
+ */
7
+ /** Registry of config builders by agent ID */
8
+ const configBuilders = new Map();
9
+ /**
10
+ * Register a config builder for an agent.
11
+ * Called by each agent's config-builder module on import.
12
+ */
13
+ function registerConfigBuilder(builder) {
14
+ if (configBuilders.has(builder.agentId)) {
15
+ throw new Error(`ConfigBuilder for "${builder.agentId}" is already registered`);
16
+ }
17
+ configBuilders.set(builder.agentId, builder);
18
+ }
19
+ /**
20
+ * Get the config builder for an agent.
21
+ *
22
+ * @returns The config builder, or undefined if not registered
23
+ */
24
+ function getConfigBuilder(agentId) {
25
+ return configBuilders.get(agentId);
26
+ }
27
+ export { getConfigBuilder, registerConfigBuilder };
package/dist/cli.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * axconfig - AI agent configuration CLI.
4
+ *
5
+ * Manages configurations for AI coding agents.
6
+ */
7
+ import "./agents/claude-code.js";
8
+ import "./agents/codex.js";
9
+ import "./agents/gemini.js";
10
+ import "./agents/opencode.js";
package/dist/cli.js ADDED
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * axconfig - AI agent configuration CLI.
4
+ *
5
+ * Manages configurations for AI coding agents.
6
+ */
7
+ import { Command } from "@commander-js/extra-typings";
8
+ import packageJson from "../package.json" with { type: "json" };
9
+ import { handleAuthExport, handleAuthList, handleAuthToken, } from "./commands/auth.js";
10
+ import { handleCreate } from "./commands/create.js";
11
+ import { AGENT_IDS } from "./types.js";
12
+ // Import to trigger self-registration
13
+ import "./agents/claude-code.js";
14
+ import "./agents/codex.js";
15
+ import "./agents/gemini.js";
16
+ import "./agents/opencode.js";
17
+ // Handle SIGINT gracefully
18
+ process.on("SIGINT", () => {
19
+ console.error("\nInterrupted");
20
+ process.exit(130); // 128 + SIGINT(2)
21
+ });
22
+ const program = new Command()
23
+ .name(packageJson.name)
24
+ .description(packageJson.description)
25
+ .version(packageJson.version, "-V, --version")
26
+ .showHelpAfterError("(add --help for additional information)")
27
+ .showSuggestionAfterError()
28
+ .helpCommand(false)
29
+ .addHelpText("after", String.raw `
30
+ Examples:
31
+ # Create config and source it in current shell
32
+ eval $(axconfig create --agent claude-code --output /tmp/cfg --allow read)
33
+
34
+ # List authenticated agents
35
+ axconfig auth list
36
+
37
+ # Filter to show only authenticated agents
38
+ axconfig auth list | tail -n +2 | awk -F'\t' '$2 == "authenticated"'
39
+
40
+ # Get access token for an agent
41
+ axconfig auth token --agent claude-code
42
+
43
+ # Export credentials for CI/CD
44
+ axconfig auth export --agent claude-code --output creds.json --no-password`);
45
+ program
46
+ .command("create")
47
+ .description("Create agent-specific configuration")
48
+ .requiredOption("-a, --agent <agent>", `Agent to configure (${AGENT_IDS.join(", ")})`)
49
+ .requiredOption("--output <dir>", "Directory to write config files")
50
+ .option("--allow <rules>", "Comma-separated permissions to allow (e.g., 'read,glob,bash:git *')")
51
+ .option("--deny <rules>", "Comma-separated permissions to deny (e.g., 'bash:rm *,read:.env')")
52
+ .option("--format <format>", "Output format: env (shell export), json", "env")
53
+ .option("--with-credentials <file>", "Path to encrypted credentials file (from 'auth export')")
54
+ .action(handleCreate);
55
+ // =============================================================================
56
+ // Auth Commands
57
+ // =============================================================================
58
+ const auth = program
59
+ .command("auth")
60
+ .description("Manage agent credentials")
61
+ .helpCommand(false);
62
+ auth
63
+ .command("list")
64
+ .description("List agents and their auth status")
65
+ .option("--json", "Output as JSON")
66
+ .action(handleAuthList);
67
+ auth
68
+ .command("token")
69
+ .description("Get access token for an agent")
70
+ .requiredOption("-a, --agent <agent>", `Agent to get token from (${AGENT_IDS.join(", ")})`)
71
+ .action(handleAuthToken);
72
+ auth
73
+ .command("export")
74
+ .description("Export credentials to encrypted file")
75
+ .requiredOption("-a, --agent <agent>", `Agent to export credentials from (${AGENT_IDS.join(", ")})`)
76
+ .requiredOption("--output <file>", "Output file path")
77
+ .option("--no-password", "Use default password (no prompt)")
78
+ .action(handleAuthExport);
79
+ await program.parseAsync(process.argv);
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Auth commands - manage agent credentials.
3
+ */
4
+ /** Handle auth list command */
5
+ declare function handleAuthList(options: {
6
+ json?: true;
7
+ }): void;
8
+ /** Handle auth token command */
9
+ declare function handleAuthToken(options: {
10
+ agent: string;
11
+ }): void;
12
+ interface AuthExportOptions {
13
+ agent: string;
14
+ output: string;
15
+ password: boolean;
16
+ }
17
+ /** Handle auth export command */
18
+ declare function handleAuthExport(options: AuthExportOptions): Promise<void>;
19
+ export { handleAuthExport, handleAuthList, handleAuthToken };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Auth commands - manage agent credentials.
3
+ */
4
+ import { renameSync, writeFileSync } from "node:fs";
5
+ import promptPassword from "@inquirer/password";
6
+ import { checkAllAuth } from "../auth/check-auth.js";
7
+ import { extractCredentials } from "../auth/extract-credentials.js";
8
+ import { getAccessToken } from "../auth/get-access-token.js";
9
+ import { DEFAULT_PASSWORD, encrypt, toBase64 } from "../crypto.js";
10
+ import { AGENT_IDS } from "../types.js";
11
+ /** Handle auth list command */
12
+ function handleAuthList(options) {
13
+ const statuses = checkAllAuth();
14
+ if (options.json) {
15
+ console.log(JSON.stringify(statuses, undefined, 2));
16
+ }
17
+ else {
18
+ printAuthTable(statuses);
19
+ }
20
+ }
21
+ /** Handle auth token command */
22
+ function handleAuthToken(options) {
23
+ const { agent } = options;
24
+ // Validate agent
25
+ if (!AGENT_IDS.includes(agent)) {
26
+ console.error(`Error: Unknown agent '${agent}'`);
27
+ console.error(`Supported agents: ${AGENT_IDS.join(", ")}`);
28
+ process.exitCode = 2;
29
+ return;
30
+ }
31
+ const creds = extractCredentials(agent);
32
+ if (!creds) {
33
+ console.error(`Error: No credentials found for ${agent}`);
34
+ process.exitCode = 1;
35
+ return;
36
+ }
37
+ // Extract the token based on credential type
38
+ const token = getAccessToken(creds);
39
+ if (!token) {
40
+ console.error(`Error: No access token available for ${agent}`);
41
+ process.exitCode = 1;
42
+ return;
43
+ }
44
+ // Output just the token (no newline for piping)
45
+ process.stdout.write(token);
46
+ }
47
+ /** Handle auth export command */
48
+ async function handleAuthExport(options) {
49
+ const { agent } = options;
50
+ // Validate agent
51
+ if (!AGENT_IDS.includes(agent)) {
52
+ console.error(`Error: Unknown agent '${agent}'`);
53
+ console.error(`Supported agents: ${AGENT_IDS.join(", ")}`);
54
+ process.exitCode = 2;
55
+ return;
56
+ }
57
+ const creds = extractCredentials(agent);
58
+ if (!creds) {
59
+ console.error(`Error: No credentials found for ${agent}`);
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+ // Get password
64
+ const userPassword = options.password
65
+ ? await promptPassword({ message: "Encryption password" })
66
+ : DEFAULT_PASSWORD;
67
+ // Encrypt and write atomically (write to temp, then rename)
68
+ const encrypted = encrypt(JSON.stringify(creds), userPassword);
69
+ const file = { version: 1, agent, ...toBase64(encrypted) };
70
+ const temporaryFile = `${options.output}.tmp.${Date.now()}`;
71
+ writeFileSync(temporaryFile, JSON.stringify(file, undefined, 2), {
72
+ mode: 0o600,
73
+ });
74
+ renameSync(temporaryFile, options.output);
75
+ console.error(`Credentials exported to ${options.output}`);
76
+ }
77
+ /** Print auth status as TSV table */
78
+ function printAuthTable(statuses) {
79
+ // Header row (UPPERCASE for visibility)
80
+ console.log("AGENT\tSTATUS\tMETHOD");
81
+ // Data rows
82
+ for (const s of statuses) {
83
+ const status = s.authenticated ? "authenticated" : "not_configured";
84
+ console.log(`${s.agentId}\t${status}\t${s.method ?? ""}`);
85
+ }
86
+ }
87
+ export { handleAuthExport, handleAuthList, handleAuthToken };