roguelike-cli 1.3.2 → 1.3.3

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
@@ -24,11 +24,7 @@
24
24
  - **RPG Engine** — Tasks are quests. Completing them earns XP, unlocks achievements, and levels you up.
25
25
  - **AI Game Master** — Integrated AI helps decompose complex tasks and generates structured plans.
26
26
  - **Local-First** — Your data stays on your machine in simple folders and JSON files.
27
- - **Themeable** — Choose your adventure style: Fantasy, Space Opera, Star Wars, Cyberpunk, and more.
28
-
29
- ## Why Roguelike CLI?
30
-
31
- Most task managers are boring. We make deep work addictive by applying proven RPG mechanics to your daily workflow.
27
+ - **Customizable Rules** — Choose adventure style: Fantasy, Space Opera, Star Wars, Cyberpunk, and more.
32
28
 
33
29
  ## Install
34
30
 
@@ -37,27 +33,6 @@ npm i -g roguelike-cli
37
33
  rlc
38
34
  ```
39
35
 
40
- ## Folder Structure
41
-
42
- Every task is a folder. You can drop files directly into task folders — designs, docs, code, anything. Your file manager becomes your task manager.
43
-
44
- ```
45
- my-startup/
46
- ├── research/
47
- │ ├── market-analysis/
48
- │ │ └── competitors.xlsx <- attached file
49
- │ └── user-interviews/
50
- │ └── notes.md <- attached file
51
- ├── development/
52
- │ ├── backend-api/
53
- │ │ └── spec.yaml <- attached file
54
- │ └── frontend-ui/
55
- └── launch/
56
- └── marketing/
57
- ```
58
-
59
- Navigate with `cd`, view with `tree`, open in Finder with `open`. It's just folders.
60
-
61
36
  ## Quick Start
62
37
 
63
38
  ```
@@ -88,41 +63,33 @@ Created: launch-my-startup/
88
63
  [x] Boss Slayer: Defeat a boss
89
64
  ```
90
65
 
91
- ## Configuration
66
+ ## Folder Structure
92
67
 
93
- Run `init` to set up, or use `config` flags:
68
+ Every task is a folder. You can drop files directly into task folders — designs, docs, code, anything. Your file manager becomes your task manager.
94
69
 
95
70
  ```
96
- > config
97
-
98
- Provider: claude
99
- Model: claude-sonnet-4-20250514
100
- API Key: sk-ant-a...xxxx
101
- Storage: /Users/you/.rlc/workspace
102
- Theme: Fantasy RPG
103
- Rules: Use fantasy RPG language...
104
-
105
- Set with flags:
106
- config -k=<key> Set API key
107
- config -m=<model> Set model
108
- config -t=<theme> Set theme
109
- config -r="<rules>" Set custom rules
71
+ my-startup/
72
+ ├── research/
73
+ │ ├── market-analysis/
74
+ │ │ └── competitors.xlsx <- attached file
75
+ │ └── user-interviews/
76
+ │ └── notes.md <- attached file
77
+ ├── development/
78
+ │ ├── backend-api/
79
+ │ │ └── spec.yaml <- attached file
80
+ │ └── frontend-ui/
81
+ └── launch/
82
+ └── marketing/
110
83
  ```
111
84
 
112
- ### Default Settings
113
-
114
- | Setting | Default |
115
- |---------|---------|
116
- | Provider | Claude Sonnet 4.5 |
117
- | Storage | `~/.rlc/workspace` |
118
- | Theme | Default (no theme) |
85
+ Navigate with `cd`, view with `tree`, open in Finder with `open`. It's just folders.
119
86
 
120
- ## Themes (Rules)
87
+ ## Rules
121
88
 
122
- Themes change how the AI speaks. Set with `config -t=<theme>` or during `init`.
89
+ Rules change how the AI speaks. Set during `init` or with `config -R="<rules>"`.
123
90
 
124
- | Theme | Style |
125
- |-------|-------|
91
+ | Preset | Style |
92
+ |--------|-------|
126
93
  | `default` | Standard task manager language |
127
94
  | `fantasy` | Quests, dungeons, dragons, loot |
128
95
  | `space` | Missions, starships, commanders |
@@ -134,11 +101,38 @@ Themes change how the AI speaks. Set with `config -t=<theme>` or during `init`.
134
101
  ### Custom Rules
135
102
 
136
103
  ```
137
- > config -r="Speak like a medieval knight. Tasks are 'duties'. Use 'huzzah' for success."
104
+ > config -R="Speak like a medieval knight. Tasks are 'duties'. Use 'huzzah' for success."
138
105
  ```
139
106
 
140
107
  Or select "Custom" during `init` to enter your own rules.
141
108
 
109
+ ## Dungeon Map
110
+
111
+ ```
112
+ > map
113
+
114
+ #########################################
115
+ # # #
116
+ # [Research] # [Development] #
117
+ # x Analysis +---* Backend #
118
+ # x Interviews # * Frontend #
119
+ # # #
120
+ ##########+###########+#################
121
+ | |
122
+ ##########+###########+#################
123
+ # #
124
+ # [Launch] #
125
+ # * Marketing #
126
+ # @ SHIP IT! [BOSS] #
127
+ # #
128
+ #########################################
129
+
130
+ Legend: * Task x Done @ Boss + Door
131
+
132
+ > map --ai
133
+ (AI generates creative dungeon layout based on your tasks)
134
+ ```
135
+
142
136
  ## Commands
143
137
 
144
138
  ### Navigation
@@ -158,7 +152,7 @@ Or select "Custom" during `init` to enter your own rules.
158
152
  |---------|-------------|
159
153
  | `done` | Complete task (earns XP) |
160
154
  | `undo` | Undo last done |
161
- | `deadline <date>` | Set deadline |
155
+ | `dl <date>` | Set deadline (dl +3d, dl Jan 15) |
162
156
  | `boss` | Toggle boss (3x XP) |
163
157
  | `block [node]` | Block by task |
164
158
  | `unblock` | Remove block |
@@ -186,18 +180,24 @@ Or select "Custom" during `init` to enter your own rules.
186
180
  |---------|-------------|
187
181
  | `init` | Setup wizard |
188
182
  | `config` | View settings |
189
- | `config -k=<key>` | Set API key |
190
- | `config -m=<model>` | Set model |
191
- | `config -t=<theme>` | Set theme |
192
- | `config -r="<rules>"` | Custom rules |
183
+ | `config -K=<key>` | or `--key=<key>` |
184
+ | `config -M=<model>` | or `--model=<model>` |
185
+ | `config -R="<rules>"` | or `--rules="<rules>"` |
186
+
187
+ ### Clipboard
188
+
189
+ | Command | Description |
190
+ |---------|-------------|
191
+ | `<cmd> \| pbcopy` | Copy to clipboard (macOS) |
192
+ | `<cmd> \| clip` | Copy to clipboard (Windows) |
193
193
 
194
194
  ## Deadlines
195
195
 
196
196
  ```
197
- > deadline today # Due today
198
- > deadline tomorrow # Due tomorrow
199
- > deadline +3d # In 3 days
200
- > deadline Jan 15 # Specific date
197
+ > dl today # Due today
198
+ > dl tomorrow # Due tomorrow
199
+ > dl +3d # In 3 days
200
+ > deadline Jan 15 # Specific date
201
201
  ```
202
202
 
203
203
  Tree shows deadlines:
@@ -228,25 +228,16 @@ Tree shows deadlines:
228
228
  | Speedrunner | Same-day completion |
229
229
  | Streak Master | 7 day streak |
230
230
 
231
- ## Dungeon Map
232
-
233
- ```
234
- > map
235
-
236
- ###########################################
237
- # # #
238
- # [Research] # [Development] #
239
- # x Analysis +---* Backend #
240
- # x Interviews # @ Deploy BOSS #
241
- # # #
242
- ##########+###########+###################
243
- ```
244
-
245
- ## Clipboard
231
+ ## Supported Models
246
232
 
247
233
  ```
248
- > tree | pbcopy # macOS
249
- > tree | clip # Windows
234
+ claude-sonnet-4-20250514 (default)
235
+ claude-opus-4-20250514
236
+ gpt-4o
237
+ gpt-4-turbo
238
+ gemini-3-pro
239
+ gemini-2.0-flash
240
+ grok-beta
250
241
  ```
251
242
 
252
243
  ## Website
@@ -128,7 +128,7 @@ async function initCommand(existingRl) {
128
128
  const apiKeyInput = await question(rl, keyPrompt);
129
129
  const apiKey = apiKeyInput.trim() || existingApiKey;
130
130
  if (!apiKey) {
131
- console.log('Warning: API key not set. You can set it later with: config -k <key>');
131
+ console.log('Warning: API key not set. You can set it later with: config -K=<key>');
132
132
  }
133
133
  else if (apiKeyInput.trim()) {
134
134
  console.log('API key saved');
@@ -136,8 +136,8 @@ async function initCommand(existingRl) {
136
136
  else {
137
137
  console.log('Using existing API key');
138
138
  }
139
- // 4. Theme/Rules selection
140
- console.log('\nSelect AI Theme (affects language style):');
139
+ // 4. Rules preset selection
140
+ console.log('\nSelect AI Rules (affects language style):');
141
141
  const presetKeys = Object.keys(config_1.RULES_PRESETS);
142
142
  presetKeys.forEach((key, index) => {
143
143
  console.log(` ${index + 1}. ${config_1.RULES_PRESETS[key].name}`);
@@ -190,7 +190,7 @@ async function initCommand(existingRl) {
190
190
  console.log(`Root directory: ${rootDir}`);
191
191
  console.log(`AI Provider: ${selectedProvider.name}`);
192
192
  console.log(`Model: ${selectedProvider.model}`);
193
- console.log(`Theme: ${config_1.RULES_PRESETS[selectedPreset]?.name || 'Custom'}\n`);
193
+ console.log(`Rules: ${config_1.RULES_PRESETS[selectedPreset]?.name || 'Custom'}\n`);
194
194
  }
195
195
  finally {
196
196
  if (shouldCloseRl) {
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.RULES_PRESETS = void 0;
36
+ exports.RULES_PRESETS = exports.SUPPORTED_MODELS = void 0;
37
37
  exports.initConfig = initConfig;
38
38
  exports.saveConfig = saveConfig;
39
39
  exports.getConfig = getConfig;
@@ -41,7 +41,17 @@ exports.updateConfig = updateConfig;
41
41
  const fs = __importStar(require("fs"));
42
42
  const path = __importStar(require("path"));
43
43
  const os = __importStar(require("os"));
44
- // Preset rules for different themes
44
+ // Supported models for validation
45
+ exports.SUPPORTED_MODELS = [
46
+ 'claude-sonnet-4-20250514',
47
+ 'claude-opus-4-20250514',
48
+ 'gpt-4o',
49
+ 'gpt-4-turbo',
50
+ 'gemini-3-pro',
51
+ 'gemini-2.0-flash',
52
+ 'grok-beta',
53
+ ];
54
+ // Preset rules
45
55
  exports.RULES_PRESETS = {
46
56
  default: {
47
57
  name: 'Default (No theme)',
@@ -478,10 +478,10 @@ async function processCommand(input, currentPath, config, signal, rl) {
478
478
  output += '\n';
479
479
  return wrapResult({ output });
480
480
  }
481
- // Deadline command
482
- if (command === 'deadline') {
481
+ // Deadline command (dl as alias)
482
+ if (command === 'deadline' || command === 'dl') {
483
483
  if (parts.length < 2) {
484
- return wrapResult({ output: 'Usage: deadline <date>\nExamples: deadline today, deadline tomorrow, deadline +3d, deadline Jan 15' });
484
+ return wrapResult({ output: 'Usage: deadline <date> (or dl <date>)\nExamples: dl today, dl +3d, deadline Jan 15' });
485
485
  }
486
486
  const dateStr = parts.slice(1).join(' ');
487
487
  const deadline = parseDeadline(dateStr);
@@ -931,64 +931,52 @@ async function processCommand(input, currentPath, config, signal, rl) {
931
931
  return wrapResult({ output: currentPath });
932
932
  }
933
933
  if (command === 'config') {
934
- const { updateConfig, RULES_PRESETS } = await Promise.resolve().then(() => __importStar(require('../config/config')));
935
- // Check for flags
936
- const keyFlag = parts.find(p => p.startsWith('-k=') || p.startsWith('--key='));
937
- const modelFlag = parts.find(p => p.startsWith('-m=') || p.startsWith('--model='));
938
- const rulesFlag = parts.find(p => p.startsWith('-r=') || p.startsWith('--rules='));
939
- const themeFlag = parts.find(p => p.startsWith('-t=') || p.startsWith('--theme='));
934
+ const { updateConfig, SUPPORTED_MODELS } = await Promise.resolve().then(() => __importStar(require('../config/config')));
935
+ // Check for flags (uppercase short, lowercase long)
936
+ const keyFlag = parts.find(p => p.startsWith('-K=') || p.startsWith('--key='));
937
+ const modelFlag = parts.find(p => p.startsWith('-M=') || p.startsWith('--model='));
938
+ const rulesFlag = parts.find(p => p.startsWith('-R=') || p.startsWith('--rules='));
940
939
  if (keyFlag) {
941
940
  const value = keyFlag.split('=').slice(1).join('=');
941
+ if (!value) {
942
+ return wrapResult({ output: 'Error: API key cannot be empty' });
943
+ }
942
944
  updateConfig({ apiKey: value });
943
945
  return wrapResult({ output: 'API key updated.' });
944
946
  }
945
947
  if (modelFlag) {
946
948
  const value = modelFlag.split('=').slice(1).join('=');
949
+ if (!SUPPORTED_MODELS.includes(value)) {
950
+ return wrapResult({
951
+ output: `Error: Unknown model "${value}"\n\nSupported models:\n ${SUPPORTED_MODELS.join('\n ')}`
952
+ });
953
+ }
947
954
  updateConfig({ model: value });
948
955
  return wrapResult({ output: `Model updated: ${value}` });
949
956
  }
950
957
  if (rulesFlag) {
951
958
  const value = rulesFlag.split('=').slice(1).join('=');
952
959
  updateConfig({ rules: value, rulesPreset: 'custom' });
953
- return wrapResult({ output: 'Custom rules updated.' });
954
- }
955
- if (themeFlag) {
956
- const value = themeFlag.split('=').slice(1).join('=').toLowerCase();
957
- if (RULES_PRESETS[value]) {
958
- updateConfig({
959
- rules: RULES_PRESETS[value].rules,
960
- rulesPreset: value
961
- });
962
- return wrapResult({ output: `Theme updated: ${RULES_PRESETS[value].name}` });
963
- }
964
- else {
965
- const themes = Object.keys(RULES_PRESETS).join(', ');
966
- return wrapResult({ output: `Unknown theme. Available: ${themes}` });
967
- }
960
+ return wrapResult({ output: 'Rules updated.' });
968
961
  }
969
962
  // Show config
970
963
  const maskedKey = config.apiKey
971
964
  ? config.apiKey.slice(0, 8) + '...' + config.apiKey.slice(-4)
972
965
  : '(not set)';
973
- const themeName = config.rulesPreset
974
- ? (RULES_PRESETS[config.rulesPreset]?.name || 'Custom')
975
- : 'Default';
976
966
  const rulesPreview = config.rules
977
- ? (config.rules.length > 50 ? config.rules.substring(0, 50) + '...' : config.rules)
978
- : '(none)';
967
+ ? (config.rules.length > 60 ? config.rules.substring(0, 60) + '...' : config.rules)
968
+ : '(default)';
979
969
  const output = `
980
970
  Provider: ${config.aiProvider}
981
971
  Model: ${config.model || '(default)'}
982
972
  API Key: ${maskedKey}
983
973
  Storage: ${config.storagePath}
984
- Theme: ${themeName}
985
974
  Rules: ${rulesPreview}
986
975
 
987
976
  Set with flags:
988
- config -k=<key> Set API key
989
- config -m=<model> Set model
990
- config -t=<theme> Set theme (fantasy, space, starwars, western, cyberpunk, pirate)
991
- config -r="<rules>" Set custom rules
977
+ config -K=<key> or --key=<key>
978
+ config -M=<model> or --model=<model>
979
+ config -R="<rules>" or --rules="<rules>"
992
980
  `.trim();
993
981
  return wrapResult({ output });
994
982
  }
@@ -1001,49 +989,50 @@ Navigation:
1001
989
  ls List tasks and files
1002
990
  tree [-A] [--depth=N] Show task tree
1003
991
  cd <task> Navigate into task
1004
- cd .., ... Go back 1 or 2 levels
1005
- pwd Show current path
1006
- open Open folder in Finder
992
+ .., ... Go up 1 or 2 levels
993
+ pwd Current path
994
+ open Open in Finder
1007
995
 
1008
- Task Management:
1009
- mkdir <name> Create new task
1010
- done Complete task (earns XP)
996
+ Tasks:
997
+ mkdir <name> Create task
998
+ done Complete (earns XP)
1011
999
  undo Undo last done
1012
- deadline <date> Set deadline (today, +3d, Jan 15)
1013
- boss Toggle boss status (3x XP)
1014
- block [node] Block by task or text
1000
+ dl <date> Set deadline (dl +3d, dl Jan 15)
1001
+ boss Toggle boss (3x XP)
1002
+ block [node] Block by task
1015
1003
  unblock Remove block
1016
1004
  status Task details
1017
- check Upcoming deadlines
1005
+ check Deadline alerts
1018
1006
 
1019
1007
  Gamification:
1020
1008
  stats XP, level, streaks
1021
1009
  achievements Achievement list
1022
- map [--ai] Dungeon map view
1010
+ map Dungeon map
1011
+ map --ai AI-generated map
1023
1012
 
1024
- Configuration:
1013
+ Rules (AI style presets):
1014
+ Set via init or config -R="<rules>"
1015
+ Presets: fantasy, space, starwars, western, cyberpunk, pirate
1016
+
1017
+ Config:
1025
1018
  init Setup wizard
1026
1019
  config Show settings
1027
- config -k=<key> Set API key
1028
- config -m=<model> Set model
1029
- config -t=<theme> Set theme (fantasy, space, starwars, etc)
1030
- config -r="<rules>" Custom AI rules
1031
-
1032
- Themes:
1033
- default, fantasy, space, starwars, western, cyberpunk, pirate
1020
+ config -K=<key> or --key=<key>
1021
+ config -M=<model> or --model=<model>
1022
+ config -R="<rules>" or --rules="<rules>"
1034
1023
 
1035
- File Operations:
1036
- cp, mv, rm [-rf] Standard file operations
1037
- clean --yes Clear current folder
1024
+ Files:
1025
+ cp, mv, rm [-rf] Standard operations
1026
+ clean --yes Clear folder
1038
1027
 
1039
- AI Generation:
1040
- <description> AI generates preview
1041
- save Save to folders/file
1028
+ AI:
1029
+ <description> Generate preview
1030
+ save Save to folders
1042
1031
  cancel Discard
1043
1032
 
1044
1033
  Clipboard:
1045
- <cmd> | pbcopy Copy to clipboard (macOS)
1046
- <cmd> | clip Copy to clipboard (Windows)
1034
+ <cmd> | pbcopy macOS
1035
+ <cmd> | clip Windows
1047
1036
 
1048
1037
  www.rlc.rocks
1049
1038
  `.trim()
@@ -19,16 +19,17 @@ const ASCII_ART = [
19
19
  '║ Roguelike CLI ║',
20
20
  '╚═════════════════════════╝',
21
21
  '',
22
- ' Tasks: done, undo, deadline, boss, block',
23
- ' Stats: stats, achievements, map, check',
24
- ' Config: init, config -t=<theme>',
22
+ ' Tasks: done, undo, dl <date>, boss, block',
23
+ ' Stats: stats, achievements, map --ai',
25
24
  '',
26
- ' Themes: fantasy, space, starwars, cyberpunk',
25
+ ' Rules: fantasy, space, starwars, cyberpunk',
26
+ ' Config: init, config -R="<rules>"',
27
27
  '',
28
28
  ' TAB autocomplete, | pbcopy to copy',
29
29
  ' <description> -> refine -> save',
30
30
  '',
31
- ' help - commands, www.rlc.rocks',
31
+ ' help - commands',
32
+ ' www.rlc.rocks',
32
33
  '',
33
34
  ' Ready...',
34
35
  '',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roguelike-cli",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "AI-powered interactive terminal for creating schemas and todo lists",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -110,15 +110,15 @@ export async function initCommand(existingRl?: readline.Interface): Promise<void
110
110
  const apiKey = apiKeyInput.trim() || existingApiKey;
111
111
 
112
112
  if (!apiKey) {
113
- console.log('Warning: API key not set. You can set it later with: config -k <key>');
113
+ console.log('Warning: API key not set. You can set it later with: config -K=<key>');
114
114
  } else if (apiKeyInput.trim()) {
115
115
  console.log('API key saved');
116
116
  } else {
117
117
  console.log('Using existing API key');
118
118
  }
119
119
 
120
- // 4. Theme/Rules selection
121
- console.log('\nSelect AI Theme (affects language style):');
120
+ // 4. Rules preset selection
121
+ console.log('\nSelect AI Rules (affects language style):');
122
122
  const presetKeys = Object.keys(RULES_PRESETS);
123
123
  presetKeys.forEach((key, index) => {
124
124
  console.log(` ${index + 1}. ${RULES_PRESETS[key].name}`);
@@ -177,7 +177,7 @@ export async function initCommand(existingRl?: readline.Interface): Promise<void
177
177
  console.log(`Root directory: ${rootDir}`);
178
178
  console.log(`AI Provider: ${selectedProvider.name}`);
179
179
  console.log(`Model: ${selectedProvider.model}`);
180
- console.log(`Theme: ${RULES_PRESETS[selectedPreset]?.name || 'Custom'}\n`);
180
+ console.log(`Rules: ${RULES_PRESETS[selectedPreset]?.name || 'Custom'}\n`);
181
181
  } finally {
182
182
  if (shouldCloseRl) {
183
183
  rl.close();
@@ -13,7 +13,18 @@ export interface Config {
13
13
  rulesPreset?: string;
14
14
  }
15
15
 
16
- // Preset rules for different themes
16
+ // Supported models for validation
17
+ export const SUPPORTED_MODELS = [
18
+ 'claude-sonnet-4-20250514',
19
+ 'claude-opus-4-20250514',
20
+ 'gpt-4o',
21
+ 'gpt-4-turbo',
22
+ 'gemini-3-pro',
23
+ 'gemini-2.0-flash',
24
+ 'grok-beta',
25
+ ];
26
+
27
+ // Preset rules
17
28
  export const RULES_PRESETS: Record<string, { name: string; rules: string }> = {
18
29
  default: {
19
30
  name: 'Default (No theme)',
@@ -566,10 +566,10 @@ export async function processCommand(
566
566
  return wrapResult({ output });
567
567
  }
568
568
 
569
- // Deadline command
570
- if (command === 'deadline') {
569
+ // Deadline command (dl as alias)
570
+ if (command === 'deadline' || command === 'dl') {
571
571
  if (parts.length < 2) {
572
- return wrapResult({ output: 'Usage: deadline <date>\nExamples: deadline today, deadline tomorrow, deadline +3d, deadline Jan 15' });
572
+ return wrapResult({ output: 'Usage: deadline <date> (or dl <date>)\nExamples: dl today, dl +3d, deadline Jan 15' });
573
573
  }
574
574
 
575
575
  const dateStr = parts.slice(1).join(' ');
@@ -1107,22 +1107,29 @@ export async function processCommand(
1107
1107
  }
1108
1108
 
1109
1109
  if (command === 'config') {
1110
- const { updateConfig, RULES_PRESETS } = await import('../config/config');
1110
+ const { updateConfig, SUPPORTED_MODELS } = await import('../config/config');
1111
1111
 
1112
- // Check for flags
1113
- const keyFlag = parts.find(p => p.startsWith('-k=') || p.startsWith('--key='));
1114
- const modelFlag = parts.find(p => p.startsWith('-m=') || p.startsWith('--model='));
1115
- const rulesFlag = parts.find(p => p.startsWith('-r=') || p.startsWith('--rules='));
1116
- const themeFlag = parts.find(p => p.startsWith('-t=') || p.startsWith('--theme='));
1112
+ // Check for flags (uppercase short, lowercase long)
1113
+ const keyFlag = parts.find(p => p.startsWith('-K=') || p.startsWith('--key='));
1114
+ const modelFlag = parts.find(p => p.startsWith('-M=') || p.startsWith('--model='));
1115
+ const rulesFlag = parts.find(p => p.startsWith('-R=') || p.startsWith('--rules='));
1117
1116
 
1118
1117
  if (keyFlag) {
1119
1118
  const value = keyFlag.split('=').slice(1).join('=');
1119
+ if (!value) {
1120
+ return wrapResult({ output: 'Error: API key cannot be empty' });
1121
+ }
1120
1122
  updateConfig({ apiKey: value });
1121
1123
  return wrapResult({ output: 'API key updated.' });
1122
1124
  }
1123
1125
 
1124
1126
  if (modelFlag) {
1125
1127
  const value = modelFlag.split('=').slice(1).join('=');
1128
+ if (!SUPPORTED_MODELS.includes(value)) {
1129
+ return wrapResult({
1130
+ output: `Error: Unknown model "${value}"\n\nSupported models:\n ${SUPPORTED_MODELS.join('\n ')}`
1131
+ });
1132
+ }
1126
1133
  updateConfig({ model: value });
1127
1134
  return wrapResult({ output: `Model updated: ${value}` });
1128
1135
  }
@@ -1130,21 +1137,7 @@ export async function processCommand(
1130
1137
  if (rulesFlag) {
1131
1138
  const value = rulesFlag.split('=').slice(1).join('=');
1132
1139
  updateConfig({ rules: value, rulesPreset: 'custom' });
1133
- return wrapResult({ output: 'Custom rules updated.' });
1134
- }
1135
-
1136
- if (themeFlag) {
1137
- const value = themeFlag.split('=').slice(1).join('=').toLowerCase();
1138
- if (RULES_PRESETS[value]) {
1139
- updateConfig({
1140
- rules: RULES_PRESETS[value].rules,
1141
- rulesPreset: value
1142
- });
1143
- return wrapResult({ output: `Theme updated: ${RULES_PRESETS[value].name}` });
1144
- } else {
1145
- const themes = Object.keys(RULES_PRESETS).join(', ');
1146
- return wrapResult({ output: `Unknown theme. Available: ${themes}` });
1147
- }
1140
+ return wrapResult({ output: 'Rules updated.' });
1148
1141
  }
1149
1142
 
1150
1143
  // Show config
@@ -1152,27 +1145,21 @@ export async function processCommand(
1152
1145
  ? config.apiKey.slice(0, 8) + '...' + config.apiKey.slice(-4)
1153
1146
  : '(not set)';
1154
1147
 
1155
- const themeName = config.rulesPreset
1156
- ? (RULES_PRESETS[config.rulesPreset]?.name || 'Custom')
1157
- : 'Default';
1158
-
1159
1148
  const rulesPreview = config.rules
1160
- ? (config.rules.length > 50 ? config.rules.substring(0, 50) + '...' : config.rules)
1161
- : '(none)';
1149
+ ? (config.rules.length > 60 ? config.rules.substring(0, 60) + '...' : config.rules)
1150
+ : '(default)';
1162
1151
 
1163
1152
  const output = `
1164
1153
  Provider: ${config.aiProvider}
1165
1154
  Model: ${config.model || '(default)'}
1166
1155
  API Key: ${maskedKey}
1167
1156
  Storage: ${config.storagePath}
1168
- Theme: ${themeName}
1169
1157
  Rules: ${rulesPreview}
1170
1158
 
1171
1159
  Set with flags:
1172
- config -k=<key> Set API key
1173
- config -m=<model> Set model
1174
- config -t=<theme> Set theme (fantasy, space, starwars, western, cyberpunk, pirate)
1175
- config -r="<rules>" Set custom rules
1160
+ config -K=<key> or --key=<key>
1161
+ config -M=<model> or --model=<model>
1162
+ config -R="<rules>" or --rules="<rules>"
1176
1163
  `.trim();
1177
1164
 
1178
1165
  return wrapResult({ output });
@@ -1187,49 +1174,50 @@ Navigation:
1187
1174
  ls List tasks and files
1188
1175
  tree [-A] [--depth=N] Show task tree
1189
1176
  cd <task> Navigate into task
1190
- cd .., ... Go back 1 or 2 levels
1191
- pwd Show current path
1192
- open Open folder in Finder
1177
+ .., ... Go up 1 or 2 levels
1178
+ pwd Current path
1179
+ open Open in Finder
1193
1180
 
1194
- Task Management:
1195
- mkdir <name> Create new task
1196
- done Complete task (earns XP)
1181
+ Tasks:
1182
+ mkdir <name> Create task
1183
+ done Complete (earns XP)
1197
1184
  undo Undo last done
1198
- deadline <date> Set deadline (today, +3d, Jan 15)
1199
- boss Toggle boss status (3x XP)
1200
- block [node] Block by task or text
1185
+ dl <date> Set deadline (dl +3d, dl Jan 15)
1186
+ boss Toggle boss (3x XP)
1187
+ block [node] Block by task
1201
1188
  unblock Remove block
1202
1189
  status Task details
1203
- check Upcoming deadlines
1190
+ check Deadline alerts
1204
1191
 
1205
1192
  Gamification:
1206
1193
  stats XP, level, streaks
1207
1194
  achievements Achievement list
1208
- map [--ai] Dungeon map view
1195
+ map Dungeon map
1196
+ map --ai AI-generated map
1209
1197
 
1210
- Configuration:
1198
+ Rules (AI style presets):
1199
+ Set via init or config -R="<rules>"
1200
+ Presets: fantasy, space, starwars, western, cyberpunk, pirate
1201
+
1202
+ Config:
1211
1203
  init Setup wizard
1212
1204
  config Show settings
1213
- config -k=<key> Set API key
1214
- config -m=<model> Set model
1215
- config -t=<theme> Set theme (fantasy, space, starwars, etc)
1216
- config -r="<rules>" Custom AI rules
1217
-
1218
- Themes:
1219
- default, fantasy, space, starwars, western, cyberpunk, pirate
1205
+ config -K=<key> or --key=<key>
1206
+ config -M=<model> or --model=<model>
1207
+ config -R="<rules>" or --rules="<rules>"
1220
1208
 
1221
- File Operations:
1222
- cp, mv, rm [-rf] Standard file operations
1223
- clean --yes Clear current folder
1209
+ Files:
1210
+ cp, mv, rm [-rf] Standard operations
1211
+ clean --yes Clear folder
1224
1212
 
1225
- AI Generation:
1226
- <description> AI generates preview
1227
- save Save to folders/file
1213
+ AI:
1214
+ <description> Generate preview
1215
+ save Save to folders
1228
1216
  cancel Discard
1229
1217
 
1230
1218
  Clipboard:
1231
- <cmd> | pbcopy Copy to clipboard (macOS)
1232
- <cmd> | clip Copy to clipboard (Windows)
1219
+ <cmd> | pbcopy macOS
1220
+ <cmd> | clip Windows
1233
1221
 
1234
1222
  www.rlc.rocks
1235
1223
  `.trim()
@@ -17,16 +17,17 @@ const ASCII_ART = [
17
17
  '║ Roguelike CLI ║',
18
18
  '╚═════════════════════════╝',
19
19
  '',
20
- ' Tasks: done, undo, deadline, boss, block',
21
- ' Stats: stats, achievements, map, check',
22
- ' Config: init, config -t=<theme>',
20
+ ' Tasks: done, undo, dl <date>, boss, block',
21
+ ' Stats: stats, achievements, map --ai',
23
22
  '',
24
- ' Themes: fantasy, space, starwars, cyberpunk',
23
+ ' Rules: fantasy, space, starwars, cyberpunk',
24
+ ' Config: init, config -R="<rules>"',
25
25
  '',
26
26
  ' TAB autocomplete, | pbcopy to copy',
27
27
  ' <description> -> refine -> save',
28
28
  '',
29
- ' help - commands, www.rlc.rocks',
29
+ ' help - commands',
30
+ ' www.rlc.rocks',
30
31
  '',
31
32
  ' Ready...',
32
33
  '',