@damper/cli 0.9.18 → 0.9.19

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,5 +1,6 @@
1
1
  import { search, select, confirm, input, Separator } from '@inquirer/prompts';
2
2
  import pc from 'picocolors';
3
+ import * as readline from 'readline';
3
4
  import { shortId, shortIdRaw, getTypeIcon, getPriorityIcon, formatEffort, formatProgressCompact, formatDueDate, sectionHeader, relativeTime, getTerminalWidth, padEnd, padStart, } from './format.js';
4
5
  // Layout constants (terminal column widths)
5
6
  const CURSOR_WIDTH = 2; // inquirer select prefix (❯ or )
@@ -265,15 +266,50 @@ export async function pickTask(options) {
265
266
  action,
266
267
  };
267
268
  }
269
+ function multilineInput(message) {
270
+ return new Promise((resolve) => {
271
+ process.stdout.write(`${pc.bold(pc.green('?'))} ${pc.bold(message)} ${pc.dim('(Enter to skip)')}\n`);
272
+ const lines = [];
273
+ let hintShown = false;
274
+ let hintTimer = null;
275
+ const rl = readline.createInterface({
276
+ input: process.stdin,
277
+ output: process.stdout,
278
+ prompt: '',
279
+ });
280
+ const showHint = () => {
281
+ if (!hintShown) {
282
+ hintShown = true;
283
+ process.stdout.write(pc.dim(' (Press Enter on an empty line to submit)\n'));
284
+ }
285
+ };
286
+ rl.on('line', (line) => {
287
+ if (hintTimer)
288
+ clearTimeout(hintTimer);
289
+ if (lines.length === 0 && line === '') {
290
+ rl.close();
291
+ return;
292
+ }
293
+ if (line === '' && lines[lines.length - 1] === '') {
294
+ lines.pop(); // remove trailing empty line
295
+ rl.close();
296
+ return;
297
+ }
298
+ lines.push(line);
299
+ hintTimer = setTimeout(showHint, 50);
300
+ });
301
+ rl.on('close', () => {
302
+ resolve(lines.join('\n'));
303
+ });
304
+ });
305
+ }
268
306
  async function handleCreateNewTask(api, searchTerm) {
269
307
  const title = await input({
270
308
  message: 'Task title:',
271
309
  default: searchTerm || undefined,
272
310
  validate: (value) => value.trim().length > 0 || 'Title is required',
273
311
  });
274
- const description = await input({
275
- message: 'Description (optional, press Enter to skip):',
276
- });
312
+ const description = await multilineInput('Description (optional):');
277
313
  const type = await select({
278
314
  message: 'Task type:',
279
315
  choices: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damper/cli",
3
- "version": "0.9.18",
3
+ "version": "0.9.19",
4
4
  "description": "CLI tool for orchestrating Damper task workflows with Claude Code",
5
5
  "author": "Damper <hello@usedamper.com>",
6
6
  "repository": {