Compare commits

...
Author SHA1 Message Date
Tabish Bidiwale edf6873afa feat(cli): add update command to refresh OpenSpec instructions and CLAUDE.md via markers 2025-08-11 21:37:46 +10:00
Tabish Bidiwale c0ce4adc0a Merge pull request #8 from Fission-AI/add-update-command
Add update command for OpenSpec instructions
2025-08-11 20:48:04 +10:00
3 changed files with 64 additions and 13 deletions
+13 -13
View File
@@ -1,20 +1,20 @@
# Implementation Tasks
## 1. Update Command Implementation
- [ ] 1.1 Create `src/core/update.ts` with `UpdateCommand` class
- [ ] 1.2 Check if `openspec` directory exists (use `FileSystemUtils.directoryExists`)
- [ ] 1.3 Write `readmeTemplate` to `openspec/README.md` using `FileSystemUtils.writeFile`
- [ ] 1.4 Update `CLAUDE.md` using markers via `FileSystemUtils.updateFileWithMarkers` and `TemplateManager.getClaudeTemplate()`
- [ ] 1.5 Display ASCII-safe success message: `Updated OpenSpec instructions`
- [x] 1.1 Create `src/core/update.ts` with `UpdateCommand` class
- [x] 1.2 Check if `openspec` directory exists (use `FileSystemUtils.directoryExists`)
- [x] 1.3 Write `readmeTemplate` to `openspec/README.md` using `FileSystemUtils.writeFile`
- [x] 1.4 Update `CLAUDE.md` using markers via `FileSystemUtils.updateFileWithMarkers` and `TemplateManager.getClaudeTemplate()`
- [x] 1.5 Display ASCII-safe success message: `Updated OpenSpec instructions`
## 2. CLI Integration
- [ ] 2.1 Register `update` command in `src/cli/index.ts`
- [ ] 2.2 Add command description: `Update OpenSpec instruction files`
- [ ] 2.3 Handle errors with `ora().fail(...)` and exit code 1 (missing `openspec` directory, file write errors)
- [x] 2.1 Register `update` command in `src/cli/index.ts`
- [x] 2.2 Add command description: `Update OpenSpec instruction files`
- [x] 2.3 Handle errors with `ora().fail(...)` and exit code 1 (missing `openspec` directory, file write errors)
## 3. Testing
- [ ] 3.1 Verify `openspec/README.md` is fully replaced with latest template
- [ ] 3.2 Verify `CLAUDE.md` OpenSpec block updates without altering user content outside markers
- [ ] 3.3 Verify idempotency (running twice yields identical files, no duplicate markers)
- [ ] 3.4 Verify error when `openspec` directory is missing with friendly message
- [ ] 3.5 Verify success message displays properly in ASCII-only terminals
- [x] 3.1 Verify `openspec/README.md` is fully replaced with latest template
- [x] 3.2 Verify `CLAUDE.md` OpenSpec block updates without altering user content outside markers
- [x] 3.3 Verify idempotency (running twice yields identical files, no duplicate markers)
- [x] 3.4 Verify error when `openspec` directory is missing with friendly message
- [x] 3.5 Verify success message displays properly in ASCII-only terminals
+16
View File
@@ -3,6 +3,7 @@ import ora from 'ora';
import path from 'path';
import { promises as fs } from 'fs';
import { InitCommand } from '../core/init.js';
import { UpdateCommand } from '../core/update.js';
const program = new Command();
@@ -44,4 +45,19 @@ program
}
});
program
.command('update [path]')
.description('Update OpenSpec instruction files')
.action(async (targetPath = '.') => {
try {
const resolvedPath = path.resolve(targetPath);
const updateCommand = new UpdateCommand();
await updateCommand.execute(resolvedPath);
} catch (error) {
console.log(); // Empty line for spacing
ora().fail(`Error: ${(error as Error).message}`);
process.exit(1);
}
});
program.parse();
+35
View File
@@ -0,0 +1,35 @@
import path from 'path';
import { FileSystemUtils } from '../utils/file-system.js';
import { TemplateManager } from './templates/index.js';
import { OPENSPEC_DIR_NAME, OPENSPEC_MARKERS } from './config.js';
import { readmeTemplate } from './templates/readme-template.js';
export class UpdateCommand {
async execute(projectPath: string): Promise<void> {
const resolvedProjectPath = path.resolve(projectPath);
const openspecDirName = OPENSPEC_DIR_NAME;
const openspecPath = path.join(resolvedProjectPath, openspecDirName);
// 1. Check openspec directory exists
if (!await FileSystemUtils.directoryExists(openspecPath)) {
throw new Error(`No OpenSpec directory found. Run 'openspec init' first.`);
}
// 2. Update README.md (full replacement)
const readmePath = path.join(openspecPath, 'README.md');
await FileSystemUtils.writeFile(readmePath, readmeTemplate);
// 3. Update CLAUDE.md (marker-based)
const claudePath = path.join(resolvedProjectPath, 'CLAUDE.md');
const claudeContent = TemplateManager.getClaudeTemplate();
await FileSystemUtils.updateFileWithMarkers(
claudePath,
claudeContent,
OPENSPEC_MARKERS.start,
OPENSPEC_MARKERS.end
);
// 4. Success message (ASCII-safe)
console.log('Updated OpenSpec instructions');
}
}