rbin-task-flow 1.19.4 → 1.23.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 (65) hide show
  1. package/.claude/skills/rbin-coding-standards/SKILL.md +29 -0
  2. package/.claude/skills/rbin-coding-standards/reference.md +42 -0
  3. package/.claude/skills/rbin-git/SKILL.md +39 -0
  4. package/.claude/skills/task-flow-audit/SKILL.md +15 -0
  5. package/.claude/skills/task-flow-check/SKILL.md +15 -0
  6. package/.claude/skills/task-flow-estimate/SKILL.md +15 -0
  7. package/.claude/skills/task-flow-generate-flow/SKILL.md +15 -0
  8. package/.claude/skills/task-flow-improve-changes/SKILL.md +15 -0
  9. package/.claude/skills/task-flow-refactor/SKILL.md +14 -0
  10. package/.claude/skills/task-flow-report/SKILL.md +15 -0
  11. package/.claude/skills/task-flow-review/SKILL.md +14 -0
  12. package/.claude/skills/task-flow-run/SKILL.md +28 -0
  13. package/.claude/skills/task-flow-run/workflow.md +59 -0
  14. package/.claude/skills/task-flow-status/SKILL.md +13 -0
  15. package/.claude/skills/task-flow-sync/SKILL.md +30 -0
  16. package/.claude/skills/task-flow-sync/workflow.md +57 -0
  17. package/.claude/skills/task-flow-think/SKILL.md +17 -0
  18. package/.codex/config.toml +10 -0
  19. package/.cursor/rules/code_comments.mdc +4 -4
  20. package/.cursor/rules/coding_standards.mdc +57 -810
  21. package/.cursor/rules/commit_practices.mdc +5 -138
  22. package/.cursor/rules/cursor_rules.mdc +4 -3
  23. package/.cursor/rules/git_control.mdc +5 -86
  24. package/.cursor/rules/graphify-task-flow.mdc +31 -0
  25. package/.cursor/rules/rbin-git-policy.mdc +47 -0
  26. package/.cursor/rules/self_improve.mdc +3 -3
  27. package/.cursor/rules/task-flow-cursor.mdc +51 -0
  28. package/.cursor/rules/task-flow-sync.mdc +46 -0
  29. package/.cursor/rules/task_analysis.mdc +31 -179
  30. package/.cursor/rules/task_audit.mdc +6 -5
  31. package/.cursor/rules/task_check.mdc +2 -3
  32. package/.cursor/rules/task_estimate.mdc +3 -4
  33. package/.cursor/rules/task_execution.mdc +26 -138
  34. package/.cursor/rules/task_generate_flow.mdc +2 -3
  35. package/.cursor/rules/task_generation.mdc +22 -140
  36. package/.cursor/rules/task_improve_changes.mdc +3 -4
  37. package/.cursor/rules/task_refactor.mdc +4 -5
  38. package/.cursor/rules/task_report.mdc +3 -4
  39. package/.cursor/rules/task_review.mdc +4 -5
  40. package/.cursor/rules/task_status.mdc +4 -4
  41. package/.cursor/rules/task_work.mdc +23 -210
  42. package/.task-flow/AI-PLATFORMS.md +104 -0
  43. package/.task-flow/CODEX.md +141 -0
  44. package/.task-flow/CURSOR.md +94 -0
  45. package/.task-flow/GRAPHIFY.md +112 -0
  46. package/.task-flow/OPTIMIZATION-IMPLEMENTATION-TASKS.md +365 -0
  47. package/.task-flow/OPTIMIZATION-PLAN.md +264 -0
  48. package/.task-flow/README.md +19 -4
  49. package/.task-flow/docs/coding-standards-full.md +851 -0
  50. package/.task-flow/platforms/claude-code.md +352 -0
  51. package/.task-flow/platforms/codex.md +379 -0
  52. package/.task-flow/platforms/cursor.md +333 -0
  53. package/AGENTS.md +69 -31
  54. package/CLAUDE.md +56 -48
  55. package/README.md +86 -10
  56. package/bin/cli.js +41 -16
  57. package/lib/codex.js +45 -0
  58. package/lib/cursor.js +41 -0
  59. package/lib/gitignore.js +101 -0
  60. package/lib/graphify.js +118 -0
  61. package/lib/install.js +106 -52
  62. package/lib/profiles.js +110 -0
  63. package/lib/skills.js +34 -0
  64. package/lib/utils.js +38 -2
  65. package/package.json +6 -2
package/lib/install.js CHANGED
@@ -3,21 +3,66 @@ const path = require('path');
3
3
  const chalk = require('chalk');
4
4
  const ora = require('ora');
5
5
  const { showHeader, showSuccess, showError, showWarning, showInfo, showNextSteps } = require('./utils');
6
+ const { setupGraphifyIntegration } = require('./graphify');
7
+ const { copySkillsToProject } = require('./skills');
8
+ const { setupCodexIntegration } = require('./codex');
9
+ const { setupCursorIntegration } = require('./cursor');
10
+ const {
11
+ PROFILE_MINIMAL,
12
+ PROFILE_STANDARD,
13
+ resolveProfile,
14
+ resolveShareAiConfig,
15
+ writeInstallMeta,
16
+ copyCursorRules,
17
+ } = require('./profiles');
18
+ const { updateGitignore } = require('./gitignore');
19
+
20
+ const PROFILES = { STANDARD: PROFILE_STANDARD, MINIMAL: PROFILE_MINIMAL };
6
21
 
7
22
  const TEMPLATE_DIR = path.join(__dirname, '..');
23
+ const PACKAGE_VERSION = require('../package.json').version;
8
24
 
9
25
  async function installInProject(targetPath, options = {}) {
10
26
  const isUpdate = options.update || false;
27
+ const isReset = options.reset || false;
28
+
29
+ let profile;
30
+ let shareAiConfig;
31
+ try {
32
+ profile = await resolveProfile(targetPath, { profile: options.profile });
33
+ shareAiConfig = await resolveShareAiConfig(targetPath, {
34
+ shareAiConfig: options.shareAiConfig,
35
+ });
36
+ } catch (error) {
37
+ showError(error.message);
38
+ process.exit(1);
39
+ }
11
40
 
12
41
  showHeader();
13
42
 
14
- if (isUpdate) {
43
+ if (isReset) {
44
+ console.log(chalk.blue('♻️ Resetting RBIN Task Flow...'));
45
+ } else if (isUpdate) {
15
46
  console.log(chalk.blue('🔄 Updating RBIN Task Flow...'));
16
47
  } else {
17
48
  console.log(chalk.blue('🚀 Installing RBIN Task Flow...'));
18
49
  }
19
50
 
20
- console.log(chalk.blue('📁 Target:'), targetPath, '\n');
51
+ console.log(chalk.blue('📁 Target:'), targetPath);
52
+ console.log(
53
+ chalk.blue('📦 Profile:'),
54
+ profile === PROFILES.MINIMAL ? chalk.yellow('minimal') : chalk.green('standard'),
55
+ profile === PROFILES.MINIMAL
56
+ ? chalk.gray('(2 always-on rules + skills; workflows via @task-flow-*)')
57
+ : chalk.gray('(all Cursor rules + skills)')
58
+ );
59
+ console.log(
60
+ chalk.blue('🔗 Git:'),
61
+ shareAiConfig
62
+ ? chalk.yellow('share-ai-config') + chalk.gray(' (.cursor/skills + .cursor/rules versionáveis)')
63
+ : chalk.gray('local .cursor/ gitignored (default)')
64
+ );
65
+ console.log('');
21
66
 
22
67
  const spinner = ora('Processing...').start();
23
68
 
@@ -36,10 +81,17 @@ async function installInProject(targetPath, options = {}) {
36
81
 
37
82
  spinner.text = 'Creating directories...';
38
83
 
84
+ if (isReset) {
85
+ await fs.remove(path.join(targetPath, '.task-flow'));
86
+ }
87
+
39
88
  const dirs = [
40
89
  '.cursor/rules',
90
+ '.cursor/skills',
41
91
  '.claude',
42
- '.task-flow'
92
+ '.claude/skills',
93
+ '.task-flow',
94
+ '.codex'
43
95
  ];
44
96
 
45
97
  for (const dir of dirs) {
@@ -48,11 +100,33 @@ async function installInProject(targetPath, options = {}) {
48
100
 
49
101
  spinner.text = 'Copying configuration files...';
50
102
 
51
- await copyConfigs(targetPath, isUpdate);
103
+ await copyConfigs(targetPath, { update: isUpdate, reset: isReset, profile });
52
104
 
53
105
  spinner.text = 'Updating .gitignore...';
54
106
 
55
- await updateGitignore(targetPath);
107
+ await updateGitignore(targetPath, { shareAiConfig });
108
+ showSuccess('.gitignore updated');
109
+ if (shareAiConfig) {
110
+ showInfo('Git: .cursor/skills/ and .cursor/rules/ can be committed (see .gitignore comment)');
111
+ }
112
+
113
+ spinner.text = 'Installing agent skills...';
114
+ await copySkillsToProject(targetPath);
115
+
116
+ spinner.text = 'Configuring Cursor (rules + skills)...';
117
+ await setupCursorIntegration(targetPath, { profile });
118
+
119
+ await writeInstallMeta(targetPath, {
120
+ profile,
121
+ packageVersion: PACKAGE_VERSION,
122
+ shareAiConfig,
123
+ });
124
+
125
+ spinner.text = 'Configuring Codex (AGENTS.md + .codex/config.toml)...';
126
+ await setupCodexIntegration(targetPath);
127
+
128
+ spinner.text = 'Configuring Graphify coexistence...';
129
+ await setupGraphifyIntegration(targetPath, { extract: options.graphify === true });
56
130
 
57
131
  spinner.succeed(chalk.green('Installation completed!'));
58
132
 
@@ -69,15 +143,21 @@ async function installInProject(targetPath, options = {}) {
69
143
  }
70
144
  }
71
145
 
72
- async function copyConfigs(targetPath, isUpdate = false) {
73
- const cursorRulesPath = path.join(TEMPLATE_DIR, '.cursor/rules');
74
- const cursorRulesDest = path.join(targetPath, '.cursor/rules');
75
- if (fs.existsSync(cursorRulesPath)) {
76
- if (isUpdate && fs.existsSync(cursorRulesDest)) {
77
- await fs.emptyDir(cursorRulesDest);
78
- }
79
- await fs.copy(cursorRulesPath, cursorRulesDest, { overwrite: true });
80
- showSuccess('Cursor rules');
146
+ async function copyConfigs(targetPath, options = {}) {
147
+ const isUpdate = options.update || false;
148
+ const isReset = options.reset || false;
149
+ const profile = options.profile;
150
+
151
+ const rulesResult = await copyCursorRules(targetPath, TEMPLATE_DIR, {
152
+ profile,
153
+ update: isUpdate,
154
+ reset: isReset,
155
+ });
156
+ if (rulesResult?.mode === PROFILE_MINIMAL) {
157
+ showSuccess(`Cursor rules (minimal: ${rulesResult.count} files, always-on only)`);
158
+ showInfo('Use @task-flow-* skills for sync, run, audit — omit heavy .mdc rules to save tokens');
159
+ } else if (rulesResult) {
160
+ showSuccess(`Cursor rules (${rulesResult.count} files)`);
81
161
  }
82
162
 
83
163
  const cursorSettingsPath = path.join(TEMPLATE_DIR, '.cursor/settings.json');
@@ -120,10 +200,12 @@ async function copyConfigs(targetPath, isUpdate = false) {
120
200
  showSuccess('Codex instructions (AGENTS.md)');
121
201
  }
122
202
 
123
- await copyTaskFlow(targetPath, isUpdate);
203
+ await copyTaskFlow(targetPath, { update: isUpdate, reset: isReset });
124
204
  }
125
205
 
126
- async function copyTaskFlow(targetPath, isUpdate = false) {
206
+ async function copyTaskFlow(targetPath, options = {}) {
207
+ const isUpdate = options.update || false;
208
+ const isReset = options.reset || false;
127
209
  const taskFlowSrc = path.join(TEMPLATE_DIR, '.task-flow');
128
210
  const taskFlowDest = path.join(targetPath, '.task-flow');
129
211
 
@@ -136,11 +218,16 @@ async function copyTaskFlow(targetPath, isUpdate = false) {
136
218
  path.join(taskFlowDest, 'tasks.input.txt'),
137
219
  path.join(taskFlowDest, 'tasks.status.md'),
138
220
  path.join(taskFlowDest, 'tasks.flow.md'),
221
+ path.join(taskFlowDest, 'install-meta.json'),
139
222
  ];
140
223
 
141
224
  await fs.copy(taskFlowSrc, taskFlowDest, {
142
225
  overwrite: true,
143
226
  filter: (src, dest) => {
227
+ if (isReset) {
228
+ return true;
229
+ }
230
+
144
231
  if (PROTECTED.some((p) => src.startsWith(p) || dest.startsWith(p))) {
145
232
  return false;
146
233
  }
@@ -168,48 +255,15 @@ async function copyTaskFlow(targetPath, isUpdate = false) {
168
255
  }
169
256
 
170
257
  showSuccess('Task Flow directory');
171
- if (isUpdate) {
258
+ if (isReset) {
259
+ showWarning('Reset completed: .task-flow was recreated from scratch');
260
+ } else if (isUpdate) {
172
261
  showInfo('Protected: .internal/ (your task data is safe)');
173
262
  } else {
174
263
  showInfo('Protected on init: .internal/, tasks.input.txt, tasks.status.md, tasks.flow.md');
175
264
  }
176
265
  }
177
266
 
178
- async function updateGitignore(targetPath) {
179
- const gitignorePath = path.join(targetPath, '.gitignore');
180
-
181
- if (!fs.existsSync(gitignorePath)) {
182
- await fs.writeFile(gitignorePath, '');
183
- }
184
-
185
- let content = await fs.readFile(gitignorePath, 'utf8');
186
-
187
- const entries = [
188
- '.claude/',
189
- '.cursor/',
190
- '.task-flow/',
191
- 'CLAUDE.md',
192
- 'AGENTS.md'
193
- ];
194
-
195
- for (const entry of entries) {
196
- const regex = new RegExp(`^${entry.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`, 'gm');
197
- content = content.replace(regex, '');
198
- }
199
-
200
- content = content.replace(/\n{3,}/g, '\n\n');
201
-
202
- if (!content.endsWith('\n')) {
203
- content += '\n';
204
- }
205
-
206
- content += '\n' + entries.join('\n') + '\n';
207
-
208
- await fs.writeFile(gitignorePath, content);
209
-
210
- showSuccess('.gitignore updated');
211
- }
212
-
213
267
  async function showModelVersions(targetPath) {
214
268
  console.log(chalk.cyan('═'.repeat(60)));
215
269
  console.log(chalk.magenta('📋 Model Versions Configured:'));
@@ -0,0 +1,110 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ const PROFILE_STANDARD = 'standard';
5
+ const PROFILE_MINIMAL = 'minimal';
6
+
7
+ const MINIMAL_RULE_FILES = ['task-flow-cursor.mdc', 'rbin-git-policy.mdc'];
8
+
9
+ function normalizeProfile(profile) {
10
+ const value = String(profile || PROFILE_STANDARD).trim().toLowerCase();
11
+ if (value !== PROFILE_STANDARD && value !== PROFILE_MINIMAL) {
12
+ throw new Error(`Invalid profile "${profile}". Use "minimal" or "standard".`);
13
+ }
14
+ return value;
15
+ }
16
+
17
+ function parseProfileOption(value) {
18
+ return normalizeProfile(value || PROFILE_STANDARD);
19
+ }
20
+
21
+ async function readInstallMeta(targetPath) {
22
+ const metaPath = path.join(targetPath, '.task-flow', 'install-meta.json');
23
+ if (!fs.existsSync(metaPath)) {
24
+ return null;
25
+ }
26
+ try {
27
+ return await fs.readJson(metaPath);
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ async function writeInstallMeta(targetPath, { profile, packageVersion, shareAiConfig }) {
34
+ const metaPath = path.join(targetPath, '.task-flow', 'install-meta.json');
35
+ await fs.ensureDir(path.dirname(metaPath));
36
+ const existing = (await readInstallMeta(targetPath)) || {};
37
+ const meta = {
38
+ ...existing,
39
+ profile: normalizeProfile(profile),
40
+ packageVersion,
41
+ updatedAt: new Date().toISOString(),
42
+ };
43
+ if (shareAiConfig !== undefined) {
44
+ meta.shareAiConfig = Boolean(shareAiConfig);
45
+ }
46
+ await fs.writeJson(metaPath, meta, { spaces: 2 });
47
+ }
48
+
49
+ async function resolveShareAiConfig(targetPath, options = {}) {
50
+ if (options.shareAiConfig !== undefined) {
51
+ return Boolean(options.shareAiConfig);
52
+ }
53
+ const meta = await readInstallMeta(targetPath);
54
+ if (meta && typeof meta.shareAiConfig === 'boolean') {
55
+ return meta.shareAiConfig;
56
+ }
57
+ return false;
58
+ }
59
+
60
+ async function resolveProfile(targetPath, options = {}) {
61
+ if (options.profile) {
62
+ return normalizeProfile(options.profile);
63
+ }
64
+ const meta = await readInstallMeta(targetPath);
65
+ if (meta?.profile) {
66
+ return normalizeProfile(meta.profile);
67
+ }
68
+ return PROFILE_STANDARD;
69
+ }
70
+
71
+ async function copyCursorRules(targetPath, templateDir, { profile, update, reset }) {
72
+ const src = path.join(templateDir, '.cursor', 'rules');
73
+ const dest = path.join(targetPath, '.cursor', 'rules');
74
+
75
+ if (!fs.existsSync(src)) {
76
+ return;
77
+ }
78
+
79
+ if ((update || reset) && fs.existsSync(dest)) {
80
+ await fs.emptyDir(dest);
81
+ }
82
+ await fs.ensureDir(dest);
83
+
84
+ if (profile === PROFILE_MINIMAL) {
85
+ for (const file of MINIMAL_RULE_FILES) {
86
+ const from = path.join(src, file);
87
+ if (fs.existsSync(from)) {
88
+ await fs.copy(from, path.join(dest, file), { overwrite: true });
89
+ }
90
+ }
91
+ return { mode: PROFILE_MINIMAL, count: MINIMAL_RULE_FILES.length };
92
+ }
93
+
94
+ await fs.copy(src, dest, { overwrite: true });
95
+ const count = (await fs.readdir(dest)).filter((name) => name.endsWith('.mdc')).length;
96
+ return { mode: PROFILE_STANDARD, count };
97
+ }
98
+
99
+ module.exports = {
100
+ PROFILE_STANDARD,
101
+ PROFILE_MINIMAL,
102
+ MINIMAL_RULE_FILES,
103
+ normalizeProfile,
104
+ parseProfileOption,
105
+ readInstallMeta,
106
+ writeInstallMeta,
107
+ resolveProfile,
108
+ resolveShareAiConfig,
109
+ copyCursorRules,
110
+ };
package/lib/skills.js ADDED
@@ -0,0 +1,34 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { showSuccess, showInfo } = require('./utils');
4
+
5
+ const TEMPLATE_DIR = path.join(__dirname, '..');
6
+ const SKILLS_SRC = path.join(TEMPLATE_DIR, '.claude', 'skills');
7
+
8
+ async function copySkillsToProject(targetPath) {
9
+ if (!fs.existsSync(SKILLS_SRC)) {
10
+ return false;
11
+ }
12
+
13
+ const destinations = [
14
+ path.join(targetPath, '.claude', 'skills'),
15
+ path.join(targetPath, '.cursor', 'skills'),
16
+ ];
17
+
18
+ for (const dest of destinations) {
19
+ await fs.ensureDir(dest);
20
+ await fs.copy(SKILLS_SRC, dest, { overwrite: true });
21
+ }
22
+
23
+ const count = (await fs.readdir(SKILLS_SRC)).filter((name) =>
24
+ fs.statSync(path.join(SKILLS_SRC, name)).isDirectory()
25
+ ).length;
26
+
27
+ showSuccess(`Agent skills (${count} skills → .claude/skills/ and .cursor/skills/)`);
28
+ showInfo('Claude Code: restart session if .claude/skills/ was created for the first time');
29
+ showInfo('Claude: /task-flow-run · Cursor: @task-flow-run in Agent (or task-flow: run next X)');
30
+
31
+ return true;
32
+ }
33
+
34
+ module.exports = { copySkillsToProject, SKILLS_SRC };
package/lib/utils.js CHANGED
@@ -36,14 +36,49 @@ function showInfo(message) {
36
36
  console.log(chalk.blue('ℹ️ ' + message));
37
37
  }
38
38
 
39
+ function measureAlwaysOnRules(targetPath) {
40
+ const rulesDir = path.join(targetPath, '.cursor', 'rules');
41
+ if (!fs.existsSync(rulesDir)) return null;
42
+
43
+ let totalBytes = 0;
44
+ const files = fs.readdirSync(rulesDir).filter((name) => name.endsWith('.mdc'));
45
+
46
+ for (const name of files) {
47
+ const filePath = path.join(rulesDir, name);
48
+ const content = fs.readFileSync(filePath, 'utf8');
49
+ if (/alwaysApply:\s*true\b/.test(content)) {
50
+ totalBytes += Buffer.byteLength(content, 'utf8');
51
+ }
52
+ }
53
+
54
+ if (totalBytes === 0) return null;
55
+ return {
56
+ bytes: totalBytes,
57
+ kb: totalBytes / 1024,
58
+ approxTokens: Math.round(totalBytes / 4),
59
+ };
60
+ }
61
+
39
62
  function showNextSteps(targetPath) {
63
+ const alwaysOn = measureAlwaysOnRules(targetPath);
64
+
40
65
  console.log('\n' + chalk.cyan('═'.repeat(60)));
41
66
  console.log(chalk.magenta.bold(' Next Steps:'));
42
67
  console.log(chalk.cyan('═'.repeat(60)));
68
+ if (alwaysOn) {
69
+ const kbLabel = alwaysOn.kb < 10 ? alwaysOn.kb.toFixed(1) : String(Math.round(alwaysOn.kb));
70
+ console.log(
71
+ chalk.gray(' Always-on rules:'),
72
+ chalk.yellow(`~${kbLabel} KB`),
73
+ chalk.gray(`(~${alwaysOn.approxTokens.toLocaleString('en-US')} tokens est.)`)
74
+ );
75
+ }
43
76
  console.log(chalk.blue(' 1.'), 'Edit', chalk.yellow('.task-flow/tasks.input.txt'));
44
- console.log(chalk.blue(' 2.'), 'Use AI command:', chalk.cyan('task-flow: sync'));
45
- console.log(chalk.blue(' 3.'), 'Work on tasks:', chalk.cyan('task-flow: run next X'));
77
+ console.log(chalk.blue(' 2.'), 'Sync:', chalk.cyan('task-flow: sync'), chalk.gray('· Cursor/Claude: @task-flow-sync or /task-flow-sync'));
78
+ console.log(chalk.blue(' 3.'), 'Run:', chalk.cyan('task-flow: run next X'), chalk.gray('· @task-flow-run'));
46
79
  console.log(chalk.blue(' 4.'), 'Check status:', chalk.cyan('task-flow: status'));
80
+ console.log(chalk.blue(' 5.'), 'Codex:', chalk.gray('AGENTS.md + .task-flow/CODEX.md on demand'));
81
+ console.log(chalk.blue(' 6.'), 'Optional Graphify:', chalk.yellow('graphify extract .'), chalk.gray('— .task-flow/GRAPHIFY.md'));
47
82
  console.log(chalk.cyan('═'.repeat(60)));
48
83
  console.log(chalk.blue('\n See'), chalk.yellow('.task-flow/README.md'), chalk.blue('for all available commands\n'));
49
84
  }
@@ -69,5 +104,6 @@ module.exports = {
69
104
  showWarning,
70
105
  showInfo,
71
106
  showNextSteps,
107
+ measureAlwaysOnRules,
72
108
  parseTaskIds
73
109
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rbin-task-flow",
3
- "version": "1.19.4",
3
+ "version": "1.23.0",
4
4
  "description": "AI-powered task management for Claude and Cursor",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -9,7 +9,8 @@
9
9
  },
10
10
  "scripts": {
11
11
  "test": "echo \"No tests yet\"",
12
- "prepublishOnly": "chmod +x bin/cli.js"
12
+ "measure:rules": "node scripts/measure-rule-bytes.js",
13
+ "prepublishOnly": "npm run measure:rules && chmod +x bin/cli.js scripts/measure-rule-bytes.js"
13
14
  },
14
15
  "keywords": [
15
16
  "task-flow",
@@ -32,10 +33,13 @@
32
33
  "bin/",
33
34
  ".cursor/",
34
35
  ".claude/",
36
+ ".claude/skills/",
37
+ ".cursor/skills/",
35
38
  ".task-flow/",
36
39
  ".model-versions.json",
37
40
  "CLAUDE.md",
38
41
  "AGENTS.md",
42
+ ".codex/",
39
43
  "lib/"
40
44
  ],
41
45
  "preferGlobal": true,