devflow-kit 0.3.3 โ†’ 0.5.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.
@@ -1,82 +1,96 @@
1
1
  import { Command } from 'commander';
2
2
  import { promises as fs } from 'fs';
3
3
  import * as path from 'path';
4
- import { homedir } from 'os';
4
+ import { getInstallationPaths, getClaudeDirectory } from '../utils/paths.js';
5
+ import { getGitRoot } from '../utils/git.js';
5
6
  /**
6
- * Get home directory with proper fallback and validation
7
- * Priority: process.env.HOME > os.homedir()
7
+ * Check if DevFlow is installed at the given paths
8
8
  */
9
- function getHomeDirectory() {
10
- const home = process.env.HOME || homedir();
11
- if (!home) {
12
- throw new Error('Unable to determine home directory. Set HOME environment variable.');
13
- }
14
- return home;
15
- }
16
- /**
17
- * Get Claude Code directory with environment variable override support
18
- * Priority: CLAUDE_CODE_DIR env var > ~/.claude
19
- */
20
- function getClaudeDirectory() {
21
- if (process.env.CLAUDE_CODE_DIR) {
22
- return process.env.CLAUDE_CODE_DIR;
9
+ async function isDevFlowInstalled(claudeDir) {
10
+ try {
11
+ await fs.access(path.join(claudeDir, 'commands', 'devflow'));
12
+ return true;
23
13
  }
24
- return path.join(getHomeDirectory(), '.claude');
25
- }
26
- /**
27
- * Get DevFlow directory with environment variable override support
28
- * Priority: DEVFLOW_DIR env var > ~/.devflow
29
- */
30
- function getDevFlowDirectory() {
31
- if (process.env.DEVFLOW_DIR) {
32
- return process.env.DEVFLOW_DIR;
14
+ catch {
15
+ return false;
33
16
  }
34
- return path.join(getHomeDirectory(), '.devflow');
35
17
  }
36
18
  export const uninstallCommand = new Command('uninstall')
37
19
  .description('Uninstall DevFlow from Claude Code')
38
20
  .option('--keep-docs', 'Keep .docs/ directory and documentation')
21
+ .option('--scope <type>', 'Uninstall from specific scope only (default: auto-detect all)', /^(user|local)$/i)
39
22
  .action(async (options) => {
40
23
  console.log('๐Ÿงน Uninstalling DevFlow...\n');
41
- let claudeDir;
42
- let devflowScriptsDir;
43
- try {
44
- claudeDir = getClaudeDirectory();
45
- devflowScriptsDir = getDevFlowDirectory();
24
+ // Determine which scopes to uninstall
25
+ let scopesToUninstall = [];
26
+ if (options.scope) {
27
+ scopesToUninstall = [options.scope.toLowerCase()];
46
28
  }
47
- catch (error) {
48
- console.error('โŒ Path configuration error:', error instanceof Error ? error.message : error);
49
- process.exit(1);
29
+ else {
30
+ // Auto-detect installed scopes
31
+ const userClaudeDir = getClaudeDirectory();
32
+ const gitRoot = await getGitRoot();
33
+ if (await isDevFlowInstalled(userClaudeDir)) {
34
+ scopesToUninstall.push('user');
35
+ }
36
+ if (gitRoot) {
37
+ const localClaudeDir = path.join(gitRoot, '.claude');
38
+ if (await isDevFlowInstalled(localClaudeDir)) {
39
+ scopesToUninstall.push('local');
40
+ }
41
+ }
42
+ if (scopesToUninstall.length === 0) {
43
+ console.log('โŒ No DevFlow installation found');
44
+ console.log(' Checked user scope (~/.claude/) and local scope (git-root/.claude/)\n');
45
+ process.exit(1);
46
+ }
47
+ if (scopesToUninstall.length > 1) {
48
+ console.log('๐Ÿ“ฆ Found DevFlow in multiple scopes:');
49
+ console.log(' - User scope (~/.claude/)');
50
+ console.log(' - Local scope (git-root/.claude/)');
51
+ console.log('\n Uninstalling from both...\n');
52
+ }
50
53
  }
51
54
  let hasErrors = false;
52
- // Remove commands
53
- try {
54
- const commandsDevflowDir = path.join(claudeDir, 'commands', 'devflow');
55
- await fs.rm(commandsDevflowDir, { recursive: true, force: true });
56
- console.log(' โœ… Removed DevFlow commands');
57
- }
58
- catch (error) {
59
- console.error(' โš ๏ธ Could not remove commands:', error);
60
- hasErrors = true;
61
- }
62
- // Remove agents
63
- try {
64
- const agentsDevflowDir = path.join(claudeDir, 'agents', 'devflow');
65
- await fs.rm(agentsDevflowDir, { recursive: true, force: true });
66
- console.log(' โœ… Removed DevFlow agents');
67
- }
68
- catch (error) {
69
- console.error(' โš ๏ธ Could not remove agents:', error);
70
- hasErrors = true;
71
- }
72
- // Remove scripts
73
- try {
74
- await fs.rm(devflowScriptsDir, { recursive: true, force: true });
75
- console.log(' โœ… Removed DevFlow scripts');
76
- }
77
- catch (error) {
78
- console.error(' โš ๏ธ Could not remove scripts:', error);
79
- hasErrors = true;
55
+ // Uninstall from each scope
56
+ for (const scope of scopesToUninstall) {
57
+ // Get installation paths for this scope
58
+ let claudeDir;
59
+ let devflowScriptsDir;
60
+ try {
61
+ const paths = await getInstallationPaths(scope);
62
+ claudeDir = paths.claudeDir;
63
+ devflowScriptsDir = paths.devflowDir;
64
+ if (scope === 'user') {
65
+ console.log('๐Ÿ“ Uninstalling user scope (~/.claude/)');
66
+ }
67
+ else {
68
+ console.log('๐Ÿ“ Uninstalling local scope (git-root/.claude/)');
69
+ }
70
+ }
71
+ catch (error) {
72
+ console.log(`โš ๏ธ Cannot uninstall ${scope} scope: ${error instanceof Error ? error.message : error}\n`);
73
+ continue;
74
+ }
75
+ // DevFlow namespace directories to remove
76
+ const devflowDirectories = [
77
+ { path: path.join(claudeDir, 'commands', 'devflow'), name: 'commands' },
78
+ { path: path.join(claudeDir, 'agents', 'devflow'), name: 'agents' },
79
+ { path: path.join(claudeDir, 'skills', 'devflow'), name: 'skills' },
80
+ { path: devflowScriptsDir, name: 'scripts' }
81
+ ];
82
+ // Remove all DevFlow directories
83
+ for (const dir of devflowDirectories) {
84
+ try {
85
+ await fs.rm(dir.path, { recursive: true, force: true });
86
+ console.log(` โœ… Removed DevFlow ${dir.name}`);
87
+ }
88
+ catch (error) {
89
+ console.error(` โš ๏ธ Could not remove ${dir.name}:`, error);
90
+ hasErrors = true;
91
+ }
92
+ }
93
+ console.log();
80
94
  }
81
95
  // Handle .docs directory
82
96
  if (!options.keepDocs) {
@@ -1 +1 @@
1
- {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/cli/commands/uninstall.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/cli/commands/uninstall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Get git repository root directory (async, non-blocking)
3
+ * Returns null if not in a git repository
4
+ *
5
+ * Security: Validates output to prevent command injection
6
+ * - Rejects paths with injection characters (newlines, semicolons, shell operators)
7
+ * - Ensures path is absolute
8
+ * - Resolves path canonically
9
+ */
10
+ export declare function getGitRoot(): Promise<string | null>;
11
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/cli/utils/git.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBzD"}
@@ -0,0 +1,36 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import * as path from 'path';
4
+ const execAsync = promisify(exec);
5
+ /**
6
+ * Get git repository root directory (async, non-blocking)
7
+ * Returns null if not in a git repository
8
+ *
9
+ * Security: Validates output to prevent command injection
10
+ * - Rejects paths with injection characters (newlines, semicolons, shell operators)
11
+ * - Ensures path is absolute
12
+ * - Resolves path canonically
13
+ */
14
+ export async function getGitRoot() {
15
+ try {
16
+ const { stdout } = await execAsync('git rev-parse --show-toplevel', {
17
+ cwd: process.cwd(),
18
+ encoding: 'utf-8'
19
+ });
20
+ const gitRootRaw = stdout.trim();
21
+ // Validate git root path (security: prevent injection)
22
+ if (!gitRootRaw || gitRootRaw.includes('\n') || gitRootRaw.includes(';') || gitRootRaw.includes('&&')) {
23
+ return null;
24
+ }
25
+ // Validate it's an absolute path
26
+ const gitRoot = path.resolve(gitRootRaw);
27
+ if (!path.isAbsolute(gitRoot)) {
28
+ return null;
29
+ }
30
+ return gitRoot;
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/cli/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,+BAA+B,EAAE;YAClE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAEjC,uDAAuD;QACvD,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,iCAAiC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Get home directory with proper fallback and validation
3
+ * Priority: process.env.HOME > os.homedir()
4
+ *
5
+ * @throws {Error} If unable to determine home directory
6
+ */
7
+ export declare function getHomeDirectory(): string;
8
+ /**
9
+ * Get Claude Code directory with environment variable override support
10
+ * Priority: CLAUDE_CODE_DIR env var > ~/.claude
11
+ *
12
+ * @throws {Error} If CLAUDE_CODE_DIR is invalid (not absolute, outside home)
13
+ */
14
+ export declare function getClaudeDirectory(): string;
15
+ /**
16
+ * Get DevFlow directory with environment variable override support
17
+ * Priority: DEVFLOW_DIR env var > ~/.devflow
18
+ *
19
+ * @throws {Error} If DEVFLOW_DIR is invalid (not absolute, outside home)
20
+ */
21
+ export declare function getDevFlowDirectory(): string;
22
+ /**
23
+ * Get installation paths based on scope (async, non-blocking)
24
+ * @param scope - 'user' or 'local'
25
+ * @returns Object with claudeDir and devflowDir
26
+ * @throws {Error} If local scope selected but not in a git repository
27
+ */
28
+ export declare function getInstallationPaths(scope: 'user' | 'local'): Promise<{
29
+ claudeDir: string;
30
+ devflowDir: string;
31
+ }>;
32
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/cli/utils/paths.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAkB3C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkB5C;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBtH"}
@@ -0,0 +1,86 @@
1
+ import { homedir } from 'os';
2
+ import * as path from 'path';
3
+ import { getGitRoot } from './git.js';
4
+ /**
5
+ * Get home directory with proper fallback and validation
6
+ * Priority: process.env.HOME > os.homedir()
7
+ *
8
+ * @throws {Error} If unable to determine home directory
9
+ */
10
+ export function getHomeDirectory() {
11
+ const home = process.env.HOME || homedir();
12
+ if (!home) {
13
+ throw new Error('Unable to determine home directory. Set HOME environment variable.');
14
+ }
15
+ return home;
16
+ }
17
+ /**
18
+ * Get Claude Code directory with environment variable override support
19
+ * Priority: CLAUDE_CODE_DIR env var > ~/.claude
20
+ *
21
+ * @throws {Error} If CLAUDE_CODE_DIR is invalid (not absolute, outside home)
22
+ */
23
+ export function getClaudeDirectory() {
24
+ if (process.env.CLAUDE_CODE_DIR) {
25
+ const customDir = process.env.CLAUDE_CODE_DIR;
26
+ // Validate path is absolute
27
+ if (!path.isAbsolute(customDir)) {
28
+ throw new Error('CLAUDE_CODE_DIR must be an absolute path');
29
+ }
30
+ // Warn if outside home directory (security best practice)
31
+ const home = getHomeDirectory();
32
+ if (!customDir.startsWith(home)) {
33
+ console.warn('โš ๏ธ CLAUDE_CODE_DIR is outside home directory. Ensure this is intentional.');
34
+ }
35
+ return customDir;
36
+ }
37
+ return path.join(getHomeDirectory(), '.claude');
38
+ }
39
+ /**
40
+ * Get DevFlow directory with environment variable override support
41
+ * Priority: DEVFLOW_DIR env var > ~/.devflow
42
+ *
43
+ * @throws {Error} If DEVFLOW_DIR is invalid (not absolute, outside home)
44
+ */
45
+ export function getDevFlowDirectory() {
46
+ if (process.env.DEVFLOW_DIR) {
47
+ const customDir = process.env.DEVFLOW_DIR;
48
+ // Validate path is absolute
49
+ if (!path.isAbsolute(customDir)) {
50
+ throw new Error('DEVFLOW_DIR must be an absolute path');
51
+ }
52
+ // Warn if outside home directory (security best practice)
53
+ const home = getHomeDirectory();
54
+ if (!customDir.startsWith(home)) {
55
+ console.warn('โš ๏ธ DEVFLOW_DIR is outside home directory. Ensure this is intentional.');
56
+ }
57
+ return customDir;
58
+ }
59
+ return path.join(getHomeDirectory(), '.devflow');
60
+ }
61
+ /**
62
+ * Get installation paths based on scope (async, non-blocking)
63
+ * @param scope - 'user' or 'local'
64
+ * @returns Object with claudeDir and devflowDir
65
+ * @throws {Error} If local scope selected but not in a git repository
66
+ */
67
+ export async function getInstallationPaths(scope) {
68
+ if (scope === 'user') {
69
+ return {
70
+ claudeDir: getClaudeDirectory(),
71
+ devflowDir: getDevFlowDirectory()
72
+ };
73
+ }
74
+ else {
75
+ // Local scope - install to git repository root
76
+ const gitRoot = await getGitRoot();
77
+ if (!gitRoot) {
78
+ throw new Error('Local scope requires a git repository. Run "git init" first or use --scope user');
79
+ }
80
+ return {
81
+ claudeDir: path.join(gitRoot, '.claude'),
82
+ devflowDir: path.join(gitRoot, '.devflow')
83
+ };
84
+ }
85
+ }
86
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/cli/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC;IAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QAE9C,4BAA4B;QAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QAED,0DAA0D;QAC1D,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAC7F,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,SAAS,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QAE1C,4BAA4B;QAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,0DAA0D;QAC1D,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;QACzF,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,UAAU,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAuB;IAChE,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO;YACL,SAAS,EAAE,kBAAkB,EAAE;YAC/B,UAAU,EAAE,mBAAmB,EAAE;SAClC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,+CAA+C;QAC/C,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;QACrG,CAAC;QACD,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;YACxC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;SAC3C,CAAC;IACJ,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devflow-kit",
3
- "version": "0.3.3",
3
+ "version": "0.5.0",
4
4
  "description": "Agentic Development Toolkit for Claude Code - Enhance AI-assisted development with intelligent commands and workflows",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",