clipy-kit 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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +65 -0
  3. package/dist/auth.d.ts +53 -0
  4. package/dist/auth.js +314 -0
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cli.js +160 -0
  7. package/dist/color.d.ts +12 -0
  8. package/dist/color.js +19 -0
  9. package/dist/colors.d.ts +6 -0
  10. package/dist/colors.js +26 -0
  11. package/dist/host/doctor.d.ts +17 -0
  12. package/dist/host/doctor.js +54 -0
  13. package/dist/host/help.d.ts +20 -0
  14. package/dist/host/help.js +142 -0
  15. package/dist/host/setup.d.ts +16 -0
  16. package/dist/host/setup.js +93 -0
  17. package/dist/http.d.ts +14 -0
  18. package/dist/http.js +53 -0
  19. package/dist/ids.d.ts +2 -0
  20. package/dist/ids.js +21 -0
  21. package/dist/json-input.d.ts +4 -0
  22. package/dist/json-input.js +34 -0
  23. package/dist/lib/format.d.ts +14 -0
  24. package/dist/lib/format.js +73 -0
  25. package/dist/lib/index.d.ts +6 -0
  26. package/dist/lib/index.js +6 -0
  27. package/dist/lib/ops.d.ts +460 -0
  28. package/dist/lib/ops.js +475 -0
  29. package/dist/lib/table.d.ts +14 -0
  30. package/dist/lib/table.js +67 -0
  31. package/dist/lib/types.d.ts +26 -0
  32. package/dist/lib/types.js +1 -0
  33. package/dist/output.d.ts +37 -0
  34. package/dist/output.js +67 -0
  35. package/dist/plugins/catalog.d.ts +11 -0
  36. package/dist/plugins/catalog.js +31 -0
  37. package/dist/plugins/sheet/plugin.d.ts +2 -0
  38. package/dist/plugins/sheet/plugin.js +8 -0
  39. package/dist/plugins/sheet/register.d.ts +2 -0
  40. package/dist/plugins/sheet/register.js +529 -0
  41. package/dist/plugins/sheet/specs.d.ts +20 -0
  42. package/dist/plugins/sheet/specs.js +291 -0
  43. package/dist/plugins/types.d.ts +7 -0
  44. package/dist/plugins/types.js +1 -0
  45. package/dist/ranges.d.ts +20 -0
  46. package/dist/ranges.js +77 -0
  47. package/dist/run.d.ts +353 -0
  48. package/dist/run.js +36 -0
  49. package/dist/specs.d.ts +1 -0
  50. package/dist/specs.js +1 -0
  51. package/package.json +50 -0
  52. package/skills/clipy/SKILL.md +38 -0
  53. package/skills/clipy-sheet/SKILL.md +71 -0
package/dist/run.d.ts ADDED
@@ -0,0 +1,353 @@
1
+ import type { Command } from 'commander';
2
+ export type Globals = {
3
+ pretty: boolean;
4
+ account?: string;
5
+ spreadsheet?: string;
6
+ dryRun: boolean;
7
+ json?: boolean;
8
+ };
9
+ export declare function takeGlobals(cmd: Command): Globals;
10
+ export declare function opsFor(account?: string): {
11
+ getSpreadsheet: (id: string, fields?: string) => Promise<import("./lib/types.js").Spreadsheet>;
12
+ findSpreadsheets: (name: string, limit?: number) => Promise<{
13
+ query: string;
14
+ files: {
15
+ id: string;
16
+ name: string;
17
+ url: string;
18
+ }[];
19
+ }>;
20
+ info: (id: string) => Promise<{
21
+ spreadsheetId: string;
22
+ title: string | undefined;
23
+ url: string | undefined;
24
+ tabs: {
25
+ sheetId: number | undefined;
26
+ title: string | undefined;
27
+ index: number | undefined;
28
+ rows: number | undefined;
29
+ columns: number | undefined;
30
+ }[];
31
+ }>;
32
+ listTabs: (id: string) => Promise<{
33
+ title: string | undefined;
34
+ tabs: {
35
+ sheetId: number | undefined;
36
+ title: string | undefined;
37
+ index: number | undefined;
38
+ rows: number | undefined;
39
+ columns: number | undefined;
40
+ }[];
41
+ }>;
42
+ readTable: (id: string, opts: import("./lib/ops.js").ReadOpts) => Promise<{
43
+ range: string;
44
+ values: unknown[][];
45
+ } | {
46
+ headers: string[];
47
+ rows: Record<string, unknown>[];
48
+ headerRow: number;
49
+ range: string;
50
+ values?: undefined;
51
+ }>;
52
+ readRange: (id: string, range: string) => Promise<{
53
+ range: string;
54
+ values: unknown[][];
55
+ }>;
56
+ append: (id: string, opts: import("./lib/ops.js").WriteTableOpts) => Promise<{
57
+ dryRun: boolean;
58
+ tab: string;
59
+ headers: string[];
60
+ rows: number;
61
+ bootstrap: boolean;
62
+ result?: undefined;
63
+ } | {
64
+ tab: string;
65
+ headers: string[];
66
+ rows: number;
67
+ bootstrap: boolean;
68
+ result: unknown;
69
+ dryRun?: undefined;
70
+ } | {
71
+ dryRun: boolean;
72
+ tab: string;
73
+ headers: string[];
74
+ rows: number;
75
+ bootstrap?: undefined;
76
+ result?: undefined;
77
+ } | {
78
+ tab: string;
79
+ headers: string[];
80
+ rows: number;
81
+ result: unknown;
82
+ dryRun?: undefined;
83
+ bootstrap?: undefined;
84
+ }>;
85
+ update: (id: string, opts: import("./lib/ops.js").UpdateOpts) => Promise<{
86
+ dryRun: boolean;
87
+ matchedRows: unknown[];
88
+ set: Record<string, unknown>;
89
+ updated?: undefined;
90
+ result?: undefined;
91
+ } | {
92
+ matchedRows: unknown[];
93
+ updated: number;
94
+ result: unknown;
95
+ dryRun?: undefined;
96
+ set?: undefined;
97
+ }>;
98
+ upsert: (id: string, opts: import("./lib/ops.js").UpsertOpts) => Promise<{
99
+ updated: number;
100
+ inserted: number;
101
+ updatedRows: unknown[];
102
+ appendResult: unknown;
103
+ }>;
104
+ setRange: (id: string, opts: import("./lib/ops.js").SetOpts) => Promise<{
105
+ dryRun: boolean;
106
+ range: string;
107
+ values: unknown[][];
108
+ result?: undefined;
109
+ } | {
110
+ range: string;
111
+ result: unknown;
112
+ dryRun?: undefined;
113
+ values?: undefined;
114
+ }>;
115
+ clear: (id: string, range: string, dryRun?: boolean) => Promise<{
116
+ dryRun: boolean;
117
+ range: string;
118
+ result?: undefined;
119
+ } | {
120
+ range: string;
121
+ result: unknown;
122
+ dryRun?: undefined;
123
+ }>;
124
+ batch: (id: string, ops: import("./lib/ops.js").BatchOp[], dryRun?: boolean) => Promise<{
125
+ count: number;
126
+ results: ({
127
+ op: "append";
128
+ result: {
129
+ dryRun: boolean;
130
+ tab: string;
131
+ headers: string[];
132
+ rows: number;
133
+ bootstrap: boolean;
134
+ result?: undefined;
135
+ } | {
136
+ tab: string;
137
+ headers: string[];
138
+ rows: number;
139
+ bootstrap: boolean;
140
+ result: unknown;
141
+ dryRun?: undefined;
142
+ } | {
143
+ dryRun: boolean;
144
+ tab: string;
145
+ headers: string[];
146
+ rows: number;
147
+ bootstrap?: undefined;
148
+ result?: undefined;
149
+ } | {
150
+ tab: string;
151
+ headers: string[];
152
+ rows: number;
153
+ result: unknown;
154
+ dryRun?: undefined;
155
+ bootstrap?: undefined;
156
+ };
157
+ } | {
158
+ op: "updateKey";
159
+ result: {
160
+ dryRun: boolean;
161
+ matchedRows: unknown[];
162
+ set: Record<string, unknown>;
163
+ updated?: undefined;
164
+ result?: undefined;
165
+ } | {
166
+ matchedRows: unknown[];
167
+ updated: number;
168
+ result: unknown;
169
+ dryRun?: undefined;
170
+ set?: undefined;
171
+ };
172
+ } | {
173
+ op: "updateRow";
174
+ result: {
175
+ dryRun: boolean;
176
+ row: number;
177
+ set: Record<string, unknown>;
178
+ result?: undefined;
179
+ } | {
180
+ row: number;
181
+ result: unknown;
182
+ dryRun?: undefined;
183
+ set?: undefined;
184
+ };
185
+ } | {
186
+ op: "setRange";
187
+ result: {
188
+ dryRun: boolean;
189
+ range: string;
190
+ values: unknown[][];
191
+ result?: undefined;
192
+ } | {
193
+ range: string;
194
+ result: unknown;
195
+ dryRun?: undefined;
196
+ values?: undefined;
197
+ };
198
+ } | {
199
+ op: "clear";
200
+ result: {
201
+ dryRun: boolean;
202
+ range: string;
203
+ result?: undefined;
204
+ } | {
205
+ range: string;
206
+ result: unknown;
207
+ dryRun?: undefined;
208
+ };
209
+ })[];
210
+ }>;
211
+ create: (opts: import("./lib/ops.js").CreateOpts) => Promise<{
212
+ properties: {
213
+ title: string;
214
+ };
215
+ sheets: {
216
+ properties: {
217
+ title: string;
218
+ index: number;
219
+ };
220
+ }[];
221
+ dryRun: boolean;
222
+ spreadsheetId?: undefined;
223
+ url?: undefined;
224
+ title?: undefined;
225
+ tabs?: undefined;
226
+ } | {
227
+ spreadsheetId: string;
228
+ url: string;
229
+ title: string | undefined;
230
+ tabs: string[];
231
+ }>;
232
+ tabAdd: (id: string, opts: import("./lib/ops.js").TabAddOpts) => Promise<{
233
+ title: string;
234
+ result: unknown;
235
+ }>;
236
+ tabRename: (id: string, opts: import("./lib/ops.js").TabRenameOpts) => Promise<{
237
+ from: string;
238
+ title: string;
239
+ result: unknown;
240
+ }>;
241
+ tabDelete: (id: string, opts: {
242
+ tab: string;
243
+ dryRun?: boolean;
244
+ }) => Promise<{
245
+ tab: string;
246
+ sheetId: number;
247
+ result: unknown;
248
+ }>;
249
+ tabDuplicate: (id: string, opts: import("./lib/ops.js").TabDupOpts) => Promise<{
250
+ tab: string;
251
+ title: string | undefined;
252
+ result: unknown;
253
+ }>;
254
+ format: (id: string, opts: import("./lib/ops.js").FormatOpts) => Promise<{
255
+ dryRun: boolean;
256
+ range: string;
257
+ requests: Record<string, unknown>[];
258
+ result?: undefined;
259
+ } | {
260
+ range: string;
261
+ result: unknown;
262
+ dryRun?: undefined;
263
+ requests?: undefined;
264
+ }>;
265
+ formatHeader: (id: string, opts: import("./lib/ops.js").HeaderFormatOpts) => Promise<{
266
+ tab: string;
267
+ freeze: boolean;
268
+ result: unknown;
269
+ }>;
270
+ freeze: (id: string, opts: import("./lib/ops.js").FreezeOpts) => Promise<{
271
+ tab: string;
272
+ rows: number;
273
+ columns: number | undefined;
274
+ result: unknown;
275
+ }>;
276
+ numberFormat: (id: string, opts: import("./lib/ops.js").NumberFormatOpts) => Promise<{
277
+ dryRun: boolean;
278
+ range: string;
279
+ requests: Record<string, unknown>[];
280
+ result?: undefined;
281
+ } | {
282
+ range: string;
283
+ result: unknown;
284
+ dryRun?: undefined;
285
+ requests?: undefined;
286
+ }>;
287
+ formula: (id: string, opts: import("./lib/ops.js").FormulaOpts) => Promise<{
288
+ dryRun: boolean;
289
+ cell: string;
290
+ expr: string;
291
+ result?: undefined;
292
+ } | {
293
+ cell: string;
294
+ expr: string;
295
+ result: unknown;
296
+ dryRun?: undefined;
297
+ }>;
298
+ fillDown: (id: string, opts: import("./lib/ops.js").FillDownOpts) => Promise<{
299
+ dryRun: boolean;
300
+ range: string;
301
+ expr: string;
302
+ rows: number;
303
+ result?: undefined;
304
+ } | {
305
+ range: string;
306
+ expr: string;
307
+ rows: number;
308
+ result: unknown;
309
+ dryRun?: undefined;
310
+ }>;
311
+ share: (id: string, opts: import("./lib/ops.js").ShareOpts) => Promise<{
312
+ dryRun: boolean;
313
+ email: string;
314
+ role: string;
315
+ result?: undefined;
316
+ } | {
317
+ email: string;
318
+ role: string;
319
+ result: unknown;
320
+ dryRun?: undefined;
321
+ }>;
322
+ unshare: (id: string, email: string, dryRun?: boolean) => Promise<{
323
+ dryRun: boolean;
324
+ email: string;
325
+ permissionId: string;
326
+ removed?: undefined;
327
+ } | {
328
+ email: string;
329
+ removed: string;
330
+ dryRun?: undefined;
331
+ permissionId?: undefined;
332
+ }>;
333
+ permissions: (id: string) => Promise<{
334
+ permissions: {
335
+ id: string;
336
+ role: string | undefined;
337
+ type: string | undefined;
338
+ email: string | undefined;
339
+ name: string | undefined;
340
+ }[];
341
+ }>;
342
+ api: (method: string, id: string | undefined, json: unknown) => Promise<{
343
+ method: string;
344
+ result: unknown;
345
+ }>;
346
+ };
347
+ export declare function idOf(positional: string | undefined, g: Globals): string;
348
+ export declare function run(cmdName: string, pretty: boolean, fn: () => Promise<{
349
+ result: unknown;
350
+ spreadsheetId?: string;
351
+ sheet?: string;
352
+ }>): Promise<void>;
353
+ export declare function need(value: string | undefined, flag: string): string;
package/dist/run.js ADDED
@@ -0,0 +1,36 @@
1
+ import { getAccessToken } from './auth.js';
2
+ import { GoogleClient } from './http.js';
3
+ import { resolveSpreadsheetId } from './ids.js';
4
+ import { createOps } from './lib/ops.js';
5
+ import { CliError, envelopeErr, envelopeOk, exitCodeFor, stringifyEnvelope } from './output.js';
6
+ export function takeGlobals(cmd) {
7
+ const opts = cmd.optsWithGlobals();
8
+ return {
9
+ pretty: Boolean(opts.pretty),
10
+ account: opts.account,
11
+ spreadsheet: opts.spreadsheet,
12
+ dryRun: Boolean(opts.dryRun),
13
+ json: Boolean(opts.json),
14
+ };
15
+ }
16
+ export function opsFor(account) {
17
+ return createOps(new GoogleClient(() => getAccessToken(account)));
18
+ }
19
+ export function idOf(positional, g) {
20
+ return resolveSpreadsheetId(positional, g.spreadsheet);
21
+ }
22
+ export async function run(cmdName, pretty, fn) {
23
+ try {
24
+ const out = await fn();
25
+ process.stdout.write(stringifyEnvelope(envelopeOk(cmdName, out.result, out), pretty) + '\n');
26
+ }
27
+ catch (err) {
28
+ process.stdout.write(stringifyEnvelope(envelopeErr(cmdName, err), pretty) + '\n');
29
+ process.exitCode = exitCodeFor(err);
30
+ }
31
+ }
32
+ export function need(value, flag) {
33
+ if (!value)
34
+ throw new CliError('VALIDATION_ERROR', `${flag} is required`);
35
+ return value;
36
+ }
@@ -0,0 +1 @@
1
+ export { COMMANDS, findSpec } from './plugins/sheet/specs.js';
package/dist/specs.js ADDED
@@ -0,0 +1 @@
1
+ export { COMMANDS, findSpec } from './plugins/sheet/specs.js';
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "clipy-kit",
3
+ "version": "0.1.0",
4
+ "description": "Clipy (clp): local intent CLI for humans and agents. Google Sheets plugin first; JSON stdout, CLI login, no rewritten API code.",
5
+ "type": "module",
6
+ "bin": {
7
+ "clp": "dist/cli.js"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/lib/index.d.ts",
12
+ "import": "./dist/lib/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "skills",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "clp": "tsx src/cli.ts",
24
+ "test": "tsx --test test/*.test.ts",
25
+ "typecheck": "tsc --noEmit",
26
+ "prepublishOnly": "npm run build"
27
+ },
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
31
+ "keywords": [
32
+ "cli",
33
+ "agent-skills",
34
+ "google-sheets",
35
+ "clipy",
36
+ "clp",
37
+ "clipy-kit"
38
+ ],
39
+ "license": "MIT",
40
+ "dependencies": {
41
+ "commander": "^13.1.0",
42
+ "google-auth-library": "^9.15.1",
43
+ "picocolors": "^1.1.1"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^22.13.10",
47
+ "tsx": "^4.19.3",
48
+ "typescript": "^5.8.2"
49
+ }
50
+ }
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: clipy
3
+ description: >-
4
+ Clipy host CLI (binary: clp). Use when installing or diagnosing clipy,
5
+ listing plugins, or when the user mentions Clipy, clp setup, clp
6
+ doctor, or adding sheet/jira/linear tools. Never write OAuth or API client
7
+ code — run clp commands. For Google Sheets details, also read the clipy-sheet skill.
8
+ ---
9
+
10
+ # clp — Clipy
11
+
12
+ One PATH binary for humans and agents. JSON on stdout for data commands.
13
+
14
+ ## If `clp` is missing
15
+
16
+ ```bash
17
+ npm i -g clipy-kit
18
+ clp setup
19
+ clp doctor --json
20
+ ```
21
+
22
+ Do not edit PATH by hand and do not generate a wrapper script.
23
+
24
+ ## Host commands
25
+
26
+ ```bash
27
+ clp --help --json
28
+ clp doctor --json
29
+ clp setup
30
+ clp plugin list --json
31
+ clp plugin add sheet
32
+ ```
33
+
34
+ `plugin list` includes **planned** names (linear, github, jira, …). Do not call those plugins; they are not shipped.
35
+
36
+ ## Plugins
37
+
38
+ Delegate to `clp <plugin> …`. Sheets: `clp sheet --help --json`. Never write `googleapis`, MCP payloads, or login code. If `AUTH_REQUIRED`, run `clp sheet auth login`.
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: clipy-sheet
3
+ description: >-
4
+ Read, write, format, and share Google Sheets via `clp sheet`. Use when the
5
+ user mentions Google Sheets, spreadsheets, Drive tabs, or tabular data in a
6
+ Google spreadsheet. Never write googleapis, OAuth, or Apps Script — run
7
+ clp sheet commands.
8
+ ---
9
+
10
+ # clp sheet
11
+
12
+ Intent-level Google Sheets plugin. JSON on stdout. Do not generate Google client or login code.
13
+
14
+ ## Auth (CLI only)
15
+
16
+ If a command returns `AUTH_REQUIRED`, run login and wait — do not write OAuth.
17
+
18
+ ```bash
19
+ clp sheet auth status
20
+ clp sheet auth login
21
+ clp sheet auth login --credentials ./client_secret.json
22
+ clp sheet auth login --service-account ./sa.json
23
+ clp sheet auth login --token "$GOOGLE_TOKEN"
24
+ clp sheet auth login --adc
25
+ clp sheet auth logout
26
+ ```
27
+
28
+ ## Workflow
29
+
30
+ `clp sheet auth status` → login if needed → read → `--dry-run` → apply. Prefer `upsert` / `update --key-col`. Check `ok`.
31
+
32
+ ```bash
33
+ clp sheet --help --json
34
+ clp sheet format --help --json
35
+ ```
36
+
37
+ `--spreadsheet` accepts a full URL.
38
+
39
+ ## Commands
40
+
41
+ ```bash
42
+ clp sheet find --name "HPP"
43
+ clp sheet info <id-or-url>
44
+ clp sheet tabs list <id>
45
+ clp sheet read <id> --tab "Sheet1" --limit 100
46
+ clp sheet read range <id> --range 'Sheet1!A1:C10'
47
+ clp sheet append <id> --tab "Sheet1" --rows '[{"Name":"A"}]' --dry-run
48
+ clp sheet update <id> --tab "Sheet1" --key-col Name --key A --set '{"Status":"Done"}'
49
+ clp sheet upsert <id> --tab "Sheet1" --key-col Name --rows '[{"Name":"A","Status":"Done"}]'
50
+ clp sheet set <id> --range 'Sheet1!A1:B2' --values '[["A","B"],["1","2"]]'
51
+ clp sheet clear <id> --range 'Sheet1!A2:Z'
52
+ clp sheet batch <id> --ops '[{"op":"append","sheet":"Sheet1","values":{"Name":"B"}}]'
53
+ clp sheet create --title "Recipes" --tabs "Minuman,Makanan"
54
+ clp sheet tab add <id> --title "Snack"
55
+ clp sheet format <id> --range 'Sheet1!A1:Z1' --bold --bg navy --fg white --align center
56
+ clp sheet format header <id> --tab Sheet1
57
+ clp sheet freeze <id> --tab Sheet1 --rows 1
58
+ clp sheet number-format <id> --range 'Sheet1!B:B' --pattern 'Rp#,##0'
59
+ clp sheet formula <id> --cell 'Sheet1!D2' --expr '=B2+C2'
60
+ clp sheet share <id> --email user@example.com --role writer
61
+ clp sheet permissions <id>
62
+ ```
63
+
64
+ ## Rules
65
+
66
+ - Never write `googleapis`, gviz, Apps Script, or token-exchange code.
67
+ - Never host an OAuth callback — `clp sheet auth login` owns the browser flow.
68
+ - Prefer key columns; `read` returns `_row` if you need a row index.
69
+ - `clp sheet api <method> --json @file.json` only when `--help --json` has no intent command.
70
+
71
+ Success: `{ "ok": true, "cmd": "...", "result": ... }`. Exit 20 = auth.