@planckspace/cli 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +109 -0
  2. package/dist/__tests__/correlate.test.d.ts +2 -0
  3. package/dist/__tests__/correlate.test.d.ts.map +1 -0
  4. package/dist/__tests__/correlate.test.js +204 -0
  5. package/dist/__tests__/correlate.test.js.map +1 -0
  6. package/dist/commands/init.d.ts +2 -0
  7. package/dist/commands/init.d.ts.map +1 -0
  8. package/dist/commands/init.js +12 -0
  9. package/dist/commands/init.js.map +1 -0
  10. package/dist/commands/login.d.ts +2 -0
  11. package/dist/commands/login.d.ts.map +1 -0
  12. package/dist/commands/login.js +45 -0
  13. package/dist/commands/login.js.map +1 -0
  14. package/dist/commands/logout.d.ts +2 -0
  15. package/dist/commands/logout.d.ts.map +1 -0
  16. package/dist/commands/logout.js +7 -0
  17. package/dist/commands/logout.js.map +1 -0
  18. package/dist/commands/scan.d.ts +5 -0
  19. package/dist/commands/scan.d.ts.map +1 -0
  20. package/dist/commands/scan.js +51 -0
  21. package/dist/commands/scan.js.map +1 -0
  22. package/dist/commands/status.d.ts +2 -0
  23. package/dist/commands/status.d.ts.map +1 -0
  24. package/dist/commands/status.js +31 -0
  25. package/dist/commands/status.js.map +1 -0
  26. package/dist/commands/sync.d.ts +15 -0
  27. package/dist/commands/sync.d.ts.map +1 -0
  28. package/dist/commands/sync.js +77 -0
  29. package/dist/commands/sync.js.map +1 -0
  30. package/dist/config.d.ts +6 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +40 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/correlate.d.ts +21 -0
  35. package/dist/correlate.d.ts.map +1 -0
  36. package/dist/correlate.js +204 -0
  37. package/dist/correlate.js.map +1 -0
  38. package/dist/db/store.d.ts +46 -0
  39. package/dist/db/store.d.ts.map +1 -0
  40. package/dist/db/store.js +210 -0
  41. package/dist/db/store.js.map +1 -0
  42. package/dist/env.d.ts +6 -0
  43. package/dist/env.d.ts.map +1 -0
  44. package/dist/env.js +7 -0
  45. package/dist/env.js.map +1 -0
  46. package/dist/index.d.ts +3 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +97 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/scrapers/__tests__/claudeCode.test.d.ts +2 -0
  51. package/dist/scrapers/__tests__/claudeCode.test.d.ts.map +1 -0
  52. package/dist/scrapers/__tests__/claudeCode.test.js +115 -0
  53. package/dist/scrapers/__tests__/claudeCode.test.js.map +1 -0
  54. package/dist/scrapers/__tests__/cursor.test.d.ts +2 -0
  55. package/dist/scrapers/__tests__/cursor.test.d.ts.map +1 -0
  56. package/dist/scrapers/__tests__/cursor.test.js +173 -0
  57. package/dist/scrapers/__tests__/cursor.test.js.map +1 -0
  58. package/dist/scrapers/__tests__/windsurf.test.d.ts +2 -0
  59. package/dist/scrapers/__tests__/windsurf.test.d.ts.map +1 -0
  60. package/dist/scrapers/__tests__/windsurf.test.js +87 -0
  61. package/dist/scrapers/__tests__/windsurf.test.js.map +1 -0
  62. package/dist/scrapers/claudeCode.d.ts +4 -0
  63. package/dist/scrapers/claudeCode.d.ts.map +1 -0
  64. package/dist/scrapers/claudeCode.js +211 -0
  65. package/dist/scrapers/claudeCode.js.map +1 -0
  66. package/dist/scrapers/cursor.d.ts +9 -0
  67. package/dist/scrapers/cursor.d.ts.map +1 -0
  68. package/dist/scrapers/cursor.js +280 -0
  69. package/dist/scrapers/cursor.js.map +1 -0
  70. package/dist/scrapers/repo.d.ts +12 -0
  71. package/dist/scrapers/repo.d.ts.map +1 -0
  72. package/dist/scrapers/repo.js +40 -0
  73. package/dist/scrapers/repo.js.map +1 -0
  74. package/dist/scrapers/types.d.ts +36 -0
  75. package/dist/scrapers/types.d.ts.map +1 -0
  76. package/dist/scrapers/types.js +5 -0
  77. package/dist/scrapers/types.js.map +1 -0
  78. package/dist/scrapers/windsurf.d.ts +9 -0
  79. package/dist/scrapers/windsurf.d.ts.map +1 -0
  80. package/dist/scrapers/windsurf.js +255 -0
  81. package/dist/scrapers/windsurf.js.map +1 -0
  82. package/dist/scripts/scanTest.d.ts +3 -0
  83. package/dist/scripts/scanTest.d.ts.map +1 -0
  84. package/dist/scripts/scanTest.js +146 -0
  85. package/dist/scripts/scanTest.js.map +1 -0
  86. package/dist/sync/__tests__/payload.privacy.test.d.ts +2 -0
  87. package/dist/sync/__tests__/payload.privacy.test.d.ts.map +1 -0
  88. package/dist/sync/__tests__/payload.privacy.test.js +100 -0
  89. package/dist/sync/__tests__/payload.privacy.test.js.map +1 -0
  90. package/dist/sync/payload.d.ts +14 -0
  91. package/dist/sync/payload.d.ts.map +1 -0
  92. package/dist/sync/payload.js +36 -0
  93. package/dist/sync/payload.js.map +1 -0
  94. package/dist/sync/syncEngine.d.ts +16 -0
  95. package/dist/sync/syncEngine.d.ts.map +1 -0
  96. package/dist/sync/syncEngine.js +76 -0
  97. package/dist/sync/syncEngine.js.map +1 -0
  98. package/install.sh +126 -0
  99. package/package.json +39 -4
  100. package/index.js +0 -1
@@ -0,0 +1,76 @@
1
+ import { getUnsyncedSessions, markSessionsSynced, recordSyncError, } from "../db/store.js";
2
+ import { buildTelemetryPayload } from "./payload.js";
3
+ const BATCH_SIZE = 100;
4
+ const MAX_RETRIES = 3;
5
+ function chunk(arr, size) {
6
+ const out = [];
7
+ for (let i = 0; i < arr.length; i += size)
8
+ out.push(arr.slice(i, i + size));
9
+ return out;
10
+ }
11
+ function sleep(ms) {
12
+ return new Promise((resolve) => setTimeout(resolve, ms));
13
+ }
14
+ /** A failure worth retrying: no response (network) or a 5xx / 429 from the server. */
15
+ function isTransient(outcome) {
16
+ if (outcome.status === undefined)
17
+ return true;
18
+ return outcome.status >= 500 || outcome.status === 429;
19
+ }
20
+ async function postBatch(deps, payloads) {
21
+ try {
22
+ const res = await fetch(`${deps.apiUrl}/api/ingest`, {
23
+ method: "POST",
24
+ headers: {
25
+ "Content-Type": "application/json",
26
+ Authorization: `Bearer ${deps.token}`,
27
+ },
28
+ body: JSON.stringify(payloads),
29
+ });
30
+ if (res.ok)
31
+ return { ok: true, status: res.status };
32
+ const text = await res.text().catch(() => "");
33
+ return {
34
+ ok: false,
35
+ status: res.status,
36
+ error: `HTTP ${res.status}${text ? `: ${text.slice(0, 200)}` : ""}`,
37
+ };
38
+ }
39
+ catch (err) {
40
+ return { ok: false, error: `network error: ${String(err)}` };
41
+ }
42
+ }
43
+ /**
44
+ * Push all unsynced sessions to {apiUrl}/api/ingest in batches of up to 100.
45
+ * Successful batches are marked synced; failed batches record lastError and stay
46
+ * unsynced for the next run. Transient failures retry with exponential backoff.
47
+ */
48
+ export async function syncOnce(deps) {
49
+ const rows = getUnsyncedSessions();
50
+ if (rows.length === 0)
51
+ return { synced: 0, failed: 0 };
52
+ let synced = 0;
53
+ let failed = 0;
54
+ for (const batch of chunk(rows, BATCH_SIZE)) {
55
+ const ids = batch.map((r) => r.id);
56
+ const payloads = batch.map((r) => buildTelemetryPayload(r, deps.workspaceId));
57
+ let outcome = { ok: false };
58
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
59
+ outcome = await postBatch(deps, payloads);
60
+ if (outcome.ok || !isTransient(outcome) || attempt === MAX_RETRIES)
61
+ break;
62
+ // Exponential backoff: 500ms, 1s, 2s.
63
+ await sleep(500 * 2 ** attempt);
64
+ }
65
+ if (outcome.ok) {
66
+ markSessionsSynced(ids);
67
+ synced += ids.length;
68
+ }
69
+ else {
70
+ recordSyncError(ids, outcome.error ?? "unknown error");
71
+ failed += ids.length;
72
+ }
73
+ }
74
+ return { synced, failed };
75
+ }
76
+ //# sourceMappingURL=syncEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncEngine.js","sourceRoot":"","sources":["../../src/sync/syncEngine.ts"],"names":[],"mappings":"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"}
package/install.sh ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env bash
2
+ # PlanckSpace installer — https://planckspace.dev/install
3
+ #
4
+ # Usage:
5
+ # curl -fsSL https://planckspace.dev/install | sh
6
+ # curl -fsSL https://planckspace.dev/install | sh -s -- --token pk_live_xxx
7
+ set -euo pipefail
8
+
9
+ DASHBOARD_URL="https://app.planckspace.dev"
10
+ VSCODE_EXT_URL="https://marketplace.visualstudio.com/items?itemName=planckspace.planckspace"
11
+ PKG="@planckspace/cli"
12
+
13
+ # ── helpers ──────────────────────────────────────────────────────────────────
14
+ say() { printf '\n%s\n' "$*"; }
15
+ info() { printf ' %s\n' "$*"; }
16
+ die() { printf '\nERROR: %s\n\n' "$*" >&2; exit 1; }
17
+
18
+ # ── parse args ───────────────────────────────────────────────────────────────
19
+ TOKEN=""
20
+ while [[ $# -gt 0 ]]; do
21
+ case "$1" in
22
+ --token) TOKEN="${2:-}"; shift 2 ;;
23
+ --token=*) TOKEN="${1#--token=}"; shift ;;
24
+ *) shift ;;
25
+ esac
26
+ done
27
+
28
+ # ── OS / arch check ──────────────────────────────────────────────────────────
29
+ OS="$(uname -s 2>/dev/null || echo unknown)"
30
+ ARCH="$(uname -m 2>/dev/null || echo unknown)"
31
+
32
+ case "$OS" in
33
+ Darwin|Linux) ;;
34
+ MINGW*|MSYS*|CYGWIN*|Windows_NT)
35
+ say "Windows detected."
36
+ say "PlanckSpace requires WSL (Windows Subsystem for Linux)."
37
+ info "1. Open PowerShell as Administrator and run: wsl --install"
38
+ info "2. After WSL is set up, open a WSL terminal and run:"
39
+ info " curl -fsSL https://planckspace.dev/install | sh"
40
+ exit 1
41
+ ;;
42
+ *)
43
+ die "Unsupported OS: $OS. Install manually with: npm install -g $PKG"
44
+ ;;
45
+ esac
46
+
47
+ say "PlanckSpace installer (OS: $OS / arch: $ARCH)"
48
+
49
+ # ── Node.js check ────────────────────────────────────────────────────────────
50
+ node_ok() {
51
+ command -v node >/dev/null 2>&1 || return 1
52
+ local v
53
+ v="$(node --version 2>/dev/null | sed 's/v//' | cut -d. -f1)"
54
+ [[ "${v:-0}" -ge 20 ]]
55
+ }
56
+
57
+ if ! node_ok; then
58
+ say "Node.js 20+ is required but was not found."
59
+ say "Install it with nvm (recommended — no sudo needed):"
60
+ info "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash"
61
+ info "source \"\${HOME}/.nvm/nvm.sh\""
62
+ info "nvm install 20"
63
+ say "Or download from: https://nodejs.org/en/download"
64
+ say "Then re-run this installer."
65
+ exit 1
66
+ fi
67
+
68
+ NODE_VER="$(node --version)"
69
+ info "Node $NODE_VER found."
70
+
71
+ # ── npm check ────────────────────────────────────────────────────────────────
72
+ command -v npm >/dev/null 2>&1 || die "npm not found. Re-install Node.js from https://nodejs.org"
73
+
74
+ # ── install CLI ──────────────────────────────────────────────────────────────
75
+ say "Installing $PKG..."
76
+ npm install -g "$PKG" --loglevel error
77
+
78
+ # verify the binary is reachable
79
+ command -v planck >/dev/null 2>&1 || {
80
+ # npm global bin might not be in PATH — try to fix
81
+ NPM_BIN="$(npm bin -g 2>/dev/null || true)"
82
+ if [[ -n "$NPM_BIN" && -x "$NPM_BIN/planck" ]]; then
83
+ export PATH="$NPM_BIN:$PATH"
84
+ else
85
+ die "'planck' binary not found after install. Add \`$(npm prefix -g)/bin\` to your PATH."
86
+ fi
87
+ }
88
+
89
+ # ── init ─────────────────────────────────────────────────────────────────────
90
+ say "Initializing ~/.planckspace..."
91
+ planck init
92
+
93
+ # ── login ────────────────────────────────────────────────────────────────────
94
+ CONNECTED=false
95
+ if [[ -n "$TOKEN" ]]; then
96
+ say "Connecting to your workspace..."
97
+ planck login --token "$TOKEN" && CONNECTED=true || true
98
+ else
99
+ say "No token provided."
100
+ info "Visit $DASHBOARD_URL to get your invite token, then run:"
101
+ info " planck login <your-token>"
102
+ fi
103
+
104
+ # ── scan (backfill existing history) ─────────────────────────────────────────
105
+ say "Scanning local AI session history (this is fast)..."
106
+ planck scan
107
+
108
+ # ── sync (only when connected) ───────────────────────────────────────────────
109
+ if [[ "$CONNECTED" == "true" ]]; then
110
+ say "Syncing data to your workspace..."
111
+ planck sync
112
+ fi
113
+
114
+ # ── done ─────────────────────────────────────────────────────────────────────
115
+ say "--------------------------------------"
116
+ say "PlanckSpace is ready."
117
+ say "--------------------------------------"
118
+ if [[ "$CONNECTED" == "true" ]]; then
119
+ info "Dashboard: $DASHBOARD_URL"
120
+ else
121
+ info "Next step: planck login <token>"
122
+ info "Dashboard: $DASHBOARD_URL"
123
+ fi
124
+ info "VS Code extension: $VSCODE_EXT_URL"
125
+ info "Check setup: planck status"
126
+ say ""
package/package.json CHANGED
@@ -1,7 +1,42 @@
1
1
  {
2
2
  "name": "@planckspace/cli",
3
- "version": "0.0.1",
4
- "description": "Planck - AI Context Management",
5
- "main": "index.js",
6
- "license": "MIT"
3
+ "version": "0.1.0",
4
+ "description": "PlanckSpace CLI — sync AI token usage from your editor to the team ledger",
5
+ "type": "module",
6
+ "bin": {
7
+ "planck": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsx src/index.ts",
12
+ "clean": "rm -rf dist",
13
+ "scan:test": "tsx src/scripts/scanTest.ts",
14
+ "test": "vitest run",
15
+ "prepublishOnly": "npm run build",
16
+ "release": "npm publish"
17
+ },
18
+ "engines": {
19
+ "node": ">=20"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "install.sh"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "dependencies": {
29
+ "@planckspace/core": "^0.1.0",
30
+ "better-sqlite3": "^12.10.0",
31
+ "commander": "^15.0.0",
32
+ "dotenv": "^17.4.2",
33
+ "simple-git": "^3.36.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/better-sqlite3": "^7.6.13",
37
+ "@types/node": "^25.9.1",
38
+ "tsx": "^4.22.4",
39
+ "typescript": "^6.0.3",
40
+ "vitest": "^4.1.7"
41
+ }
7
42
  }
package/index.js DELETED
@@ -1 +0,0 @@
1
- // placeholder