Sign In

@agentpump/cli

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@agentpump/cli - npm Package Compare versions

Comparing version
0.1.0
to
0.2.0
+41
src/browser.mjs
// Best-effort browser opener for the login flow.
//
// The caller always prints the URL and code first, so this is pure convenience: it never throws and
// never blocks. If it can't (or shouldn't) open, the user just copies the link.
import { spawn } from 'node:child_process';
// Don't auto-open when it would be useless or land on the wrong machine:
// - opted out (--no-browser, NO_BROWSER, or BROWSER='')
// - not an interactive terminal (CI, piped output)
// - a remote session — a browser would open on the remote host, not the user's screen
// - headless Linux (no display server)
function shouldOpen(disabled) {
const env = process.env;
if (disabled || env.NO_BROWSER || env.BROWSER === '') return false;
if (!process.stdout.isTTY) return false;
if (env.SSH_CONNECTION || env.SSH_TTY) return false;
if (process.platform === 'linux' && !env.DISPLAY && !env.WAYLAND_DISPLAY) return false;
return true;
}
function opener(url) {
if (process.platform === 'darwin') return ['open', [url]];
// The empty title arg keeps `start` from treating a quoted URL as the window title.
if (process.platform === 'win32') return ['cmd', ['/c', 'start', '', url]];
const browser = process.env.BROWSER;
return browser ? [browser, [url]] : ['xdg-open', [url]];
}
// Returns true only if we actually spawned an opener — the caller uses that to word its message.
export function openBrowser(url, { disabled = false } = {}) {
if (!shouldOpen(disabled)) return false;
const [cmd, args] = opener(url);
try {
const child = spawn(cmd, args, { stdio: 'ignore', detached: true });
child.on('error', () => {}); // e.g. xdg-open not installed — stay silent, URL is already shown
child.unref();
return true;
} catch {
return false;
}
}
+2
-2

@@ -48,4 +48,4 @@ #!/usr/bin/env node

Flags: --json --yes --no-keychain --base <url> --app-id <id> --profile <name>
Env: AGENTPUMP_TOKEN, AGENTPUMP_BASE, AGENTPUMP_PRIVY_APP_ID, AGENTPUMP_PROFILE
Flags: --json --yes --no-keychain --no-browser --base <url> --app-id <id> --profile <name>
Env: AGENTPUMP_TOKEN, AGENTPUMP_BASE, AGENTPUMP_PRIVY_APP_ID, AGENTPUMP_PROFILE, NO_BROWSER

@@ -52,0 +52,0 @@ Deposits cannot be made from the CLI — they need your Privy wallet to sign in a browser.`;

{
"name": "@agentpump/cli",
"version": "0.1.0",
"version": "0.2.0",
"description": "Drive your AgentPump account from the terminal — create and tune autonomous trading agents, manage funds, watch the market.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -33,2 +33,3 @@ # @agentpump/cli

Opened your browser.
Waiting for approval....

@@ -38,2 +39,6 @@ Signed in as you@example.com · balance $3.00 · 0 agent(s)

The CLI opens that link for you when it can. It doesn't in a CI job, over SSH, or on a headless
machine — there the URL is printed to copy. Pass `--no-browser` (or set `NO_BROWSER`) to always
skip opening.
After that you are done. The access token lasts 15 minutes and the CLI refreshes it silently; the

@@ -109,3 +114,3 @@ refresh token is good for 30 days from last use.

|---|---|---|
| `--base <url>` | `AGENTPUMP_BASE` | `https://agentpump-server.fly.dev` |
| `--base <url>` | `AGENTPUMP_BASE` | `https://agentpump.app` |
| `--app-id <id>` | `AGENTPUMP_PRIVY_APP_ID` | the production Privy app |

@@ -115,3 +120,4 @@ | `--profile <name>` | `AGENTPUMP_PROFILE` | `default` — separate credential slots |

`--json` prints raw responses, `--yes` skips confirmations, `--no-keychain` forces file storage.
`--json` prints raw responses, `--yes` skips confirmations, `--no-keychain` forces file storage,
`--no-browser` (or `NO_BROWSER`) never opens a browser on login.

@@ -118,0 +124,0 @@ ## License

@@ -5,3 +5,3 @@ // Minimal argv parser: `--flag`, `--flag value`, `--flag=value`, and positionals.

// --json and the command vanishes (the same way `--yes create …` broke before this set existed).
const BOOL_FLAGS = new Set(['json', 'yes', 'new', 'stdin', 'no-keychain', 'help']);
const BOOL_FLAGS = new Set(['json', 'yes', 'new', 'stdin', 'no-keychain', 'no-browser', 'help']);

@@ -8,0 +8,0 @@ export function parseArgs(argv) {

@@ -7,2 +7,3 @@ // Privy device authorization (RFC 8628) — the login flow.

import { die, sleep } from './ui.mjs';
import { openBrowser } from './browser.mjs';

@@ -16,3 +17,6 @@ export async function deviceLogin(config) {

const d = await dr.json();
console.log(`\nApprove this device in your browser:\n ${d.verification_uri_complete}\n\n Code: ${d.user_code}\n`);
const url = d.verification_uri_complete;
console.log(`\nApprove this device in your browser:\n ${url}\n\n Code: ${d.user_code}\n`);
// Best-effort convenience — the URL is already shown, so this only ever helps.
if (openBrowser(url, { disabled: config.noBrowser })) console.log('Opened your browser.\n');
process.stdout.write('Waiting for approval...');

@@ -19,0 +23,0 @@

@@ -15,3 +15,5 @@ // Runtime configuration, resolved once from flags and environment.

const DEFAULT_BASE = 'https://agentpump-server.fly.dev';
// The public site proxies /api/* to the API server (Next.js rewrites), so the CLI talks to the brand
// domain and stays decoupled from where the backend is hosted.
const DEFAULT_BASE = 'https://agentpump.app';
const DEFAULT_APP_ID = 'cmrw3m8xp00ca0clhkmi2vikr';

@@ -26,2 +28,3 @@

useKeychain: process.platform === 'darwin' && !flags['no-keychain'],
noBrowser: !!flags['no-browser'],
// An env token overrides stored credentials entirely (CI, one-off runs).

@@ -28,0 +31,0 @@ envToken: process.env.AGENTPUMP_TOKEN || null,