costaff-workspace 0.1.5 → 0.1.6

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/README.md CHANGED
@@ -95,6 +95,7 @@ Names, folders, and who may read each file are managed at
95
95
  | `costaff-workspace pull <token> [dir]` | fetch a published file's source |
96
96
  | `costaff-workspace theme push\|list\|pull\|rm` | keep the project's `themes/` folder in the workspace |
97
97
  | `costaff-workspace whoami` | what this machine is signed in as |
98
+ | `costaff-workspace skills` | install the agent skill into this project |
98
99
  | `costaff-workspace login` | sign this machine in |
99
100
  | `costaff-workspace logout` | forget this machine's sign-in |
100
101
 
package/README.zh-TW.md CHANGED
@@ -88,6 +88,7 @@ q3-numbers → https://workspace.costaffs.app/8fjq2ldk3nx7yrpv
88
88
  | `costaff-workspace pull <token> [dir]` | 取回某份已發佈檔案的原始碼 |
89
89
  | `costaff-workspace theme push\|list\|pull\|rm` | 把專案的 `themes/` 資料夾留在工作區 |
90
90
  | `costaff-workspace whoami` | 這台機器登入的是誰 |
91
+ | `costaff-workspace skills` | 把 agent skill 裝進這個專案 |
91
92
  | `costaff-workspace login` | 讓這台機器登入 |
92
93
  | `costaff-workspace logout` | 忘掉這台機器的登入 |
93
94
 
@@ -0,0 +1,115 @@
1
+ /**
2
+ * 把 skill 裝進使用者的專案。
3
+ *
4
+ * skill 隨套件一起發,所以裝了 CLI 就有了 —— 但 agent 讀的是專案裡的
5
+ * `.claude/skills/`,不是 node_modules。這個指令做的就是那一段複製,並且說得出
6
+ * 哪幾份變了。
7
+ *
8
+ * 覆蓋而不是合併:這些檔案是這個套件的產物,不是使用者的稿子。想改的人應該改自己
9
+ * 的那一份、換個名字,而不是編輯一個下次升級就會被蓋掉的檔案。
10
+ */
11
+ import { existsSync } from 'node:fs';
12
+ import fs from 'node:fs/promises';
13
+ import path from 'node:path';
14
+ import { fileURLToPath } from 'node:url';
15
+ import { done, line } from "./report.js";
16
+ const USAGE = `costaff-workspace skills — install the agent skill into this project
17
+
18
+ costaff-workspace skills [--dry-run] [--json]
19
+
20
+ Writes into .claude/skills/ and .agents/skills/, overwriting what is there.
21
+ `;
22
+ /* 兩個都寫:Claude Code 讀前者,其他工具讀後者,而同一份東西不該要人選邊。 */
23
+ const TARGETS = ['.claude/skills', '.agents/skills'];
24
+ /**
25
+ * 套件裡 skills/ 的位置。
26
+ *
27
+ * 從這個模組往上找,而不是從 cwd —— 執行時 cwd 是使用者的專案。編譯後這個檔案在
28
+ * `dist/`,所以答案是它的上一層。
29
+ */
30
+ export function builtinSkillsDir(from = fileURLToPath(import.meta.url)) {
31
+ return path.resolve(path.dirname(from), '..', 'skills');
32
+ }
33
+ async function tree(dir) {
34
+ const out = new Map();
35
+ const walk = async (at) => {
36
+ for (const entry of await fs.readdir(at, { withFileTypes: true })) {
37
+ const abs = path.join(at, entry.name);
38
+ if (entry.isDirectory())
39
+ await walk(abs);
40
+ else
41
+ out.set(path.relative(dir, abs), await fs.readFile(abs, 'utf8'));
42
+ }
43
+ };
44
+ await walk(dir);
45
+ return out;
46
+ }
47
+ async function same(src, dst) {
48
+ if (!existsSync(dst))
49
+ return false;
50
+ const [a, b] = await Promise.all([tree(src), tree(dst)]);
51
+ if (a.size !== b.size)
52
+ return false;
53
+ for (const [file, text] of a)
54
+ if (b.get(file) !== text)
55
+ return false;
56
+ return true;
57
+ }
58
+ export async function skillChanges(builtin, cwd) {
59
+ if (!existsSync(builtin))
60
+ return [];
61
+ const names = (await fs.readdir(builtin, { withFileTypes: true }))
62
+ .filter((e) => e.isDirectory())
63
+ .map((e) => e.name)
64
+ .sort();
65
+ const changes = [];
66
+ for (const name of names) {
67
+ /* 以第一個目標判斷。兩個目標寫的是同一份,分開比對只會report出兩次同一件事。 */
68
+ const dst = path.join(cwd, TARGETS[0] ?? '', name);
69
+ const status = !existsSync(dst)
70
+ ? 'added'
71
+ : (await same(path.join(builtin, name), dst))
72
+ ? 'unchanged'
73
+ : 'updated';
74
+ changes.push({ name, status });
75
+ }
76
+ return changes;
77
+ }
78
+ export async function installSkills(builtin, cwd, dryRun) {
79
+ const changes = await skillChanges(builtin, cwd);
80
+ if (dryRun)
81
+ return changes;
82
+ for (const { name, status } of changes) {
83
+ if (status === 'unchanged')
84
+ continue;
85
+ for (const target of TARGETS) {
86
+ const dst = path.join(cwd, target, name);
87
+ await fs.rm(dst, { recursive: true, force: true });
88
+ await fs.mkdir(path.dirname(dst), { recursive: true });
89
+ await fs.cp(path.join(builtin, name), dst, { recursive: true });
90
+ }
91
+ }
92
+ return changes;
93
+ }
94
+ export async function runSkills(argv) {
95
+ if (argv.includes('--help') || argv.includes('-h')) {
96
+ process.stdout.write(USAGE);
97
+ return;
98
+ }
99
+ const dryRun = argv.includes('--dry-run');
100
+ const builtin = builtinSkillsDir();
101
+ const cwd = process.cwd();
102
+ const changes = await installSkills(builtin, cwd, dryRun);
103
+ if (changes.length === 0) {
104
+ line('no skills in this package\n');
105
+ }
106
+ else {
107
+ for (const { name, status } of changes) {
108
+ line(` ${name.padEnd(20)} ${dryRun && status !== 'unchanged' ? `would be ${status}` : status}\n`);
109
+ }
110
+ if (!dryRun)
111
+ line(`\nwritten to ${TARGETS.join(' and ')}\n`);
112
+ }
113
+ done({ command: 'skills', dryRun, targets: TARGETS, skills: changes });
114
+ }
115
+ //# sourceMappingURL=cli-skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-skills.js","sourceRoot":"","sources":["../src/cli-skills.ts"],"names":[],"mappings":"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"}
package/dist/main.js CHANGED
@@ -7,6 +7,7 @@
7
7
  * 還有哪些兄弟指令存在。
8
8
  */
9
9
  import { runPull } from "./cli-pull.js";
10
+ import { runSkills } from "./cli-skills.js";
10
11
  import { runTheme } from "./cli-theme.js";
11
12
  import { runWhoami } from "./cli-whoami.js";
12
13
  import { runPush } from "./cli.js";
@@ -20,6 +21,7 @@ const USAGE = `costaff-workspace — publish to and pull back from CoStaff Works
20
21
  pull <token> fetch a published file's source back out
21
22
  theme push, list, pull and remove the themes/ folder
22
23
  whoami what this machine is signed in as
24
+ skills install the agent skill into this project
23
25
  login sign this machine in
24
26
  logout forget this machine's sign-in
25
27
 
@@ -48,6 +50,8 @@ async function main() {
48
50
  return runTheme(rest);
49
51
  case 'whoami':
50
52
  return runWhoami(rest);
53
+ case 'skills':
54
+ return runSkills(rest);
51
55
  /* login 和 logout 走的是 push 那條路:它們本來就是同一組憑證。 */
52
56
  case 'login':
53
57
  return runPush([...rest, '--login']);
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,KAAK,GAAG;;;;;;;;;;;;;;uBAcS,gBAAgB;;CAEtC,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB;;;;OAIG;IACH,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEhC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,OAAO,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,KAAK,QAAQ;YACX,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,8CAA8C;QAC9C,KAAK,OAAO;YACV,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QACvC,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QACxC,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI,CAAC;QACV,KAAK,MAAM;YACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO;QACT;YACE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,OAAO,QAAQ,KAAK,EAAE,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;uBAeS,gBAAgB;;CAEtC,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB;;;;OAIG;IACH,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEhC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,OAAO,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,KAAK,QAAQ;YACX,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,QAAQ;YACX,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,8CAA8C;QAC9C,KAAK,OAAO;YACV,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QACvC,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QACxC,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI,CAAC;QACV,KAAK,MAAM;YACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO;QACT;YACE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,OAAO,QAAQ,KAAK,EAAE,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "costaff-workspace",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Publish documents, decks and workbooks to CoStaff Workspace, and pull their source back out",
5
5
  "keywords": [
6
6
  "costaff",
@@ -31,6 +31,7 @@
31
31
  },
32
32
  "files": [
33
33
  "dist",
34
+ "skills",
34
35
  "README.zh-TW.md"
35
36
  ],
36
37
  "scripts": {
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: costaff-workspace
3
+ description: Publish a built open-doc, open-slide or open-sheet project to CoStaff Workspace and get shareable links back, pull a published file's source onto this machine to keep working on it, or keep a project's themes/ folder in the workspace. Use whenever the user asks to publish, ship, share, upload or "put this online", asks for the link to something they published, wants to continue editing something that lives in the workspace, or mentions costaff-workspace, workspace.costaffs.app, or a token that looks like a workspace address.
4
+ ---
5
+
6
+ # Publishing to CoStaff Workspace
7
+
8
+ The `costaff-workspace` CLI is the only way files get into the workspace — there
9
+ is no browser upload. Every command takes `--json`, which prints one line on
10
+ stdout and nothing else. Use it: the prose output is for people and its wording
11
+ is not a contract.
12
+
13
+ ## Before anything else: is this machine signed in?
14
+
15
+ ```bash
16
+ costaff-workspace whoami --json
17
+ ```
18
+
19
+ ```json
20
+ {"ok":true,"command":"whoami","endpoint":"https://workspace.costaffs.app","signedIn":false,"source":"none","account":null,"expiresAt":null}
21
+ ```
22
+
23
+ **If `signedIn` is false, stop and ask the user to run `costaff-workspace login`
24
+ themselves.** Signing in prints a device code that has to be approved in a
25
+ browser; you cannot do that, and you must not try. Under `--json` every command
26
+ that would need it fails immediately rather than waiting, so a run that skips
27
+ this check does not hang — it just fails later with less to say.
28
+
29
+ `source` tells you where a credential came from: `flag`, `env`, `stored`, or
30
+ `none`. `whoami` reads local state only, so a token revoked on the server still
31
+ reads as signed in until something uses it.
32
+
33
+ ## Publishing
34
+
35
+ Publishing sends the **built** output, so build first. Then, from the project
36
+ folder:
37
+
38
+ ```bash
39
+ pnpm build
40
+ costaff-workspace push --dry-run --json # packages and reports, uploads nothing
41
+ costaff-workspace push --json
42
+ ```
43
+
44
+ Always dry-run first and show the user what it found. `push` guesses the slug
45
+ from the folder name and the kind from `package.json`; a wrong guess publishes
46
+ under the wrong identity, and the dry run is where that is cheap to catch.
47
+
48
+ ```json
49
+ {"ok":true,"command":"push","endpoint":"https://workspace.costaffs.app","dryRun":false,
50
+ "items":[{"slug":"q3-report","kind":"deck","token":"8fjq2ldk3nx7yrpv0aet",
51
+ "url":"https://workspace.costaffs.app/8fjq2ldk3nx7yrpv0aet"}]}
52
+ ```
53
+
54
+ Give the user the `url`. Keep the `token`: it is what `pull` takes.
55
+
56
+ **Ask before pushing.** A push puts the user's work on a public host under an
57
+ address they can hand to other people. It is private until they share it, and
58
+ re-pushing keeps the same address, so this is not dangerous — but it is theirs
59
+ to decide, and an unasked-for publish is a surprise.
60
+
61
+ A project with several documents publishes each as its own bundle, so `items`
62
+ usually has more than one entry. Report all of them.
63
+
64
+ ## Continuing somewhere else
65
+
66
+ ```bash
67
+ costaff-workspace pull <token> ./my-doc --json
68
+ cd my-doc && pnpm install
69
+ ```
70
+
71
+ What comes back is a complete project. Build it, push it, and the same address
72
+ updates — that is how a document moves between machines without the link
73
+ changing.
74
+
75
+ ## Themes
76
+
77
+ A theme is a house style the next document can start from: `themes/<id>.md`
78
+ describes it, an optional `themes/<id>.demo.tsx` shows it. Themes belong to the
79
+ account rather than to one file.
80
+
81
+ ```bash
82
+ costaff-workspace theme list --json # what the account already has
83
+ costaff-workspace theme pull aurora # copy one into ./themes to follow it
84
+ costaff-workspace theme push # send this project's themes up
85
+ ```
86
+
87
+ When the user asks for a document that should look like their others, check
88
+ `theme list` first and pull the spec rather than inventing a look.
89
+
90
+ ## When something fails
91
+
92
+ Every failure is the same shape, with exit status 1:
93
+
94
+ ```json
95
+ {"ok":false,"error":"not signed in — run `costaff-workspace login` once, or set COSTAFF_WORKSPACE_TOKEN"}
96
+ ```
97
+
98
+ Read `error` and say what it says. Two worth recognising:
99
+
100
+ - **not signed in** — ask the user to run `login`. Do not retry.
101
+ - **a guess it could not make** — `push` refuses rather than inventing a slug or
102
+ kind. Pass `--slug` or `--kind` once you and the user agree what they are.
103
+
104
+ ## What not to do
105
+
106
+ - Do not open a browser, or tell the user you will sign in for them.
107
+ - Do not parse the human-readable output. `--json` exists for this.
108
+ - Do not push without building first; the workspace serves what `dist/` held.
109
+ - Do not push a project you have not been asked to publish.