codeadd 0.1.0 → 0.1.2

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
@@ -1,34 +1,34 @@
1
- # pff
1
+ # add
2
2
 
3
- CLI installer for [Product Flow Factory (PFF)](https://github.com/brabos-ai/product-flow-factory).
3
+ CLI installer for [Product Flow Factory (ADD)](https://github.com/brabos-ai/product-flow-factory).
4
4
 
5
5
  ## Install and run
6
6
 
7
7
  ```bash
8
8
  # interactive install
9
- npx pff install
9
+ npx add install
10
10
 
11
11
  # install from main branch
12
- npx pff install --version main
12
+ npx add install --version main
13
13
 
14
14
  # install from a specific tag
15
- npx pff install --version v2.0.1
15
+ npx add install --version v2.0.1
16
16
 
17
17
  # update installed files to latest release
18
- npx pff update
18
+ npx add update
19
19
 
20
20
  # environment checks
21
- npx pff doctor
21
+ npx add doctor
22
22
 
23
23
  # integrity checks
24
- npx pff validate
24
+ npx add validate
25
25
 
26
26
  # repair integrity issues by restoring from release
27
- npx pff validate --repair
27
+ npx add validate --repair
28
28
 
29
29
  # remove installed files
30
- npx pff uninstall
31
- npx pff uninstall --force
30
+ npx add uninstall
31
+ npx add uninstall --force
32
32
  ```
33
33
 
34
34
  ## Commands
@@ -37,15 +37,15 @@ npx pff uninstall --force
37
37
  - `install --version main`: install from GitHub `main` branch
38
38
  - `install --version <tag>`: install from a specific GitHub tag
39
39
  - `update`: update installed files to latest GitHub release
40
- - `doctor`: verify Node, Git, and PFF installation health
41
- - `validate`: verify file hashes from `.pff/manifest.json`
40
+ - `doctor`: verify Node, Git, and ADD installation health
41
+ - `validate`: verify file hashes from `.add/manifest.json`
42
42
  - `validate --repair`: restore missing or modified files
43
- - `config show`: print current PFF installation config
43
+ - `config show`: print current ADD installation config
44
44
  - `config show --verbose`: config + release update check
45
45
 
46
46
  ## What gets installed
47
47
 
48
- - Core (`.pff/`): always installed
48
+ - Core (`.add/`): always installed
49
49
  - Provider integration (optional, selected interactively):
50
50
  - Claude Code -> `.claude/`
51
51
  - Codex (OpenAI) -> `.agent/`
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "codeadd",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CLI for Code Addiction framework - AI-powered development workflows",
5
5
  "type": "module",
6
- "repository": {
6
+ "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/brabos-ai/product-flow-factory.git"
9
9
  },
package/src/config.js CHANGED
@@ -4,12 +4,12 @@ import { intro, outro, spinner, log } from '@clack/prompts';
4
4
  import { getLatestTag } from './github.js';
5
5
 
6
6
  /**
7
- * Read and parse .pff/manifest.json.
7
+ * Read and parse .add/manifest.json.
8
8
  * @param {string} cwd
9
9
  * @returns {{ version: string, releaseTag: string, installedAt: string, providers: string[], files: string[], hashes?: object } | null}
10
10
  */
11
11
  function readManifest(cwd) {
12
- const manifestPath = path.join(cwd, '.pff', 'manifest.json');
12
+ const manifestPath = path.join(cwd, '.add', 'manifest.json');
13
13
  if (!fs.existsSync(manifestPath)) return null;
14
14
  try {
15
15
  return JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
@@ -45,12 +45,12 @@ function formatDate(isoDate) {
45
45
  * @param {boolean} verbose if true, checks for updates
46
46
  */
47
47
  export async function config(cwd, verbose = false) {
48
- intro('PFF CLI - Config');
48
+ intro('ADD CLI - Config');
49
49
 
50
50
  const manifest = readManifest(cwd);
51
51
 
52
52
  if (!manifest) {
53
- outro('ERROR: PFF not installed. Run `npx pff install` first.');
53
+ outro('ERROR: ADD not installed. Run `npx add install` first.');
54
54
  process.exit(1);
55
55
  }
56
56
 
@@ -82,7 +82,7 @@ export async function config(cwd, verbose = false) {
82
82
  log.success('OK You are running the latest version!');
83
83
  } else {
84
84
  log.warn(`WARN Update available: ${latestTag} (current: ${manifest.releaseTag || manifest.version})`);
85
- log.info(' Run `npx pff update` to upgrade.');
85
+ log.info(' Run `npx add update` to upgrade.');
86
86
  }
87
87
  } catch (err) {
88
88
  s.stop('Update check failed.');
package/src/doctor.js CHANGED
@@ -42,17 +42,17 @@ function checkGit() {
42
42
  }
43
43
 
44
44
  /**
45
- * Check if .pff/ directory exists and is non-empty.
45
+ * Check if .add/ directory exists and is non-empty.
46
46
  * @param {string} cwd
47
47
  * @returns {{ok: boolean, exists: boolean, hasFiles: boolean}}
48
48
  */
49
- function checkPffDir(cwd) {
50
- const pffDir = path.join(cwd, '.pff');
51
- const exists = fs.existsSync(pffDir);
49
+ function checkAddDir(cwd) {
50
+ const addDir = path.join(cwd, '.add');
51
+ const exists = fs.existsSync(addDir);
52
52
  let hasFiles = false;
53
53
  if (exists) {
54
54
  try {
55
- const entries = fs.readdirSync(pffDir);
55
+ const entries = fs.readdirSync(addDir);
56
56
  hasFiles = entries.length > 0;
57
57
  } catch {
58
58
  // ignore
@@ -71,7 +71,7 @@ function checkPffDir(cwd) {
71
71
  * @returns {{ok: boolean, exists: boolean, valid: boolean}}
72
72
  */
73
73
  function checkManifest(cwd) {
74
- const manifestPath = path.join(cwd, '.pff', 'manifest.json');
74
+ const manifestPath = path.join(cwd, '.add', 'manifest.json');
75
75
  const exists = fs.existsSync(manifestPath);
76
76
  let valid = false;
77
77
  if (exists) {
@@ -94,14 +94,14 @@ function checkManifest(cwd) {
94
94
  * @param {string} cwd
95
95
  */
96
96
  export async function doctor(cwd) {
97
- intro('PFF CLI - Doctor');
97
+ intro('ADD CLI - Doctor');
98
98
 
99
99
  const s = spinner();
100
100
  s.start('Checking environment...');
101
101
 
102
102
  const nodeCheck = checkNode();
103
103
  const gitCheck = await checkGit();
104
- const pffCheck = checkPffDir(cwd);
104
+ const addCheck = checkAddDir(cwd);
105
105
  const manifestCheck = checkManifest(cwd);
106
106
 
107
107
  s.stop('Checks complete.');
@@ -116,9 +116,9 @@ export async function doctor(cwd) {
116
116
  const gitIcon = gitCheck.ok ? 'OK' : 'ERROR';
117
117
  log.info(`${gitIcon} Git: ${gitCheck.ok ? gitCheck.version : 'not found'}`);
118
118
 
119
- const pffIcon = pffCheck.ok ? 'OK' : pffCheck.exists ? 'WARN' : 'ERROR';
120
- const pffStatus = pffCheck.ok ? 'present' : pffCheck.exists ? 'empty' : 'missing';
121
- log.info(`${pffIcon} .pff/ directory: ${pffStatus}`);
119
+ const addIcon = addCheck.ok ? 'OK' : addCheck.exists ? 'WARN' : 'ERROR';
120
+ const addStatus = addCheck.ok ? 'present' : addCheck.exists ? 'empty' : 'missing';
121
+ log.info(`${addIcon} .add/ directory: ${addStatus}`);
122
122
 
123
123
  let manifestIcon;
124
124
  let manifestStatus;
@@ -136,16 +136,16 @@ export async function doctor(cwd) {
136
136
 
137
137
  log.info('');
138
138
 
139
- const allOk = nodeCheck.ok && gitCheck.ok && pffCheck.ok && manifestCheck.ok;
139
+ const allOk = nodeCheck.ok && gitCheck.ok && addCheck.ok && manifestCheck.ok;
140
140
 
141
141
  if (allOk) {
142
- outro('OK All checks passed! PFF is properly installed.');
142
+ outro('OK All checks passed! ADD is properly installed.');
143
143
  process.exit(0);
144
144
  } else {
145
145
  const issues = [];
146
146
  if (!nodeCheck.ok) issues.push('Node.js >= 18 required');
147
147
  if (!gitCheck.ok) issues.push('Git not found');
148
- if (!pffCheck.ok) issues.push('.pff/ directory missing or empty');
148
+ if (!addCheck.ok) issues.push('.add/ directory missing or empty');
149
149
  if (!manifestCheck.ok) issues.push('manifest.json missing or invalid');
150
150
 
151
151
  outro(`ERROR Issues found:\n${issues.map((i) => ` - ${i}`).join('\n')}`);
package/src/github.js CHANGED
@@ -11,7 +11,7 @@ export async function getLatestTag(repo = REPO) {
11
11
  const res = await fetch(url, {
12
12
  headers: {
13
13
  Accept: 'application/vnd.github+json',
14
- 'User-Agent': 'pff-cli',
14
+ 'User-Agent': 'add-cli',
15
15
  },
16
16
  }).catch(() => {
17
17
  throw new Error('Could not reach GitHub. Check your connection.');
@@ -37,7 +37,7 @@ export async function getLatestTag(repo = REPO) {
37
37
  export async function downloadTagZip(tag, repo = REPO) {
38
38
  const url = `https://github.com/${repo}/archive/refs/tags/${tag}.zip`;
39
39
  const res = await fetch(url, {
40
- headers: { 'User-Agent': 'pff-cli' },
40
+ headers: { 'User-Agent': 'add-cli' },
41
41
  }).catch(() => {
42
42
  throw new Error('Could not reach GitHub. Check your connection.');
43
43
  });
@@ -64,7 +64,7 @@ export async function downloadTagZip(tag, repo = REPO) {
64
64
  export async function downloadBranchZip(branch, repo = REPO) {
65
65
  const url = `https://github.com/${repo}/archive/refs/heads/${branch}.zip`;
66
66
  const res = await fetch(url, {
67
- headers: { 'User-Agent': 'pff-cli' },
67
+ headers: { 'User-Agent': 'add-cli' },
68
68
  }).catch(() => {
69
69
  throw new Error('Could not reach GitHub. Check your connection.');
70
70
  });
package/src/installer.js CHANGED
@@ -39,7 +39,7 @@ function calculateHash(filePath) {
39
39
  }
40
40
 
41
41
  /**
42
- * Write .pff/manifest.json
42
+ * Write .add/manifest.json
43
43
  * @param {string} cwd
44
44
  * @param {string} version
45
45
  * @param {string[]} providers
@@ -48,7 +48,7 @@ function calculateHash(filePath) {
48
48
  * @param {object} [metadata]
49
49
  */
50
50
  export function writeManifest(cwd, version, providers, files, releaseTag, metadata = {}) {
51
- const manifestPath = path.join(cwd, '.pff', 'manifest.json');
51
+ const manifestPath = path.join(cwd, '.add', 'manifest.json');
52
52
 
53
53
  const hashes = {};
54
54
  for (const file of files) {
@@ -160,7 +160,7 @@ function dirExists(dir) {
160
160
  *
161
161
  * @param {AdmZip} zip
162
162
  * @param {string} zipRoot top-level folder name inside zip (e.g. "product-flow-factory-2.0.1")
163
- * @param {string} srcPrefix path inside zip after zipRoot (e.g. "framwork/.pff")
163
+ * @param {string} srcPrefix path inside zip after zipRoot (e.g. "framwork/.add")
164
164
  * @param {string} destDir absolute destination directory
165
165
  * @param {string} cwd project root
166
166
  * @returns {string[]}
@@ -195,7 +195,7 @@ function copyFromZip(zip, zipRoot, srcPrefix, destDir, cwd) {
195
195
  * @param {{version?: string}} [options]
196
196
  */
197
197
  export async function install(cwd, options = {}) {
198
- intro('PFF CLI - Install');
198
+ intro('ADD CLI - Install');
199
199
 
200
200
  const s = spinner();
201
201
  s.start('Resolving install source from GitHub...');
@@ -208,9 +208,9 @@ export async function install(cwd, options = {}) {
208
208
  s.stop(`Selected tag: ${installSource.downloadValue}`);
209
209
  }
210
210
 
211
- const pffDir = path.join(cwd, '.pff');
212
- if (dirExists(pffDir)) {
213
- await promptConfirm('.pff/ already exists. Overwrite with latest version?');
211
+ const addDir = path.join(cwd, '.add');
212
+ if (dirExists(addDir)) {
213
+ await promptConfirm('.add/ already exists. Overwrite with latest version?');
214
214
  }
215
215
 
216
216
  const selectedKeys = await promptProviders();
@@ -237,7 +237,7 @@ export async function install(cwd, options = {}) {
237
237
 
238
238
  const allFiles = [];
239
239
 
240
- const coreFiles = copyFromZip(zip, zipRoot, 'framwork/.pff', pffDir, cwd);
240
+ const coreFiles = copyFromZip(zip, zipRoot, 'framwork/.add', addDir, cwd);
241
241
  allFiles.push(...coreFiles);
242
242
 
243
243
  for (const p of providers) {
@@ -248,7 +248,7 @@ export async function install(cwd, options = {}) {
248
248
 
249
249
  s.stop(`Installed ${allFiles.length} files.`);
250
250
 
251
- fixLineEndings(path.join(pffDir, 'scripts'));
251
+ fixLineEndings(path.join(addDir, 'scripts'));
252
252
 
253
253
  writeManifest(
254
254
  cwd,
@@ -263,9 +263,9 @@ export async function install(cwd, options = {}) {
263
263
  log.success(`Providers installed: ${providerList}`);
264
264
 
265
265
  outro(
266
- `PFF installed successfully!\n\n` +
266
+ `ADD installed successfully!\n\n` +
267
267
  `Next steps:\n` +
268
- ` 1. Open your AI editor and run: /pff-init\n` +
268
+ ` 1. Open your AI editor and run: /add-init\n` +
269
269
  ` 2. Follow the onboarding to configure your project\n\n` +
270
270
  `Docs: https://github.com/brabos-ai/product-flow-factory`
271
271
  );
@@ -3,17 +3,17 @@ import path from 'node:path';
3
3
  import { intro, outro, spinner, log } from '@clack/prompts';
4
4
  import { promptConfirm } from './prompt.js';
5
5
 
6
- const PFF_DIRS = ['.pff', '.claude', '.agent', '.agents', '.kilocode', '.opencode'];
6
+ const ADD_DIRS = ['.add', '.claude', '.agent', '.agents', '.kilocode', '.opencode'];
7
7
 
8
8
  /**
9
- * Read and parse .pff/manifest.json.
9
+ * Read and parse .add/manifest.json.
10
10
  * @param {string} cwd
11
11
  * @returns {{ version: string, providers: string[], files: string[], corrupted?: boolean } | null}
12
12
  * Returns null if manifest does not exist.
13
13
  * Returns object with corrupted=true if file exists but JSON is invalid.
14
14
  */
15
15
  export function readManifest(cwd) {
16
- const manifestPath = path.join(cwd, '.pff', 'manifest.json');
16
+ const manifestPath = path.join(cwd, '.add', 'manifest.json');
17
17
  if (!fs.existsSync(manifestPath)) return null;
18
18
  try {
19
19
  return JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
@@ -72,32 +72,32 @@ function removeEmptyDirs(dir) {
72
72
  * @param {boolean} force skip confirmation
73
73
  */
74
74
  export async function uninstall(cwd, force = false) {
75
- intro('PFF CLI - Uninstall');
75
+ intro('ADD CLI - Uninstall');
76
76
 
77
77
  const manifest = readManifest(cwd);
78
78
 
79
79
  if (!manifest) {
80
- throw new Error('No PFF installation found. Run `npx pff install` first.');
80
+ throw new Error('No ADD installation found. Run `npx add install` first.');
81
81
  }
82
82
 
83
83
  if (manifest.corrupted) {
84
84
  log.warn('Manifest is corrupted. Falling back to directory-based removal.');
85
85
 
86
86
  const allPresent = [];
87
- for (const dir of PFF_DIRS) {
87
+ for (const dir of ADD_DIRS) {
88
88
  allPresent.push(...walkDir(path.join(cwd, dir), cwd));
89
89
  }
90
90
 
91
91
  if (allPresent.length === 0) {
92
- outro('No PFF files found. Nothing to remove.');
92
+ outro('No ADD files found. Nothing to remove.');
93
93
  return;
94
94
  }
95
95
 
96
- log.info(`Found ${allPresent.length} file(s) in PFF directories.`);
96
+ log.info(`Found ${allPresent.length} file(s) in ADD directories.`);
97
97
 
98
98
  if (!force) {
99
99
  await promptConfirm(
100
- `Remove all ${allPresent.length} files found in PFF directories? This cannot be undone.`
100
+ `Remove all ${allPresent.length} files found in ADD directories? This cannot be undone.`
101
101
  );
102
102
  }
103
103
 
@@ -117,31 +117,31 @@ export async function uninstall(cwd, force = false) {
117
117
  }
118
118
  s.stop(`Removed ${removed} files.`);
119
119
 
120
- for (const dir of PFF_DIRS) {
120
+ for (const dir of ADD_DIRS) {
121
121
  removeEmptyDirs(path.join(cwd, dir));
122
122
  }
123
123
 
124
- outro('PFF removed successfully.');
124
+ outro('ADD removed successfully.');
125
125
  return;
126
126
  }
127
127
 
128
128
  const manifestFiles = new Set(manifest.files ?? []);
129
129
 
130
130
  const allPresent = [];
131
- for (const dir of PFF_DIRS) {
131
+ for (const dir of ADD_DIRS) {
132
132
  allPresent.push(...walkDir(path.join(cwd, dir), cwd));
133
133
  }
134
134
 
135
135
  const userFiles = allPresent.filter((f) => !manifestFiles.has(f));
136
136
 
137
- log.info(`Files installed by PFF: ${manifestFiles.size}`);
137
+ log.info(`Files installed by ADD: ${manifestFiles.size}`);
138
138
  if (userFiles.length > 0) {
139
- log.warn(`Found ${userFiles.length} file(s) not installed by PFF (will be kept):`);
139
+ log.warn(`Found ${userFiles.length} file(s) not installed by ADD (will be kept):`);
140
140
  for (const f of userFiles) log.warn(` ${f}`);
141
141
  }
142
142
 
143
143
  if (!force) {
144
- await promptConfirm(`Remove ${manifestFiles.size} PFF files? (user files will be kept)`);
144
+ await promptConfirm(`Remove ${manifestFiles.size} ADD files? (user files will be kept)`);
145
145
  }
146
146
 
147
147
  const s = spinner();
@@ -160,7 +160,7 @@ export async function uninstall(cwd, force = false) {
160
160
  }
161
161
  }
162
162
 
163
- const manifestPath = path.join(cwd, '.pff', 'manifest.json');
163
+ const manifestPath = path.join(cwd, '.add', 'manifest.json');
164
164
  try {
165
165
  if (fs.existsSync(manifestPath)) {
166
166
  fs.unlinkSync(manifestPath);
@@ -172,9 +172,9 @@ export async function uninstall(cwd, force = false) {
172
172
 
173
173
  s.stop(`Removed ${removed} files.`);
174
174
 
175
- for (const dir of PFF_DIRS) {
175
+ for (const dir of ADD_DIRS) {
176
176
  removeEmptyDirs(path.join(cwd, dir));
177
177
  }
178
178
 
179
- outro('PFF removed successfully.');
179
+ outro('ADD removed successfully.');
180
180
  }
package/src/updater.js CHANGED
@@ -59,18 +59,18 @@ function copyFromZip(zip, zipRoot, srcPrefix, destDir, cwd) {
59
59
  * @param {string} cwd
60
60
  */
61
61
  export async function update(cwd) {
62
- intro('PFF CLI - Update');
62
+ intro('ADD CLI - Update');
63
63
 
64
- const manifestPath = path.join(cwd, '.pff', 'manifest.json');
64
+ const manifestPath = path.join(cwd, '.add', 'manifest.json');
65
65
  if (!fs.existsSync(manifestPath)) {
66
- throw new Error('No PFF installation found. Run `npx pff install` first.');
66
+ throw new Error('No ADD installation found. Run `npx add install` first.');
67
67
  }
68
68
 
69
69
  let manifest;
70
70
  try {
71
71
  manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
72
72
  } catch {
73
- throw new Error('Manifest is corrupted. Run `npx pff install` to reinstall.');
73
+ throw new Error('Manifest is corrupted. Run `npx add install` to reinstall.');
74
74
  }
75
75
 
76
76
  const currentVersion = manifest.version ?? 'unknown';
@@ -97,9 +97,9 @@ export async function update(cwd) {
97
97
  if (!zipRoot) throw new Error('Unexpected zip structure.');
98
98
 
99
99
  const allFiles = [];
100
- const pffDir = path.join(cwd, '.pff');
100
+ const addDir = path.join(cwd, '.add');
101
101
 
102
- const coreFiles = copyFromZip(zip, zipRoot, 'framwork/.pff', pffDir, cwd);
102
+ const coreFiles = copyFromZip(zip, zipRoot, 'framwork/.add', addDir, cwd);
103
103
  allFiles.push(...coreFiles);
104
104
 
105
105
  const providers = resolveSelected(providerKeys);
@@ -111,10 +111,10 @@ export async function update(cwd) {
111
111
 
112
112
  s.stop(`Updated ${allFiles.length} files.`);
113
113
 
114
- fixLineEndings(path.join(pffDir, 'scripts'));
114
+ fixLineEndings(path.join(addDir, 'scripts'));
115
115
 
116
116
  writeManifest(cwd, tag, providerKeys, allFiles);
117
117
 
118
118
  log.success(`Updated from v${currentVersion} to v${newVersion}`);
119
- outro('PFF updated successfully!');
119
+ outro('ADD updated successfully!');
120
120
  }
package/src/validator.js CHANGED
@@ -6,12 +6,12 @@ import { intro, outro, spinner, log } from '@clack/prompts';
6
6
  import { downloadZip } from './github.js';
7
7
 
8
8
  /**
9
- * Read and parse .pff/manifest.json.
9
+ * Read and parse .add/manifest.json.
10
10
  * @param {string} cwd
11
11
  * @returns {{ version: string, releaseTag: string, installedAt: string, providers: string[], files: string[], hashes?: object } | null}
12
12
  */
13
13
  function readManifest(cwd) {
14
- const manifestPath = path.join(cwd, '.pff', 'manifest.json');
14
+ const manifestPath = path.join(cwd, '.add', 'manifest.json');
15
15
  if (!fs.existsSync(manifestPath)) return null;
16
16
  try {
17
17
  return JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
@@ -110,19 +110,19 @@ async function repairFiles(cwd, filesToRepair, releaseTag) {
110
110
  * @param {boolean} repair if true, restore missing/modified files
111
111
  */
112
112
  export async function validate(cwd, repair = false) {
113
- intro('PFF CLI - Validate');
113
+ intro('ADD CLI - Validate');
114
114
 
115
115
  const manifest = readManifest(cwd);
116
116
 
117
117
  if (!manifest) {
118
- outro('ERROR: PFF not installed. Run `npx pff install` first.');
118
+ outro('ERROR: ADD not installed. Run `npx add install` first.');
119
119
  process.exit(1);
120
120
  }
121
121
 
122
122
  if (!manifest.hashes || Object.keys(manifest.hashes).length === 0) {
123
123
  log.warn('');
124
124
  log.warn('WARN Hash not available for this install.');
125
- log.warn(' Run `npx pff update` to enable validation.');
125
+ log.warn(' Run `npx add update` to enable validation.');
126
126
  log.warn('');
127
127
  outro('Validation skipped.');
128
128
  process.exit(0);