axinstall 1.3.0 → 1.4.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.
package/README.md CHANGED
@@ -6,37 +6,30 @@ Install AI CLI agents (Claude Code, Codex, Gemini, etc.) in any environment.
6
6
 
7
7
  ```bash
8
8
  # Install Claude Code globally
9
- npx -y axinstall "claude"
9
+ npx axinstall claude
10
+
11
+ # Install multiple agents in one command
12
+ npx axinstall claude codex gemini opencode copilot
10
13
 
11
14
  # Install with a specific package manager
12
- npx -y axinstall "claude" --with "npm"
15
+ npx axinstall claude --with npm
13
16
 
14
17
  # Preview what would be installed (dry run)
15
- npx -y axinstall "claude" --dry-run
18
+ npx axinstall claude --dry-run
19
+
20
+ # Enable verbose output
21
+ npx axinstall claude --verbose
16
22
 
17
23
  # List supported agents
18
- npx -y axinstall --list-agents
24
+ npx axinstall --list-agents
19
25
 
20
26
  # Check installed agents and available package managers
21
- npx -y axinstall --status
22
-
23
- # Enable verbose output
24
- npx -y axinstall "claude" --verbose
27
+ npx axinstall --status
25
28
  ```
26
29
 
27
- ## Prerequisites
28
-
29
- - Node.js >=22.14.0
30
- - Use `pnpm dlx` (recommended) or `npx` (bundled with npm) for one-off runs
31
- - Examples assume a POSIX shell (sh/bash/zsh); adjust for PowerShell or CMD
30
+ ## Requirements
32
31
 
33
- By default, `axinstall` installs agents using **npm**. This means `npm` must be
34
- available unless you explicitly override the installer:
35
-
36
- - `--with <installer>` (e.g., `--with "pnpm"`)
37
- - `AXINSTALL_WITH=<installer>`
38
-
39
- Supported installers:
32
+ axinstall needs at least one supported package manager available:
40
33
 
41
34
  - npm
42
35
  - pnpm
@@ -44,11 +37,6 @@ Supported installers:
44
37
  - yarn
45
38
  - Homebrew (`brew`)
46
39
 
47
- ## Conventions
48
-
49
- - Prefer long flags in scripts (`--verbose` instead of `-v`)
50
- - Examples include explicit quoting for flag values and arguments
51
-
52
40
  ### Custom Paths
53
41
 
54
42
  Override the default binary lookup by setting environment variables:
@@ -61,59 +49,46 @@ export AXINSTALL_YARN_PATH=/path/to/yarn
61
49
  export AXINSTALL_BREW_PATH=/path/to/brew
62
50
  ```
63
51
 
52
+ Choose a default installer via environment variable:
53
+
54
+ ```bash
55
+ export AXINSTALL_WITH=pnpm
56
+ ```
57
+
64
58
  ## Examples
65
59
 
66
60
  ### Install agents
67
61
 
68
62
  ```bash
69
- # Install using npm (default)
70
- npx -y axinstall "claude"
71
- npx -y axinstall "codex"
72
- npx -y axinstall "gemini"
63
+ # Install using auto-detected package manager (npm > pnpm > bun > yarn > brew)
64
+ axinstall claude
65
+ axinstall codex
66
+ axinstall gemini
67
+ axinstall claude codex gemini opencode copilot
73
68
 
74
69
  # Force a specific package manager
75
- npx -y axinstall "claude" --with "npm"
76
- npx -y axinstall "opencode" --with "brew"
70
+ axinstall claude --with npm
71
+ axinstall opencode --with brew
77
72
 
78
73
  # Install locally (not globally)
79
- npx -y axinstall "claude" --local
74
+ axinstall claude --local
80
75
  ```
81
76
 
82
77
  ### Pipeline examples
83
78
 
84
79
  ```bash
85
80
  # Get list of agent CLI names
86
- npx -y axinstall --list-agents | tail -n +2 | cut -f1
81
+ axinstall --list-agents | tail -n +2 | cut -f1
87
82
 
88
83
  # Find agents from a specific provider
89
- npx -y axinstall --list-agents | tail -n +2 | awk -F'\t' '$4 == "Anthropic" {print $1}'
84
+ axinstall --list-agents | tail -n +2 | awk -F'\t' '$4 == "Anthropic" {print $1}'
90
85
 
91
86
  # Get available installers only
92
- npx -y axinstall --status --only "installers" | tail -n +2 | awk -F'\t' '$4 == "available" {print $2}'
87
+ axinstall --status --only installers | tail -n +2 | awk -F'\t' '$4 == "available" {print $2}'
93
88
 
94
89
  # Count installed vs not found agents
95
- npx -y axinstall --status --only "agents" | tail -n +2 | cut -f4 | sort | uniq -c
96
- ```
97
-
98
- ## Output
99
-
100
- `--list-agents` prints a tab-separated header and rows with columns:
101
-
90
+ axinstall --status --only agents | tail -n +2 | cut -f4 | sort | uniq -c
102
91
  ```
103
- CLI NAME PACKAGE PROVIDER
104
- ```
105
-
106
- `--status` prints a tab-separated header and rows with columns:
107
-
108
- ```
109
- TYPE ID NAME STATUS VERSION PROVIDER PACKAGE
110
- ```
111
-
112
- - `TYPE` values: `AGENT` | `INSTALLER`
113
- - `STATUS` values:
114
- - for `AGENT`: `installed` | `not_found`
115
- - for `INSTALLER`: `available` | `not_found`
116
- - `--only` values: `"all"` | `"agents"` | `"installers"`
117
92
 
118
93
  ## Agent Rule
119
94
 
@@ -124,9 +99,9 @@ Add to your `CLAUDE.md` or `AGENTS.md`:
124
99
 
125
100
  Run `npx -y axinstall --help` to learn available options.
126
101
 
127
- Use `axinstall` to install AI CLI agents in any environment. It uses the
128
- requested package manager (via `--with` / `AXINSTALL_WITH`) and uses npm
129
- by default.
102
+ Use `axinstall` to install AI CLI agents in any environment. It auto-detects
103
+ the best available package manager (npm, pnpm, bun, yarn, brew) and handles
104
+ the installation with a single command.
130
105
  ```
131
106
 
132
107
  ## License
package/dist/cli.js CHANGED
@@ -36,6 +36,7 @@ const program = new Command()
36
36
  .addHelpText("after", `
37
37
  Examples:
38
38
  $ axinstall "claude" Install Claude Code globally
39
+ $ axinstall "claude" "codex" "gemini" Install multiple agents sequentially
39
40
  $ axinstall "claude" --local Install to node_modules/.bin
40
41
  $ axinstall "claude" --with "npm" Use specific package manager
41
42
  $ axinstall "claude" --dry-run Preview installation command
@@ -56,12 +57,12 @@ Supported installers:
56
57
  // Install / List / Status (Default)
57
58
  // =============================================================================
58
59
  program
59
- .argument("[agent]", `Agent to install (${AGENT_CLIS.join(", ")})`)
60
+ .argument("[agents...]", `Agents to install (${AGENT_CLIS.join(", ")})`)
60
61
  .option("--with <installer>", `Package manager to use (${INSTALLER_IDS.join(", ")})`)
61
62
  .option("--local", "Install to node_modules/.bin (run via package runner)", false)
62
63
  .option("--dry-run", "Show command without executing", false)
63
- .action((agentCli, cliOptions) => {
64
- runCommand(agentCli, cliOptions);
64
+ .action((agentClis, cliOptions) => {
65
+ runCommand(agentClis, cliOptions);
65
66
  });
66
67
  // =============================================================================
67
68
  // Parse and Execute
@@ -7,5 +7,5 @@ interface InstallOptions {
7
7
  dryRun: boolean;
8
8
  verbose?: boolean;
9
9
  }
10
- export declare function handleInstall(agentCli: string, options: InstallOptions): void;
10
+ export declare function handleInstall(agentCli: string, options: InstallOptions): boolean;
11
11
  export {};
@@ -30,7 +30,7 @@ export function handleInstall(agentCli, options) {
30
30
  console.error(`Available: ${AGENT_CLIS.join(", ")}`);
31
31
  console.error("Try 'axinstall --help' for usage information.");
32
32
  process.exitCode = 1;
33
- return;
33
+ return false;
34
34
  }
35
35
  const agent = getAgent(agentCli);
36
36
  const rawInstallerInput = options.with ?? process.env["AXINSTALL_WITH"];
@@ -40,12 +40,12 @@ export function handleInstall(agentCli, options) {
40
40
  console.error(`Available: ${INSTALLER_IDS.join(", ")}`);
41
41
  console.error("Try 'axinstall --help' for usage information.");
42
42
  process.exitCode = 1;
43
- return;
43
+ return false;
44
44
  }
45
45
  const installer = getInstaller(requestedInstaller);
46
46
  if (!isInstallerAvailable(requestedInstaller)) {
47
47
  reportMissingInstaller(installer);
48
- return;
48
+ return false;
49
49
  }
50
50
  // Validate local installation support
51
51
  if (options.local && !installer.localInstallArgs) {
@@ -56,7 +56,7 @@ export function handleInstall(agentCli, options) {
56
56
  console.error(`Error: Installer '${installer.id}' does not support local installation`);
57
57
  console.error(`Use a different installer: ${localInstallers}`);
58
58
  process.exitCode = 1;
59
- return;
59
+ return false;
60
60
  }
61
61
  const result = executeInstall({
62
62
  agent,
@@ -66,7 +66,7 @@ export function handleInstall(agentCli, options) {
66
66
  });
67
67
  if (options.dryRun) {
68
68
  console.log(result.command);
69
- return;
69
+ return true;
70
70
  }
71
71
  if (result.ok) {
72
72
  if (options.verbose) {
@@ -86,7 +86,7 @@ export function handleInstall(agentCli, options) {
86
86
  console.error(`Run '${agent.cli}' to get started.`);
87
87
  }
88
88
  }
89
- return;
89
+ return true;
90
90
  }
91
91
  console.error(`Error: Failed to install ${agent.name}`);
92
92
  console.error(`Command: ${result.command}`);
@@ -94,4 +94,5 @@ export function handleInstall(agentCli, options) {
94
94
  console.error(`Details: ${result.error.message}`);
95
95
  }
96
96
  process.exitCode = 1;
97
+ return false;
97
98
  }
@@ -10,4 +10,4 @@ export interface CliOptions {
10
10
  local: boolean;
11
11
  dryRun: boolean;
12
12
  }
13
- export declare function runCommand(agentCli: string | undefined, options: CliOptions): void;
13
+ export declare function runCommand(agentClis: string[] | undefined, options: CliOptions): void;
@@ -6,14 +6,14 @@ import { isStatusScope, printStatus, printSupportedAgents, } from "./print-statu
6
6
  import { validateOptions } from "./validate-cli-options.js";
7
7
  function reportUsageError(message) {
8
8
  console.error(`Error: ${message}`);
9
- console.error("Usage: axinstall [options] [agent]");
9
+ console.error("Usage: axinstall [options] [agents...]");
10
10
  console.error(" axinstall --list-agents");
11
11
  console.error(" axinstall --status [--only <scope>]");
12
12
  console.error("Try 'axinstall --help' for usage information.");
13
13
  process.exitCode = 1;
14
14
  }
15
- export function runCommand(agentCli, options) {
16
- const validation = validateOptions(agentCli, options);
15
+ export function runCommand(agentClis, options) {
16
+ const validation = validateOptions(agentClis, options);
17
17
  if (!validation.valid) {
18
18
  reportUsageError(validation.message);
19
19
  return;
@@ -31,9 +31,14 @@ export function runCommand(agentCli, options) {
31
31
  printStatus(scopeInput);
32
32
  return;
33
33
  }
34
- if (!agentCli) {
35
- reportUsageError("Missing required argument 'agent' (or use --list-agents/--status).");
34
+ if (!agentClis || agentClis.length === 0) {
35
+ reportUsageError("Missing required argument 'agent(s)' (or use --list-agents/--status).");
36
36
  return;
37
37
  }
38
- handleInstall(agentCli, options);
38
+ for (const agentCli of agentClis) {
39
+ const installOk = handleInstall(agentCli, options);
40
+ if (!installOk) {
41
+ return;
42
+ }
43
+ }
39
44
  }
@@ -10,5 +10,5 @@ type ValidationSuccess = {
10
10
  valid: true;
11
11
  };
12
12
  type ValidationResult = ValidationError | ValidationSuccess;
13
- export declare function validateOptions(agentCli: string | undefined, options: CliOptions): ValidationResult;
13
+ export declare function validateOptions(agentClis: string[] | undefined, options: CliOptions): ValidationResult;
14
14
  export {};
@@ -1,17 +1,18 @@
1
1
  /**
2
2
  * CLI option validation.
3
3
  */
4
- export function validateOptions(agentCli, options) {
4
+ export function validateOptions(agentClis, options) {
5
+ const hasAgentArguments = Boolean(agentClis && agentClis.length > 0);
5
6
  if (options.listAgents && options.status) {
6
7
  return {
7
8
  valid: false,
8
9
  message: "Use either --list-agents or --status, not both.",
9
10
  };
10
11
  }
11
- if ((options.listAgents || options.status) && agentCli) {
12
+ if ((options.listAgents || options.status) && hasAgentArguments) {
12
13
  return {
13
14
  valid: false,
14
- message: "Do not pass an agent when using --list-agents or --status.",
15
+ message: "Do not pass agents when using --list-agents or --status.",
15
16
  };
16
17
  }
17
18
  if ((options.listAgents || options.status) && options.with) {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "axinstall",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "1.3.0",
5
+ "version": "1.4.0",
6
6
  "description": "Universal installer for AI CLI agents (defaults to npm)",
7
7
  "repository": {
8
8
  "type": "git",
@@ -69,21 +69,21 @@
69
69
  },
70
70
  "dependencies": {
71
71
  "@commander-js/extra-typings": "^14.0.0",
72
- "axshared": "^4.0.0",
73
- "commander": "^14.0.2"
72
+ "axshared": "^5.0.0",
73
+ "commander": "^14.0.3"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@total-typescript/ts-reset": "^0.6.1",
77
- "@types/node": "^25.0.10",
78
- "@vitest/coverage-v8": "^4.0.17",
79
- "eslint": "^9.39.2",
80
- "eslint-config-axkit": "^1.1.0",
77
+ "@types/node": "^25.3.0",
78
+ "@vitest/coverage-v8": "^4.0.18",
79
+ "eslint": "^10.0.1",
80
+ "eslint-config-axkit": "^1.2.1",
81
81
  "fta-check": "^1.5.1",
82
82
  "fta-cli": "^3.0.0",
83
- "knip": "^5.82.1",
83
+ "knip": "^5.85.0",
84
84
  "prettier": "3.8.1",
85
- "semantic-release": "^25.0.2",
85
+ "semantic-release": "^25.0.3",
86
86
  "typescript": "^5.9.3",
87
- "vitest": "^4.0.17"
87
+ "vitest": "^4.0.18"
88
88
  }
89
89
  }