@jonit-dev/night-watch-cli 1.0.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +509 -0
  3. package/bin/night-watch.mjs +2 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +35 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/init.d.ts +8 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +376 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/install.d.ts +15 -0
  13. package/dist/commands/install.d.ts.map +1 -0
  14. package/dist/commands/install.js +135 -0
  15. package/dist/commands/install.js.map +1 -0
  16. package/dist/commands/logs.d.ts +15 -0
  17. package/dist/commands/logs.d.ts.map +1 -0
  18. package/dist/commands/logs.js +104 -0
  19. package/dist/commands/logs.js.map +1 -0
  20. package/dist/commands/review.d.ts +26 -0
  21. package/dist/commands/review.d.ts.map +1 -0
  22. package/dist/commands/review.js +144 -0
  23. package/dist/commands/review.js.map +1 -0
  24. package/dist/commands/run.d.ts +26 -0
  25. package/dist/commands/run.d.ts.map +1 -0
  26. package/dist/commands/run.js +161 -0
  27. package/dist/commands/run.js.map +1 -0
  28. package/dist/commands/status.d.ts +14 -0
  29. package/dist/commands/status.d.ts.map +1 -0
  30. package/dist/commands/status.js +303 -0
  31. package/dist/commands/status.js.map +1 -0
  32. package/dist/commands/uninstall.d.ts +13 -0
  33. package/dist/commands/uninstall.d.ts.map +1 -0
  34. package/dist/commands/uninstall.js +97 -0
  35. package/dist/commands/uninstall.js.map +1 -0
  36. package/dist/config.d.ts +23 -0
  37. package/dist/config.d.ts.map +1 -0
  38. package/dist/config.js +213 -0
  39. package/dist/config.js.map +1 -0
  40. package/dist/constants.d.ts +21 -0
  41. package/dist/constants.d.ts.map +1 -0
  42. package/dist/constants.js +33 -0
  43. package/dist/constants.js.map +1 -0
  44. package/dist/types.d.ts +35 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +5 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/utils/crontab.d.ts +50 -0
  49. package/dist/utils/crontab.d.ts.map +1 -0
  50. package/dist/utils/crontab.js +116 -0
  51. package/dist/utils/crontab.js.map +1 -0
  52. package/dist/utils/shell.d.ts +13 -0
  53. package/dist/utils/shell.d.ts.map +1 -0
  54. package/dist/utils/shell.js +44 -0
  55. package/dist/utils/shell.js.map +1 -0
  56. package/dist/utils/ui.d.ts +55 -0
  57. package/dist/utils/ui.d.ts.map +1 -0
  58. package/dist/utils/ui.js +121 -0
  59. package/dist/utils/ui.js.map +1 -0
  60. package/package.json +64 -0
  61. package/scripts/night-watch-cron.sh +148 -0
  62. package/scripts/night-watch-helpers.sh +155 -0
  63. package/scripts/night-watch-pr-reviewer-cron.sh +135 -0
  64. package/templates/night-watch-pr-reviewer.md +144 -0
  65. package/templates/night-watch.config.json +21 -0
  66. package/templates/night-watch.md +100 -0
  67. package/templates/prd-executor.md +235 -0
@@ -0,0 +1,376 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { execSync } from 'child_process';
5
+ import { fileURLToPath } from 'url';
6
+ import { dirname, join } from 'path';
7
+ import * as readline from 'readline';
8
+ import { CONFIG_FILE_NAME, DEFAULT_PRD_DIR, LOG_DIR, VALID_PROVIDERS, } from '../constants.js';
9
+ import { success, error as uiError, info, header, dim, label, step, createTable, } from '../utils/ui.js';
10
+ // Get templates directory path
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ const TEMPLATES_DIR = join(__dirname, '..', '..', 'templates');
14
+ /**
15
+ * Get the default branch name for the repository
16
+ */
17
+ function getDefaultBranch(cwd) {
18
+ try {
19
+ // Try to get the default branch from origin
20
+ const remoteRef = execSync('git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo ""', {
21
+ encoding: 'utf-8',
22
+ cwd,
23
+ stdio: ['pipe', 'pipe', 'pipe']
24
+ }).trim();
25
+ if (remoteRef) {
26
+ // Extract branch name from refs/remotes/origin/HEAD -> refs/remotes/origin/main
27
+ const match = remoteRef.match(/refs\/remotes\/origin\/(.+)/);
28
+ if (match) {
29
+ return match[1];
30
+ }
31
+ }
32
+ // Fallback: check if main or master exists
33
+ const branches = execSync('git branch --list main master', {
34
+ encoding: 'utf-8',
35
+ cwd,
36
+ stdio: ['pipe', 'pipe', 'pipe']
37
+ }).trim();
38
+ if (branches.includes('main')) {
39
+ return 'main';
40
+ }
41
+ if (branches.includes('master')) {
42
+ return 'master';
43
+ }
44
+ // Default to main
45
+ return 'main';
46
+ }
47
+ catch {
48
+ return 'main';
49
+ }
50
+ }
51
+ /**
52
+ * Get the project name from the directory
53
+ */
54
+ function getProjectName(cwd) {
55
+ return path.basename(cwd);
56
+ }
57
+ /**
58
+ * Check if current directory is a git repository
59
+ */
60
+ function isGitRepo(cwd) {
61
+ return fs.existsSync(path.join(cwd, '.git'));
62
+ }
63
+ /**
64
+ * Check if gh CLI is authenticated
65
+ */
66
+ function isGhAuthenticated() {
67
+ try {
68
+ execSync('gh auth status', {
69
+ encoding: 'utf-8',
70
+ stdio: ['pipe', 'pipe', 'pipe']
71
+ });
72
+ return true;
73
+ }
74
+ catch {
75
+ return false;
76
+ }
77
+ }
78
+ /**
79
+ * Check if claude CLI is available
80
+ */
81
+ function isClaudeAvailable() {
82
+ try {
83
+ execSync('which claude', {
84
+ encoding: 'utf-8',
85
+ stdio: ['pipe', 'pipe', 'pipe']
86
+ });
87
+ return true;
88
+ }
89
+ catch {
90
+ return false;
91
+ }
92
+ }
93
+ /**
94
+ * Check if codex CLI is available
95
+ */
96
+ function isCodexAvailable() {
97
+ try {
98
+ execSync('which codex', {
99
+ encoding: 'utf-8',
100
+ stdio: ['pipe', 'pipe', 'pipe']
101
+ });
102
+ return true;
103
+ }
104
+ catch {
105
+ return false;
106
+ }
107
+ }
108
+ /**
109
+ * Detect which AI provider CLIs are installed
110
+ */
111
+ function detectProviders() {
112
+ const providers = [];
113
+ if (isClaudeAvailable()) {
114
+ providers.push('claude');
115
+ }
116
+ if (isCodexAvailable()) {
117
+ providers.push('codex');
118
+ }
119
+ return providers;
120
+ }
121
+ /**
122
+ * Prompt user to select a provider from available options
123
+ */
124
+ function promptProviderSelection(providers) {
125
+ return new Promise((resolve, reject) => {
126
+ const rl = readline.createInterface({
127
+ input: process.stdin,
128
+ output: process.stdout
129
+ });
130
+ console.log('\nMultiple AI providers detected:');
131
+ providers.forEach((p, i) => {
132
+ console.log(` ${i + 1}. ${p}`);
133
+ });
134
+ rl.question('\nSelect a provider (enter number): ', (answer) => {
135
+ rl.close();
136
+ const selection = parseInt(answer.trim(), 10);
137
+ if (isNaN(selection) || selection < 1 || selection > providers.length) {
138
+ reject(new Error('Invalid selection. Please run init again and select a valid number.'));
139
+ return;
140
+ }
141
+ resolve(providers[selection - 1]);
142
+ });
143
+ });
144
+ }
145
+ /**
146
+ * Create directory if it doesn't exist
147
+ */
148
+ function ensureDir(dirPath) {
149
+ if (!fs.existsSync(dirPath)) {
150
+ fs.mkdirSync(dirPath, { recursive: true });
151
+ }
152
+ }
153
+ /**
154
+ * Copy and process template file
155
+ */
156
+ function processTemplate(templateName, targetPath, replacements, force) {
157
+ // Skip if exists and not forcing
158
+ if (fs.existsSync(targetPath) && !force) {
159
+ console.log(` Skipped (exists): ${targetPath}`);
160
+ return false;
161
+ }
162
+ const templatePath = join(TEMPLATES_DIR, templateName);
163
+ let content = fs.readFileSync(templatePath, 'utf-8');
164
+ // Replace placeholders
165
+ for (const [key, value] of Object.entries(replacements)) {
166
+ content = content.replaceAll(key, value);
167
+ }
168
+ fs.writeFileSync(targetPath, content);
169
+ console.log(` Created: ${targetPath}`);
170
+ return true;
171
+ }
172
+ /**
173
+ * Add /logs/ to .gitignore if not already there
174
+ */
175
+ function addToGitignore(cwd) {
176
+ const gitignorePath = path.join(cwd, '.gitignore');
177
+ if (!fs.existsSync(gitignorePath)) {
178
+ fs.writeFileSync(gitignorePath, '# Night Watch logs\n/logs/\n');
179
+ console.log(` Created: ${gitignorePath} (with /logs/ entry)`);
180
+ return;
181
+ }
182
+ const content = fs.readFileSync(gitignorePath, 'utf-8');
183
+ // Check if /logs/ or logs/ already exists
184
+ if (content.includes('/logs/') || /^logs\//m.test(content)) {
185
+ console.log(` Skipped (exists): /logs/ in .gitignore`);
186
+ return;
187
+ }
188
+ // Append /logs/ to .gitignore
189
+ const newContent = content.trimEnd() + '\n\n# Night Watch logs\n/logs/\n';
190
+ fs.writeFileSync(gitignorePath, newContent);
191
+ console.log(` Updated: ${gitignorePath} (added /logs/ entry)`);
192
+ }
193
+ /**
194
+ * Create NIGHT-WATCH-SUMMARY.md template if it doesn't exist
195
+ */
196
+ function createSummaryFile(summaryPath, force) {
197
+ if (fs.existsSync(summaryPath) && !force) {
198
+ console.log(` Skipped (exists): ${summaryPath}`);
199
+ return;
200
+ }
201
+ const content = `# Night Watch Summary
202
+
203
+ This file tracks the progress of PRDs executed by Night Watch.
204
+
205
+ ---
206
+
207
+ `;
208
+ fs.writeFileSync(summaryPath, content);
209
+ console.log(` Created: ${summaryPath}`);
210
+ }
211
+ /**
212
+ * Main init command implementation
213
+ */
214
+ export function initCommand(program) {
215
+ program
216
+ .command('init')
217
+ .description('Initialize night-watch in the current project')
218
+ .option('-f, --force', 'Overwrite existing configuration')
219
+ .option('-d, --prd-dir <path>', 'Path to PRD directory')
220
+ .option('-p, --provider <name>', 'AI provider to use (claude or codex)')
221
+ .option('--no-reviewer', 'Disable reviewer cron job')
222
+ .action(async (options) => {
223
+ const cwd = process.cwd();
224
+ const force = options.force || false;
225
+ const prdDir = options.prdDir || DEFAULT_PRD_DIR;
226
+ console.log();
227
+ header('Night Watch CLI - Initializing');
228
+ // Step 1: Verify git repository
229
+ step(1, 9, 'Checking git repository...');
230
+ if (!isGitRepo(cwd)) {
231
+ uiError('Current directory is not a git repository.');
232
+ dim('Please run this command from the root of a git repository.');
233
+ process.exit(1);
234
+ }
235
+ success('Git repository found');
236
+ // Step 2: Verify gh CLI
237
+ step(2, 9, 'Checking GitHub CLI (gh)...');
238
+ if (!isGhAuthenticated()) {
239
+ uiError('GitHub CLI (gh) is not authenticated.');
240
+ dim('Please run: gh auth login');
241
+ process.exit(1);
242
+ }
243
+ success('GitHub CLI is authenticated');
244
+ // Step 3: Detect AI providers
245
+ step(3, 9, 'Detecting AI providers...');
246
+ let selectedProvider;
247
+ if (options.provider) {
248
+ // Validate provider flag
249
+ if (!VALID_PROVIDERS.includes(options.provider)) {
250
+ uiError(`Invalid provider "${options.provider}".`);
251
+ dim(`Valid providers: ${VALID_PROVIDERS.join(', ')}`);
252
+ process.exit(1);
253
+ }
254
+ selectedProvider = options.provider;
255
+ info(`Using provider from flag: ${selectedProvider}`);
256
+ }
257
+ else {
258
+ // Auto-detect providers
259
+ const detectedProviders = detectProviders();
260
+ if (detectedProviders.length === 0) {
261
+ uiError('No AI provider CLI found.');
262
+ dim('\nPlease install one of the following:');
263
+ dim(' - Claude CLI: https://docs.anthropic.com/en/docs/claude-cli');
264
+ dim(' - Codex CLI: https://github.com/openai/codex');
265
+ process.exit(1);
266
+ }
267
+ else if (detectedProviders.length === 1) {
268
+ selectedProvider = detectedProviders[0];
269
+ info(`Auto-detected provider: ${selectedProvider}`);
270
+ }
271
+ else {
272
+ // Multiple providers - prompt user
273
+ try {
274
+ selectedProvider = await promptProviderSelection(detectedProviders);
275
+ info(`Selected provider: ${selectedProvider}`);
276
+ }
277
+ catch (err) {
278
+ uiError(`${err instanceof Error ? err.message : String(err)}`);
279
+ process.exit(1);
280
+ }
281
+ }
282
+ }
283
+ // Set reviewerEnabled from flag (default: true, --no-reviewer sets to false)
284
+ const reviewerEnabled = options.reviewer !== false;
285
+ // Gather project information
286
+ const projectName = getProjectName(cwd);
287
+ const defaultBranch = getDefaultBranch(cwd);
288
+ // Display project configuration
289
+ header('Project Configuration');
290
+ label('Project', projectName);
291
+ label('Default branch', defaultBranch);
292
+ label('Provider', selectedProvider);
293
+ label('Reviewer', reviewerEnabled ? 'Enabled' : 'Disabled');
294
+ console.log();
295
+ // Define replacements for templates
296
+ const replacements = {
297
+ '${PROJECT_DIR}': cwd,
298
+ '${PROJECT_NAME}': projectName,
299
+ '${DEFAULT_BRANCH}': defaultBranch,
300
+ };
301
+ // Step 4: Create PRD directory structure
302
+ step(4, 9, 'Creating PRD directory structure...');
303
+ const prdDirPath = path.join(cwd, prdDir);
304
+ const doneDirPath = path.join(prdDirPath, 'done');
305
+ ensureDir(doneDirPath);
306
+ success(`Created ${prdDirPath}/`);
307
+ success(`Created ${doneDirPath}/`);
308
+ // Step 5: Create NIGHT-WATCH-SUMMARY.md
309
+ step(5, 9, 'Creating NIGHT-WATCH-SUMMARY.md...');
310
+ const summaryPath = path.join(prdDirPath, 'NIGHT-WATCH-SUMMARY.md');
311
+ createSummaryFile(summaryPath, force);
312
+ // Step 6: Create logs directory
313
+ step(6, 9, 'Creating logs directory...');
314
+ const logsPath = path.join(cwd, LOG_DIR);
315
+ ensureDir(logsPath);
316
+ success(`Created ${logsPath}/`);
317
+ // Add /logs/ to .gitignore
318
+ addToGitignore(cwd);
319
+ // Step 7: Create .claude/commands directory and copy templates
320
+ step(7, 9, 'Creating Claude slash commands...');
321
+ const commandsDir = path.join(cwd, '.claude', 'commands');
322
+ ensureDir(commandsDir);
323
+ success(`Created ${commandsDir}/`);
324
+ // Copy night-watch.md template
325
+ processTemplate('night-watch.md', path.join(commandsDir, 'night-watch.md'), replacements, force);
326
+ // Copy prd-executor.md template
327
+ processTemplate('prd-executor.md', path.join(commandsDir, 'prd-executor.md'), replacements, force);
328
+ // Copy night-watch-pr-reviewer.md template
329
+ processTemplate('night-watch-pr-reviewer.md', path.join(commandsDir, 'night-watch-pr-reviewer.md'), replacements, force);
330
+ // Step 8: Create config file
331
+ step(8, 9, 'Creating configuration file...');
332
+ const configPath = path.join(cwd, CONFIG_FILE_NAME);
333
+ if (fs.existsSync(configPath) && !force) {
334
+ dim(` Skipped (exists): ${configPath}`);
335
+ }
336
+ else {
337
+ // Read and process config template
338
+ let configContent = fs.readFileSync(join(TEMPLATES_DIR, 'night-watch.config.json'), 'utf-8');
339
+ // Replace placeholders with project values
340
+ configContent = configContent.replace('"projectName": ""', `"projectName": "${projectName}"`);
341
+ configContent = configContent.replace('"defaultBranch": ""', `"defaultBranch": "${defaultBranch}"`);
342
+ // Set provider in config
343
+ configContent = configContent.replace(/"provider":\s*"[^"]*"/, `"provider": "${selectedProvider}"`);
344
+ // Set reviewerEnabled in config
345
+ configContent = configContent.replace(/"reviewerEnabled":\s*(true|false)/, `"reviewerEnabled": ${reviewerEnabled}`);
346
+ fs.writeFileSync(configPath, configContent);
347
+ success(`Created ${configPath}`);
348
+ }
349
+ // Step 9: Print summary
350
+ step(9, 9, 'Initialization complete!');
351
+ // Summary with table
352
+ header('Initialization Complete');
353
+ const filesTable = createTable({ head: ['Created Files', ''] });
354
+ filesTable.push(['PRD Directory', `${prdDir}/done/`]);
355
+ filesTable.push(['Summary File', `${prdDir}/NIGHT-WATCH-SUMMARY.md`]);
356
+ filesTable.push(['Logs Directory', `${LOG_DIR}/`]);
357
+ filesTable.push(['Slash Commands', '.claude/commands/night-watch.md']);
358
+ filesTable.push(['', '.claude/commands/prd-executor.md']);
359
+ filesTable.push(['', '.claude/commands/night-watch-pr-reviewer.md']);
360
+ filesTable.push(['Config File', CONFIG_FILE_NAME]);
361
+ console.log(filesTable.toString());
362
+ // Configuration summary
363
+ header('Configuration');
364
+ label('Provider', selectedProvider);
365
+ label('Reviewer', reviewerEnabled ? 'Enabled' : 'Disabled');
366
+ console.log();
367
+ // Next steps
368
+ header('Next Steps');
369
+ info('1. Add your PRD files to docs/PRDs/night-watch/');
370
+ info('2. Run `night-watch install` to set up cron jobs');
371
+ info('3. Or run `night-watch run` to execute PRDs manually');
372
+ console.log();
373
+ });
374
+ }
375
+ export default initCommand;
376
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Install command for Night Watch CLI
3
+ * Adds crontab entries for automated PRD execution
4
+ */
5
+ import { Command } from "commander";
6
+ export interface InstallOptions {
7
+ schedule?: string;
8
+ reviewerSchedule?: string;
9
+ noReviewer?: boolean;
10
+ }
11
+ /**
12
+ * Install crontab entries for night-watch
13
+ */
14
+ export declare function installCommand(program: Command): void;
15
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA+CD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwFrD"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Install command for Night Watch CLI
3
+ * Adds crontab entries for automated PRD execution
4
+ */
5
+ import { execSync } from "child_process";
6
+ import * as path from "path";
7
+ import * as fs from "fs";
8
+ import { loadConfig } from "../config.js";
9
+ import { LOG_DIR } from "../constants.js";
10
+ import { generateMarker, getEntries, readCrontab, writeCrontab, } from "../utils/crontab.js";
11
+ import { success, error as uiError, warn, header, dim, } from "../utils/ui.js";
12
+ /**
13
+ * Get the path to the night-watch binary
14
+ */
15
+ function getNightWatchBinPath() {
16
+ // Try to find night-watch in npm global bin
17
+ try {
18
+ const npmBin = execSync("npm bin -g", { encoding: "utf-8" }).trim();
19
+ const binPath = path.join(npmBin, "night-watch");
20
+ if (fs.existsSync(binPath)) {
21
+ return binPath;
22
+ }
23
+ }
24
+ catch {
25
+ // Ignore error, fall back to which
26
+ }
27
+ // Try which command
28
+ try {
29
+ return execSync("which night-watch", { encoding: "utf-8" }).trim();
30
+ }
31
+ catch {
32
+ // Fall back to assuming it's in PATH
33
+ return "night-watch";
34
+ }
35
+ }
36
+ /**
37
+ * Get the project name from directory or package.json
38
+ */
39
+ function getProjectName(projectDir) {
40
+ // Try to get name from package.json
41
+ const packageJsonPath = path.join(projectDir, "package.json");
42
+ if (fs.existsSync(packageJsonPath)) {
43
+ try {
44
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
45
+ if (packageJson.name) {
46
+ return packageJson.name;
47
+ }
48
+ }
49
+ catch {
50
+ // Ignore parse errors
51
+ }
52
+ }
53
+ // Fall back to directory name
54
+ return path.basename(projectDir);
55
+ }
56
+ /**
57
+ * Install crontab entries for night-watch
58
+ */
59
+ export function installCommand(program) {
60
+ program
61
+ .command("install")
62
+ .description("Add crontab entries for automated execution")
63
+ .option("-s, --schedule <cron>", "Cron schedule for PRD executor")
64
+ .option("--reviewer-schedule <cron>", "Cron schedule for reviewer")
65
+ .option("--no-reviewer", "Skip installing reviewer cron")
66
+ .action(async (options) => {
67
+ try {
68
+ // Get project directory
69
+ const projectDir = process.cwd();
70
+ // Load configuration
71
+ const config = loadConfig(projectDir);
72
+ // Get schedule from options or config
73
+ const executorSchedule = options.schedule || config.cronSchedule;
74
+ const reviewerSchedule = options.reviewerSchedule || config.reviewerSchedule;
75
+ // Get paths
76
+ const nightWatchBin = getNightWatchBinPath();
77
+ const projectName = getProjectName(projectDir);
78
+ const marker = generateMarker(projectName);
79
+ const logDir = path.join(projectDir, LOG_DIR);
80
+ // Ensure log directory exists
81
+ if (!fs.existsSync(logDir)) {
82
+ fs.mkdirSync(logDir, { recursive: true });
83
+ }
84
+ const executorLog = path.join(logDir, "executor.log");
85
+ const reviewerLog = path.join(logDir, "reviewer.log");
86
+ // Check if already installed
87
+ const existingEntries = getEntries(marker);
88
+ if (existingEntries.length > 0) {
89
+ warn(`Night Watch is already installed for ${projectName}.`);
90
+ console.log();
91
+ dim("Existing crontab entries:");
92
+ existingEntries.forEach((entry) => dim(` ${entry}`));
93
+ console.log();
94
+ dim("Run 'night-watch uninstall' first to reinstall.");
95
+ return;
96
+ }
97
+ // Create crontab entries
98
+ const entries = [];
99
+ // Executor entry
100
+ const executorEntry = `${executorSchedule} cd ${projectDir} && ${nightWatchBin} run >> ${executorLog} 2>&1 ${marker}`;
101
+ entries.push(executorEntry);
102
+ // Determine if reviewer should be installed
103
+ // Priority: --no-reviewer flag > config.reviewerEnabled
104
+ const installReviewer = options.noReviewer === true ? false : config.reviewerEnabled;
105
+ // Reviewer entry (if enabled)
106
+ if (installReviewer) {
107
+ const reviewerEntry = `${reviewerSchedule} cd ${projectDir} && ${nightWatchBin} review >> ${reviewerLog} 2>&1 ${marker}`;
108
+ entries.push(reviewerEntry);
109
+ }
110
+ // Add all entries
111
+ const currentCrontab = readCrontab();
112
+ const newCrontab = [...currentCrontab, ...entries];
113
+ writeCrontab(newCrontab);
114
+ // Success message
115
+ success(`Night Watch installed successfully for ${projectName}!`);
116
+ console.log();
117
+ header("Crontab Entries Added");
118
+ entries.forEach((entry) => dim(` ${entry}`));
119
+ console.log();
120
+ header("Log Files");
121
+ dim(` Executor: ${executorLog}`);
122
+ if (installReviewer) {
123
+ dim(` Reviewer: ${reviewerLog}`);
124
+ }
125
+ console.log();
126
+ dim("To uninstall, run: night-watch uninstall");
127
+ dim("To check status, run: night-watch status");
128
+ }
129
+ catch (err) {
130
+ uiError(`Error installing Night Watch: ${err instanceof Error ? err.message : String(err)}`);
131
+ process.exit(1);
132
+ }
133
+ });
134
+ }
135
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Logs command for Night Watch CLI
3
+ * View log output from executor and reviewer
4
+ */
5
+ import { Command } from "commander";
6
+ export interface LogsOptions {
7
+ lines?: string;
8
+ follow?: boolean;
9
+ type?: string;
10
+ }
11
+ /**
12
+ * Logs command implementation
13
+ */
14
+ export declare function logsCommand(program: Command): void;
15
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA4CD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8DlD"}