@take-out/cli 0.7.0 → 0.7.1-1784516754882

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
@@ -63,7 +63,8 @@ takeout check
63
63
 
64
64
  #### `takeout docs`
65
65
 
66
- Manage and retrieve documentation files:
66
+ Read documentation from the current repository's `skills/` or `docs/`
67
+ directory:
67
68
 
68
69
  ```bash
69
70
  # list available docs
@@ -75,9 +76,6 @@ takeout docs get zero tamagui
75
76
  # get path to docs directory
76
77
  takeout docs path
77
78
 
78
- # eject docs to local ./docs folder
79
- takeout docs eject
80
-
81
79
  # generate Claude Code skills from docs
82
80
  takeout skills generate
83
81
  takeout skills generate --clean # clean and regenerate
@@ -87,7 +85,7 @@ takeout skills generate --clean # clean and regenerate
87
85
 
88
86
  The `skills generate` command generates Claude Code skills from your documentation:
89
87
 
90
- 1. scans docs from both `./docs/` (local) and package docs
88
+ 1. scans docs from `./skills/` when present, otherwise `./docs/`
91
89
  2. only docs with YAML frontmatter containing `name` and `description` become skills
92
90
  3. those docs are symlinked into `.claude/skills/`
93
91
 
@@ -37,45 +37,39 @@ __export(docs_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(docs_exports);
39
39
  var import_node_fs = require("node:fs");
40
- var import_node_module = require("node:module");
41
40
  var import_node_path = require("node:path");
42
41
  var import_citty = require("citty");
43
42
  var import_picocolors = __toESM(require("picocolors"), 1);
44
- var import_sync = require("../utils/sync.cjs");
45
- const import_meta = {};
46
- const require2 = (0, import_node_module.createRequire)(import_meta.url);
47
- const DOCS_DIR = (0, import_node_path.dirname)(require2.resolve("@take-out/docs/package.json"));
43
+ function resolveDocsDir(cwd = process.cwd()) {
44
+ const skillsDir = (0, import_node_path.join)(cwd, "skills");
45
+ if ((0, import_node_fs.existsSync)(skillsDir)) return skillsDir;
46
+ const docsDir = (0, import_node_path.join)(cwd, "docs");
47
+ if ((0, import_node_fs.existsSync)(docsDir)) return docsDir;
48
+ throw new Error(`No docs or skills directory found in ${cwd}`);
49
+ }
48
50
  const listCommand = (0, import_citty.defineCommand)({
49
51
  meta: {
50
52
  name: "list",
51
- description: "List all available documentation files"
53
+ description: "List repository documentation files"
52
54
  },
53
55
  async run() {
54
- if (!(0, import_node_fs.existsSync)(DOCS_DIR)) {
55
- console.error(import_picocolors.default.red("\u2717 Docs directory not found"));
56
+ let docsDir;
57
+ try {
58
+ docsDir = resolveDocsDir();
59
+ } catch (error) {
60
+ console.error(import_picocolors.default.red(`\u2717 ${error instanceof Error ? error.message : String(error)}`));
56
61
  process.exit(1);
57
62
  }
58
- const files = (0, import_node_fs.readdirSync)(DOCS_DIR).filter(f => f.endsWith(".md")).sort();
63
+ const files = (0, import_node_fs.readdirSync)(docsDir).filter(file => file.endsWith(".md")).sort();
59
64
  console.info();
60
65
  console.info(import_picocolors.default.bold(import_picocolors.default.cyan("\u{1F4DA} Available Documentation")));
61
66
  console.info();
62
67
  for (const file of files) {
63
68
  const name = file.replace(/\.md$/, "");
64
- const path = (0, import_node_path.join)(DOCS_DIR, file);
65
- let description = "";
66
- try {
67
- const content = (0, import_node_fs.readFileSync)(path, "utf-8");
68
- const match = content.match(/^#\s+(.+)$/m);
69
- if (match?.[1]) {
70
- description = match[1];
71
- }
72
- } catch {}
73
- if (description) {
74
- console.info(` ${import_picocolors.default.green(name)}`);
75
- console.info(` ${import_picocolors.default.dim(description)}`);
76
- } else {
77
- console.info(` ${import_picocolors.default.green(name)}`);
78
- }
69
+ const content = (0, import_node_fs.readFileSync)((0, import_node_path.join)(docsDir, file), "utf-8");
70
+ const heading = content.match(/^#\s+(.+)$/m)?.[1];
71
+ console.info(` ${import_picocolors.default.green(name)}`);
72
+ if (heading) console.info(` ${import_picocolors.default.dim(heading)}`);
79
73
  }
80
74
  console.info();
81
75
  console.info(import_picocolors.default.dim(`Use 'takeout docs get <name>' to view a document`));
@@ -85,7 +79,7 @@ const listCommand = (0, import_citty.defineCommand)({
85
79
  const getCommand = (0, import_citty.defineCommand)({
86
80
  meta: {
87
81
  name: "get",
88
- description: "Get the content of one or more documentation files"
82
+ description: "Get the content of one or more repository documentation files"
89
83
  },
90
84
  args: {
91
85
  name: {
@@ -98,65 +92,38 @@ const getCommand = (0, import_citty.defineCommand)({
98
92
  async run({
99
93
  args
100
94
  }) {
95
+ let docsDir;
96
+ try {
97
+ docsDir = resolveDocsDir();
98
+ } catch (error) {
99
+ console.error(import_picocolors.default.red(`\u2717 ${error instanceof Error ? error.message : String(error)}`));
100
+ process.exit(1);
101
+ }
101
102
  const names = args._.length > 0 ? args._ : [args.name];
102
103
  const results = [];
103
- const errors = [];
104
- const cwd = process.cwd();
105
- const localSkillsDir = (0, import_node_path.join)(cwd, "skills");
106
- const localDocsDir = (0, import_node_path.join)(cwd, "docs");
107
104
  for (const name of names) {
108
105
  const fileName = name.endsWith(".md") ? name : `${name}.md`;
109
- const localSkillsPath = (0, import_node_path.join)(localSkillsDir, fileName);
110
- const localDocsPath = (0, import_node_path.join)(localDocsDir, fileName);
111
- const packageFilePath = (0, import_node_path.join)(DOCS_DIR, fileName);
112
- let filePath = null;
113
- if ((0, import_node_fs.existsSync)(localSkillsPath)) {
114
- filePath = localSkillsPath;
115
- } else if ((0, import_node_fs.existsSync)(localDocsPath)) {
116
- filePath = localDocsPath;
117
- } else if ((0, import_node_fs.existsSync)(packageFilePath)) {
118
- filePath = packageFilePath;
119
- }
120
- if (!filePath) {
121
- errors.push({
122
- name,
123
- error: "File not found"
124
- });
106
+ const filePath = (0, import_node_path.join)(docsDir, fileName);
107
+ if (!(0, import_node_fs.existsSync)(filePath)) {
108
+ console.error(import_picocolors.default.red(`\u2717 Doc file not found: ${name}`));
125
109
  continue;
126
110
  }
127
- try {
128
- const content = (0, import_node_fs.readFileSync)(filePath, "utf-8");
129
- results.push({
130
- name,
131
- content
132
- });
133
- } catch (err) {
134
- errors.push({
135
- name,
136
- error: String(err)
137
- });
138
- }
111
+ results.push({
112
+ name,
113
+ content: (0, import_node_fs.readFileSync)(filePath, "utf-8")
114
+ });
139
115
  }
140
- if (errors.length > 0) {
141
- for (const {
142
- name
143
- } of errors) {
144
- console.error(import_picocolors.default.red(`\u2717 Doc file not found: ${name}`));
145
- }
116
+ if (results.length === 0) {
146
117
  console.info();
147
118
  console.info(import_picocolors.default.dim(`Use 'takeout docs list' to see available docs`));
148
- if (results.length === 0) {
149
- process.exit(1);
150
- }
151
- console.info();
119
+ process.exit(1);
152
120
  }
153
- for (let i = 0; i < results.length; i++) {
154
- const result = results[i];
155
- if (!result) continue;
121
+ for (let index = 0; index < results.length; index++) {
122
+ const result = results[index];
156
123
  console.info(`# ${result.name}`);
157
124
  console.info();
158
125
  console.info(result.content);
159
- if (i < results.length - 1) {
126
+ if (index < results.length - 1) {
160
127
  console.info();
161
128
  console.info("---");
162
129
  console.info();
@@ -167,7 +134,7 @@ const getCommand = (0, import_citty.defineCommand)({
167
134
  const pathCommand = (0, import_citty.defineCommand)({
168
135
  meta: {
169
136
  name: "path",
170
- description: "Get the absolute path to a documentation file"
137
+ description: "Get the absolute path to repository documentation"
171
138
  },
172
139
  args: {
173
140
  name: {
@@ -179,12 +146,19 @@ const pathCommand = (0, import_citty.defineCommand)({
179
146
  async run({
180
147
  args
181
148
  }) {
149
+ let docsDir;
150
+ try {
151
+ docsDir = resolveDocsDir();
152
+ } catch (error) {
153
+ console.error(import_picocolors.default.red(`\u2717 ${error instanceof Error ? error.message : String(error)}`));
154
+ process.exit(1);
155
+ }
182
156
  if (!args.name) {
183
- console.info(DOCS_DIR);
157
+ console.info(docsDir);
184
158
  return;
185
159
  }
186
160
  const fileName = args.name.endsWith(".md") ? args.name : `${args.name}.md`;
187
- const filePath = (0, import_node_path.join)(DOCS_DIR, fileName);
161
+ const filePath = (0, import_node_path.join)(docsDir, fileName);
188
162
  if (!(0, import_node_fs.existsSync)(filePath)) {
189
163
  console.error(import_picocolors.default.red(`\u2717 Doc file not found: ${args.name}`));
190
164
  process.exit(1);
@@ -192,114 +166,14 @@ const pathCommand = (0, import_citty.defineCommand)({
192
166
  console.info(filePath);
193
167
  }
194
168
  });
195
- const ejectCommand = (0, import_citty.defineCommand)({
196
- meta: {
197
- name: "eject",
198
- description: "Eject Takeout documentation files into your project"
199
- },
200
- args: {
201
- yes: {
202
- type: "boolean",
203
- description: "Skip confirmations and eject all files",
204
- default: false
205
- }
206
- },
207
- async run({
208
- args
209
- }) {
210
- const cwd = process.cwd();
211
- const targetDocsDir = (0, import_node_path.join)(cwd, "docs");
212
- const sourceDocsDir = DOCS_DIR;
213
- console.info();
214
- console.info(import_picocolors.default.bold(import_picocolors.default.cyan("\u{1F4DA} Eject Docs")));
215
- console.info();
216
- console.info(import_picocolors.default.dim(`Source: ${sourceDocsDir}`));
217
- console.info(import_picocolors.default.dim(`Target: ${targetDocsDir}`));
218
- console.info();
219
- if (!(0, import_node_fs.existsSync)(sourceDocsDir)) {
220
- console.error(import_picocolors.default.red("\u2717 Source docs directory not found in Takeout package"));
221
- process.exit(1);
222
- }
223
- if (!(0, import_node_fs.existsSync)(targetDocsDir)) {
224
- console.info(import_picocolors.default.yellow("\u26A0 Target docs directory does not exist, will create it"));
225
- (0, import_node_fs.mkdirSync)(targetDocsDir, {
226
- recursive: true
227
- });
228
- }
229
- const sourceFiles = (0, import_node_fs.readdirSync)(sourceDocsDir).filter(f => f.endsWith(".md"));
230
- if (sourceFiles.length === 0) {
231
- console.info(import_picocolors.default.yellow("No markdown files found in Takeout docs"));
232
- return;
233
- }
234
- const filesToSync = [];
235
- const stats = {
236
- new: 0,
237
- modified: 0,
238
- identical: 0
239
- };
240
- for (const file of sourceFiles) {
241
- const sourcePath = (0, import_node_path.join)(sourceDocsDir, file);
242
- const targetPath = (0, import_node_path.join)(targetDocsDir, file);
243
- const status = (0, import_sync.compareFiles)(sourcePath, targetPath);
244
- stats[status]++;
245
- filesToSync.push({
246
- name: file,
247
- sourcePath,
248
- targetPath,
249
- status,
250
- sourceSize: (0, import_sync.getFileSize)(sourcePath),
251
- targetSize: (0, import_sync.getFileSize)(targetPath)
252
- });
253
- }
254
- console.info(import_picocolors.default.bold("Summary:"));
255
- console.info(` ${import_picocolors.default.green(`${stats.new} new`)}`);
256
- console.info(` ${import_picocolors.default.yellow(`${stats.modified} modified`)}`);
257
- console.info(` ${import_picocolors.default.dim(`${stats.identical} identical`)}`);
258
- console.info();
259
- if (stats.new === 0 && stats.modified === 0) {
260
- console.info(import_picocolors.default.green("\u2713 All docs are already up to date!"));
261
- return;
262
- }
263
- const sortOrder = {
264
- new: 0,
265
- modified: 1,
266
- identical: 2
267
- };
268
- filesToSync.sort((a, b) => sortOrder[a.status] - sortOrder[b.status]);
269
- let syncedCount = 0;
270
- for (const file of filesToSync) {
271
- if (args.yes && file.status !== "identical") {
272
- const targetDir = (0, import_node_path.join)(targetDocsDir);
273
- if (!(0, import_node_fs.existsSync)(targetDir)) {
274
- (0, import_node_fs.mkdirSync)(targetDir, {
275
- recursive: true
276
- });
277
- }
278
- const content = (0, import_node_fs.readFileSync)(file.sourcePath);
279
- (0, import_node_fs.writeFileSync)(file.targetPath, content);
280
- console.info(import_picocolors.default.green(` \u2713 ${file.name}`));
281
- syncedCount++;
282
- } else {
283
- const wasSynced = await (0, import_sync.syncFileWithConfirmation)(file);
284
- if (wasSynced) {
285
- syncedCount++;
286
- }
287
- }
288
- }
289
- console.info();
290
- console.info(import_picocolors.default.bold(import_picocolors.default.green(`\u2713 Complete: ${syncedCount} file(s) ejected`)));
291
- console.info();
292
- }
293
- });
294
169
  const docsCommand = (0, import_citty.defineCommand)({
295
170
  meta: {
296
171
  name: "docs",
297
- description: "List and retrieve Takeout documentation"
172
+ description: "List and retrieve repository documentation"
298
173
  },
299
174
  subCommands: {
300
175
  list: listCommand,
301
176
  get: getCommand,
302
- path: pathCommand,
303
- eject: ejectCommand
177
+ path: pathCommand
304
178
  }
305
179
  });
@@ -285,7 +285,7 @@ const onboardCommand = (0, import_citty.defineCommand)({
285
285
  console.info();
286
286
  console.info(" bun ios # build iOS dev app");
287
287
  console.info(" bun android # build Android dev app");
288
- console.info(" bun tko docs list # view Takeout docs");
288
+ console.info(" bun tko docs list # view repository docs");
289
289
  console.info();
290
290
  }
291
291
  if (startStep !== "production") {
@@ -690,7 +690,7 @@ async function setupUncloudDeployment(cwd) {
690
690
  console.info(import_picocolors.default.gray(" uc machine add --name server-2 root@IP"));
691
691
  console.info(import_picocolors.default.gray(" uc scale web 3 # run 3 instances"));
692
692
  console.info();
693
- console.info(import_picocolors.default.gray("view detailed guide: bun tko docs read deployment-uncloud"));
693
+ console.info(import_picocolors.default.gray("view detailed guide: bun tko docs get deploy-uncloud"));
694
694
  console.info(import_picocolors.default.gray("or see: docs/deployment-uncloud.md"));
695
695
  }
696
696
  async function setupSSTDeployment(cwd) {
@@ -37,18 +37,9 @@ __export(skills_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(skills_exports);
39
39
  var import_node_fs = require("node:fs");
40
- var import_node_module = require("node:module");
41
40
  var import_node_path = require("node:path");
42
41
  var import_citty = require("citty");
43
42
  var import_picocolors = __toESM(require("picocolors"), 1);
44
- const import_meta = {};
45
- const require2 = (0, import_node_module.createRequire)(import_meta.url);
46
- let DOCS_DIR;
47
- try {
48
- DOCS_DIR = (0, import_node_path.dirname)(require2.resolve("@take-out/docs/package.json"));
49
- } catch {
50
- DOCS_DIR = "";
51
- }
52
43
  const SKILL_PREFIX = "takeout-";
53
44
  function hasSkillFrontmatter(content) {
54
45
  if (!content.startsWith("---")) return false;
@@ -71,7 +62,6 @@ function resolveLocalDocsDir(cwd) {
71
62
  }
72
63
  function collectAllDocs(cwd) {
73
64
  const docs = [];
74
- const seen = /* @__PURE__ */new Set();
75
65
  const localDocsDir = resolveLocalDocsDir(cwd);
76
66
  if ((0, import_node_fs.existsSync)(localDocsDir)) {
77
67
  const files = (0, import_node_fs.readdirSync)(localDocsDir).filter(f => f.endsWith(".md"));
@@ -79,23 +69,8 @@ function collectAllDocs(cwd) {
79
69
  const name = file.replace(/\.md$/, "");
80
70
  docs.push({
81
71
  name,
82
- path: (0, import_node_path.join)(localDocsDir, file),
83
- source: "local"
72
+ path: (0, import_node_path.join)(localDocsDir, file)
84
73
  });
85
- seen.add(name);
86
- }
87
- }
88
- if (DOCS_DIR && (0, import_node_fs.existsSync)(DOCS_DIR)) {
89
- const files = (0, import_node_fs.readdirSync)(DOCS_DIR).filter(f => f.endsWith(".md"));
90
- for (const file of files) {
91
- const name = file.replace(/\.md$/, "");
92
- if (!seen.has(name)) {
93
- docs.push({
94
- name,
95
- path: (0, import_node_path.join)(DOCS_DIR, file),
96
- source: "package"
97
- });
98
- }
99
74
  }
100
75
  }
101
76
  return docs;
@@ -165,8 +140,7 @@ async function generateDocSkills(cwd, clean) {
165
140
  if (!shouldCreate) continue;
166
141
  (0, import_node_fs.symlinkSync)(relativePath, skillFile);
167
142
  symlinked++;
168
- const sourceLabel = doc.source === "local" ? import_picocolors.default.blue("local") : import_picocolors.default.dim("package");
169
- console.info(` ${import_picocolors.default.green("\u27F7")} ${skillName} ${sourceLabel} ${import_picocolors.default.dim("(symlink)")}`);
143
+ console.info(` ${import_picocolors.default.green("\u27F7")} ${skillName} ${import_picocolors.default.dim("(symlink)")}`);
170
144
  } else {
171
145
  if (!hasFrontmatter) {
172
146
  skipped++;
@@ -194,7 +168,7 @@ async function generateDocSkills(cwd, clean) {
194
168
  if (stat.isSymbolicLink()) {
195
169
  const linkTarget = (0, import_node_fs.readlinkSync)(skillFile);
196
170
  const resolvedTarget = (0, import_node_path.resolve)(skillDir, linkTarget);
197
- shouldUnlink = resolvedTarget.startsWith(`${localDocsDir}/`) || !!DOCS_DIR && resolvedTarget.startsWith(`${DOCS_DIR}/`);
171
+ shouldUnlink = resolvedTarget.startsWith(`${localDocsDir}/`);
198
172
  }
199
173
  } catch {}
200
174
  if (!shouldUnlink) continue;
@@ -40,29 +40,18 @@ var import_node_child_process = require("node:child_process");
40
40
  var import_node_fs = require("node:fs");
41
41
  var import_node_os = require("node:os");
42
42
  var import_node_path = require("node:path");
43
- var import_node_url = require("node:url");
44
43
  var import_citty = require("citty");
45
44
  var import_picocolors = __toESM(require("picocolors"), 1);
46
45
  var import_prompts = require("../utils/prompts.cjs");
47
- const import_meta = {};
48
46
  const UPSTREAM_REPO = "tamagui/takeout2";
49
47
  const UPSTREAM_REMOTE = "takeout-upstream";
50
48
  const TAKEOUT_FILE = ".takeout";
51
49
  function getSyncPrompt() {
52
- try {
53
- const currentDir = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
54
- let monorepoRoot = currentDir;
55
- while (monorepoRoot !== (0, import_node_path.parse)(monorepoRoot).root) {
56
- const promptPath = (0, import_node_path.join)(monorepoRoot, "packages", "docs", "sync-prompt.md");
57
- if ((0, import_node_fs.existsSync)(promptPath)) {
58
- return (0, import_node_fs.readFileSync)(promptPath, "utf-8");
59
- }
60
- monorepoRoot = (0, import_node_path.dirname)(monorepoRoot);
61
- }
62
- throw new Error("Could not find sync-prompt.md in packages/docs");
63
- } catch (error) {
64
- throw new Error(`Could not load sync prompt: ${error instanceof Error ? error.message : "Unknown error"}`);
50
+ const promptPath = (0, import_node_path.join)(process.cwd(), "docs", "upgrade.md");
51
+ if (!(0, import_node_fs.existsSync)(promptPath)) {
52
+ throw new Error("Missing docs/upgrade.md. Copy it from https://github.com/tamagui/takeout2/blob/main/docs/upgrade.md and rerun `bun tko sync`.");
65
53
  }
54
+ return (0, import_node_fs.readFileSync)(promptPath, "utf-8");
66
55
  }
67
56
  function checkToolAvailable(command) {
68
57
  try {