@alchemy/cli 0.1.3 → 0.2.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,18 +6,69 @@ You can use API keys, access keys, or x402 wallet auth depending on the command.
6
6
 
7
7
  ## Installation
8
8
 
9
- The current repository workflow is source install:
9
+ Install globally from npm:
10
10
 
11
11
  ```bash
12
- git clone https://github.com/alchemyplatform/alchemy-cli.git
13
- cd alchemy-cli
14
- pnpm install
15
- pnpm build
16
- pnpm link --global
12
+ npm i -g @alchemy/cli
17
13
  ```
18
14
 
19
- This makes the `alchemy` command available globally.
20
- To unlink later: `pnpm unlink --global`.
15
+ Or run without installing globally:
16
+
17
+ ```bash
18
+ npx @alchemy/cli <command>
19
+ ```
20
+
21
+ ## Getting Started
22
+
23
+ ### Authentication Quick Start
24
+
25
+ Authentication is required before making requests. Configure auth first, then run commands.
26
+
27
+ If you are using the CLI as a human in an interactive terminal, the easiest path is:
28
+
29
+ ```bash
30
+ alchemy
31
+ ```
32
+
33
+ Then follow the setup flow in the terminal UI to configure auth.
34
+
35
+ Know which auth method does what:
36
+
37
+ - **API key** - direct auth for blockchain queries (`balance`, `tx`, `block`, `nfts`, `tokens`, `rpc`)
38
+ - **Access key** - Admin/API app management; app setup/selection can also provide API key auth for blockchain queries
39
+ - **x402 wallet auth** - wallet-authenticated, pay-per-request model for supported blockchain queries
40
+
41
+ If you use Notify webhooks, add webhook auth on top via `alchemy config set webhook-api-key <key>`, `--webhook-api-key`, or `ALCHEMY_WEBHOOK_API_KEY`.
42
+
43
+ For setup commands, env vars, and resolution order, see [Authentication Reference](#authentication-reference).
44
+
45
+ ### Usage By Workflow
46
+
47
+ After auth is configured, use the CLI differently depending on who is driving it:
48
+
49
+ - **Humans (interactive terminal):** start with `alchemy` and use the terminal UI/setup flow; this is the recommended path for human usage
50
+ - **Agents/scripts (automation):** always use `--json` and prefer non-interactive execution (`--no-interactive`)
51
+
52
+ Quick usage examples:
53
+
54
+ ```bash
55
+ # Human recommended entrypoint
56
+ alchemy
57
+
58
+ # Agent/script-friendly command
59
+ alchemy balance 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --json --no-interactive
60
+ ```
61
+
62
+ #### Agent bootstrap
63
+
64
+ Have your agent run `agent-prompt` as its first step to get a complete, machine-readable contract describing every command, auth method, error code, and execution rule:
65
+
66
+ ```bash
67
+ # Agent runs this once to learn everything the CLI can do
68
+ alchemy --json agent-prompt
69
+ ```
70
+
71
+ This returns a single JSON document with execution policy, preflight instructions, auth matrix, the full command tree with all arguments and options, error codes with recovery actions, and example invocations. No external docs required.
21
72
 
22
73
  ## Command Reference
23
74
 
@@ -104,6 +155,7 @@ Use `alchemy help` or `alchemy help <command>` for generated command help.
104
155
  | `config get <key>` | Gets one config value | `alchemy config get network` |
105
156
  | `config list` | Lists all config values | `alchemy config list` |
106
157
  | `config reset [key]` | Resets one or all config values | `alchemy config reset --yes` |
158
+ | `agent-prompt` | Emits complete agent/automation usage instructions | `alchemy --json agent-prompt` |
107
159
  | `version` | Prints CLI version | `alchemy version` |
108
160
 
109
161
  ## Flags
@@ -177,13 +229,13 @@ Additional env vars:
177
229
  | `network list` | `--configured`, `--app-id <id>` |
178
230
  | `config reset` | `-y, --yes` |
179
231
 
180
- ## Authentication
232
+ ## Authentication Reference
181
233
 
182
234
  The CLI supports three auth inputs:
183
235
 
184
236
  - API key for blockchain queries (`balance`, `tx`, `block`, `nfts`, `tokens`, `rpc`)
185
- - Access key for Admin API operations (`apps`, `chains`, configured network lookups)
186
- - x402 wallet key for wallet-authenticated blockchain queries
237
+ - Access key for Admin API operations (`apps`, `chains`, configured network lookups`) and app setup/selection, which can also supply the API key used by blockchain query commands
238
+ - x402 wallet key for wallet-authenticated blockchain queries in a pay-per-request model
187
239
 
188
240
  Notify/webhook commands use a webhook API key with resolution order:
189
241
  `--webhook-api-key` -> `ALCHEMY_WEBHOOK_API_KEY` -> `ALCHEMY_NOTIFY_AUTH_TOKEN` -> config `webhook-api-key` -> configured app webhook key.
@@ -222,6 +274,9 @@ Resolution order: `--access-key` -> `ALCHEMY_ACCESS_KEY` -> config file.
222
274
 
223
275
  #### x402 wallet auth
224
276
 
277
+ x402 is a wallet-authenticated, pay-per-request usage model for supported blockchain queries.
278
+ The CLI can generate or import the wallet key used for these requests.
279
+
225
280
  ```bash
226
281
  # Generate/import a wallet managed by CLI
227
282
  alchemy wallet generate
@@ -278,59 +333,3 @@ Errors are structured JSON in JSON mode:
278
333
  }
279
334
  }
280
335
  ```
281
-
282
- ## Development
283
-
284
- Prerequisites:
285
-
286
- - [Node.js 18+](https://nodejs.org/)
287
- - [pnpm](https://pnpm.io/)
288
-
289
- Run during development:
290
-
291
- ```bash
292
- # Run without building
293
- npx tsx src/index.ts balance 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
294
-
295
- # Build in watch mode
296
- pnpm dev
297
- ```
298
-
299
- Build:
300
-
301
- ```bash
302
- pnpm build
303
- ```
304
-
305
- Test:
306
-
307
- ```bash
308
- pnpm test
309
- pnpm test:e2e
310
- ```
311
-
312
- Type check:
313
-
314
- ```bash
315
- pnpm lint
316
- ```
317
-
318
- Coverage:
319
-
320
- ```bash
321
- pnpm test:coverage
322
- ```
323
-
324
- ### Endpoint Override Env Vars (Local Testing Only)
325
-
326
- These are for local/mock testing, not normal production usage:
327
-
328
- - `ALCHEMY_RPC_BASE_URL`
329
- - `ALCHEMY_ADMIN_API_BASE_URL`
330
- - `ALCHEMY_X402_BASE_URL`
331
-
332
- Safety constraints:
333
-
334
- - Only localhost targets are accepted (`localhost`, `127.0.0.1`, `::1`)
335
- - Non-HTTPS transport is allowed only for localhost
336
- - Production defaults are unchanged when unset
@@ -2,7 +2,7 @@
2
2
  if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
3
3
  import {
4
4
  isInteractiveAllowed
5
- } from "./chunk-QKXQW4OF.js";
5
+ } from "./chunk-VRBWUQHA.js";
6
6
 
7
7
  // src/lib/networks.ts
8
8
  var TESTNET_TOKEN_RE = /(testnet|sepolia|holesky|hoodi|devnet|minato|amoy|fuji|saigon|cardona|aeneid|curtis|chiado|cassiopeia|blaze|ropsten|signet|mocha|fam|bepolia)$/i;
@@ -40,7 +40,7 @@ import {
40
40
  toMap,
41
41
  withSpinner,
42
42
  yellow
43
- } from "./chunk-QKXQW4OF.js";
43
+ } from "./chunk-VRBWUQHA.js";
44
44
 
45
45
  // src/lib/client-utils.ts
46
46
  function isLocalhost(hostname) {
@@ -1063,6 +1063,7 @@ export {
1063
1063
  debug,
1064
1064
  formatCommanderError,
1065
1065
  ErrorCode,
1066
+ EXIT_CODES,
1066
1067
  CLIError,
1067
1068
  errAuthRequired,
1068
1069
  errAccessKeyRequired,
package/dist/index.js CHANGED
@@ -14,14 +14,16 @@ import {
14
14
  splitCommaList,
15
15
  validateAddress,
16
16
  validateTxHash
17
- } from "./chunk-PH4BPYSY.js";
17
+ } from "./chunk-VD5WQHLQ.js";
18
18
  import {
19
19
  getRPCNetworks,
20
20
  getSetupStatus,
21
21
  isSetupComplete,
22
22
  shouldRunOnboarding
23
- } from "./chunk-F7KTEZFZ.js";
23
+ } from "./chunk-MAKSV2EA.js";
24
24
  import {
25
+ EXIT_CODES,
26
+ ErrorCode,
25
27
  bold,
26
28
  brand,
27
29
  brandedHelp,
@@ -60,7 +62,7 @@ import {
60
62
  verbose,
61
63
  weiToEth,
62
64
  withSpinner
63
- } from "./chunk-QKXQW4OF.js";
65
+ } from "./chunk-VRBWUQHA.js";
64
66
 
65
67
  // src/index.ts
66
68
  import { Command, Help } from "commander";
@@ -1609,6 +1611,195 @@ function registerSolana(program2) {
1609
1611
  });
1610
1612
  }
1611
1613
 
1614
+ // src/commands/agent-prompt.ts
1615
+ var RETRYABLE_CODES = /* @__PURE__ */ new Set([
1616
+ ErrorCode.RATE_LIMITED,
1617
+ ErrorCode.NETWORK_ERROR
1618
+ ]);
1619
+ var ERROR_RECOVERY = {
1620
+ AUTH_REQUIRED: "Set ALCHEMY_API_KEY env var or run: alchemy config set api-key <key>",
1621
+ INVALID_API_KEY: "Check your API key and set a valid one: alchemy config set api-key <key>",
1622
+ NETWORK_NOT_ENABLED: "Enable the target network for your app at dashboard.alchemy.com",
1623
+ INVALID_ACCESS_KEY: "Check your access key: https://dashboard.alchemy.com/",
1624
+ ACCESS_KEY_REQUIRED: "Set ALCHEMY_ACCESS_KEY env var or run: alchemy config set access-key <key>",
1625
+ APP_REQUIRED: "Select an app: alchemy config set app <app-id>",
1626
+ ADMIN_API_ERROR: "Check the error message for details; verify access key permissions",
1627
+ NETWORK_ERROR: "Check internet connection and retry",
1628
+ RPC_ERROR: "Check RPC method, params, and network; verify API key has access",
1629
+ INVALID_ARGS: "Check command usage via: alchemy --json help <command>",
1630
+ NOT_FOUND: "Verify the resource identifier (address, hash, id) is correct",
1631
+ RATE_LIMITED: "Wait and retry; consider upgrading your Alchemy plan",
1632
+ PAYMENT_REQUIRED: "Fund your x402 wallet or switch to API key auth",
1633
+ SETUP_REQUIRED: "Run preflight: alchemy --json setup status, then follow nextCommands",
1634
+ INTERNAL_ERROR: "Unexpected error; retry or report a bug"
1635
+ };
1636
+ function buildCommandSchema(cmd) {
1637
+ const schema = {
1638
+ name: cmd.name(),
1639
+ description: cmd.description()
1640
+ };
1641
+ const aliases = cmd.aliases();
1642
+ if (aliases.length > 0) {
1643
+ schema.aliases = aliases;
1644
+ }
1645
+ const args = cmd.registeredArguments;
1646
+ if (args.length > 0) {
1647
+ schema.arguments = args.map((a) => ({
1648
+ name: a.name(),
1649
+ description: a.description,
1650
+ required: a.required
1651
+ }));
1652
+ }
1653
+ const opts = cmd.options;
1654
+ if (opts.length > 0) {
1655
+ schema.options = opts.map((o) => ({
1656
+ flags: o.flags,
1657
+ description: o.description
1658
+ }));
1659
+ }
1660
+ const subs = cmd.commands;
1661
+ if (subs.length > 0) {
1662
+ schema.subcommands = subs.map(buildCommandSchema);
1663
+ }
1664
+ return schema;
1665
+ }
1666
+ function buildAgentPrompt(program2) {
1667
+ const errors = {};
1668
+ for (const [code, exitCode] of Object.entries(EXIT_CODES)) {
1669
+ errors[code] = {
1670
+ exitCode,
1671
+ retryable: RETRYABLE_CODES.has(code),
1672
+ recovery: ERROR_RECOVERY[code] ?? "Check error message"
1673
+ };
1674
+ }
1675
+ const commands = program2.commands.filter((cmd) => cmd.name() !== "agent-prompt").map(buildCommandSchema);
1676
+ return {
1677
+ executionPolicy: [
1678
+ "Always pass --json --no-interactive",
1679
+ "Parse stdout as JSON on exit code 0",
1680
+ "Parse stderr as JSON on nonzero exit code",
1681
+ "Never run bare 'alchemy' without --json --no-interactive"
1682
+ ],
1683
+ preflight: {
1684
+ command: "alchemy --json setup status",
1685
+ description: "Check auth readiness before first command. If complete is false, follow nextCommands in the response to configure auth."
1686
+ },
1687
+ auth: [
1688
+ {
1689
+ method: "API key",
1690
+ envVar: "ALCHEMY_API_KEY",
1691
+ flag: "--api-key <key>",
1692
+ configKey: "api-key",
1693
+ commandFamilies: [
1694
+ "balance",
1695
+ "tx",
1696
+ "block",
1697
+ "rpc",
1698
+ "trace",
1699
+ "debug",
1700
+ "tokens",
1701
+ "nfts",
1702
+ "transfers",
1703
+ "prices",
1704
+ "portfolio",
1705
+ "simulate",
1706
+ "solana"
1707
+ ]
1708
+ },
1709
+ {
1710
+ method: "Access key",
1711
+ envVar: "ALCHEMY_ACCESS_KEY",
1712
+ flag: "--access-key <key>",
1713
+ configKey: "access-key",
1714
+ commandFamilies: ["apps", "chains", "network list --configured"]
1715
+ },
1716
+ {
1717
+ method: "Webhook API key",
1718
+ envVar: "ALCHEMY_WEBHOOK_API_KEY",
1719
+ flag: "--webhook-api-key <key>",
1720
+ configKey: "webhook-api-key",
1721
+ commandFamilies: ["webhooks"]
1722
+ },
1723
+ {
1724
+ method: "x402 wallet",
1725
+ envVar: "ALCHEMY_WALLET_KEY",
1726
+ flag: "--x402 --wallet-key-file <path>",
1727
+ configKey: "x402",
1728
+ commandFamilies: [
1729
+ "balance",
1730
+ "tx",
1731
+ "block",
1732
+ "rpc",
1733
+ "trace",
1734
+ "debug",
1735
+ "tokens",
1736
+ "nfts",
1737
+ "transfers"
1738
+ ]
1739
+ }
1740
+ ],
1741
+ commands,
1742
+ errors,
1743
+ examples: [
1744
+ "alchemy --json --no-interactive setup status",
1745
+ "alchemy --json --no-interactive balance 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --api-key $ALCHEMY_API_KEY",
1746
+ "alchemy --json --no-interactive apps list --access-key $ALCHEMY_ACCESS_KEY",
1747
+ "alchemy --json --no-interactive rpc eth_blockNumber --api-key $ALCHEMY_API_KEY",
1748
+ "alchemy --json --no-interactive network list"
1749
+ ],
1750
+ docs: "https://www.alchemy.com/docs"
1751
+ };
1752
+ }
1753
+ function formatAsSystemPrompt(payload) {
1754
+ const lines = [];
1755
+ lines.push("Alchemy CLI agent instructions");
1756
+ lines.push("==============================");
1757
+ lines.push("");
1758
+ lines.push("Execution policy:");
1759
+ for (const rule of payload.executionPolicy) {
1760
+ lines.push(` - ${rule}`);
1761
+ }
1762
+ lines.push("");
1763
+ lines.push("Preflight:");
1764
+ lines.push(` Command: ${payload.preflight.command}`);
1765
+ lines.push(` ${payload.preflight.description}`);
1766
+ lines.push("");
1767
+ lines.push("Auth methods:");
1768
+ for (const auth of payload.auth) {
1769
+ lines.push(` ${auth.method}:`);
1770
+ lines.push(` env: ${auth.envVar}`);
1771
+ lines.push(` flag: ${auth.flag}`);
1772
+ lines.push(` config: alchemy config set ${auth.configKey} <value>`);
1773
+ lines.push(` commands: ${auth.commandFamilies.join(", ")}`);
1774
+ }
1775
+ lines.push("");
1776
+ lines.push("Error codes:");
1777
+ for (const [code, entry] of Object.entries(payload.errors)) {
1778
+ const retry = entry.retryable ? " [retryable]" : "";
1779
+ lines.push(` ${code} (exit ${entry.exitCode})${retry}: ${entry.recovery}`);
1780
+ }
1781
+ lines.push("");
1782
+ lines.push("Examples:");
1783
+ for (const example of payload.examples) {
1784
+ lines.push(` ${example}`);
1785
+ }
1786
+ lines.push("");
1787
+ lines.push(`Docs: ${payload.docs}`);
1788
+ lines.push(" For RPC method signatures, parameters, and supported networks.");
1789
+ lines.push("");
1790
+ lines.push(
1791
+ "For full command tree, run: alchemy --json agent-prompt"
1792
+ );
1793
+ lines.push("");
1794
+ return lines.join("\n");
1795
+ }
1796
+ function registerAgentPrompt(program2) {
1797
+ program2.command("agent-prompt").description("Emit complete agent/automation usage instructions").action(() => {
1798
+ const payload = buildAgentPrompt(program2);
1799
+ printHuman(formatAsSystemPrompt(payload), payload);
1800
+ });
1801
+ }
1802
+
1612
1803
  // src/index.ts
1613
1804
  var hBrand = noColor ? identity : (s) => `\x1B[38;2;54;63;249m${s}\x1B[39m`;
1614
1805
  var hBold = esc("1");
@@ -1646,7 +1837,7 @@ var ROOT_COMMAND_PILLARS = [
1646
1837
  },
1647
1838
  {
1648
1839
  label: "Admin",
1649
- commands: ["apps", "config", "setup", "version", "help"]
1840
+ commands: ["apps", "config", "setup", "agent-prompt", "version", "help"]
1650
1841
  }
1651
1842
  ];
1652
1843
  function formatCommandSignature(sub) {
@@ -1683,7 +1874,7 @@ var findCommandByPath = (root, path) => {
1683
1874
  };
1684
1875
  program.name("alchemy").description(
1685
1876
  "The Alchemy CLI lets you query blockchain data, call JSON-RPC methods, and manage your Alchemy configuration."
1686
- ).version("0.1.3").option("--api-key <key>", "Alchemy API key (env: ALCHEMY_API_KEY)").option("--access-key <key>", "Alchemy access key (env: ALCHEMY_ACCESS_KEY)").option(
1877
+ ).version("0.2.0").option("--api-key <key>", "Alchemy API key (env: ALCHEMY_API_KEY)").option("--access-key <key>", "Alchemy access key (env: ALCHEMY_ACCESS_KEY)").option(
1687
1878
  "-n, --network <network>",
1688
1879
  "Target network (default: eth-mainnet) (env: ALCHEMY_NETWORK)"
1689
1880
  ).option("--x402", "Use x402 wallet-based gateway auth").option("--wallet-key-file <path>", "Path to wallet private key file for x402").option("--json", "Force JSON output").option("-q, --quiet", "Suppress non-essential output").option("-v, --verbose", "Enable verbose output").option("--no-color", "Disable color output").option("--reveal", "Show secrets in plain text (TTY only)").option("--timeout <ms>", "Request timeout in milliseconds", parseInt).option("--debug", "Enable debug diagnostics").option("--no-interactive", "Disable REPL and prompt-driven interactions").addHelpCommand(false).configureOutput({
@@ -1835,13 +2026,13 @@ ${styledLine}`;
1835
2026
  }
1836
2027
  if (isInteractiveAllowed(program)) {
1837
2028
  if (shouldRunOnboarding(program, cfg)) {
1838
- const { runOnboarding } = await import("./onboarding-3J4EXZMG.js");
2029
+ const { runOnboarding } = await import("./onboarding-IKIXUTY7.js");
1839
2030
  const completed = await runOnboarding(program);
1840
2031
  if (!completed) {
1841
2032
  return;
1842
2033
  }
1843
2034
  }
1844
- const { startREPL } = await import("./interactive-2ITFWH3B.js");
2035
+ const { startREPL } = await import("./interactive-CP6E23OD.js");
1845
2036
  program.exitOverride();
1846
2037
  program.configureOutput({
1847
2038
  writeErr: () => {
@@ -1874,6 +2065,7 @@ registerApps(program);
1874
2065
  registerSetup(program);
1875
2066
  registerConfig(program);
1876
2067
  registerSolana(program);
2068
+ registerAgentPrompt(program);
1877
2069
  registerVersion(program);
1878
2070
  program.command("help [command...]").description("display help for command").action((commandPath) => {
1879
2071
  if (!commandPath || commandPath.length === 0) {
@@ -3,7 +3,7 @@ if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
3
3
  import {
4
4
  getRPCNetworkIds,
5
5
  getSetupMethod
6
- } from "./chunk-F7KTEZFZ.js";
6
+ } from "./chunk-MAKSV2EA.js";
7
7
  import {
8
8
  bgRgb,
9
9
  bold,
@@ -18,7 +18,7 @@ import {
18
18
  rgb,
19
19
  setBrandedHelpSuppressed,
20
20
  setReplMode
21
- } from "./chunk-QKXQW4OF.js";
21
+ } from "./chunk-VRBWUQHA.js";
22
22
 
23
23
  // src/commands/interactive.ts
24
24
  import * as readline from "readline";
@@ -100,6 +100,7 @@ var COMMAND_NAMES = [
100
100
  "tokens metadata",
101
101
  "tokens allowance",
102
102
  "tx",
103
+ "agent-prompt",
103
104
  "version",
104
105
  "wallet",
105
106
  "wallet generate",
@@ -5,7 +5,7 @@ import {
5
5
  generateAndPersistWallet,
6
6
  importAndPersistWallet,
7
7
  selectOrCreateApp
8
- } from "./chunk-PH4BPYSY.js";
8
+ } from "./chunk-VD5WQHLQ.js";
9
9
  import {
10
10
  bold,
11
11
  brand,
@@ -18,7 +18,7 @@ import {
18
18
  promptSelect,
19
19
  promptText,
20
20
  save
21
- } from "./chunk-QKXQW4OF.js";
21
+ } from "./chunk-VRBWUQHA.js";
22
22
 
23
23
  // src/commands/onboarding.ts
24
24
  function printNextSteps(method) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alchemy/cli",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Alchemy CLI — interact with blockchain data",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,8 @@
14
14
  ],
15
15
  "files": [
16
16
  "dist",
17
- "README.md"
17
+ "README.md",
18
+ "scripts/postinstall.cjs"
18
19
  ],
19
20
  "repository": {
20
21
  "type": "git",
@@ -25,7 +26,7 @@
25
26
  },
26
27
  "license": "MIT",
27
28
  "engines": {
28
- "node": ">=18"
29
+ "node": ">=22"
29
30
  },
30
31
  "dependencies": {
31
32
  "@alchemy/x402": "^0.4.0",
@@ -34,6 +35,8 @@
34
35
  "zod": "^4.3.6"
35
36
  },
36
37
  "devDependencies": {
38
+ "@changesets/changelog-github": "^0.6.0",
39
+ "@changesets/cli": "^2.30.0",
37
40
  "@types/node": "^25.3.0",
38
41
  "@vitest/coverage-v8": "^4.0.18",
39
42
  "tsup": "^8.5.1",
@@ -44,10 +47,14 @@
44
47
  "scripts": {
45
48
  "build": "tsup",
46
49
  "dev": "tsup --watch",
50
+ "postinstall": "node ./scripts/postinstall.cjs",
47
51
  "test": "vitest run",
48
52
  "test:coverage": "vitest run --coverage",
49
53
  "test:e2e": "pnpm build && vitest run --config vitest.e2e.config.ts",
50
54
  "test:watch": "vitest",
51
- "lint": "tsc --noEmit"
55
+ "lint": "tsc --noEmit",
56
+ "changeset": "changeset",
57
+ "version-packages": "changeset version",
58
+ "release": "pnpm build && changeset publish"
52
59
  }
53
60
  }
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ function isGlobalInstall() {
4
+ return process.env.npm_config_global === "true";
5
+ }
6
+
7
+ function isCI() {
8
+ return process.env.CI === "true";
9
+ }
10
+
11
+ if (isGlobalInstall() && !isCI()) {
12
+ // Keep this concise so it stays readable in npm install output.
13
+ console.log("");
14
+ console.log("◆ Alchemy CLI installed");
15
+ console.log(" Run `alchemy` to get started.");
16
+ console.log("");
17
+ }