@aladac/hu 0.1.0-a1

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 (70) hide show
  1. package/.tool-versions +1 -0
  2. package/CLAUDE.md +122 -0
  3. package/HOOKS-DATA-INTEGRATION.md +457 -0
  4. package/SAMPLE.md +378 -0
  5. package/TODO.md +25 -0
  6. package/biome.json +51 -0
  7. package/commands/bootstrap.md +13 -0
  8. package/commands/c.md +1 -0
  9. package/commands/check-name.md +62 -0
  10. package/commands/disk.md +141 -0
  11. package/commands/docs/archive.md +27 -0
  12. package/commands/docs/check-internal.md +53 -0
  13. package/commands/docs/cleanup.md +65 -0
  14. package/commands/docs/consolidate.md +72 -0
  15. package/commands/docs/get.md +101 -0
  16. package/commands/docs/list.md +61 -0
  17. package/commands/docs/sync.md +64 -0
  18. package/commands/docs/update.md +49 -0
  19. package/commands/plans/clear.md +23 -0
  20. package/commands/plans/create.md +71 -0
  21. package/commands/plans/list.md +21 -0
  22. package/commands/plans/sync.md +38 -0
  23. package/commands/reinstall.md +20 -0
  24. package/commands/replicate.md +303 -0
  25. package/commands/warp.md +0 -0
  26. package/doc/README.md +35 -0
  27. package/doc/claude-code/capabilities.md +202 -0
  28. package/doc/claude-code/directory-structure.md +246 -0
  29. package/doc/claude-code/hooks.md +348 -0
  30. package/doc/claude-code/overview.md +109 -0
  31. package/doc/claude-code/plugins.md +273 -0
  32. package/doc/claude-code/sdk-protocols.md +202 -0
  33. package/document-manifest.toml +29 -0
  34. package/justfile +39 -0
  35. package/package.json +33 -0
  36. package/plans/compiled-watching-feather.md +217 -0
  37. package/plans/crispy-crafting-pnueli.md +103 -0
  38. package/plans/greedy-booping-coral.md +146 -0
  39. package/plans/imperative-sleeping-flamingo.md +192 -0
  40. package/plans/jaunty-sprouting-marble.md +171 -0
  41. package/plans/jiggly-discovering-lake.md +68 -0
  42. package/plans/magical-nibbling-spark.md +144 -0
  43. package/plans/mellow-kindling-acorn.md +110 -0
  44. package/plans/recursive-questing-engelbart.md +65 -0
  45. package/plans/serialized-roaming-kernighan.md +227 -0
  46. package/plans/structured-wondering-wirth.md +230 -0
  47. package/plans/vectorized-dreaming-iverson.md +191 -0
  48. package/plans/velvety-enchanting-ocean.md +92 -0
  49. package/plans/wiggly-sparking-pixel.md +48 -0
  50. package/plans/zippy-shimmying-fox.md +188 -0
  51. package/plugins/installed_plugins.json +4 -0
  52. package/sample-hooks.json +298 -0
  53. package/settings.json +24 -0
  54. package/settings.local.json +7 -0
  55. package/src/commands/bump.ts +130 -0
  56. package/src/commands/disk.ts +419 -0
  57. package/src/commands/docs.ts +729 -0
  58. package/src/commands/plans.ts +259 -0
  59. package/src/commands/utils.ts +299 -0
  60. package/src/index.ts +26 -0
  61. package/src/lib/colors.ts +87 -0
  62. package/src/lib/exec.ts +25 -0
  63. package/src/lib/fs.ts +119 -0
  64. package/src/lib/html.ts +205 -0
  65. package/src/lib/spinner.ts +42 -0
  66. package/src/types/index.ts +61 -0
  67. package/tests/lib/colors.test.ts +69 -0
  68. package/tests/lib/fs.test.ts +65 -0
  69. package/tsconfig.json +20 -0
  70. package/vitest.config.ts +15 -0
@@ -0,0 +1,227 @@
1
+ # Plan: honbu data Subcommand for Claude Code Data Integration
2
+
3
+ Implements the `honbu data` command hierarchy to access Claude Code's local data stores, enabling hooks to query session transcripts, history, stats, todos, and file history.
4
+
5
+ ## Phase 1: Core Data Access Commands
6
+
7
+ ### Description
8
+ Implement read-only access to the primary data stores: sessions, history, and stats. These form the foundation for all subsequent queries.
9
+
10
+ ### Steps
11
+
12
+ #### Step 1.1: Create data command module structure
13
+ - **Objective**: Set up the data subcommand with initial scaffolding
14
+ - **Files**: `src/commands/data.ts`
15
+ - **Dependencies**: None
16
+ - **Implementation**:
17
+ - Create `dataCommand` with subCommands structure
18
+ - Add placeholder subcommands: session, stats, history
19
+ - Register in `src/index.ts`
20
+
21
+ #### Step 1.2: Add data store path utilities
22
+ - **Objective**: Centralize paths to Claude Code data stores
23
+ - **Files**: `src/lib/fs.ts`
24
+ - **Dependencies**: Step 1.1
25
+ - **Implementation**:
26
+ - Add constants: `PROJECTS_DIR`, `HISTORY_FILE`, `STATS_FILE`, `TODOS_DIR`, `FILE_HISTORY_DIR`, `DEBUG_DIR`
27
+ - Add `encodeProjectPath(path)` function (mirrors Claude's encoding)
28
+ - Add `decodeProjectPath(encoded)` function
29
+
30
+ #### Step 1.3: Implement session list command
31
+ - **Objective**: List sessions with optional project filter
32
+ - **Files**: `src/commands/data.ts`
33
+ - **Dependencies**: Step 1.2
34
+ - **Implementation**:
35
+ - `honbu data session list [--project <path>] [--limit n] [--json]`
36
+ - Read projects/ directory structure
37
+ - Parse JSONL files to extract session metadata
38
+ - Display: sessionId, timestamp, messageCount, project
39
+
40
+ #### Step 1.4: Implement session read command
41
+ - **Objective**: Read and format a session transcript
42
+ - **Files**: `src/commands/data.ts`
43
+ - **Dependencies**: Step 1.3
44
+ - **Implementation**:
45
+ - `honbu data session read <id> [--format json|md]`
46
+ - Parse JSONL file, reconstruct message thread via parentUuid
47
+ - JSON: output raw messages
48
+ - Markdown: format as conversation with tool calls summarized
49
+
50
+ #### Step 1.5: Implement stats command
51
+ - **Objective**: Display usage statistics
52
+ - **Files**: `src/commands/data.ts`
53
+ - **Dependencies**: Step 1.2
54
+ - **Implementation**:
55
+ - `honbu data stats [--period <days>] [--json]`
56
+ - Read and parse stats-cache.json
57
+ - Display: totalSessions, totalMessages, modelUsage, dailyActivity
58
+ - Filter by period if specified
59
+
60
+ #### Step 1.6: Implement history command
61
+ - **Objective**: List and search session history
62
+ - **Files**: `src/commands/data.ts`
63
+ - **Dependencies**: Step 1.2
64
+ - **Implementation**:
65
+ - `honbu data history [--project <path>] [--limit n] [--json]`
66
+ - Read history.jsonl
67
+ - Filter by project if specified
68
+ - Display: timestamp, display (prompt preview), project
69
+
70
+ ## Phase 2: Extended Data Access
71
+
72
+ ### Description
73
+ Add commands for todos, file history, and the current session context.
74
+
75
+ ### Steps
76
+
77
+ #### Step 2.1: Implement todos list command
78
+ - **Objective**: List todos across sessions
79
+ - **Files**: `src/commands/data.ts`
80
+ - **Dependencies**: Phase 1
81
+ - **Implementation**:
82
+ - `honbu data todos [--status <status>] [--session <id>] [--json]`
83
+ - Read todos/*.json files
84
+ - Filter by status (pending/in_progress/completed)
85
+ - Display: content, status, session association
86
+
87
+ #### Step 2.2: Implement todos pending command
88
+ - **Objective**: Show incomplete todos across all sessions
89
+ - **Files**: `src/commands/data.ts`
90
+ - **Dependencies**: Step 2.1
91
+ - **Implementation**:
92
+ - `honbu data todos pending [--project <path>] [--json]`
93
+ - Filter for status != "completed"
94
+ - Group by session or project
95
+
96
+ #### Step 2.3: Implement file-history list command
97
+ - **Objective**: List files modified in sessions
98
+ - **Files**: `src/commands/data.ts`
99
+ - **Dependencies**: Phase 1
100
+ - **Implementation**:
101
+ - `honbu data files [--session <id>] [--recent <days>] [--json]`
102
+ - Read file-history/{session}/ directories
103
+ - Extract file paths from hash-based names (requires reverse lookup)
104
+ - Display: file path, version count, last modified
105
+
106
+ #### Step 2.4: Implement session current command
107
+ - **Objective**: Get current session from environment
108
+ - **Files**: `src/commands/data.ts`
109
+ - **Dependencies**: Step 1.4
110
+ - **Implementation**:
111
+ - `honbu data session current`
112
+ - Read $SESSION_ID environment variable
113
+ - Output session info or error if not in session context
114
+
115
+ ## Phase 3: Search and Query
116
+
117
+ ### Description
118
+ Add full-text search across sessions and pattern analysis.
119
+
120
+ ### Steps
121
+
122
+ #### Step 3.1: Implement session search command
123
+ - **Objective**: Search message content across sessions
124
+ - **Files**: `src/commands/data.ts`
125
+ - **Dependencies**: Phase 1
126
+ - **Implementation**:
127
+ - `honbu data search <query> [--limit n] [--json]`
128
+ - Scan JSONL files for matching content
129
+ - Return: sessionId, messageId, matched text snippet, timestamp
130
+
131
+ #### Step 3.2: Implement tools usage command
132
+ - **Objective**: Analyze tool usage patterns
133
+ - **Files**: `src/commands/data.ts`
134
+ - **Dependencies**: Phase 1
135
+ - **Implementation**:
136
+ - `honbu data tools [--tool <name>] [--session <id>] [--json]`
137
+ - Parse assistant messages for tool_use content blocks
138
+ - Aggregate: tool name, call count, common inputs
139
+
140
+ #### Step 3.3: Implement errors command
141
+ - **Objective**: Extract errors from debug logs
142
+ - **Files**: `src/commands/data.ts`
143
+ - **Dependencies**: Phase 1
144
+ - **Implementation**:
145
+ - `honbu data errors [--session <id>] [--recent <days>] [--json]`
146
+ - Parse debug/*.txt files for error patterns
147
+ - Display: timestamp, error message, session context
148
+
149
+ ## Phase 4: JSONL Parsing Library
150
+
151
+ ### Description
152
+ Create reusable parsing utilities for JSONL data stores.
153
+
154
+ ### Steps
155
+
156
+ #### Step 4.1: Create JSONL parser module
157
+ - **Objective**: Efficient JSONL reading with streaming support
158
+ - **Files**: `src/lib/jsonl.ts`
159
+ - **Dependencies**: None
160
+ - **Implementation**:
161
+ - `parseJsonlFile(path)` - returns array of parsed objects
162
+ - `streamJsonlFile(path, callback)` - streaming parser for large files
163
+ - `appendJsonl(path, object)` - append single record
164
+
165
+ #### Step 4.2: Create session transcript parser
166
+ - **Objective**: Parse and thread session messages
167
+ - **Files**: `src/lib/transcript.ts`
168
+ - **Dependencies**: Step 4.1
169
+ - **Implementation**:
170
+ - `parseTranscript(path)` - parse JSONL to message array
171
+ - `threadMessages(messages)` - reconstruct conversation tree
172
+ - `extractToolCalls(message)` - extract tool usage from content
173
+ - `summarizeSession(messages)` - generate session summary
174
+
175
+ #### Step 4.3: Refactor data commands to use parsers
176
+ - **Objective**: Use new parsing utilities in data commands
177
+ - **Files**: `src/commands/data.ts`
178
+ - **Dependencies**: Steps 4.1, 4.2
179
+ - **Implementation**:
180
+ - Replace inline parsing with library calls
181
+ - Add error handling for malformed JSONL
182
+ - Optimize for large session files
183
+
184
+ ## Verification
185
+
186
+ ### Unit Tests
187
+ - Test JSONL parsing with sample data
188
+ - Test project path encoding/decoding
189
+ - Test message threading logic
190
+
191
+ ### Integration Tests
192
+ ```bash
193
+ # Phase 1 verification
194
+ honbu data session list
195
+ honbu data session list --project ~/.claude --json
196
+ honbu data session read <session-id>
197
+ honbu data stats
198
+ honbu data stats --period 7
199
+ honbu data history --limit 10
200
+
201
+ # Phase 2 verification
202
+ honbu data todos
203
+ honbu data todos pending
204
+ honbu data files --recent 1
205
+
206
+ # Phase 3 verification
207
+ honbu data search "error"
208
+ honbu data tools --tool Bash
209
+ honbu data errors --recent 7
210
+ ```
211
+
212
+ ### Hook Integration Test
213
+ ```bash
214
+ # Test from a hook context
215
+ export SESSION_ID="test-session-id"
216
+ honbu data session current
217
+ ```
218
+
219
+ ## Files Summary
220
+
221
+ | File | Action |
222
+ |------|--------|
223
+ | `src/commands/data.ts` | Create |
224
+ | `src/lib/fs.ts` | Modify (add paths) |
225
+ | `src/lib/jsonl.ts` | Create |
226
+ | `src/lib/transcript.ts` | Create |
227
+ | `src/index.ts` | Modify (register command) |
@@ -0,0 +1,230 @@
1
+ # Internal AI Utility Interface Design
2
+
3
+ ## Goal
4
+ Design an internal AI utility system leveraging existing Ollama/LM Studio connections for text processing tasks like:
5
+ - Extracting model settings from CivitAI HTML descriptions
6
+ - JSON correction/formatting
7
+ - Text organization utilities
8
+
9
+ ## Current Infrastructure
10
+
11
+ ### Existing Connections (from `src/prompts/extract/client.py`)
12
+ | Host | Backend | Endpoint | Purpose |
13
+ |------|---------|----------|---------|
14
+ | junkpile | Ollama | `192.168.0.26:11434` | Vision models (GGUF) |
15
+ | fuji | LM Studio | `localhost:1234` | Local dev (MLX) |
16
+
17
+ ### Available Text Models
18
+ - `hermes3` - Structured output (Ollama)
19
+ - `huihui_ai/dolphin3-abliterated` - Text synthesis (Ollama)
20
+ - `dolphin-2.9-llama3-8b-mlx` - Text (LM Studio)
21
+
22
+ ### Existing Pattern
23
+ - `VisionClient` class wraps OpenAI SDK
24
+ - Auto-detects backend from port
25
+ - Environment variables: `OPENAPI_HOST`, `OPENAPI_BACKEND`
26
+
27
+ ## Design
28
+
29
+ ### Architecture Overview
30
+
31
+ Reuse `VisionClient` from `src/prompts/extract/client.py` since it already supports text-only generation via `_generate_text()`. Create a thin wrapper with task-specific processors.
32
+
33
+ ```
34
+ src/prompts/ai/
35
+ ├── __init__.py # Exports AIClient, processors
36
+ ├── client.py # AIClient wrapping VisionClient for text tasks
37
+ ├── processors.py # SettingsExtractor, JSONFixer, TextTransformer
38
+ └── cli.py # CLI commands: prompts ai extract-settings, fix-json
39
+ ```
40
+
41
+ ### Default Model Selection
42
+
43
+ | Host | Default Model | Reason |
44
+ |------|---------------|--------|
45
+ | junkpile (Ollama) | `hermes3` | Structured output, good at extraction |
46
+ | fuji (LM Studio) | `dolphin-2.9-llama3-8b-mlx` | MLX optimized |
47
+
48
+ ### AIClient Class
49
+
50
+ ```python
51
+ # src/prompts/ai/client.py
52
+ from prompts.extract.client import VisionClient
53
+
54
+ DEFAULT_MODEL = "hermes3" # Best for structured extraction
55
+
56
+ class AIClient:
57
+ """AI utility client for text processing tasks."""
58
+
59
+ def __init__(self, host=None, model=None):
60
+ self._vision = VisionClient(host=host)
61
+ self.model = model or DEFAULT_MODEL
62
+
63
+ def generate(self, prompt: str, system: str = None) -> str:
64
+ """Generate text response."""
65
+ full_prompt = f"{system}\n\n{prompt}" if system else prompt
66
+ return self._vision._generate_text(self.model, full_prompt)
67
+
68
+ def extract_settings(self, html: str) -> ModelSettings:
69
+ """Extract SD settings from HTML description."""
70
+ return SettingsExtractor(self).extract(html)
71
+
72
+ def fix_json(self, broken_json: str) -> str:
73
+ """Fix malformed JSON."""
74
+ return JSONFixer(self).fix(broken_json)
75
+ ```
76
+
77
+ ### Processors
78
+
79
+ ```python
80
+ # src/prompts/ai/processors.py
81
+ from pydantic import BaseModel
82
+ from typing import Optional
83
+
84
+ class ModelSettings(BaseModel):
85
+ """Extracted SD model settings."""
86
+ sampler: Optional[str] = None
87
+ scheduler: Optional[str] = None
88
+ steps: Optional[str] = None # Can be range like "20-35"
89
+ cfg_scale: Optional[str] = None # Can be range like "1-2"
90
+ clip_skip: Optional[int] = None
91
+ vae: Optional[str] = None
92
+ notes: Optional[str] = None
93
+
94
+ SETTINGS_SYSTEM_PROMPT = """Extract Stable Diffusion generation settings from the HTML description.
95
+ Return ONLY valid JSON matching this schema:
96
+ {
97
+ "sampler": "sampler name or null",
98
+ "scheduler": "scheduler name or null",
99
+ "steps": "step count or range like '20-35' or null",
100
+ "cfg_scale": "CFG value or range like '1-2' or null",
101
+ "clip_skip": clip skip number or null,
102
+ "vae": "VAE name or null",
103
+ "notes": "any other relevant settings notes or null"
104
+ }
105
+ Do not include any other text, only the JSON object."""
106
+
107
+ class SettingsExtractor:
108
+ def __init__(self, client):
109
+ self.client = client
110
+
111
+ def extract(self, html: str) -> ModelSettings:
112
+ response = self.client.generate(
113
+ prompt=f"Extract settings from:\n\n{html}",
114
+ system=SETTINGS_SYSTEM_PROMPT
115
+ )
116
+ # Parse JSON response into ModelSettings
117
+ import json
118
+ data = json.loads(response)
119
+ return ModelSettings(**data)
120
+
121
+ JSON_FIX_PROMPT = """Fix the following malformed JSON and return ONLY the corrected JSON.
122
+ Do not explain, just output valid JSON."""
123
+
124
+ class JSONFixer:
125
+ def __init__(self, client):
126
+ self.client = client
127
+
128
+ def fix(self, broken: str) -> str:
129
+ return self.client.generate(
130
+ prompt=f"Fix this JSON:\n\n{broken}",
131
+ system=JSON_FIX_PROMPT
132
+ )
133
+ ```
134
+
135
+ ### CLI Commands
136
+
137
+ ```python
138
+ # src/prompts/ai/cli.py
139
+ import click
140
+ from .client import AIClient
141
+
142
+ @click.group()
143
+ def ai():
144
+ """AI-powered text utilities."""
145
+ pass
146
+
147
+ @ai.command("extract-settings")
148
+ @click.argument("model_id", type=int)
149
+ @click.option("--host", help="AI backend host")
150
+ def extract_settings(model_id: int, host: str):
151
+ """Extract SD settings from CivitAI model description."""
152
+ from prompts.civitai.cache import get_cached_model
153
+
154
+ cached = get_cached_model(model_id)
155
+ if not cached:
156
+ click.echo(f"Model {model_id} not in cache. Run: prompts models info {model_id}")
157
+ return
158
+
159
+ html = cached.get("description", "")
160
+ client = AIClient(host=host)
161
+ settings = client.extract_settings(html)
162
+
163
+ click.echo(settings.model_dump_json(indent=2))
164
+
165
+ @ai.command("fix-json")
166
+ @click.argument("file", type=click.Path(exists=True))
167
+ @click.option("--output", "-o", help="Output file (default: stdout)")
168
+ def fix_json(file: str, output: str):
169
+ """Fix malformed JSON file."""
170
+ from pathlib import Path
171
+
172
+ broken = Path(file).read_text()
173
+ client = AIClient()
174
+ fixed = client.fix_json(broken)
175
+
176
+ if output:
177
+ Path(output).write_text(fixed)
178
+ click.echo(f"Fixed JSON written to {output}")
179
+ else:
180
+ click.echo(fixed)
181
+ ```
182
+
183
+ ### Integration with Scene Generation
184
+
185
+ Update `prompts scenes json` to auto-extract settings:
186
+
187
+ ```python
188
+ # In scenes/cli.py
189
+ @scenes.command("json")
190
+ @click.option("--auto-settings", is_flag=True, help="Extract settings from CivitAI")
191
+ def generate_json(..., auto_settings: bool):
192
+ if auto_settings and model_id:
193
+ from prompts.ai.client import AIClient
194
+ client = AIClient()
195
+ # Get cached model description
196
+ settings = client.extract_settings(html)
197
+ # Apply to scene
198
+ ```
199
+
200
+ ## Files to Create/Modify
201
+
202
+ | File | Action |
203
+ |------|--------|
204
+ | `src/prompts/ai/__init__.py` | Create |
205
+ | `src/prompts/ai/client.py` | Create |
206
+ | `src/prompts/ai/processors.py` | Create |
207
+ | `src/prompts/ai/cli.py` | Create |
208
+ | `src/prompts/cli.py` | Add `ai` group import |
209
+
210
+ ## Verification
211
+
212
+ 1. **Test extraction**:
213
+ ```bash
214
+ # First cache a model
215
+ uv run prompts models info 1836956
216
+
217
+ # Then extract settings
218
+ uv run prompts ai extract-settings 1836956
219
+ ```
220
+
221
+ 2. **Test JSON fixing**:
222
+ ```bash
223
+ echo '{"broken: json}' > /tmp/broken.json
224
+ uv run prompts ai fix-json /tmp/broken.json
225
+ ```
226
+
227
+ 3. **Verify hermes3 is available**:
228
+ ```bash
229
+ curl http://192.168.0.26:11434/api/tags | jq '.models[].name'
230
+ ```
@@ -0,0 +1,191 @@
1
+ # Refactor: Internal Model ID as Primary Key
2
+
3
+ ## Overview
4
+
5
+ Make the 8-character internal ID the primary key for all model operations. All commands that operate on a single model will use `-m/--model-id` accepting our internal ID format.
6
+
7
+ ## Key Design Decisions
8
+
9
+ 1. **Internal ID is primary** - All lookups start with internal 8-char ID
10
+ 2. **CivitAI IDs retained** - Stored as `civitai_id` field, used for API calls
11
+ 3. **Unified lookup function** - New `resolve_model()` function handles ID resolution
12
+ 4. **Consistent CLI pattern** - All single-model commands use `-m MODEL_ID` or `--model-id MODEL_ID`
13
+
14
+ ## Files to Modify
15
+
16
+ ### 1. `src/prompts/models/cache.py` - Add Unified Lookup
17
+
18
+ Add a `resolve()` method to `ModelCache` that accepts flexible input:
19
+
20
+ ```python
21
+ def resolve(self, identifier: str) -> Optional[CachedModel]:
22
+ """Resolve a model by internal ID (primary), name, or CivitAI ID.
23
+
24
+ Lookup order:
25
+ 1. Exact internal ID match (8-char)
26
+ 2. CivitAI ID (if numeric)
27
+ 3. Name partial match (fallback)
28
+ """
29
+ ```
30
+
31
+ ### 2. `src/prompts/models/cli.py` - Standardize Commands
32
+
33
+ | Command | Current | New |
34
+ |---------|---------|-----|
35
+ | `models info` | `@click.argument("name_or_id")` | `@click.option("-m", "--model-id")` |
36
+ | `models set` | `@click.argument("model_id")` | `@click.option("-m", "--model-id", required=True)` |
37
+ | `models show` | `@click.argument("model_id")` | `@click.option("-m", "--model-id", required=True)` |
38
+ | `models cache clear` | `@click.argument("model_id", type=int)` | `@click.option("-m", "--model-id")` |
39
+
40
+ ### 3. `src/prompts/civitai/cli.py` - Update CivitAI Commands
41
+
42
+ | Command | Current | New |
43
+ |---------|---------|-----|
44
+ | `civitai prompts` | `@click.argument("model_id", type=int)` | `@click.option("-m", "--model-id", required=True)` |
45
+ | `civitai images` | `@click.argument("model_id", type=int)` | `@click.option("-m", "--model-id", required=True)` |
46
+
47
+ These commands need to:
48
+ 1. Accept internal ID
49
+ 2. Resolve to CachedModel
50
+ 3. Use `civitai_id` for API calls
51
+
52
+ ### 4. `src/prompts/ai/cli.py` - Update AI Commands
53
+
54
+ | Command | Current | New |
55
+ |---------|---------|-----|
56
+ | `ai extract-settings` | `@click.argument("model_id", type=int)` | `@click.option("-m", "--model-id", required=True)` |
57
+
58
+ ### 5. `src/prompts/scenes/cli.py` - Update Scene Commands
59
+
60
+ | Command | Current | New |
61
+ |---------|---------|-----|
62
+ | `scenes json` | `--model-id/-m type=int` | `--model-id/-m` (string, internal ID) |
63
+ | `scenes list` | `--model/-m` | `--model-id/-m` (for consistency) |
64
+
65
+ ## Implementation Steps
66
+
67
+ ### Step 1: Add `resolve()` to ModelCache
68
+
69
+ Location: `src/prompts/models/cache.py`
70
+
71
+ ```python
72
+ def resolve(self, identifier: str) -> Optional[CachedModel]:
73
+ """Resolve model by internal ID, CivitAI ID, or name."""
74
+ # 1. Try exact internal ID (case-insensitive)
75
+ model = self.get(identifier.upper())
76
+ if model:
77
+ return model
78
+
79
+ # 2. Try CivitAI ID if numeric
80
+ try:
81
+ civitai_id = int(identifier)
82
+ model = self.get_by_civitai_id(civitai_id)
83
+ if model:
84
+ return model
85
+ except ValueError:
86
+ pass
87
+
88
+ # 3. Try name partial match
89
+ identifier_lower = identifier.lower()
90
+ for model in self._models.values():
91
+ if identifier_lower in model.name.lower():
92
+ return model
93
+
94
+ return None
95
+ ```
96
+
97
+ ### Step 2: Update `models` CLI Commands
98
+
99
+ File: `src/prompts/models/cli.py`
100
+
101
+ **`models info`** (line 582):
102
+ - Change from `@click.argument("name_or_id")` to `@click.option("-m", "--model-id", required=True)`
103
+ - Use `cache.resolve(model_id)` for lookup
104
+ - If model has `civitai_id`, fetch from CivitAI API
105
+
106
+ **`models set`** (line 1021):
107
+ - Change from `@click.argument("model_id")` to `@click.option("-m", "--model-id", required=True)`
108
+ - Use `cache.resolve(model_id)`
109
+
110
+ **`models show`** (line 1091):
111
+ - Change from `@click.argument("model_id")` to `@click.option("-m", "--model-id", required=True)`
112
+ - Use `cache.resolve(model_id)`
113
+
114
+ **`models cache clear`** (line 964):
115
+ - Change from `@click.argument("model_id", type=int)` to `@click.option("-m", "--model-id")`
116
+ - Resolve internal ID to get `civitai_id` for cache clear
117
+
118
+ ### Step 3: Update `civitai` CLI Commands
119
+
120
+ File: `src/prompts/civitai/cli.py`
121
+
122
+ **`civitai prompts`** (line 270):
123
+ ```python
124
+ @civitai.command("prompts")
125
+ @click.option("-m", "--model-id", required=True, help="Model ID (internal or CivitAI)")
126
+ def get_prompts(model_id: str, ...):
127
+ cache = get_cache()
128
+ model = cache.resolve(model_id)
129
+ if not model or not model.civitai_id:
130
+ console.print(f"[red]Model not found or has no CivitAI ID[/red]")
131
+ return
132
+ # Use model.civitai_id for API call
133
+ ```
134
+
135
+ **`civitai images`** (line 304):
136
+ - Same pattern as above
137
+
138
+ ### Step 4: Update `ai` CLI Commands
139
+
140
+ File: `src/prompts/ai/cli.py`
141
+
142
+ **`ai extract-settings`** (line 20):
143
+ - Change from `@click.argument("model_id", type=int)` to `@click.option("-m", "--model-id", required=True)`
144
+ - Resolve internal ID, use `civitai_id` for cache lookup
145
+
146
+ ### Step 5: Update `scenes` CLI Commands
147
+
148
+ File: `src/prompts/scenes/cli.py`
149
+
150
+ **`scenes json`** (line 413):
151
+ - Change `type=int` to string
152
+ - Resolve internal ID to get model file path
153
+
154
+ **`scenes list`** (line 227):
155
+ - Rename `--model` to `--model-id` for consistency
156
+ - Keep existing filter logic (base model matching)
157
+
158
+ ## Verification
159
+
160
+ ```bash
161
+ # Test internal ID lookup
162
+ uv run prompts models show -m C1GVKMA9
163
+
164
+ # Test CivitAI ID fallback
165
+ uv run prompts models show -m 827184
166
+
167
+ # Test name fallback
168
+ uv run prompts models show -m "WAI"
169
+
170
+ # Test civitai commands with internal ID
171
+ uv run prompts civitai prompts -m C1GVKMA9
172
+
173
+ # Test scenes with internal ID
174
+ uv run prompts scenes json wc-r01 -m C1GVKMA9
175
+
176
+ # Test set command
177
+ uv run prompts models set -m C1GVKMA9 --favorite
178
+ ```
179
+
180
+ ## Error Messages
181
+
182
+ When model not found:
183
+ ```
184
+ Model 'XYZ' not found.
185
+ Use 'prompts models list' to see available models and their IDs.
186
+ ```
187
+
188
+ When CivitAI ID required but not available:
189
+ ```
190
+ Model 'XYZ' has no CivitAI ID. This command requires a model from CivitAI.
191
+ ```