🌈 jup.sh docs

Quickstart

This guide runs the current jup.sh 1.0 CLI with npx.

The CLI is useful for agent-facing payment flows:

agent intent -> policy decision -> Jupiter quote -> authorization -> receipt

The server path never signs or custodies funds. The CLI can sign and submit only when the user explicitly provides a local Solana keypair.

Prerequisites

You need:

The homepage keeps the first step intentionally short:

npx jup-sh init
npx jup-sh doctor

This page expands that into the full developer flow:

npx jup-sh init
npx jup-sh doctor
npx jup-sh policy trust api.vendor.example
npx jup-sh pay --agent deepseek --token SOL --amount 6 --settle USDC --recipient api.vendor.example --json

For source development, you also need a working Rust toolchain and git:

git clone https://github.com/jerrywang33/jup.git
cd jup
npm install

Use npm run cli:alpha -- for the local Node wrapper, or npm run cli -- to run the Rust CLI directly through Cargo.

Command Flow

flowchart LR
  Agent["agent or script"]
  CLI["jup.sh CLI"]
  Policy["local policy"]
  Quote["mock or Jupiter quote"]
  Store["local intent store"]
  Result["JSON + exit code"]
  Review["Risk Review URL"]

  Agent -->|"pay command"| CLI
  CLI --> Policy
  CLI --> Quote
  Policy --> Result
  Quote --> Result
  Result --> Store
  Result -->|"review_required"| Review

The CLI always creates a local intent record when the command is valid enough to evaluate. The policy decision controls what the caller should do next.

1. Initialize Local Config

npx jup-sh init

This writes:

jup.config.json
jup.policy.json

jup.config.json controls local paths and defaults. jup.policy.json controls risk thresholds. Use --force if you intentionally want to overwrite them.

For source development, use:

npm run cli:alpha -- init

2. Check The Workspace

npx jup-sh doctor
npx jup-sh doctor --json

doctor verifies the local config, policy file, intent store, review URL, quote provider, and trusted recipients. It is the fastest way to confirm that the workspace is ready before an agent creates payment intents.

For source development, use:

npm run cli:alpha -- doctor

3. Configure Local Policy

npx jup-sh policy show

The default policy is conservative:

Create or overwrite only the local policy file:

npx jup-sh policy init

This writes:

jup.policy.json

Use --force if you intentionally want to overwrite it.

Trust a known API or vendor recipient:

npx jup-sh policy trust api.vendor.example

Raise the auto-pay limit:

npx jup-sh policy set max-auto 10

For source development, prefix the same commands with npm run cli:alpha --.

4. Create A Payment Intent

npx jup-sh pay --agent deepseek --token SOL --amount 20 --settle USDC

This creates a local payment intent and saves it under:

.jup-sh/intents/<intent_id>.json

By default, the command uses the mock quote provider. That makes tests stable and does not call external APIs.

5. Use JSON Mode For Agents

Agents and scripts should use --json:

npx jup-sh pay \
  --agent deepseek \
  --token SOL \
  --amount 20 \
  --settle USDC \
  --json

--json prints one structured object to stdout. Agents should branch on the exit code and nextAction.

Exit code Decision Agent behavior
0 auto_pay Intent is inside policy and ready for local authorization in a future phase.
2 review_required Open or return the Risk Review URL. This is a controlled policy outcome.
1 rejected or command failure Stop the payment flow.

The field-level contract is documented in CLI JSON Contract.

For a fuller caller guide, see Agent Integration.

6. Test The Three Policy Outcomes

Trust the demo recipient first:

npx jup-sh policy trust jup-sh-demo

Auto-pay candidate with a trusted recipient and small amount:

npx jup-sh pay \
  --agent deepseek \
  --token SOL \
  --amount 2 \
  --settle USDC \
  --recipient jup-sh-demo \
  --json

Review-required payment with the default policy:

npx jup-sh pay \
  --agent deepseek \
  --token SOL \
  --amount 20 \
  --settle USDC \
  --json

Rejected payment with an unsupported token:

npx jup-sh pay \
  --agent deepseek \
  --token FAKE \
  --amount 20 \
  --settle USDC \
  --json

7. Use Jupiter Execution Mode

npx jup-sh pay \
  --agent deepseek \
  --token SOL \
  --amount 20 \
  --settle USDC \
  --recipient-token-account <RECIPIENT_USDC_TOKEN_ACCOUNT> \
  --quote-provider jupiter

This asks Jupiter for an ExactOut quote that can be turned into a swap transaction. To execute from the CLI, sign locally with a user keypair:

npx jup-sh intent execute intent_xxx \
  --keypair ~/.config/solana/id.json \
  --rpc-url https://api.mainnet-beta.solana.com \
  --json

The CLI submits the signed transaction and writes a local receipt.

Optional settings:

--jupiter-api-key <key>
--jupiter-quote-url <url>
--slippage-bps 50

You can also set:

JUPITER_API_KEY=...

See Jupiter Quote-Only Design for the settlement boundary.

8. Inspect Local Intents

List saved intents:

npx jup-sh intent list

Show one intent:

npx jup-sh intent show intent_xxx

Export a Risk Review URL:

npx jup-sh intent export intent_xxx

Or use the review shortcut:

npx jup-sh review intent_xxx

The exported URL contains a fragment payload:

https://jup.sh/pay/intent_xxx#intent=<base64url-json-payload>

See Risk Review Export Design for the static review model.

9. Try The SDK Surface

The first TypeScript SDK surface is local and source-only:

import { createPaymentIntent } from "../sdk/index.js";

const intent = await createPaymentIntent({
  agent: "deepseek",
  token: "SOL",
  amount: 20,
  settle: "USDC",
});

Typecheck the SDK and example:

npm run sdk:check
npm run sdk:smoke
npm run sdk:jupiter:live

The SDK returns the same PaymentIntent contract as the CLI JSON mode. The SDK itself is still source-only and does not call a hosted backend yet.

Use the SDK Jupiter quote-only provider:

import { createJupiterQuoteProvider, createPaymentIntent } from "../sdk/index.js";

const intent = await createPaymentIntent(
  {
    agent: "deepseek",
    token: "SOL",
    amount: 20,
    settle: "USDC",
  },
  {
    quoteProvider: createJupiterQuoteProvider(),
  }
);

This calls Jupiter for a quote estimate only. It does not sign, submit, or execute a swap.

sdk:jupiter:live is skipped by default. Set JUP_SH_LIVE_JUPITER=1 when you want to call Jupiter’s live quote API from the example.

Generate a Risk Review URL from the SDK:

import {
  createPaymentIntent,
  createRiskReviewUrl,
} from "../sdk/index.js";

const intent = await createPaymentIntent({
  agent: "deepseek",
  token: "SOL",
  amount: 20,
  settle: "USDC",
});

if (intent.nextAction === "open_review") {
  const reviewUrl = createRiskReviewUrl(intent, {
    reviewBaseUrl: "https://www.jup.sh",
  });

  console.log(reviewUrl);
}

This uses the same #intent=<base64url-json-payload> model as CLI intent export, so the URL opens directly in the hosted Risk Review page.

Try SDK policy profiles:

import {
  createPaymentIntent,
  getPolicyProfile,
} from "../sdk/index.js";

const intent = await createPaymentIntent(
  {
    agent: "deepseek",
    token: "SOL",
    amount: 20,
    settle: "USDC",
  },
  {
    policy: getPolicyProfile("sandbox"),
  }
);

Available profiles:

Profile Intended use
sandbox Agent demos, hackathons, and local testing with fewer review interruptions.
balanced Known agents paying known APIs. This is the default alpha behavior.
strict New agents, unknown recipients, or higher-risk environments.

Add a trusted recipient to a profile:

import {
  createPaymentIntent,
  getPolicyProfile,
  withTrustedRecipients,
} from "../sdk/index.js";

const policy = withTrustedRecipients(getPolicyProfile("balanced"), [
  "api.vendor.example",
]);

const intent = await createPaymentIntent(
  {
    agent: "deepseek",
    token: "SOL",
    amount: 2,
    settle: "USDC",
    recipient: "api.vendor.example",
  },
  { policy }
);

This keeps small known-recipient payments inside policy while still sending unknown recipients to Risk Review.

Explain a policy decision:

import {
  createPaymentIntent,
  explainPolicyDecision,
  getPolicyProfile,
} from "../sdk/index.js";

const intent = await createPaymentIntent(
  {
    agent: "deepseek",
    token: "SOL",
    amount: 20,
    settle: "USDC",
  },
  {
    policy: getPolicyProfile("balanced"),
  }
);

const explanation = explainPolicyDecision(intent);

console.log(explanation.summary);
console.log(explanation.riskFactors);
console.log(explanation.recommendedAction);

This is useful for agent logs, Risk Review, and local audit trails. It explains the existing policyChecks; it does not change the payment decision.

10. Run The Release Gate

Before a release checkpoint:

npm run release:check

This runs:

The release gate exists because agent payment tools need predictable command behavior before they touch signing or money movement.