@todoforai/cli 0.1.55 → 0.1.57
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/bin/todoforai-cli.js +5 -3
- package/dist/todoforai-cli.js +1565 -38
- package/package.json +1 -1
package/dist/todoforai-cli.js
CHANGED
|
@@ -42745,7 +42745,7 @@ function randomTip() {
|
|
|
42745
42745
|
return TIPS[Math.floor(Math.random() * TIPS.length)];
|
|
42746
42746
|
}
|
|
42747
42747
|
|
|
42748
|
-
//
|
|
42748
|
+
// ../packages/shared-api/src/api.ts
|
|
42749
42749
|
function restBasePath(apiKey) {
|
|
42750
42750
|
return apiKey.startsWith("dst_") ? "/dst/v1" : "/api/v1";
|
|
42751
42751
|
}
|
|
@@ -42939,6 +42939,12 @@ class ApiClient {
|
|
|
42939
42939
|
sendFeedMessage(msg) {
|
|
42940
42940
|
return this.request("POST", "/api/v1/feed/message", msg);
|
|
42941
42941
|
}
|
|
42942
|
+
getProjectMembers(projectId) {
|
|
42943
|
+
return this.request("GET", `/api/v1/projects/${projectId}/members`);
|
|
42944
|
+
}
|
|
42945
|
+
sendMemberMessage(msg) {
|
|
42946
|
+
return this.request("POST", "/api/v1/feed/message/member", msg);
|
|
42947
|
+
}
|
|
42942
42948
|
listProjectSurfaces(projectId) {
|
|
42943
42949
|
return this.request("GET", `/api/v1/projects/${projectId}/surfaces`);
|
|
42944
42950
|
}
|
|
@@ -43169,11 +43175,11 @@ class ApiClient {
|
|
|
43169
43175
|
return res.json();
|
|
43170
43176
|
}
|
|
43171
43177
|
}
|
|
43172
|
-
//
|
|
43178
|
+
// ../packages/shared-api/src/frontend-ws.ts
|
|
43173
43179
|
import { randomUUID } from "crypto";
|
|
43174
43180
|
import WebSocket from "ws";
|
|
43175
43181
|
|
|
43176
|
-
//
|
|
43182
|
+
// ../packages/shared-credentials/src/index.ts
|
|
43177
43183
|
import { readFileSync, writeFileSync, mkdirSync, chmodSync } from "node:fs";
|
|
43178
43184
|
import { join, dirname } from "node:path";
|
|
43179
43185
|
import { homedir, platform } from "node:os";
|
|
@@ -43213,7 +43219,7 @@ function writeCredential(apiUrl, apiKey) {
|
|
|
43213
43219
|
writeSecure(c);
|
|
43214
43220
|
}
|
|
43215
43221
|
|
|
43216
|
-
//
|
|
43222
|
+
// ../packages/shared-api/src/frontend-ws.ts
|
|
43217
43223
|
var log = (level, ...args) => console.log(`[frontend-ws:${level}]`, ...args);
|
|
43218
43224
|
|
|
43219
43225
|
class FrontendWebSocket {
|
|
@@ -43483,7 +43489,7 @@ class FrontendWebSocket {
|
|
|
43483
43489
|
});
|
|
43484
43490
|
}
|
|
43485
43491
|
}
|
|
43486
|
-
//
|
|
43492
|
+
// ../packages/shared-fbe/src/enums.ts
|
|
43487
43493
|
var TodoStatus;
|
|
43488
43494
|
((TodoStatus2) => {
|
|
43489
43495
|
TodoStatus2["PROPOSED"] = "PROPOSED";
|
|
@@ -43507,7 +43513,7 @@ var TodoStatus;
|
|
|
43507
43513
|
TodoStatus2["ARCHIVED"] = "ARCHIVED";
|
|
43508
43514
|
TodoStatus2["DELETED"] = "DELETED";
|
|
43509
43515
|
})(TodoStatus ||= {});
|
|
43510
|
-
//
|
|
43516
|
+
// ../packages/shared-fbe/src/models.ts
|
|
43511
43517
|
var DEFAULT_MODEL = "anthropic:anthropic/claude-opus-5.5";
|
|
43512
43518
|
var MODEL_ALIASES = {
|
|
43513
43519
|
claude: DEFAULT_MODEL
|
|
@@ -43578,7 +43584,7 @@ function qualifiedModelIds(listing, filter) {
|
|
|
43578
43584
|
}
|
|
43579
43585
|
return q ? ids.filter((id) => id.toLowerCase().includes(q)) : ids;
|
|
43580
43586
|
}
|
|
43581
|
-
//
|
|
43587
|
+
// ../packages/shared-fbe/src/billing.ts
|
|
43582
43588
|
var USAGE_WINDOWS = {
|
|
43583
43589
|
SESSION_MS: 5 * 60 * 60 * 1000,
|
|
43584
43590
|
WEEK_MS: 7 * 24 * 60 * 60 * 1000,
|
|
@@ -43586,7 +43592,7 @@ var USAGE_WINDOWS = {
|
|
|
43586
43592
|
SESSION_FACTOR: 1 / 5
|
|
43587
43593
|
};
|
|
43588
43594
|
var NEVER_SCHEDULED_TIMESTAMP = 8640000000000000;
|
|
43589
|
-
//
|
|
43595
|
+
// ../packages/shared-fbe/src/mimetypes.json
|
|
43590
43596
|
var mimetypes_default = {
|
|
43591
43597
|
conversionProfiles: {
|
|
43592
43598
|
to_jpeg_90: { toMime: "image/jpeg", toExt: "jpg", quality: 0.9 }
|
|
@@ -43679,7 +43685,7 @@ var mimetypes_default = {
|
|
|
43679
43685
|
}
|
|
43680
43686
|
};
|
|
43681
43687
|
|
|
43682
|
-
//
|
|
43688
|
+
// ../packages/shared-fbe/src/attachmentUtils.ts
|
|
43683
43689
|
var MCP_TEXT_MIME = Object.entries(mimetypes_default.aliases).find(([, type]) => type === "mcp_text")[0];
|
|
43684
43690
|
var MCP_AUDIO_MIME = Object.entries(mimetypes_default.aliases).find(([, type]) => type === "mcp_audio")[0];
|
|
43685
43691
|
var AttachmentType = Object.fromEntries(Object.keys(mimetypes_default.types).map((k) => [k.toUpperCase(), k]));
|
|
@@ -43719,7 +43725,7 @@ for (const [ext, entry] of Object.entries(mimetypes_default.extensions)) {
|
|
|
43719
43725
|
if (!MIME_TO_EXT[mime])
|
|
43720
43726
|
MIME_TO_EXT[mime] = ext;
|
|
43721
43727
|
}
|
|
43722
|
-
//
|
|
43728
|
+
// ../packages/shared-fbe/src/edgeTypes.ts
|
|
43723
43729
|
var NON_SHELL_TYPES = new Set([
|
|
43724
43730
|
"WEB_EXTENSION" /* WEB_EXTENSION */,
|
|
43725
43731
|
"EXTENSION" /* EXTENSION */,
|
|
@@ -43727,7 +43733,7 @@ var NON_SHELL_TYPES = new Set([
|
|
|
43727
43733
|
"ANDROID" /* ANDROID */,
|
|
43728
43734
|
"IOS" /* IOS */
|
|
43729
43735
|
]);
|
|
43730
|
-
//
|
|
43736
|
+
// ../packages/shared-fbe/src/blocks/index.ts
|
|
43731
43737
|
var USER_INPUT_BLOCK_TYPES = new Set([
|
|
43732
43738
|
"question" /* Question */,
|
|
43733
43739
|
"login_prompt" /* Login */,
|
|
@@ -43781,7 +43787,7 @@ var FILE_TOOL_TYPES = new Set([
|
|
|
43781
43787
|
"edit" /* Edit */,
|
|
43782
43788
|
"modify_file" /* ModifyFile */
|
|
43783
43789
|
]);
|
|
43784
|
-
//
|
|
43790
|
+
// ../packages/shared-fbe/src/channels.ts
|
|
43785
43791
|
var privateSuffix = (privateOwnerId) => privateOwnerId ? `:private:${privateOwnerId}` : "";
|
|
43786
43792
|
var SERVER_TO_FRONTENDS = {
|
|
43787
43793
|
task: {
|
|
@@ -43871,7 +43877,7 @@ var SERVER_TO_FRONTENDS = {
|
|
|
43871
43877
|
function_call_request: (userId) => `${"FUNCTION_CALL_REQUEST_AGENT" /* FUNCTION_CALL_REQUEST_AGENT */}:frontend:${userId}`
|
|
43872
43878
|
}
|
|
43873
43879
|
};
|
|
43874
|
-
//
|
|
43880
|
+
// ../packages/shared-fbe/src/REST_types.ts
|
|
43875
43881
|
var MANUAL_CHANNEL = "Manual";
|
|
43876
43882
|
function manualAnswersOf(sources) {
|
|
43877
43883
|
const manual = sources?.find((s) => s.channel === MANUAL_CHANNEL);
|
|
@@ -43882,8 +43888,8 @@ function manualAnswersOf(sources) {
|
|
|
43882
43888
|
return out;
|
|
43883
43889
|
}
|
|
43884
43890
|
var manualSamples = (answers) => Object.entries(answers).filter(([, a]) => a.trim()).map(([prompt, text]) => ({ prompt, text: text.trim() }));
|
|
43885
|
-
var senderLabel = (s) => s.kind === "team" ? `${s.name} · TODO for AI team` : `${s.name} · your agent`;
|
|
43886
|
-
//
|
|
43891
|
+
var senderLabel = (s) => s.kind === "team" ? `${s.name} · TODO for AI team` : s.kind === "member" ? `${s.name} · teammate` : `${s.name} · your agent`;
|
|
43892
|
+
// ../packages/shared-fbe/src/templateBody.ts
|
|
43887
43893
|
var USER_HEADINGS = new Set([
|
|
43888
43894
|
"your task",
|
|
43889
43895
|
"your tasks",
|
|
@@ -43892,7 +43898,7 @@ var USER_HEADINGS = new Set([
|
|
|
43892
43898
|
"steps",
|
|
43893
43899
|
"data needed"
|
|
43894
43900
|
]);
|
|
43895
|
-
//
|
|
43901
|
+
// ../packages/shared-fbe/src/bashPatterns.ts
|
|
43896
43902
|
function splitShellCommands(input) {
|
|
43897
43903
|
const parts = [];
|
|
43898
43904
|
let current = "";
|
|
@@ -44134,7 +44140,7 @@ function getBlockServerId(block) {
|
|
|
44134
44140
|
return prefix ? prefix.slice(0, -1) : "*";
|
|
44135
44141
|
}
|
|
44136
44142
|
|
|
44137
|
-
//
|
|
44143
|
+
// ../packages/shared-fbe/src/permissionUtils.ts
|
|
44138
44144
|
function parsePattern(pattern) {
|
|
44139
44145
|
const colonIndex = pattern.indexOf(":");
|
|
44140
44146
|
if (colonIndex === -1)
|
|
@@ -44235,7 +44241,7 @@ function getBlockNewPatterns(block, permissions) {
|
|
|
44235
44241
|
}
|
|
44236
44242
|
return pairs.filter(({ raw, pattern }) => !isPatternAllowed(permissions, pattern) && !allow.some((rule) => bashRuleMatchesCmd(rule, serverId, raw))).map(({ pattern }) => pattern);
|
|
44237
44243
|
}
|
|
44238
|
-
//
|
|
44244
|
+
// ../packages/shared-fbe/src/systemAgents.ts
|
|
44239
44245
|
var BUSINESS_ANALYZER_AGENT = {
|
|
44240
44246
|
id: "00000000-0000-0000-0000-202601013151",
|
|
44241
44247
|
name: "Business Analyzer",
|
|
@@ -44381,7 +44387,7 @@ var SYSTEM_AGENTS = {
|
|
|
44381
44387
|
[ONBOARDING_AGENT.id]: ONBOARDING_AGENT
|
|
44382
44388
|
};
|
|
44383
44389
|
var RECOMMEND_STEP = "Recommend growth TODOs for this project: materialize the ones you genuinely believe fit " + "as proposal cards on the board (api_recommend_template, one call per recommendation). " + "No quota — fewer good cards beat padding.";
|
|
44384
|
-
//
|
|
44390
|
+
// ../packages/shared-fbe/src/outputLimits.ts
|
|
44385
44391
|
var MAX_LINE_LEN = 300;
|
|
44386
44392
|
var STREAM_FIRST = 1e4;
|
|
44387
44393
|
var STREAM_LAST = 1e4;
|
|
@@ -44392,7 +44398,1501 @@ var OUTPUT_POLICIES = {
|
|
|
44392
44398
|
full: { firstLimit: Infinity, lastLimit: 0, hardCap: RUN_OUTPUT_CAP, lineLimit: MAX_LINE_LEN },
|
|
44393
44399
|
raw: { firstLimit: Infinity, lastLimit: 0, hardCap: Infinity, lineLimit: Infinity }
|
|
44394
44400
|
};
|
|
44395
|
-
//
|
|
44401
|
+
// ../packages/shared-fbe/src/tool_catalog.json
|
|
44402
|
+
var tool_catalog_default = {
|
|
44403
|
+
zele: {
|
|
44404
|
+
category: "email",
|
|
44405
|
+
pkg: "zele",
|
|
44406
|
+
installer: "npm",
|
|
44407
|
+
label: "Gmail",
|
|
44408
|
+
summary: "Read and send Gmail from your own account.",
|
|
44409
|
+
statusCmd: "zele whoami 2>/dev/null | grep 'email:' | grep -m1 .",
|
|
44410
|
+
loginNeedsPty: true,
|
|
44411
|
+
loginCmd: "zele login --method google",
|
|
44412
|
+
oauthUrlPattern: "(https://accounts\\.google\\.com\\S+)",
|
|
44413
|
+
oauthCallbackPort: 8089,
|
|
44414
|
+
credentialPaths: ["~/.zele/sqlite.db"],
|
|
44415
|
+
versionCmd: "zele --version 2>/dev/null | sed -n 1p",
|
|
44416
|
+
preinstallCloud: true,
|
|
44417
|
+
preinstallJarvis: true,
|
|
44418
|
+
description: "Gmail (multi-account, OAuth login): inbox, search, send, reply, contacts. Google Calendar via `zele cal`: list/create/update/delete events (Meet links, recurrence), respond to invites, free/busy."
|
|
44419
|
+
},
|
|
44420
|
+
"zele-calendar": {
|
|
44421
|
+
preinstallCloud: true,
|
|
44422
|
+
category: "utility",
|
|
44423
|
+
pkg: "zele",
|
|
44424
|
+
installer: "npm",
|
|
44425
|
+
binName: "zele",
|
|
44426
|
+
label: "Google Calendar",
|
|
44427
|
+
summary: "See your Google Calendar and book, move or cancel events.",
|
|
44428
|
+
statusCmd: "zele whoami 2>/dev/null | grep 'email:' | grep -m1 .",
|
|
44429
|
+
loginNeedsPty: true,
|
|
44430
|
+
loginCmd: "zele login --method google",
|
|
44431
|
+
oauthUrlPattern: "(https://accounts\\.google\\.com\\S+)",
|
|
44432
|
+
oauthCallbackPort: 8089,
|
|
44433
|
+
credentialPaths: ["~/.zele/sqlite.db"],
|
|
44434
|
+
versionCmd: "zele --version 2>/dev/null | sed -n 1p",
|
|
44435
|
+
preinstallJarvis: true,
|
|
44436
|
+
description: "Google Calendar via `zele cal`: list calendars and events, create/update/delete events with Google Meet links, recurrence and reminders, respond to invites, free/busy."
|
|
44437
|
+
},
|
|
44438
|
+
xurl: {
|
|
44439
|
+
category: "social",
|
|
44440
|
+
pkg: "@xdevplatform/xurl",
|
|
44441
|
+
installer: "npm",
|
|
44442
|
+
label: "X",
|
|
44443
|
+
summary: "Post to X and read timelines, replies and DMs.",
|
|
44444
|
+
statusCmd: `xurl whoami 2>&1 | sed -n 's/.*"username"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
44445
|
+
loginCmd: "xurl auth oauth2",
|
|
44446
|
+
loginTerminalHint: "X needs your own developer app first: create one at developer.x.com (callback `http://localhost:8080/callback`), run `xurl auth apps add tfa --client-id <id> --client-secret <secret>`, then `xurl auth oauth2`.",
|
|
44447
|
+
oauthUrlPattern: "(https://(?:twitter|x)\\.com/i/oauth2\\S+)",
|
|
44448
|
+
oauthCallbackPort: 8080,
|
|
44449
|
+
credentialPaths: ["~/.xurl"],
|
|
44450
|
+
description: "Raw X API access via `xurl <method> <path>`.",
|
|
44451
|
+
versionCmd: "xurl version 2>/dev/null | sed -n 1p",
|
|
44452
|
+
preinstallJarvis: true,
|
|
44453
|
+
preinstallCloud: true
|
|
44454
|
+
},
|
|
44455
|
+
"linkedin-api": {
|
|
44456
|
+
preinstallCloud: true,
|
|
44457
|
+
category: "social",
|
|
44458
|
+
pkg: "@todoforai/linkedin-api",
|
|
44459
|
+
installer: "npm",
|
|
44460
|
+
label: "LinkedIn",
|
|
44461
|
+
summary: "Read LinkedIn profiles and send messages and connection requests.",
|
|
44462
|
+
statusCmd: `linkedin-api whoami 2>/dev/null | sed -n 's/.*"publicId"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
44463
|
+
loginCmd: "linkedin-api auth <li_at> <jsessionid>",
|
|
44464
|
+
credentialPaths: ["~/.config/linkedin-api/credentials.json"],
|
|
44465
|
+
description: "LinkedIn Voyager API CLI for profiles, conversations, DMs, and connections.",
|
|
44466
|
+
versionCmd: "linkedin-api --version 2>/dev/null | sed -n 1p"
|
|
44467
|
+
},
|
|
44468
|
+
"figma-api": {
|
|
44469
|
+
category: "design",
|
|
44470
|
+
pkg: "@todoforai/figma-api",
|
|
44471
|
+
installer: "npm",
|
|
44472
|
+
label: "Figma",
|
|
44473
|
+
summary: "Read Figma files, export images and leave comments.",
|
|
44474
|
+
statusCmd: `figma-api me 2>/dev/null | sed -n 's/.*"email"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
44475
|
+
loginCmd: "figma-api auth <token>",
|
|
44476
|
+
credentialPaths: ["~/.config/figma-api/credentials.json"],
|
|
44477
|
+
description: "Figma REST API CLI. File commands take a file key or Figma URL. Canvas writes (frames/text/shapes) use `figma-api run` via the plugin bridge. Run `figma-api <cmd> --help` for params.",
|
|
44478
|
+
versionCmd: "figma-api --version 2>/dev/null | sed -n 1p"
|
|
44479
|
+
},
|
|
44480
|
+
"slack-cli": {
|
|
44481
|
+
preinstallCloud: true,
|
|
44482
|
+
cloudInstallCmd: "curl -fsSL https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_linux_amd64.tar.gz | tar -xz -C /tmp bin/slack && install -m0755 /tmp/bin/slack /usr/local/bin/slack-cli && rm -rf /tmp/bin",
|
|
44483
|
+
cloudVerifyCmd: "slack-cli --version",
|
|
44484
|
+
category: "social",
|
|
44485
|
+
pkg: "slack-cli",
|
|
44486
|
+
installer: "binary",
|
|
44487
|
+
label: "Slack",
|
|
44488
|
+
summary: "Work with Slack workspaces and apps.",
|
|
44489
|
+
statusCmd: "slack-cli auth list 2>&1 | grep 'Team' >/dev/null && echo authenticated",
|
|
44490
|
+
loginCmd: "slack-cli login",
|
|
44491
|
+
loginTerminalHint: "Run `slack-cli login` in a terminal on this host, paste the `/slackauthticket …` command it prints into any Slack channel, then type the challenge code Slack shows you back into the terminal.",
|
|
44492
|
+
credentialPaths: ["~/.slack/credentials.json"],
|
|
44493
|
+
description: "Invoked as `slack-cli` to avoid colliding with the Slack desktop app’s `slack` binary.",
|
|
44494
|
+
versionCmd: "slack-cli version 2>/dev/null | sed -n 1p",
|
|
44495
|
+
binName: "slack-cli",
|
|
44496
|
+
binary: {
|
|
44497
|
+
"linux-x86_64": {
|
|
44498
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_linux_amd64.tar.gz",
|
|
44499
|
+
archive: "tar.gz",
|
|
44500
|
+
extract: "bin/slack"
|
|
44501
|
+
},
|
|
44502
|
+
"linux-aarch64": {
|
|
44503
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_linux_arm64.tar.gz",
|
|
44504
|
+
archive: "tar.gz",
|
|
44505
|
+
extract: "bin/slack"
|
|
44506
|
+
},
|
|
44507
|
+
"darwin-x86_64": {
|
|
44508
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_macOS_amd64.tar.gz",
|
|
44509
|
+
archive: "tar.gz",
|
|
44510
|
+
extract: "bin/slack"
|
|
44511
|
+
},
|
|
44512
|
+
"darwin-aarch64": {
|
|
44513
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_macOS_arm64.tar.gz",
|
|
44514
|
+
archive: "tar.gz",
|
|
44515
|
+
extract: "bin/slack"
|
|
44516
|
+
},
|
|
44517
|
+
"windows-x86_64": {
|
|
44518
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_windows_64-bit.zip",
|
|
44519
|
+
archive: "zip",
|
|
44520
|
+
extract: "bin/slack.exe"
|
|
44521
|
+
}
|
|
44522
|
+
}
|
|
44523
|
+
},
|
|
44524
|
+
"telegram-send": {
|
|
44525
|
+
preinstallCloud: true,
|
|
44526
|
+
packages: ["telegram-send==0.39.2"],
|
|
44527
|
+
category: "social",
|
|
44528
|
+
pkg: "telegram-send",
|
|
44529
|
+
installer: "pip",
|
|
44530
|
+
label: "Telegram",
|
|
44531
|
+
summary: "Send Telegram messages, photos and files.",
|
|
44532
|
+
loginCmd: `t=<bot_token>; c=$(curl -sf "https://api.telegram.org/bot$t/getUpdates" | python3 -c "import json,sys; u=[x for x in json.load(sys.stdin)['result'] if 'message' in x]; print(u[-1]['message']['chat']['id'])" 2>/dev/null) || { echo "No message from you yet: open your bot in Telegram, send it any message, then retry"; exit 1; }; mkdir -p "$HOME/.config" && printf '[telegram]\\ntoken = %s\\nchat_id = %s\\n' "$t" "$c" > "$HOME/.config/telegram-send.conf" && telegram-send "Connected to TODOforAI"`,
|
|
44533
|
+
credentialPaths: ["~/.config/telegram-send.conf"],
|
|
44534
|
+
versionCmd: "telegram-send --version 2>/dev/null | sed -n 1p",
|
|
44535
|
+
statusCmd: "test -f ~/.config/telegram-send.conf && echo authenticated",
|
|
44536
|
+
description: "Send messages, send files & images, send video & audio, Markdown/HTML formatting, channel & group support"
|
|
44537
|
+
},
|
|
44538
|
+
"meta-ads": {
|
|
44539
|
+
preinstallCloud: true,
|
|
44540
|
+
packages: ["meta-ads==1.1.0"],
|
|
44541
|
+
category: "marketing",
|
|
44542
|
+
pkg: "meta-ads",
|
|
44543
|
+
installer: "pip",
|
|
44544
|
+
label: "Meta Ads",
|
|
44545
|
+
summary: "Run Facebook and Instagram ad campaigns and see how they perform.",
|
|
44546
|
+
binName: "meta",
|
|
44547
|
+
statusCmd: `out=$(meta auth status 2>&1); rc=$?; printf '%s\\n' "$out" | grep -m1 .; exit $rc`,
|
|
44548
|
+
versionCmd: "meta --version 2>/dev/null | sed -n 1p",
|
|
44549
|
+
description: "Meta/Facebook & Instagram ad campaigns: campaigns/adsets/ads CRUD, insights & reporting, catalog/product-feed/product-set/product-item, ad creatives, datasets (pixels), pages — Marketing API via the official `meta` CLI. No raw/passthrough mode; for arbitrary Graph API calls with a Page token use `facebook-pages-api request <method> <path>`."
|
|
44550
|
+
},
|
|
44551
|
+
"elevenlabs-api": {
|
|
44552
|
+
preinstallCloud: true,
|
|
44553
|
+
category: "media",
|
|
44554
|
+
pkg: "@todoforai/elevenlabs-api",
|
|
44555
|
+
installer: "npm",
|
|
44556
|
+
label: "ElevenLabs",
|
|
44557
|
+
summary: "Turn text into natural speech, in many voices and languages.",
|
|
44558
|
+
versionCmd: "elevenlabs-api --version 2>/dev/null | sed -n 1p",
|
|
44559
|
+
statusCmd: 'test -f ~/.config/todoforai/elevenlabs.json -o -n "$ELEVENLABS_API_KEY" && echo authenticated',
|
|
44560
|
+
loginCmd: "elevenlabs-api auth <api_key>",
|
|
44561
|
+
credentialPaths: ["~/.config/todoforai/elevenlabs.json"],
|
|
44562
|
+
description: "Text-to-speech, voice cloning, multiple languages."
|
|
44563
|
+
},
|
|
44564
|
+
ffmpeg: {
|
|
44565
|
+
commodity: true,
|
|
44566
|
+
category: "media",
|
|
44567
|
+
pkg: "ffmpeg",
|
|
44568
|
+
installer: "system",
|
|
44569
|
+
label: "FFmpeg",
|
|
44570
|
+
summary: "Convert, trim and resize video and audio files.",
|
|
44571
|
+
cloudAptPackages: ["ffmpeg"],
|
|
44572
|
+
preinstallCloud: true,
|
|
44573
|
+
description: "Media swiss-army knife: `ffmpeg -i in.mp4 out.webm`; `ffprobe` for metadata.",
|
|
44574
|
+
versionCmd: "ffmpeg -version 2>/dev/null | sed -n 1p"
|
|
44575
|
+
},
|
|
44576
|
+
"tfa-imagegen": {
|
|
44577
|
+
preinstallCloud: true,
|
|
44578
|
+
category: "media",
|
|
44579
|
+
pkg: "@todoforai/image-api",
|
|
44580
|
+
installer: "npm",
|
|
44581
|
+
label: "Image Gen",
|
|
44582
|
+
summary: "Generate and edit images from a description.",
|
|
44583
|
+
platformAuth: true,
|
|
44584
|
+
versionCmd: "tfa-imagegen --version 2>/dev/null | sed -n 1p",
|
|
44585
|
+
credentialPaths: ["~/.config/todoforai/credentials.json"],
|
|
44586
|
+
description: "AI image generation & editing via TODOFORAI backend (gpt-image, nano-banana, nano-banana-pro, mai-image-2.6)"
|
|
44587
|
+
},
|
|
44588
|
+
"suno-api": {
|
|
44589
|
+
preinstallCloud: true,
|
|
44590
|
+
category: "media",
|
|
44591
|
+
pkg: "@todoforai/suno-api",
|
|
44592
|
+
installer: "npm",
|
|
44593
|
+
label: "Suno",
|
|
44594
|
+
summary: "Generate music and songs from a prompt.",
|
|
44595
|
+
versionCmd: "suno-api --version 2>/dev/null | sed -n 1p",
|
|
44596
|
+
statusCmd: 'test -f ~/.config/todoforai/suno.json -o -n "$SUNO_API_KEY" && echo authenticated',
|
|
44597
|
+
loginCmd: "suno-api auth <api_key>",
|
|
44598
|
+
credentialPaths: [
|
|
44599
|
+
"~/.config/todoforai/suno.json"
|
|
44600
|
+
],
|
|
44601
|
+
description: "AI music generation, custom lyrics, multiple genres."
|
|
44602
|
+
},
|
|
44603
|
+
ntn: {
|
|
44604
|
+
preinstallCloud: true,
|
|
44605
|
+
category: "utility",
|
|
44606
|
+
pkg: "ntn",
|
|
44607
|
+
installer: "npm",
|
|
44608
|
+
label: "Notion",
|
|
44609
|
+
summary: "Read and update Notion pages and databases.",
|
|
44610
|
+
statusCmd: "ntn doctor 2>&1 | grep -E 'Token valid\\s+✔' >/dev/null && echo authenticated",
|
|
44611
|
+
loginCmd: "ntn login",
|
|
44612
|
+
loginNeedsPty: true,
|
|
44613
|
+
oauthUrlPattern: "(https://www\\.notion\\.so/workers/cli-login\\S+)",
|
|
44614
|
+
sessionIdPattern: "verificationCode=([A-Z0-9-]{5,12})",
|
|
44615
|
+
credentialPaths: ["~/.config/notion"],
|
|
44616
|
+
versionCmd: "ntn --version 2>/dev/null | sed -n 1p",
|
|
44617
|
+
description: "Official Notion CLI: raw API calls (`ntn api <path>`), page/data-source management, file uploads, Workers deploy."
|
|
44618
|
+
},
|
|
44619
|
+
"perplexity-api": {
|
|
44620
|
+
preinstallCloud: true,
|
|
44621
|
+
category: "utility",
|
|
44622
|
+
pkg: "@todoforai/perplexity-api",
|
|
44623
|
+
installer: "npm",
|
|
44624
|
+
label: "Perplexity",
|
|
44625
|
+
summary: "Ask questions and get answers researched from the web.",
|
|
44626
|
+
versionCmd: "perplexity-api --version 2>/dev/null | sed -n 1p",
|
|
44627
|
+
statusCmd: 'test -f ~/.config/todoforai/perplexity.json && echo authenticated || test -n "$PERPLEXITY_API_KEY" && echo authenticated',
|
|
44628
|
+
loginCmd: "perplexity-api auth <api_key>",
|
|
44629
|
+
credentialPaths: ["~/.config/todoforai/perplexity.json"],
|
|
44630
|
+
description: "AI-powered web search, chat completions, async chat, embeddings and agent runs"
|
|
44631
|
+
},
|
|
44632
|
+
gh: {
|
|
44633
|
+
category: "development",
|
|
44634
|
+
pkg: "gh",
|
|
44635
|
+
installer: "binary",
|
|
44636
|
+
preinstallCloud: true,
|
|
44637
|
+
label: "GitHub",
|
|
44638
|
+
summary: "Work with your GitHub repos, pull requests and issues.",
|
|
44639
|
+
statusCmd: "gh auth status 2>&1 | grep 'Logged in to' | grep -m1 .",
|
|
44640
|
+
loginCmd: "gh auth login --hostname github.com --git-protocol https",
|
|
44641
|
+
oauthUrlPattern: "(https://github\\.com/login/device\\S*)",
|
|
44642
|
+
deviceCodePattern: "one-time code:\\s*([A-Z0-9]{4}-[A-Z0-9]{4})",
|
|
44643
|
+
canStreamLogin: true,
|
|
44644
|
+
logoutCmd: "gh auth logout --hostname github.com --user {{ACCOUNT}}",
|
|
44645
|
+
credentialPaths: ["~/.config/gh/hosts.yml"],
|
|
44646
|
+
description: "Prefer `gh` over raw GitHub API calls.",
|
|
44647
|
+
versionCmd: "gh --version 2>/dev/null | sed -n 1p",
|
|
44648
|
+
preinstallJarvis: true
|
|
44649
|
+
},
|
|
44650
|
+
mcporter: {
|
|
44651
|
+
category: "development",
|
|
44652
|
+
pkg: "mcporter",
|
|
44653
|
+
installer: "npm",
|
|
44654
|
+
label: "MCP (mcporter)",
|
|
44655
|
+
summary: "Use tools from any MCP server.",
|
|
44656
|
+
statusCmd: "mcporter list 2>/dev/null | grep -v 'No MCP servers' | grep -m1 .",
|
|
44657
|
+
description: "MCP servers as CLI: `mcporter list [server] [--schema]`, `mcporter call <server>.<tool> key=value` (`key=@file`), `mcporter config add <name> <cmd-or-url>`, `mcporter auth <server>`. `--help` for more.",
|
|
44658
|
+
versionCmd: "mcporter --version 2>/dev/null | sed -n 1p",
|
|
44659
|
+
preinstallJarvis: true,
|
|
44660
|
+
preinstallCloud: true
|
|
44661
|
+
},
|
|
44662
|
+
glab: {
|
|
44663
|
+
category: "development",
|
|
44664
|
+
pkg: "glab",
|
|
44665
|
+
installer: "binary",
|
|
44666
|
+
label: "GitLab",
|
|
44667
|
+
summary: "Work with your GitLab repos, merge requests and pipelines.",
|
|
44668
|
+
statusCmd: "glab auth status 2>&1 | grep 'Logged in to' | grep -m1 .",
|
|
44669
|
+
loginCmd: "glab auth login --device",
|
|
44670
|
+
credentialPaths: ["~/.config/glab-cli/config.yml"],
|
|
44671
|
+
description: "GitLab equivalent of `gh`.",
|
|
44672
|
+
versionCmd: "glab --version 2>/dev/null | sed -n 1p",
|
|
44673
|
+
deviceCodePattern: "one-time code: ([A-Z0-9-]+)",
|
|
44674
|
+
oauthUrlPattern: "(https://gitlab\\.com/oauth/device)",
|
|
44675
|
+
canStreamLogin: true
|
|
44676
|
+
},
|
|
44677
|
+
vercel: {
|
|
44678
|
+
preinstallCloud: true,
|
|
44679
|
+
category: "deployment",
|
|
44680
|
+
pkg: "vercel",
|
|
44681
|
+
installer: "npm",
|
|
44682
|
+
label: "Vercel",
|
|
44683
|
+
summary: "Deploy websites to Vercel and manage them.",
|
|
44684
|
+
statusCmd: "vercel whoami 2>/dev/null | tr -d '\\r' | grep -m1 .",
|
|
44685
|
+
loginCmd: "vercel login",
|
|
44686
|
+
credentialPaths: ["~/.local/share/com.vercel.cli/auth.json"],
|
|
44687
|
+
description: "`vercel deploy`; manage env vars, domains, preview URLs.",
|
|
44688
|
+
versionCmd: "vercel --version 2>/dev/null | sed -n 1p",
|
|
44689
|
+
deviceCodePattern: "user_code=([A-Z0-9-]+)",
|
|
44690
|
+
oauthUrlPattern: "(https://vercel\\.com/oauth/device\\S*)",
|
|
44691
|
+
canStreamLogin: true
|
|
44692
|
+
},
|
|
44693
|
+
eas: {
|
|
44694
|
+
category: "deployment",
|
|
44695
|
+
pkg: "eas-cli",
|
|
44696
|
+
installer: "npm",
|
|
44697
|
+
label: "Expo EAS",
|
|
44698
|
+
summary: "Build, update and submit mobile apps with Expo.",
|
|
44699
|
+
statusCmd: `out=$(eas whoami 2>/dev/null) && printf '%s\\n' "$out" | tr -d '\\r' | grep -m1 .`,
|
|
44700
|
+
loginCmd: "eas login --browser",
|
|
44701
|
+
logoutCmd: "eas logout",
|
|
44702
|
+
oauthUrlPattern: "(https://expo\\.dev/(?:sso-)?login\\?\\S+)",
|
|
44703
|
+
canStreamLogin: true,
|
|
44704
|
+
credentialPaths: ["~/.expo/state.json"],
|
|
44705
|
+
description: "Expo Application Services for React Native apps: `eas update --channel <c>` ships a JS-only OTA, `eas build -p ios --profile production --auto-submit` (`-p all` for both) makes a native build and sends it to TestFlight / Play. `eas build:list`, `eas update:list` and `eas submit` inspect or re-submit existing builds. An OTA only reaches installs whose runtimeVersion matches, so a native version bump needs a real build. The browser login binds to a RANDOM loopback port, so it only completes in a browser on the same host; on a remote/headless host set EXPO_TOKEN (Account -> Access tokens) instead. EXPO_TOKEN (Account -> Access tokens) works in CI instead of a login.",
|
|
44706
|
+
versionCmd: "eas --version 2>/dev/null | sed -n 1p"
|
|
44707
|
+
},
|
|
44708
|
+
netlify: {
|
|
44709
|
+
category: "deployment",
|
|
44710
|
+
pkg: "netlify-cli",
|
|
44711
|
+
installer: "npm",
|
|
44712
|
+
label: "Netlify",
|
|
44713
|
+
summary: "Deploy websites to Netlify and manage them.",
|
|
44714
|
+
statusCmd: `netlify api getCurrentUser 2>&1 | sed -n 's/.*"email"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
44715
|
+
loginCmd: "netlify login",
|
|
44716
|
+
credentialPaths: ["~/.netlify/config.json"],
|
|
44717
|
+
description: "`netlify deploy --prod` for production; manage env vars, forms, identity.",
|
|
44718
|
+
versionCmd: "netlify --version 2>/dev/null | sed -n 1p",
|
|
44719
|
+
oauthUrlPattern: "(https://app\\.netlify\\.com/authorize\\S+)",
|
|
44720
|
+
canStreamLogin: true
|
|
44721
|
+
},
|
|
44722
|
+
firebase: {
|
|
44723
|
+
preinstallCloud: true,
|
|
44724
|
+
category: "deployment",
|
|
44725
|
+
pkg: "firebase-tools",
|
|
44726
|
+
installer: "npm",
|
|
44727
|
+
label: "Firebase",
|
|
44728
|
+
summary: "Deploy and manage Firebase hosting, database and functions.",
|
|
44729
|
+
statusCmd: "firebase login:list 2>&1 | grep -oiE '[[:alnum:]._%+-]+@[[:alnum:].-]+\\.[[:alpha:]]{2,}' | grep -m1 .",
|
|
44730
|
+
loginCmd: "firebase login --no-localhost --reauth",
|
|
44731
|
+
loginNeedsPty: true,
|
|
44732
|
+
stdinPaste: true,
|
|
44733
|
+
credentialPaths: ["~/.config/configstore/firebase-tools.json"],
|
|
44734
|
+
description: "Deploy hosting/functions, manage Firestore/RTDB rules and data, auth users, emulators.",
|
|
44735
|
+
versionCmd: "firebase --version 2>/dev/null | sed -n 1p",
|
|
44736
|
+
oauthUrlPattern: "(https://auth\\.firebase\\.tools/login\\S+)",
|
|
44737
|
+
sessionIdPattern: "session ID:\\s*([0-9A-Za-z]{4,8})"
|
|
44738
|
+
},
|
|
44739
|
+
wrangler: {
|
|
44740
|
+
preinstallCloud: true,
|
|
44741
|
+
category: "deployment",
|
|
44742
|
+
pkg: "wrangler",
|
|
44743
|
+
installer: "npm",
|
|
44744
|
+
label: "Cloudflare",
|
|
44745
|
+
summary: "Deploy and manage Cloudflare Workers and Pages.",
|
|
44746
|
+
statusCmd: "wrangler whoami 2>&1 | grep -oiE '[[:alnum:]._%+-]+@[[:alnum:].-]+\\.[[:alpha:]]{2,}' | grep -m1 .",
|
|
44747
|
+
loginCmd: "wrangler login",
|
|
44748
|
+
credentialPaths: ["~/.config/.wrangler/config/default.toml"],
|
|
44749
|
+
description: "Tail logs with `wrangler tail`. Use `cloudflared` for tunnels.",
|
|
44750
|
+
versionCmd: "wrangler --version 2>/dev/null | sed -n 1p",
|
|
44751
|
+
oauthUrlPattern: "(https://dash\\.cloudflare\\.com/oauth2/auth\\S+)",
|
|
44752
|
+
oauthCallbackPort: 8976
|
|
44753
|
+
},
|
|
44754
|
+
stripe: {
|
|
44755
|
+
preinstallCloud: true,
|
|
44756
|
+
cloudInstallCmd: "curl -fsSL https://github.com/stripe/stripe-cli/releases/download/v1.50.10/stripe_1.50.10_linux_x86_64.tar.gz | tar -xz -C /usr/local/bin stripe",
|
|
44757
|
+
cloudVerifyCmd: "stripe --version",
|
|
44758
|
+
category: "payments",
|
|
44759
|
+
pkg: "stripe",
|
|
44760
|
+
installer: "binary",
|
|
44761
|
+
label: "Stripe",
|
|
44762
|
+
summary: "Look up Stripe payments, customers and subscriptions.",
|
|
44763
|
+
statusCmd: "stripe config --list 2>/dev/null | sed -n 's/^account_id[[:space:]]*=[[:space:]]*.\\([^'\\'']*\\).*/\\1/p' | grep -m10 .",
|
|
44764
|
+
loginCmd: "stripe login",
|
|
44765
|
+
loginNeedsPty: true,
|
|
44766
|
+
credentialPaths: ["~/.config/stripe/config.toml"],
|
|
44767
|
+
description: "`stripe listen` forwards webhooks locally; `stripe get/post /v1/...` for raw API.",
|
|
44768
|
+
versionCmd: "stripe --version 2>/dev/null | sed -n 1p",
|
|
44769
|
+
deviceCodePattern: "verification code:\\s*([A-Z0-9]{4}-[A-Z0-9]{4})",
|
|
44770
|
+
oauthUrlPattern: "(https://access\\.stripe\\.com/stripecli/\\S+)",
|
|
44771
|
+
canStreamLogin: true
|
|
44772
|
+
},
|
|
44773
|
+
flyctl: {
|
|
44774
|
+
category: "cloud",
|
|
44775
|
+
pkg: "flyctl",
|
|
44776
|
+
installer: "binary",
|
|
44777
|
+
label: "Fly.io",
|
|
44778
|
+
summary: "Deploy and scale apps on Fly.io.",
|
|
44779
|
+
statusCmd: "flyctl auth whoami 2>/dev/null | tr -d '\\r' | grep -m1 .",
|
|
44780
|
+
loginCmd: "flyctl auth login -t <access_token>",
|
|
44781
|
+
credentialPaths: ["~/.fly/config.yml"],
|
|
44782
|
+
description: "`flyctl deploy` from app dir; manage Postgres/volumes/machines/secrets.",
|
|
44783
|
+
versionCmd: "flyctl version 2>/dev/null | sed -n 1p"
|
|
44784
|
+
},
|
|
44785
|
+
supabase: {
|
|
44786
|
+
preinstallCloud: true,
|
|
44787
|
+
cloudInstallCmd: "curl -fsSL https://github.com/supabase/cli/releases/download/v2.117.0/supabase_2.117.0_linux_amd64.tar.gz | tar -xz -C /usr/local/bin supabase",
|
|
44788
|
+
cloudVerifyCmd: "supabase --version",
|
|
44789
|
+
category: "cloud",
|
|
44790
|
+
pkg: "supabase",
|
|
44791
|
+
installer: "binary",
|
|
44792
|
+
label: "Supabase",
|
|
44793
|
+
summary: "Manage your Supabase database, auth and storage.",
|
|
44794
|
+
statusCmd: "supabase projects list >/dev/null 2>&1 && echo authenticated",
|
|
44795
|
+
loginCmd: "supabase login --token <access_token>",
|
|
44796
|
+
credentialPaths: ["~/.config/supabase/access-token"],
|
|
44797
|
+
description: "Link to cloud project; runs/migrates local Postgres.",
|
|
44798
|
+
versionCmd: "supabase --version 2>/dev/null | sed -n 1p"
|
|
44799
|
+
},
|
|
44800
|
+
railway: {
|
|
44801
|
+
category: "cloud",
|
|
44802
|
+
pkg: "@railway/cli",
|
|
44803
|
+
installer: "npm",
|
|
44804
|
+
label: "Railway",
|
|
44805
|
+
summary: "Deploy and manage apps and databases on Railway.",
|
|
44806
|
+
statusCmd: `out=$(RAILWAY_NO_TELEMETRY=1 railway whoami 2>&1); rc=$?; printf '%s\\n' "$out" | grep -m1 .; exit $rc`,
|
|
44807
|
+
loginCmd: "railway login --browserless",
|
|
44808
|
+
credentialPaths: ["~/.railway/config.json"],
|
|
44809
|
+
description: "`railway up` to deploy current dir.",
|
|
44810
|
+
versionCmd: "railway --version 2>/dev/null | sed -n 1p",
|
|
44811
|
+
deviceCodePattern: "user_code=([A-Z0-9-]+)",
|
|
44812
|
+
oauthUrlPattern: "(https://railway\\.com/activate\\S*)",
|
|
44813
|
+
canStreamLogin: true
|
|
44814
|
+
},
|
|
44815
|
+
shopify: {
|
|
44816
|
+
preinstallCloud: true,
|
|
44817
|
+
category: "ecommerce",
|
|
44818
|
+
pkg: "@shopify/cli",
|
|
44819
|
+
installer: "npm",
|
|
44820
|
+
label: "Shopify",
|
|
44821
|
+
summary: "Build and manage Shopify stores and themes.",
|
|
44822
|
+
loginCmd: "shopify auth login --alias tfa",
|
|
44823
|
+
credentialPaths: ["~/.config/shopify-cli-kit-nodejs/config.json"],
|
|
44824
|
+
versionCmd: `node -p "require(require('fs').realpathSync(require('child_process').execSync('command -v shopify',{encoding:'utf8'}).trim()).replace(/\\/bin\\/[^/]*$/, '/package.json')).version" 2>/dev/null`,
|
|
44825
|
+
statusCmd: `python3 -c "import json,os,sys;p=os.path.expanduser('~/.config/shopify-cli-kit-nodejs/config.json');sys.exit(0 if json.load(open(p)).get('session') else 1)" 2>/dev/null && echo authenticated`,
|
|
44826
|
+
deviceCodePattern: "verification code: ([A-Z0-9-]+)",
|
|
44827
|
+
oauthUrlPattern: "(https://accounts\\.shopify\\.com/activate-with-code\\S*)",
|
|
44828
|
+
canStreamLogin: true,
|
|
44829
|
+
description: "Theme development, app scaffolding, store management"
|
|
44830
|
+
},
|
|
44831
|
+
"shop-app": {
|
|
44832
|
+
preinstallCloud: true,
|
|
44833
|
+
category: "ecommerce",
|
|
44834
|
+
pkg: "@todoforai/shop-app",
|
|
44835
|
+
installer: "npm",
|
|
44836
|
+
label: "Shop",
|
|
44837
|
+
summary: "Search products and compare prices across Shopify stores.",
|
|
44838
|
+
description: "Shop.app product search across Shopify stores. `shop-app search '<query>' --ships-to HU -n 10` returns products with price, rating, URL, and variants. `shop-app similar <variantId>` finds lookalikes.",
|
|
44839
|
+
versionCmd: "shop-app --version 2>/dev/null | sed -n 1p"
|
|
44840
|
+
},
|
|
44841
|
+
"datadog-ci": {
|
|
44842
|
+
category: "monitoring",
|
|
44843
|
+
pkg: "@datadog/datadog-ci",
|
|
44844
|
+
installer: "npm",
|
|
44845
|
+
label: "Datadog",
|
|
44846
|
+
summary: "Send test results and releases to Datadog.",
|
|
44847
|
+
versionCmd: "datadog-ci version 2>/dev/null | sed -n 1p",
|
|
44848
|
+
statusCmd: 'test -n "$DATADOG_API_KEY" && echo authenticated',
|
|
44849
|
+
description: "CI test visibility, sourcemap uploads, deployment tracking."
|
|
44850
|
+
},
|
|
44851
|
+
"sentry-cli": {
|
|
44852
|
+
preinstallCloud: true,
|
|
44853
|
+
category: "monitoring",
|
|
44854
|
+
pkg: "@sentry/cli",
|
|
44855
|
+
installer: "npm",
|
|
44856
|
+
label: "Sentry",
|
|
44857
|
+
summary: "Manage Sentry releases and error tracking.",
|
|
44858
|
+
statusCmd: "sentry-cli info --no-defaults >/dev/null 2>&1 && echo authenticated",
|
|
44859
|
+
loginCmd: "sentry-cli login --auth-token <auth_token>",
|
|
44860
|
+
credentialPaths: ["~/.sentryclirc"],
|
|
44861
|
+
description: "`sentry-cli releases new <version>`.",
|
|
44862
|
+
versionCmd: "sentry-cli --version 2>/dev/null | sed -n 1p"
|
|
44863
|
+
},
|
|
44864
|
+
"tfa-cli": {
|
|
44865
|
+
category: "utility",
|
|
44866
|
+
pkg: "@todoforai/cli",
|
|
44867
|
+
installer: "npm",
|
|
44868
|
+
label: "TODOforAI",
|
|
44869
|
+
summary: "Create and follow up on your TODOs, and show results in the chat.",
|
|
44870
|
+
description: 'Manage the user\'s OWN TODOforAI tasks (not code `// TODO` comments). Delegate/spin off work: `tfa-cli "prompt"` creates a real TODO with its own agent and chat (`-n` wait for completion, `--no-watch` fire-and-forget, `--project/--agent/--model`, `--resume <id>`, `addmessage <id> "text"`). Inspect: `list [--status open]`, `--inspect <id>`. Edit any todo without opening it: `status <id> DONE|READY|ARCHIVED|POSTPONED|CANCELLED|DELETED` (close, reopen, shelve, trash — `todo restore <id>` undoes a delete) and `todo set <id|-> title=… group=… star=true schedule=<unix-ms> agent=… brand=…` (own todo fields). Both take ONE id, so a loop over `list --json | jq -r \'.items[].id\'` is how you close, retitle, refile or archive MANY todos at once; `project set|settings|groups …` (name, settings, todo groups), `agent create|update <agent> model=… sysmsg=…` (permissions/MCP/device wiring and delete are refused from an agent shell). Surface results into chat: `show <file|-> [todo-id]` (renders by mimetype; `--card <name>` via project renderer; `--alias <name>` updates in place), `open <url>` embeds a live preview. Notifications: `inbox [needs-you|messages|activity] [--unread]` reads the user\'s bell feed (what finished/failed/needs them while away), `inbox seen [tab]` marks it read; `notify "Title" "message" [--href /t/<id>]` leaves a note in the user\'s Messages tab + phone push (shown as from you); `--to <email>` reaches a member of the current project instead (`project members` lists them, 20/day) — nobody else; same text is delivered once, max 10/day to the user, use for things they must see later (not chat replies). This is the ONLY way to display a local file (image, pdf, html) in the chat: markdown `` with a local/relative path does NOT resolve to workspace files or attachments and 404s in the browser. `--template` for registry workflows.',
|
|
44871
|
+
installCmd: "npm install -g @todoforai/cli",
|
|
44872
|
+
versionCmd: "tfa-cli --version 2>/dev/null | sed -n 1p",
|
|
44873
|
+
preinstallCloud: true,
|
|
44874
|
+
preinstallJarvis: true,
|
|
44875
|
+
aliases: ["todoforai-cli", "todoai"]
|
|
44876
|
+
},
|
|
44877
|
+
curl: {
|
|
44878
|
+
commodity: true,
|
|
44879
|
+
category: "networking",
|
|
44880
|
+
pkg: "curl",
|
|
44881
|
+
installer: "system",
|
|
44882
|
+
label: "Web Request",
|
|
44883
|
+
summary: "Fetch URLs and call web APIs.",
|
|
44884
|
+
binName: "curl",
|
|
44885
|
+
description: "HTTP/HTTPS/FTP client: GET/POST/PUT/DELETE, headers, auth, file upload/download, follow redirects, cookies, TLS.",
|
|
44886
|
+
versionCmd: "curl --version 2>/dev/null | sed -n 1p | cut -d' ' -f1-2",
|
|
44887
|
+
preinstallCloud: true,
|
|
44888
|
+
internal: true,
|
|
44889
|
+
preinstallJarvis: true
|
|
44890
|
+
},
|
|
44891
|
+
cloudflared: {
|
|
44892
|
+
preinstallCloud: true,
|
|
44893
|
+
cloudInstallCmd: "curl -fsSL https://github.com/cloudflare/cloudflared/releases/download/2026.9.0/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared && chmod 0755 /usr/local/bin/cloudflared",
|
|
44894
|
+
cloudVerifyCmd: "cloudflared --version",
|
|
44895
|
+
commodity: true,
|
|
44896
|
+
category: "networking",
|
|
44897
|
+
pkg: "cloudflared",
|
|
44898
|
+
installer: "binary",
|
|
44899
|
+
label: "Tunnel",
|
|
44900
|
+
summary: "Put a local app on a public web address.",
|
|
44901
|
+
description: "`cloudflared tunnel --url http://localhost:<port>` prints a public https URL.",
|
|
44902
|
+
versionCmd: "cloudflared --version 2>/dev/null | sed -n 1p"
|
|
44903
|
+
},
|
|
44904
|
+
vault: {
|
|
44905
|
+
category: "security",
|
|
44906
|
+
pkg: "vault",
|
|
44907
|
+
installer: "binary",
|
|
44908
|
+
label: "HashiCorp Vault",
|
|
44909
|
+
summary: "Read and manage secrets in HashiCorp Vault.",
|
|
44910
|
+
statusCmd: "vault token lookup >/dev/null 2>&1 && echo authenticated",
|
|
44911
|
+
loginCmd: "vault login <token>",
|
|
44912
|
+
credentialPaths: ["~/.vault-token"],
|
|
44913
|
+
versionCmd: "vault --version 2>/dev/null | sed -n '1s/ (.*//p'",
|
|
44914
|
+
description: "HashiCorp Vault secrets management and dynamic credentials."
|
|
44915
|
+
},
|
|
44916
|
+
rclone: {
|
|
44917
|
+
category: "cloud",
|
|
44918
|
+
pkg: "rclone",
|
|
44919
|
+
installer: "binary",
|
|
44920
|
+
preinstallCloud: true,
|
|
44921
|
+
binary: {
|
|
44922
|
+
"linux-x86_64": { url: "https://github.com/todoforai/rclone-backend/releases/download/v0.1.6/rclone-linux-amd64.tar.gz", archive: "tar.gz", extract: "rclone" },
|
|
44923
|
+
"linux-aarch64": { url: "https://github.com/todoforai/rclone-backend/releases/download/v0.1.6/rclone-linux-arm64.tar.gz", archive: "tar.gz", extract: "rclone" },
|
|
44924
|
+
"darwin-x86_64": { url: "https://github.com/todoforai/rclone-backend/releases/download/v0.1.6/rclone-darwin-amd64.tar.gz", archive: "tar.gz", extract: "rclone" },
|
|
44925
|
+
"darwin-aarch64": { url: "https://github.com/todoforai/rclone-backend/releases/download/v0.1.6/rclone-darwin-arm64.tar.gz", archive: "tar.gz", extract: "rclone" },
|
|
44926
|
+
"windows-x86_64": { url: "https://github.com/todoforai/rclone-backend/releases/download/v0.1.6/rclone-windows-amd64.zip", archive: "zip", extract: "rclone.exe" }
|
|
44927
|
+
},
|
|
44928
|
+
label: "Cloud Storage",
|
|
44929
|
+
summary: "Move files between Google Drive, Dropbox, OneDrive, S3 and more.",
|
|
44930
|
+
statusCmd: "rclone listremotes --long 2>/dev/null | tr -s ' ' | grep -v ' todoforai *$' | grep -m20 .",
|
|
44931
|
+
loginCmd: "rclone config",
|
|
44932
|
+
loginTerminalHint: "Connect a storage from its own tile (Google Drive, OneDrive, Dropbox…). For other backends run `rclone config` in a terminal on this host.",
|
|
44933
|
+
oauthUrlPattern: "(https?://127\\.0\\.0\\.1:\\d+/auth\\?\\S+)",
|
|
44934
|
+
oauthCallbackPort: 53682,
|
|
44935
|
+
credentialPaths: ["~/.config/rclone/rclone.conf"],
|
|
44936
|
+
subProviders: {
|
|
44937
|
+
gdrive: {
|
|
44938
|
+
label: "Google Drive",
|
|
44939
|
+
authType: "oauth",
|
|
44940
|
+
connectCmd: "rclone config create {{REMOTE}} drive",
|
|
44941
|
+
remoteName: "gdrive",
|
|
44942
|
+
rcloneType: "drive",
|
|
44943
|
+
userInfoCmd: `TOKEN=$(rclone config dump 2>/dev/null | python3 -c "import json,sys; print(json.loads(json.load(sys.stdin)['{{REMOTE}}']['token'])['access_token'])") && curl -sf 'https://www.googleapis.com/drive/v3/about?fields=user' -H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; print(json.load(sys.stdin)['user']['emailAddress'])" 2>/dev/null`
|
|
44944
|
+
},
|
|
44945
|
+
onedrive: {
|
|
44946
|
+
label: "OneDrive",
|
|
44947
|
+
authType: "oauth",
|
|
44948
|
+
connectCmd: "rclone config create {{REMOTE}} onedrive",
|
|
44949
|
+
remoteName: "onedrive",
|
|
44950
|
+
rcloneType: "onedrive",
|
|
44951
|
+
userInfoCmd: `TOKEN=$(rclone config dump 2>/dev/null | python3 -c "import json,sys; print(json.loads(json.load(sys.stdin)['{{REMOTE}}']['token'])['access_token'])") && curl -sf 'https://graph.microsoft.com/v1.0/me' -H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('mail') or d.get('userPrincipalName',''))" 2>/dev/null`
|
|
44952
|
+
},
|
|
44953
|
+
dropbox: {
|
|
44954
|
+
label: "Dropbox",
|
|
44955
|
+
authType: "oauth",
|
|
44956
|
+
connectCmd: "rclone config create {{REMOTE}} dropbox",
|
|
44957
|
+
remoteName: "dropbox",
|
|
44958
|
+
rcloneType: "dropbox",
|
|
44959
|
+
userInfoCmd: `TOKEN=$(rclone config dump 2>/dev/null | python3 -c "import json,sys; print(json.loads(json.load(sys.stdin)['{{REMOTE}}']['token'])['access_token'])") && curl -sf -X POST 'https://api.dropboxapi.com/2/users/get_current_account' -H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; print(json.load(sys.stdin)['email'])" 2>/dev/null`
|
|
44960
|
+
},
|
|
44961
|
+
s3: {
|
|
44962
|
+
label: "Amazon S3",
|
|
44963
|
+
authType: "credentials",
|
|
44964
|
+
connectCmd: "rclone config create {{REMOTE}} s3",
|
|
44965
|
+
remoteName: "s3",
|
|
44966
|
+
rcloneType: "s3"
|
|
44967
|
+
}
|
|
44968
|
+
},
|
|
44969
|
+
versionCmd: "rclone version 2>/dev/null | sed -n 1p",
|
|
44970
|
+
preinstallJarvis: true,
|
|
44971
|
+
description: "Access Google Drive, OneDrive, Dropbox, S3, and 40+ cloud providers. List, copy, sync, move, and mount files; use `rclone config create <name> <provider>` to connect."
|
|
44972
|
+
},
|
|
44973
|
+
aws: {
|
|
44974
|
+
preinstallCloud: true,
|
|
44975
|
+
cloudInstallCmd: "curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o /tmp/awscli.zip && unzip -qo /tmp/awscli.zip -d /tmp && /tmp/aws/install --update && rm -rf /tmp/aws /tmp/awscli.zip",
|
|
44976
|
+
cloudVerifyCmd: "aws --version",
|
|
44977
|
+
category: "cloud",
|
|
44978
|
+
pkg: "awscli",
|
|
44979
|
+
installer: "system",
|
|
44980
|
+
label: "AWS",
|
|
44981
|
+
summary: "Manage your AWS account and services.",
|
|
44982
|
+
installCmd: `mkdir -p "$HOME/.todoforai/tools/bin"; if [ "$(uname -s)" = Darwin ]; then curl -fsSL https://awscli.amazonaws.com/AWSCLIV2.pkg -o /tmp/AWSCLIV2.pkg && printf '<?xml version="1.0" encoding="UTF-8"?>\\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\\n<plist version="1.0"><array><dict><key>choiceAttribute</key><string>customLocation</string><key>attributeSetting</key><string>%s</string><key>choiceIdentifier</key><string>default</string></dict></array></plist>\\n' "$HOME/.todoforai/tools" > /tmp/aws-choices.xml && installer -pkg /tmp/AWSCLIV2.pkg -target CurrentUserHomeDirectory -applyChoiceChangesXML /tmp/aws-choices.xml && mkdir -p "$HOME/.todoforai/tools/bin" && ln -sf "$HOME/.todoforai/tools/aws-cli/aws" "$HOME/.todoforai/tools/bin/aws" && ln -sf "$HOME/.todoforai/tools/aws-cli/aws_completer" "$HOME/.todoforai/tools/bin/aws_completer"; rc=$?; rm -f /tmp/AWSCLIV2.pkg /tmp/aws-choices.xml; exit $rc; else ARCH=$(uname -m); case "$ARCH" in arm64|aarch64) ARCH=aarch64;; *) ARCH=x86_64;; esac; curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-$ARCH.zip" -o /tmp/awscli.zip && rm -rf /tmp/aws && unzip -qo /tmp/awscli.zip -d /tmp && /tmp/aws/install --update --install-dir "$HOME/.todoforai/tools/aws-cli" --bin-dir "$HOME/.todoforai/tools/bin"; rc=$?; rm -rf /tmp/aws /tmp/awscli.zip; exit $rc; fi`,
|
|
44983
|
+
statusCmd: "aws sts get-caller-identity --query Arn --output text 2>/dev/null | sed 's/.*\\///' | grep -m1 .",
|
|
44984
|
+
loginCmd: "aws configure set aws_access_key_id <access_key_id> && aws configure set aws_secret_access_key <secret_access_key> && aws configure set region <region>",
|
|
44985
|
+
credentialPaths: ["~/.aws/credentials", "~/.aws/config", "~/.aws/sso/cache"],
|
|
44986
|
+
description: "Official AWS CLI v2, installed user-locally into ~/.todoforai/tools (no sudo; Linux x86_64/aarch64 + macOS). Auth via `aws configure` (access keys) or `aws configure sso` + `aws sso login` (browser device flow).",
|
|
44987
|
+
versionCmd: "aws --version 2>/dev/null | sed -n 1p",
|
|
44988
|
+
uninstallCmd: 'rm -rf "$HOME/.todoforai/tools/aws-cli" "$HOME/.todoforai/tools/bin/aws" "$HOME/.todoforai/tools/bin/aws_completer"; hash -r 2>/dev/null; ! command -v aws >/dev/null 2>&1 || { echo "aws is still on PATH: $(command -v aws) — not installed by TODOforAI, remove it with the package manager that installed it (snap/apt/brew/sudo)"; exit 1; }'
|
|
44989
|
+
},
|
|
44990
|
+
gcloud: {
|
|
44991
|
+
category: "cloud",
|
|
44992
|
+
pkg: "google-cloud-sdk",
|
|
44993
|
+
installer: "system",
|
|
44994
|
+
label: "Google Cloud",
|
|
44995
|
+
summary: "Manage your Google Cloud projects and services.",
|
|
44996
|
+
needsPython: true,
|
|
44997
|
+
installCmd: `curl -fsSL https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-sdk.tar.gz | tar -xzC "$HOME" && CLOUDSDK_PYTHON="$py" "$HOME/google-cloud-sdk/install.sh" --quiet --install-python false --usage-reporting false --path-update false --command-completion false && mkdir -p "$HOME/.todoforai/tools/bin" && rm -f "$HOME/.todoforai/tools/bin/gcloud" && printf '#!/bin/sh\\nCLOUDSDK_PYTHON="\${CLOUDSDK_PYTHON:-%s}" exec "$HOME/google-cloud-sdk/bin/gcloud" "$@"\\n' "$py" > "$HOME/.todoforai/tools/bin/gcloud" && chmod +x "$HOME/.todoforai/tools/bin/gcloud"`,
|
|
44998
|
+
statusCmd: `gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>/dev/null | tr -d '\\r' | grep -m1 .`,
|
|
44999
|
+
loginCmd: "gcloud auth login --no-launch-browser",
|
|
45000
|
+
loginNeedsPty: true,
|
|
45001
|
+
stdinPaste: true,
|
|
45002
|
+
oauthUrlPattern: "(https://accounts\\.google\\.com/o/oauth2/auth\\S+)",
|
|
45003
|
+
credentialPaths: ["~/.config/gcloud"],
|
|
45004
|
+
description: "Official Google Cloud CLI. `gcloud auth login --no-launch-browser` prints the OAuth URL and waits for the pasted verification code.",
|
|
45005
|
+
versionCmd: "gcloud --version 2>/dev/null | sed -n 1p",
|
|
45006
|
+
uninstallCmd: 'rm -rf "$HOME/google-cloud-sdk" "$HOME/.todoforai/tools/bin/gcloud"; hash -r 2>/dev/null; ! command -v gcloud >/dev/null 2>&1 || { echo "gcloud is still on PATH: $(command -v gcloud)"; exit 1; }',
|
|
45007
|
+
updateCmd: "gcloud components update --quiet"
|
|
45008
|
+
},
|
|
45009
|
+
az: {
|
|
45010
|
+
category: "cloud",
|
|
45011
|
+
pkg: "azure-cli",
|
|
45012
|
+
installer: "pip",
|
|
45013
|
+
label: "Azure",
|
|
45014
|
+
summary: "Manage your Microsoft Azure resources.",
|
|
45015
|
+
binName: "az",
|
|
45016
|
+
statusCmd: "az account show --query user.name -o tsv 2>/dev/null | tr -d '\\r' | grep -m1 .",
|
|
45017
|
+
loginCmd: "az login --use-device-code",
|
|
45018
|
+
oauthUrlPattern: "(https://login\\.microsoft\\.com/device\\S*)",
|
|
45019
|
+
deviceCodePattern: "enter the code ([A-Z0-9]+)",
|
|
45020
|
+
canStreamLogin: true,
|
|
45021
|
+
credentialPaths: ["~/.azure"],
|
|
45022
|
+
description: "Official Azure CLI. Device-code login: prints login.microsoft.com/device + a code, then polls — no callback port.",
|
|
45023
|
+
versionCmd: `az version --query '"azure-cli"' -o tsv 2>/dev/null | sed -n 1p`
|
|
45024
|
+
},
|
|
45025
|
+
doctl: {
|
|
45026
|
+
preinstallCloud: true,
|
|
45027
|
+
cloudInstallCmd: "curl -fsSL https://github.com/digitalocean/doctl/releases/download/v1.168.0/doctl-1.168.0-linux-amd64.tar.gz | tar -xz -C /usr/local/bin doctl",
|
|
45028
|
+
cloudVerifyCmd: "doctl version",
|
|
45029
|
+
category: "cloud",
|
|
45030
|
+
pkg: "doctl",
|
|
45031
|
+
installer: "binary",
|
|
45032
|
+
label: "DigitalOcean",
|
|
45033
|
+
summary: "Manage your DigitalOcean servers and apps.",
|
|
45034
|
+
statusCmd: "doctl account get --format Email --no-header 2>/dev/null | tr -d '\\r' | grep -m1 .",
|
|
45035
|
+
loginCmd: "doctl auth init -t <access_token>",
|
|
45036
|
+
loginNeedsPty: true,
|
|
45037
|
+
credentialPaths: ["~/.config/doctl/config.yaml"],
|
|
45038
|
+
description: "Official DigitalOcean CLI. `doctl auth init` prompts for an API token from cloud.digitalocean.com/account/api/tokens.",
|
|
45039
|
+
versionCmd: "doctl version 2>/dev/null | sed -n 1p"
|
|
45040
|
+
},
|
|
45041
|
+
rdt: {
|
|
45042
|
+
preinstallCloud: true,
|
|
45043
|
+
packages: ["rdt-cli==0.4.1"],
|
|
45044
|
+
category: "social",
|
|
45045
|
+
pkg: "rdt-cli",
|
|
45046
|
+
installer: "pip",
|
|
45047
|
+
label: "Reddit",
|
|
45048
|
+
summary: "Search Reddit, read threads and post comments.",
|
|
45049
|
+
statusCmd: `rdt status 2>&1 | sed -n 's/.*"username"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
45050
|
+
loginCmd: "rdt login",
|
|
45051
|
+
loginTerminalHint: "Log in to reddit.com in a browser on this host (Chrome/Firefox), then run `rdt login`: it imports that browser's Reddit cookies.",
|
|
45052
|
+
credentialPaths: ["~/.config/rdt-cli/credential.json"],
|
|
45053
|
+
description: 'Reddit CLI. Read: `rdt search "<query>" -r <sub> --json -c`, `rdt sub <name>`, `rdt read <postId>`, `rdt user-comments <user>`. Write: `rdt comment <postId> "<text>"`, `rdt upvote`, `rdt save`.',
|
|
45054
|
+
versionCmd: "rdt --version 2>/dev/null | sed -n 1p"
|
|
45055
|
+
},
|
|
45056
|
+
pymupdf: {
|
|
45057
|
+
category: "utility",
|
|
45058
|
+
pkg: "pymupdf",
|
|
45059
|
+
packages: ["pymupdf==1.28.2"],
|
|
45060
|
+
installer: "pip",
|
|
45061
|
+
label: "PDF",
|
|
45062
|
+
summary: "Read, edit, merge and split PDF files.",
|
|
45063
|
+
versionCmd: "{ python -c 'import pymupdf; print(pymupdf.__version__)' || python3 -c 'import pymupdf; print(pymupdf.__version__)' || py -c 'import pymupdf; print(pymupdf.__version__)'; } 2>/dev/null",
|
|
45064
|
+
preinstallCloud: true,
|
|
45065
|
+
cloudVerifyCmd: "python3 -c 'import pymupdf'",
|
|
45066
|
+
preinstallJarvis: true,
|
|
45067
|
+
description: "PDF text editing, extraction, merge, split. Call via `python3 -c`."
|
|
45068
|
+
},
|
|
45069
|
+
pyhanko: {
|
|
45070
|
+
category: "security",
|
|
45071
|
+
pkg: "pyhanko-cli",
|
|
45072
|
+
packages: ["pyhanko-cli==0.5.0", "pyHanko[pkcs11,image-support,opentype]==0.37.0"],
|
|
45073
|
+
installer: "pip",
|
|
45074
|
+
binName: "pyhanko",
|
|
45075
|
+
label: "PDF Signing",
|
|
45076
|
+
summary: "Digitally sign and verify PDFs with a certificate (PAdES, timestamps, smart cards).",
|
|
45077
|
+
versionCmd: "pyhanko --version 2>/dev/null | sed -n 1p",
|
|
45078
|
+
preinstallCloud: true,
|
|
45079
|
+
cloudVerifyCmd: "pyhanko --version",
|
|
45080
|
+
preinstallJarvis: true,
|
|
45081
|
+
description: "Cryptographic PDF signing/validation (PAdES B-B..B-LTA). Sign: `pyhanko sign addsig --field Sig1 [--timestamp-url <tsa>] pkcs12 --passfile pass.txt in.pdf out.pdf cert.p12`; smart card/eID: `... pkcs11 --lib <pkcs11.so> in.pdf out.pdf`; verify: `pyhanko sign validate --pretty-print [--trust ca.pem] out.pdf`; list fields: `pyhanko sign list`. The signer's cert/key comes from the user (vault); self-signed certs validate only with `--trust`. Not for click-to-sign workflows."
|
|
45082
|
+
},
|
|
45083
|
+
anydoc: {
|
|
45084
|
+
category: "utility",
|
|
45085
|
+
pkg: "@firecrawl/anydoc",
|
|
45086
|
+
installer: "npm",
|
|
45087
|
+
binName: "anydoc",
|
|
45088
|
+
label: "Doc to Markdown",
|
|
45089
|
+
summary: "Turn Word, PowerPoint, Excel and other documents into clean text.",
|
|
45090
|
+
description: "Office/rich docs (docx/pptx/xlsx/odt/rtf/epub/csv) → Markdown, fully local. `anydoc file.docx` → stdout, `-o out.md` writes, `anydoc - --format csv < stdin`. Prefer over raw XML extraction for reading; one-way, no OCR for scanned PDFs.",
|
|
45091
|
+
versionCmd: "anydoc --version 2>/dev/null | sed -n 1p",
|
|
45092
|
+
preinstallCloud: true,
|
|
45093
|
+
preinstallJarvis: true
|
|
45094
|
+
},
|
|
45095
|
+
"agent-browser": {
|
|
45096
|
+
category: "development",
|
|
45097
|
+
pkg: "agent-browser@0.30.1",
|
|
45098
|
+
installer: "npm",
|
|
45099
|
+
preinstallCloud: true,
|
|
45100
|
+
label: "Browser",
|
|
45101
|
+
summary: "Browse websites automatically: click, type, read and screenshot.",
|
|
45102
|
+
description: "Browser automation over CDP (`open`/`snapshot`/`click`/`type`/`fill`/`read`/`screenshot`/`eval`). `connect '<url>'` to a listed live browser (prefer the user's real Chrome), verify with `snapshot`; if empty, `close` (own session only) and reconnect once. NEVER `close --all`. Shared browser: `tab new` for your own tab, `tab <id>` before each command. No URL listed: cloud → browser-manager-cli; PC with display → Chrome `--remote-debugging-port=9222`, attach `--cdp 9222`.",
|
|
45103
|
+
versionCmd: "agent-browser --version 2>/dev/null | sed -n 1p",
|
|
45104
|
+
preinstallJarvis: true
|
|
45105
|
+
},
|
|
45106
|
+
"browser-manager-cli": {
|
|
45107
|
+
category: "development",
|
|
45108
|
+
pkg: "browser-manager-cli",
|
|
45109
|
+
installer: "binary",
|
|
45110
|
+
binName: "browser-manager-cli",
|
|
45111
|
+
preinstallCloud: true,
|
|
45112
|
+
label: "Browser Manager",
|
|
45113
|
+
summary: "Start browsers in the cloud for automated browsing.",
|
|
45114
|
+
platformAuth: true,
|
|
45115
|
+
description: "Spawns cloud Chromium sessions, each exposed as a CDP WebSocket for agent-browser to drive. `create` prints one line ending in a cdpUrl — pass it straight to `agent-browser connect '<cdpUrl>'` (connect the cdpUrl, not the Chrome debug port). `list`/`get <id>`, `delete <id>`/`delete-all`, `hibernate`/`restore`. Sessions run stealth Chromium that reads as a real desktop browser. For sites that block datacenter IPs, route through a proxy: `create --proxy socks5://host:port [--proxy-user U --proxy-pass P]`. Use this on the cloud VM instead of launching a local browser.",
|
|
45116
|
+
versionCmd: "browser-manager-cli version 2>/dev/null | sed -n 1p",
|
|
45117
|
+
binary: {
|
|
45118
|
+
"linux-x86_64": {
|
|
45119
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-linux-x86_64",
|
|
45120
|
+
archive: "raw"
|
|
45121
|
+
},
|
|
45122
|
+
"linux-aarch64": {
|
|
45123
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-linux-aarch64",
|
|
45124
|
+
archive: "raw"
|
|
45125
|
+
},
|
|
45126
|
+
"darwin-x86_64": {
|
|
45127
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-darwin-x86_64",
|
|
45128
|
+
archive: "raw"
|
|
45129
|
+
},
|
|
45130
|
+
"darwin-aarch64": {
|
|
45131
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-darwin-aarch64",
|
|
45132
|
+
archive: "raw"
|
|
45133
|
+
},
|
|
45134
|
+
"windows-x86_64": {
|
|
45135
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-windows-x86_64.exe",
|
|
45136
|
+
archive: "raw"
|
|
45137
|
+
}
|
|
45138
|
+
},
|
|
45139
|
+
preinstallJarvis: true
|
|
45140
|
+
},
|
|
45141
|
+
"todoforai-browser": {
|
|
45142
|
+
category: "development",
|
|
45143
|
+
pkg: "@todoforai/browser",
|
|
45144
|
+
aliases: ["tfa-browser"],
|
|
45145
|
+
installer: "npm",
|
|
45146
|
+
preinstallCloud: true,
|
|
45147
|
+
label: "Browser (Extension)",
|
|
45148
|
+
summary: "Drive your own browser through the TODOforAI extension.",
|
|
45149
|
+
versionCmd: `node -p "require(require('fs').realpathSync(require('child_process').execSync('command -v todoforai-browser',{encoding:'utf8'}).trim()).replace(/\\/dist\\/index\\.js$/, '/package.json')).version" 2>/dev/null`,
|
|
45150
|
+
internal: true,
|
|
45151
|
+
preinstallJarvis: true,
|
|
45152
|
+
description: "Browser automation via extension (non-headless), web scraping, accessibility tree snapshots, screenshots, PDF generation"
|
|
45153
|
+
},
|
|
45154
|
+
"tfa-explore": {
|
|
45155
|
+
preinstallCloud: true,
|
|
45156
|
+
category: "development",
|
|
45157
|
+
pkg: "@todoforai/tfa-explore",
|
|
45158
|
+
installer: "npm",
|
|
45159
|
+
label: "Explore",
|
|
45160
|
+
summary: "Send a helper agent to explore a codebase and report back.",
|
|
45161
|
+
platformAuth: true,
|
|
45162
|
+
description: 'Sub-agent codebase exploration in its own context, you get only the answer: `tfa-explore "where is auth handled?" [--repo <path>]`. Prefer over manual multi-file searching.',
|
|
45163
|
+
versionCmd: "tfa-explore --version 2>/dev/null | sed -n 1p",
|
|
45164
|
+
installCmd: "npm install -g @todoforai/tfa-explore",
|
|
45165
|
+
internal: true
|
|
45166
|
+
},
|
|
45167
|
+
"tfa-review": {
|
|
45168
|
+
preinstallCloud: true,
|
|
45169
|
+
category: "development",
|
|
45170
|
+
pkg: "@todoforai/tfa-review",
|
|
45171
|
+
installer: "npm",
|
|
45172
|
+
label: "Review",
|
|
45173
|
+
summary: "Send a helper agent to review your code changes.",
|
|
45174
|
+
platformAuth: true,
|
|
45175
|
+
description: 'Sub-agent review of a git diff in its own context: `tfa-review "<goal>" [--repo <path>] [--against <ref>]` (default: uncommitted). Run before calling a non-trivial change done.',
|
|
45176
|
+
versionCmd: "tfa-review --version 2>/dev/null | sed -n 1p",
|
|
45177
|
+
installCmd: "npm install -g @todoforai/tfa-review",
|
|
45178
|
+
internal: true
|
|
45179
|
+
},
|
|
45180
|
+
"tfa-summary": {
|
|
45181
|
+
preinstallCloud: true,
|
|
45182
|
+
category: "development",
|
|
45183
|
+
pkg: "@todoforai/tfa-summary",
|
|
45184
|
+
installer: "npm",
|
|
45185
|
+
label: "Summary",
|
|
45186
|
+
summary: "Summarize files or long output with a helper agent.",
|
|
45187
|
+
platformAuth: true,
|
|
45188
|
+
description: 'Sub-agent summary so raw text never enters your context: `cat big.log | tfa-summary "what failed?"`, or `-f <file>` (repeatable).',
|
|
45189
|
+
versionCmd: "tfa-summary --version 2>/dev/null | sed -n 1p",
|
|
45190
|
+
installCmd: "npm install -g @todoforai/tfa-summary",
|
|
45191
|
+
internal: true
|
|
45192
|
+
},
|
|
45193
|
+
"tfa-handoff": {
|
|
45194
|
+
preinstallCloud: true,
|
|
45195
|
+
category: "development",
|
|
45196
|
+
pkg: "@todoforai/tfa-handoff",
|
|
45197
|
+
installer: "npm",
|
|
45198
|
+
label: "Handoff",
|
|
45199
|
+
summary: "Turn a long conversation into a short handover note.",
|
|
45200
|
+
platformAuth: true,
|
|
45201
|
+
description: "Compact a conversation into a handoff document for a fresh agent.",
|
|
45202
|
+
versionCmd: "tfa-handoff --version 2>/dev/null | sed -n 1p",
|
|
45203
|
+
installCmd: "npm install -g @todoforai/tfa-handoff",
|
|
45204
|
+
internal: true
|
|
45205
|
+
},
|
|
45206
|
+
"tfa-wait": {
|
|
45207
|
+
category: "development",
|
|
45208
|
+
pkg: "@todoforai/tfa-wait",
|
|
45209
|
+
installer: "npm",
|
|
45210
|
+
label: "Wait",
|
|
45211
|
+
summary: "Wait for a time or an event, then continue the task.",
|
|
45212
|
+
platformAuth: true,
|
|
45213
|
+
description: "Schedule a wake-up: `tfa-wait '<expr>' \"<message>\"` — expr is a time (`3h`, `daily@9:00`), a webhook, or a command's output; the message arrives later as a new chat message. Wait for a long job: `tfa-wait 'bench || 6h' \"Done: exit {{payload.exit}}\"` then `tfa-wait run '<cmd>' --pipe bench --on-exit &` (each stdout line = event; cancelling kills the command). Never pgrep/sleep poll loops.",
|
|
45214
|
+
versionCmd: "tfa-wait --version 2>/dev/null | sed -n 1p",
|
|
45215
|
+
installCmd: "npm install -g @todoforai/tfa-wait",
|
|
45216
|
+
preinstallCloud: true,
|
|
45217
|
+
internal: true,
|
|
45218
|
+
preinstallJarvis: true
|
|
45219
|
+
},
|
|
45220
|
+
"tfa-vault": {
|
|
45221
|
+
category: "security",
|
|
45222
|
+
pkg: "@todoforai/tfa-vault",
|
|
45223
|
+
installer: "npm",
|
|
45224
|
+
label: "Vault",
|
|
45225
|
+
summary: "Your password and secret store.",
|
|
45226
|
+
platformAuth: true,
|
|
45227
|
+
description: "The user's encrypted secret vault — using its secrets is the intended workflow. READ: when a task needs a key/token/password the user owns, `tfa-vault list` then `get <path>`; don't ask for what's already stored; never echo values. WRITE proactively: any new secret in the conversation (pasted, generated, from a login) → `put <path> field=value` (`patch` adds fields; `put` refuses an existing path — `put --force` replaces all fields on rotation). Paths: `accounts/<svc>`, `api/<svc>`, `secrets/<name>`.",
|
|
45228
|
+
versionCmd: "tfa-vault --version 2>/dev/null | sed -n 1p",
|
|
45229
|
+
installCmd: "npm install -g @todoforai/tfa-vault",
|
|
45230
|
+
preinstallCloud: true,
|
|
45231
|
+
preinstallJarvis: true
|
|
45232
|
+
},
|
|
45233
|
+
"tfa-settings": {
|
|
45234
|
+
category: "utility",
|
|
45235
|
+
pkg: "@todoforai/tfa-settings",
|
|
45236
|
+
installer: "npm",
|
|
45237
|
+
label: "Settings",
|
|
45238
|
+
summary: "Change your TODOforAI app preferences from the shell.",
|
|
45239
|
+
platformAuth: true,
|
|
45240
|
+
description: "The user's TODOforAI app preferences (AppSettings): `list`, `get <key>`, `set key=value …`, `keys` (documented keys). Use when asked to change theme, list style, tool-block density, thinking traces, sounds/toasts, preview columns, wallpaper etc. Values are JSON when parseable. Consent/credential/escalation keys (shellExecution, notifications, analytics, keyboard bindings, vault provider, billing address) are refused from an agent shell — tell the user to change those in Settings.",
|
|
45241
|
+
versionCmd: "tfa-settings --version 2>/dev/null | sed -n 1p",
|
|
45242
|
+
installCmd: "npm install -g @todoforai/tfa-settings",
|
|
45243
|
+
preinstallCloud: true,
|
|
45244
|
+
preinstallJarvis: true
|
|
45245
|
+
},
|
|
45246
|
+
"tfa-memory": {
|
|
45247
|
+
category: "productivity",
|
|
45248
|
+
pkg: "@todoforai/tfa-memory",
|
|
45249
|
+
installer: "npm",
|
|
45250
|
+
label: "Memory",
|
|
45251
|
+
summary: "Your long-term memory of notes, facts and past TODOs.",
|
|
45252
|
+
platformAuth: true,
|
|
45253
|
+
description: 'User\'s long-term memory (notes/procedures/decisions, address `source/ref`) plus every past TODO message (read-only, `todo/<todoId>:<messageId>`). READ: `search "<topic>" --mode fused` first (`lexical` = all words newest first, `semantic` = meaning; `--source todo` / `--todo <id>` narrow). stderr prints `N row(s) contain a query word` — if N exceeds what you saw, page with `--exclude <address>`. `get <address>` = full row, `around <address> --before N --after N` = surrounding dialogue. Before answering from memory, search once more with your draft\'s key facts. WRITE durable facts proactively: `add <source>/<ref> "text"` (same address updates in place; short source names like deploy-notes, preferences). `sources` lists them.',
|
|
45254
|
+
versionCmd: "tfa-memory --version 2>/dev/null | sed -n 1p",
|
|
45255
|
+
installCmd: "npm install -g @todoforai/tfa-memory",
|
|
45256
|
+
preinstallCloud: true,
|
|
45257
|
+
preinstallJarvis: true
|
|
45258
|
+
},
|
|
45259
|
+
"todoregistry-cli": {
|
|
45260
|
+
category: "development",
|
|
45261
|
+
pkg: "@todoforai/todoregistry-cli",
|
|
45262
|
+
installer: "npm",
|
|
45263
|
+
label: "TODO Registry",
|
|
45264
|
+
summary: "Browse ready-made business task templates.",
|
|
45265
|
+
description: "Reusable business task templates (SEO, email, CRM, ads, social, …): `search <q>`, `get <id>`, `list [category]`, `categories`, `create --name … --description … --body @prompt.md`. To recommend a template, don't create a todo directly — `tfa-cli recommend --template <id> --project <projectId>`.",
|
|
45266
|
+
versionCmd: "todoregistry-cli --version 2>/dev/null | sed -n 1p",
|
|
45267
|
+
installCmd: "npm install -g @todoforai/todoregistry-cli",
|
|
45268
|
+
preinstallCloud: true,
|
|
45269
|
+
internal: true,
|
|
45270
|
+
preinstallJarvis: true
|
|
45271
|
+
},
|
|
45272
|
+
"tfa-surface": {
|
|
45273
|
+
preinstallCloud: true,
|
|
45274
|
+
category: "utility",
|
|
45275
|
+
pkg: "@todoforai/tfa-surface",
|
|
45276
|
+
installer: "npm",
|
|
45277
|
+
label: "Surface",
|
|
45278
|
+
summary: "See and control what is on your TODOforAI screen.",
|
|
45279
|
+
platformAuth: true,
|
|
45280
|
+
description: "The user's live UI from the shell. Everything on screen is a SURFACE holding one ref (a todo id, `<todoId>:<alias>` = a shown artifact, or a url). `describe` lists them (kind, id, ref, focus, embedded-browser CDP URL; `--json`). `open overlay <todoId>` (full page), `open window <ref>` (floating), `open panel changes|preview|browser|terminal [--url]` (a todo's side panel), `open card <ref> [--title] [--group <slug>]` (a persisted board card every member sees); `close|focus <kind> <id>`. Persistent state (plans, reports, live status) → `show chat.panel <todoId> \"...md\"` (stdin ok; re-show updates in place), `clear` removes; events go in chat. `card add|list|get|rm <name>` = project HTML renderers. Exit 2 = no frontend connected.",
|
|
45281
|
+
versionCmd: "tfa-surface --version 2>/dev/null | sed -n 1p",
|
|
45282
|
+
installCmd: "npm install -g @todoforai/tfa-surface",
|
|
45283
|
+
internal: true
|
|
45284
|
+
},
|
|
45285
|
+
bun: {
|
|
45286
|
+
commodity: true,
|
|
45287
|
+
category: "development",
|
|
45288
|
+
pkg: "bun",
|
|
45289
|
+
installer: "system",
|
|
45290
|
+
label: "JS/TS Runtime",
|
|
45291
|
+
summary: "Run JavaScript and TypeScript code, fast.",
|
|
45292
|
+
versionCmd: "bun --version 2>/dev/null",
|
|
45293
|
+
preinstallCloud: true,
|
|
45294
|
+
cloudInstallCmd: "export BUN_INSTALL=/usr/local && curl -fsSL https://bun.sh/install | bash && ln -sf /usr/local/bin/bun /usr/local/bin/bunx",
|
|
45295
|
+
cloudVerifyCmd: "bun --version",
|
|
45296
|
+
internal: true,
|
|
45297
|
+
preinstallJarvis: true,
|
|
45298
|
+
description: "Run JavaScript/TypeScript, install packages, run tests (`bun`, `bunx`)."
|
|
45299
|
+
},
|
|
45300
|
+
bunx: {
|
|
45301
|
+
commodity: true,
|
|
45302
|
+
category: "development",
|
|
45303
|
+
pkg: "bunx",
|
|
45304
|
+
installer: "system",
|
|
45305
|
+
label: "Bun Package Runner",
|
|
45306
|
+
summary: "Run a JavaScript package without installing it.",
|
|
45307
|
+
versionCmd: "bunx --version 2>/dev/null",
|
|
45308
|
+
preinstallCloud: true,
|
|
45309
|
+
cloudVerifyCmd: "bunx --version",
|
|
45310
|
+
internal: true,
|
|
45311
|
+
description: "Run package binaries with Bun."
|
|
45312
|
+
},
|
|
45313
|
+
node: {
|
|
45314
|
+
commodity: true,
|
|
45315
|
+
category: "development",
|
|
45316
|
+
pkg: "node",
|
|
45317
|
+
installer: "system",
|
|
45318
|
+
label: "JavaScript Runtime",
|
|
45319
|
+
summary: "Run JavaScript code.",
|
|
45320
|
+
versionCmd: "node -p 'process.version' 2>/dev/null",
|
|
45321
|
+
preinstallCloud: true,
|
|
45322
|
+
cloudInstallCmd: "curl -fsSL https://deb.nodesource.com/setup_24.x | bash -",
|
|
45323
|
+
cloudAptPackages: ["nodejs"],
|
|
45324
|
+
cloudVerifyCmd: "node --version",
|
|
45325
|
+
internal: true,
|
|
45326
|
+
preinstallJarvis: true,
|
|
45327
|
+
description: "Run Node.js scripts."
|
|
45328
|
+
},
|
|
45329
|
+
python3: {
|
|
45330
|
+
commodity: true,
|
|
45331
|
+
category: "development",
|
|
45332
|
+
pkg: "python3",
|
|
45333
|
+
installer: "system",
|
|
45334
|
+
label: "Python",
|
|
45335
|
+
summary: "Run Python code.",
|
|
45336
|
+
versionCmd: "{ python3 --version || python --version || py --version; } 2>/dev/null | sed -n 1p",
|
|
45337
|
+
preinstallCloud: true,
|
|
45338
|
+
cloudAptPackages: ["python3"],
|
|
45339
|
+
cloudVerifyCmd: "python3 --version",
|
|
45340
|
+
internal: true,
|
|
45341
|
+
preinstallJarvis: true,
|
|
45342
|
+
description: "Run Python scripts."
|
|
45343
|
+
},
|
|
45344
|
+
npm: {
|
|
45345
|
+
commodity: true,
|
|
45346
|
+
category: "development",
|
|
45347
|
+
pkg: "npm",
|
|
45348
|
+
installer: "system",
|
|
45349
|
+
label: "Node Package Manager",
|
|
45350
|
+
summary: "Install JavaScript packages.",
|
|
45351
|
+
versionCmd: "npm --version 2>/dev/null",
|
|
45352
|
+
preinstallCloud: true,
|
|
45353
|
+
cloudVerifyCmd: "npm --version",
|
|
45354
|
+
internal: true,
|
|
45355
|
+
description: "Install Node packages and run package scripts."
|
|
45356
|
+
},
|
|
45357
|
+
npx: {
|
|
45358
|
+
commodity: true,
|
|
45359
|
+
category: "development",
|
|
45360
|
+
pkg: "npx",
|
|
45361
|
+
installer: "system",
|
|
45362
|
+
label: "Node Package Runner",
|
|
45363
|
+
summary: "Run a JavaScript package without installing it.",
|
|
45364
|
+
versionCmd: "npx --version 2>/dev/null",
|
|
45365
|
+
preinstallCloud: true,
|
|
45366
|
+
cloudVerifyCmd: "npx --version",
|
|
45367
|
+
internal: true,
|
|
45368
|
+
description: "Run npm package binaries."
|
|
45369
|
+
},
|
|
45370
|
+
pip3: {
|
|
45371
|
+
preinstallCloud: true,
|
|
45372
|
+
cloudAptPackages: ["python3-pip"],
|
|
45373
|
+
cloudVerifyCmd: "pip3 --version",
|
|
45374
|
+
commodity: true,
|
|
45375
|
+
category: "development",
|
|
45376
|
+
pkg: "pip3",
|
|
45377
|
+
installer: "system",
|
|
45378
|
+
label: "Python Package Installer",
|
|
45379
|
+
summary: "Install Python packages.",
|
|
45380
|
+
versionCmd: "pip3 --version 2>/dev/null | sed -n 1p | cut -d' ' -f1-2",
|
|
45381
|
+
internal: true,
|
|
45382
|
+
description: "Install Python packages."
|
|
45383
|
+
},
|
|
45384
|
+
uv: {
|
|
45385
|
+
commodity: true,
|
|
45386
|
+
category: "development",
|
|
45387
|
+
pkg: "uv",
|
|
45388
|
+
installer: "system",
|
|
45389
|
+
label: "Python Package Manager",
|
|
45390
|
+
summary: "Install Python packages and manage environments, fast.",
|
|
45391
|
+
versionCmd: "uv --version 2>/dev/null",
|
|
45392
|
+
preinstallCloud: true,
|
|
45393
|
+
cloudInstallCmd: "curl -LsSf https://astral.sh/uv/0.9.6/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh",
|
|
45394
|
+
cloudVerifyCmd: "uv --version",
|
|
45395
|
+
internal: true,
|
|
45396
|
+
description: "Manage Python dependencies, environments, tools, and scripts (`uv`, `uvx`)."
|
|
45397
|
+
},
|
|
45398
|
+
uvx: {
|
|
45399
|
+
commodity: true,
|
|
45400
|
+
category: "development",
|
|
45401
|
+
pkg: "uvx",
|
|
45402
|
+
installer: "system",
|
|
45403
|
+
label: "Python Tool Runner",
|
|
45404
|
+
summary: "Run a Python tool without installing it.",
|
|
45405
|
+
versionCmd: "uvx --version 2>/dev/null",
|
|
45406
|
+
preinstallCloud: true,
|
|
45407
|
+
cloudVerifyCmd: "uvx --version",
|
|
45408
|
+
internal: true,
|
|
45409
|
+
description: "Run Python tools in isolated environments."
|
|
45410
|
+
},
|
|
45411
|
+
ripgrep: {
|
|
45412
|
+
commodity: true,
|
|
45413
|
+
category: "development",
|
|
45414
|
+
pkg: "ripgrep",
|
|
45415
|
+
installer: "binary",
|
|
45416
|
+
label: "Search",
|
|
45417
|
+
summary: "Search text across files, very fast.",
|
|
45418
|
+
description: "Fast recursive grep with regex, .gitignore-aware, parallel, unicode-correct",
|
|
45419
|
+
versionCmd: "rg --version 2>/dev/null | sed -n 1p",
|
|
45420
|
+
preinstallCloud: true,
|
|
45421
|
+
binary: {
|
|
45422
|
+
"linux-x86_64": {
|
|
45423
|
+
url: "https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz",
|
|
45424
|
+
archive: "tar.gz",
|
|
45425
|
+
extract: "ripgrep-14.1.1-x86_64-unknown-linux-musl/rg"
|
|
45426
|
+
},
|
|
45427
|
+
"linux-aarch64": {
|
|
45428
|
+
url: "https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-aarch64-unknown-linux-gnu.tar.gz",
|
|
45429
|
+
archive: "tar.gz",
|
|
45430
|
+
extract: "ripgrep-14.1.1-aarch64-unknown-linux-gnu/rg"
|
|
45431
|
+
},
|
|
45432
|
+
"darwin-x86_64": {
|
|
45433
|
+
url: "https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-apple-darwin.tar.gz",
|
|
45434
|
+
archive: "tar.gz",
|
|
45435
|
+
extract: "ripgrep-14.1.1-x86_64-apple-darwin/rg"
|
|
45436
|
+
},
|
|
45437
|
+
"darwin-aarch64": {
|
|
45438
|
+
url: "https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-aarch64-apple-darwin.tar.gz",
|
|
45439
|
+
archive: "tar.gz",
|
|
45440
|
+
extract: "ripgrep-14.1.1-aarch64-apple-darwin/rg"
|
|
45441
|
+
},
|
|
45442
|
+
"windows-x86_64": {
|
|
45443
|
+
url: "https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-pc-windows-msvc.zip",
|
|
45444
|
+
archive: "zip",
|
|
45445
|
+
extract: "ripgrep-14.1.1-x86_64-pc-windows-msvc/rg.exe"
|
|
45446
|
+
}
|
|
45447
|
+
},
|
|
45448
|
+
binName: "rg",
|
|
45449
|
+
internal: true,
|
|
45450
|
+
preinstallJarvis: true
|
|
45451
|
+
},
|
|
45452
|
+
"ast-grep": {
|
|
45453
|
+
category: "development",
|
|
45454
|
+
pkg: "ast-grep",
|
|
45455
|
+
installer: "binary",
|
|
45456
|
+
label: "Structural Search",
|
|
45457
|
+
summary: "Search and rewrite code by its structure, not just text.",
|
|
45458
|
+
description: 'Use when regex cannot distinguish syntax from text: `ast-grep -p "foo($$$)" -l ts` finds real calls while ignoring strings and comments; add `--rewrite "..."` for codemods. Prefer `rg` for literal or token search.',
|
|
45459
|
+
versionCmd: "ast-grep --version 2>/dev/null | sed -n 1p",
|
|
45460
|
+
preinstallCloud: true,
|
|
45461
|
+
binary: {
|
|
45462
|
+
"linux-x86_64": {
|
|
45463
|
+
url: "https://github.com/ast-grep/ast-grep/releases/download/0.44.1/app-x86_64-unknown-linux-gnu.zip",
|
|
45464
|
+
archive: "zip",
|
|
45465
|
+
extract: "ast-grep"
|
|
45466
|
+
},
|
|
45467
|
+
"linux-aarch64": {
|
|
45468
|
+
url: "https://github.com/ast-grep/ast-grep/releases/download/0.44.1/app-aarch64-unknown-linux-gnu.zip",
|
|
45469
|
+
archive: "zip",
|
|
45470
|
+
extract: "ast-grep"
|
|
45471
|
+
},
|
|
45472
|
+
"darwin-x86_64": {
|
|
45473
|
+
url: "https://github.com/ast-grep/ast-grep/releases/download/0.44.1/app-x86_64-apple-darwin.zip",
|
|
45474
|
+
archive: "zip",
|
|
45475
|
+
extract: "ast-grep"
|
|
45476
|
+
},
|
|
45477
|
+
"darwin-aarch64": {
|
|
45478
|
+
url: "https://github.com/ast-grep/ast-grep/releases/download/0.44.1/app-aarch64-apple-darwin.zip",
|
|
45479
|
+
archive: "zip",
|
|
45480
|
+
extract: "ast-grep"
|
|
45481
|
+
},
|
|
45482
|
+
"windows-x86_64": {
|
|
45483
|
+
url: "https://github.com/ast-grep/ast-grep/releases/download/0.44.1/app-x86_64-pc-windows-msvc.zip",
|
|
45484
|
+
archive: "zip",
|
|
45485
|
+
extract: "ast-grep.exe"
|
|
45486
|
+
}
|
|
45487
|
+
},
|
|
45488
|
+
binName: "ast-grep",
|
|
45489
|
+
internal: true,
|
|
45490
|
+
preinstallJarvis: true
|
|
45491
|
+
},
|
|
45492
|
+
fd: {
|
|
45493
|
+
commodity: true,
|
|
45494
|
+
category: "development",
|
|
45495
|
+
pkg: "fd-find",
|
|
45496
|
+
installer: "binary",
|
|
45497
|
+
label: "Find Files",
|
|
45498
|
+
summary: "Find files and folders by name.",
|
|
45499
|
+
description: "Fast user-friendly find replacement: regex by default, .gitignore-aware, parallel",
|
|
45500
|
+
versionCmd: "fd --version 2>/dev/null | sed -n 1p",
|
|
45501
|
+
preinstallCloud: true,
|
|
45502
|
+
binary: {
|
|
45503
|
+
"linux-x86_64": {
|
|
45504
|
+
url: "https://github.com/sharkdp/fd/releases/download/v10.2.0/fd-v10.2.0-x86_64-unknown-linux-musl.tar.gz",
|
|
45505
|
+
archive: "tar.gz",
|
|
45506
|
+
extract: "fd-v10.2.0-x86_64-unknown-linux-musl/fd"
|
|
45507
|
+
},
|
|
45508
|
+
"linux-aarch64": {
|
|
45509
|
+
url: "https://github.com/sharkdp/fd/releases/download/v10.2.0/fd-v10.2.0-aarch64-unknown-linux-gnu.tar.gz",
|
|
45510
|
+
archive: "tar.gz",
|
|
45511
|
+
extract: "fd-v10.2.0-aarch64-unknown-linux-gnu/fd"
|
|
45512
|
+
},
|
|
45513
|
+
"darwin-x86_64": {
|
|
45514
|
+
url: "https://github.com/sharkdp/fd/releases/download/v10.2.0/fd-v10.2.0-x86_64-apple-darwin.tar.gz",
|
|
45515
|
+
archive: "tar.gz",
|
|
45516
|
+
extract: "fd-v10.2.0-x86_64-apple-darwin/fd"
|
|
45517
|
+
},
|
|
45518
|
+
"darwin-aarch64": {
|
|
45519
|
+
url: "https://github.com/sharkdp/fd/releases/download/v10.2.0/fd-v10.2.0-aarch64-apple-darwin.tar.gz",
|
|
45520
|
+
archive: "tar.gz",
|
|
45521
|
+
extract: "fd-v10.2.0-aarch64-apple-darwin/fd"
|
|
45522
|
+
},
|
|
45523
|
+
"windows-x86_64": {
|
|
45524
|
+
url: "https://github.com/sharkdp/fd/releases/download/v10.2.0/fd-v10.2.0-x86_64-pc-windows-msvc.zip",
|
|
45525
|
+
archive: "zip",
|
|
45526
|
+
extract: "fd-v10.2.0-x86_64-pc-windows-msvc/fd.exe"
|
|
45527
|
+
}
|
|
45528
|
+
},
|
|
45529
|
+
binName: "fd",
|
|
45530
|
+
internal: true,
|
|
45531
|
+
preinstallJarvis: true
|
|
45532
|
+
},
|
|
45533
|
+
jq: {
|
|
45534
|
+
commodity: true,
|
|
45535
|
+
category: "development",
|
|
45536
|
+
pkg: "jq",
|
|
45537
|
+
installer: "binary",
|
|
45538
|
+
label: "JSON",
|
|
45539
|
+
summary: "Read and reshape JSON data.",
|
|
45540
|
+
description: "Command-line JSON processor: query, filter, transform, format JSON streams",
|
|
45541
|
+
versionCmd: "jq --version 2>/dev/null | sed -n 1p",
|
|
45542
|
+
preinstallCloud: true,
|
|
45543
|
+
binary: {
|
|
45544
|
+
"linux-x86_64": {
|
|
45545
|
+
url: "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64",
|
|
45546
|
+
archive: "raw"
|
|
45547
|
+
},
|
|
45548
|
+
"linux-aarch64": {
|
|
45549
|
+
url: "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-arm64",
|
|
45550
|
+
archive: "raw"
|
|
45551
|
+
},
|
|
45552
|
+
"darwin-x86_64": {
|
|
45553
|
+
url: "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-macos-amd64",
|
|
45554
|
+
archive: "raw"
|
|
45555
|
+
},
|
|
45556
|
+
"darwin-aarch64": {
|
|
45557
|
+
url: "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-macos-arm64",
|
|
45558
|
+
archive: "raw"
|
|
45559
|
+
},
|
|
45560
|
+
"windows-x86_64": {
|
|
45561
|
+
url: "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-windows-amd64.exe",
|
|
45562
|
+
archive: "raw"
|
|
45563
|
+
}
|
|
45564
|
+
},
|
|
45565
|
+
binName: "jq",
|
|
45566
|
+
internal: true,
|
|
45567
|
+
preinstallJarvis: true
|
|
45568
|
+
},
|
|
45569
|
+
patch: {
|
|
45570
|
+
commodity: true,
|
|
45571
|
+
category: "development",
|
|
45572
|
+
pkg: "patch",
|
|
45573
|
+
installer: "system",
|
|
45574
|
+
preinstallCloud: true,
|
|
45575
|
+
label: "Apply Diff",
|
|
45576
|
+
summary: "Apply a diff to files.",
|
|
45577
|
+
description: "Apply unified/context diff patches to files; reverse, dry-run, fuzzy matching",
|
|
45578
|
+
versionCmd: "patch --version 2>/dev/null | sed -n 1p",
|
|
45579
|
+
binName: "patch",
|
|
45580
|
+
internal: true,
|
|
45581
|
+
preinstallJarvis: true
|
|
45582
|
+
},
|
|
45583
|
+
sed: {
|
|
45584
|
+
commodity: true,
|
|
45585
|
+
category: "development",
|
|
45586
|
+
pkg: "sed",
|
|
45587
|
+
installer: "system",
|
|
45588
|
+
preinstallCloud: true,
|
|
45589
|
+
label: "Replace Text",
|
|
45590
|
+
summary: "Find and replace text in files.",
|
|
45591
|
+
description: "Stream editor: in-place text substitution, line filtering, scripted edits",
|
|
45592
|
+
versionCmd: "sed --version 2>/dev/null | sed -n 1p",
|
|
45593
|
+
binName: "sed",
|
|
45594
|
+
internal: true,
|
|
45595
|
+
preinstallJarvis: true
|
|
45596
|
+
},
|
|
45597
|
+
grep: {
|
|
45598
|
+
commodity: true,
|
|
45599
|
+
category: "development",
|
|
45600
|
+
pkg: "grep",
|
|
45601
|
+
installer: "system",
|
|
45602
|
+
preinstallCloud: true,
|
|
45603
|
+
label: "Search Text",
|
|
45604
|
+
summary: "Search for text in files.",
|
|
45605
|
+
description: "Search plain text for lines matching a regex: recursive, fixed-string, context, invert, count",
|
|
45606
|
+
versionCmd: "grep --version 2>/dev/null | sed -n 1p",
|
|
45607
|
+
binName: "grep",
|
|
45608
|
+
internal: true,
|
|
45609
|
+
preinstallJarvis: true
|
|
45610
|
+
},
|
|
45611
|
+
"wordpress-api": {
|
|
45612
|
+
preinstallCloud: true,
|
|
45613
|
+
category: "development",
|
|
45614
|
+
pkg: "@todoforai/wordpress-api",
|
|
45615
|
+
installer: "npm",
|
|
45616
|
+
label: "WordPress",
|
|
45617
|
+
summary: "Read and publish WordPress posts and pages.",
|
|
45618
|
+
statusCmd: `wordpress-api whoami 2>/dev/null | sed -n 's/.*"slug"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
45619
|
+
loginCmd: "wordpress-api auth --site <url> --user <username> --password <app_password>",
|
|
45620
|
+
credentialPaths: ["~/.config/wordpress-api/credentials.json"],
|
|
45621
|
+
description: "WordPress REST API CLI. `wordpress-api auth --site https://example.com --user <user> --password '<application password>'` (application password, not the login password). Reading published content needs no auth. `posts list|get|create|update|delete`, `pages`, `media`, `categories`. `posts create` saves a draft unless --status publish. On Elementor/JetEngine sites content.rendered comes back empty — fetch the post's public URL for the body.",
|
|
45622
|
+
versionCmd: "wordpress-api --version 2>/dev/null | sed -n 1p"
|
|
45623
|
+
},
|
|
45624
|
+
"facebook-pages-api": {
|
|
45625
|
+
preinstallCloud: true,
|
|
45626
|
+
category: "social",
|
|
45627
|
+
pkg: "@todoforai/facebook-pages-api",
|
|
45628
|
+
installer: "npm",
|
|
45629
|
+
label: "Facebook Pages",
|
|
45630
|
+
summary: "Post to your Facebook Page and handle comments.",
|
|
45631
|
+
statusCmd: `facebook-pages-api whoami 2>/dev/null | sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
45632
|
+
loginCmd: "facebook-pages-api auth --page-id <id> --page-token <token>",
|
|
45633
|
+
credentialPaths: ["~/.config/facebook-pages-api/credentials.json"],
|
|
45634
|
+
description: "Facebook Pages CLI (Meta Graph API). `auth --page-id <id> --page-token <token>` (or env FB_PAGE_ID/FB_PAGE_TOKEN). `feed`, `comments`, `insights`, `conversations`, `media`, and `request <GET|POST|DELETE> <path> [--data <json>]` = any Graph edge with the page token attached (use instead of curl). Writes are live: `feed create --published false` for tests; `comments reply` posts publicly — get human approval. Follower totals: `whoami --fields followers_count,fan_count` (many classic insights metrics are retired). `--help` for subcommands.",
|
|
45635
|
+
versionCmd: "facebook-pages-api --version 2>/dev/null | sed -n 1p"
|
|
45636
|
+
},
|
|
45637
|
+
"ews-api": {
|
|
45638
|
+
category: "email",
|
|
45639
|
+
pkg: "ews-api",
|
|
45640
|
+
installer: "pip",
|
|
45641
|
+
label: "Exchange (EWS)",
|
|
45642
|
+
summary: "Read and write mail on a company Exchange server.",
|
|
45643
|
+
statusCmd: `ews-api whoami 2>/dev/null | sed -n 's/.*"email"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
45644
|
+
loginCmd: "ews-api auth --email <email> --username <username> --server <server> --password <password>",
|
|
45645
|
+
credentialPaths: ["~/.config/ews-api/credentials.json"],
|
|
45646
|
+
description: "On-prem Microsoft Exchange mail over EWS (cloud/M365 → outlook-api). `auth --email <e> --username 'DOMAIN\\\\user' --server <host>` (NTLM; password prompt or `--password-stdin`; --server required). Multi-mailbox: `whoami`, `--account <email>`/EWS_ACCOUNT, `default`, `logout`; EWS_EMAIL/EWS_USERNAME/EWS_PASSWORD/EWS_SERVER for unattended runs. `list`, `search <q>`, `read <id>`, `draft`, `reply <id>` — draft/reply stay in Drafts unless --send. Password stored plaintext in ~/.config/ews-api (0600); re-auth after rotation.",
|
|
45647
|
+
versionCmd: "ews-api --version 2>/dev/null | sed -n 1p",
|
|
45648
|
+
logoutCmd: "ews-api logout {{ACCOUNT}}"
|
|
45649
|
+
},
|
|
45650
|
+
"outlook-api": {
|
|
45651
|
+
preinstallCloud: true,
|
|
45652
|
+
category: "email",
|
|
45653
|
+
pkg: "@todoforai/outlook-api",
|
|
45654
|
+
installer: "npm",
|
|
45655
|
+
label: "Outlook (Graph)",
|
|
45656
|
+
summary: "Read and write your Outlook mail.",
|
|
45657
|
+
statusCmd: `outlook-api whoami 2>/dev/null | sed -n 's/.*"userPrincipalName"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
45658
|
+
loginCmd: "outlook-api auth",
|
|
45659
|
+
credentialPaths: ["~/.config/outlook-api/config.json"],
|
|
45660
|
+
description: "Outlook/Hotmail/M365 mail over Microsoft Graph (on-prem Exchange → ews-api). `auth` = device-code flow; `--tenant consumers` (default, personal) | `organizations`. list/search/read/attachments are read-only; `draft`/`reply` stay in Drafts unless --send; `send <draftId>`. `get <path>` = raw Graph GET. JSON out.",
|
|
45661
|
+
versionCmd: "outlook-api --version 2>/dev/null | sed -n 1p",
|
|
45662
|
+
deviceCodePattern: "enter the code ([A-Z0-9]+)",
|
|
45663
|
+
oauthUrlPattern: "(https://(?:www\\.microsoft\\.com/link|login\\.microsoft\\.com/device))",
|
|
45664
|
+
canStreamLogin: true
|
|
45665
|
+
},
|
|
45666
|
+
neonctl: {
|
|
45667
|
+
category: "database",
|
|
45668
|
+
pkg: "neonctl",
|
|
45669
|
+
installer: "npm",
|
|
45670
|
+
label: "Neon Postgres",
|
|
45671
|
+
summary: "Manage your Neon Postgres databases and branches.",
|
|
45672
|
+
statusCmd: `test -f ~/.config/neon/credentials.json && neonctl me --output json 2>/dev/null | sed -n 's/.*"email"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
|
|
45673
|
+
loginCmd: "neonctl auth",
|
|
45674
|
+
oauthUrlPattern: "(https://oauth2\\.neon\\.tech/oauth2/auth\\S+)",
|
|
45675
|
+
credentialPaths: ["~/.config/neon/credentials.json"],
|
|
45676
|
+
description: "Manage Neon Postgres branches and run SQL: `neonctl projects list`, `neonctl branches create`, `neonctl connection-string`. Aliased as `neon`.",
|
|
45677
|
+
versionCmd: "neonctl --version 2>/dev/null | sed -n 1p",
|
|
45678
|
+
aliases: ["neon"],
|
|
45679
|
+
canStreamLogin: true
|
|
45680
|
+
},
|
|
45681
|
+
m365: {
|
|
45682
|
+
preinstallCloud: true,
|
|
45683
|
+
category: "productivity",
|
|
45684
|
+
pkg: "@pnp/cli-microsoft365",
|
|
45685
|
+
installer: "npm",
|
|
45686
|
+
label: "Microsoft 365",
|
|
45687
|
+
summary: "Work with Microsoft 365 mail, Teams, SharePoint and users.",
|
|
45688
|
+
statusCmd: `m365 status --output text 2>/dev/null | tr -d '"' | grep -vi 'logged out' | grep -m1 .`,
|
|
45689
|
+
loginCmd: "m365 login --authType deviceCode --appId 04b07795-8ddb-461a-bbee-02f9e1bf7b46",
|
|
45690
|
+
deviceCodePattern: "enter the code ([A-Z0-9]{8,}) to authenticate",
|
|
45691
|
+
oauthUrlPattern: "open the page (https://\\S+) and enter",
|
|
45692
|
+
credentialPaths: ["~/.cli-m365-msal.json", "~/.cli-m365-connection.json"],
|
|
45693
|
+
description: "Microsoft 365 from the shell: `m365 outlook message list`, `m365 teams team list`, `m365 spo site list`. Device-code login; add `--output json` for parseable output.",
|
|
45694
|
+
versionCmd: `m365 version 2>/dev/null | tr -d '"' | sed -n 1p`
|
|
45695
|
+
},
|
|
45696
|
+
hubspot: {
|
|
45697
|
+
preinstallCloud: true,
|
|
45698
|
+
category: "marketing",
|
|
45699
|
+
pkg: "@hubspot/cli",
|
|
45700
|
+
installer: "npm",
|
|
45701
|
+
label: "HubSpot",
|
|
45702
|
+
summary: "Work with your HubSpot contacts, deals and content.",
|
|
45703
|
+
binName: "hs",
|
|
45704
|
+
statusCmd: "hs account list >/dev/null 2>&1 && echo authenticated",
|
|
45705
|
+
loginCmd: "hs account auth",
|
|
45706
|
+
oauthUrlPattern: "(https://app\\.hubspot\\.com/l/personal-access-key\\S+)",
|
|
45707
|
+
loginNeedsPty: true,
|
|
45708
|
+
credentialPaths: ["~/.hscli/config.yml"],
|
|
45709
|
+
description: "Invoked as `hs`. `hs api <endpoint>` makes authenticated calls to any HubSpot API (contacts, deals, companies) — prefer it over raw curl.",
|
|
45710
|
+
versionCmd: "hs --version 2>/dev/null | sed -n 1p",
|
|
45711
|
+
canStreamLogin: true
|
|
45712
|
+
},
|
|
45713
|
+
"posthog-cli": {
|
|
45714
|
+
preinstallCloud: true,
|
|
45715
|
+
category: "monitoring",
|
|
45716
|
+
pkg: "@posthog/cli",
|
|
45717
|
+
installer: "npm",
|
|
45718
|
+
label: "PostHog",
|
|
45719
|
+
summary: "Query PostHog product analytics and manage feature flags.",
|
|
45720
|
+
statusCmd: `grep -q '"token"' "\${POSTHOG_HOME:-$HOME/.posthog}/credentials.json" 2>/dev/null && echo authenticated`,
|
|
45721
|
+
loginCmd: "posthog-cli login",
|
|
45722
|
+
loginTerminalHint: "Interactive only: run `posthog-cli login` in a terminal on this host (it asks for host, project and a personal API key), or set `POSTHOG_CLI_API_KEY` + `POSTHOG_CLI_PROJECT_ID`.",
|
|
45723
|
+
credentialPaths: ["~/.posthog/credentials.json"],
|
|
45724
|
+
description: "Official PostHog CLI. `posthog-cli api tools` lists the agent-first API tool catalog, `posthog-cli api call <tool> '<json>'` runs one (SQL queries, insights, flags). Also uploads sourcemaps/dSYM. Env alternative: POSTHOG_CLI_API_KEY + POSTHOG_CLI_PROJECT_ID.",
|
|
45725
|
+
versionCmd: "posthog-cli --version 2>/dev/null | sed -n 1p"
|
|
45726
|
+
},
|
|
45727
|
+
canva: {
|
|
45728
|
+
category: "design",
|
|
45729
|
+
pkg: "@canva/cli",
|
|
45730
|
+
installer: "npm",
|
|
45731
|
+
label: "Canva",
|
|
45732
|
+
summary: "Build and deploy Canva apps.",
|
|
45733
|
+
statusCmd: "test -s ~/.canva-cli/credentials && echo authenticated",
|
|
45734
|
+
loginCmd: "canva login --mode manual --lite",
|
|
45735
|
+
loginNeedsPty: true,
|
|
45736
|
+
stdinPaste: true,
|
|
45737
|
+
credentialPaths: ["~/.canva-cli/credentials"],
|
|
45738
|
+
description: "Official Canva CLI — app-development focused: `canva apps create/list/preview`. `canva mcp` starts the Canva Developer MCP server. For design/export automation use the Canva Connect REST API.",
|
|
45739
|
+
versionCmd: "canva --version 2>/dev/null | sed -n 1p",
|
|
45740
|
+
oauthUrlPattern: "OPEN_URL: (https://www\\.canva\\.com/api/oauth/authorize\\S+)"
|
|
45741
|
+
},
|
|
45742
|
+
webflow: {
|
|
45743
|
+
category: "development",
|
|
45744
|
+
pkg: "@webflow/webflow-cli",
|
|
45745
|
+
installer: "npm",
|
|
45746
|
+
label: "Webflow",
|
|
45747
|
+
summary: "Manage Webflow sites, CMS content and assets.",
|
|
45748
|
+
statusCmd: "webflow auth status --skip-update-check >/dev/null 2>&1 && echo authenticated",
|
|
45749
|
+
loginCmd: "webflow auth login --skip-update-check",
|
|
45750
|
+
loginNeedsPty: true,
|
|
45751
|
+
oauthUrlPattern: "(https://webflow\\.com/oauth/webflow/initiate\\S+)",
|
|
45752
|
+
credentialPaths: ["~/.config/webflow"],
|
|
45753
|
+
description: "Manage Webflow sites from the shell: `webflow sites list`, `webflow cms ...`, `webflow assets ...`. Add `--skip-update-check` in scripts.",
|
|
45754
|
+
versionCmd: "webflow --version 2>/dev/null | sed -n 1p"
|
|
45755
|
+
},
|
|
45756
|
+
readwise: {
|
|
45757
|
+
category: "productivity",
|
|
45758
|
+
pkg: "@readwise/cli",
|
|
45759
|
+
installer: "npm",
|
|
45760
|
+
label: "Readwise",
|
|
45761
|
+
summary: "Search and save articles and highlights in Readwise.",
|
|
45762
|
+
statusCmd: "readwise whoami >/dev/null 2>&1 && readwise whoami 2>/dev/null | sed 's/\\x1b\\[[0-9;]*m//g' | grep -m1 .",
|
|
45763
|
+
loginCmd: "readwise login",
|
|
45764
|
+
credentialPaths: ["~/.readwise-cli.json"],
|
|
45765
|
+
description: "Official Readwise/Reader CLI. `readwise search <query>`, `readwise list`, `readwise save <url>`; supports JSON output for piping and a read-only mode for agents. Token login for CI: `readwise login-with-token <token>` (get one at readwise.io/access_token).",
|
|
45766
|
+
versionCmd: "readwise --version 2>/dev/null | sed -n 1p",
|
|
45767
|
+
oauthUrlPattern: "OPEN_URL: (https://readwise\\.io/o/authorize\\S+)",
|
|
45768
|
+
oauthCallbackPort: 6274
|
|
45769
|
+
},
|
|
45770
|
+
granola: {
|
|
45771
|
+
preinstallCloud: true,
|
|
45772
|
+
category: "productivity",
|
|
45773
|
+
pkg: "granola-cli",
|
|
45774
|
+
installer: "npm",
|
|
45775
|
+
binName: "granola",
|
|
45776
|
+
label: "Granola",
|
|
45777
|
+
summary: "Read your Granola meeting notes and transcripts.",
|
|
45778
|
+
statusCmd: `granola auth status -o json 2>/dev/null | sed -n 's/.*"authenticated": *true.*/authenticated/p' | grep -m1 .`,
|
|
45779
|
+
loginCmd: "granola auth login",
|
|
45780
|
+
loginTerminalHint: "Imports the Granola desktop app's session: install Granola on this host, sign in there, then run `granola auth login`.",
|
|
45781
|
+
credentialPaths: ["~/.config/keyring", "~/.config/granola"],
|
|
45782
|
+
versionCmd: "granola --version 2>/dev/null | sed -n 1p",
|
|
45783
|
+
description: "Community Granola CLI (read-only). `granola meeting list [-l N] [--since <date>] [-s <query>] [-a <attendee>] -o json`, `granola meeting notes|enhanced|transcript <id>`, `granola meeting export <id>`; `granola folder list`, `granola workspace list`. `-o json|yaml|toon` for piping. Login imports credentials from the installed Granola desktop app (`granola auth login`) — desktop app must be logged in on the same machine; transcripts need a paid Granola plan."
|
|
45784
|
+
},
|
|
45785
|
+
trello: {
|
|
45786
|
+
preinstallCloud: true,
|
|
45787
|
+
category: "productivity",
|
|
45788
|
+
pkg: "trello-cli",
|
|
45789
|
+
installer: "npm",
|
|
45790
|
+
binName: "trello",
|
|
45791
|
+
label: "Trello",
|
|
45792
|
+
summary: "Manage your Trello boards, lists and cards.",
|
|
45793
|
+
statusCmd: "trello board:list --format json </dev/null >/dev/null 2>&1 && echo authenticated",
|
|
45794
|
+
loginCmd: "trello auth:api-key <key> && trello auth:token <token>",
|
|
45795
|
+
credentialPaths: [
|
|
45796
|
+
"~/.trello-cli"
|
|
45797
|
+
],
|
|
45798
|
+
versionCmd: "trello --version 2>/dev/null | sed -n 1p",
|
|
45799
|
+
description: "Community Trello CLI (mheap/trello-cli, no official one exists). Auth is a Trello API key + token from https://trello.com/app-key — `trello auth:api-key <key>` then `trello auth:token <token>`. `board:list`, `list:list --board <name>`, `card:list --board <b> --list <l>`, `card:create --board <b> --list <l> --name <n> [--description ..] [--due <date>]`, `card:move`, `card:comment`, `label:*`, `search <q>`. Add `--format json` for piping. Names resolve via a local cache; run `trello board:list` once after login to warm it."
|
|
45800
|
+
},
|
|
45801
|
+
mapps: {
|
|
45802
|
+
category: "development",
|
|
45803
|
+
pkg: "@mondaycom/apps-cli",
|
|
45804
|
+
installer: "npm",
|
|
45805
|
+
label: "monday.com",
|
|
45806
|
+
summary: "Build and deploy monday.com apps.",
|
|
45807
|
+
statusCmd: "grep -qsE '[A-Za-z0-9]' ~/.config/mapps/.mappsrc ~/.mappsrc && echo authenticated",
|
|
45808
|
+
loginCmd: "mapps init -t <api_token>",
|
|
45809
|
+
credentialPaths: ["~/.config/mapps/.mappsrc", "~/.mappsrc"],
|
|
45810
|
+
description: "Invoked as `mapps` — app development and monday-code deployments only; `mapps init -t <token>` stores a monday.com API token in ~/.mappsrc. To read/write board DATA use the monday.com GraphQL API (api.monday.com/v2) with that same token.",
|
|
45811
|
+
versionCmd: "mapps --version 2>/dev/null | sed -n 1p"
|
|
45812
|
+
},
|
|
45813
|
+
"exa-cli": {
|
|
45814
|
+
preinstallCloud: true,
|
|
45815
|
+
category: "utility",
|
|
45816
|
+
pkg: "exa-cli",
|
|
45817
|
+
installer: "npm",
|
|
45818
|
+
label: "Exa Search",
|
|
45819
|
+
summary: "Search the web and pull page contents, built for AI.",
|
|
45820
|
+
binName: "exa",
|
|
45821
|
+
statusCmd: 'test -n "$EXA_API_KEY" && echo authenticated',
|
|
45822
|
+
credentialPaths: [],
|
|
45823
|
+
description: "Invoked as `exa`. `exa search <query>`, `exa answer <question>`, `exa contents <url>`, `exa find-similar <url>` — JSON by default. Needs EXA_API_KEY in the environment (get one at dashboard.exa.ai); store it in the vault.",
|
|
45824
|
+
versionCmd: "exa --version 2>/dev/null | sed -n 1p"
|
|
45825
|
+
},
|
|
45826
|
+
mobbin: {
|
|
45827
|
+
category: "design",
|
|
45828
|
+
pkg: "mobbin",
|
|
45829
|
+
installer: "npm",
|
|
45830
|
+
label: "Mobbin",
|
|
45831
|
+
summary: "Browse real app and website design examples.",
|
|
45832
|
+
statusCmd: "mobbin auth print-cookie 2>/dev/null | grep -E '[A-Za-z0-9]' >/dev/null && echo authenticated",
|
|
45833
|
+
loginCmd: "mobbin auth save-cookie",
|
|
45834
|
+
loginTerminalHint: "Log in to mobbin.com in a browser on this host, then run `mobbin auth save-cookie`: it imports that browser's cookies.",
|
|
45835
|
+
credentialPaths: ["~/.config/mobbin/cookie.txt", "~/.config/mobbin/storage-state.json"],
|
|
45836
|
+
description: 'Unofficial CLI over Mobbin\'s undocumented web endpoints. `mobbin search --query "login" --platform ios`. Auth reuses browser cookies: log into mobbin.com in Chrome, then `mobbin auth save-cookie`.',
|
|
45837
|
+
versionCmd: "mobbin --version 2>/dev/null | sed -n '1,2p' | tr '\\n' ' '"
|
|
45838
|
+
},
|
|
45839
|
+
"blender-mcp": {
|
|
45840
|
+
preinstallCloud: true,
|
|
45841
|
+
packages: ["blender-mcp==1.9.1"],
|
|
45842
|
+
category: "design",
|
|
45843
|
+
pkg: "blender-mcp",
|
|
45844
|
+
installer: "pip",
|
|
45845
|
+
label: "Blender",
|
|
45846
|
+
summary: "Model, texture and render 3D scenes in a running Blender.",
|
|
45847
|
+
statusCmd: `command -v blender-mcp >/dev/null && mcporter call blender.get_addon_status --output json 2>/dev/null | grep -o '"blender_version": "[^"]*"' | grep -m1 .`,
|
|
45848
|
+
loginNoBrowser: true,
|
|
45849
|
+
loginTerminalHint: "Needs Blender (blender.org) open on this host: in Blender, Edit → Preferences → Add-ons, enable `Blender MCP`, then press N in the 3D view → BlenderMCP tab → Connect / Start MCP server. Then press Connect here.",
|
|
45850
|
+
loginCmd: `blender-mcp install-addon >/dev/null 2>&1; command -v mcporter >/dev/null 2>&1 || npm install -g --prefix "$HOME/.local" mcporter; mcporter config add blender --command blender-mcp --env BLENDER_MCP_DISABLE_TELEMETRY=1 --description 'Blender 3D via ahujasid/blender-mcp addon' --scope home`,
|
|
45851
|
+
logoutCmd: "cd ~ && mcporter config remove blender",
|
|
45852
|
+
credentialPaths: ["~/.mcporter/mcporter.json"],
|
|
45853
|
+
description: "Blender 3D via the ahujasid/blender-mcp server through mcporter: `mcporter list blender --schema`, `mcporter call blender.<tool> key=value` (`code=@file.py`; every tool needs `user_prompt`). Workhorse: execute_blender_code (any bpy Python); also scene/object info, viewport screenshot (`--save-images <dir>`), PolyHaven/Sketchfab import. Needs a GUI Blender with the addon server started (socket :9876; headless has none). 'Could not connect' → `blender-mcp install-addon`, enable in Preferences → Add-ons, N-panel → Start MCP Server (scripted: `blender --python s.py`, s.py registers a `bpy.app.timers` calling `bpy.ops.blendermcp.start_server()`). Code runs unguarded: save first (`bpy.ops.wm.save_mainfile()`), approve destructive ops.",
|
|
45854
|
+
versionCmd: `{ python -c 'from importlib.metadata import version; print(version("blender-mcp"))' || python3 -c 'from importlib.metadata import version; print(version("blender-mcp"))'; } 2>/dev/null`
|
|
45855
|
+
},
|
|
45856
|
+
"google-ads": {
|
|
45857
|
+
category: "marketing",
|
|
45858
|
+
pkg: "google-ads",
|
|
45859
|
+
packages: [
|
|
45860
|
+
"google-ads==32.0.0"
|
|
45861
|
+
],
|
|
45862
|
+
installer: "pip",
|
|
45863
|
+
label: "Google Ads",
|
|
45864
|
+
summary: "Query and manage Google Ads campaigns, keywords and conversions.",
|
|
45865
|
+
loginCmd: `printf 'developer_token: %s\\nclient_id: %s\\nclient_secret: %s\\nrefresh_token: %s\\nlogin_customer_id: %s\\nuse_proto_plus: true\\n' <developer_token> <client_id> <client_secret> <refresh_token> <mcc_id_digits_only> > "$HOME/google-ads.yaml" && python3 -c 'from google.ads.googleads.client import GoogleAdsClient; GoogleAdsClient.load_from_storage(); print("ok")'`,
|
|
45866
|
+
credentialPaths: [
|
|
45867
|
+
"~/google-ads.yaml"
|
|
45868
|
+
],
|
|
45869
|
+
statusCmd: `python3 -c 'from google.ads.googleads.client import GoogleAdsClient; c=GoogleAdsClient.load_from_storage(); print(c.login_customer_id or "authenticated")' 2>/dev/null | grep -m1 .`,
|
|
45870
|
+
versionCmd: "python3 -c 'import google.ads.googleads as g; print(g.VERSION)' 2>/dev/null",
|
|
45871
|
+
cloudVerifyCmd: "python3 -c 'import google.ads.googleads'",
|
|
45872
|
+
description: "Official Google Ads API client library (Python) — there is no official CLI, so call it via `python3 -c` or a script. Config `~/google-ads.yaml` (developer_token, client_id/secret, refresh_token, login_customer_id = MCC digits). Mint refresh_token with the bundled `google-oauthlib-tool --client-secrets <json> --scope https://www.googleapis.com/auth/adwords --save --headless` (or examples/authentication/generate_user_credentials.py). Read: `client.get_service('GoogleAdsService').search_stream(customer_id=<digits>, query=<GAQL>)`. Write: `<X>Service.mutate_<x>s(customer_id, operations, validate_only=True)` first, then real. Keyword ideas: `KeywordPlanIdeaService.generate_keyword_ideas`. Offline conversions: `ConversionUploadService.upload_click_conversions`. Customer ids are digits without dashes."
|
|
45873
|
+
},
|
|
45874
|
+
"cua-driver": {
|
|
45875
|
+
category: "development",
|
|
45876
|
+
pkg: "cua-driver",
|
|
45877
|
+
installer: "system",
|
|
45878
|
+
label: "Desktop Control",
|
|
45879
|
+
summary: "Click, type and read native desktop apps without taking over the mouse or focus.",
|
|
45880
|
+
installCmd: 'curl -fsSL https://cua.ai/driver/install.sh | CUA_DRIVER_NO_MODIFY_PATH=1 CUA_DRIVER_BIN_DIR="$HOME/.todoforai/tools/bin" bash',
|
|
45881
|
+
uninstallCmd: 'curl -fsSL https://cua.ai/driver/uninstall.sh | bash; rm -f "$HOME/.todoforai/tools/bin/cua-driver" "$HOME/.todoforai/tools/bin/cua-cursor-theme"; hash -r 2>/dev/null; ! command -v cua-driver >/dev/null 2>&1 || { echo "cua-driver is still on PATH: $(command -v cua-driver)"; exit 1; }',
|
|
45882
|
+
installCmdWindows: "powershell.exe -NoProfile -ExecutionPolicy Bypass -Command '$ProgressPreference='\\''SilentlyContinue'\\''; $ErrorActionPreference='\\''Stop'\\''; [Net.ServicePointManager]::SecurityProtocol=[Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12; $t=Join-Path $env:USERPROFILE '\\''.todoforai\\tools'\\''; $d=Join-Path $t '\\''bin'\\''; New-Item -ItemType Directory -Force -Path $d | Out-Null; $env:CUA_DRIVER_RS_INSTALL_DIR=Join-Path $t '\\''cua-driver\\bin'\\''; $f=Join-Path $env:TEMP '\\''cua-driver-install.ps1'\\''; Invoke-RestMethod -UseBasicParsing https://cua.ai/driver/install.ps1 | Set-Content -LiteralPath $f -Encoding UTF8; & $f -NoAutoStart -NoPathUpdate; if($LASTEXITCODE){exit $LASTEXITCODE}; $u=New-Object Text.UTF8Encoding $false; [IO.File]::WriteAllText((Join-Path $d '\\''cua-driver'\\''), \"#!/bin/sh`nexec `\"`$(dirname `\"`$0`\")/../cua-driver/bin/cua-driver.exe`\" `\"`$@`\"`n\", $u); [IO.File]::WriteAllText((Join-Path $d '\\''cua-driver.cmd'\\''), \"@echo off`r`n`\"%~dp0..\\cua-driver\\bin\\cua-driver.exe`\" %*`r`n\", $u)'",
|
|
45883
|
+
uninstallCmdWindows: "powershell.exe -NoProfile -ExecutionPolicy Bypass -Command '$ErrorActionPreference='\\''Continue'\\''; $t=Join-Path $env:USERPROFILE '\\''.todoforai\\tools'\\''; $d=Join-Path $t '\\''bin'\\''; $j=Join-Path $t '\\''cua-driver\\bin'\\''; $exe=Join-Path $j '\\''cua-driver.exe'\\''; if(Test-Path -LiteralPath $exe){& $exe stop 2>$null | Out-Null}; Stop-Process -Name cua-driver -Force -ErrorAction SilentlyContinue; $env:CUA_DRIVER_RS_UNINSTALL_FORCE='\\''1'\\''; $env:CUA_DRIVER_RS_INSTALL_DIR=$j; Invoke-RestMethod -UseBasicParsing https://cua.ai/driver/uninstall.ps1 | Invoke-Expression; Remove-Item -Force -ErrorAction SilentlyContinue (Join-Path $d '\\''cua-driver'\\''), (Join-Path $d '\\''cua-driver.cmd'\\''); if(Test-Path -LiteralPath $j){[IO.Directory]::Delete($j,$false)}; Remove-Item -Recurse -Force -ErrorAction SilentlyContinue (Join-Path $t '\\''cua-driver'\\'')'",
|
|
45884
|
+
versionCmd: "cua-driver --version 2>/dev/null | sed -n 1p",
|
|
45885
|
+
description: 'Native desktop automation (macOS/Windows/Linux X11; Wayland only via AT-SPI, no window screenshots) through the accessibility tree — actions land in the BACKGROUND without moving the user\'s focus or pointer. Needs a daemon: `cua-driver status || (cua-driver serve --no-overlay >/dev/null 2>&1 &)`; on macOS grant permissions first with `cua-driver permissions grant`; on Windows the daemon must run in the interactive desktop session (`cua-driver autostart enable` registers a logon task). Loop: `cua-driver call list_windows \'{}\'` → pid+window_id; `cua-driver call get_window_state \'{"pid":P,"window_id":W,"include_screenshot":false}\'` → `elements[]` with `element_token`; act with `cua-driver call click \'{"pid":P,"window_id":W,"element_token":"s..:N"}\'`, `type_text {..,"text":".."}`, `hotkey {..,"keys":["ctrl","s"]}`, `press_key`, `scroll`, `invoke_menu`. Tokens are snapshot-bound: re-run get_window_state after EVERY action (stale token = refusal). Window screenshot: add `--screenshot-out-file out.png` (`max_dimension` to shrink). Responses say `effect:unverifiable` — verify from a fresh tree, not from the click reply. `delivery_mode:"foreground"` steals focus; use only when asked. Chrome/Electron trees are near-empty — use agent-browser for web pages. `cua-driver list-tools` / `describe <tool>` for the full surface; `cua-driver mcp` exposes the same over stdio MCP.'
|
|
45886
|
+
}
|
|
45887
|
+
};
|
|
45888
|
+
|
|
45889
|
+
// ../packages/shared-fbe/src/toolCatalog.ts
|
|
45890
|
+
var TOOL_CATALOG = tool_catalog_default;
|
|
45891
|
+
// ../packages/shared-fbe/src/toolInstallCommand.ts
|
|
45892
|
+
var KEY_OF = new Map(Object.entries(TOOL_CATALOG).map(([k, e]) => [e, k]));
|
|
45893
|
+
var NODE_MIN_MAJOR = 24;
|
|
45894
|
+
var NODE_OK = `command -v npm >/dev/null 2>&1 && node -e 'process.exit(+process.versions.node.split(".")[0]>=${NODE_MIN_MAJOR}?0:1)' >/dev/null 2>&1`;
|
|
45895
|
+
// ../packages/shared-fbe/src/model_promos.json
|
|
44396
45896
|
var model_promos_default = {
|
|
44397
45897
|
_doc: [
|
|
44398
45898
|
"Single source of truth for TODOforAI promotional model discounts.",
|
|
@@ -44434,10 +45934,10 @@ var model_promos_default = {
|
|
|
44434
45934
|
]
|
|
44435
45935
|
};
|
|
44436
45936
|
|
|
44437
|
-
//
|
|
45937
|
+
// ../packages/shared-fbe/src/modelPromos.ts
|
|
44438
45938
|
var BOOST_FACTOR = model_promos_default.boost_remaining_price_factor;
|
|
44439
45939
|
var MODEL_PROMOS = model_promos_default.promos;
|
|
44440
|
-
//
|
|
45940
|
+
// ../packages/shared-fbe/src/realtime/topics.ts
|
|
44441
45941
|
var TOPICS = {
|
|
44442
45942
|
["todo:new" /* NEW_TODO */]: {
|
|
44443
45943
|
channel: (p) => SERVER_TO_FRONTENDS.project.new_todo(p.projectId, p.privateOwnerId),
|
|
@@ -44604,12 +46104,12 @@ var TOPICS = {
|
|
|
44604
46104
|
audience: "frontend"
|
|
44605
46105
|
}
|
|
44606
46106
|
};
|
|
44607
|
-
//
|
|
46107
|
+
// ../packages/shared-fbe/src/modelNames.ts
|
|
44608
46108
|
var LEGACY_MODEL_MAPPING = {
|
|
44609
46109
|
claude: DEFAULT_MODEL.slice(DEFAULT_MODEL.indexOf(":") + 1),
|
|
44610
46110
|
"gemini-pro": "google/gemini-3.1-pro-preview"
|
|
44611
46111
|
};
|
|
44612
|
-
//
|
|
46112
|
+
// ../packages/shared-credentials/src/index.ts
|
|
44613
46113
|
function normalizeApiUrl2(url) {
|
|
44614
46114
|
if (url.startsWith("localhost"))
|
|
44615
46115
|
return `http://${url}`;
|
|
@@ -44623,7 +46123,7 @@ import { parseArgs } from "util";
|
|
|
44623
46123
|
// package.json
|
|
44624
46124
|
var package_default = {
|
|
44625
46125
|
name: "@todoforai/cli",
|
|
44626
|
-
version: "0.1.
|
|
46126
|
+
version: "0.1.57",
|
|
44627
46127
|
type: "module",
|
|
44628
46128
|
bin: {
|
|
44629
46129
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -44693,7 +46193,7 @@ Examples:
|
|
|
44693
46193
|
tfa-cli recommend --template <id> # Add a template as a recommendation card
|
|
44694
46194
|
tfa-cli inbox [needs-you|messages|activity] [--unread] # Read the notification feed (the bell)
|
|
44695
46195
|
tfa-cli inbox seen [tab] # Mark notifications read
|
|
44696
|
-
tfa-cli notify "Title" "message" [--href /t/<id>] # Note to
|
|
46196
|
+
tfa-cli notify [--to <email>] "Title" "message" [--href /t/<id>] # Note to your own user, or --to a project member (Messages tab + phone push)
|
|
44697
46197
|
tfa-cli claim mint --seed <projectId> [--emails a@x,b@y] [--ttl <sec>] # Mint /claim/<token> links for a project you own
|
|
44698
46198
|
tfa-cli next [--direction "<text>"] # Analyzer growth recommendation cards
|
|
44699
46199
|
tfa-cli <command> help # Details per command
|
|
@@ -44811,6 +46311,7 @@ function parseCliArgs() {
|
|
|
44811
46311
|
ttl: { type: "string" },
|
|
44812
46312
|
subject: { type: "string" },
|
|
44813
46313
|
href: { type: "string" },
|
|
46314
|
+
to: { type: "string" },
|
|
44814
46315
|
unread: { type: "boolean", default: false },
|
|
44815
46316
|
limit: { type: "string" },
|
|
44816
46317
|
resume: { type: "string", short: "r" },
|
|
@@ -48031,6 +49532,7 @@ tfa-cli project — edit the current project
|
|
|
48031
49532
|
|
|
48032
49533
|
Usage:
|
|
48033
49534
|
tfa-cli project list Projects you can access (* = default)
|
|
49535
|
+
tfa-cli project members Who is on it (notify --to <email> reaches them)
|
|
48034
49536
|
tfa-cli project set <field=value>… name=… description=…
|
|
48035
49537
|
(isPublic refused from an agent shell)
|
|
48036
49538
|
tfa-cli project default Make it the project you land on at /
|
|
@@ -48132,6 +49634,17 @@ async function projectCommand(api, positionals, args, projectId) {
|
|
|
48132
49634
|
}
|
|
48133
49635
|
if (!projectId)
|
|
48134
49636
|
fail(NO_PROJECT);
|
|
49637
|
+
if (sub === "members") {
|
|
49638
|
+
const members = await api.getProjectMembers(projectId);
|
|
49639
|
+
if (args.json) {
|
|
49640
|
+
console.log(JSON.stringify(members, null, 2));
|
|
49641
|
+
return;
|
|
49642
|
+
}
|
|
49643
|
+
for (const m of members)
|
|
49644
|
+
process.stderr.write(` ${m.name ?? ""} ${m.email ?? ""} ${DIM}${m.id}${RESET}
|
|
49645
|
+
`);
|
|
49646
|
+
return;
|
|
49647
|
+
}
|
|
48135
49648
|
if (sub === "set") {
|
|
48136
49649
|
if (!rest.length)
|
|
48137
49650
|
fail("Usage: tfa-cli project set <field=value>…");
|
|
@@ -49064,16 +50577,19 @@ Filters (same as the bell's chips):
|
|
|
49064
50577
|
}
|
|
49065
50578
|
function printNotifyHelp() {
|
|
49066
50579
|
process.stderr.write(`
|
|
49067
|
-
tfa-cli notify — leave a note
|
|
50580
|
+
tfa-cli notify — leave a note in someone's Messages inbox (+ phone push)
|
|
49068
50581
|
|
|
49069
50582
|
Usage:
|
|
49070
50583
|
tfa-cli notify "Title" "message" [--href /t/<todo-id>] [--subject <key>] [--json]
|
|
50584
|
+
tfa-cli notify --to <email> "Title" "message" [--project <id>]
|
|
49071
50585
|
echo "message" | tfa-cli notify "Title"
|
|
49072
50586
|
|
|
49073
|
-
Recipient:
|
|
49074
|
-
|
|
50587
|
+
Recipient: your own user by default. --to <email> reaches a TEAMMATE: someone who is a member
|
|
50588
|
+
of the current project (--project, $TODOFORAI_PROJECT_ID or your default), shown as from you.
|
|
50589
|
+
Anyone else is refused. List them with: tfa-cli project members
|
|
49075
50590
|
--subject dedupes: the same subject is delivered once (default: hash of title+message,
|
|
49076
|
-
so a retry never double-notifies). --href must be an in-app path.
|
|
50591
|
+
so a retry never double-notifies). --href must be an in-app path.
|
|
50592
|
+
Limits: 10 notes/day to yourself, 20/day to teammates.
|
|
49077
50593
|
`);
|
|
49078
50594
|
}
|
|
49079
50595
|
function tierArg(name) {
|
|
@@ -49125,12 +50641,22 @@ async function inboxCommand(api, positionals, args) {
|
|
|
49125
50641
|
console.log(` ${DIM}${e.href}${RESET}`);
|
|
49126
50642
|
}
|
|
49127
50643
|
}
|
|
49128
|
-
var
|
|
49129
|
-
async function notifyCommand(api, positionals, args) {
|
|
49130
|
-
const
|
|
49131
|
-
const bad = argv.find((a) => RECIPIENT_FLAGS.some((f) => a === f || a.startsWith(`${f}=`)));
|
|
50644
|
+
var OTHER_RECIPIENT_FLAGS = ["--email", "--user", "--recipient", "--cc"];
|
|
50645
|
+
async function notifyCommand(api, positionals, args, projectId) {
|
|
50646
|
+
const bad = process.argv.slice(2).find((a) => OTHER_RECIPIENT_FLAGS.some((f) => a === f || a.startsWith(`${f}=`)));
|
|
49132
50647
|
if (bad) {
|
|
49133
|
-
process.stderr.write(`${RED}
|
|
50648
|
+
process.stderr.write(`${RED}Unknown option ${bad.split("=")[0]}: use --to <email> for a project teammate${RESET}
|
|
50649
|
+
`);
|
|
50650
|
+
process.exit(2);
|
|
50651
|
+
}
|
|
50652
|
+
const to = args.to === undefined ? undefined : String(args.to).trim();
|
|
50653
|
+
if (to === "") {
|
|
50654
|
+
process.stderr.write(`${RED}--to is empty: pass a teammate's email, or drop --to to notify your own user${RESET}
|
|
50655
|
+
`);
|
|
50656
|
+
process.exit(2);
|
|
50657
|
+
}
|
|
50658
|
+
if (to && !projectId) {
|
|
50659
|
+
process.stderr.write(`${RED}--to needs a project: pass --project <id> (the recipient must be a member of it)${RESET}
|
|
49134
50660
|
`);
|
|
49135
50661
|
process.exit(2);
|
|
49136
50662
|
}
|
|
@@ -49142,12 +50668,13 @@ async function notifyCommand(api, positionals, args) {
|
|
|
49142
50668
|
}
|
|
49143
50669
|
const subject = args.subject || createHash("sha256").update(`${title}
|
|
49144
50670
|
${message}`).digest("hex").slice(0, 16);
|
|
49145
|
-
const
|
|
50671
|
+
const msg = { subject, title, message, ...args.href ? { href: String(args.href) } : {} };
|
|
50672
|
+
const row = await (to ? api.sendMemberMessage({ ...msg, projectId, to }) : api.sendFeedMessage(msg));
|
|
49146
50673
|
if (args.json) {
|
|
49147
50674
|
console.log(JSON.stringify(row));
|
|
49148
50675
|
return;
|
|
49149
50676
|
}
|
|
49150
|
-
process.stderr.write(row.created !== false ? `${GREEN}✅ Delivered to your own user's Messages inbox
|
|
50677
|
+
process.stderr.write(row.created !== false ? `${GREEN}✅ Delivered to ${to ?? "your own user"}'s Messages inbox${RESET} ${DIM}(subject ${subject})${RESET}
|
|
49151
50678
|
` : `${DIM}Already sent (subject ${subject}) — nothing new delivered${RESET}
|
|
49152
50679
|
`);
|
|
49153
50680
|
}
|
|
@@ -73860,7 +75387,7 @@ async function main() {
|
|
|
73860
75387
|
return;
|
|
73861
75388
|
}
|
|
73862
75389
|
if (positionals[0] === "notify") {
|
|
73863
|
-
await notifyCommand(api2, positionals, args);
|
|
75390
|
+
await notifyCommand(api2, positionals, args, scopedProject);
|
|
73864
75391
|
return;
|
|
73865
75392
|
}
|
|
73866
75393
|
if (positionals[0] === "delete") {
|