dikt 1.0.0 → 1.0.2

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 (3) hide show
  1. package/README.md +6 -0
  2. package/cli.mjs +42 -10
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -55,6 +55,12 @@ This opens an interactive TUI where you can record, transcribe, and copy text.
55
55
  | `?` | Show keybindings |
56
56
  | `q` | Quit |
57
57
 
58
+ ### Update
59
+
60
+ ```
61
+ dikt update
62
+ ```
63
+
58
64
  ### Single-shot mode
59
65
 
60
66
  ```bash
package/cli.mjs CHANGED
@@ -25,6 +25,8 @@ const SHOW_CURSOR = `${ESC}?25h`;
25
25
  const CLEAR_LINE = `${ESC}2K`;
26
26
  const CLEAR_DOWN = `${ESC}J`;
27
27
  const CLEAR_SCREEN = `${ESC}2J${ESC}H`;
28
+ const ALT_SCREEN_ON = `${ESC}?1049h`;
29
+ const ALT_SCREEN_OFF = `${ESC}?1049l`;
28
30
 
29
31
  if (process.env.NO_COLOR != null || process.env.TERM === 'dumb' || process.argv.includes('--no-color')) {
30
32
  RESET = BOLD = DIM = RED = GREEN = YELLOW = GREY = WHITE = RED_BG = '';
@@ -34,7 +36,7 @@ const moveTo = (row, col = 1) => `${ESC}${row};${col}H`;
34
36
 
35
37
  // ── Constants ─────────────────────────────────────────────────────────────────
36
38
 
37
- const VERSION = '1.0.0';
39
+ const VERSION = '1.0.2';
38
40
  const CONFIG_BASE = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
39
41
  const CONFIG_DIR = path.join(CONFIG_BASE, 'dikt');
40
42
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
@@ -128,7 +130,7 @@ function readSecret(prompt) {
128
130
  default:
129
131
  if (ch.charCodeAt(0) >= 32) {
130
132
  secret += ch;
131
- process.stderr.write('*');
133
+ process.stderr.write('*'.repeat(ch.length));
132
134
  }
133
135
  break;
134
136
  }
@@ -263,7 +265,13 @@ function render() {
263
265
  out += CLEAR_LINE + ` ${DIM}Press SPACE to start dictating.${RESET}` + '\n';
264
266
  out += CLEAR_LINE + ` ${DIM}Press ? for all keybindings.${RESET}` + '\n';
265
267
  } else {
266
- const lines = wrapTranscript(w);
268
+ let lines = wrapTranscript(w);
269
+ // Cap transcript to available terminal rows to prevent overflow
270
+ const rows = process.stdout.rows || 24;
271
+ const availableRows = rows - 9; // header(2) + blank + keybar + blank + status + blank + meta + cleardown
272
+ if (availableRows > 0 && lines.length > availableRows) {
273
+ lines = lines.slice(lines.length - availableRows);
274
+ }
267
275
  for (const line of lines) {
268
276
  out += CLEAR_LINE + line + '\n';
269
277
  }
@@ -449,6 +457,9 @@ function toggleAutoCopy() {
449
457
 
450
458
  function startRecording() {
451
459
  state.error = '';
460
+ state.transcript = '';
461
+ state.wordCount = 0;
462
+ state.latency = 0;
452
463
 
453
464
  // Clean up previous recording file
454
465
  if (state.recFile) {
@@ -723,7 +734,7 @@ async function runSetup() {
723
734
  // Temporarily exit raw mode and detach keypress handler for the setup wizard
724
735
  process.stdin.removeListener('keypress', handleKey);
725
736
  process.stdin.setRawMode(false);
726
- process.stdout.write(SHOW_CURSOR + CLEAR_SCREEN);
737
+ process.stdout.write(SHOW_CURSOR + ALT_SCREEN_OFF);
727
738
 
728
739
  config = await setupWizard();
729
740
  applyEnvOverrides(config);
@@ -731,7 +742,7 @@ async function runSetup() {
731
742
  process.stdin.resume();
732
743
  process.stdin.setRawMode(true);
733
744
  process.stdin.on('keypress', handleKey);
734
- process.stdout.write(HIDE_CURSOR + CLEAR_SCREEN);
745
+ process.stdout.write(ALT_SCREEN_ON + HIDE_CURSOR + CLEAR_SCREEN);
735
746
  renderAll();
736
747
  }
737
748
 
@@ -838,8 +849,7 @@ function quit() {
838
849
 
839
850
  cleanupTempFiles();
840
851
 
841
- const h = process.stdout.rows || 24;
842
- process.stdout.write(SHOW_CURSOR + moveTo(h) + '\n');
852
+ process.stdout.write(SHOW_CURSOR + ALT_SCREEN_OFF);
843
853
  process.stdin.setRawMode(false);
844
854
  process.exit(EXIT_OK);
845
855
  }
@@ -860,6 +870,25 @@ async function main() {
860
870
  process.exit(EXIT_OK);
861
871
  }
862
872
 
873
+ if (args.includes('--update') || args[0] === 'update') {
874
+ try {
875
+ const resp = await fetch('https://registry.npmjs.org/dikt/latest');
876
+ const data = await resp.json();
877
+ const latest = data.version;
878
+ if (latest === VERSION) {
879
+ console.log(`dikt v${VERSION} is already up to date.`);
880
+ process.exit(EXIT_OK);
881
+ }
882
+ console.log(`Updating dikt v${VERSION} → v${latest}...`);
883
+ execFileSync('npm', ['install', '-g', 'dikt@latest'], { stdio: 'inherit' });
884
+ console.log(`Updated to dikt v${latest}.`);
885
+ } catch (err) {
886
+ console.error(`Update failed: ${err.message}`);
887
+ process.exit(EXIT_DEPENDENCY);
888
+ }
889
+ process.exit(EXIT_OK);
890
+ }
891
+
863
892
  if (args.includes('--help') || args.includes('-h')) {
864
893
  console.log(`dikt v${VERSION} — voice dictation for the terminal
865
894
 
@@ -867,9 +896,11 @@ Usage: dikt [options] [command]
867
896
 
868
897
  Commands:
869
898
  setup Reconfigure API key and model
899
+ update Update dikt to the latest version
870
900
 
871
901
  Options:
872
902
  --setup Run setup wizard
903
+ --update Update to latest version
873
904
  --json Record once, output JSON to stdout
874
905
  -q, --quiet Record once, print transcript to stdout
875
906
  --no-input Fail if config is missing (no wizard)
@@ -890,6 +921,7 @@ Examples:
890
921
  dikt -q Record once, print transcript to stdout
891
922
  dikt --json Record once, output JSON to stdout
892
923
  dikt -q | claude Dictate a prompt to Claude Code
924
+ dikt update Update to the latest version
893
925
 
894
926
  Environment variables:
895
927
  DIKT_API_KEY Override API key from config
@@ -946,8 +978,8 @@ Requires: sox (brew install sox)`);
946
978
  // Interactive TUI mode
947
979
  checkTTY();
948
980
 
949
- // Enter raw TUI mode
950
- process.stdout.write(HIDE_CURSOR + CLEAR_SCREEN);
981
+ // Enter raw TUI mode (alternate screen buffer prevents scrollback corruption)
982
+ process.stdout.write(ALT_SCREEN_ON + HIDE_CURSOR + CLEAR_SCREEN);
951
983
 
952
984
  readline.emitKeypressEvents(process.stdin);
953
985
  process.stdin.setRawMode(true);
@@ -965,7 +997,7 @@ Requires: sox (brew install sox)`);
965
997
  }
966
998
 
967
999
  main().catch((err) => {
968
- process.stdout.write(SHOW_CURSOR);
1000
+ process.stdout.write(SHOW_CURSOR + ALT_SCREEN_OFF);
969
1001
  console.error(err);
970
1002
  process.exit(EXIT_DEPENDENCY);
971
1003
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dikt",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Voice dictation for the terminal.",
5
5
  "type": "module",
6
6
  "bin": {