llm-cli-council 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.
@@ -0,0 +1,353 @@
1
+ #!/usr/bin/env bash
2
+ # Platform Utilities for llm-cli-council
3
+ # Cross-platform compatibility layer for macOS, Linux, and Windows/WSL
4
+
5
+ set -euo pipefail
6
+
7
+ # =============================================================================
8
+ # Platform Detection
9
+ # =============================================================================
10
+
11
+ # detect_platform - Returns: macos, linux, windows, unknown
12
+ # Usage: PLATFORM=$(detect_platform)
13
+ detect_platform() {
14
+ local uname_s
15
+ uname_s=$(uname -s 2>/dev/null || echo "unknown")
16
+
17
+ case "$uname_s" in
18
+ Darwin*)
19
+ echo "macos"
20
+ ;;
21
+ Linux*)
22
+ # Check if running under WSL
23
+ if grep -qiE 'microsoft|wsl' /proc/version 2>/dev/null; then
24
+ echo "windows"
25
+ else
26
+ echo "linux"
27
+ fi
28
+ ;;
29
+ MINGW*|MSYS*|CYGWIN*)
30
+ echo "windows"
31
+ ;;
32
+ *)
33
+ echo "unknown"
34
+ ;;
35
+ esac
36
+ }
37
+
38
+ # =============================================================================
39
+ # Timeout Command
40
+ # =============================================================================
41
+
42
+ # timeout_cmd - Execute command with timeout
43
+ # Usage: timeout_cmd <seconds> <command> [args...]
44
+ # Returns: Command exit code, or 124 on timeout
45
+ timeout_cmd() {
46
+ local timeout_duration="$1"
47
+ shift
48
+
49
+ local platform
50
+ platform=$(detect_platform)
51
+
52
+ case "$platform" in
53
+ macos)
54
+ # Check for GNU timeout (from coreutils)
55
+ if command -v gtimeout &>/dev/null; then
56
+ gtimeout "$timeout_duration" "$@"
57
+ else
58
+ # Fallback: bash-only solution
59
+ _timeout_bash "$timeout_duration" "$@"
60
+ fi
61
+ ;;
62
+ linux|windows)
63
+ # Standard timeout command available
64
+ if command -v timeout &>/dev/null; then
65
+ timeout "$timeout_duration" "$@"
66
+ else
67
+ _timeout_bash "$timeout_duration" "$@"
68
+ fi
69
+ ;;
70
+ *)
71
+ # Unknown platform, try bash fallback
72
+ _timeout_bash "$timeout_duration" "$@"
73
+ ;;
74
+ esac
75
+ }
76
+
77
+ # _timeout_bash - Bash-only timeout implementation (fallback)
78
+ _timeout_bash() {
79
+ local timeout_duration="$1"
80
+ shift
81
+
82
+ # Run command in background
83
+ "$@" &
84
+ local cmd_pid=$!
85
+
86
+ # Wait with timeout
87
+ local count=0
88
+ while kill -0 "$cmd_pid" 2>/dev/null; do
89
+ if [ "$count" -ge "$timeout_duration" ]; then
90
+ kill -TERM "$cmd_pid" 2>/dev/null || true
91
+ sleep 0.5
92
+ kill -KILL "$cmd_pid" 2>/dev/null || true
93
+ return 124
94
+ fi
95
+ sleep 1
96
+ ((count++)) || true
97
+ done
98
+
99
+ # Get exit code
100
+ wait "$cmd_pid"
101
+ }
102
+
103
+ # =============================================================================
104
+ # Process Management
105
+ # =============================================================================
106
+
107
+ # wait_for_pid - Wait for a process to complete with timeout
108
+ # Usage: wait_for_pid <pid> <timeout_seconds>
109
+ # Returns: 0 if process completed, 1 if timeout
110
+ wait_for_pid() {
111
+ local pid="$1"
112
+ local timeout="${2:-30}"
113
+ local count=0
114
+
115
+ while kill -0 "$pid" 2>/dev/null; do
116
+ if [ "$count" -ge "$timeout" ]; then
117
+ return 1
118
+ fi
119
+ sleep 1
120
+ ((count++)) || true
121
+ done
122
+
123
+ return 0
124
+ }
125
+
126
+ # =============================================================================
127
+ # Temporary Files and Directories
128
+ # =============================================================================
129
+
130
+ # make_temp_file - Create temporary file
131
+ # Usage: TEMP_FILE=$(make_temp_file [prefix])
132
+ make_temp_file() {
133
+ local prefix="${1:-tmp}"
134
+ local platform
135
+ platform=$(detect_platform)
136
+
137
+ case "$platform" in
138
+ macos)
139
+ mktemp -t "${prefix}.XXXXXX"
140
+ ;;
141
+ linux|windows)
142
+ mktemp -t "${prefix}.XXXXXX"
143
+ ;;
144
+ *)
145
+ # Fallback: manual temp file creation
146
+ local temp_file="/tmp/${prefix}.$$.$RANDOM"
147
+ touch "$temp_file"
148
+ echo "$temp_file"
149
+ ;;
150
+ esac
151
+ }
152
+
153
+ # make_temp_dir - Create temporary directory
154
+ # Usage: TEMP_DIR=$(make_temp_dir [prefix])
155
+ make_temp_dir() {
156
+ local prefix="${1:-tmp}"
157
+ local platform
158
+ platform=$(detect_platform)
159
+
160
+ case "$platform" in
161
+ macos)
162
+ mktemp -d -t "${prefix}.XXXXXX"
163
+ ;;
164
+ linux|windows)
165
+ mktemp -d -t "${prefix}.XXXXXX"
166
+ ;;
167
+ *)
168
+ # Fallback: manual temp dir creation
169
+ local temp_dir="/tmp/${prefix}.$$.$RANDOM"
170
+ mkdir -p "$temp_dir"
171
+ echo "$temp_dir"
172
+ ;;
173
+ esac
174
+ }
175
+
176
+ # =============================================================================
177
+ # JSON Parsing
178
+ # =============================================================================
179
+
180
+ # json_get - Simple JSON value extraction
181
+ # Usage: json_get <json_file> <key>
182
+ # Example: json_get config.json ".providers[0].name"
183
+ # Note: Requires jq if available, otherwise uses grep/sed fallback
184
+ json_get() {
185
+ local json_file="$1"
186
+ local key="$2"
187
+
188
+ if ! [ -f "$json_file" ]; then
189
+ echo "Error: JSON file not found: $json_file" >&2
190
+ return 1
191
+ fi
192
+
193
+ # Try jq first (most reliable)
194
+ if command -v jq &>/dev/null; then
195
+ jq -r "$key // empty" "$json_file" 2>/dev/null || echo ""
196
+ return 0
197
+ fi
198
+
199
+ # Fallback: grep + sed (limited, but works for simple keys)
200
+ # This only handles simple cases like: {"key": "value"}
201
+ # Does NOT handle nested objects or arrays reliably
202
+ local simple_key
203
+ simple_key=$(echo "$key" | sed 's/^\.//; s/\[.*\]//g')
204
+
205
+ grep -o "\"$simple_key\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" "$json_file" 2>/dev/null \
206
+ | head -1 \
207
+ | sed 's/.*:[[:space:]]*"\([^"]*\)".*/\1/' \
208
+ || echo ""
209
+ }
210
+
211
+ # json_has_key - Check if JSON file contains a key
212
+ # Usage: json_has_key <json_file> <key>
213
+ # Returns: 0 if key exists, 1 otherwise
214
+ json_has_key() {
215
+ local json_file="$1"
216
+ local key="$2"
217
+
218
+ if ! [ -f "$json_file" ]; then
219
+ return 1
220
+ fi
221
+
222
+ if command -v jq &>/dev/null; then
223
+ jq -e "$key" "$json_file" &>/dev/null
224
+ return $?
225
+ fi
226
+
227
+ # Fallback: simple grep
228
+ local simple_key
229
+ simple_key=$(echo "$key" | sed 's/^\.//; s/\[.*\]//g')
230
+ grep -q "\"$simple_key\"" "$json_file" 2>/dev/null
231
+ }
232
+
233
+ # =============================================================================
234
+ # Path Resolution
235
+ # =============================================================================
236
+
237
+ # path_resolve - Resolve path with tilde expansion and environment variables
238
+ # Usage: RESOLVED=$(path_resolve "~/path/to/file")
239
+ path_resolve() {
240
+ local path="$1"
241
+
242
+ # Expand tilde
243
+ if [[ "$path" =~ ^~ ]]; then
244
+ path="${path/#\~/$HOME}"
245
+ fi
246
+
247
+ # Expand environment variables
248
+ # Handle both $VAR and ${VAR} syntax
249
+ path=$(eval echo "$path")
250
+
251
+ echo "$path"
252
+ }
253
+
254
+ # path_exists - Check if path exists (after resolution)
255
+ # Usage: if path_exists "~/file"; then ...
256
+ path_exists() {
257
+ local path
258
+ path=$(path_resolve "$1")
259
+ [ -e "$path" ]
260
+ }
261
+
262
+ # =============================================================================
263
+ # Shell Detection and Version
264
+ # =============================================================================
265
+
266
+ # get_shell_version - Get bash version
267
+ # Usage: VERSION=$(get_shell_version)
268
+ get_shell_version() {
269
+ echo "${BASH_VERSION:-unknown}"
270
+ }
271
+
272
+ # check_bash_version - Check if bash version meets minimum requirement
273
+ # Usage: check_bash_version "4.0"
274
+ # Returns: 0 if meets requirement, 1 otherwise
275
+ check_bash_version() {
276
+ local required="$1"
277
+ local current="${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
278
+
279
+ # Simple version comparison (assumes major.minor format)
280
+ local req_major req_minor cur_major cur_minor
281
+ req_major=$(echo "$required" | cut -d. -f1)
282
+ req_minor=$(echo "$required" | cut -d. -f2)
283
+ cur_major="${BASH_VERSINFO[0]}"
284
+ cur_minor="${BASH_VERSINFO[1]}"
285
+
286
+ if [ "$cur_major" -gt "$req_major" ]; then
287
+ return 0
288
+ elif [ "$cur_major" -eq "$req_major" ] && [ "$cur_minor" -ge "$req_minor" ]; then
289
+ return 0
290
+ else
291
+ return 1
292
+ fi
293
+ }
294
+
295
+ # =============================================================================
296
+ # Utility Functions
297
+ # =============================================================================
298
+
299
+ # command_exists - Check if command is available
300
+ # Usage: if command_exists "jq"; then ...
301
+ command_exists() {
302
+ command -v "$1" &>/dev/null
303
+ }
304
+
305
+ # get_config_dir - Get platform-appropriate config directory
306
+ # Usage: CONFIG_DIR=$(get_config_dir)
307
+ get_config_dir() {
308
+ local platform
309
+ platform=$(detect_platform)
310
+
311
+ case "$platform" in
312
+ macos)
313
+ echo "${HOME}/Library/Application Support"
314
+ ;;
315
+ linux|windows)
316
+ echo "${XDG_CONFIG_HOME:-${HOME}/.config}"
317
+ ;;
318
+ *)
319
+ echo "${HOME}/.config"
320
+ ;;
321
+ esac
322
+ }
323
+
324
+ # ensure_dir - Ensure directory exists
325
+ # Usage: ensure_dir "/path/to/dir"
326
+ ensure_dir() {
327
+ local dir="$1"
328
+ if [ ! -d "$dir" ]; then
329
+ mkdir -p "$dir"
330
+ fi
331
+ }
332
+
333
+ # =============================================================================
334
+ # Export Functions (for sourcing)
335
+ # =============================================================================
336
+
337
+ # When sourced, make functions available
338
+ if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
339
+ export -f detect_platform
340
+ export -f timeout_cmd
341
+ export -f wait_for_pid
342
+ export -f make_temp_file
343
+ export -f make_temp_dir
344
+ export -f json_get
345
+ export -f json_has_key
346
+ export -f path_resolve
347
+ export -f path_exists
348
+ export -f get_shell_version
349
+ export -f check_bash_version
350
+ export -f command_exists
351
+ export -f get_config_dir
352
+ export -f ensure_dir
353
+ fi
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "llm-cli-council",
3
+ "version": "1.0.0",
4
+ "description": "Get diverse AI perspectives on your code and plans via multiple LLM CLIs — orchestrates Claude, GitHub Copilot, Codex, Gemini, and Ollama as a council",
5
+ "bin": {
6
+ "llm-cli-council": "bin/install.js"
7
+ },
8
+ "files": [
9
+ "bin",
10
+ "skills",
11
+ "lib",
12
+ "prompts",
13
+ "rules",
14
+ "config",
15
+ ".claude-plugin"
16
+ ],
17
+ "keywords": [
18
+ "claude",
19
+ "claude-code",
20
+ "llm",
21
+ "code-review",
22
+ "copilot",
23
+ "codex",
24
+ "gemini",
25
+ "ollama",
26
+ "claude-plugin",
27
+ "ai-council"
28
+ ],
29
+ "author": "GuitaristForEver",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/GuitaristForEver/llm-cli-council.git"
34
+ },
35
+ "homepage": "https://github.com/GuitaristForEver/llm-cli-council#readme",
36
+ "bugs": {
37
+ "url": "https://github.com/GuitaristForEver/llm-cli-council/issues"
38
+ },
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
+ },
42
+ "scripts": {
43
+ "test": "bash tests/test-setup.sh",
44
+ "prepublishOnly": "npm test"
45
+ }
46
+ }
@@ -0,0 +1,153 @@
1
+ # Chairman Synthesis Prompt
2
+
3
+ Claude acts as Chairman of the council, synthesizing multiple provider reviews into unified guidance.
4
+
5
+ ---
6
+
7
+ ## Chairman Role
8
+
9
+ As Chairman, you:
10
+ 1. **Synthesize** - Combine multiple reviews into coherent guidance
11
+ 2. **Resolve** - Make decisions when providers disagree
12
+ 3. **Prioritize** - Order recommendations by importance
13
+ 4. **Decide** - Provide final APPROVE/REQUEST CHANGES verdict
14
+
15
+ ---
16
+
17
+ ## Synthesis Prompt Template
18
+
19
+ ```
20
+ TASK: As Chairman of the LLM Council, synthesize the following provider reviews into unified guidance.
21
+
22
+ REVIEWS RECEIVED:
23
+ {PROVIDER_REVIEWS}
24
+
25
+ SYNTHESIS RULES:
26
+ 1. CONSENSUS: Points raised by 2+ providers go here
27
+ 2. CONCERNS: Points raised by at least one provider that merit attention
28
+ 3. DISSENT: Where providers disagree - YOU must resolve with reasoning
29
+ 4. Maximum 5 recommendations total, ordered by priority
30
+ 5. You MUST provide a final verdict
31
+
32
+ ANTI-PARALYSIS RULES:
33
+ - Do NOT present conflicting advice without resolution
34
+ - Do NOT defer decisions to the user
35
+ - Do NOT exceed 5 recommendations
36
+ - Do NOT leave verdict ambiguous
37
+
38
+ WEIGHTING:
39
+ - For code-related plans: Weight Codex and Copilot higher
40
+ - For architecture plans: Weight Claude higher
41
+ - For general plans: Equal weighting
42
+
43
+ OUTPUT FORMAT:
44
+ COUNCIL REVIEW
45
+ ═══════════════════════════════════════════════════════
46
+
47
+ CONSENSUS (All/Majority agree):
48
+ • [Point that 2+ providers agree on]
49
+ • [Another consensus point]
50
+
51
+ CONCERNS (Raised by at least one):
52
+ • [Concern] — Raised by: [Provider names]
53
+ Assessment: [Your assessment of validity/priority]
54
+
55
+ DISSENTING VIEWS:
56
+ • [Topic]: [Provider A] says X, [Provider B] says Y
57
+ Resolution: [Your decision with reasoning]
58
+
59
+ RECOMMENDATIONS (max 5, prioritized):
60
+ 1. [Most important] [Quick/Short/Medium effort estimate]
61
+ 2. [Second priority] [Effort]
62
+ 3. [Third priority] [Effort]
63
+
64
+ PROVIDER VERDICTS:
65
+ [Provider 1]: [VERDICT] ([CONFIDENCE])
66
+ [Provider 2]: [VERDICT] ([CONFIDENCE])
67
+
68
+ FINAL VERDICT: [APPROVE / REQUEST CHANGES]
69
+ Reasoning: [Clear explanation of why, referencing provider input]
70
+
71
+ ═══════════════════════════════════════════════════════
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Variable Substitution
77
+
78
+ | Variable | Source |
79
+ |----------|--------|
80
+ | `{PROVIDER_REVIEWS}` | Concatenated reviews from all providers, each prefixed with provider name |
81
+
82
+ ---
83
+
84
+ ## Review Formatting
85
+
86
+ Format each provider review as:
87
+
88
+ ```
89
+ --- REVIEW FROM: [PROVIDER NAME] ---
90
+ [Full review content]
91
+ --- END REVIEW ---
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Resolution Guidelines
97
+
98
+ ### When Providers Disagree on Verdict
99
+
100
+ 1. **Majority rules** if 2+ providers agree
101
+ 2. **Tie-breaker**: Weight by task type (code → Codex, architecture → Claude)
102
+ 3. **All disagree**: Chairman decides based on strongest reasoning
103
+
104
+ ### When Recommendations Conflict
105
+
106
+ 1. Evaluate each recommendation on merit
107
+ 2. Keep recommendations that don't contradict
108
+ 3. For contradictions, pick one and explain why
109
+
110
+ ### Effort Estimates
111
+
112
+ Standardize to:
113
+ - **Quick**: < 1 hour
114
+ - **Short**: 1-4 hours
115
+ - **Medium**: 1-2 days
116
+ - **Large**: 3+ days
117
+
118
+ ---
119
+
120
+ ## Output Validation
121
+
122
+ Before presenting synthesis, verify:
123
+ - [ ] Maximum 5 recommendations
124
+ - [ ] All dissent has resolution
125
+ - [ ] Final verdict is clear (not "probably" or "maybe")
126
+ - [ ] Reasoning references specific provider input
127
+ - [ ] No raw provider output passed through
128
+
129
+ ---
130
+
131
+ ## Error Cases
132
+
133
+ ### Only 1 Provider Responded
134
+ ```
135
+ Note: Only [Provider] responded. This review lacks council diversity.
136
+ Consider running with --mode=full for comprehensive feedback.
137
+
138
+ [Present single review with disclaimer]
139
+ ```
140
+
141
+ ### All Providers Approve
142
+ ```
143
+ CONSENSUS: All providers approve this plan.
144
+
145
+ [Present combined recommendations anyway - unanimous approval doesn't mean perfect]
146
+ ```
147
+
148
+ ### All Providers Request Changes
149
+ ```
150
+ STRONG CONSENSUS: All providers request changes.
151
+
152
+ [Prioritize most critical issues across all reviews]
153
+ ```
@@ -0,0 +1,134 @@
1
+ # Code Review Prompt Template
2
+
3
+ This template is sent to each council provider for independent code review.
4
+
5
+ ---
6
+
7
+ ## Prompt Template
8
+
9
+ ```
10
+ TASK: Review the following code changes for bugs, security issues, performance problems, and maintainability concerns.
11
+
12
+ EXPECTED OUTCOME: Provide a structured code review with:
13
+ - Assessment of code quality (1-10 scale)
14
+ - Identified issues categorized by severity
15
+ - Specific recommendations with file/line references
16
+ - Final verdict: APPROVE, REQUEST CHANGES, or REJECT
17
+
18
+ CONTEXT:
19
+ - This is a code review, not implementation
20
+ - Focus on issues that matter, not style nitpicks
21
+ - Prioritize: Correctness → Security → Performance → Maintainability
22
+
23
+ CODE CHANGES:
24
+ ---
25
+ {CODE_CONTENT}
26
+ ---
27
+
28
+ FILES AFFECTED:
29
+ {FILE_LIST}
30
+
31
+ CONSTRAINTS:
32
+ - You are one voice in a council of reviewers
33
+ - Keep feedback actionable and specific
34
+ - Reference file:line when possible
35
+
36
+ MUST DO:
37
+ 1. Rate code quality on 1-10 scale with justification
38
+ 2. List issues by severity: CRITICAL | HIGH | MEDIUM | LOW
39
+ 3. For each issue: file, line (if known), description, suggested fix
40
+ 4. Provide 3-5 actionable recommendations
41
+ 5. Give clear verdict: APPROVE | REQUEST CHANGES | REJECT
42
+
43
+ MUST NOT DO:
44
+ - Nitpick formatting (let formatters handle this)
45
+ - Flag theoretical concerns unlikely to occur
46
+ - Suggest complete rewrites for minor issues
47
+ - Be overly verbose
48
+
49
+ OUTPUT FORMAT:
50
+ RATING: [1-10] - [one-line justification]
51
+
52
+ ISSUES:
53
+ CRITICAL:
54
+ • [file:line] [Description] → [Suggested fix]
55
+
56
+ HIGH:
57
+ • [file:line] [Description] → [Suggested fix]
58
+
59
+ MEDIUM:
60
+ • [file:line] [Description] → [Suggested fix]
61
+
62
+ LOW:
63
+ • [file:line] [Description] → [Suggested fix]
64
+
65
+ RECOMMENDATIONS:
66
+ 1. [Specific recommendation]
67
+ 2. [Specific recommendation]
68
+ 3. [Specific recommendation]
69
+
70
+ VERDICT: [APPROVE / REQUEST CHANGES / REJECT]
71
+ CONFIDENCE: [HIGH / MEDIUM / LOW]
72
+ REASONING: [1-2 sentences explaining verdict]
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Variable Substitution
78
+
79
+ | Variable | Source |
80
+ |----------|--------|
81
+ | `{CODE_CONTENT}` | Git diff, file contents, or pasted code |
82
+ | `{FILE_LIST}` | List of files being reviewed |
83
+
84
+ ---
85
+
86
+ ## Provider-Specific Adjustments
87
+
88
+ ### Claude
89
+ No adjustments - template works as-is.
90
+
91
+ ### Codex
92
+ Add prefix: "You are an expert code reviewer. Focus on bugs and security issues."
93
+
94
+ ### Copilot
95
+ Add prefix: "Review this code from a GitHub PR perspective. Be specific about issues."
96
+
97
+ ### Gemini
98
+ Add prefix: "Provide comprehensive code review covering all quality aspects."
99
+
100
+ ### Ollama
101
+ Simplify for smaller models - focus on critical issues only.
102
+
103
+ ---
104
+
105
+ ## Response Parsing
106
+
107
+ Expected response sections to parse:
108
+ 1. `RATING:` line with number and justification
109
+ 2. `ISSUES:` with severity categories
110
+ 3. `RECOMMENDATIONS:` numbered list
111
+ 4. `VERDICT:` APPROVE, REQUEST CHANGES, or REJECT
112
+ 5. `CONFIDENCE:` HIGH, MEDIUM, or LOW
113
+ 6. `REASONING:` explanation
114
+
115
+ ---
116
+
117
+ ## Issue Severity Definitions
118
+
119
+ | Severity | Definition | Example |
120
+ |----------|------------|---------|
121
+ | CRITICAL | Security vulnerability, data loss risk, crash | SQL injection, null pointer |
122
+ | HIGH | Bug that affects functionality | Wrong calculation, broken feature |
123
+ | MEDIUM | Code smell, maintainability issue | Complex function, poor naming |
124
+ | LOW | Minor improvement opportunity | Documentation, minor refactor |
125
+
126
+ ---
127
+
128
+ ## Verdict Definitions
129
+
130
+ | Verdict | When to Use |
131
+ |---------|-------------|
132
+ | APPROVE | No critical/high issues, code is ready to merge |
133
+ | REQUEST CHANGES | Has high issues or multiple medium issues needing fix |
134
+ | REJECT | Critical issues or fundamentally flawed approach |