codecard-cli 0.1.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/dist/commands/alerts.d.ts +2 -0
  4. package/dist/commands/alerts.js +44 -0
  5. package/dist/commands/auth/login.d.ts +2 -0
  6. package/dist/commands/auth/login.js +43 -0
  7. package/dist/commands/auth/logout.d.ts +2 -0
  8. package/dist/commands/auth/logout.js +20 -0
  9. package/dist/commands/auth/whoami.d.ts +2 -0
  10. package/dist/commands/auth/whoami.js +32 -0
  11. package/dist/commands/balance.d.ts +2 -0
  12. package/dist/commands/balance.js +35 -0
  13. package/dist/commands/card/freeze.d.ts +3 -0
  14. package/dist/commands/card/freeze.js +68 -0
  15. package/dist/commands/card/list.d.ts +2 -0
  16. package/dist/commands/card/list.js +44 -0
  17. package/dist/commands/pnl.d.ts +2 -0
  18. package/dist/commands/pnl.js +57 -0
  19. package/dist/commands/project/create.d.ts +2 -0
  20. package/dist/commands/project/create.js +36 -0
  21. package/dist/commands/project/list.d.ts +2 -0
  22. package/dist/commands/project/list.js +42 -0
  23. package/dist/commands/rewards.d.ts +2 -0
  24. package/dist/commands/rewards.js +61 -0
  25. package/dist/commands/spend.d.ts +2 -0
  26. package/dist/commands/spend.js +116 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.js +52 -0
  29. package/dist/lib/api-client.d.ts +23 -0
  30. package/dist/lib/api-client.js +113 -0
  31. package/dist/lib/config.d.ts +16 -0
  32. package/dist/lib/config.js +40 -0
  33. package/dist/lib/output.d.ts +20 -0
  34. package/dist/lib/output.js +69 -0
  35. package/dist/lib/update-check.d.ts +1 -0
  36. package/dist/lib/update-check.js +74 -0
  37. package/dist/mcp-server.d.ts +2 -0
  38. package/dist/mcp-server.js +133 -0
  39. package/dist/shared/alert.d.ts +24 -0
  40. package/dist/shared/alert.js +2 -0
  41. package/dist/shared/alerts.d.ts +3 -0
  42. package/dist/shared/alerts.js +103 -0
  43. package/dist/shared/card.d.ts +12 -0
  44. package/dist/shared/card.js +2 -0
  45. package/dist/shared/cards.d.ts +2 -0
  46. package/dist/shared/cards.js +60 -0
  47. package/dist/shared/common.d.ts +21 -0
  48. package/dist/shared/common.js +2 -0
  49. package/dist/shared/filters.d.ts +8 -0
  50. package/dist/shared/filters.js +59 -0
  51. package/dist/shared/formatters.d.ts +7 -0
  52. package/dist/shared/formatters.js +44 -0
  53. package/dist/shared/index.d.ts +15 -0
  54. package/dist/shared/index.js +43 -0
  55. package/dist/shared/project.d.ts +24 -0
  56. package/dist/shared/project.js +2 -0
  57. package/dist/shared/projects.d.ts +3 -0
  58. package/dist/shared/projects.js +104 -0
  59. package/dist/shared/reward.d.ts +26 -0
  60. package/dist/shared/reward.js +2 -0
  61. package/dist/shared/rewards.d.ts +4 -0
  62. package/dist/shared/rewards.js +25 -0
  63. package/dist/shared/transaction.d.ts +36 -0
  64. package/dist/shared/transaction.js +2 -0
  65. package/dist/shared/transactions.d.ts +2 -0
  66. package/dist/shared/transactions.js +34 -0
  67. package/dist/shared/user.d.ts +12 -0
  68. package/dist/shared/user.js +2 -0
  69. package/dist/shared/users.d.ts +3 -0
  70. package/dist/shared/users.js +15 -0
  71. package/package.json +41 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Code Financial, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # codecard-cli
2
+
3
+ > **code_** — The financial stack for AI-native builders
4
+
5
+ CLI tool for managing your Code_ neobank account. Track spend, manage virtual cards, view project P&L, earn rewards — all from the terminal.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g codecard-cli
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Authenticate
17
+ codecard auth login
18
+
19
+ # Create a project (auto-provisions a virtual Visa card)
20
+ codecard project create "my-ai-app" --budget 3000
21
+
22
+ # View your spend
23
+ codecard spend
24
+
25
+ # Check project P&L
26
+ codecard pnl my-ai-app
27
+
28
+ # See rewards earned
29
+ codecard rewards
30
+ ```
31
+
32
+ ## Commands
33
+
34
+ | Command | Description |
35
+ |---|---|
36
+ | `codecard auth login` | Authenticate via browser OAuth or API key |
37
+ | `codecard auth logout` | Clear stored credentials |
38
+ | `codecard auth whoami` | Show current user |
39
+ | `codecard project list` | List all projects |
40
+ | `codecard project create <name>` | Create project + virtual card |
41
+ | `codecard spend` | View spend breakdown |
42
+ | `codecard balance` | Check balance and credit |
43
+ | `codecard pnl <project>` | Project profit & loss |
44
+ | `codecard card list` | List virtual cards |
45
+ | `codecard card freeze <id>` | Freeze a card |
46
+ | `codecard card unfreeze <id>` | Unfreeze a card |
47
+ | `codecard rewards` | View Code Credits |
48
+ | `codecard alerts` | View spend alerts |
49
+ | `codecard mcp` | Start MCP server for AI agents |
50
+
51
+ ## JSON Output
52
+
53
+ Every command supports `--json` for machine-readable output:
54
+
55
+ ```bash
56
+ codecard balance --json | jq '.available'
57
+ # → 12400
58
+
59
+ codecard spend --json --project my-ai-app | jq '.byProvider'
60
+ ```
61
+
62
+ ## MCP Server
63
+
64
+ The CLI includes a built-in MCP (Model Context Protocol) server, letting AI agents manage your finances:
65
+
66
+ ```bash
67
+ # Start the MCP server
68
+ codecard mcp
69
+
70
+ # Add to Claude Code
71
+ claude mcp add codecard -- codecard mcp
72
+ ```
73
+
74
+ **Available tools:** `list_projects`, `create_project`, `get_project_pnl`, `get_spend`, `get_balance`, `list_cards`, `freeze_card`, `unfreeze_card`, `get_rewards`, `get_alerts`
75
+
76
+ ## Reward Rates
77
+
78
+ | Category | Rate |
79
+ |---|---|
80
+ | AI Model APIs (OpenAI, Anthropic, etc.) | **5%** |
81
+ | Cloud & Infrastructure (Vercel, AWS, etc.) | **4%** |
82
+ | Dev Tools & SaaS (GitHub, Cursor, etc.) | **3%** |
83
+ | Everything Else | **1%** |
84
+
85
+ ## Links
86
+
87
+ - **Website:** [codecard.ai](https://codecard.ai)
88
+ - **Dashboard:** [codecard.ai/dashboard](https://codecard.ai/dashboard)
89
+ - **Docs:** [codecard.ai/docs](https://codecard.ai/docs)
90
+ - **GitHub:** [github.com/rajparekh7/code_](https://github.com/rajparekh7/code_)
91
+
92
+ ## License
93
+
94
+ MIT
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const alertsCommand: Command;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.alertsCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../lib/config");
10
+ const api_client_1 = require("../lib/api-client");
11
+ const output_1 = require("../lib/output");
12
+ const severityColor = {
13
+ critical: output_1.pink,
14
+ warning: output_1.orange,
15
+ info: output_1.blue,
16
+ };
17
+ exports.alertsCommand = new commander_1.Command("alerts")
18
+ .description("View spend alerts")
19
+ .option("--json", "Output as JSON")
20
+ .action(async (opts) => {
21
+ if (!(0, config_1.isAuthenticated)()) {
22
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
23
+ return;
24
+ }
25
+ const spinner = (0, ora_1.default)({ text: "Fetching alerts...", color: "green" }).start();
26
+ const { events } = await (0, api_client_1.getAlerts)();
27
+ spinner.stop();
28
+ if (opts.json) {
29
+ (0, output_1.printJson)(events);
30
+ return;
31
+ }
32
+ const unacked = events.filter((e) => !e.acknowledged).length;
33
+ (0, output_1.printHeader)(`Alerts (${unacked} unread)`);
34
+ for (const event of events) {
35
+ const color = severityColor[event.severity] || output_1.muted;
36
+ const badge = event.acknowledged ? (0, output_1.dim)(" ○") : color(" ●");
37
+ const severity = color(event.severity.toUpperCase().padEnd(8));
38
+ console.log();
39
+ console.log(badge + " " + severity + " " + event.title);
40
+ console.log((0, output_1.dim)(" " + event.projectName + " · " + new Date(event.triggeredAt).toLocaleDateString()));
41
+ console.log((0, output_1.muted)(" " + event.message));
42
+ }
43
+ console.log();
44
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const loginCommand: Command;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loginCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../../lib/config");
10
+ const output_1 = require("../../lib/output");
11
+ exports.loginCommand = new commander_1.Command("login")
12
+ .description("Authenticate with Code_")
13
+ .option("--api-key <key>", "Authenticate with an API key")
14
+ .option("--json", "Output as JSON")
15
+ .action(async (opts) => {
16
+ if (opts.apiKey) {
17
+ (0, config_1.setAuth)("sarah@dev.io", "Sarah Chen", opts.apiKey);
18
+ if (opts.json) {
19
+ (0, output_1.printJson)({ success: true, email: "sarah@dev.io", name: "Sarah Chen" });
20
+ return;
21
+ }
22
+ (0, output_1.printHeader)("Authentication");
23
+ (0, output_1.printSuccess)("Authenticated as " + (0, output_1.accent)("sarah@dev.io"));
24
+ return;
25
+ }
26
+ if (!opts.json) {
27
+ (0, output_1.printHeader)("Authentication");
28
+ console.log();
29
+ }
30
+ const spinner = (0, ora_1.default)({ text: "Opening browser for authentication...", color: "green" }).start();
31
+ await (0, output_1.delay)(1500);
32
+ spinner.text = "Waiting for browser confirmation...";
33
+ await (0, output_1.delay)(1000);
34
+ spinner.succeed("Browser authentication complete");
35
+ (0, config_1.setAuth)("sarah@dev.io", "Sarah Chen", "mock_token_abc123xyz");
36
+ if (opts.json) {
37
+ (0, output_1.printJson)({ success: true, email: "sarah@dev.io", name: "Sarah Chen" });
38
+ }
39
+ else {
40
+ (0, output_1.printSuccess)("Authenticated as " + (0, output_1.accent)("sarah@dev.io"));
41
+ console.log();
42
+ }
43
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const logoutCommand: Command;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logoutCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../../lib/config");
6
+ const output_1 = require("../../lib/output");
7
+ exports.logoutCommand = new commander_1.Command("logout")
8
+ .description("Log out of Code_")
9
+ .option("--json", "Output as JSON")
10
+ .action((opts) => {
11
+ (0, config_1.clearAuth)();
12
+ if (opts.json) {
13
+ (0, output_1.printJson)({ success: true, message: "Logged out" });
14
+ }
15
+ else {
16
+ (0, output_1.printHeader)("Authentication");
17
+ (0, output_1.printSuccess)("Logged out successfully.");
18
+ console.log();
19
+ }
20
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const whoamiCommand: Command;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.whoamiCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../../lib/config");
6
+ const output_1 = require("../../lib/output");
7
+ exports.whoamiCommand = new commander_1.Command("whoami")
8
+ .description("Show current authenticated user")
9
+ .option("--json", "Output as JSON")
10
+ .action((opts) => {
11
+ const auth = (0, config_1.getAuth)();
12
+ if (!auth) {
13
+ if (opts.json) {
14
+ (0, output_1.printJsonError)("Not authenticated");
15
+ }
16
+ else {
17
+ (0, output_1.printHeader)("Who Am I");
18
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
19
+ console.log();
20
+ }
21
+ return;
22
+ }
23
+ if (opts.json) {
24
+ (0, output_1.printJson)({ authenticated: true, email: auth.email, name: auth.name });
25
+ }
26
+ else {
27
+ (0, output_1.printHeader)("Who Am I");
28
+ (0, output_1.printRow)("Name", auth.name);
29
+ (0, output_1.printRow)("Email", auth.email);
30
+ console.log();
31
+ }
32
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const balanceCommand: Command;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.balanceCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../lib/config");
10
+ const api_client_1 = require("../lib/api-client");
11
+ const output_1 = require("../lib/output");
12
+ const shared_1 = require("../shared");
13
+ exports.balanceCommand = new commander_1.Command("balance")
14
+ .description("Check account balance and credit")
15
+ .option("--json", "Output as JSON")
16
+ .action(async (opts) => {
17
+ if (!(0, config_1.isAuthenticated)()) {
18
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
19
+ return;
20
+ }
21
+ const spinner = (0, ora_1.default)({ text: "Fetching balance...", color: "green" }).start();
22
+ const bal = await (0, api_client_1.getBalance)();
23
+ spinner.stop();
24
+ if (opts.json) {
25
+ (0, output_1.printJson)(bal);
26
+ return;
27
+ }
28
+ (0, output_1.printHeader)("Account Balance");
29
+ (0, output_1.printRow)("Available", (0, shared_1.currency)(bal.available));
30
+ (0, output_1.printRow)("Pending", (0, shared_1.currency)(bal.pending));
31
+ (0, output_1.printRow)("Credit limit", (0, shared_1.currency)(bal.creditLimit));
32
+ (0, output_1.printRow)("Credit used", (0, shared_1.currency)(bal.creditUsed));
33
+ (0, output_1.printRow)("Credit available", (0, shared_1.currency)(bal.creditLimit - bal.creditUsed));
34
+ console.log();
35
+ });
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const cardFreezeCommand: Command;
3
+ export declare const cardUnfreezeCommand: Command;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cardUnfreezeCommand = exports.cardFreezeCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../../lib/config");
10
+ const api_client_1 = require("../../lib/api-client");
11
+ const output_1 = require("../../lib/output");
12
+ const shared_1 = require("../../shared");
13
+ exports.cardFreezeCommand = new commander_1.Command("freeze")
14
+ .description("Freeze a virtual card")
15
+ .argument("<cardId>", "Card ID to freeze")
16
+ .option("--json", "Output as JSON")
17
+ .action(async (cardId, opts) => {
18
+ if (!(0, config_1.isAuthenticated)()) {
19
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
20
+ return;
21
+ }
22
+ const spinner = (0, ora_1.default)({ text: "Freezing card...", color: "green" }).start();
23
+ const card = await (0, api_client_1.freezeCard)(cardId);
24
+ spinner.stop();
25
+ if (!card) {
26
+ if (opts.json)
27
+ (0, output_1.printJsonError)("Card not found");
28
+ else
29
+ (0, output_1.printError)("Card " + cardId + " not found.");
30
+ return;
31
+ }
32
+ if (opts.json) {
33
+ (0, output_1.printJson)({ success: true, card });
34
+ }
35
+ else {
36
+ (0, output_1.printHeader)("Card Frozen");
37
+ (0, output_1.printSuccess)("Card " + (0, output_1.muted)((0, shared_1.maskCard)(card.last4)) + " is now frozen.");
38
+ console.log();
39
+ }
40
+ });
41
+ exports.cardUnfreezeCommand = new commander_1.Command("unfreeze")
42
+ .description("Unfreeze a virtual card")
43
+ .argument("<cardId>", "Card ID to unfreeze")
44
+ .option("--json", "Output as JSON")
45
+ .action(async (cardId, opts) => {
46
+ if (!(0, config_1.isAuthenticated)()) {
47
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
48
+ return;
49
+ }
50
+ const spinner = (0, ora_1.default)({ text: "Unfreezing card...", color: "green" }).start();
51
+ const card = await (0, api_client_1.unfreezeCard)(cardId);
52
+ spinner.stop();
53
+ if (!card) {
54
+ if (opts.json)
55
+ (0, output_1.printJsonError)("Card not found");
56
+ else
57
+ (0, output_1.printError)("Card " + cardId + " not found.");
58
+ return;
59
+ }
60
+ if (opts.json) {
61
+ (0, output_1.printJson)({ success: true, card });
62
+ }
63
+ else {
64
+ (0, output_1.printHeader)("Card Unfrozen");
65
+ (0, output_1.printSuccess)("Card " + (0, output_1.muted)((0, shared_1.maskCard)(card.last4)) + " is now active.");
66
+ console.log();
67
+ }
68
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const cardListCommand: Command;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cardListCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../../lib/config");
10
+ const api_client_1 = require("../../lib/api-client");
11
+ const output_1 = require("../../lib/output");
12
+ const shared_1 = require("../../shared");
13
+ exports.cardListCommand = new commander_1.Command("list")
14
+ .description("List all virtual cards")
15
+ .option("--json", "Output as JSON")
16
+ .action(async (opts) => {
17
+ if (!(0, config_1.isAuthenticated)()) {
18
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
19
+ return;
20
+ }
21
+ const spinner = (0, ora_1.default)({ text: "Fetching cards...", color: "green" }).start();
22
+ const [cards, projects] = await Promise.all([(0, api_client_1.getCards)(), (0, api_client_1.getProjects)()]);
23
+ spinner.stop();
24
+ if (opts.json) {
25
+ (0, output_1.printJson)(cards);
26
+ return;
27
+ }
28
+ const active = cards.filter((c) => c.status === "active").length;
29
+ const frozen = cards.filter((c) => c.status === "frozen").length;
30
+ (0, output_1.printHeader)(`Cards (${active} active, ${frozen} frozen)`);
31
+ const table = (0, output_1.createTable)(["Card", "Project", "Status", "Spend / Limit"]);
32
+ for (const c of cards) {
33
+ const project = projects.find((p) => p.id === c.projectId);
34
+ const statusColor = c.status === "active" ? output_1.accent : c.status === "frozen" ? output_1.pink : output_1.dim;
35
+ table.push([
36
+ (0, output_1.muted)((0, shared_1.maskCard)(c.last4)),
37
+ project ? (0, output_1.accent)(project.name) : (0, output_1.dim)("personal"),
38
+ statusColor(c.status),
39
+ (0, output_1.muted)((0, shared_1.currency)(c.currentMonthSpend) + " / " + (0, shared_1.currency)(c.monthlyLimit)),
40
+ ]);
41
+ }
42
+ console.log(table.toString());
43
+ console.log();
44
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const pnlCommand: Command;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pnlCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../lib/config");
10
+ const api_client_1 = require("../lib/api-client");
11
+ const output_1 = require("../lib/output");
12
+ const shared_1 = require("../shared");
13
+ exports.pnlCommand = new commander_1.Command("pnl")
14
+ .description("View project P&L")
15
+ .argument("<project>", "Project name")
16
+ .option("--json", "Output as JSON")
17
+ .action(async (projectName, opts) => {
18
+ if (!(0, config_1.isAuthenticated)()) {
19
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
20
+ return;
21
+ }
22
+ const spinner = (0, ora_1.default)({ text: "Fetching P&L...", color: "green" }).start();
23
+ const projects = await (0, api_client_1.getProjects)();
24
+ const project = projects.find((p) => p.name === projectName);
25
+ if (!project) {
26
+ spinner.stop();
27
+ (0, output_1.printError)("Project " + (0, output_1.accent)('"' + projectName + '"') + " not found.");
28
+ return;
29
+ }
30
+ const pnl = await (0, api_client_1.getProjectPnl)(project.id);
31
+ spinner.stop();
32
+ if (!pnl) {
33
+ (0, output_1.printError)("No P&L data for " + (0, output_1.accent)(projectName));
34
+ return;
35
+ }
36
+ if (opts.json) {
37
+ (0, output_1.printJson)(pnl);
38
+ return;
39
+ }
40
+ (0, output_1.printHeader)(pnl.projectName + " │ " + pnl.period);
41
+ console.log();
42
+ (0, output_1.printRow)("Spend", (0, output_1.pink)((0, shared_1.currency)(pnl.spend)));
43
+ (0, output_1.printRow)("Revenue", (0, output_1.cyan)((0, shared_1.currency)(pnl.revenue)));
44
+ const netColor = pnl.net >= 0 ? output_1.accent : output_1.orange;
45
+ (0, output_1.printRow)("Net", netColor((pnl.net >= 0 ? "+" : "") + (0, shared_1.currency)(pnl.net)));
46
+ (0, output_1.printRow)("Margin", netColor((0, shared_1.percentage)(pnl.margin)));
47
+ console.log();
48
+ if (pnl.topProviders.length > 0) {
49
+ console.log((0, output_1.dim)(" Top Providers"));
50
+ const table = (0, output_1.createTable)(["Provider", "Amount"]);
51
+ for (const p of pnl.topProviders) {
52
+ table.push([(0, output_1.muted)(p.name), (0, shared_1.currency)(p.amount)]);
53
+ }
54
+ console.log(table.toString());
55
+ }
56
+ console.log();
57
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const projectCreateCommand: Command;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.projectCreateCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../../lib/config");
10
+ const api_client_1 = require("../../lib/api-client");
11
+ const output_1 = require("../../lib/output");
12
+ const shared_1 = require("../../shared");
13
+ exports.projectCreateCommand = new commander_1.Command("create")
14
+ .description("Create a new project with a virtual card")
15
+ .argument("<name>", "Project name")
16
+ .option("-d, --description <desc>", "Project description", "")
17
+ .option("-b, --budget <amount>", "Monthly budget in dollars", "2000")
18
+ .option("--json", "Output as JSON")
19
+ .action(async (name, opts) => {
20
+ if (!(0, config_1.isAuthenticated)()) {
21
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
22
+ return;
23
+ }
24
+ const spinner = (0, ora_1.default)({ text: "Creating project...", color: "green" }).start();
25
+ const project = await (0, api_client_1.createProject)(name, opts.description, parseInt(opts.budget, 10));
26
+ spinner.succeed("Project created");
27
+ if (opts.json) {
28
+ (0, output_1.printJson)(project);
29
+ return;
30
+ }
31
+ (0, output_1.printHeader)("Project Created");
32
+ (0, output_1.printSuccess)("Project " + (0, output_1.accent)('"' + project.name + '"') + " created");
33
+ (0, output_1.printSuccess)("Card " + (0, output_1.muted)((0, shared_1.maskCard)(project.cardId.slice(-4))) + " assigned");
34
+ (0, output_1.printSuccess)("Budget limit: " + (0, output_1.accent)("$" + project.monthlyBudget.toLocaleString() + "/mo"));
35
+ console.log();
36
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const projectListCommand: Command;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.projectListCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../../lib/config");
10
+ const api_client_1 = require("../../lib/api-client");
11
+ const output_1 = require("../../lib/output");
12
+ const shared_1 = require("../../shared");
13
+ exports.projectListCommand = new commander_1.Command("list")
14
+ .description("List all projects")
15
+ .option("--json", "Output as JSON")
16
+ .action(async (opts) => {
17
+ if (!(0, config_1.isAuthenticated)()) {
18
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
19
+ return;
20
+ }
21
+ const spinner = (0, ora_1.default)({ text: "Fetching projects...", color: "green" }).start();
22
+ const projects = await (0, api_client_1.getProjects)();
23
+ spinner.stop();
24
+ if (opts.json) {
25
+ (0, output_1.printJson)(projects);
26
+ return;
27
+ }
28
+ (0, output_1.printHeader)(`Projects (${projects.length})`);
29
+ const table = (0, output_1.createTable)(["", "Name", "Status", "Budget", "Card"]);
30
+ for (const p of projects) {
31
+ const statusColor = p.status === "active" ? output_1.accent : p.status === "paused" ? output_1.muted : output_1.dim;
32
+ table.push([
33
+ "●",
34
+ (0, output_1.accent)(p.name),
35
+ statusColor(p.status),
36
+ (0, output_1.muted)((0, shared_1.currency)(p.monthlyBudget) + "/mo"),
37
+ (0, output_1.dim)("•••• " + p.cardId.slice(-3)),
38
+ ]);
39
+ }
40
+ console.log(table.toString());
41
+ console.log();
42
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const rewardsCommand: Command;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.rewardsCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_1 = require("../lib/config");
10
+ const api_client_1 = require("../lib/api-client");
11
+ const output_1 = require("../lib/output");
12
+ const shared_1 = require("../shared");
13
+ const tierColors = [output_1.accent, output_1.blue, output_1.purple, output_1.orange];
14
+ exports.rewardsCommand = new commander_1.Command("rewards")
15
+ .description("View rewards and Code Credits")
16
+ .option("--json", "Output as JSON")
17
+ .action(async (opts) => {
18
+ if (!(0, config_1.isAuthenticated)()) {
19
+ (0, output_1.printError)("Not authenticated. Run " + (0, output_1.accent)("code auth login") + " first.");
20
+ return;
21
+ }
22
+ const spinner = (0, ora_1.default)({ text: "Fetching rewards...", color: "green" }).start();
23
+ const { balance, tiers, history } = await (0, api_client_1.getRewards)();
24
+ spinner.stop();
25
+ if (opts.json) {
26
+ (0, output_1.printJson)({ balance, tiers, history });
27
+ return;
28
+ }
29
+ (0, output_1.printHeader)("Code Credits");
30
+ (0, output_1.printRow)("Available", (0, output_1.accent)((0, shared_1.currency)(balance.totalCredits)));
31
+ (0, output_1.printRow)("Pending", (0, output_1.muted)((0, shared_1.currency)(balance.pendingCredits)));
32
+ (0, output_1.printRow)("Lifetime earned", (0, shared_1.currency)(balance.lifetimeEarned));
33
+ (0, output_1.printRow)("Lifetime redeemed", (0, shared_1.currency)(balance.lifetimeRedeemed));
34
+ console.log();
35
+ // Tiers
36
+ console.log((0, output_1.dim)(" Reward Tiers"));
37
+ const table = (0, output_1.createTable)(["Category", "Rate", "Earned", "On Spend"]);
38
+ tiers.forEach((t, i) => {
39
+ const colorFn = tierColors[i] || output_1.muted;
40
+ table.push([
41
+ colorFn(t.category),
42
+ colorFn(t.rate + "%"),
43
+ (0, shared_1.currency)(t.earned),
44
+ (0, output_1.dim)((0, shared_1.currency)(t.spend)),
45
+ ]);
46
+ });
47
+ console.log(table.toString());
48
+ // Recent history
49
+ console.log((0, output_1.dim)(" Recent Activity"));
50
+ const histTable = (0, output_1.createTable)(["Type", "Amount", "Description"]);
51
+ for (const h of history.slice(0, 5)) {
52
+ const colorFn = h.type === "earned" ? output_1.accent : output_1.muted;
53
+ histTable.push([
54
+ colorFn(h.type),
55
+ colorFn(h.amount > 0 ? "+" + (0, shared_1.currency)(h.amount) : (0, shared_1.currency)(h.amount)),
56
+ (0, output_1.dim)(h.description),
57
+ ]);
58
+ }
59
+ console.log(histTable.toString());
60
+ console.log();
61
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const spendCommand: Command;