@get-blu/blu-code 1.1.0 → 1.5.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.
- package/LICENSE +22 -22
- package/README.md +318 -318
- package/bin/cli.js +45 -24
- package/package.json +47 -26
- package/scripts/install-npm.js +139 -94
package/LICENSE
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Kujtim Hoxha
|
|
4
|
-
Copyright (c) 2026 Garv Agnihotri (Blu)
|
|
5
|
-
|
|
6
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
-
in the Software without restriction, including without limitation the rights
|
|
9
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
-
furnished to do so, subject to the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be included in all
|
|
14
|
-
copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kujtim Hoxha
|
|
4
|
+
Copyright (c) 2026 Garv Agnihotri (Blu)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,319 +1,319 @@
|
|
|
1
|
-
# Blu
|
|
2
|
-
|
|
3
|
-
>Blu is a Go-powered terminal UI that brings AI-assisted coding directly into your command line. It connects to leading models and gives them tools to read, analyze, and modify your codebase from an elegant TUI built with Bubble Tea.
|
|
4
|
-
|
|
5
|
-
[](LICENSE)
|
|
6
|
-
[](https://go.dev/)
|
|
7
|
-
|
|
8
|
-
## Overview
|
|
9
|
-
|
|
10
|
-
Blu is a Go-powered terminal UI that transforms your command line into an intelligent development environment. It connects to leading AI models and provides them with powerful tools to read, analyze, and modify your codebase - all from an elegant TUI built with [Bubble Tea](https://github.com/charmbracelet/bubbletea).
|
|
11
|
-
|
|
12
|
-
**Key capabilities:**
|
|
13
|
-
- Chat with AI models that can see and edit your files
|
|
14
|
-
- Execute bash commands through AI suggestions
|
|
15
|
-
- Apply complex code refactors automatically
|
|
16
|
-
- Get real-time LSP diagnostics and code intelligence
|
|
17
|
-
- Manage multiple conversation sessions with full context
|
|
18
|
-
- Use Model Context Protocol (MCP) servers for extensibility
|
|
19
|
-
|
|
20
|
-
## Quick Start
|
|
21
|
-
|
|
22
|
-
### Installation
|
|
23
|
-
|
|
24
|
-
**Via npm (recommended):**
|
|
25
|
-
```bash
|
|
26
|
-
npm install -g @get-blu/blu-code
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
**Via raw script:**
|
|
30
|
-
```bash
|
|
31
|
-
curl -fsSL https://raw.githubusercontent.com/Get-Blu/blu-code/main/install | bash
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
**From source:**
|
|
35
|
-
```bash
|
|
36
|
-
git clone https://github.com/Get-Blu/blu-code.git
|
|
37
|
-
cd blu-code
|
|
38
|
-
go build -o blu
|
|
39
|
-
blu
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Setup
|
|
43
|
-
|
|
44
|
-
1. Set your API key(s):
|
|
45
|
-
```bash
|
|
46
|
-
export ANTHROPIC_API_KEY="your-key-here"
|
|
47
|
-
# or OPENAI_API_KEY, GEMINI_API_KEY
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
2. Create a `.blu.json` config file (optional):
|
|
51
|
-
```json
|
|
52
|
-
{
|
|
53
|
-
"agents": {
|
|
54
|
-
"coder": {
|
|
55
|
-
"model": "claude-3.7-sonnet",
|
|
56
|
-
"maxTokens": 8192
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
"autoCompact": true
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
3. Launch Blu:
|
|
64
|
-
```bash
|
|
65
|
-
blu
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Features
|
|
69
|
-
|
|
70
|
-
### Multi-Model Support
|
|
71
|
-
Switch between Claude, GPT, Gemini, or any OpenAI-compatible endpoint. Use different models for different tasks within the same session.
|
|
72
|
-
|
|
73
|
-
### Intelligent File Operations
|
|
74
|
-
- **Glob patterns**: Find files matching complex patterns
|
|
75
|
-
- **Smart grep**: Search across your codebase with regex
|
|
76
|
-
- **Atomic edits**: Apply precise diffs and patches
|
|
77
|
-
- **Batch operations**: Modify multiple files in one go
|
|
78
|
-
|
|
79
|
-
### Development Tools
|
|
80
|
-
- **LSP Integration**: Real-time diagnostics and code intelligence via Language Server Protocol
|
|
81
|
-
- **Command execution**: Run bash commands directly from chat
|
|
82
|
-
- **MCP Support**: Extend with Model Context Protocol servers
|
|
83
|
-
- **Version control aware**: Understands your git context
|
|
84
|
-
|
|
85
|
-
### Productivity Features
|
|
86
|
-
- **Session management**: Switch between multiple conversations (`Ctrl+S`)
|
|
87
|
-
- **Custom commands**: Create reusable prompt templates (`Ctrl+K`)
|
|
88
|
-
- **Auto-compaction**: Intelligent context window management
|
|
89
|
-
- **SQLite persistence**: Full local history storage
|
|
90
|
-
- **Interactive sidebar**: Visualize file changes in real-time
|
|
91
|
-
|
|
92
|
-
## Usage
|
|
93
|
-
|
|
94
|
-
### Basic Workflow
|
|
95
|
-
|
|
96
|
-
1. **Start a conversation**: Launch `blu` and ask a question
|
|
97
|
-
2. **Let AI explore**: Blu can read files, search your codebase, and understand context
|
|
98
|
-
3. **Review changes**: See proposed file modifications in the sidebar
|
|
99
|
-
4. **Apply or reject**: Accept changes you want, skip the rest
|
|
100
|
-
|
|
101
|
-
## Documentation
|
|
102
|
-
|
|
103
|
-
Comprehensive documentation is available in the `docs/` directory:
|
|
104
|
-
|
|
105
|
-
- [Introduction](docs/introduction.md)
|
|
106
|
-
- [Getting Started](docs/getting-started.md)
|
|
107
|
-
- [Configuration](docs/configuration.md)
|
|
108
|
-
- [Key Bindings](docs/key-bindings.md)
|
|
109
|
-
- [Architecture](docs/architecture/overview.md)
|
|
110
|
-
|
|
111
|
-
### Detailed Features
|
|
112
|
-
- [AI Chat](docs/features/ai-chat.md)
|
|
113
|
-
- [File Operations](docs/features/file-operations.md)
|
|
114
|
-
- [LSP Intelligence](docs/features/lsp-and-intelligence.md)
|
|
115
|
-
- [MCP Servers](docs/features/mcp-servers.md)
|
|
116
|
-
- [Session Management](docs/features/session-management.md)
|
|
117
|
-
|
|
118
|
-
### Guides
|
|
119
|
-
- [Best Practices](docs/guides/best-practices.md)
|
|
120
|
-
- [Troubleshooting](docs/guides/troubleshooting.md)
|
|
121
|
-
|
|
122
|
-
## Keyboard Shortcuts
|
|
123
|
-
|
|
124
|
-
### Global Shortcuts
|
|
125
|
-
|
|
126
|
-
| Shortcut | Action |
|
|
127
|
-
| -------- | ------------------------------------------------------- |
|
|
128
|
-
| `Ctrl+C` | Quit application |
|
|
129
|
-
| `Ctrl+?` | Toggle help dialog |
|
|
130
|
-
| `?` | Toggle help dialog (when not in editing mode) |
|
|
131
|
-
| `Ctrl+L` | View logs |
|
|
132
|
-
| `Ctrl+S` | Switch session |
|
|
133
|
-
| `Ctrl+K` | Command dialog |
|
|
134
|
-
| `Ctrl+O` | Toggle model selection dialog |
|
|
135
|
-
| `Ctrl+P` | Toggle provider selection (API key configuration) |
|
|
136
|
-
| `Esc` | Close current overlay/dialog or return to previous mode |
|
|
137
|
-
|
|
138
|
-
### Chat Page Shortcuts
|
|
139
|
-
|
|
140
|
-
| Shortcut | Action |
|
|
141
|
-
| -------- | --------------------------------------- |
|
|
142
|
-
| `Ctrl+N` | Create new session |
|
|
143
|
-
| `Ctrl+X` | Cancel current operation/generation |
|
|
144
|
-
| `i` | Focus editor (when not in writing mode) |
|
|
145
|
-
| `Esc` | Exit writing mode and focus messages |
|
|
146
|
-
|
|
147
|
-
### Editor Shortcuts
|
|
148
|
-
|
|
149
|
-
| Shortcut | Action |
|
|
150
|
-
| ------------------- | ----------------------------------------- |
|
|
151
|
-
| `Ctrl+S` | Send message (when editor is focused) |
|
|
152
|
-
| `Enter` or `Ctrl+S` | Send message (when editor is not focused) |
|
|
153
|
-
| `Ctrl+E` | Open external editor |
|
|
154
|
-
| `Esc` | Blur editor and focus messages |
|
|
155
|
-
|
|
156
|
-
### Session Dialog Shortcuts
|
|
157
|
-
|
|
158
|
-
| Shortcut | Action |
|
|
159
|
-
| ---------- | ---------------- |
|
|
160
|
-
| `↑` or `k` | Previous session |
|
|
161
|
-
| `↓` or `j` | Next session |
|
|
162
|
-
| `Enter` | Select session |
|
|
163
|
-
| `Esc` | Close dialog |
|
|
164
|
-
|
|
165
|
-
### Model Dialog Shortcuts
|
|
166
|
-
|
|
167
|
-
| Shortcut | Action |
|
|
168
|
-
| ---------- | ----------------- |
|
|
169
|
-
| `↑` or `k` | Move up |
|
|
170
|
-
| `↓` or `j` | Move down |
|
|
171
|
-
| `←` or `h` | Previous provider (within model dialog) |
|
|
172
|
-
| `→` or `l` | Next provider (within model dialog) |
|
|
173
|
-
| `Esc` | Close dialog |
|
|
174
|
-
|
|
175
|
-
### Provider & API Key Dialog Shortcuts
|
|
176
|
-
|
|
177
|
-
| Shortcut | Action |
|
|
178
|
-
| -------- | -------------------- |
|
|
179
|
-
| `↑` / `↓` | Move up/down |
|
|
180
|
-
| `Enter` | Select provider |
|
|
181
|
-
| `Esc` | Close dialog |
|
|
182
|
-
| `Enter` | Save API key (input) |
|
|
183
|
-
|
|
184
|
-
### Permission Dialog Shortcuts
|
|
185
|
-
|
|
186
|
-
| Shortcut | Action |
|
|
187
|
-
| ----------------------- | ---------------------------- |
|
|
188
|
-
| `←` or `left` | Switch options left |
|
|
189
|
-
| `→` or `right` or `tab` | Switch options right |
|
|
190
|
-
| `Enter` or `space` | Confirm selection |
|
|
191
|
-
| `a` | Allow permission |
|
|
192
|
-
| `A` | Allow permission for session |
|
|
193
|
-
| `d` | Deny permission |
|
|
194
|
-
|
|
195
|
-
### Logs Page Shortcuts
|
|
196
|
-
|
|
197
|
-
| Shortcut | Action |
|
|
198
|
-
| ------------------ | ------------------- |
|
|
199
|
-
| `Backspace` or `q` | Return to chat page |
|
|
200
|
-
|
|
201
|
-
## Configuration
|
|
202
|
-
|
|
203
|
-
Place `.blu.json` in your home directory (`~/.blu.json`) or project root:
|
|
204
|
-
|
|
205
|
-
```json
|
|
206
|
-
{
|
|
207
|
-
"agents": {
|
|
208
|
-
"coder": {
|
|
209
|
-
"model": "claude-3.7-sonnet",
|
|
210
|
-
"maxTokens": 8192,
|
|
211
|
-
"temperature": 0.7
|
|
212
|
-
},
|
|
213
|
-
"summarizer": {
|
|
214
|
-
"model": "gpt-4o-mini",
|
|
215
|
-
"maxTokens": 2048
|
|
216
|
-
}
|
|
217
|
-
},
|
|
218
|
-
"autoCompact": true,
|
|
219
|
-
"mcpServers": {
|
|
220
|
-
"filesystem": {
|
|
221
|
-
"command": "npx",
|
|
222
|
-
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### Supported Models
|
|
229
|
-
|
|
230
|
-
**Anthropic (Claude):**
|
|
231
|
-
- `claude-3.7-sonnet` - Recommended for coding (supports reasoning)
|
|
232
|
-
- `claude-3.5-sonnet` - Fast and highly capable
|
|
233
|
-
- `claude-4.6-opus` - Next-gen flagship capability
|
|
234
|
-
|
|
235
|
-
**OpenAI:**
|
|
236
|
-
- `o3-ultra` - Latest reasoning flagship
|
|
237
|
-
- `gpt-5.3-codex` - Specialized for agentic coding
|
|
238
|
-
- `gpt-4o` - Balanced speed and intelligence
|
|
239
|
-
|
|
240
|
-
**Google:**
|
|
241
|
-
- `gemini-3-deep-think` - Advanced reasoning and engineering
|
|
242
|
-
- `gemini-2.0-flash` - High-speed intelligence
|
|
243
|
-
- `gemini-1.5-pro` - Large context window
|
|
244
|
-
|
|
245
|
-
**DeepSeek:**
|
|
246
|
-
- `deepseek-v3` - High performance open-weights model
|
|
247
|
-
- `deepseek-r1` - Reasoning focused model
|
|
248
|
-
|
|
249
|
-
### Environment Variables
|
|
250
|
-
|
|
251
|
-
| Variable | Purpose |
|
|
252
|
-
|----------|---------|
|
|
253
|
-
| `ANTHROPIC_API_KEY` | Claude API access |
|
|
254
|
-
| `OPENAI_API_KEY` | GPT-4 API access |
|
|
255
|
-
| `GEMINI_API_KEY` | Gemini API access |
|
|
256
|
-
| `BLU_DEBUG=true` | Enable debug logging |
|
|
257
|
-
| `BLU_CONFIG=/path/to/.blu.json` | Custom config location |
|
|
258
|
-
|
|
259
|
-
## Troubleshooting
|
|
260
|
-
|
|
261
|
-
**Blu won't start**
|
|
262
|
-
- Check your API keys are set
|
|
263
|
-
- Verify Go 1.21+ is installed
|
|
264
|
-
- Try `blu --debug` for detailed logs
|
|
265
|
-
|
|
266
|
-
**AI can't see my files**
|
|
267
|
-
- Ensure you're running Blu from your project directory
|
|
268
|
-
- Check file permissions
|
|
269
|
-
- Verify paths in error messages
|
|
270
|
-
|
|
271
|
-
**Context window errors**
|
|
272
|
-
- Enable `autoCompact` in config
|
|
273
|
-
- Start a new session for fresh context
|
|
274
|
-
- Use more concise prompts
|
|
275
|
-
|
|
276
|
-
## Building from Source
|
|
277
|
-
|
|
278
|
-
```bash
|
|
279
|
-
# Clone the repository
|
|
280
|
-
git clone https://github.com/Get-Blu/blu-code.git
|
|
281
|
-
cd blu-code
|
|
282
|
-
|
|
283
|
-
# Install dependencies
|
|
284
|
-
go mod download
|
|
285
|
-
|
|
286
|
-
# Build
|
|
287
|
-
go build -o blu
|
|
288
|
-
|
|
289
|
-
# Run tests
|
|
290
|
-
go test ./...
|
|
291
|
-
|
|
292
|
-
# Install globally
|
|
293
|
-
sudo mv blu /usr/local/bin/
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
## Contributing
|
|
297
|
-
|
|
298
|
-
Contributions are welcome! Please feel free to submit issues or pull requests.
|
|
299
|
-
|
|
300
|
-
1. Fork the repository
|
|
301
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
302
|
-
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
303
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
304
|
-
5. Open a Pull Request
|
|
305
|
-
|
|
306
|
-
## Credits
|
|
307
|
-
|
|
308
|
-
Blu builds on the excellent work of:
|
|
309
|
-
|
|
310
|
-
- **[OpenCode](https://github.com/opencode-ai/opencode)** - The foundation Blu is built upon
|
|
311
|
-
- **[@adamdottv](https://github.com/adamdottv)** - Original OpenCode design and architecture
|
|
312
|
-
- **[@isaacphi](https://github.com/isaacphi)** - LSP integration via `mcp-language-server`
|
|
313
|
-
- **[Bubble Tea](https://github.com/charmbracelet/bubbletea)** - Excellent TUI framework
|
|
314
|
-
|
|
315
|
-
## License
|
|
316
|
-
|
|
317
|
-
Distributed under the **MIT License**. See `LICENSE` for more information.
|
|
318
|
-
|
|
1
|
+
# Blu
|
|
2
|
+
|
|
3
|
+
>Blu is a Go-powered terminal UI that brings AI-assisted coding directly into your command line. It connects to leading models and gives them tools to read, analyze, and modify your codebase from an elegant TUI built with Bubble Tea.
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://go.dev/)
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Blu is a Go-powered terminal UI that transforms your command line into an intelligent development environment. It connects to leading AI models and provides them with powerful tools to read, analyze, and modify your codebase - all from an elegant TUI built with [Bubble Tea](https://github.com/charmbracelet/bubbletea).
|
|
11
|
+
|
|
12
|
+
**Key capabilities:**
|
|
13
|
+
- Chat with AI models that can see and edit your files
|
|
14
|
+
- Execute bash commands through AI suggestions
|
|
15
|
+
- Apply complex code refactors automatically
|
|
16
|
+
- Get real-time LSP diagnostics and code intelligence
|
|
17
|
+
- Manage multiple conversation sessions with full context
|
|
18
|
+
- Use Model Context Protocol (MCP) servers for extensibility
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Installation
|
|
23
|
+
|
|
24
|
+
**Via npm (recommended):**
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g @get-blu/blu-code
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Via raw script:**
|
|
30
|
+
```bash
|
|
31
|
+
curl -fsSL https://raw.githubusercontent.com/Get-Blu/blu-code/main/install | bash
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**From source:**
|
|
35
|
+
```bash
|
|
36
|
+
git clone https://github.com/Get-Blu/blu-code.git
|
|
37
|
+
cd blu-code
|
|
38
|
+
go build -o blu
|
|
39
|
+
blu
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Setup
|
|
43
|
+
|
|
44
|
+
1. Set your API key(s):
|
|
45
|
+
```bash
|
|
46
|
+
export ANTHROPIC_API_KEY="your-key-here"
|
|
47
|
+
# or OPENAI_API_KEY, GEMINI_API_KEY
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
2. Create a `.blu.json` config file (optional):
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"agents": {
|
|
54
|
+
"coder": {
|
|
55
|
+
"model": "claude-3.7-sonnet",
|
|
56
|
+
"maxTokens": 8192
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"autoCompact": true
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
3. Launch Blu:
|
|
64
|
+
```bash
|
|
65
|
+
blu
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
### Multi-Model Support
|
|
71
|
+
Switch between Claude, GPT, Gemini, or any OpenAI-compatible endpoint. Use different models for different tasks within the same session.
|
|
72
|
+
|
|
73
|
+
### Intelligent File Operations
|
|
74
|
+
- **Glob patterns**: Find files matching complex patterns
|
|
75
|
+
- **Smart grep**: Search across your codebase with regex
|
|
76
|
+
- **Atomic edits**: Apply precise diffs and patches
|
|
77
|
+
- **Batch operations**: Modify multiple files in one go
|
|
78
|
+
|
|
79
|
+
### Development Tools
|
|
80
|
+
- **LSP Integration**: Real-time diagnostics and code intelligence via Language Server Protocol
|
|
81
|
+
- **Command execution**: Run bash commands directly from chat
|
|
82
|
+
- **MCP Support**: Extend with Model Context Protocol servers
|
|
83
|
+
- **Version control aware**: Understands your git context
|
|
84
|
+
|
|
85
|
+
### Productivity Features
|
|
86
|
+
- **Session management**: Switch between multiple conversations (`Ctrl+S`)
|
|
87
|
+
- **Custom commands**: Create reusable prompt templates (`Ctrl+K`)
|
|
88
|
+
- **Auto-compaction**: Intelligent context window management
|
|
89
|
+
- **SQLite persistence**: Full local history storage
|
|
90
|
+
- **Interactive sidebar**: Visualize file changes in real-time
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### Basic Workflow
|
|
95
|
+
|
|
96
|
+
1. **Start a conversation**: Launch `blu` and ask a question
|
|
97
|
+
2. **Let AI explore**: Blu can read files, search your codebase, and understand context
|
|
98
|
+
3. **Review changes**: See proposed file modifications in the sidebar
|
|
99
|
+
4. **Apply or reject**: Accept changes you want, skip the rest
|
|
100
|
+
|
|
101
|
+
## Documentation
|
|
102
|
+
|
|
103
|
+
Comprehensive documentation is available in the `docs/` directory:
|
|
104
|
+
|
|
105
|
+
- [Introduction](docs/introduction.md)
|
|
106
|
+
- [Getting Started](docs/getting-started.md)
|
|
107
|
+
- [Configuration](docs/configuration.md)
|
|
108
|
+
- [Key Bindings](docs/key-bindings.md)
|
|
109
|
+
- [Architecture](docs/architecture/overview.md)
|
|
110
|
+
|
|
111
|
+
### Detailed Features
|
|
112
|
+
- [AI Chat](docs/features/ai-chat.md)
|
|
113
|
+
- [File Operations](docs/features/file-operations.md)
|
|
114
|
+
- [LSP Intelligence](docs/features/lsp-and-intelligence.md)
|
|
115
|
+
- [MCP Servers](docs/features/mcp-servers.md)
|
|
116
|
+
- [Session Management](docs/features/session-management.md)
|
|
117
|
+
|
|
118
|
+
### Guides
|
|
119
|
+
- [Best Practices](docs/guides/best-practices.md)
|
|
120
|
+
- [Troubleshooting](docs/guides/troubleshooting.md)
|
|
121
|
+
|
|
122
|
+
## Keyboard Shortcuts
|
|
123
|
+
|
|
124
|
+
### Global Shortcuts
|
|
125
|
+
|
|
126
|
+
| Shortcut | Action |
|
|
127
|
+
| -------- | ------------------------------------------------------- |
|
|
128
|
+
| `Ctrl+C` | Quit application |
|
|
129
|
+
| `Ctrl+?` | Toggle help dialog |
|
|
130
|
+
| `?` | Toggle help dialog (when not in editing mode) |
|
|
131
|
+
| `Ctrl+L` | View logs |
|
|
132
|
+
| `Ctrl+S` | Switch session |
|
|
133
|
+
| `Ctrl+K` | Command dialog |
|
|
134
|
+
| `Ctrl+O` | Toggle model selection dialog |
|
|
135
|
+
| `Ctrl+P` | Toggle provider selection (API key configuration) |
|
|
136
|
+
| `Esc` | Close current overlay/dialog or return to previous mode |
|
|
137
|
+
|
|
138
|
+
### Chat Page Shortcuts
|
|
139
|
+
|
|
140
|
+
| Shortcut | Action |
|
|
141
|
+
| -------- | --------------------------------------- |
|
|
142
|
+
| `Ctrl+N` | Create new session |
|
|
143
|
+
| `Ctrl+X` | Cancel current operation/generation |
|
|
144
|
+
| `i` | Focus editor (when not in writing mode) |
|
|
145
|
+
| `Esc` | Exit writing mode and focus messages |
|
|
146
|
+
|
|
147
|
+
### Editor Shortcuts
|
|
148
|
+
|
|
149
|
+
| Shortcut | Action |
|
|
150
|
+
| ------------------- | ----------------------------------------- |
|
|
151
|
+
| `Ctrl+S` | Send message (when editor is focused) |
|
|
152
|
+
| `Enter` or `Ctrl+S` | Send message (when editor is not focused) |
|
|
153
|
+
| `Ctrl+E` | Open external editor |
|
|
154
|
+
| `Esc` | Blur editor and focus messages |
|
|
155
|
+
|
|
156
|
+
### Session Dialog Shortcuts
|
|
157
|
+
|
|
158
|
+
| Shortcut | Action |
|
|
159
|
+
| ---------- | ---------------- |
|
|
160
|
+
| `↑` or `k` | Previous session |
|
|
161
|
+
| `↓` or `j` | Next session |
|
|
162
|
+
| `Enter` | Select session |
|
|
163
|
+
| `Esc` | Close dialog |
|
|
164
|
+
|
|
165
|
+
### Model Dialog Shortcuts
|
|
166
|
+
|
|
167
|
+
| Shortcut | Action |
|
|
168
|
+
| ---------- | ----------------- |
|
|
169
|
+
| `↑` or `k` | Move up |
|
|
170
|
+
| `↓` or `j` | Move down |
|
|
171
|
+
| `←` or `h` | Previous provider (within model dialog) |
|
|
172
|
+
| `→` or `l` | Next provider (within model dialog) |
|
|
173
|
+
| `Esc` | Close dialog |
|
|
174
|
+
|
|
175
|
+
### Provider & API Key Dialog Shortcuts
|
|
176
|
+
|
|
177
|
+
| Shortcut | Action |
|
|
178
|
+
| -------- | -------------------- |
|
|
179
|
+
| `↑` / `↓` | Move up/down |
|
|
180
|
+
| `Enter` | Select provider |
|
|
181
|
+
| `Esc` | Close dialog |
|
|
182
|
+
| `Enter` | Save API key (input) |
|
|
183
|
+
|
|
184
|
+
### Permission Dialog Shortcuts
|
|
185
|
+
|
|
186
|
+
| Shortcut | Action |
|
|
187
|
+
| ----------------------- | ---------------------------- |
|
|
188
|
+
| `←` or `left` | Switch options left |
|
|
189
|
+
| `→` or `right` or `tab` | Switch options right |
|
|
190
|
+
| `Enter` or `space` | Confirm selection |
|
|
191
|
+
| `a` | Allow permission |
|
|
192
|
+
| `A` | Allow permission for session |
|
|
193
|
+
| `d` | Deny permission |
|
|
194
|
+
|
|
195
|
+
### Logs Page Shortcuts
|
|
196
|
+
|
|
197
|
+
| Shortcut | Action |
|
|
198
|
+
| ------------------ | ------------------- |
|
|
199
|
+
| `Backspace` or `q` | Return to chat page |
|
|
200
|
+
|
|
201
|
+
## Configuration
|
|
202
|
+
|
|
203
|
+
Place `.blu.json` in your home directory (`~/.blu.json`) or project root:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"agents": {
|
|
208
|
+
"coder": {
|
|
209
|
+
"model": "claude-3.7-sonnet",
|
|
210
|
+
"maxTokens": 8192,
|
|
211
|
+
"temperature": 0.7
|
|
212
|
+
},
|
|
213
|
+
"summarizer": {
|
|
214
|
+
"model": "gpt-4o-mini",
|
|
215
|
+
"maxTokens": 2048
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
"autoCompact": true,
|
|
219
|
+
"mcpServers": {
|
|
220
|
+
"filesystem": {
|
|
221
|
+
"command": "npx",
|
|
222
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Supported Models
|
|
229
|
+
|
|
230
|
+
**Anthropic (Claude):**
|
|
231
|
+
- `claude-3.7-sonnet` - Recommended for coding (supports reasoning)
|
|
232
|
+
- `claude-3.5-sonnet` - Fast and highly capable
|
|
233
|
+
- `claude-4.6-opus` - Next-gen flagship capability
|
|
234
|
+
|
|
235
|
+
**OpenAI:**
|
|
236
|
+
- `o3-ultra` - Latest reasoning flagship
|
|
237
|
+
- `gpt-5.3-codex` - Specialized for agentic coding
|
|
238
|
+
- `gpt-4o` - Balanced speed and intelligence
|
|
239
|
+
|
|
240
|
+
**Google:**
|
|
241
|
+
- `gemini-3-deep-think` - Advanced reasoning and engineering
|
|
242
|
+
- `gemini-2.0-flash` - High-speed intelligence
|
|
243
|
+
- `gemini-1.5-pro` - Large context window
|
|
244
|
+
|
|
245
|
+
**DeepSeek:**
|
|
246
|
+
- `deepseek-v3` - High performance open-weights model
|
|
247
|
+
- `deepseek-r1` - Reasoning focused model
|
|
248
|
+
|
|
249
|
+
### Environment Variables
|
|
250
|
+
|
|
251
|
+
| Variable | Purpose |
|
|
252
|
+
|----------|---------|
|
|
253
|
+
| `ANTHROPIC_API_KEY` | Claude API access |
|
|
254
|
+
| `OPENAI_API_KEY` | GPT-4 API access |
|
|
255
|
+
| `GEMINI_API_KEY` | Gemini API access |
|
|
256
|
+
| `BLU_DEBUG=true` | Enable debug logging |
|
|
257
|
+
| `BLU_CONFIG=/path/to/.blu.json` | Custom config location |
|
|
258
|
+
|
|
259
|
+
## Troubleshooting
|
|
260
|
+
|
|
261
|
+
**Blu won't start**
|
|
262
|
+
- Check your API keys are set
|
|
263
|
+
- Verify Go 1.21+ is installed
|
|
264
|
+
- Try `blu --debug` for detailed logs
|
|
265
|
+
|
|
266
|
+
**AI can't see my files**
|
|
267
|
+
- Ensure you're running Blu from your project directory
|
|
268
|
+
- Check file permissions
|
|
269
|
+
- Verify paths in error messages
|
|
270
|
+
|
|
271
|
+
**Context window errors**
|
|
272
|
+
- Enable `autoCompact` in config
|
|
273
|
+
- Start a new session for fresh context
|
|
274
|
+
- Use more concise prompts
|
|
275
|
+
|
|
276
|
+
## Building from Source
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
# Clone the repository
|
|
280
|
+
git clone https://github.com/Get-Blu/blu-code.git
|
|
281
|
+
cd blu-code
|
|
282
|
+
|
|
283
|
+
# Install dependencies
|
|
284
|
+
go mod download
|
|
285
|
+
|
|
286
|
+
# Build
|
|
287
|
+
go build -o blu
|
|
288
|
+
|
|
289
|
+
# Run tests
|
|
290
|
+
go test ./...
|
|
291
|
+
|
|
292
|
+
# Install globally
|
|
293
|
+
sudo mv blu /usr/local/bin/
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Contributing
|
|
297
|
+
|
|
298
|
+
Contributions are welcome! Please feel free to submit issues or pull requests.
|
|
299
|
+
|
|
300
|
+
1. Fork the repository
|
|
301
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
302
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
303
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
304
|
+
5. Open a Pull Request
|
|
305
|
+
|
|
306
|
+
## Credits
|
|
307
|
+
|
|
308
|
+
Blu builds on the excellent work of:
|
|
309
|
+
|
|
310
|
+
- **[OpenCode](https://github.com/opencode-ai/opencode)** - The foundation Blu is built upon
|
|
311
|
+
- **[@adamdottv](https://github.com/adamdottv)** - Original OpenCode design and architecture
|
|
312
|
+
- **[@isaacphi](https://github.com/isaacphi)** - LSP integration via `mcp-language-server`
|
|
313
|
+
- **[Bubble Tea](https://github.com/charmbracelet/bubbletea)** - Excellent TUI framework
|
|
314
|
+
|
|
315
|
+
## License
|
|
316
|
+
|
|
317
|
+
Distributed under the **MIT License**. See `LICENSE` for more information.
|
|
318
|
+
|
|
319
319
|
**Created by [Garv Agnihotri](https://github.com/Get-Blu)**
|
package/bin/cli.js
CHANGED
|
@@ -1,24 +1,45 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { spawn } = require('child_process');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
|
|
8
|
+
const isWindows = process.platform === 'win32';
|
|
9
|
+
const binaryName = isWindows ? 'blu.exe' : 'blu';
|
|
10
|
+
const binaryPath = path.join(__dirname, binaryName);
|
|
11
|
+
|
|
12
|
+
// Check if the binary was downloaded by the postinstall script
|
|
13
|
+
if (!fs.existsSync(binaryPath)) {
|
|
14
|
+
console.error(
|
|
15
|
+
'\n Blu binary not found at: ' + binaryPath + '\n' +
|
|
16
|
+
' Try reinstalling: npm install -g @get-blu/blu-code\n' +
|
|
17
|
+
' Or download manually: https://github.com/Get-Blu/blu-code/releases\n'
|
|
18
|
+
);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const child = spawn(binaryPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
23
|
+
|
|
24
|
+
child.on('exit', (code, signal) => {
|
|
25
|
+
if (signal) {
|
|
26
|
+
process.kill(process.pid, signal);
|
|
27
|
+
} else {
|
|
28
|
+
process.exit(code ?? 0);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
child.on('error', (err) => {
|
|
33
|
+
if (err.code === 'EACCES') {
|
|
34
|
+
console.error('\n Permission denied. Fixing permissions...');
|
|
35
|
+
try {
|
|
36
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
37
|
+
console.error(' Fixed! Please re-run your command.\n');
|
|
38
|
+
} catch (_) {
|
|
39
|
+
console.error(` Could not fix automatically. Run: chmod +x ${binaryPath}\n`);
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
console.error(`\n Failed to launch Blu: ${err.message}\n`);
|
|
43
|
+
}
|
|
44
|
+
process.exit(1);
|
|
45
|
+
});
|
package/package.json
CHANGED
|
@@ -1,26 +1,47 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@get-blu/blu-code",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Terminal-based AI assistant for software development",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@get-blu/blu-code",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Terminal-based AI assistant for software development",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"cli",
|
|
8
|
+
"coding",
|
|
9
|
+
"assistant",
|
|
10
|
+
"terminal",
|
|
11
|
+
"llm"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/Get-Blu/blu-code",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/Get-Blu/blu-code/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/Get-Blu/blu-code.git"
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"blu": "./bin/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"postinstall": "node scripts/install-npm.js"
|
|
26
|
+
},
|
|
27
|
+
"author": "Get-Blu",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=14.0.0"
|
|
31
|
+
},
|
|
32
|
+
"os": [
|
|
33
|
+
"linux",
|
|
34
|
+
"darwin",
|
|
35
|
+
"win32"
|
|
36
|
+
],
|
|
37
|
+
"cpu": [
|
|
38
|
+
"x64",
|
|
39
|
+
"arm64"
|
|
40
|
+
],
|
|
41
|
+
"files": [
|
|
42
|
+
"bin/cli.js",
|
|
43
|
+
"scripts/install-npm.js",
|
|
44
|
+
"README.md",
|
|
45
|
+
"LICENSE"
|
|
46
|
+
]
|
|
47
|
+
}
|
package/scripts/install-npm.js
CHANGED
|
@@ -1,94 +1,139 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
//
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} else if (
|
|
30
|
-
|
|
31
|
-
} else {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const https = require('https');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
// Try to get version from package.json
|
|
11
|
+
let version;
|
|
12
|
+
try {
|
|
13
|
+
const pkg = require('../package.json');
|
|
14
|
+
version = pkg.version;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
console.error('Could not read package.json:', e.message);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const platform = process.platform;
|
|
21
|
+
const arch = process.arch;
|
|
22
|
+
|
|
23
|
+
// Map Node OS to GOOS
|
|
24
|
+
let goos = '';
|
|
25
|
+
let ext = '';
|
|
26
|
+
if (platform === 'win32') {
|
|
27
|
+
goos = 'windows';
|
|
28
|
+
ext = '.exe';
|
|
29
|
+
} else if (platform === 'darwin') {
|
|
30
|
+
goos = 'darwin';
|
|
31
|
+
} else if (platform === 'linux') {
|
|
32
|
+
goos = 'linux';
|
|
33
|
+
} else {
|
|
34
|
+
console.error(`Unsupported platform: ${platform}`);
|
|
35
|
+
console.error('Please download the binary manually from:');
|
|
36
|
+
console.error(` https://github.com/Get-Blu/blu-code/releases`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Map Node arch to GOARCH
|
|
41
|
+
let goarch = '';
|
|
42
|
+
if (arch === 'x64') {
|
|
43
|
+
goarch = 'amd64';
|
|
44
|
+
} else if (arch === 'arm64') {
|
|
45
|
+
goarch = 'arm64';
|
|
46
|
+
} else {
|
|
47
|
+
console.error(`Unsupported architecture: ${arch}`);
|
|
48
|
+
console.error('Please download the binary manually from:');
|
|
49
|
+
console.error(` https://github.com/Get-Blu/blu-code/releases`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Binary name matches GoReleaser output: blu-linux-amd64, blu-windows-amd64.exe, etc.
|
|
54
|
+
const binName = `blu-${goos}-${goarch}${ext}`;
|
|
55
|
+
const downloadUrl = `https://github.com/Get-Blu/blu-code/releases/download/v${version}/${binName}`;
|
|
56
|
+
|
|
57
|
+
const destDir = path.join(__dirname, '..', 'bin');
|
|
58
|
+
if (!fs.existsSync(destDir)) {
|
|
59
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const destFile = path.join(destDir, `blu${ext}`);
|
|
63
|
+
|
|
64
|
+
console.log(`\nDownloading Blu CLI v${version} for ${goos}/${goarch}...`);
|
|
65
|
+
console.log(`URL: ${downloadUrl}\n`);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Follows redirects and returns the final URL.
|
|
69
|
+
*/
|
|
70
|
+
function resolveRedirect(url, maxRedirects = 10) {
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
if (maxRedirects === 0) return reject(new Error('Too many redirects'));
|
|
73
|
+
https.get(url, (res) => {
|
|
74
|
+
res.resume(); // Drain the response body
|
|
75
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
76
|
+
return resolve(resolveRedirect(res.headers.location, maxRedirects - 1));
|
|
77
|
+
}
|
|
78
|
+
if (res.statusCode !== 200) {
|
|
79
|
+
return reject(
|
|
80
|
+
new Error(
|
|
81
|
+
`HTTP ${res.statusCode} — binary not found.\n` +
|
|
82
|
+
`Make sure release v${version} exists at:\n` +
|
|
83
|
+
` https://github.com/Get-Blu/blu-code/releases/tag/v${version}`
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
resolve(url);
|
|
88
|
+
}).on('error', reject);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Downloads a URL to a local file (no redirects — call resolveRedirect first).
|
|
94
|
+
*/
|
|
95
|
+
function downloadDirect(url, dest) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
const file = fs.createWriteStream(dest);
|
|
98
|
+
https.get(url, (res) => {
|
|
99
|
+
res.pipe(file);
|
|
100
|
+
file.on('finish', () => {
|
|
101
|
+
file.close();
|
|
102
|
+
const stats = fs.statSync(dest);
|
|
103
|
+
if (stats.size === 0) {
|
|
104
|
+
fs.unlinkSync(dest);
|
|
105
|
+
return reject(new Error('Downloaded binary is empty — the release asset may be missing.'));
|
|
106
|
+
}
|
|
107
|
+
resolve();
|
|
108
|
+
});
|
|
109
|
+
}).on('error', (err) => {
|
|
110
|
+
file.close();
|
|
111
|
+
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
112
|
+
reject(err);
|
|
113
|
+
});
|
|
114
|
+
file.on('error', (err) => {
|
|
115
|
+
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
116
|
+
reject(err);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
resolveRedirect(downloadUrl)
|
|
123
|
+
.then((finalUrl) => downloadDirect(finalUrl, destFile))
|
|
124
|
+
.then(() => {
|
|
125
|
+
// Make executable on Unix
|
|
126
|
+
if (platform !== 'win32') {
|
|
127
|
+
fs.chmodSync(destFile, 0o755);
|
|
128
|
+
}
|
|
129
|
+
console.log(`✅ Blu CLI installed to: ${destFile}`);
|
|
130
|
+
console.log(' Run "blu --version" to verify the installation.\n');
|
|
131
|
+
})
|
|
132
|
+
.catch((err) => {
|
|
133
|
+
console.error(`\n❌ Installation failed: ${err.message}\n`);
|
|
134
|
+
console.error('Manual install options:');
|
|
135
|
+
console.error(' • Download from: https://github.com/Get-Blu/blu-code/releases');
|
|
136
|
+
console.error(` • Homebrew (macOS/Linux): brew install Get-Blu/tap/blu`);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
});
|
|
139
|
+
|