software-engineer 0.1.20 → 0.1.22

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,6 +1,6 @@
1
1
  # software-engineer
2
2
 
3
- A CLI tool that automates the software development workflow using Claude AI. It runs a 7-step pipeline to implement features, simplify code, review, ensure quality, test, commit, and update changelogs.
3
+ A CLI tool that automates the software development workflow using Claude AI. It runs an 8-step pipeline to implement features, simplify code, review, ensure quality, test, commit, and update changelogs with real-time progress visualization.
4
4
 
5
5
  ## Installation
6
6
 
@@ -13,6 +13,26 @@ npm install -g software-engineer
13
13
  - Node.js >= 18.0.0
14
14
  - [Claude CLI](https://github.com/anthropics/claude-code) installed and configured
15
15
 
16
+ ## Recommended Workflow
17
+
18
+ For best results, follow this workflow:
19
+
20
+ 1. **Plan with Claude**: Start a Claude session and use plan mode to design what needs to be done
21
+ - Discuss requirements with Claude
22
+ - Iterate and refine the plan until it's complete
23
+ - Claude will generate a plan file (usually a `.md` file)
24
+
25
+ 2. **Execute with software-engineer**: Once your plan is finalized, close Claude and run:
26
+ ```bash
27
+ sf "implement the plan mentioned in /path/to/plan.md"
28
+ ```
29
+
30
+ 3. **Wait for completion**: The tool will automatically execute the entire pipeline and implement your plan
31
+
32
+ This approach gives you the best of both worlds:
33
+ - **Interactive planning** with Claude to ensure the approach is correct
34
+ - **Automated execution** with comprehensive quality checks
35
+
16
36
  ## Usage
17
37
 
18
38
  ```bash
@@ -22,7 +42,10 @@ sf "<requirement>"
22
42
  ### Examples
23
43
 
24
44
  ```bash
25
- # Basic usage
45
+ # Recommended: Use with a plan file from Claude
46
+ sf "implement the plan mentioned in ./docs/feature-plan.md"
47
+
48
+ # Basic usage with direct requirement
26
49
  sf "add user authentication with JWT"
27
50
 
28
51
  # Custom review iterations
@@ -44,8 +67,10 @@ sf --log pipeline.log "implement caching layer"
44
67
  |--------|-------------|
45
68
  | `-d, --dry-run` | Print commands without executing |
46
69
  | `-r, --reviews <n>` | Number of review iterations (default: 2) |
70
+ | `-a, --adaptive` | Enable adaptive step execution (AI decides which steps to skip) |
47
71
  | `--skip-tests` | Skip the testing step |
48
72
  | `--skip-push` | Commit but don't push to remote |
73
+ | `--skip-branch-management` | Skip smart branch management |
49
74
  | `--log <file>` | Log output to file |
50
75
  | `--dangerously-skip-permissions` | Skip Claude permission prompts |
51
76
  | `-h, --help` | Display help |
@@ -58,10 +83,12 @@ All options can be set via environment variables:
58
83
  | Variable | Description |
59
84
  |----------|-------------|
60
85
  | `SF_REVIEW_ITERATIONS` | Number of review iterations |
86
+ | `SF_ADAPTIVE_EXECUTION` | `true`/`false` for adaptive execution |
61
87
  | `SF_DRY_RUN` | `true`/`false` for dry run |
62
88
  | `SF_LOG_FILE` | Path to log file |
63
89
  | `SF_SKIP_TESTS` | `true`/`false` to skip tests |
64
90
  | `SF_SKIP_PUSH` | `true`/`false` to skip push |
91
+ | `SF_SKIP_BRANCH_MANAGEMENT` | `true`/`false` to skip branch management |
65
92
  | `SF_DANGEROUSLY_SKIP_PERMISSIONS` | `true`/`false` to skip Claude permissions |
66
93
 
67
94
  Example:
@@ -69,41 +96,63 @@ Example:
69
96
  SF_REVIEW_ITERATIONS=3 sf "add feature X"
70
97
  ```
71
98
 
72
- ## Pipeline Steps
99
+ ## Features
73
100
 
74
- ### 1. Implement
75
- Takes your requirement and asks Claude to implement it following project conventions.
101
+ - **Real-time Progress Visualization**: See exactly what Claude is doing with colorized, emoji-enhanced output
102
+ - 📖 File reads in cyan
103
+ - ✍️ File writes in green
104
+ - ✏️ File edits in yellow
105
+ - ⚡ Command execution in magenta
106
+ - 🔍 Code searches in blue
107
+ - **Smart Branch Management**: Automatically creates feature branches based on requirement type
108
+ - **Adaptive Execution**: AI-powered step optimization that skips unnecessary stages
109
+ - **Comprehensive Code Quality**: Multi-stage review process ensuring best practices
110
+
111
+ ## Pipeline Steps
76
112
 
77
- ### 2. Code Simplification
78
- Refines the implementation for clarity, consistency, and maintainability while preserving functionality:
113
+ ### 1. Smart Branch Management
114
+ Analyzes your requirement and automatically creates appropriate feature branches:
115
+ - Detects change type (feature/fix/refactor/docs/chore)
116
+ - Creates semantically named branches
117
+ - Warns about potential conflicts
118
+
119
+ ### 2. Implement
120
+ Claude understands your codebase and implements the requirement:
121
+ - Analyzes project structure and patterns
122
+ - Follows project conventions
123
+ - Handles edge cases appropriately
124
+ - Minimal, focused changes
125
+
126
+ ### 3. Code Simplification
127
+ Refines the implementation for clarity, consistency, and maintainability:
79
128
  - Follows project standards (ES modules, explicit types)
80
129
  - Enhances clarity by avoiding nested ternaries
81
130
  - Removes redundant abstractions
82
131
 
83
- ### 3. Code Review (configurable iterations)
132
+ ### 4. Code Review (configurable iterations)
84
133
  Reviews the implementation for:
85
134
  - Bugs (logic errors, null refs, race conditions)
86
135
  - Security issues (injection, auth problems)
87
136
  - Performance (N+1 queries, memory leaks)
88
137
  - Maintainability (clarity, naming, complexity)
89
138
 
90
- ### 4. SOLID & Clean Code
139
+ ### 5. SOLID & Clean Code
91
140
  Ensures compliance with:
92
141
  - SOLID principles (SRP, OCP, LSP, ISP, DIP)
93
142
  - Clean code practices (naming, small functions, no magic numbers)
94
143
 
95
- ### 5. Testing
144
+ ### 6. Testing
96
145
  - Runs existing tests
97
146
  - Adds new tests for changed code
98
147
  - Verifies coverage
99
148
 
100
- ### 6. Commit
149
+ ### 7. Commit
101
150
  Creates a well-formatted commit with:
102
151
  - Conventional commit format
103
152
  - Clear subject line
104
153
  - Detailed body explaining why and what
105
154
 
106
- ### 7. Changelog
155
+ ### 8. Changelog
107
156
  Updates CHANGELOG.md following Keep a Changelog format.
108
157
 
109
158
  ## License
package/dist/claude.js CHANGED
@@ -1,8 +1,73 @@
1
1
  import spawn from 'cross-spawn';
2
+ import chalk from 'chalk';
2
3
  import { logInfo, logSuccess, logError, logDryRun } from './logger.js';
3
4
  // Exit codes
4
5
  const EXIT_SUCCESS = 0;
5
6
  const EXIT_INTERRUPTED = 130;
7
+ function formatToolCall(name, input) {
8
+ const toolColors = {
9
+ Read: 'cyan',
10
+ Write: 'green',
11
+ Edit: 'yellow',
12
+ Bash: 'magenta',
13
+ Grep: 'blue',
14
+ Glob: 'blue',
15
+ };
16
+ const color = toolColors[name] || 'white';
17
+ const colorFn = chalk[color];
18
+ if (name === 'Read' && input && typeof input === 'object' && 'file_path' in input) {
19
+ return colorFn(`📖 Reading: ${input.file_path}`);
20
+ }
21
+ if (name === 'Write' && input && typeof input === 'object' && 'file_path' in input) {
22
+ return colorFn(`✍️ Writing: ${input.file_path}`);
23
+ }
24
+ if (name === 'Edit' && input && typeof input === 'object' && 'file_path' in input) {
25
+ return colorFn(`✏️ Editing: ${input.file_path}`);
26
+ }
27
+ if (name === 'Bash' && input && typeof input === 'object' && 'description' in input) {
28
+ return colorFn(`⚡ Running: ${input.description}`);
29
+ }
30
+ if (name === 'Grep' && input && typeof input === 'object' && 'pattern' in input) {
31
+ return colorFn(`🔍 Searching: ${input.pattern}`);
32
+ }
33
+ if (name === 'Glob' && input && typeof input === 'object' && 'pattern' in input) {
34
+ return colorFn(`📁 Finding: ${input.pattern}`);
35
+ }
36
+ return colorFn(`🔧 ${name}`);
37
+ }
38
+ let lastPrintedMessage = '';
39
+ function processStreamEvent(line) {
40
+ try {
41
+ const event = JSON.parse(line);
42
+ if (event.type === 'system' && event.subtype === 'init') {
43
+ console.log(chalk.dim('━'.repeat(60)));
44
+ console.log(chalk.bold.cyan('🤖 Claude is ready'));
45
+ console.log(chalk.dim('━'.repeat(60)));
46
+ lastPrintedMessage = ''; // Reset on new session
47
+ return;
48
+ }
49
+ if (event.type === 'assistant' && event.message?.content) {
50
+ for (const content of event.message.content) {
51
+ if (content.type === 'text' && content.text) {
52
+ // Print assistant text responses (always print, don't deduplicate text)
53
+ console.log(chalk.white(content.text));
54
+ lastPrintedMessage = ''; // Reset after text message
55
+ }
56
+ else if (content.type === 'tool_use' && content.name) {
57
+ // Print formatted tool calls (deduplicate consecutive identical messages)
58
+ const message = formatToolCall(content.name, content.input);
59
+ if (message !== lastPrintedMessage) {
60
+ console.log(message);
61
+ lastPrintedMessage = message;
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ catch (error) {
68
+ // Silently ignore JSON parse errors for non-JSON lines
69
+ }
70
+ }
6
71
  export async function runClaude(options, config) {
7
72
  // Build the full prompt with exit instruction (like Python version)
8
73
  const fullPrompt = `${options.prompt}. Once the work is completed, exit.`;
@@ -10,9 +75,8 @@ export async function runClaude(options, config) {
10
75
  if (config.dangerouslySkipPermissions) {
11
76
  args.push('--dangerously-skip-permissions');
12
77
  }
13
- if (config.printOutput) {
14
- args.push('-p');
15
- }
78
+ // Always pass -p for output and add streaming JSON output format
79
+ args.push('-p', '--output-format=stream-json', '--verbose');
16
80
  if (options.continueConversation) {
17
81
  args.push('-c');
18
82
  }
@@ -24,16 +88,38 @@ export async function runClaude(options, config) {
24
88
  }
25
89
  logInfo('Calling Claude...');
26
90
  return new Promise((resolve) => {
27
- // Spawn Claude using cross-spawn for cross-platform compatibility
28
- // cross-spawn handles Windows .cmd/.bat files automatically without shell:true
29
- // Use 'inherit' for stdio to allow Claude's interactive UI to work properly
91
+ let outputBuffer = '';
92
+ // Spawn Claude with piped stdio to capture stream-json output
30
93
  const child = spawn('claude', args, {
31
94
  cwd: process.cwd(),
32
95
  env: process.env,
33
- stdio: 'inherit',
96
+ stdio: ['inherit', 'pipe', 'inherit'], // pipe stdout, inherit stdin and stderr
97
+ });
98
+ // Process stdout line by line
99
+ child.stdout?.on('data', (data) => {
100
+ const lines = data.toString().split('\n');
101
+ for (let i = 0; i < lines.length; i++) {
102
+ if (i === lines.length - 1) {
103
+ // Last line might be incomplete, buffer it
104
+ outputBuffer += lines[i];
105
+ }
106
+ else {
107
+ // Complete line, process it
108
+ const line = outputBuffer + lines[i];
109
+ outputBuffer = '';
110
+ if (line.trim()) {
111
+ processStreamEvent(line);
112
+ }
113
+ }
114
+ }
34
115
  });
35
116
  // Handle process exit
36
117
  child.on('close', (exitCode) => {
118
+ // Process any remaining buffered output
119
+ if (outputBuffer.trim()) {
120
+ processStreamEvent(outputBuffer);
121
+ }
122
+ console.log(chalk.dim('━'.repeat(60)));
37
123
  if (exitCode === EXIT_INTERRUPTED || exitCode === 2) {
38
124
  logError('Claude interrupted');
39
125
  process.exit(EXIT_INTERRUPTED);
package/dist/config.d.ts CHANGED
@@ -6,7 +6,6 @@ export interface Config {
6
6
  skipPush: boolean;
7
7
  skipBranchManagement: boolean;
8
8
  dangerouslySkipPermissions: boolean;
9
- printOutput: boolean;
10
9
  requirement: string;
11
10
  adaptiveExecution: boolean;
12
11
  }
package/dist/config.js CHANGED
@@ -19,7 +19,6 @@ export function loadConfigFromEnv() {
19
19
  skipPush: parseBoolEnv(process.env.SF_SKIP_PUSH, false),
20
20
  skipBranchManagement: parseBoolEnv(process.env.SF_SKIP_BRANCH_MANAGEMENT, false),
21
21
  dangerouslySkipPermissions: parseBoolEnv(process.env.SF_DANGEROUSLY_SKIP_PERMISSIONS, false),
22
- printOutput: parseBoolEnv(process.env.SF_PRINT_OUTPUT, false),
23
22
  adaptiveExecution: parseBoolEnv(process.env.SF_ADAPTIVE_EXECUTION, false),
24
23
  };
25
24
  }
@@ -32,7 +31,6 @@ export function mergeConfig(envConfig, cliConfig) {
32
31
  skipPush: cliConfig.skipPush ?? envConfig.skipPush ?? false,
33
32
  skipBranchManagement: cliConfig.skipBranchManagement ?? envConfig.skipBranchManagement ?? false,
34
33
  dangerouslySkipPermissions: cliConfig.dangerouslySkipPermissions ?? envConfig.dangerouslySkipPermissions ?? false,
35
- printOutput: cliConfig.printOutput ?? envConfig.printOutput ?? false,
36
34
  requirement: cliConfig.requirement ?? '',
37
35
  adaptiveExecution: cliConfig.adaptiveExecution ?? envConfig.adaptiveExecution ?? false,
38
36
  };
package/dist/index.js CHANGED
@@ -4,9 +4,34 @@ import chalk from 'chalk';
4
4
  import { readFileSync } from 'fs';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { dirname, join } from 'path';
7
+ import { createInterface } from 'readline';
7
8
  import { loadConfigFromEnv, mergeConfig } from './config.js';
8
9
  import { runPipeline } from './pipeline.js';
9
10
  import { checkForUpdates } from './utils/updateNotifier.js';
11
+ async function promptForRequirement() {
12
+ console.log(chalk.cyan('Enter your requirement (press Ctrl+D or type END on a new line when done):'));
13
+ console.log(chalk.gray('─'.repeat(60)));
14
+ const rl = createInterface({
15
+ input: process.stdin,
16
+ output: process.stdout,
17
+ terminal: process.stdin.isTTY ?? false,
18
+ });
19
+ const lines = [];
20
+ return new Promise((resolve) => {
21
+ rl.on('line', (line) => {
22
+ if (line.trim().toUpperCase() === 'END') {
23
+ rl.close();
24
+ }
25
+ else {
26
+ lines.push(line);
27
+ }
28
+ });
29
+ rl.on('close', () => {
30
+ console.log(chalk.gray('─'.repeat(60)));
31
+ resolve(lines.join('\n').trim());
32
+ });
33
+ });
34
+ }
10
35
  const __filename = fileURLToPath(import.meta.url);
11
36
  const __dirname = dirname(__filename);
12
37
  const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
@@ -15,7 +40,7 @@ program
15
40
  .name('sf')
16
41
  .description('Software Factory Pipeline - Automate development workflow with Claude AI')
17
42
  .version(pkg.version)
18
- .argument('<requirement>', 'The requirement or task to implement')
43
+ .argument('[requirement]', 'The requirement or task to implement')
19
44
  .option('-d, --dry-run', 'Print commands without executing')
20
45
  .option('-r, --reviews <n>', 'Number of review iterations', '2')
21
46
  .option('-a, --adaptive', 'Enable adaptive step execution (AI decides which steps to skip)')
@@ -24,13 +49,17 @@ program
24
49
  .option('--skip-branch-management', 'Skip smart branch management')
25
50
  .option('--log <file>', 'Log output to file')
26
51
  .option('--dangerously-skip-permissions', 'Pass flag to claude to skip permission prompts')
27
- .option('-p, --print', 'Print Claude output (pass -p to claude CLI)')
28
52
  .action(async (requirement, options) => {
29
53
  // Check for updates (non-blocking, fails silently)
30
54
  await checkForUpdates(pkg.name, pkg.version).catch(() => { });
55
+ // Prompt for requirement if not provided
56
+ let finalRequirement = requirement;
57
+ if (!finalRequirement) {
58
+ finalRequirement = await promptForRequirement();
59
+ }
31
60
  const envConfig = loadConfigFromEnv();
32
61
  const cliConfig = {
33
- requirement,
62
+ requirement: finalRequirement,
34
63
  dryRun: options.dryRun ?? undefined,
35
64
  reviewIterations: options.reviews ? parseInt(options.reviews, 10) : undefined,
36
65
  skipTests: options.skipTests ?? undefined,
@@ -38,7 +67,6 @@ program
38
67
  skipBranchManagement: options.skipBranchManagement ?? undefined,
39
68
  logFile: options.log ?? undefined,
40
69
  dangerouslySkipPermissions: options.dangerouslySkipPermissions ?? undefined,
41
- printOutput: options.print ?? undefined,
42
70
  adaptiveExecution: options.adaptive ?? undefined,
43
71
  };
44
72
  const config = mergeConfig(envConfig, cliConfig);
package/dist/pipeline.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { log, logHeader, setLogFile, logInfo } from './logger.js';
3
- import { stepBranchManagement, stepUnderstandCodebase, stepImplement, stepSimplify, stepReview, stepSolidCleanCode, stepTest, stepCommit, stepChangelog, } from './steps/index.js';
3
+ import { stepBranchManagement, stepImplement, stepSimplify, stepReview, stepSolidCleanCode, stepTest, stepCommit, stepChangelog, } from './steps/index.js';
4
4
  let signalHandlersRegistered = false;
5
5
  export async function runPipeline(config) {
6
6
  // Setup logging
@@ -31,13 +31,7 @@ export async function runPipeline(config) {
31
31
  // Extract adaptive analysis for step decisions
32
32
  const adaptive = branchResult.adaptiveAnalysis;
33
33
  const rec = adaptive?.stepRecommendation;
34
- // Step 2: Understand Codebase
35
- const understandSuccess = await stepUnderstandCodebase(config);
36
- if (!understandSuccess) {
37
- console.log(chalk.red('\nUnderstand codebase step failed. Exiting.'));
38
- process.exit(1);
39
- }
40
- // Step 3: Implement
34
+ // Step 2: Implement
41
35
  const implSuccess = await stepImplement(config);
42
36
  if (!implSuccess) {
43
37
  console.log(chalk.red('\nImplementation step failed. Exiting.'));
@@ -46,7 +46,7 @@ function branchMatchesRequirement(currentBranch, analysis) {
46
46
  return overlap || (prefixMatches && suggestedKeywords.length === 0);
47
47
  }
48
48
  export async function stepBranchManagement(config) {
49
- logStep('1/9', 'SMART BRANCH MANAGEMENT');
49
+ logStep('1/8', 'SMART BRANCH MANAGEMENT');
50
50
  const adaptiveAnalysis = config.adaptiveExecution ? await performAdaptiveAnalysis(config) : null;
51
51
  if (config.skipBranchManagement) {
52
52
  logInfo('Branch management skipped (--skip-branch-management)');
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepChangelog(config) {
4
- logStep('9/9', 'UPDATE CHANGELOG');
4
+ logStep('8/8', 'UPDATE CHANGELOG');
5
5
  const prompt = `Update CHANGELOG.md:
6
6
 
7
7
  ## Format (Keep a Changelog):
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepCommit(config) {
4
- logStep('8/9', 'COMMIT CHANGES');
4
+ logStep('7/8', 'COMMIT CHANGES');
5
5
  const pushInstruction = config.skipPush ? '' : 'Then push to remote.';
6
6
  const prompt = `Commit the changes:
7
7
 
@@ -1,14 +1,15 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepImplement(config) {
4
- logStep('3/9', 'IMPLEMENT REQUIREMENT');
4
+ logStep('2/8', 'IMPLEMENT REQUIREMENT');
5
5
  const prompt = `${config.requirement}
6
6
 
7
7
  ## Implementation Guidelines:
8
+ - First, understand the codebase structure and identify relevant files for this requirement
8
9
  - Write clean, idiomatic code following project conventions
9
10
  - Handle edge cases and errors appropriately
10
11
  - Add necessary comments for complex logic
11
12
  - Keep changes focused and minimal. Once the work is completed, exit.`;
12
- const result = await runClaude({ prompt, continueConversation: true }, config);
13
+ const result = await runClaude({ prompt }, config);
13
14
  return result.success;
14
15
  }
@@ -1,5 +1,4 @@
1
1
  export { stepBranchManagement, type BranchResult } from './branchManagement.js';
2
- export { stepUnderstandCodebase } from './understand.js';
3
2
  export { stepImplement } from './implement.js';
4
3
  export { stepSimplify } from './simplify.js';
5
4
  export { stepReview, type ReviewResult, type ReviewDepth } from './review.js';
@@ -1,5 +1,4 @@
1
1
  export { stepBranchManagement } from './branchManagement.js';
2
- export { stepUnderstandCodebase } from './understand.js';
3
2
  export { stepImplement } from './implement.js';
4
3
  export { stepSimplify } from './simplify.js';
5
4
  export { stepReview } from './review.js';
@@ -60,7 +60,7 @@ function getPromptForDepth(depth) {
60
60
  }
61
61
  export async function stepReview(iteration, config, depth = 'standard') {
62
62
  const depthLabel = depth !== 'standard' ? ` [${depth}]` : '';
63
- logStep('5/9', `CODE REVIEW (Round ${iteration}/${config.reviewIterations})${depthLabel}`);
63
+ logStep('4/8', `CODE REVIEW (Round ${iteration}/${config.reviewIterations})${depthLabel}`);
64
64
  const prompt = getPromptForDepth(depth);
65
65
  const result = await runClaude({ prompt, continueConversation: true }, config);
66
66
  const noIssuesFound = result.success && detectNoIssues(result.output);
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepSimplify(config) {
4
- logStep('4/9', 'CODE SIMPLIFICATION');
4
+ logStep('3/8', 'CODE SIMPLIFICATION');
5
5
  const prompt = `Refine the recently modified code for clarity, consistency, and maintainability while preserving all functionality.
6
6
 
7
7
  ## Core Principles:
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepSolidCleanCode(config) {
4
- logStep('6/9', 'SOLID PRINCIPLES & CLEAN CODE');
4
+ logStep('5/8', 'SOLID PRINCIPLES & CLEAN CODE');
5
5
  const prompt = `Review the code for SOLID principles and Clean Code compliance:
6
6
 
7
7
  ## SOLID Principles:
@@ -2,7 +2,7 @@ import chalk from 'chalk';
2
2
  import { logStep } from '../logger.js';
3
3
  import { runClaude } from '../claude.js';
4
4
  export async function stepTest(config) {
5
- logStep('7/9', 'TESTING');
5
+ logStep('6/8', 'TESTING');
6
6
  if (config.skipTests) {
7
7
  console.log(chalk.yellow('[SKIPPED]') + ' Testing step skipped via configuration');
8
8
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "software-engineer",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "CLI that automates the full dev workflow with Claude AI - implement, review, test, and commit code with a single command",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",