axauth 3.1.0 → 3.1.2

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,13 +24,27 @@ axauth provides a consistent interface for managing credentials across multiple
24
24
  ## Installation
25
25
 
26
26
  ```bash
27
- npm install axauth
27
+ # CLI (global)
28
+ npm install -g axauth
28
29
  # or
29
- pnpm add axauth
30
+ pnpm add -g axauth
31
+
32
+ # Library usage (non-global)
33
+ npm install axauth
30
34
  ```
31
35
 
36
+ ## Prerequisites
37
+
38
+ - Node.js 22+
39
+ - pnpm or npm
40
+ - jq for JSON examples
41
+ - Agent CLIs installed (as needed): `claude`, `codex`, `gemini`, `opencode`, `copilot`
42
+ - POSIX shell assumed in examples (bash/zsh); PowerShell needs syntax adjustments
43
+
32
44
  ## CLI Usage
33
45
 
46
+ Examples use long-form flags; short flags exist but prefer long for clarity.
47
+
34
48
  ```bash
35
49
  # List agents and their auth status
36
50
  axauth list
@@ -53,18 +67,34 @@ axauth remove-credentials --agent claude
53
67
  axauth remove-credentials --agent claude --config-dir /tmp/config
54
68
  ```
55
69
 
70
+ ## Output Formats
71
+
72
+ - `axauth list` outputs TSV by default; `--json` returns a JSON array
73
+ - `axauth vault fetch` outputs JSON by default; `--json` pretty-prints JSON
74
+ - `axauth token` outputs the raw token for piping
75
+
56
76
  ### Pipeline Examples
57
77
 
58
- The CLI outputs TSV format for easy processing with standard Unix tools:
78
+ The `axauth list` command outputs TSV with a header row:
79
+
80
+ - Columns: `AGENT`, `STATUS`, `METHOD`
81
+ - `STATUS` values: `authenticated` | `not_configured`
59
82
 
60
83
  ```bash
61
84
  # List all agents and their auth status
62
85
  axauth list
63
- # AGENT STATUS METHOD
64
- # claude authenticated OAuth (max)
65
- # codex authenticated ChatGPT OAuth
66
- # ...
86
+ ```
67
87
 
88
+ Output (TSV):
89
+
90
+ ```
91
+ AGENT STATUS METHOD
92
+ claude authenticated OAuth (max)
93
+ codex authenticated ChatGPT OAuth
94
+ ...
95
+ ```
96
+
97
+ ```bash
68
98
  # Filter to show only authenticated agents
69
99
  axauth list | tail -n +2 | awk -F'\t' '$2 == "authenticated"'
70
100
 
@@ -80,6 +110,10 @@ curl -s -H "Authorization: Bearer $(axauth token --agent claude)" \
80
110
  https://api.anthropic.com/api/oauth/usage | jq .
81
111
  ```
82
112
 
113
+ ## Security Note: `--no-password`
114
+
115
+ `--no-password` uses a deterministic “default password” derived from the source code. This is intended for CI/CD convenience (e.g., storing the exported file as a secret), not for protecting credentials at rest.
116
+
83
117
  ## Library API
84
118
 
85
119
  ```typescript
@@ -170,9 +204,9 @@ Each agent adapter declares its storage capabilities:
170
204
  | Agent | Keychain | File | Environment | Install API Key |
171
205
  | -------- | :------: | :--: | :---------: | :-------------: |
172
206
  | claude | macOS | Yes | Yes | No (env-only) |
173
- | codex | macOS | Yes | Yes | No (env-only) |
207
+ | codex | macOS | Yes | Yes | Yes |
174
208
  | gemini | macOS | Yes | Yes | No (env-only) |
175
- | opencode | No | Yes | Yes | No |
209
+ | opencode | No | Yes | No | Yes |
176
210
  | copilot | macOS | Yes | Yes | No (env-only) |
177
211
 
178
212
  **Notes:**
@@ -215,47 +249,24 @@ For CI/CD workflows, credentials can be passed via environment variables:
215
249
 
216
250
  Use `installCredentialsFromEnvironmentVariable()` to install credentials from these variables programmatically.
217
251
 
218
- ## Config Directory Requirements
252
+ ## Custom Directory Behavior
219
253
 
220
- Some agents require specific directory name suffixes:
254
+ Directory handling depends on whether the agent separates config and data:
221
255
 
222
- | Agent | Directory Requirement | Example |
223
- | -------- | ------------------------ | -------------------- |
224
- | claude | Any name | `/tmp/my-config` |
225
- | codex | Any name | `/tmp/my-config` |
226
- | gemini | Must end with `.gemini` | `/tmp/home/.gemini` |
227
- | copilot | Must end with `.copilot` | `/tmp/home/.copilot` |
228
- | opencode | Must end with `opencode` | `/tmp/data/opencode` |
256
+ - **Shared config/data agents** (`claude`, `codex`, `gemini`, `copilot`): `--config-dir` and `--data-dir` are interchangeable and point to the same location.
257
+ - **Separate config/data agent** (`opencode`): `--config-dir` and `--data-dir` are independent.
258
+ If only one is provided, the other uses the default location and axauth emits a warning.
229
259
 
230
260
  ## Architecture
231
261
 
232
- axauth follows the adapter pattern with a functional core:
262
+ axauth follows an adapter architecture with a functional core:
233
263
 
234
- ```
235
- src/
236
- ├── index.ts # Public API exports
237
- ├── cli.ts # CLI entry point
238
- ├── crypto.ts # AES-256-GCM encryption
239
- ├── commands/
240
- │ └── auth.ts # CLI command handlers
241
- └── auth/
242
- ├── adapter.ts # AuthAdapter interface
243
- ├── types.ts # AuthStatus, Credentials types
244
- ├── registry.ts # Adapter registry and unified operations
245
- └── agents/ # Agent-specific adapters
246
- ├── claude-code.ts
247
- ├── claude-code-storage.ts
248
- ├── codex.ts
249
- ├── codex-storage.ts
250
- ├── codex-config.ts
251
- ├── gemini.ts
252
- ├── gemini-storage.ts
253
- ├── gemini-auth-check.ts
254
- ├── copilot.ts
255
- ├── copilot-storage.ts
256
- ├── copilot-auth-check.ts
257
- └── opencode.ts
258
- ```
264
+ - `src/auth/` — core auth domain logic, adapter interfaces, registry, shared utilities
265
+ - `src/auth/agents/` — agent-specific adapter implementations and storage/install/remove flows
266
+ - `src/commands/` CLI command handlers (`list`, `token`, `export`, `install-credentials`, `vault`, etc.)
267
+ - `src/vault/` axvault client/config integration for fetch/push workflows
268
+ - `src/crypto.ts` — credential encryption/decryption primitives (AES-256-GCM + PBKDF2)
269
+ - `src/index.ts` / `src/cli.ts` — library exports and CLI entrypoint
259
270
 
260
271
  ## Related Packages
261
272
 
@@ -23,7 +23,7 @@ async function handleAuthToken(options) {
23
23
  // OpenCode requires --provider
24
24
  if (agentId === "opencode" && !options.provider) {
25
25
  console.error("Error: --provider is required for opencode");
26
- console.error("Hint: Use 'axauth auth list' to see available providers");
26
+ console.error("Hint: Use 'axauth list --json' to see available providers");
27
27
  process.exitCode = 1;
28
28
  return;
29
29
  }
@@ -141,7 +141,7 @@ async function handleVaultPush(options) {
141
141
  }
142
142
  if (agentId === "opencode" && !options.provider) {
143
143
  console.error("Error: --provider is required for opencode");
144
- console.error("Hint: Use 'axauth auth list' to see available providers");
144
+ console.error("Hint: Use 'axauth list --json' to see available providers");
145
145
  process.exitCode = 1;
146
146
  return;
147
147
  }
@@ -159,7 +159,7 @@ async function handleVaultPush(options) {
159
159
  if (!credentials) {
160
160
  const hint = agentId === "opencode"
161
161
  ? `No credentials found for provider '${options.provider}'`
162
- : `No credentials found for ${agentId}\nHint: Authenticate with the agent first, or use 'axauth auth list' to check status`;
162
+ : `No credentials found for ${agentId}\nHint: Authenticate with the agent first, or use 'axauth list' to check status`;
163
163
  console.error(`Error: ${hint}`);
164
164
  process.exitCode = 1;
165
165
  return;
@@ -5,7 +5,7 @@
5
5
  * a remote axvault server. It handles authentication, error responses,
6
6
  * and returns a typed result.
7
7
  */
8
- import { type AgentCli } from "axshared";
8
+ import type { AgentCli } from "axshared";
9
9
  import type { Credentials } from "../auth/types.js";
10
10
  /** Reason why vault operation failed */
11
11
  type VaultFailureReason = "not-configured" | "unreachable" | "unauthorized" | "forbidden" | "not-found" | "legacy-credential" | "client-error" | "server-error";
@@ -5,17 +5,12 @@
5
5
  * a remote axvault server. It handles authentication, error responses,
6
6
  * and returns a typed result.
7
7
  */
8
- import { CredentialType } from "axshared";
9
8
  import { z } from "zod";
10
9
  import { getVaultConfig } from "./vault-config.js";
11
- /** Zod schema for vault API response */
10
+ /** Zod schema for vault API response envelope */
12
11
  const VaultCredentialResponse = z.object({
13
- agent: z.string(),
14
12
  name: z.string(),
15
- type: CredentialType,
16
- data: z.record(z.string(), z.unknown()),
17
- provider: z.string().trim().min(1).optional(), // OpenCode provider support
18
- expiresAt: z.string().nullish(), // optional for oauth-token type
13
+ credential: z.record(z.string(), z.unknown()),
19
14
  updatedAt: z.string(),
20
15
  });
21
16
  /**
@@ -41,7 +36,7 @@ async function fetchVaultCredentials(options) {
41
36
  if (!config) {
42
37
  return { ok: false, reason: "not-configured" };
43
38
  }
44
- const url = `${config.url}/api/v1/credentials/${encodeURIComponent(options.agentId)}/${encodeURIComponent(options.name)}`;
39
+ const url = `${config.url}/api/v1/credentials/${encodeURIComponent(options.name)}`;
45
40
  try {
46
41
  const response = await fetch(url, {
47
42
  method: "GET",
@@ -83,33 +78,11 @@ async function fetchVaultCredentials(options) {
83
78
  const refreshFailed = response.headers.get("X-Axvault-Refresh-Failed") === "true";
84
79
  // Log warning if refresh failed (stale credentials returned)
85
80
  if (refreshFailed) {
86
- console.error(`[axauth] Vault returned stale credentials for ${options.agentId}/${options.name} (refresh failed)`);
81
+ console.error(`[axauth] Vault returned stale credentials for ${options.name} (refresh failed)`);
87
82
  }
88
- // Build credentials based on agent type
89
- // OpenCode requires provider field - treat missing provider as server error
90
- if (options.agentId === "opencode") {
91
- if (!body.provider) {
92
- return { ok: false, reason: "server-error" };
93
- }
94
- return {
95
- ok: true,
96
- credentials: {
97
- agent: options.agentId,
98
- type: body.type,
99
- provider: body.provider,
100
- data: body.data,
101
- },
102
- refreshed: wasRefreshed,
103
- };
104
- }
105
- const credentials = {
106
- agent: options.agentId,
107
- type: body.type,
108
- data: body.data,
109
- };
110
83
  return {
111
84
  ok: true,
112
- credentials,
85
+ credentials: body.credential,
113
86
  refreshed: wasRefreshed,
114
87
  };
115
88
  }
@@ -145,7 +118,7 @@ async function pushVaultCredentials(options) {
145
118
  if (!config) {
146
119
  return { ok: false, reason: "not-configured" };
147
120
  }
148
- const url = `${config.url}/api/v1/credentials/${encodeURIComponent(options.agentId)}/${encodeURIComponent(options.name)}`;
121
+ const url = `${config.url}/api/v1/credentials/${encodeURIComponent(options.name)}`;
149
122
  try {
150
123
  const response = await fetch(url, {
151
124
  method: "PUT",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "axauth",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "3.1.0",
5
+ "version": "3.1.2",
6
6
  "description": "Authentication management library and CLI for AI coding agents",
7
7
  "repository": {
8
8
  "type": "git",
@@ -62,7 +62,7 @@
62
62
  "automation",
63
63
  "coding-assistant"
64
64
  ],
65
- "packageManager": "pnpm@10.28.0",
65
+ "packageManager": "pnpm@10.28.1",
66
66
  "engines": {
67
67
  "node": ">=22.14.0"
68
68
  },
@@ -70,21 +70,21 @@
70
70
  "@commander-js/extra-typings": "^14.0.0",
71
71
  "@inquirer/password": "^5.0.4",
72
72
  "axconfig": "^3.6.3",
73
- "axexec": "^1.6.0",
73
+ "axexec": "^1.7.0",
74
74
  "axshared": "^4.0.0",
75
75
  "commander": "^14.0.2",
76
76
  "zod": "^4.3.5"
77
77
  },
78
78
  "devDependencies": {
79
79
  "@total-typescript/ts-reset": "^0.6.1",
80
- "@types/node": "^25.0.9",
80
+ "@types/node": "^25.0.10",
81
81
  "@vitest/coverage-v8": "^4.0.17",
82
82
  "eslint": "^9.39.2",
83
83
  "eslint-config-axkit": "^1.1.0",
84
84
  "fta-check": "^1.5.1",
85
85
  "fta-cli": "^3.0.0",
86
- "knip": "^5.82.0",
87
- "prettier": "3.8.0",
86
+ "knip": "^5.82.1",
87
+ "prettier": "3.8.1",
88
88
  "semantic-release": "^25.0.2",
89
89
  "typescript": "^5.9.3",
90
90
  "vitest": "^4.0.17"