teak-cli 1.0.51 → 1.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +48 -0
  2. package/dist/index.js +100 -15
  3. package/package.json +20 -3
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Teak CLI
2
+
3
+ Command-line client for [Teak](https://teakvault.com), the personal knowledge hub for saving and rediscovering ideas, links, files, notes, and references.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g teak-cli
9
+ ```
10
+
11
+ ```bash
12
+ teak --version
13
+ ```
14
+
15
+ ## Sign In
16
+
17
+ ```bash
18
+ teak login
19
+ ```
20
+
21
+ The CLI opens Teak in your browser and stores the resulting session securely in macOS Keychain when available. You can also use an API key:
22
+
23
+ ```bash
24
+ teak --api-key teakapi_... cards list
25
+ ```
26
+
27
+ ## Common Commands
28
+
29
+ ```bash
30
+ teak add "Design note from today's review" --tags design,research
31
+ teak add --url https://example.com --tags reference
32
+ teak add --file ./screenshot.png --notes "Homepage inspiration"
33
+ teak search "homepage inspiration"
34
+ teak cards list --type link --limit 20
35
+ teak cards get <card-id>
36
+ teak cards update <card-id> --tags design,approved
37
+ teak fav <card-id>
38
+ teak rm <card-id>
39
+ teak tags
40
+ ```
41
+
42
+ Use `--json` on any command for script-friendly output.
43
+
44
+ ## Docs
45
+
46
+ - CLI guide: [teakvault.com/docs/cli](https://teakvault.com/docs/cli)
47
+ - API docs: [teakvault.com/docs/api](https://teakvault.com/docs/api)
48
+ - MCP docs: [teakvault.com/docs/mcp](https://teakvault.com/docs/mcp)
package/dist/index.js CHANGED
@@ -4,8 +4,8 @@
4
4
  import { readFileSync as readFileSync3, realpathSync } from "node:fs";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
- // ../../packages/sdk/src/index.ts
8
- var CARD_TYPES = [
7
+ // ../../packages/convex/shared/constants.ts
8
+ var cardTypes = [
9
9
  "text",
10
10
  "link",
11
11
  "image",
@@ -15,6 +15,61 @@ var CARD_TYPES = [
15
15
  "palette",
16
16
  "quote"
17
17
  ];
18
+ var MAX_FILE_SIZE = 20 * 1024 * 1024;
19
+ var CARD_TYPES = [...cardTypes];
20
+ var CARD_TYPE_REGISTRY = {
21
+ text: {
22
+ label: "Text",
23
+ icon: "FileText",
24
+ searchLabel: "Text"
25
+ },
26
+ link: {
27
+ label: "Link",
28
+ icon: "Link",
29
+ searchLabel: "Links"
30
+ },
31
+ image: {
32
+ label: "Image",
33
+ icon: "Image",
34
+ searchLabel: "Images"
35
+ },
36
+ video: {
37
+ label: "Video",
38
+ icon: "Video",
39
+ searchLabel: "Videos"
40
+ },
41
+ audio: {
42
+ label: "Audio",
43
+ icon: "Volume2",
44
+ searchLabel: "Audio"
45
+ },
46
+ document: {
47
+ label: "Document",
48
+ icon: "File",
49
+ searchLabel: "Documents"
50
+ },
51
+ palette: {
52
+ label: "Palette",
53
+ icon: "Palette",
54
+ searchLabel: "Palettes"
55
+ },
56
+ quote: {
57
+ label: "Quote",
58
+ icon: "Quote",
59
+ searchLabel: "Quotes"
60
+ }
61
+ };
62
+ var RESERVED_KEYWORDS = [
63
+ ...cardTypes.map((cardType) => ({
64
+ value: cardType,
65
+ label: CARD_TYPE_REGISTRY[cardType].searchLabel
66
+ })),
67
+ { value: "favorites", label: "Favorites" },
68
+ { value: "trash", label: "Trash" }
69
+ ];
70
+
71
+ // ../../packages/convex/client/sdk.ts
72
+ var CARD_TYPES2 = cardTypes;
18
73
  var ERROR_CODES = [
19
74
  "AUTH_REQUIRED",
20
75
  "BAD_REQUEST",
@@ -73,6 +128,21 @@ var normalizeLimit = (limit) => {
73
128
  }
74
129
  return Math.max(1, Math.min(Math.trunc(limit ?? 50), 100));
75
130
  };
131
+ var byteLengthForBody = (bytes) => {
132
+ if (bytes instanceof ArrayBuffer) {
133
+ return bytes.byteLength;
134
+ }
135
+ if (ArrayBuffer.isView(bytes)) {
136
+ return bytes.byteLength;
137
+ }
138
+ if (typeof Blob !== "undefined" && bytes instanceof Blob) {
139
+ return bytes.size;
140
+ }
141
+ if (typeof bytes === "string") {
142
+ return new TextEncoder().encode(bytes).byteLength;
143
+ }
144
+ return null;
145
+ };
76
146
  var buildCardsSearchParams = (input) => {
77
147
  const search = new URLSearchParams;
78
148
  if (input.query?.trim()) {
@@ -239,9 +309,14 @@ var createTeakClient = (options) => {
239
309
  uploads: {
240
310
  create: (input) => request("/v1/uploads", { body: JSON.stringify(input), method: "POST" }, asUpload),
241
311
  putFile: async (uploadUrl, bytes, mimeType) => {
312
+ const headers = new Headers({ "Content-Type": mimeType });
313
+ const byteLength = byteLengthForBody(bytes);
314
+ if (byteLength !== null) {
315
+ headers.set("Content-Length", String(byteLength));
316
+ }
242
317
  const response = await fetchImpl(uploadUrl, {
243
318
  body: bytes,
244
- headers: { "Content-Type": mimeType },
319
+ headers,
245
320
  method: "PUT"
246
321
  });
247
322
  if (!response.ok) {
@@ -252,7 +327,7 @@ var createTeakClient = (options) => {
252
327
  };
253
328
  };
254
329
  var parseTags = (value) => value === undefined ? undefined : Array.from(new Set(value.split(",").map((tag) => tag.trim()).filter(Boolean)));
255
- var isCardType = (value) => CARD_TYPES.includes(value);
330
+ var isCardType = (value) => CARD_TYPES2.includes(value);
256
331
 
257
332
  // ../../node_modules/commander/lib/error.js
258
333
  class CommanderError extends Error {
@@ -2327,6 +2402,7 @@ var VERSION = readPackageVersion();
2327
2402
  var EXIT = { api: 1, auth: 3, notFound: 4, rateLimited: 5, usage: 2 };
2328
2403
  var DEFAULT_API_URL = "https://api.teakvault.com";
2329
2404
  var DEFAULT_AUTH_URL = "https://app.teakvault.com";
2405
+ var CLI_OAUTH_SCOPE = "profile email offline_access";
2330
2406
  var SERVICE = "com.teakvault.cli";
2331
2407
  var ACCOUNT = "default";
2332
2408
  var readJson = (value) => {
@@ -2498,6 +2574,17 @@ var openBrowser = (url) => {
2498
2574
  const args = platform() === "win32" ? ["/c", "start", "", url] : [url];
2499
2575
  spawn(command, args, { detached: true, stdio: "ignore" }).unref();
2500
2576
  };
2577
+ var createAuthorizeUrl = (options, params) => {
2578
+ const authUrl = new URL(authorizeEndpoint(options));
2579
+ authUrl.searchParams.set("response_type", "code");
2580
+ authUrl.searchParams.set("client_id", "teak-cli");
2581
+ authUrl.searchParams.set("redirect_uri", params.redirectUri);
2582
+ authUrl.searchParams.set("code_challenge", params.codeChallenge);
2583
+ authUrl.searchParams.set("code_challenge_method", "S256");
2584
+ authUrl.searchParams.set("scope", CLI_OAUTH_SCOPE);
2585
+ authUrl.searchParams.set("state", params.state);
2586
+ return authUrl;
2587
+ };
2501
2588
  var login = async (options) => {
2502
2589
  const verifier = b64url(randomBytes(32));
2503
2590
  const state = b64url(randomBytes(24));
@@ -2536,13 +2623,11 @@ var login = async (options) => {
2536
2623
  }
2537
2624
  });
2538
2625
  server.listen(port, "127.0.0.1", () => {
2539
- const authUrl = new URL(authorizeEndpoint(options));
2540
- authUrl.searchParams.set("response_type", "code");
2541
- authUrl.searchParams.set("client_id", "teak-cli");
2542
- authUrl.searchParams.set("redirect_uri", redirectUri);
2543
- authUrl.searchParams.set("code_challenge", sha256(verifier));
2544
- authUrl.searchParams.set("code_challenge_method", "S256");
2545
- authUrl.searchParams.set("state", state);
2626
+ const authUrl = createAuthorizeUrl(options, {
2627
+ codeChallenge: sha256(verifier),
2628
+ redirectUri,
2629
+ state
2630
+ });
2546
2631
  process.stdout.write(`${authUrl.toString()}
2547
2632
  `);
2548
2633
  if (options.browser !== false) {
@@ -2565,7 +2650,7 @@ var login = async (options) => {
2565
2650
 
2566
2651
  // src/files.ts
2567
2652
  var MAX_STDIN_BYTES = 1024 * 1024;
2568
- var MAX_FILE_SIZE = 20 * 1024 * 1024;
2653
+ var MAX_FILE_SIZE2 = 20 * 1024 * 1024;
2569
2654
  var readStdin = async () => {
2570
2655
  if (process.stdin.isTTY) {
2571
2656
  return "";
@@ -2622,8 +2707,8 @@ var addCard = async (input, options) => {
2622
2707
  const { candidate, raw } = await resolveAddInput(input, options.file);
2623
2708
  if (candidate && existsSync2(candidate) && statSync(candidate).isFile()) {
2624
2709
  const stats = statSync(candidate);
2625
- if (stats.size > MAX_FILE_SIZE) {
2626
- throw new InvalidArgumentError(`file must be at most ${MAX_FILE_SIZE} bytes`);
2710
+ if (stats.size > MAX_FILE_SIZE2) {
2711
+ throw new InvalidArgumentError(`file must be at most ${MAX_FILE_SIZE2} bytes`);
2627
2712
  }
2628
2713
  const mimeType = mimeFor(candidate);
2629
2714
  const upload = await api.uploads.create({
@@ -2706,7 +2791,7 @@ var parseSince = (value) => {
2706
2791
  };
2707
2792
  var parseType = (value) => {
2708
2793
  if (!isCardType(value)) {
2709
- throw new InvalidArgumentError(`type must be one of: ${CARD_TYPES.join(", ")}`);
2794
+ throw new InvalidArgumentError(`type must be one of: ${CARD_TYPES2.join(", ")}`);
2710
2795
  }
2711
2796
  return value;
2712
2797
  };
package/package.json CHANGED
@@ -1,13 +1,24 @@
1
1
  {
2
2
  "name": "teak-cli",
3
- "version": "1.0.51",
4
- "description": "Command line client for Teak.",
3
+ "version": "1.0.53",
4
+ "description": "Command-line client for Teak, the personal knowledge hub for saving and rediscovering ideas.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "teak": "./dist/index.js"
8
8
  },
9
9
  "files": [
10
- "dist"
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "keywords": [
14
+ "teak",
15
+ "cli",
16
+ "knowledge-base",
17
+ "bookmark-manager",
18
+ "notes",
19
+ "mcp",
20
+ "api-client",
21
+ "productivity"
11
22
  ],
12
23
  "engines": {
13
24
  "node": ">=20"
@@ -21,6 +32,7 @@
21
32
  "commander": "^15.0.0"
22
33
  },
23
34
  "devDependencies": {
35
+ "@teak/convex": "workspace:*",
24
36
  "@types/node": "^25.9.3",
25
37
  "typescript": "^6.0.3"
26
38
  },
@@ -33,5 +45,10 @@
33
45
  "url": "git+https://github.com/praveenjuge/teak.git",
34
46
  "directory": "apps/cli"
35
47
  },
48
+ "homepage": "https://teakvault.com/docs/cli",
49
+ "bugs": {
50
+ "url": "https://github.com/praveenjuge/teak/issues"
51
+ },
52
+ "author": "Praveen Juge <hello@praveenjuge.com>",
36
53
  "license": "MIT"
37
54
  }