@bankr/cli 0.2.13 → 0.2.15

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
@@ -10,6 +10,8 @@ npm install -g @bankr/cli
10
10
 
11
11
  ## Quick Start
12
12
 
13
+ A [Bankr Club subscription](https://bankr.bot) or LLM credits (Max Mode) is required to use the agent. There is no free tier.
14
+
13
15
  ```bash
14
16
  # Authenticate with your API key
15
17
  bankr login
@@ -101,6 +103,31 @@ bankr agent status job_ABC123DEF456
101
103
  bankr agent cancel job_ABC123DEF456
102
104
  ```
103
105
 
106
+ ### LLM Gateway
107
+
108
+ Launch Claude Code / OpenCode routed through the Bankr gateway:
109
+
110
+ ```bash
111
+ # Claude Code (auto-translates dotted model IDs to the Anthropic wire format)
112
+ bankr llm claude --model claude-opus-4-7
113
+
114
+ # Or use dotted form — bankr llm claude rewrites it to claude-opus-4-7
115
+ bankr llm claude --model claude-opus-4.7
116
+
117
+ # OpenCode (use the bankr/ prefix with the gateway-canonical dotted form)
118
+ bankr llm opencode -m bankr/claude-opus-4.7
119
+ ```
120
+
121
+ **Claude Code model format**: Claude Code's `--model` flag expects
122
+ Anthropic-style dashed IDs (`claude-opus-4-7`, `claude-sonnet-4-6`,
123
+ `claude-haiku-4-5`). If you pass the gateway-canonical dotted form
124
+ (`claude-opus-4.7`), Claude Code silently falls back to its default —
125
+ the flag appears honored but the real request is a different model.
126
+
127
+ `bankr llm claude` translates dotted → dashed for you. If you use older
128
+ versions of the CLI (or invoke `claude` directly via `ANTHROPIC_BASE_URL`),
129
+ pass the dashed form explicitly.
130
+
104
131
  ### Configuration
105
132
 
106
133
  ```bash
package/dist/cli.js CHANGED
@@ -23,7 +23,10 @@ import { updateCommand } from "./commands/update.js";
23
23
  import { whoamiCommand } from "./commands/whoami.js";
24
24
  import { tokensSearchCommand, tokensInfoCommand } from "./commands/tokens.js";
25
25
  import { x402InitCommand, x402AddCommand, x402ConfigureCommand, x402DeployCommand, x402ListCommand, x402PauseResumeCommand, x402DeleteCommand, x402RevenueCommand, x402EnvSetCommand, x402EnvListCommand, x402EnvUnsetCommand, x402SearchCommand, x402SchemaCommand, x402CallCommand, } from "./commands/x402.js";
26
+ import { webhooksInitCommand, webhooksAddCommand, webhooksDeployCommand, webhooksListCommand, webhooksPauseResumeCommand, webhooksDeleteCommand, webhooksLogsCommand, webhooksEnvSetCommand, webhooksEnvListCommand, webhooksEnvUnsetCommand, } from "./commands/webhooks.js";
26
27
  import { profileViewCommand, profileCreateCommand, profileUpdateCommand, profileDeleteCommand, profileAddUpdateCommand, } from "./commands/profile.js";
28
+ import { filesListCommand, filesUploadCommand, filesDownloadCommand, filesMkdirCommand, filesRmCommand, filesStorageCommand, filesCatCommand, filesEditCommand, filesWriteCommand, filesSearchCommand, filesMvCommand, filesRenameCommand, filesInfoCommand, } from "./commands/files.js";
29
+ import { clubStatusCommand, clubSignupCommand, clubCancelCommand, } from "./commands/club.js";
27
30
  import * as output from "./lib/output.js";
28
31
  import { checkForUpdate } from "./lib/updateCheck.js";
29
32
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
@@ -740,6 +743,96 @@ program
740
743
  .action(async (opts) => {
741
744
  await updateCommand({ check: opts.check });
742
745
  });
746
+ // ── File Storage ────────────────────────────────────────────────────────
747
+ const filesCmd = program
748
+ .command("files")
749
+ .description("Manage your file storage")
750
+ .action(() => filesListCommand({}));
751
+ filesCmd
752
+ .command("ls")
753
+ .description("List files")
754
+ .option("--folder <path>", "Filter by folder path")
755
+ .action(filesListCommand);
756
+ filesCmd
757
+ .command("upload <file>")
758
+ .description("Upload a file from your local machine")
759
+ .option("--folder <path>", "Destination folder (default: /)")
760
+ .action(filesUploadCommand);
761
+ filesCmd
762
+ .command("download <fileId>")
763
+ .description("Get a download URL for a file")
764
+ .action(filesDownloadCommand);
765
+ filesCmd
766
+ .command("mkdir <name>")
767
+ .description("Create a folder")
768
+ .option("--parent <path>", "Parent folder path (default: /)")
769
+ .action(filesMkdirCommand);
770
+ filesCmd
771
+ .command("rm <fileId>")
772
+ .description("Delete a file")
773
+ .action(filesRmCommand);
774
+ filesCmd
775
+ .command("storage")
776
+ .description("Show storage usage and quota")
777
+ .action(filesStorageCommand);
778
+ filesCmd
779
+ .command("cat <fileId>")
780
+ .description("Print file contents to stdout (or save to a local path)")
781
+ .option("-o, --output <path>", "Save contents to a local file instead of stdout")
782
+ .action(filesCatCommand);
783
+ filesCmd
784
+ .command("edit <fileId>")
785
+ .description("Edit a file in place: find-and-replace (--find + --replace) or full overwrite (--content or --from)")
786
+ .option("-f, --find <text>", "Text to find (requires --replace)")
787
+ .option("-r, --replace <text>", "Replacement text (requires --find)")
788
+ .option("--all", "Replace every occurrence (default: must match once)")
789
+ .option("--content <text>", "Full new file content (overwrite mode)")
790
+ .option("--from <path>", "Read new file content from a local file (overwrite mode)")
791
+ .action(filesEditCommand);
792
+ filesCmd
793
+ .command("write <fileId>")
794
+ .description("Overwrite a file's text content from a local file or stdin")
795
+ .option("--from <path>", "Read content from a local file (default: stdin)")
796
+ .action(filesWriteCommand);
797
+ filesCmd
798
+ .command("search <query>")
799
+ .description("Search files by filename, extension, or description")
800
+ .option("--folder <path>", "Limit search to a specific folder")
801
+ .option("--mime-type <prefix>", "Filter by MIME type prefix (e.g. text/, image/)")
802
+ .option("--limit <n>", "Max results (default: 20)")
803
+ .action(async (query, opts) => filesSearchCommand(query, opts));
804
+ filesCmd
805
+ .command("mv <fileId> <folder>")
806
+ .description("Move a file to a different folder")
807
+ .action(filesMvCommand);
808
+ filesCmd
809
+ .command("rename <fileId> <name>")
810
+ .description("Rename a file or folder")
811
+ .action(filesRenameCommand);
812
+ filesCmd
813
+ .command("info <fileId>")
814
+ .description("Show file metadata")
815
+ .action(filesInfoCommand);
816
+ // ── Bankr Club ────────────────────────────────────────────────────────
817
+ const clubCmd = program
818
+ .command("club")
819
+ .description("View Bankr Club membership, sign up, or cancel")
820
+ .action(clubStatusCommand);
821
+ clubCmd
822
+ .command("status")
823
+ .description("Show your Bankr Club membership status")
824
+ .action(clubStatusCommand);
825
+ clubCmd
826
+ .command("signup")
827
+ .description("Sign up for Bankr Club (pays in $BNKR from your wallet)")
828
+ .option("--yearly", "Subscribe yearly instead of monthly")
829
+ .option("-y, --yes", "Skip confirmation prompt")
830
+ .action(clubSignupCommand);
831
+ clubCmd
832
+ .command("cancel")
833
+ .description("Cancel your Bankr Club subscription")
834
+ .option("-y, --yes", "Skip confirmation prompt")
835
+ .action(clubCancelCommand);
743
836
  // ── x402 Endpoint Hosting ─────────────────────────────────────────────
744
837
  const x402Cmd = program
745
838
  .command("x402")
@@ -795,6 +888,58 @@ x402EnvCmd
795
888
  .command("unset <key>")
796
889
  .description("Remove an env var")
797
890
  .action(x402EnvUnsetCommand);
891
+ // ── User Webhooks ─────────────────────────────────────────────────────
892
+ const webhooksCmd = program
893
+ .command("webhooks")
894
+ .description("Deploy and manage user webhooks that trigger the Bankr agent on external events");
895
+ webhooksCmd
896
+ .command("init")
897
+ .description("Scaffold webhooks/ folder and bankr.webhooks.json config")
898
+ .action(webhooksInitCommand);
899
+ webhooksCmd
900
+ .command("add <name>")
901
+ .description("Add a new webhook handler")
902
+ .option("--provider <name>", "Scaffold with a provider template: slack | github | stripe | generic", "generic")
903
+ .action((name, opts) => webhooksAddCommand(name, { provider: opts.provider }));
904
+ webhooksCmd
905
+ .command("deploy [name]")
906
+ .description("Bundle and deploy webhooks to Bankr")
907
+ .action(webhooksDeployCommand);
908
+ webhooksCmd
909
+ .command("list")
910
+ .description("List your deployed webhooks")
911
+ .action(webhooksListCommand);
912
+ webhooksCmd
913
+ .command("pause <name>")
914
+ .description("Pause a deployed webhook")
915
+ .action(async (name) => webhooksPauseResumeCommand(name, "pause"));
916
+ webhooksCmd
917
+ .command("resume <name>")
918
+ .description("Resume a paused webhook")
919
+ .action(async (name) => webhooksPauseResumeCommand(name, "resume"));
920
+ webhooksCmd
921
+ .command("delete <name>")
922
+ .description("Delete a deployed webhook (cannot be undone)")
923
+ .action(webhooksDeleteCommand);
924
+ webhooksCmd
925
+ .command("logs <name>")
926
+ .description("View recent invocations for a webhook")
927
+ .action(webhooksLogsCommand);
928
+ const webhooksEnvCmd = webhooksCmd
929
+ .command("env")
930
+ .description("Manage encrypted environment variables for your webhooks");
931
+ webhooksEnvCmd
932
+ .command("set <keyValue>")
933
+ .description("Set an env var (KEY=VALUE)")
934
+ .action(webhooksEnvSetCommand);
935
+ webhooksEnvCmd
936
+ .command("list")
937
+ .description("List env var names")
938
+ .action(webhooksEnvListCommand);
939
+ webhooksEnvCmd
940
+ .command("unset <key>")
941
+ .description("Remove an env var")
942
+ .action(webhooksEnvUnsetCommand);
798
943
  x402Cmd
799
944
  .command("search [query...]")
800
945
  .description("Search the x402 service marketplace (no auth required)")
@@ -0,0 +1,9 @@
1
+ export declare function clubStatusCommand(): Promise<void>;
2
+ export declare function clubSignupCommand(opts: {
3
+ yearly?: boolean;
4
+ yes?: boolean;
5
+ }): Promise<void>;
6
+ export declare function clubCancelCommand(opts: {
7
+ yes?: boolean;
8
+ }): Promise<void>;
9
+ //# sourceMappingURL=club.d.ts.map
@@ -0,0 +1,151 @@
1
+ import { confirm } from "@inquirer/prompts";
2
+ import { CLI_USER_AGENT, getApiUrl, requireApiKey } from "../lib/config.js";
3
+ import * as output from "../lib/output.js";
4
+ function authHeaders() {
5
+ return {
6
+ "X-API-Key": requireApiKey(),
7
+ "Content-Type": "application/json",
8
+ "User-Agent": CLI_USER_AGENT,
9
+ };
10
+ }
11
+ async function fetchStatus() {
12
+ const res = await fetch(`${getApiUrl()}/bankr-club/`, {
13
+ headers: authHeaders(),
14
+ });
15
+ if (!res.ok) {
16
+ const body = await res.json().catch(() => ({ error: res.statusText }));
17
+ throw new Error(body.error || res.statusText);
18
+ }
19
+ return (await res.json());
20
+ }
21
+ function formatRenewDate(unix) {
22
+ if (!unix)
23
+ return "—";
24
+ return new Date(unix * 1000).toLocaleDateString();
25
+ }
26
+ // ── Status ──────────────────────────────────────────────────────────────
27
+ export async function clubStatusCommand() {
28
+ const spinner = output.spinner("Fetching Bankr Club status...");
29
+ try {
30
+ const status = await fetchStatus();
31
+ spinner.stop();
32
+ if (!status.hasBankrClub) {
33
+ output.label("Membership", output.fmt.dim("Not a member"));
34
+ output.dim("Run `bankr club signup` to join.");
35
+ return;
36
+ }
37
+ const state = status.active
38
+ ? output.fmt.success("active")
39
+ : output.fmt.warn("cancelled (grace period)");
40
+ output.label("Membership", state);
41
+ if (status.subscriptionType) {
42
+ output.label("Plan", status.subscriptionType);
43
+ }
44
+ if (status.renewOrCancelOn) {
45
+ const label = status.active ? "Renews on" : "Ends on";
46
+ output.label(label, formatRenewDate(status.renewOrCancelOn));
47
+ }
48
+ if (typeof status.dailyMessageCount === "number") {
49
+ output.label("Messages today", String(status.dailyMessageCount));
50
+ }
51
+ }
52
+ catch (err) {
53
+ spinner.stop();
54
+ output.error(err instanceof Error ? err.message : String(err));
55
+ process.exit(1);
56
+ }
57
+ }
58
+ // ── Sign up ─────────────────────────────────────────────────────────────
59
+ export async function clubSignupCommand(opts) {
60
+ try {
61
+ const current = await fetchStatus();
62
+ if (current.hasBankrClub && current.active) {
63
+ output.warn("You already have an active Bankr Club subscription.");
64
+ return;
65
+ }
66
+ const yearly = !!opts.yearly;
67
+ const quoteRes = await fetch(`${getApiUrl()}/bankr-club/quote?yearly=${yearly}`, { headers: authHeaders() });
68
+ if (!quoteRes.ok) {
69
+ const body = await quoteRes
70
+ .json()
71
+ .catch(() => ({ error: quoteRes.statusText }));
72
+ throw new Error(body.error || quoteRes.statusText);
73
+ }
74
+ const quote = (await quoteRes.json());
75
+ output.label("Plan", yearly ? "Yearly" : "Monthly");
76
+ output.label("Price", `${output.formatUsd(quote.usdPrice)} (in $BNKR)`);
77
+ output.label("Cost", `${quote.priceInBankr} BNKR`);
78
+ output.dim(`Quote expires ${new Date(quote.expiresAt * 1000).toLocaleString()}.`);
79
+ output.blank();
80
+ output.dim("Payment is deducted from the $BNKR balance in your Bankr wallet.");
81
+ const ok = opts.yes ||
82
+ (await confirm({
83
+ message: "Confirm subscription?",
84
+ default: false,
85
+ theme: output.bankrTheme,
86
+ }));
87
+ if (!ok) {
88
+ output.dim("Cancelled.");
89
+ return;
90
+ }
91
+ const spinner = output.spinner("Signing up for Bankr Club...");
92
+ const signUpRes = await fetch(`${getApiUrl()}/bankr-club/sign-up?yearly=${yearly}`, { headers: authHeaders() });
93
+ spinner.stop();
94
+ if (!signUpRes.ok) {
95
+ const body = await signUpRes
96
+ .json()
97
+ .catch(() => ({ error: signUpRes.statusText }));
98
+ throw new Error(body.error || signUpRes.statusText);
99
+ }
100
+ output.success("Welcome to Bankr Club!");
101
+ output.dim("Run `bankr club` to see your status.");
102
+ }
103
+ catch (err) {
104
+ output.error(err instanceof Error ? err.message : String(err));
105
+ process.exit(1);
106
+ }
107
+ }
108
+ // ── Cancel ──────────────────────────────────────────────────────────────
109
+ export async function clubCancelCommand(opts) {
110
+ try {
111
+ const status = await fetchStatus();
112
+ if (!status.hasBankrClub) {
113
+ output.dim("You are not a Bankr Club member.");
114
+ return;
115
+ }
116
+ if (!status.active) {
117
+ output.dim("Your subscription is already cancelled.");
118
+ if (status.renewOrCancelOn) {
119
+ output.dim(`Access ends on ${formatRenewDate(status.renewOrCancelOn)}.`);
120
+ }
121
+ return;
122
+ }
123
+ const ok = opts.yes ||
124
+ (await confirm({
125
+ message: "Cancel Bankr Club? You'll keep access until the current billing period ends.",
126
+ default: false,
127
+ theme: output.bankrTheme,
128
+ }));
129
+ if (!ok) {
130
+ output.dim("Cancelled (subscription unchanged).");
131
+ return;
132
+ }
133
+ const spinner = output.spinner("Cancelling subscription...");
134
+ const res = await fetch(`${getApiUrl()}/bankr-club/cancel`, {
135
+ method: "POST",
136
+ headers: authHeaders(),
137
+ });
138
+ spinner.stop();
139
+ if (!res.ok) {
140
+ const body = await res.json().catch(() => ({ error: res.statusText }));
141
+ throw new Error(body.error || res.statusText);
142
+ }
143
+ output.success("Subscription cancelled.");
144
+ output.dim("You'll keep Bankr Club access until the end of the current billing period.");
145
+ }
146
+ catch (err) {
147
+ output.error(err instanceof Error ? err.message : String(err));
148
+ process.exit(1);
149
+ }
150
+ }
151
+ //# sourceMappingURL=club.js.map
@@ -0,0 +1,34 @@
1
+ export declare function filesListCommand(opts: {
2
+ folder?: string;
3
+ }): Promise<void>;
4
+ export declare function filesUploadCommand(filePath: string, opts: {
5
+ folder?: string;
6
+ }): Promise<void>;
7
+ export declare function filesDownloadCommand(fileId: string): Promise<void>;
8
+ export declare function filesMkdirCommand(name: string, opts: {
9
+ parent?: string;
10
+ }): Promise<void>;
11
+ export declare function filesRmCommand(fileId: string): Promise<void>;
12
+ export declare function filesStorageCommand(): Promise<void>;
13
+ export declare function filesCatCommand(fileId: string, opts: {
14
+ output?: string;
15
+ }): Promise<void>;
16
+ export declare function filesEditCommand(fileId: string, opts: {
17
+ find?: string;
18
+ replace?: string;
19
+ all?: boolean;
20
+ content?: string;
21
+ from?: string;
22
+ }): Promise<void>;
23
+ export declare function filesWriteCommand(fileId: string, opts: {
24
+ from?: string;
25
+ }): Promise<void>;
26
+ export declare function filesSearchCommand(query: string, opts: {
27
+ folder?: string;
28
+ mimeType?: string;
29
+ limit?: string;
30
+ }): Promise<void>;
31
+ export declare function filesMvCommand(fileId: string, folder: string): Promise<void>;
32
+ export declare function filesRenameCommand(fileId: string, name: string): Promise<void>;
33
+ export declare function filesInfoCommand(fileId: string): Promise<void>;
34
+ //# sourceMappingURL=files.d.ts.map