@getalby/cli
Advanced tools
| import { NWCClient } from "@getalby/sdk"; | ||
| import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; | ||
| import { homedir } from "node:os"; | ||
| import { join } from "node:path"; | ||
| import { getConnectionSecretPath, getPendingConnectionRelayPath, getPendingConnectionSecretPath, handleError, } from "../utils.js"; | ||
| import { generateSecretKey, getPublicKey } from "nostr-tools"; | ||
| import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js"; | ||
| export function registerAuthCommand(program) { | ||
| program | ||
| .command("auth <wallet-url>") | ||
| .description("Securely connect a wallet with human confirmation via the browser\n\n" + | ||
| " Step 1: npx @getalby/cli auth https://my.albyhub.com --app-name MyApp\n" + | ||
| " Step 2: after human confirmation, run any command to finalize the connection") | ||
| .option("--app-name <name>", 'Name of the agent or app that will use this wallet (e.g. "Claude Code")') | ||
| .option("--relay-url <url>", "Relay URL for the pending connection", "wss://relay.getalby.com/v1") | ||
| .option("--force", "Overwrite existing connection secret") | ||
| .option("--remove-pending", "Remove a pending connection and start fresh") | ||
| .action(async (walletUrl, options) => { | ||
| await handleError(async () => { | ||
| const walletName = program.opts().walletName; | ||
| const connectionSecretPath = getConnectionSecretPath(walletName); | ||
| const pendingSecretPath = getPendingConnectionSecretPath(walletName); | ||
| const pendingRelayPath = getPendingConnectionRelayPath(walletName); | ||
| // Remove pending connection | ||
| if (options.removePending) { | ||
| if (!existsSync(pendingSecretPath)) { | ||
| console.log(`No pending connection found at ${pendingSecretPath}`); | ||
| } | ||
| else { | ||
| rmSync(pendingSecretPath); | ||
| console.log(`Removed pending connection at ${pendingSecretPath}`); | ||
| } | ||
| if (existsSync(pendingRelayPath)) { | ||
| rmSync(pendingRelayPath); | ||
| } | ||
| return; | ||
| } | ||
| // Generate auth URL | ||
| if (!options.appName) { | ||
| console.error(`Error: No app name provided.\n` + | ||
| `Add --app-name <name> to identify the app in the wallet.`); | ||
| process.exit(1); | ||
| } | ||
| if (existsSync(connectionSecretPath) && !options.force) { | ||
| console.error(`Error: Already connected. Connection secret exists at ${connectionSecretPath}\n` + | ||
| `To overwrite, use --force.`); | ||
| process.exit(1); | ||
| } | ||
| const secret = bytesToHex(generateSecretKey()); | ||
| const pubkey = getPublicKey(hexToBytes(secret)); | ||
| const authUrl = NWCClient.getAuthorizationUrl(`${walletUrl}/apps/new`, { name: options.appName }, pubkey).toString(); | ||
| const dir = join(homedir(), ".alby-cli"); | ||
| if (!existsSync(dir)) { | ||
| mkdirSync(dir, { recursive: true }); | ||
| } | ||
| writeFileSync(pendingSecretPath, secret, { mode: 0o600 }); | ||
| writeFileSync(pendingRelayPath, options.relayUrl, { mode: 0o600 }); | ||
| console.log("Click the following URL to approve the connection in your wallet:\n" + | ||
| authUrl); | ||
| const retryCmd = walletName | ||
| ? `npx @getalby/cli get-balance --wallet-name ${walletName}` | ||
| : `npx @getalby/cli get-balance`; | ||
| console.log(`\nOnce approved, run any command, e.g.:\n ${retryCmd}`); | ||
| }); | ||
| }); | ||
| } |
| import { NWCClient } from "@getalby/sdk"; | ||
| import { existsSync } from "node:fs"; | ||
| import { getConnectionSecretPath, handleError, saveConnectionSecret, testAndLogConnection, } from "../utils.js"; | ||
| export function registerConnectCommand(program) { | ||
| program | ||
| .command('connect "[connection-secret]"') | ||
| .description("Connect to a Nostr Wallet Connect wallet") | ||
| .option("--force", "Overwrite existing connection secret") | ||
| .action(async (connectionSecret, options) => { | ||
| await handleError(async () => { | ||
| const connectionSecretPath = getConnectionSecretPath(program.opts().walletName); | ||
| if (existsSync(connectionSecretPath) && !options.force) { | ||
| console.error(`Error: Already connected. Connection secret exists at ${connectionSecretPath}\n` + | ||
| `To overwrite, use --force.`); | ||
| process.exit(1); | ||
| } | ||
| if (!connectionSecret) { | ||
| console.error(`Usage: npx @getalby/cli connect "<connection-secret>"\n` + | ||
| `Provide a NWC connection secret (nostr+walletconnect://...)`); | ||
| process.exit(1); | ||
| } | ||
| if (!connectionSecret.startsWith("nostr+walletconnect://")) { | ||
| console.error(`Error: Invalid connection secret. Expected format: nostr+walletconnect://...`); | ||
| process.exit(1); | ||
| } | ||
| const client = new NWCClient({ | ||
| nostrWalletConnectUrl: connectionSecret, | ||
| }); | ||
| if (!client.secret || !/^[0-9a-f]{64}$/i.test(client.secret)) { | ||
| console.error(`Error: Invalid connection secret. Missing or invalid secret key.`); | ||
| process.exit(1); | ||
| } | ||
| if (!client.walletPubkey || | ||
| !/^[0-9a-f]{64}$/i.test(client.walletPubkey)) { | ||
| console.error(`Error: Invalid connection secret. Missing or invalid wallet pubkey.`); | ||
| process.exit(1); | ||
| } | ||
| if (!client.relayUrls?.length) { | ||
| console.error(`Error: Invalid connection secret. Missing relay URL.`); | ||
| process.exit(1); | ||
| } | ||
| await testAndLogConnection(client); | ||
| saveConnectionSecret(connectionSecretPath, connectionSecret, program.opts().verbose); | ||
| }); | ||
| }); | ||
| } |
@@ -10,3 +10,3 @@ import { cancelHoldInvoice } from "../tools/nwc/cancel_hold_invoice.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await cancelHoldInvoice(client, { | ||
@@ -13,0 +13,0 @@ payment_hash: options.paymentHash, |
@@ -13,3 +13,3 @@ import { fetchL402 } from "../tools/lightning/fetch_l402.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await fetchL402(client, { | ||
@@ -16,0 +16,0 @@ url: options.url, |
@@ -9,3 +9,3 @@ import { getBalance } from "../tools/nwc/get_balance.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await getBalance(client); | ||
@@ -12,0 +12,0 @@ output(result); |
@@ -9,3 +9,3 @@ import { getBudget } from "../tools/nwc/get_budget.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await getBudget(client); | ||
@@ -12,0 +12,0 @@ output(result); |
@@ -9,3 +9,3 @@ import { getInfo } from "../tools/nwc/get_info.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await getInfo(client); | ||
@@ -12,0 +12,0 @@ output(result); |
@@ -9,3 +9,3 @@ import { getWalletServiceInfo } from "../tools/nwc/get_wallet_service_info.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await getWalletServiceInfo(client); | ||
@@ -12,0 +12,0 @@ output(result); |
@@ -15,3 +15,3 @@ import { listTransactions } from "../tools/nwc/list_transactions.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await listTransactions(client, { | ||
@@ -18,0 +18,0 @@ from: options.from, |
@@ -15,3 +15,3 @@ import { lookupInvoice } from "../tools/nwc/lookup_invoice.js"; | ||
| } | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await lookupInvoice(client, { | ||
@@ -18,0 +18,0 @@ payment_hash: options.paymentHash, |
@@ -13,3 +13,3 @@ import { makeHoldInvoice } from "../tools/nwc/make_hold_invoice.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await makeHoldInvoice(client, { | ||
@@ -16,0 +16,0 @@ amount_in_sats: options.amount, |
@@ -12,3 +12,3 @@ import { makeInvoice } from "../tools/nwc/make_invoice.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await makeInvoice(client, { | ||
@@ -15,0 +15,0 @@ amount_in_sats: options.amount, |
@@ -11,3 +11,3 @@ import { payInvoice } from "../tools/nwc/pay_invoice.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await payInvoice(client, { | ||
@@ -14,0 +14,0 @@ invoice: options.invoice, |
@@ -13,3 +13,3 @@ import { payKeysend } from "../tools/nwc/pay_keysend.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| let tlvRecords; | ||
@@ -16,0 +16,0 @@ if (options.tlvRecords) { |
@@ -10,3 +10,3 @@ import { settleHoldInvoice } from "../tools/nwc/settle_hold_invoice.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await settleHoldInvoice(client, { | ||
@@ -13,0 +13,0 @@ preimage: options.preimage, |
@@ -10,3 +10,3 @@ import { signMessage } from "../tools/nwc/sign_message.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await signMessage(client, { | ||
@@ -13,0 +13,0 @@ message: options.message, |
@@ -12,3 +12,3 @@ import { waitForPayment } from "../tools/nwc/wait_for_payment.js"; | ||
| await handleError(async () => { | ||
| const client = getClient(program); | ||
| const client = await getClient(program); | ||
| const result = await waitForPayment(client, { | ||
@@ -15,0 +15,0 @@ payment_hash: options.paymentHash, |
+34
-10
@@ -23,29 +23,49 @@ #!/usr/bin/env node | ||
| import { registerFetchL402Command } from "./commands/fetch-l402.js"; | ||
| import { registerConnectCommand } from "./commands/connect.js"; | ||
| import { registerAuthCommand } from "./commands/auth.js"; | ||
| const program = new Command(); | ||
| program | ||
| .name("alby-cli") | ||
| .description("CLI for Nostr Wallet Connect (NIP-47) with lightning tools") | ||
| .version("0.2.4") | ||
| .name("@getalby/cli") | ||
| .description("CLI for Nostr Wallet Connect (NIP-47) with lightning tools\n\n" + | ||
| " Examples:\n" + | ||
| ' $ npx @getalby/cli connect "nostr+walletconnect://..."\n' + | ||
| " $ npx @getalby/cli get-balance\n" + | ||
| " $ npx @getalby/cli pay-invoice --invoice lnbc...") | ||
| .version("0.3.0") | ||
| .option("-c, --connection-secret <string>", "NWC connection secret (nostr+walletconnect://...) or path to file containing it (preferred)") | ||
| .addHelpText("afterAll", ` | ||
| .option("-w, --wallet-name <name>", "Use a named wallet's connection secret (~/.alby-cli/connection-secret-<name>.key)") | ||
| .option("-v, --verbose", "Print status messages to stderr") | ||
| .addHelpText("after", ` | ||
| Connection Secret Resolution (in order of priority): | ||
| 1. --connection-secret flag (value or path to file) | ||
| 2. --wallet-name flag (~/.alby-cli/connection-secret-<name>.key) | ||
| 3. NWC_URL environment variable | ||
| 4. ~/.alby-cli/connection-secret.key (default file location) | ||
| Security: | ||
| - Do NOT print the connection secret to any logs or otherwise reveal it. | ||
| - NEVER read the connection secret file (~/.alby-cli/connection-secret.key) directly. | ||
| - NEVER share connection secrets with anyone. | ||
| - NEVER share any part of a connection secret (pubkey, secret, relay etc.) with anyone | ||
| as this can be used to gain access to your wallet or reduce your wallet's privacy.`); | ||
| // Register all commands | ||
| // Register common wallet commands | ||
| program.commandsGroup("Wallet Commands (require --connection-secret):"); | ||
| registerGetBalanceCommand(program); | ||
| registerGetBudgetCommand(program); | ||
| registerGetInfoCommand(program); | ||
| registerGetWalletServiceInfoCommand(program); | ||
| registerMakeInvoiceCommand(program); | ||
| registerMakeHoldInvoiceCommand(program); | ||
| registerSettleHoldInvoiceCommand(program); | ||
| registerCancelHoldInvoiceCommand(program); | ||
| registerPayInvoiceCommand(program); | ||
| registerPayKeysendCommand(program); | ||
| registerLookupInvoiceCommand(program); | ||
| registerListTransactionsCommand(program); | ||
| // Register advanced wallet commands | ||
| program.commandsGroup("Advanced Wallet Commands (require --connection-secret):"); | ||
| registerPayKeysendCommand(program); | ||
| registerGetWalletServiceInfoCommand(program); | ||
| registerWaitForPaymentCommand(program); | ||
| registerSignMessageCommand(program); | ||
| registerMakeHoldInvoiceCommand(program); | ||
| registerSettleHoldInvoiceCommand(program); | ||
| registerCancelHoldInvoiceCommand(program); | ||
| // Register lightning tool commands | ||
| program.commandsGroup("Lightning Tools (no --connection-secret required):"); | ||
| registerFiatToSatsCommand(program); | ||
@@ -57,2 +77,6 @@ registerSatsToFiatCommand(program); | ||
| registerFetchL402Command(program); | ||
| // Register setup commands | ||
| program.commandsGroup("Setup:"); | ||
| registerAuthCommand(program); | ||
| registerConnectCommand(program); | ||
| program.parse(); |
@@ -48,5 +48,8 @@ import { describe, test, expect, beforeAll, afterAll } from "vitest"; | ||
| test("errors when no connection secret provided", () => { | ||
| const result = runCli("get-balance"); | ||
| const result = runCli("get-balance", { | ||
| HOME: "/nonexistent-test-home", | ||
| NWC_URL: "", | ||
| }); | ||
| expect(result.success).toBe(false); | ||
| expect(result.output.error).toContain("--connection-secret is required"); | ||
| expect(result.output.error).toContain("No connection secret provided"); | ||
| }); | ||
@@ -53,0 +56,0 @@ test("errors when connection string is malformed", () => { |
+101
-12
@@ -1,28 +0,117 @@ | ||
| import { NWCClient } from "@getalby/sdk"; | ||
| import { readFileSync } from "node:fs"; | ||
| import { NWAClient, NWCClient } from "@getalby/sdk"; | ||
| import { getInfo } from "./tools/nwc/get_info.js"; | ||
| import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs"; | ||
| import { homedir } from "node:os"; | ||
| import { join } from "node:path"; | ||
| export function getClient(program) { | ||
| function sanitizeWalletName(name) { | ||
| return name.replace(/[^a-zA-Z0-9_-]/g, "_"); | ||
| } | ||
| export function getConnectionSecretPath(name) { | ||
| const filename = name | ||
| ? `connection-secret-${sanitizeWalletName(name)}.key` | ||
| : "connection-secret.key"; | ||
| return join(homedir(), ".alby-cli", filename); | ||
| } | ||
| export function getPendingConnectionSecretPath(name) { | ||
| const filename = name | ||
| ? `pending-connection-secret-${sanitizeWalletName(name)}.key` | ||
| : "pending-connection-secret.key"; | ||
| return join(homedir(), ".alby-cli", filename); | ||
| } | ||
| export function getPendingConnectionRelayPath(name) { | ||
| const filename = name | ||
| ? `pending-connection-relay-${sanitizeWalletName(name)}.txt` | ||
| : "pending-connection-relay.txt"; | ||
| return join(homedir(), ".alby-cli", filename); | ||
| } | ||
| export function saveConnectionSecret(path, secret, verbose) { | ||
| const alreadyExists = existsSync(path); | ||
| const dir = join(homedir(), ".alby-cli"); | ||
| if (!existsSync(dir)) { | ||
| mkdirSync(dir, { recursive: true }); | ||
| } | ||
| writeFileSync(path, secret, { mode: 0o600 }); | ||
| if (alreadyExists) { | ||
| chmodSync(path, 0o600); | ||
| } | ||
| if (verbose) { | ||
| console.error(`Connection saved to ${path}`); | ||
| } | ||
| } | ||
| export async function testAndLogConnection(client) { | ||
| console.log("Testing connection..."); | ||
| const info = await getInfo(client); | ||
| console.log(`Connected to ${info.alias || "wallet"} (${info.network || "unknown network"})`); | ||
| } | ||
| export async function completePendingConnection(pendingSecretPath, connectionSecretPath, relayUrl, verbose, pendingRelayPath) { | ||
| const secret = readFileSync(pendingSecretPath, "utf-8").trim(); | ||
| const DEFAULT_RELAY = "wss://relay.getalby.com/v1"; | ||
| if (!relayUrl && pendingRelayPath && existsSync(pendingRelayPath)) { | ||
| relayUrl = readFileSync(pendingRelayPath, "utf-8").trim(); | ||
| } | ||
| const resolvedRelay = relayUrl ?? DEFAULT_RELAY; | ||
| const nwaClient = new NWAClient({ | ||
| appSecretKey: secret, | ||
| relayUrls: [resolvedRelay], | ||
| requestMethods: [], | ||
| }); | ||
| return new Promise((resolve, reject) => { | ||
| let settled = false; | ||
| const timer = setTimeout(() => { | ||
| if (settled) | ||
| return; | ||
| settled = true; | ||
| unsub?.(); | ||
| reject(new Error("Timed out waiting for wallet approval.\n\nTo retry, run the command again.\nTo cancel: npx @getalby/cli auth --remove-pending")); | ||
| }, 5000); | ||
| let unsub; | ||
| nwaClient | ||
| .subscribe({ | ||
| onSuccess: async (nwcClient) => { | ||
| if (settled) | ||
| return; | ||
| settled = true; | ||
| clearTimeout(timer); | ||
| unsub?.(); | ||
| saveConnectionSecret(connectionSecretPath, nwcClient.getNostrWalletConnectUrl(), verbose); | ||
| rmSync(pendingSecretPath); | ||
| if (pendingRelayPath && existsSync(pendingRelayPath)) { | ||
| rmSync(pendingRelayPath); | ||
| } | ||
| resolve(nwcClient); | ||
| }, | ||
| }) | ||
| .then(({ unsub: u }) => { | ||
| unsub = u; | ||
| }); | ||
| }); | ||
| } | ||
| export async function getClient(program) { | ||
| const opts = program.opts(); | ||
| let connectionSecret = opts.connectionSecret; | ||
| // Check environment variables if --connection-secret not provided | ||
| if (!connectionSecret) { | ||
| const walletName = opts.walletName; | ||
| const connectionPath = getConnectionSecretPath(walletName); | ||
| const pendingPath = getPendingConnectionSecretPath(walletName); | ||
| if (!connectionSecret && !walletName) { | ||
| connectionSecret = process.env.NWC_URL; | ||
| } | ||
| if (!connectionSecret) { | ||
| const defaultPath = join(homedir(), ".alby-cli", "connection-secret.key"); | ||
| try { | ||
| connectionSecret = readFileSync(defaultPath, "utf-8").trim(); | ||
| connectionSecret = readFileSync(connectionPath, "utf-8").trim(); | ||
| } | ||
| catch (error) { | ||
| const err = error; | ||
| if (err.code !== "ENOENT") { | ||
| // only throw an error if it's not a file not found error | ||
| if (err.code !== "ENOENT") | ||
| throw err; | ||
| } | ||
| } | ||
| } | ||
| if (!connectionSecret && existsSync(pendingPath)) { | ||
| if (opts.verbose) { | ||
| console.error("Pending connection found. Waiting for wallet approval..."); | ||
| } | ||
| const pendingRelayPath = getPendingConnectionRelayPath(walletName); | ||
| return await completePendingConnection(pendingPath, connectionPath, undefined, opts.verbose, pendingRelayPath); | ||
| } | ||
| if (!connectionSecret) { | ||
| console.error("Error: No connection secret found. Pass -c <secret>, set NWC_URL, or create ~/.alby-cli/connection-secret.key"); | ||
| process.exit(1); | ||
| throw new Error("No connection secret provided. Pass -c <secret or file path>, set NWC_URL, use --wallet-name <name>, or create ~/.alby-cli/connection-secret.key"); | ||
| } | ||
@@ -29,0 +118,0 @@ // Auto-detect: if it doesn't start with the protocol, treat as file path |
+8
-4
@@ -5,8 +5,7 @@ { | ||
| "repository": "https://github.com/getAlby/cli.git", | ||
| "version": "0.2.4", | ||
| "version": "0.3.0", | ||
| "type": "module", | ||
| "main": "build/index.js", | ||
| "bin": { | ||
| "cli": "build/index.js", | ||
| "alby-cli": "build/index.js" | ||
| "cli": "build/index.js" | ||
| }, | ||
@@ -37,6 +36,11 @@ "files": [ | ||
| "license": "MIT", | ||
| "engines": { | ||
| "node": ">=20" | ||
| }, | ||
| "dependencies": { | ||
| "@getalby/lightning-tools": "^7.0.2", | ||
| "@getalby/sdk": "^7.0.0", | ||
| "commander": "^13.1.0" | ||
| "@noble/hashes": "^2.0.1", | ||
| "commander": "^14.0.3", | ||
| "nostr-tools": "^2.23.3" | ||
| }, | ||
@@ -43,0 +47,0 @@ "devDependencies": { |
+55
-5
@@ -9,4 +9,54 @@ # Alby NWC CLI | ||
| ### First-time setup | ||
| The CLI is an interface to a wallet and therefore needs a connection secret. | ||
| **Option 1: `auth` — for wallets that support it (e.g. Alby Hub)** | ||
| ```bash | ||
| # Pass a file path to a connection secret (preferred) | ||
| # Step 1: generate a connection URL and open it in your wallet to approve | ||
| # --app-name is the name of the agent/app that will use the wallet via the CLI (e.g. "Claude Code", "OpenClaw") | ||
| npx @getalby/cli auth https://my.albyhub.com --app-name "Claude Code" | ||
| # Step 2: after approving in the wallet, complete the connection | ||
| npx @getalby/cli auth --complete | ||
| ``` | ||
| **Option 2: `connect` — paste a NWC connection secret directly** | ||
| ```bash | ||
| npx @getalby/cli connect "nostr+walletconnect://..." | ||
| ``` | ||
| ### Multiple wallets | ||
| Use `--wallet-name` when setting up to save named connections: | ||
| ```bash | ||
| npx @getalby/cli connect "nostr+walletconnect://..." --wallet-name work | ||
| npx @getalby/cli auth https://my.albyhub.com --app-name "Claude Code" --wallet-name personal | ||
| ``` | ||
| Then pass `--wallet-name` to any command to use that wallet: | ||
| ```bash | ||
| npx @getalby/cli --wallet-name work get-balance | ||
| npx @getalby/cli --wallet-name personal pay-invoice --invoice lnbc... | ||
| ``` | ||
| ### Connection secret resolution (in order of priority) | ||
| 1. `--connection-secret` flag (value or path to file) | ||
| 2. `--wallet-name` flag (`~/.alby-cli/connection-secret-<name>.key`) | ||
| 3. `NWC_URL` environment variable | ||
| 4. `~/.alby-cli/connection-secret.key` (default file location) | ||
| ```bash | ||
| # Use the default saved wallet connection (preferred) | ||
| npx @getalby/cli <command> [options] | ||
| # Use a named wallet | ||
| npx @getalby/cli --wallet-name alice <command> [options] | ||
| # Pass a file path to a connection secret | ||
| npx @getalby/cli -c /path/to/secret.txt <command> [options] | ||
@@ -20,3 +70,3 @@ | ||
| You can also pass a connection string via the `NWC_URL` environment variable instead of using the `-c` option: | ||
| You can also set the `NWC_URL` environment variable instead of using the `-c` option: | ||
@@ -47,3 +97,3 @@ ```txt | ||
| These commands require `--connection-secret`: | ||
| These commands require a wallet connection (`-c`, `--wallet-name`, or `NWC_URL`): | ||
@@ -128,3 +178,3 @@ ```bash | ||
| These require `-c` or `--connection-secret`: | ||
| These require a wallet connection (`-c`, `--wallet-name`, or `NWC_URL`): | ||
@@ -148,3 +198,3 @@ | Command | Description | Required Options | | ||
| These require `-c` or `--connection-secret`: | ||
| These require a wallet connection (`-c`, `--wallet-name`, or `NWC_URL`): | ||
@@ -151,0 +201,0 @@ | Command | Description | Required Options | |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
77169
19.8%54
3.85%1331
20.56%217
29.94%5
66.67%+ Added
+ Added
+ Added
+ Added
- Removed
Updated