Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ jobs:

- name: Lint
run: bun run lint

- name: Unit tests
run: bun run test

- name: Build project
run: bun run build
Expand Down
59 changes: 47 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,15 @@ curl -fsSL https://raw.githubusercontent.com/bernoussama/lazyshell/main/install
```

2. **Interactive Setup**: Choose from supported providers:
- **Groq** - Fast LLaMA models with great performance
- **Groq** - Fast GPT-OSS models with great performance
- **Google Gemini** - Google's latest AI models
- **OpenRouter** - Access to multiple models including free options
- **Anthropic Claude** - Powerful reasoning capabilities
- **OpenAI** - GPT models including GPT-4
- **Ollama** - Local models (no API key required)
- **Mistral** - Mistral AI models for code generation
- **LMStudio** - Local models via LMStudio (experimental, no API key required)
- **Bundled** - Optional ~469 MB Qwen2.5-Coder 0.5B GGUF (downloaded on Yes, no Ollama required)

3. **Automatic Configuration**: Your preferences are saved to `~/.lazyshell/config.json` and used for future runs.

Expand All @@ -108,15 +109,22 @@ curl -fsSL https://raw.githubusercontent.com/bernoussama/lazyshell/main/install

On first run, LazyShell will guide you through:

1. Selecting your preferred AI provider
2. Entering your API key (if required)
3. Automatically saving the configuration
1. Optionally downloading the bundled local model (~469 MB)
2. Selecting your preferred AI provider
3. Entering your API key (if required)
4. Automatically saving the configuration

Skip the download prompt with `--skip-bundled-model` or `LSH_SKIP_BUNDLED_MODEL=1`. The choice is saved; use `lazyshell model install` or `lazyshell model remove` later.

### Configuration Management

```bash
# Open configuration UI
lazyshell config

# Bundled local model
lazyshell model install
lazyshell model remove
```

### Manual Environment Variables (Optional)
Expand All @@ -135,7 +143,7 @@ export ANTHROPIC_API_KEY='your-api-key-here'
export OPENAI_API_KEY='your-api-key-here'
```

> **Note**: Ollama and LMStudio don't require API keys as they run models locally.
> **Note**: Ollama, LM Studio, and the bundled local model don't require API keys.

### Configuration File Location

Expand All @@ -146,14 +154,34 @@ export OPENAI_API_KEY='your-api-key-here'

| Provider | Models | API Key Required | Notes |
|----------|--------|------------------|-------|
| **Groq** | LLaMA 3.3 70B | Yes | Fast inference, excellent performance |
| **Groq** | GPT-OSS 120B | Yes | Fast inference, excellent performance |
| **Google Gemini** | Gemini 2.0 Flash Lite | Yes | Latest Google AI models |
| **OpenRouter** | Multiple models | Yes | Includes free tier options |
| **Anthropic** | Claude 3.5 Haiku | Yes | Advanced reasoning capabilities |
| **OpenAI** | GPT-4o Mini | Yes | Industry standard models |
| **Ollama** | Local models | No | Run models locally |
| **Ollama** | Curated local catalog (see below) | No | Run models locally |
| **Mistral** | Devstral Small | No | Code-optimized models |
| **LMStudio** | Local models | No | **Experimental** - Local models via LMStudio |
| **LMStudio** | Curated local catalog | No | **Experimental** - Local models via LMStudio |
| **Bundled** | Qwen2.5-Coder 0.5B Instruct Q4_K_M | No | Optional ~469 MB GGUF, Apache-2.0 |

## Local models

Ollama and LM Studio stay first-class. When you pick either provider, LazyShell offers a catalog plus Custom…:

- CPU / small: `qwen2.5-coder:0.5b`, `qwen2.5-coder:1.5b` (default), `hf.co/AryaYT/nl2shell-0.8b`
- GPU: `qwen2.5-coder:3b`, `qwen2.5-coder:7b`, `westenfelder/NL2SH`

Command-only NL2SH fine-tunes may skip explanations and ignore OS/package-manager context. Prefer Qwen2.5-Coder instruct models when you want LazyShell’s full system prompt.

### Bundled model (opt-in / opt-out)

The npm package does **not** contain weights. On first setup you can download [Qwen2.5-Coder-0.5B-Instruct Q4_K_M](https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF) (~469 MB, Apache-2.0) to `~/.lazyshell/models/`. The file is checksum-verified.

- **Yes** on first run: download, then use the bundled provider if Ollama is not running and no cloud API key is set.
- **No**: remembered as declined; you will not be asked again until `lazyshell config` or `lazyshell model install`.
- **Skip**: `lazyshell --skip-bundled-model "..."` or `LSH_SKIP_BUNDLED_MODEL=1`.

If the configured provider is Ollama but Ollama is down and the bundled model is installed, LazyShell starts a local `llama-server` (downloaded once for your OS) and uses that instead.

## Usage Examples

Expand Down Expand Up @@ -280,10 +308,10 @@ bun dist/bench_models.mjs

### Available Models

- `llama-3.3-70b-versatile` (Groq)
- `openai/gpt-oss-120b` (Groq)
- `gemini-2.0-flash-lite` (Google)
- `devstral-small-2505` (Mistral)
- `ollama3.2` (Ollama)
- `qwen2.5-coder:1.5b` (Ollama)
- `or-devstral` (OpenRouter)

## CI Evaluations
Expand All @@ -308,6 +336,9 @@ LazyShell includes automated quality assessments that run in CI to ensure consis
```bash
# Run CI evaluations locally
bun run eval:ci

# Evaluate the bundled local model (downloads GGUF on first run)
bun run eval:bundled
```

### Custom Evaluation Scripts
Expand Down Expand Up @@ -383,12 +414,15 @@ src/
├── bench_models.ts # Model benchmarking script
├── test-ai-lib.ts # AI library testing script
├── commands/
│ └── config.ts # Configuration UI command
│ ├── config.ts # Configuration UI command
│ └── model.ts # Bundled model install/remove
├── helpers/
│ ├── index.ts # Helper exports
│ └── package-manager.ts # System package manager detection
└── lib/
├── ai.ts # AI provider integrations and command generation
├── local-models.ts # Ollama/LM Studio catalog and bundled GGUF pin
├── bundled-model.ts # Bundled download, checksum, llama-server
├── config.ts # Configuration management
├── eval.ts # Evaluation framework
├── basic.eval.ts # Basic evaluation examples
Expand Down Expand Up @@ -421,7 +455,8 @@ LazyShell will automatically fall back to environment variables if the config fi
### Common Issues

- **Clipboard not working**: Ensure your system supports clipboard operations
- **Model timeout**: Some models (especially Ollama) may take longer to respond
- **Model timeout**: Some models (especially Ollama or the first bundled-model start) may take longer to respond
- **Bundled model missing**: Run `lazyshell model install` or pick Ollama/LM Studio/cloud in `lazyshell config`
- **Rate limiting**: Built-in retry logic handles temporary rate limits
- **Command not found**: Make sure the package is properly installed globally

Expand Down
7 changes: 5 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ export default [
afterEach: 'readonly',
beforeAll: 'readonly',
afterAll: 'readonly',
Bun: 'readonly',
},
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-floating-promises': 'off',
},
},

Expand Down
72 changes: 72 additions & 0 deletions eval-results/eval-bundled-1788481301832.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"model": "qwen2.5-coder-0.5b-instruct-q4_k_m",
"license": "Apache-2.0",
"generatedAt": "2026-09-04T00:21:41.832Z",
"name": "Bundled Model Command Generation",
"totalTests": 6,
"averageScores": {
"ExpectedToken": 0.6666666666666666
},
"results": [
{
"testCase": {
"input": "list all files in the current directory, including hidden ones, in long format",
"expected": "ls"
},
"output": "ls -la",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "show me the current working directory",
"expected": "pwd"
},
"output": "```\ncd /workspace\n```",
"scores": {
"ExpectedToken": 0
}
},
{
"testCase": {
"input": "make a new folder called test-project",
"expected": "mkdir"
},
"output": "```bash\nsudo mkdir test-project\n```",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "find all javascript files recursively",
"expected": "find"
},
"output": "To find all JavaScript files recursively in a Linux system using the `find` command, you can use the following command:\n\n```bash\nfind /workspace -type f -name \"*.js\"\n```\n\nThis command will search the `/workspace` directory and its subdirectories for all files with the `.js` extension. The `-type f` option specifies that we are looking for files, and `-name \"*.js\"` specifies that we are looking for files with the `.js` extension. The `-name` option is used to specify the file name, and the `*` wildcard matches any sequence of characters.\n\nThis command will return the full path of each JavaScript file found in the specified directory and its subdirectories.",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "show system information",
"expected": "uname"
},
"output": "sudo apt show systeminformation",
"scores": {
"ExpectedToken": 0
}
},
{
"testCase": {
"input": "check disk usage",
"expected": "df"
},
"output": "sudo df -h | grep -E '\\d+%' | awk '{print $1}'",
"scores": {
"ExpectedToken": 1
}
}
]
}
72 changes: 72 additions & 0 deletions eval-results/eval-bundled-1788483267742.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"model": "qwen2.5-coder-0.5b-instruct-q4_k_m",
"license": "Apache-2.0",
"generatedAt": "2026-09-04T00:54:27.742Z",
"name": "Bundled Model Command Generation",
"totalTests": 6,
"averageScores": {
"ExpectedToken": 1
},
"results": [
{
"testCase": {
"input": "list all files in the current directory, including hidden ones, in long format",
"expected": "ls"
},
"output": "ls -la",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "show me the current working directory",
"expected": "pwd"
},
"output": "pwd",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "make a new folder called test-project",
"expected": "mkdir"
},
"output": "mkdir test-project",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "find all javascript files recursively",
"expected": "find"
},
"output": "find . -type f -name '*.js'",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "show system information",
"expected": "uname"
},
"output": "uname -a",
"scores": {
"ExpectedToken": 1
}
},
{
"testCase": {
"input": "check disk usage",
"expected": "df"
},
"output": "df -h",
"scores": {
"ExpectedToken": 1
}
}
]
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"release:patch": "bun run build && npm version patch && npm run build && npm publish && git push --follow-tags",
"prerelease": "bun run build && npm version prerelease && npm run build && npm publish && git push --follow-tags",
"eval:ci": "bun src/lib/ci-eval.ts",
"eval:bundled": "bun src/lib/bundled.eval.ts",
"test": "bun test src/lib/bundled-model.test.ts src/lib/command-output.test.ts",
"prepare": "husky",
"compile": "bun build --compile --minify --sourcemap src/index.ts --outfile bin/lsh"
},
Expand All @@ -42,6 +44,7 @@
"@ai-sdk/openai-compatible": "^0.2.14",
"@eslint/js": "^9.30.0",
"@jest/types": "^29.6.3",
"@types/bun": "^1.4.0",
"@types/node": "^22.15.34",
"@typescript-eslint/eslint-plugin": "^8.35.1",
"@typescript-eslint/parser": "^8.35.1",
Expand Down
Loading
Loading