Compare commits

..

2 Commits

Author SHA1 Message Date
Elephant Lumps 8a78148c10 changeset 2025-05-22 11:26:29 -07:00
Elephant Lumps c5932addea put protos back in gitignore 2025-05-22 11:25:56 -07:00
721 changed files with 64663 additions and 74664 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Fix Global Rules directory documentation for Linux/WSL systems
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
DeepSeek R1 0528 support under Hugging Face
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
remove duplicate tool registration for claude4-experimental
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": minor
---
Add Huawei Cloud MaaS Provider
+5
View File
@@ -0,0 +1,5 @@
---
"claude-dev": patch
---
Put protos back in .gitignore
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Fixed token counting when using VSCode LM API provider
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
fix: only focus on editor panel that is visible and active to stop input field stealing issue
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": minor
---
Add Cerebras Qwen 3 235B instruct
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
trim input value for URL fields
+1 -2
View File
@@ -164,7 +164,6 @@ Key providers include:
- **OpenRouter**: Meta-provider supporting multiple model providers
- **AWS Bedrock**: Integration with Amazon's AI services
- **Gemini**: Google's AI models
- **Cerebras**: High-performance inference with Llama, Qwen, and DeepSeek models
- **Ollama**: Local model hosting
- **LM Studio**: Local model hosting
- **VSCode LM**: VSCode's built-in language models
@@ -716,7 +715,7 @@ The Controller class manages MCP servers through the McpHub service:
class Controller {
mcpHub?: McpHub
constructor(context: vscode.ExtensionContext, webviewProvider: WebviewProvider) {
constructor(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel, webviewProvider: WebviewProvider) {
this.mcpHub = new McpHub(this)
}
-89
View File
@@ -1,89 +0,0 @@
# Cline Protobuf Development Guide
This guide outlines how to add new gRPC endpoints for communication between the webview (frontend) and the extension host (backend).
## Overview
Cline uses [Protobuf](https://protobuf.dev/) to define a strongly-typed API, ensuring efficient and type-safe communication. All definitions are in the `/proto` directory. The compiler and plugins are included as project dependencies, so no manual installation is needed.
## Key Concepts & Best Practices
- **File Structure**: Each feature domain should have its own `.proto` file (e.g., `account.proto`, `task.proto`).
- **Message Design**:
- For simple, single-value data, use the shared types in `proto/common.proto` (e.g., `StringRequest`, `Empty`, `Int64Request`). This promotes consistency.
- For complex data structures, define custom messages within the feature's `.proto` file (see `task.proto` for examples like `NewTaskRequest`).
- **Naming Conventions**:
- Services: `PascalCaseService` (e.g., `AccountService`).
- RPCs: `camelCase` (e.g., `accountEmailIdentified`).
- Messages: `PascalCase` (e.g., `StringRequest`).
- **Streaming**: For server-to-client streaming, use the `stream` keyword on the response type. See `subscribeToAuthCallback` in `account.proto` for an example.
---
## 4-Step Development Workflow
Heres how to add a new RPC, using `scrollToSettings` as an example.
### 1. Define the RPC in a `.proto` File
Add your service method to the appropriate file in the `proto/` directory.
**File: `proto/ui.proto`**
```proto
service UiService {
// ... other RPCs
// Scrolls to a specific settings section in the settings view
rpc scrollToSettings(StringRequest) returns (KeyValuePair);
}
```
Here, we use the common `StringRequest` and `KeyValuePair` types.
### 2. Compile Definitions
After editing a `.proto` file, regenerate the TypeScript code. From the project root, run:
```bash
npm run protos
```
This command compiles all `.proto` files and outputs the generated code to `src/generated/` and `src/shared/`. Do not edit these generated files manually.
### 3. Implement the Backend Handler
Create the RPC implementation in the backend. Handlers are located in `src/core/controller/[service-name]/`.
**File: `src/core/controller/ui/scrollToSettings.ts`**
```typescript
import { Controller } from ".."
import { StringRequest, KeyValuePair } from "../../../shared/proto/common"
/**
* Executes a scroll to settings action
* @param controller The controller instance
* @param request The request containing the ID of the settings section to scroll to
* @returns KeyValuePair with action and value fields for the UI to process
*/
export async function scrollToSettings(controller: Controller, request: StringRequest): Promise<KeyValuePair> {
return KeyValuePair.create({
key: "scrollToSettings",
value: request.value || "",
})
}
```
### 4. Call the RPC from the Webview
Call the new RPC from a React component in `webview-ui/`. The generated client makes this simple.
**File: `webview-ui/src/components/browser/BrowserSettingsMenu.tsx`** (Example)
```tsx
import { UiServiceClient } from "../../../services/grpc"
import { StringRequest } from "../../../../shared/proto/common"
// ... inside a React component
const handleMenuClick = async () => {
try {
await UiServiceClient.scrollToSettings(StringRequest.create({ value: "browser" }))
} catch (error) {
console.error("Error scrolling to browser settings:", error)
}
}
```
@@ -1,75 +0,0 @@
# Git Diff Analysis Workflow
## Objective
Analyze the current branch's changes against main to provide informed insights and context for development decisions.
## Step 1: Gather Git Information
<important>Do not return any text or conversation other than what is necessary to run these commands</important>
**First, check the expected output size:**
```shell
(git branch --show-current && echo "=== STATUS ===" && git status --porcelain | cat && echo "=== COMMIT MESSAGES ===" && git log main..HEAD --oneline | cat && echo "=== CHANGED FILES ===" && git diff main --name-only | cat && echo "=== FULL DIFF ===" && git diff main | cat) | wc -l
```
**If the expected line count is greater than 500 lines, use the file-based approach:**
```shell
git branch --show-current > cline-git-analysis.temp && echo "=== STATUS ===" >> cline-git-analysis.temp && git status --porcelain >> cline-git-analysis.temp && echo "=== COMMIT MESSAGES ===" >> cline-git-analysis.temp && git log main..HEAD --oneline >> cline-git-analysis.temp && echo "=== CHANGED FILES ===" >> cline-git-analysis.temp && git diff main --name-only >> cline-git-analysis.temp && echo "=== FULL DIFF ===" >> cline-git-analysis.temp && git diff main >> cline-git-analysis.temp
```
Then, read the file using the read_file tool. After you have read the file but before you proceed with subsequent steps, delete it:
```shell
rm cline-git-analysis.temp
```
**If the expected line count is 500 lines or fewer, use the direct approach:**
```shell
git branch --show-current && echo "=== STATUS ===" && git status --porcelain | cat && echo "=== COMMIT MESSAGES ===" && git log main..HEAD --oneline | cat && echo "=== CHANGED FILES ===" && git diff main --name-only | cat && echo "=== FULL DIFF ===" && git diff main | cat
```
<important>If using the direct approach, pipe outputs through `cat` to avoid interactive terminals. If the user's shell is not bash/zsh, adjust the command and chaining
syntax accordingly.</important>
## Step 2: Silent, Structured Analysis Phase
- Analyze all git output without providing commentary or narration
- Read the full diff to understand the scope and nature of changes
- Identify patterns, architectural modifications, or potential impacts
- Use `read_file` to examine any related files providing additional context on the changes you have observed
## Step 3: Context Gathering
- Analyze related code without providing commentary or narration
- Read relevant related source files if needed for complete understanding
- Check dependencies, imports, or cross-references spanning the changes
- Understand the broader codebase context around modifications
- This additional context gathering should include related backend code, as well as related ui/frontend code
- You will typically need to analyze at least several files, potentially many, in order to fully complete this step
- You should not continue reading additional context if you have exhausted more than 60% of your available context window
- If you have exhausted less than 40% of your context window, you should continue reviewing additional context
## Step 4: Ready for User Interaction
**Only after completing the full analysis:**
- Engage with the user based on comprehensive understanding
- Provide insights about specific modifications and their impacts
- If you are certain they exist, note potential breaking changes or compatibility issues
- Answer questions with informed context from the complete change set and context gathering
- If the user has not provided a question, or the question is insufficient to provide a quality response, ask brief (one sentence) clarifying questions.
- Only offer recommendations if they are applicable to the user's request and relevant to the changes that you have observed
## Key Rules
- **No prose or conversation during git research phase**
- **No prose or conversation during context gathering phase**
- **Complete all analysis before any user interaction**
- **Use gathered information for all subsequent questions and insights**
- **Focus on understanding the complete picture before discussing**
## Optional: Additional Analysis Commands
For deeper investigation when needed:
```shell
# Detailed commit history with author info
git log main..HEAD --format="%h %s (%an)" | cat
# Change statistics
git diff main --stat | cat
# Specific file type changes
git diff main --name-only | grep -E '\.(ts|js|tsx|jsx|py|md)$' | cat
@@ -1,392 +0,0 @@
# General writing guide
# How I want you to write
I'm gonna write something technical.
It's often less about the nitty-gritty details of the tech stuff and more about learning something new or getting a solution handed to me on a silver platter.
Look, when I read, I want something out of it. So when I write, I gotta remember that my readers want something too. This whole piece? It's about cluing in anyone who writes for me, or wants me to write for them, on how I see this whole writing product thing.
I'm gonna lay out a checklist of stuff I'd like to have. It'll make the whole writing gig a bit smoother, you know?
## Crafting Compelling Titles
I often come across titles like "How to do X with Y,Z technology." These don't excite me because X or Y are usually unfamiliar unless they're already well-known. Its rarely the dream to use X unless X is the dream.
My dream isnt to use instructor, its to do something valueble with the data it extracts
An effective title should:
- Evoke an emotional response
- Highlight someone's goal
- Offer a dream or aspiration
- Challenge or comment on a belief
- Address someone's problems
I believe it's more impactful to write about specific problems. If this approach works, you can replicate it across various scenarios rather than staying too general.
- Time management for everyone can be a 15$ ebook
- Time management for executives is a 2000$ workshop
Aim for titles that answer questions you think everyone is asking, or address thoughts people have but can't quite articulate.
Instead of "How I do something" or "How to do something," frame it from the reader's perspective with "How you can do something." This makes the title more engaging. Just make sure the difference is advisory if the content is subjective. “How I made a million dollars” might be more reasonable than “How to make a million dollars” since you are the subject and the goal might be to share your story in hopes of helping others.
This approach ultimately trains the reader to have a stronger emotional connection to your content.
- "How I do X"
- "How You Can do X"
Between these two titles, it's obvious which one resonates more emotionally.
You can take it further by adding specific conditions. For instance, you could target a particular audience or set a timeframe:
- How to set up Braintrust
- How to set up Braintrust in 5 minutes
## NO adjectiives
I want you to almost always avoid adjectives and try to use evidence instead. Instead of saying "production ready," you can write something like "scaling this to 100 servers or 1 million documents per second." Numbers like that will tell you exactly what the specificity of your product is. If you have to use adjectives rather than evidence, you are probably making something up.
There's no reason to say something like "blazingly fast" unless those things are already known phrases.
Instead, say "200 times faster" or "30% faster." A 30% improvement in recommendation system speed is insane.
There's a 200 times performance improvement because we went from one programming language to another. It's just something that's a little bit more expected and understandable.
Another test that I really like using recently is tracking whether or not the statements you make can be:
- Visualized
- Proven false
- Said only by you
If you can nail all three, the claim you make will be more likely to resonate with an audience because only you can say it.
Earlier this year, I had an example where I embedded all of Wikipedia in 17 minutes with 20 bucks, and it got half a million views. All we posted was a video of me kicking off the job, and then you can see all the log lines go through. You see the number of containers go from 1 out of 50 to 50 out of 50.
It was easy to visualize and could have been proven false by being unreproducible. Lastly, Modal is the only company that could do that in such an effortless way, which made it unique.
## Keep It Digestible
- Aim for 5-minute reads
- Write at a Grade 10 reading level
- Break up long paragraphs
- Use headers and bullet points
## Make It Scannable
- Bold key points
- Use subheadings every 3-4 paragraphs
- Include plenty of white space
- Add relevant examples
This structure works whether you're writing a tweet thread or a full blog post. The key is making complex ideas accessible.
# Guide to Writing Cline Documentation
## Some general principles for explaining features
If you're talking about a feature, it's helpful to start with a human-readable explanations that cover what the feature is in simple terms. Skip jargon and explain it like you're talking to someone who's never seen it before. This sets the foundation for everything that follows.
Combine location and usage into one flowing section. Tell users exactly where to find the feature and how to use it, but weave the instructions into natural prose with a good balance of bullet points, numbered lists, code examples (if applicable), mintlify components, and headers/subheaders. Users shouldn't have to jump between separate "where is it" and "how do I use it" sections.
Show the feature in action with real examples like actual files, workflows, or code. Users need to see concrete implementations, not just abstract descriptions. This is where understanding turns into practical knowledge.
When talking about a feature, include an inspiration section that sparks imagination. This section pushes people from understanding to action by showing them what becomes possible when they use this feature creatively. It's what separates good documentation from great documentation.
## Writing Principles That Actually Work
### Write for Action, Not Just Understanding
Documentation should motivate users to try things. Instead of just explaining how something works, focus on what users can accomplish with it. The inspiration section is crucial - it's what transforms passive readers into active users.
### Create a Natural Story Flow
It should feel like a conversation that naturally progresses from "what is this?" to "how do I use it?" to "here's a real example" to "imagine what you could do with this."
### Show Real Examples, Not Toy Demos
Provide actual workflow files, real code snippets, and concrete implementations that users can copy and adapt. Abstract examples don't help anyone - users want to see exactly what they'll be working with.
### Keep It Scannable But Not Fragmented
Write in prose that flows naturally when read completely, but structure it so users can quickly find specific information when they're troubleshooting. Avoid dense walls of text, but also avoid over-formatting with excessive bullet points and bold headers. There should be a nice visual heirarchy of balance between all elements, so you can quickly scan the page and find what you're looking for.
## Language and Tone Guidelines
Write clearly without dumbing things down. Use simple language when possible, but don't avoid technical terms that users need to know. Explain concepts in terms of what users can achieve rather than how the software works internally.
Make your writing conversational and encouraging. Phrases like "you can also try" or "when that works" feel more natural than rigid instructional language. Help users feel confident about trying new things.
Keep content concise and purposeful. Every sentence should either help users understand something or help them do something. If it doesn't serve one of those purposes, cut it.
Build in context and reasoning. Users want to understand why they're doing something, not just what to do. This builds confidence and helps them troubleshoot when things don't work exactly as expected.
## Practical Implementation
Structure each feature page consistently with the four-section approach, but let the content flow naturally within that structure. Use visual assets like videos and screenshots to complement the written content - they often communicate more effectively than paragraphs of description.
Link generously to related resources, examples, and deeper documentation. Users should never feel stuck or wonder where to go next. Maintain a repository of real examples that users can reference and adapt to their own needs.
The goal is documentation that feels more like helpful guidance from an experienced colleague than a technical manual. Users should finish reading feeling excited about what they can accomplish, not just informed about what the feature does.
## Balance Structure with Flexibility
While they discuss having consistent documentation structure, there's also mention of making content feel less rigid and more natural. The writing should follow guidelines while still feeling conversational and engaging.
## Bad examples
I personally hate this pattern of bullet point **Bold Text** colon and then more text:
<bad_example_of_writing>
#### macOS
1. **Switch to bash**: Go to Cline Settings → Terminal → Default Terminal Profile → Select "bash"
2. **Disable Oh-My-Zsh temporarily**: If using zsh, try `mv ~/.zshrc ~/.zshrc.backup` and restart VSCode
3. **Set environment**: Add to your shell config: `export TERM=xterm-256color`
#### Windows
1. **Use PowerShell 7**: Install from Microsoft Store, then select it in Cline settings
2. **Disable Windows ConPTY**: VSCode Settings → Terminal Integrated: Windows Enable Conpty → Uncheck
3. **Try Command Prompt**: Sometimes simpler is better - switch to cmd.exe
#### Linux
1. **Use bash**: Most reliable option - select in Cline settings
2. **Check permissions**: Ensure VSCode has terminal access permissions
3. **Disable custom prompts**: Comment out prompt customizations in `.bashrc`
</bad_example_of_writing>
We should instead strive to write beautiful docs that read well. We can use bullet points and numbered lists but it should read naturally and be delightful to look at hierachally when scanning through the doc. There should be a good balance between blocks of text, code snippets, paragraphs, numbered lists, and bullet points. When scanning the documentation visually, you should feel like you're adminiring a tasteful art piece.
<good_example_of_writing>
#### macOS
The most common fix is switching to bash. Navigate to Cline Settings → Terminal → Default Terminal Profile and select "bash" from the dropdown.
If you're still having issues, Oh-My-Zsh might be interfering with terminal integration. Try temporarily disabling it:
- Run `mv ~/.zshrc ~/.zshrc.backup`
- Restart VSCode
You can also add `export TERM=xterm-256color` to your shell configuration file to improve compatibility.
#### Windows
PowerShell 7 provides the most reliable experience. Install it from the Microsoft Store, then select it in your Cline settings.
Still seeing problems? Try these solutions:
- Disable Windows ConPTY: VSCode Settings → Terminal Integrated: Windows Enable Conpty → uncheck
- Switch to Command Prompt (cmd.exe) - sometimes simpler shells work better
#### Linux
Bash is your most dependable option. Select it in Cline settings if you haven't already.
Check these common issues:
- Ensure VSCode has terminal access permissions
- Temporarily comment out custom prompt configurations in your `.bashrc`
</good_example_of_writing>
This is much more natural to read. Writing this way creates a conversational flow, and bullet points are used idiomatically.
# Using Mintlify Components Idiomatically
Mintlify's custom components can transform basic documentation into engaging, scannable content that users actually want to read. Here's how to use them effectively.
## Visual Content with Frames
Videos and images should be wrapped in `<Frame>` components rather than using raw HTML or markdown. This creates consistent styling and proper responsive behavior.
For videos, embed them directly rather than linking externally. Users are much more likely to watch a 30-second demonstration than click through to another platform:
```jsx
<Frame>
<iframe
style={{ width: "100%", aspectRatio: "16/9" }}
src="https://www.youtube.com/embed/your-video-id"
title="Feature demonstration"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen
/>
</Frame>
```
Screenshots work similarly - the frame provides visual polish and consistency:
```jsx
<Frame>
<img src="/path/to/screenshot.png" alt="Descriptive alt text" />
</Frame>
```
## Cards for Navigation and Overview
Cards excel at creating scannable overviews that link to detailed documentation. They're perfect for feature listings, getting started guides, or any section where users need to choose their path.
Use the two-column layout for related features:
```jsx
<Columns cols={2}>
<Card title="Feature Name" icon="relevant-icon" href="/link/to/docs">
Brief description that explains what this feature does and why someone would use it.
</Card>
<Card title="Related Feature" icon="another-icon" href="/another/link">
Another concise explanation that helps users understand the value proposition.
</Card>
</Columns>
```
The key is writing card descriptions that are informative enough to help users decide whether to click through, but concise enough to scan quickly. Each card should answer "what does this do?" and "why would I need this?"
## Tips and Notes for Context
Use `<Tip>` components for helpful information that enhances the main content without cluttering it:
```jsx
<Tip>
Pro tip: You can combine multiple @ mentions in a single message to give Cline
comprehensive context about your issue.
</Tip>
```
`<Note>` components work well for important caveats or technical limitations:
```jsx
<Note>
Due to VS Code limitations, some features require specific settings to work properly.
</Note>
```
`<Info>` is also cool:
<Info>
**Quick Fix**: If you're experiencing terminal issues, try switching to a simpler shell like `bash` in the Cline settings.
This resolves 90% of terminal integration problems.
</Info>
**Never** fall into that awful **Bold Text** - description pattern that we specifically identified as bad writing. The content should flow naturally as connected thoughts rather than feeling like a templated AI response with forced formatting.
## When to Use Bullet Points and Numbered Lists Strategically
Bullet points serve functional purposes - use them for:
**Sequential actions or troubleshooting steps** where users need to follow a specific order:
1. Install the extension
2. Restart VSCode
3. Check the settings panel
**Lists of related options** where users need to choose one approach:
- Try PowerShell 7 for the most reliable experience
- Switch to Command Prompt if you're still having issues
- Use WSL Bash for Linux compatibility
**Quick reference items** that users might need to scan quickly when problem-solving.
**Improving Visual Hierarchy** when there's a wall of text - that's a good time to introduce bullet points or numbered lists.
Each bulleted item or numbered list should be a discrete action or piece of information that benefits from being visually separated. This is a key weapon you can employ when going for that artwork experience I mentioned earlier.
<good_example_of_bullet_points>
## Finding and Configuring Terminal Settings
You can access Cline's terminal settings by clicking the settings icon in the Cline sidebar, then navigating to the Terminal section. These settings control how Cline interacts with your system's terminal.
- The **Default Terminal Profile** setting determines which shell Cline uses for executing commands. If you're experiencing issues, this is usually the first thing to change. I personally keep this set to `bash` on all my systems because it's the most reliable option, even though I use `zsh` for my regular terminal work.
- **Shell Integration Timeout** controls how long Cline waits for the terminal to become ready. The default is 4 seconds, but if you have a heavy shell configuration (lots of plugins, slow startup scripts), you might need to increase this to 10 or even 15 seconds. I've found that WSL environments and SSH connections often need longer timeouts.
- The **Enable Aggressive Terminal Reuse** setting determines whether Cline tries to reuse existing terminals even when they're not in the correct directory. When this causes problems (commands running in the wrong directory, virtual environment issues), disabling it creates more terminal instances but ensures each command runs in a clean state.
- **Terminal Output Line Limit** sets how many lines of output Cline will read from commands. The default of 500 lines works for most cases, but you might need to adjust it. For verbose build outputs, increase it. For commands with progress bars that spam thousands of lines, decrease it to around 100 to avoid consuming too many tokens.
</good_example_of_bullet_points>
## Write Like a Human, Not an AI
Keep it short and direct. If you can say something in fewer words, do it. Long explanations often confuse more than they help.
Use normal sentence lengths. Mix short and long sentences naturally, like you would when talking to someone. Avoid those meandering compound sentences that go on forever.
Cut the corporate speak. Instead of "utilize," say "use." Instead of "in order to," just say "to." Write like you're explaining something to a colleague, not drafting a press release.
Don't over-explain obvious things. If users are reading documentation, they probably understand basic concepts. Respect their intelligence.
## Never use em dashes or emojis
That's pretty much it. Never use them. Only AI writes with em dashes or emojis.
# Anthropomorphizing Cline
When referring to Cline, always call him a "him" not an "it".
Bad example:
- When Cline cant execute commands or read their output, you lose access to one of its most powerful capabilities.
Good Example:
- When Cline cant execute commands or read their output, you lose access to one of his most powerful capabilities.
# Using "I" when sharing your workflow
Adding a personal touch goes a long way. There are great examples in the docs currently where I use "I" to share how I personally use cline, from dev to dev. It's a great technique.
# Crosslinking relevant documentation pages
Make sure you crosslink when you're done writing the docs. If there are relevant docs, just link to them.
# Brevity is the soul of wit
Don't ramble if you don't need to. Use bullet points and numbered lists. Keep things easy to read.
<bad_example>
When Cline can't execute commands or read their output, you lose access to one of his most powerful capabilities. Terminal integration problems are frustrating, but they're usually fixable with a few simple changes.
## The Most Common Problem: Shell Integration Issues
If you're seeing "Shell integration unavailable" or Cline isn't getting command output, the issue is almost always your shell configuration. Complex shell setups with custom prompts, plugins, and fancy configurations can interfere with VSCode's terminal integration.
**Switch to bash first.** This fixes the problem 90% of the time. Navigate to Cline Settings → Terminal → Default Terminal Profile and select "bash" from the dropdown. Restart VSCode after making this change.
Still having issues? Try increasing the shell integration timeout. Go to Cline Settings → Terminal → Shell Integration Timeout and change it from 4 seconds to 10 seconds. Heavy shell configurations need more time to initialize properly.
If commands are running in the wrong directories or you're seeing weird behavior, disable aggressive terminal reuse. In Cline Settings → Terminal, uncheck "Enable aggressive terminal reuse." This creates more terminal instances but ensures each command runs in a clean environment.
</bad_exaxmple>
The first part is total filler, useless to any serious developer. You can tell it's written by a non technical person that doesn't value clean, straightforward information.
<good_example>
## Shell Integration Issues
If you're seeing "Shell integration unavailable" or Cline can't read command output, your shell configuration is interfering with VSCode's terminal integration.
**Switch to bash first.** Go to Cline Settings → Terminal → Default Terminal Profile and select "bash." This fixes 90% of problems.
Still broken? Try these:
- Increase shell integration timeout to 10 seconds in Cline Settings → Terminal
- Disable "aggressive terminal reuse" if commands run in wrong directories
- Restart VSCode after making changes
</good_example>
The good version cuts straight to the problem and solution. No hand-holding, no emotional language about frustration, just the facts: what's wrong, how to fix it, what to try next. Respects that developers want information, not sympathy.RetryClaude can make mistakes. Please double-check responses.
ALWAYS consider your audience. And your audience is devs who don't want their time wasted. Give them the info. I cannot stress this enough. Use bullet points and numbered lists. Prose is good, but every word should actually mean something to the dev reading it.
# Lastly, before you start writing docs
1. Internalize these guidelines. I mean it.
2. Read `docs/docs.json` and get an understanding of the structure of the docs. This will come in handly at the end when you're doing a final pass so you can cross link to docs where relevant.
3. Read some good examples that I personally wrote and am proud of:
- docs/features/slash-commands/workflows.mdx
- docs/features/slash-commands/new-task.mdx
- docs/features/at-mentions/overview.mdx
- docs/features/drag-and-drop.mdx
4. If the user specifies any other instructions make sure you follow them.
+2 -10
View File
@@ -5,7 +5,7 @@
"ecmaVersion": 6,
"sourceType": "module"
},
"plugins": ["@typescript-eslint", "eslint-rules"],
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/naming-convention": [
"warn",
@@ -19,15 +19,7 @@
"eqeqeq": "warn",
"no-throw-literal": "warn",
"semi": "off",
"react-hooks/exhaustive-deps": "off",
"eslint-rules/no-direct-vscode-api": "warn",
"no-restricted-syntax": [
"error",
{
"selector": "VariableDeclarator[id.type=\"ObjectPattern\"][init.object.name=\"process\"][init.property.name=\"env\"]",
"message": "Use process.env.VARIABLE_NAME directly instead of destructuring"
}
]
"react-hooks/exhaustive-deps": "off"
},
"ignorePatterns": ["out", "dist", "**/*.d.ts"]
}
+18 -12
View File
@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
**Important:** All bug reports must be reproducible using Claude 4 Sonnet. Cline uses complex prompts so less capable models may not work as expected.
**Important:** All bug reports must be reproducible using Claude 3.5 Sonnet. Cline uses complex prompts so less capable models may not work as expected.
- type: textarea
id: what-happened
attributes:
@@ -24,7 +24,7 @@ body:
2.
3.
validations:
required: false
required: true
- type: textarea
id: logs
attributes:
@@ -39,19 +39,20 @@ body:
placeholder: "e.g., cline:anthropic/claude-3.7-sonnet, gemini:gemini-2.5-pro-exp-03-25"
validations:
required: true
- type: input
id: operating-system
attributes:
label: Operating System
description: What operating system are you using?
placeholder: "e.g., Windows 11, macOS Sonoma, Ubuntu 22.04"
validations:
required: true
- type: textarea
id: system-info
attributes:
label: System Information
description: What operating system and hardware are you using?
placeholder: |
Operating System: Windows 11, macOS Sonoma, Ubuntu 22.04, etc.
Hardware: CPU, GPU, RAM specifications if relevant
e.g.,
OS: Windows 11
CPU: Intel Core i7-11700K
GPU: NVIDIA GeForce RTX 3070
RAM: 32GB DDR4
label: System Info
description: What system information is relevant to the issue?
placeholder: "e.g., CPU: Intel Core i7-11700K, GPU: NVIDIA GeForce RTX 3070, RAM: 32GB DDR4"
validations:
required: true
- type: input
@@ -62,3 +63,8 @@ body:
placeholder: "e.g., 1.2.3"
validations:
required: true
- type: textarea
id: additional-context
attributes:
label: Additional context
description: Add any other context about the problem here, such as screenshots or related issues.
+4 -1
View File
@@ -1,4 +1,4 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: ✨ Feature Request
url: https://github.com/cline/cline/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop
@@ -6,3 +6,6 @@ contact_links:
- name: 👋 Cline Discord
url: https://discord.gg/cline
about: Join our Discord community for discussions and support
- name: ❓ Other Questions?
url: https://x.com/sdrzn
about: Contact the developer on X @sdrzn for other inquiries
+3 -47
View File
@@ -1,46 +1,10 @@
<!--
Thank you for contributing to Cline!
⚠️ Important: Before submitting this PR, please ensure you have:
- For feature requests: Created a discussion in our Feature Requests discussions board https://github.com/cline/cline/discussions/categories/feature-requests and received approval from core maintainers before implementation
- For all changes: Link the associated issue/discussion in the "Related Issue" section below
Limited exceptions:
Small bug fixes, typo corrections, minor wording improvements, or simple type fixes that don't change functionality may be submitted directly without prior discussion.
Why this requirement?
We deeply appreciate all community contributions - they are essential to Cline's success! To ensure the best use of everyone's time and maintain project direction, we use our Feature Requests discussions board to gauge community interest and validate feature ideas before implementation begins. This helps us focus development efforts on features that will benefit the most users.
-->
### Related Issue
<!-- Replace XXXX with the issue number that this PR addresses -->
**Issue:** #XXXX
### Description
<!--
Help reviewers understand your changes by making this PR readable and well-organized:
- What problem does this PR solve?
- Why were these changes introduced and what purpose do they serve?
- For larger changes, provide context about your approach and reasoning
Small PRs may need minimal description, but larger changes benefit from explaining where you're coming from. Much of this context can be in the linked issue above, so feel free to reference it rather than repeating everything here.
-->
<!-- Describe your changes in detail. What problem does this PR solve? -->
### Test Procedure
<!--
Please walk us through your testing approach and thought process. This helps reviewers understand that you've thoroughly considered the impact of your changes:
- How did you test this change?
- What could potentially break and how did you verify it doesn't?
- What existing functionality might be affected and how did you check it still works?
- Why are you confident this is ready for merge?
We're not looking for exhaustive documentation - just evidence that you've thought through the implications of your changes and tested accordingly.
-->
<!-- How did you test this? Are you confident that it will not introduce bugs? If so, why? -->
### Type of Change
@@ -65,15 +29,7 @@ We're not looking for exhaustive documentation - just evidence that you've thoug
### Screenshots
<!--
Help reviewers quickly understand your changes:
- **UI Changes**: Please include screenshots showing before/after states
- **Complex Workflows**: Consider uploading a screen recording (video) if your changes involve multiple steps or state transitions
- **Backend Changes**: Not required, but feel free to include terminal output or other evidence that demonstrates functionality
This helps reviewers see what you've built without having to pull down and test your branch first.
-->
<!-- For UI changes, add screenshots here -->
### Additional Notes
-108
View File
@@ -1,108 +0,0 @@
name: E2E Tests
on:
push:
branches:
- main
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
matrix_prep:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: |
echo 'matrix=[{"runner":"ubuntu"},{"runner":"windows"},{"runner":"macos"}]' >> $GITHUB_OUTPUT
e2e:
needs: matrix_prep
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.matrix_prep.outputs.matrix) }}
runs-on: ${{ matrix.runner }}-latest
timeout-minutes: 20
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version: 22
# Cache root dependencies - only reuse if package-lock.json exactly matches
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
# Cache webview-ui dependencies - only reuse if package-lock.json exactly matches
- name: Cache webview-ui dependencies
uses: actions/cache@v4
id: webview-cache
with:
path: webview-ui/node_modules
key: ${{ runner.os }}-npm-webview-${{ hashFiles('webview-ui/package-lock.json') }}
# Cache VS Code installation
- name: Cache VS Code
uses: actions/cache@v4
id: vscode-cache
with:
path: .vscode-test
key: vscode-${{ runner.os }}-stable-${{ hashFiles('.vscode-test.mjs', 'package.json') }}
restore-keys: |
vscode-${{ runner.os }}-stable-
# Cache Playwright browsers
- name: Cache Playwright browsers
uses: actions/cache@v4
id: playwright-cache
with:
path: |
~/.cache/ms-playwright
~/Library/Caches/ms-playwright
~/AppData/Local/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
playwright-browsers-${{ runner.os }}-
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci
- name: Install webview-ui dependencies
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm ci
- name: Install xvfb on Linux
if: matrix.runner == 'ubuntu'
run: sudo apt-get update && sudo apt-get install -y xvfb
# Run optimized E2E tests (eliminates redundant builds)
- name: Run E2E tests - Linux
if: matrix.runner == 'ubuntu'
run: xvfb-run -a npm run test:e2e:optimal
- name: Run E2E tests - Non-Linux
if: matrix.runner != 'ubuntu'
run: npm run test:e2e:optimal
- uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
name: playwright-recordings-${{ matrix.runner }}
path: |
test-results/playwright/
+8 -21
View File
@@ -11,10 +11,6 @@ on:
options:
- pre-release
- release
tag:
description: "Enter existing tag to publish (e.g., v3.1.2)"
required: true
type: string
permissions:
contents: write
@@ -34,8 +30,6 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.tag }}
- name: Setup Node.js
uses: actions/setup-node@v4
@@ -75,26 +69,19 @@ jobs:
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Validate Tag
id: validate_tag
- name: Create Git Tag
id: create_tag
run: |
TAG="${{ github.event.inputs.tag }}"
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "Using existing tag: $TAG"
# Verify the tag exists
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Error: Tag '$TAG' does not exist in the repository"
exit 1
fi
echo "Tag '$TAG' validated successfully"
VERSION=v${{ steps.get_version.outputs.version }}
echo "tag=$VERSION" >> $GITHUB_OUTPUT
echo "Tagging with $VERSION"
git tag "$VERSION"
git push origin "$VERSION"
- name: Package and Publish Extension
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
OVSX_PAT: ${{ secrets.OVSX_PAT }}
CLINE_ENVIRONMENT: production
run: |
# Required to generate the .vsix
vsce package --out "cline-${{ steps.get_version.outputs.version }}.vsix"
@@ -119,7 +106,7 @@ jobs:
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.validate_tag.outputs.tag }}
tag_name: ${{ steps.create_tag.outputs.tag }}
files: "*.vsix"
# body: ${{ steps.changelog.outputs.content }}
generate_release_notes: true
-25
View File
@@ -1,25 +0,0 @@
# This workflow will only label and/or close 30 issues at a time in order to avoid exceeding a rate limit.
# More info: https://docs.github.com/en/actions/use-cases-and-examples/project-management/closing-inactive-issues
name: Close inactive issues
on:
schedule:
- cron: "30 1 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
days-before-issue-stale: 60
days-before-issue-close: 14
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 60 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
days-before-pr-stale: -1
days-before-pr-close: -1
exempt-issue-labels: "pinned,security"
repo-token: ${{ secrets.GITHUB_TOKEN }}
-32
View File
@@ -1,32 +0,0 @@
name: Test Stale Issues Workflow
on:
workflow_dispatch:
inputs:
days-before-stale:
description: "Days before an issue becomes stale"
required: true
default: "1"
days-before-close:
description: "Days before a stale issue is closed"
required: true
default: "1"
jobs:
test-stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@28ca103
with:
days-before-issue-stale: ${{ github.event.inputs.days-before-stale }}
days-before-issue-close: ${{ github.event.inputs.days-before-close }}
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for ${{ github.event.inputs.days-before-stale }} days with no activity."
close-issue-message: "This issue was closed because it has been inactive for ${{ github.event.inputs.days-before-close }} days since being marked as stale."
days-before-pr-stale: -1
days-before-pr-close: -1
exempt-issue-labels: "pinned,security"
repo-token: ${{ secrets.GITHUB_TOKEN }}
debug-only: true
+2 -13
View File
@@ -68,16 +68,6 @@ jobs:
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm ci
- name: Install xvfb on Linux
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y xvfb
- name: Install local modules on windows
if: runner.os == 'Windows' && steps.root-cache.outputs.cache-hit == 'true'
run: |
npm install eslint-plugin-eslint-rules
cd webview-ui/ && npm install eslint-plugin-eslint-rules
- name: Set up NPM on Windows
if: runner.os == 'Windows'
run: |
@@ -96,9 +86,8 @@ jobs:
- name: Build Tests and Extension
run: npm run pretest
# Unit Tests disabled due to module system conflicts between backend and webview-ui
# - name: Unit Tests
# run: npm run test:unit
- name: Unit Tests
run: npm run test:unit
# Run extension tests with coverage
- name: Extension Tests with Coverage
+6 -10
View File
@@ -7,7 +7,6 @@ tmp
*.vsix
.DS_Store
.idea
pnpm-lock.yaml
@@ -15,9 +14,6 @@ pnpm-lock.yaml
.venv
.actrc
webview-ui/src/**/*.js
webview-ui/src/**/*.js.map
# Ignore coverage directories and files
coverage
# But don't ignore the coverage scripts in .github/scripts/
@@ -25,10 +21,10 @@ coverage
*evals.env
## Generated files ##
src/generated/
src/shared/proto/
# Generated proto files
src/shared/proto/*.ts
src/core/controller/*/methods.ts
src/core/controller/*/index.ts
src/core/controller/grpc-service-config.ts
webview-ui/src/services/grpc-client.ts
# E2E Tests
test-results
src/standalone/server-setup.ts
+4 -4
View File
@@ -9,9 +9,9 @@ npm run lint || {
# Run Prettier
echo "Running Prettier..."
npx lint-staged --verbose || {
echo "❌ Prettier failed. Please fix the errors and try committing again."
exit 1
}
npm run format || {
echo "❌ Prettier check failed. Run 'npm run format:fix' to automatically fix formatting issues."
exit 1
}
echo "✅ All checks passed!"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"extension": ["ts"],
"spec": ["src/**/__tests__/*.ts", "eslint-rules/__tests__/**/*.test.ts"],
"spec": "src/**/__tests__/*.ts",
"require": ["ts-node/register", "source-map-support/register", "./src/test/requires.ts"],
"recursive": true
}
-5
View File
@@ -3,8 +3,3 @@ node_modules
webview-ui/build/
*.md
package-lock.json
src/core/prompts/system.ts
src/core/prompts/model_prompts/claude4.ts
evals/
docs/
out/
+1 -1
View File
@@ -2,7 +2,7 @@ import { defineConfig } from "@vscode/test-cli"
import path from "path"
export default defineConfig({
files: "{out/**/*.test.js,src/**/*.test.js,!src/test/e2e/**/*.test.js,!out/src/test/e2e/**/*.test.js}",
files: "{out/**/*.test.js,src/**/*.test.js}",
mocha: {
ui: "bdd",
timeout: 20000, // Maximum time (in ms) that a test can run before failing
+10 -40
View File
@@ -6,7 +6,7 @@
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension (production)",
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--disable-workspace-trust", "${workspaceFolder}"],
@@ -14,34 +14,7 @@
"preLaunchTask": "${defaultBuildTask}",
"env": {
"IS_DEV": "true",
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}",
"CLINE_ENVIRONMENT": "production"
}
},
{
"name": "Run Extension (staging)",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--disable-workspace-trust", "${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "${defaultBuildTask}",
"env": {
"IS_DEV": "true",
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}",
"CLINE_ENVIRONMENT": "staging"
}
},
{
"name": "Run Extension (local)",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--disable-workspace-trust", "${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "${defaultBuildTask}",
"env": {
"IS_DEV": "true",
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}",
"CLINE_ENVIRONMENT": "local"
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}"
}
},
{
@@ -50,28 +23,26 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--user-data-dir=${workspaceFolder}/dist/tmp/user",
"--profile-temp",
"--sync=off",
"--sync",
"off",
"--disable-extensions",
"--extensionDevelopmentPath=${workspaceFolder}",
"${workspaceFolder}"
],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "clean-tmp-user",
"preLaunchTask": "clean-sandbox",
"internalConsoleOptions": "openOnSessionStart",
"postDebugTask": "stop",
"env": {
"IS_DEV": "true",
"TEMP_PROFILE": "true",
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}",
"CLINE_ENVIRONMENT": "production"
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}"
}
},
{
"type": "node",
"request": "launch",
"name": "Run cline-core service",
"name": "Run Standalone Extension",
"skipFiles": ["<node_internals>/**"],
"sourceMaps": true,
"resolveSourceMapLocations": ["${workspaceFolder}/**", "!**/node_modules/**"],
@@ -79,12 +50,11 @@
"outFiles": ["${workspaceFolder}/dist-standalone/**/*.js"],
"preLaunchTask": "compile-standalone",
"env": {
// Turns on grpc debug log.
//"GRPC_TRACE": "all",
//"GRPC_VERBOSITY": "DEBUG",
"GRPC_TRACE": "all",
"GRPC_VERBOSITY": "DEBUG",
"NODE_PATH": "${workspaceFolder}/dist-standalone/node_modules"
},
"program": "cline-core.js"
"program": "standalone.js"
}
]
}
+1 -5
View File
@@ -9,9 +9,5 @@
"dist": true // set this to false to include "dist" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off",
// Protobuf settings
"protoc": {
"options": ["--proto_path=proto"]
}
"typescript.tsc.autoDetect": "off"
}
+4 -40
View File
@@ -128,25 +128,7 @@
"type": "npm",
"script": "watch:esbuild",
"group": "build",
"problemMatcher": {
"pattern": [
{
"regexp": "^✘ \\[ERROR\\] (.*)$",
"message": 1
},
{
"regexp": "^\\s+(.*):(\\d+):(\\d+):$",
"file": 1,
"line": 2,
"column": 3
}
],
"background": {
"activeOnStart": true,
"beginsPattern": "^\\[watch\\] build started$",
"endsPattern": "^\\[watch\\] build finished$"
}
},
"problemMatcher": "$esbuild-watch",
"isBackground": true,
"label": "npm: watch:esbuild",
"dependsOn": ["npm: protos"],
@@ -164,25 +146,7 @@
"type": "npm",
"script": "watch:esbuild:test",
"group": "build",
"problemMatcher": {
"pattern": [
{
"regexp": "^✘ \\[ERROR\\] (.*)$",
"message": 1
},
{
"regexp": "^\\s+(.*):(\\d+):(\\d+):$",
"file": 1,
"line": 2,
"column": 3
}
],
"background": {
"activeOnStart": true,
"beginsPattern": "^\\[watch\\] build started$",
"endsPattern": "^\\[watch\\] build finished$"
}
},
"problemMatcher": "$esbuild-watch",
"isBackground": true,
"label": "npm: watch:esbuild:test",
"dependsOn": ["npm: protos"],
@@ -233,10 +197,10 @@
"type": "shell"
},
{
"label": "clean-tmp-user",
"label": "clean-sandbox",
"type": "shell",
"dependsOn": ["watch"],
"command": "rm -rf ${workspaceFolder}/dist/tmp/user && mkdir -p ${workspaceFolder}/dist/tmp/user"
"command": "rm -rf .vscode-dev"
}
],
"inputs": [
+8 -26
View File
@@ -1,40 +1,24 @@
# Default
.vscode/**
.vscode-test/**
out/
dist-standalone/
node_modules/
out/**
node_modules/**
src/**
standalone/**
.gitignore
.yarnrc
esbuild.js
vsc-extension-quickstart.md
tsconfig*.json
**/tsconfig.json
**/.eslintrc.json
**/*.map
**/*.ts
**/.vscode-test.*
eslint-rules/**
.github/**
.husky/**
# Custom
**/demo.gif
demo.gif
.nvmrc
.gitattributes
.prettierignore
.husky/
.github/
eslint-rules/
old_docs/
evals/
.changie.yaml
.codespellrc
.mocharc.json
buf.yaml
.changeset/
.clinerules/
# Ignore all webview-ui files except the build directory (https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/frameworks/hello-world-react-cra/.vscodeignore)
webview-ui/src/**
@@ -48,19 +32,17 @@ webview-ui/node_modules/**
# Ignore docs
docs/**
old_docs/**
# Fix issue where codicons don't get packaged (https://github.com/microsoft/vscode-extension-samples/issues/692)
!node_modules/@vscode/codicons/dist/codicon.css
!node_modules/@vscode/codicons/dist/codicon.ttf
# Include KaTeX CSS and fonts for LaTeX rendering
!webview-ui/node_modules/katex/dist/katex.min.css
!webview-ui/node_modules/katex/dist/fonts/**
# Include default themes JSON files used in getTheme
!src/integrations/theme/default-themes/**
# Include icons
!assets/icons/**
# Ignore E2E build files
e2e-build.js
e2e.vsix
test-results/
+418 -696
View File
File diff suppressed because it is too large Load Diff
+13 -84
View File
@@ -10,74 +10,16 @@ Bug reports help make Cline better for everyone! Before creating a new issue, pl
🔐 <b>Important:</b> If you discover a security vulnerability, please use the <a href="https://github.com/cline/cline/security/advisories/new">Github security tool to report it privately</a>.
</blockquote>
## Before Contributing
All contributions must begin with a GitHub Issue, unless the change is for small bug fixes, typo corrections, minor wording improvements, or simple type fixes that don't change functionality.
**For features and contributions**:
- First check the [Feature Requests discussions board](https://github.com/cline/cline/discussions/categories/feature-requests) for similar ideas
- If your idea is new, create a new feature request
- Wait for approval from core maintainers before starting implementation
- Once approved, feel free to begin working on a PR with the help of our community!
**PRs without approved issues may be closed.**
## Deciding What to Work On
Looking for a good first contribution? Check out issues labeled ["good first issue"](https://github.com/cline/cline/labels/good%20first%20issue) or ["help wanted"](https://github.com/cline/cline/labels/help%20wanted). These are specifically curated for new contributors and areas where we'd love some help!
We also welcome contributions to our [documentation](https://github.com/cline/cline/tree/main/docs)! Whether it's fixing typos, improving existing guides, or creating new educational content - we'd love to build a community-driven repository of resources that helps everyone get the most out of Cline. You can start by diving into `/docs` and looking for areas that need improvement.
If you're planning to work on a bigger feature, please create a [feature request](https://github.com/cline/cline/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop) first so we can discuss whether it aligns with Cline's vision.
## Development Setup
### Local Development Instructions
1. Clone the repository _(Requires [git-lfs](https://git-lfs.com/))_:
```bash
git clone https://github.com/cline/cline.git
```
2. Open the project in VSCode:
```bash
code cline
```
3. Install the necessary dependencies for the extension and webview-gui:
```bash
npm run install:all
```
4. Launch by pressing `F5` (or `Run`->`Start Debugging`) to open a new VSCode window with the extension loaded. (You may need to install the [esbuild problem matchers extension](https://marketplace.visualstudio.com/items?itemName=connor4312.esbuild-problem-matchers) if you run into issues building the project.)
### Creating a Pull Request
1. Before creating a PR, generate a changeset entry:
```bash
npm run changeset
```
This will prompt you for:
- Type of change (major, minor, patch)
- `major` → breaking changes (1.0.0 → 2.0.0)
- `minor` → new features (1.0.0 → 1.1.0)
- `patch` → bug fixes (1.0.0 → 1.0.1)
- Description of your changes
2. Commit your changes and the generated `.changeset` file
3. Push your branch and create a PR on GitHub. Our CI will:
- Run tests and checks
- Changesetbot will create a comment showing the version impact
- When merged to main, changesetbot will create a Version Packages PR
- When the Version Packages PR is merged, a new release will be published
4. Testing
- Run `npm run test` to run tests locally.
- Before submitting PR, run `npm run format:fix` to format your code
- Run `npm run test:ci` to run tests locally
### Extension
1. **VS Code Extensions**
- When opening the project, VS Code will prompt you to install recommended extensions
@@ -87,26 +29,23 @@ We also welcome contributions to our [documentation](https://github.com/cline/cl
2. **Local Development**
- Run `npm run install:all` to install dependencies
- Run `npm run test` to run tests locally
- Run → Start Debugging or `>Debug: Select and Start Debugging` and wait for a new VS Code instance to open
- Before submitting PR, run `npm run format:fix` to format your code
3. **Linux-specific Setup**
VS Code extension tests on Linux require the following system libraries:
- `dbus`
- `libasound2`
- `libatk-bridge2.0-0`
- `libatk1.0-0`
- `libdrm2`
- `libgbm1`
- `libgtk-3-0`
- `libnss3`
- `libatk-bridge2.0-0`
- `libxkbfile1`
- `libx11-xcb1`
- `libxcomposite1`
- `libxdamage1`
- `libxfixes3`
- `libxkbfile1`
- `libxrandr2`
- `libgbm1`
- `libdrm2`
- `libgtk-3-0`
- `dbus`
- `xvfb`
These libraries provide necessary GUI components and system services for the test environment.
@@ -115,23 +54,13 @@ We also welcome contributions to our [documentation](https://github.com/cline/cl
```bash
sudo apt update
sudo apt install -y \
dbus \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libdrm2 \
libgbm1 \
libgtk-3-0 \
libnss3 \
libx11-xcb1 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libxkbfile1 \
libxrandr2 \
xvfb
libatk1.0-0 libatk-bridge2.0-0 libxkbfile1 libx11-xcb1 \
libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 \
libdrm2 libgtk-3-0 dbus xvfb
```
- Run `npm run test:ci` to run tests locally
## Writing and Submitting Code
Anyone can contribute code to Cline, but we ask that you follow these guidelines to ensure your contributions can be smoothly integrated:
+46 -2
View File
@@ -30,7 +30,7 @@ English | <a href="https://github.com/cline/cline/blob/main/locales/es/README.md
</table>
</div>
Meet Cline (pronounced /klaɪn/, like "Klein"), an AI assistant that can use your **CLI** a**N**d **E**ditor.
Meet Cline, an AI assistant that can use your **CLI** a**N**d **E**ditor.
Thanks to [Claude 3.7 Sonnet's agentic coding capabilities](https://www.anthropic.com/claude/sonnet), Cline can handle complex software development tasks step-by-step. With tools that let him create & edit files, explore large projects, use the browser, and execute terminal commands (after you grant permission), he can assist you in ways that go beyond code completion or tech support. Cline can even use the Model Context Protocol (MCP) to create new tools and extend his own capabilities. While autonomous AI scripts traditionally run in sandboxed environments, this extension provides a human-in-the-loop GUI to approve every file change and terminal command, providing a safe and accessible way to explore the potential of agentic AI.
@@ -51,7 +51,7 @@ Thanks to [Claude 3.7 Sonnet's agentic coding capabilities](https://www.anthrop
### Use any API and Model
Cline supports API providers like OpenRouter, Anthropic, OpenAI, Google Gemini, AWS Bedrock, Azure, GCP Vertex, Cerebras and Groq. You can also configure any OpenAI compatible API, or use a local model through LM Studio/Ollama. If you're using OpenRouter, the extension fetches their latest model list, allowing you to use the newest models as soon as they're available.
Cline supports API providers like OpenRouter, Anthropic, OpenAI, Google Gemini, AWS Bedrock, Azure, and GCP Vertex. You can also configure any OpenAI compatible API, or use a local model through LM Studio/Ollama. If you're using OpenRouter, the extension fetches their latest model list, allowing you to use the newest models as soon as they're available.
The extension also keeps track of total tokens and API usage cost for the entire task loop and individual requests, keeping you informed of spend every step of the way.
@@ -141,6 +141,50 @@ For example, when working with a local web server, you can use 'Restore Workspac
To contribute to the project, start with our [Contributing Guide](CONTRIBUTING.md) to learn the basics. You can also join our [Discord](https://discord.gg/cline) to chat with other contributors in the `#contributors` channel. If you're looking for full-time work, check out our open positions on our [careers page](https://cline.bot/join-us)!
<details>
<summary>Local Development Instructions</summary>
1. Clone the repository _(Requires [git-lfs](https://git-lfs.com/))_:
```bash
git clone https://github.com/cline/cline.git
```
2. Open the project in VSCode:
```bash
code cline
```
3. Install the necessary dependencies for the extension and webview-gui:
```bash
npm run install:all
```
4. Launch by pressing `F5` (or `Run`->`Start Debugging`) to open a new VSCode window with the extension loaded. (You may need to install the [esbuild problem matchers extension](https://marketplace.visualstudio.com/items?itemName=connor4312.esbuild-problem-matchers) if you run into issues building the project.)
</details>
<details>
<summary>Creating a Pull Request</summary>
1. Before creating a PR, generate a changeset entry:
```bash
npm run changeset
```
This will prompt you for:
- Type of change (major, minor, patch)
- `major` → breaking changes (1.0.0 → 2.0.0)
- `minor` → new features (1.0.0 → 1.1.0)
- `patch` → bug fixes (1.0.0 → 1.0.1)
- Description of your changes
2. Commit your changes and the generated `.changeset` file
3. Push your branch and create a PR on GitHub. Our CI will:
- Run tests and checks
- Changesetbot will create a comment showing the version impact
- When merged to main, changesetbot will create a Version Packages PR
- When the Version Packages PR is merged, a new release will be published
</details>
## License
[Apache 2.0 © 2025 Cline Bot Inc.](./LICENSE)
-21
View File
@@ -1,21 +0,0 @@
version: v2
modules:
- path: proto
name: cline/cline/lint
lint:
use:
- STANDARD
except: # Add exceptions for current patterns that contradict STANDARD settings
- RPC_PASCAL_CASE # rpcs are camel case (start with lowercase)
- RPC_REQUEST_RESPONSE_UNIQUE # request messages are not unique.
- RPC_REQUEST_STANDARD_NAME # request messages dont all end with Request
- RPC_RESPONSE_STANDARD_NAME # response messages dont all end with Response
- PACKAGE_VERSION_SUFFIX # package name does not contain version.
- ENUM_VALUE_PREFIX # enum values dont start with the enum name.
- ENUM_ZERO_VALUE_SUFFIX # first value does not have to be UNSPECIFIED.
# breaking:
# use:
# - WIRE_JSON # Detect changes that break the json wire format (this is the minimum recommended level.)
@@ -5,7 +5,7 @@ description: "Learn how to set up AWS Bedrock with Cline using credentials authe
### Overview
- **AWS Bedrock:** A fully managed service that offers access to leading generative AI models (e.g., Anthropic Claude, Amazon Nova) through AWS.\
- **AWS Bedrock:** A fully managed service that offers access to leading generative AI models (e.g., Anthropic Claude, Amazon Titan) through AWS.\
[Learn more about AWS Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html).
- **Cline:** A VS Code extension that acts as a coding assistant by integrating with AI models—empowering developers to generate code, debug, and analyze data.
- **Enterprise Focus:** This guide is tailored for organizations with established AWS environments (using IAM roles, AWS SSO, AWS Organizations, etc.) to ensure secure and compliant usage.
@@ -25,41 +25,12 @@ description: "Learn how to set up AWS Bedrock with Cline using credentials authe
#### 1.2 Attach the Required Policies
To ensure Cline can interact with AWS Bedrock, your IAM user or role needs specific permissions. While the `AmazonBedrockLimitedAccess` managed policy provides comprehensive access, for a more restricted and secure setup adhering to the principle of least privilege, the following minimal permissions are sufficient for Cline's core model invocation functionality:
- `bedrock:InvokeModel`
- `bedrock:InvokeModelWithResponseStream`
You can create a custom IAM policy with these permissions and attach it to your IAM user or role.
**Option 1: Minimal Permissions (Recommended for Production & Least Privilege)**
1. In the AWS IAM console, create a new policy.
2. Use the JSON editor to add the following policy document:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"],
"Resource": "*" // For enhanced security, scope this to specific model ARNs if possible.
}
]
}
```
3. Name the policy (e.g., `ClineBedrockInvokeAccess`) and attach it to your IAM user or role.
**Option 2: Using a Managed Policy (Simpler Initial Setup)**
- Alternatively, you can attach the AWS managed policy **`AmazonBedrockLimitedAccess`**. This grants broader permissions, including the ability to list models, manage provisioning, and other Bedrock features. This might be simpler for initial setup or if you require these wider capabilities.
[View AmazonBedrockLimitedAccess Policy Details](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html)
**Important Considerations:**
- **Model Listing in Cline:** The minimal permissions (`bedrock:InvokeModel`, `bedrock:InvokeModelWithResponseStream`) are sufficient for Cline to _use_ a model if you specify the model ID directly in Cline's settings. If you rely on Cline to dynamically list available Bedrock models, you might need additional permissions like `bedrock:ListFoundationModels`.
- **AWS Marketplace Subscriptions:** For third-party models (e.g., Anthropic Claude), ensure you have active AWS Marketplace subscriptions. This is typically managed in the AWS Bedrock console under "Model access" and might require `aws-marketplace:Subscribe` permissions if not already handled.
- _Enterprise Tip:_ Always apply least-privilege practices. Where possible, scope resource ARNs in your IAM policies to specific models or regions. Utilize [Service Control Policies (SCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) for overarching governance in AWS Organizations.
1. **Attach the Managed Policy:**
- Attach the **`AmazonBedrockFullAccess`** managed policy to your user/role.\
[View AmazonBedrockFullAccess Policy Details](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html)
2. **Confirm Additional Permissions:**
- Ensure your policy includes permissions for model invocation (e.g., `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream`), model listing, and AWS Marketplace actions (like `aws-marketplace:Subscribe`).
- _Enterprise Tip:_ Apply least-privilege practices by scoping resource ARNs and using [Service Control Policies (SCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) to restrict access where necessary.
---
@@ -71,8 +42,8 @@ You can create a custom IAM policy with these permissions and attach it to your
AWS Bedrock is available in multiple regions (e.g., US East, Europe, Asia Pacific). Choose the region that meets your latency and compliance needs.\
[AWS Global Infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/)
2. **Verify Model Access:**
- In the AWS Bedrock console, confirm that the models your team requires (e.g., Anthropic Claude, Amazon Nova) are marked as "Access granted."
- **Note:** Some advanced models might require an [Inference Profile](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html) if not available on-demand.
- In the AWS Bedrock console, confirm that the models your team requires (e.g., Anthropic Claude, Amazon Titan) are marked as "Access granted."
- **Note:** Some advanced models might require an [Inference Profile](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-prereq.html) if not available on-demand.
#### 2.2 Set Up AWS Marketplace Subscriptions (if needed)
@@ -138,7 +109,7 @@ You can create a custom IAM policy with these permissions and attach it to your
By following these steps, your enterprise team can securely integrate AWS Bedrock with the Cline VS Code extension to accelerate development:
1. **Prepare Your AWS Environment:** Create or use a secure IAM role/user, attach the `AmazonBedrockLimitedAccess` policy, and ensure necessary permissions.
1. **Prepare Your AWS Environment:** Create or use a secure IAM role/user, attach the `AmazonBedrockFullAccess` policy, and ensure necessary permissions.
2. **Verify Region and Model Access:** Confirm that your selected region supports your required models and subscribe via AWS Marketplace if needed.
3. **Configure Cline in VS Code:** Install and set up Cline with your AWS credentials and choose an appropriate model.
4. **Implement Security and Monitoring:** Use best practices for IAM, network security, monitoring, and cost management.
+6 -22
View File
@@ -61,6 +61,7 @@
"getting-started/installing-cline",
"getting-started/installing-dev-essentials",
"getting-started/model-selection-guide",
"getting-started/our-favorite-tech-stack",
"getting-started/task-management",
"getting-started/understanding-context-management",
"getting-started/what-is-cline"
@@ -142,25 +143,12 @@
]
},
{
"group": "Provider Configuration",
"group": "Custom Model Configurations",
"pages": [
"provider-config/anthropic",
"provider-config/claude-code",
"provider-config/aws-bedrock-with-apikey-authentication",
"provider-config/aws-bedrock-with-credentials-authentication",
"provider-config/aws-bedrock-with-profile-authentication",
"provider-config/gcp-vertex-ai",
"provider-config/litellm-and-cline-using-codestral",
"provider-config/vscode-language-model-api",
"provider-config/xai-grok",
"provider-config/mistral-ai",
"provider-config/deepseek",
"provider-config/ollama",
"provider-config/openai",
"provider-config/openai-compatible",
"provider-config/openrouter",
"provider-config/requesty",
"provider-config/sap-aicore"
"custom-model-configs/aws-bedrock-with-credentials-authentication",
"custom-model-configs/aws-bedrock-with-profile-authentication",
"custom-model-configs/gcp-vertex-ai",
"custom-model-configs/litellm-and-cline-using-codestral"
]
},
{
@@ -171,10 +159,6 @@
"running-models-locally/ollama"
]
},
{
"group": "Troubleshooting",
"pages": ["troubleshooting/terminal-quick-fixes", "troubleshooting/terminal-integration-guide"]
},
{
"group": "More Info",
"pages": ["more-info/telemetry"]
@@ -14,11 +14,9 @@ Certain scenarios may warrant using local models, including handling highly sens
#### [IAM Security Best Practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) (For administrators)
#### [AWS Bedrock setup for API Keys](/provider-config/aws-bedrock-with-apikey-authentication)
#### [AWS Bedrock setup for Legacy IAM (AWS Credentials)](/custom-model-configs/aws-bedrock-with-credentials-authentication.mdx)
#### [AWS Bedrock setup for Legacy IAM (AWS Credentials)](/provider-config/aws-bedrock-with-credentials-authentication)
#### [AWS Bedrock setup for SSO token (AWS Profile)](/provider-config/aws-bedrock-with-profile-authentication)
#### [AWS Bedrock setup for SSO token (AWS Profile)](/custom-model-configs/aws-bedrock-with-profile-authentication.mdx)
#### VPC Endpoint Setup
@@ -120,7 +120,7 @@ Example of context window usage over 50% with a 200K context window:
# Context Window Usage
105,000 / 200,000 tokens (53%)
Model: anthropic/claude-sonnet-4 (200K context window)
Model: anthropic/claude-3.7-sonnet (200K context window)
\`\`\`
**IMPORTANT**: When you see context window usage at or above 50%, you MUST:
@@ -58,16 +58,3 @@ When you use the terminal mention in your message, here's what happens behind th
6. The AI can now "see" the complete terminal output with all formatting preserved
This process happens automatically whenever you use the terminal mention, giving the AI access to your command results, error messages, and other terminal output without you having to copy it manually.
## Troubleshooting Terminal Issues
If you're experiencing issues with terminal mentions or terminal integration in general (such as "Shell Integration Unavailable" or commands not showing output), please refer to our comprehensive [Terminal Integration Troubleshooting Guide](/troubleshooting/terminal-integration-guide).
Common issues include:
- Terminal mentions not capturing output
- "Shell Integration Unavailable" messages in Cline chat
- Commands executing but output not visible to Cline
- Terminal integration working inconsistently
The troubleshooting guide provides platform-specific solutions and detailed configuration steps to resolve these issues.
+1 -13
View File
@@ -11,19 +11,7 @@ You can create a rule by clicking the `+` button in the Rules tab. This will ope
Once you save the file:
- Your rule will be stored in the `.clinerules/` directory in your project (if it's a Workspace Rule)
- Or in the Global Rules directory (if it's a Global Rule):
### Global Rules Directory Location
The location of your Global Rules directory depends on your operating system:
| Operating System | Default Location | Notes |
|------------------|------------------|-------|
| **Windows** | `Documents\Cline\Rules` | Uses system Documents folder |
| **macOS** | `~/Documents/Cline/Rules` | Uses user Documents folder |
| **Linux/WSL** | `~/Documents/Cline/Rules` | May fall back to `~/Cline/Rules` on some systems |
> **Note for Linux/WSL users**: If you don't find your global rules in `~/Documents/Cline/Rules`, check `~/Cline/Rules` as the location may vary depending on your system configuration and whether the Documents directory exists.
- Or in the `Documents/Cline/Rules` directory (if it's a Global Rule).
You can also have Cline create a rule for you by using the [`/newrule` slash command](/features/slash-commands/new-rule) in the chat.
@@ -74,25 +74,8 @@ This approach ensures that all terminal output, including colors and formatting,
- **Select specific output when needed**: By default, the integration captures all terminal content, but you can also select specific lines before right-clicking to focus on just the relevant output.
- **Combine terminal outputs with file mentions**: After sending terminal output to Cline, you can enhance your question by mentioning relevant files using the @ mentions feature.
- **Combine with file mentions**: After sending terminal output to Cline, you can enhance your question by mentioning relevant files using the @ mentions feature.
- **Contextualize build & test outputs with the terminal**: Terminal integration is particularly useful for understanding complex build errors or test failures that span multiple lines.
- **Use for build and test output**: Terminal integration is particularly useful for understanding complex build errors or test failures that span multiple lines.
Next time you're staring at a cryptic error message in your terminal, try using Cline's terminal integration instead of copying and pasting. You'll get more accurate help because Cline can see the complete terminal context with proper formatting.
## Troubleshooting Terminal Issues
If you're experiencing issues with terminal integration, such as "Shell Integration Unavailable" or commands not showing output, please refer to our comprehensive [Terminal Integration Troubleshooting Guide](/troubleshooting/terminal-integration-guide).
The troubleshooting guide covers:
- Common terminal integration issues and quick fixes
- Platform-specific solutions for Windows, macOS, and Linux
- Shell-specific configurations for zsh, bash, PowerShell, and more
- Advanced debugging techniques
- Terminal settings optimization
<Tip>
**Quick Fix**: Most terminal issues can be resolved by switching to bash in the Cline settings and increasing the shell
integration timeout to 10 seconds.
</Tip>
+4 -7
View File
@@ -6,13 +6,10 @@ sidebarTitle: "Plan & Act"
Plan & Act modes represent Cline's approach to structured AI development, emphasizing thoughtful planning before implementation. This dual-mode system helps developers create more maintainable, accurate code while reducing iteration time.
<Frame>
<iframe
style={{ width: "100%", aspectRatio: "16/9" }}
src="https://www.youtube.com/embed/b7o6URFPp64"
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen></iframe>
<img
src="https://storage.googleapis.com/cline_public_images/docs/assets/planningThenActing%20(1).gif"
alt="Use Plan to gather context before using Act to implement the plan"
/>
</Frame>
#### Plan Mode: Think First
+27 -27
View File
@@ -13,13 +13,35 @@ Before you jump into coding, make sure you have these essentials ready:
A popular, free, and powerful code editor.
- [<u>Download VS Code</u>](https://code.visualstudio.com/)
- [Download VS Code](https://code.visualstudio.com/)
📺 **Recommended YouTube Tutorial:** [<u>How to Install VS Code</u>](https://www.youtube.com/watch?v=MlIzFUI1QGA)
📺 **Recommended YouTube Tutorial:** [How to Install VS Code](https://www.youtube.com/watch?v=MlIzFUI1QGA)
> ✅ **Pro Tip:** Install VS Code in your Applications folder (macOS) or Program Files (Windows) for easy access from your dock or start menu.
#### 2. **Organize Your Projects**
#### 2. **Essential Development Tools**
Basic software required for coding efficiently:
- Homebrew (macOS)
- Node.js
- Git
👉 Follow our detailed guide on Installing Essential Development Tools with step-by-step help from Cline.
📺 **Recommended YouTube Tutorials:**
- **For macOS:**
- [Install Homebrew on Mac](https://www.youtube.com/watch?v=hwGNgVbqasc)
- [Install Git on MacOS 2024](https://www.youtube.com/watch?v=B4qsvQ5IqWk)
- [Install Node.js on Mac (M1 | M2 | M3)](https://www.youtube.com/watch?v=I8H4wolRFBk)
- **For Windows:**
- [Install Git on Windows 10/11 (2024)](https://www.youtube.com/watch?v=yjxv1HuRQy0)
- [Install Node.js in Windows 10/11](https://www.youtube.com/watch?v=uCgAuOYpJd0)
> ⚠️ **Note:** If you run into permission issues during installation, try running your terminal or command prompt as an administrator.
#### 3. **Organize Your Projects**
Create a dedicated folder named `Cline` in your Documents folder for all your coding projects:
@@ -33,36 +55,14 @@ Inside your `Cline` folder, structure projects clearly:
> 💡 **Tip:** Keeping your projects organized from the start will save you time and confusion later!
#### 3. **Install the Cline VS Code Extension**
#### 4. **Install the Cline VS Code Extension**
Enhance your coding workflow by installing the Cline extension directly within VS Code:
- Get Started with Cline Extension Tutorial
📺 **Recommended YouTube Tutorial:** [<u>How To Install Extensions in VS Code</u>](https://www.youtube.com/watch?v=E7trgwZa-mk)
📺 **Recommended YouTube Tutorial:** [How To Install Extensions in VS Code](https://www.youtube.com/watch?v=E7trgwZa-mk)
> ✅ **Pro Tip:** After installing, reload VS Code to ensure the extension is activated properly.
#### 4. **Essential Development Tools**
Basic software required for coding efficiently:
- Homebrew (macOS)
- Node.js
- Git
👉 [<u>Follow our detailed guide on Installing Essential Development Tools with step-by-step help from Cline.</u>](https://docs.cline.bot/getting-started/installing-dev-essentials#installing-dev-essentials)
📺 **Recommended YouTube Tutorials for Manual Installation:**
- **For macOS:**
- [<u>Install Homebrew on Mac</u>](https://www.youtube.com/watch?v=hwGNgVbqasc)
- [<u>Install Git on macOS 2024</u>](https://www.youtube.com/watch?v=B4qsvQ5IqWk)
- [<u>Install Node.js on Mac (M1 | M2 | M3)</u>](https://www.youtube.com/watch?v=I8H4wolRFBk)
- **For Windows:**
- [<u>Install Git on Windows 10/11 (2024)</u>](https://www.youtube.com/watch?v=yjxv1HuRQy0)
- [<u>Install Node.js in Windows 10/11</u>](https://www.youtube.com/watch?v=uCgAuOYpJd0)
> ⚠️ **Note:** If you run into permission issues during installation, try running your terminal or command prompt as an administrator.
🎉 You're all set! Dive in and start coding smarter and faster with **Cline**.
@@ -60,6 +60,7 @@ Now that you have Cline installed, let's get you set up with your account:
- DeepSeek Chat (cost-effective alternative)
- Google Gemini 2.0 Flash
- And more — all through your Cline account.
4. -
### 💻 Your First Interaction with Cline
@@ -0,0 +1,238 @@
---
title: "Our Favorite Tech Stack"
description: "A curated list of our recommended technologies and tools for building modern web applications with Cline."
---
## Recommended Stack for New Cline Users (2025)
### Your Complete Development Environment
#### Development Tools
- **VS Code** - Your code editor, [download here](https://code.visualstudio.com/)
- **GitHub** - Where your code lives, [sign up here](https://github.com)
#### Frontend
- **Next.js 14+** - React framework with App Router
- **Tailwind CSS** - Beautiful styling without writing CSS
- **TypeScript** - JavaScript, but safer and smarter
#### Backend
- **Supabase** - Your complete backend solution, [sign up with GitHub](https://supabase.com)
- PostgreSQL database
- Authentication
- File storage
- Real-time updates
#### Deployment
- **Vercel** - Where your app runs, [sign up with GitHub](https://vercel.com)
- Automatic deployments from GitHub
- Preview deployments for testing
- Production-ready CDN
#### AI Development
Choose your AI assistant based on your needs:
| Model | Input Cost (per 1M tokens) | Output Cost (per 1M tokens) | Best For |
| ----------------- | -------------------------- | --------------------------- | ------------------------------ |
| Claude 3.5 Sonnet | $3.00 | $15.00 | Production apps, complex tasks |
| DeepSeek R1 | $1.00 | $3.00 | Budget-conscious production |
| DeepSeek V3 | $0.14 | $2.20 | Budget-conscious development |
#### Free Tier Benefits
**Vercel (Hobby)**
- 100 GB data transfer/month
- 100k serverless function invocations
- 100 MB deployment size
- Automatic HTTPS & CI/CD
**Supabase (Free)**
- 500 MB database storage
- 1 GB file storage
- 50k monthly active users
- 2M real-time messages/month
**GitHub (Free)**
- Unlimited public repositories
- GitHub Actions CI/CD
- Project management tools
- Collaboration features
### Getting Started
1. Install the development essentials:
- Follow our [Development Essentials Installation Guide](https://docs.cline.bot/getting-started/getting-started-new-coders/installing-dev-essentials)
2. Set up Cline's Memory Bank:
- Follow the [Memory Bank setup instructions](https://docs.cline.bot/improving-your-prompting-skills/custom-instructions-library/cline-memory-bank)
- Create an empty `cline_docs` folder in your project root
- Create `projectBrief.md` in the `cline_docs` folder (see example below)
- Tell Cline to "initialize memory bank"
3. Add our recommended stack configuration:
- Create `.clinerules` file (see template below)
- Let Cline handle the rest!
#### Example Project Brief
```markdown
# Project Brief
## Overview
Building a [type of application] that will [main purpose].
## Core Features
- Feature 1
- Feature 2
- Feature 3
## Target Users
[Describe who will use your application]
## Technical Preferences (optional)
- Any specific technologies you want to use
- Any specific requirements or constraints
```
### .clinerules Template
```markdown
# Project Configuration
## Tech Stack
- Next.js 14+ with App Router
- Tailwind CSS for styling
- Supabase for backend
- Vercel for deployment
- GitHub for version control
## Project Structure
/src
/app # Next.js App Router pages
/components # React components
/lib # Utility functions
/types # TypeScript types
/supabase
/migrations # SQL migration files
/seed # Seed data files
/public # Static assets
## Database Migrations
SQL files in /supabase/migrations should:
- Use sequential numbering: 001, 002, etc.
- Include descriptive names
- Be reviewed by Cline before execution
Example: 001_create_users_table.sql
## Development Workflow
- Cline helps write and review code changes
- Vercel automatically deploys from main branch
- Database migrations reviewed by Cline before execution
## Security
DO NOT read or modify:
- .env files
- \*_/config/secrets._
- Any file containing API keys or credentials
```
### Learning Resources (2025)
Want to learn more about the technologies we're using? Here are some great resources:
#### Next.js and React
- [Official Learn Next.js Course](https://nextjs.org/learn) - Interactive tutorial
- [NextJS App Router: Modern Web Dev in 1 Hour](https://www.youtube.com/nextjs-modern) - Quick overview
- [Building Real-World Apps with Next.js](https://www.youtube.com/nextjs-real-world) - Practical examples
#### Supabase
- [Supabase From Scratch](https://www.udemy.com/supabase-scratch) - Comprehensive course
- [Official Quickstart Guides](https://supabase.com/docs/guides/getting-started)
- [Real-Time Apps with Next.js and Supabase](https://www.newline.co/courses/supabase-nextjs)
#### Tailwind CSS
- [Tailwind CSS Tutorial for Beginners](https://www.youtube.com/tailwind-2025)
- [Official Tailwind Documentation](https://tailwindcss.com/docs)
- Interactive course at [Scrimba Tailwind CSS Course](https://scrimba.com/learn/tailwind)
### Other Things to Know
#### Working with Git & GitHub
Git helps you track changes in your code and collaborate with others. Here are the essential commands you'll use:
**Daily Development**
```bash
# Save your changes (do this often!)
git add . # Stage all changed files
git commit -m "Add login page" # Save changes with a clear message
# Share your changes
git push origin main # Upload to GitHub
```
**Common Workflow**
1. **Start of day**: Get latest changes
```bash
bashCopygit pull origin main # Download latest code
```
2. **During development**: Save work regularly
```bash
bashCopygit add .
git commit -m "Clear message about changes"
```
3. **End of day**: Share your progress
```bash
bashCopygit push origin main # Upload to GitHub
```
**Best Practices**
- Commit often with clear messages
- Pull before starting new work
- Push completed work to share with others
- Use `.gitignore` to avoid committing sensitive files
> **Tip**: Vercel automatically deploys when you push to main!
#### Environment Variables
- Store secrets in `.env.local` for development
- Add them to Vercel project settings for production
- Never commit `.env` files to Git
#### Getting Help
1. Use `/help` in Cline chat for immediate assistance
2. Check [Cline Documentation](https://docs.cline.bot)
3. Join our [Discord Community](https://discord.gg/cline)
4. Search GitHub issues for common problems
Remember: Cline is here to help at every step. Just ask for guidance or clarification when needed!
@@ -38,7 +38,7 @@ Cline actively builds context in two ways:
- Guide focus areas
- Share design thoughts and requirements
💡 **Key Point**: Cline isn't passive - it actively seeks to understand your project. You can either let it explore or guide its focus, especially in [Plan](https://docs.cline.bot/features/plan-and-act) mode.
💡 **Key Point**: Cline isn't passive - it actively seeks to understand your project. You can either let it explore or guide its focus, especially in [Plan](https://docs.cline.bot/exploring-clines-tools/plan-and-act-modes-a-guide-to-effective-ai-development) mode.
### Context & Context Windows
@@ -93,7 +93,7 @@ Context files help maintain understanding across sessions. They serve as documen
#### Approaches to Context Files
1. **Evergreen Project Context (i.e.** [**Memory Bank**](https://docs.cline.bot/prompting/cline-memory-bank)**)**
1. **Evergreen Project Context (i.e.** [**Memory Bank**](https://docs.cline.bot/improving-your-prompting-skills/custom-instructions-library/cline-memory-bank)**)**
- Living documentation that evolves with your project
- Updated as architecture and patterns emerge
- Example: The Memory Bank pattern maintains files like `techContext.md` and `systemPatterns.md`
@@ -151,7 +151,7 @@ Context files help maintain understanding across sessions. They serve as documen
- Use Plan mode for complex discussions
- Start fresh sessions when needed
3. **Team Projects**
- Share common context files (consider using [.clinerules](https://docs.cline.bot/features/cline-rules) files in project roots)
- Share common context files (consider using [.clinerules](https://docs.cline.bot/improving-your-prompting-skills/prompting) files in project roots)
- Document architectural decisions
- Maintain consistent patterns
- Keep documentation current
@@ -17,7 +17,6 @@ There are multiple places online to find MCP servers:
- [mcpservers.org](https://mcpservers.org/)
- [mcp.so](https://mcp.so/)
- [glama.ai/mcp/servers](https://glama.ai/mcp/servers)
- [mcp.composio.dev](https://mcp.composio.dev/)
These directories allow users to sort the servers by various criteria such as downloads, date, stars, and use case. Each entry provides information such as features, tools, and configuration instructions.
+6 -6
View File
@@ -4,17 +4,17 @@ title: "Telemetry"
### Overview
To help make Cline better for everyone, we collect usage data that helps us understand how developers are using our open-source AI coding agent. This feedback loop is crucial for improving Cline's capabilities and user experience.
To help make Cline better for everyone, we collect anonymous usage data that helps us understand how developers are using our open-source AI coding agent. This feedback loop is crucial for improving Cline's capabilities and user experience.
We use PostHog, an open-source analytics platform, for data collection and analysis. Our telemetry implementation is fully transparent - you can review the [source code](https://github.com/cline/cline/blob/main/src/services/posthog/telemetry/TelemetryService.ts) to see exactly what we track.
We use PostHog, an open-source analytics platform, for data collection and analysis. Our telemetry implementation is fully transparent - you can review the [source code](https://github.com/cline/cline/blob/main/src/services/telemetry/TelemetryService.ts) to see exactly what we track.
### Tracking Policy
Privacy is our priority. By default, all collected data is anonymized. If you log in with a Cline account, your telemetry data will be associated with your account to help us improve the product and provide better support when you encounter issues. Your code, prompts, and conversation content always remain private and are never collected.
Privacy is our priority. All collected data is anonymized before being sent to PostHog, with no personally identifiable information (PII) included. Your code, prompts, and conversation content always remain private and are never collected.
### What We Track
We collect basic usage data including:
We collect basic anonymous usage data including:
**Task Interactions:** When tasks start and finish, conversation flow (without content)\
**Mode and Tool Usage:** Switches between plan/act modes, which tools are being used\
@@ -22,13 +22,13 @@ We collect basic usage data including:
**System Context:** OS type and VS Code environment details\
**UI Activity:** Navigation patterns and feature usage
For complete transparency, you can inspect our [telemetry implementation](https://github.com/cline/cline/blob/main/src/services/posthog/telemetry/TelemetryService.ts) to see the exact events we track.
For complete transparency, you can inspect our [telemetry implementation](https://github.com/cline/cline/blob/main/src/services/telemetry/TelemetryService.ts) to see the exact events we track.
### How to Opt Out
Telemetry in Cline is entirely optional:
- When you update or install our VS Code extension, you'll see a message about our telemetry
- When you update or install our VS Code extension, you'll see a message about our anonymous telemetry
- You can change your preference anytime in settings
Cline also respects VS Code's global telemetry settings. If you've disabled telemetry at the VS Code level, Cline's telemetry will automatically be disabled as well.
+10118
View File
File diff suppressed because it is too large Load Diff
+2 -4
View File
@@ -4,15 +4,13 @@
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "mintlify dev",
"check": "mintlify broken-links",
"rename": "mintlify rename"
"dev": "mintlify dev"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"mintlify": "^4.2.23"
"mintlify": "^4.0.538"
}
}
-61
View File
@@ -1,61 +0,0 @@
---
title: "Anthropic"
description: "Learn how to configure and use Anthropic Claude models with Cline. Covers API key setup, model selection, and advanced features like prompt caching."
---
**Website:** [https://www.anthropic.com/](https://www.anthropic.com/)
### Getting an API Key
1. **Sign Up/Sign In:** Go to the [Anthropic Console](https://console.anthropic.com/). Create an account or sign in.
2. **Navigate to API Keys:** Go to the [API keys](https://console.anthropic.com/settings/keys) section.
3. **Create a Key:** Click "Create Key". Give your key a descriptive name (e.g., "Cline").
4. **Copy the Key:** **Important:** Copy the API key _immediately_. You will not be able to see it again. Store it securely.
### Supported Models
Cline supports the following Anthropic Claude models:
- `claude-opus-4-20250514`
- `claude-opus-4-20250514:thinking` (Extended Thinking variant)
- `claude-sonnet-4-20250514` (Recommended)
- `claude-sonnet-4-20250514:thinking` (Extended Thinking variant)
- `claude-3-7-sonnet-20250219`
- `claude-3-7-sonnet-20250219:thinking` (Extended Thinking variant)
- `claude-3-5-sonnet-20241022`
- `claude-3-5-haiku-20241022`
- `claude-3-opus-20240229`
- `claude-3-haiku-20240307`
See [Anthropic's Model Documentation](https://docs.anthropic.com/en/docs/about-claude/models) for more details on each model's capabilities.
### Configuration in Cline
1. **Open Cline Settings:** Click the settings icon (⚙️) in the Cline panel.
2. **Select Provider:** Choose "Anthropic" from the "API Provider" dropdown.
3. **Enter API Key:** Paste your Anthropic API key into the "Anthropic API Key" field.
4. **Select Model:** Choose your desired Claude model from the "Model" dropdown.
5. **(Optional) Custom Base URL:** If you need to use a custom base URL for the Anthropic API, check "Use custom base URL" and enter the URL. Most users won't need to adjust this setting.
### Extended Thinking
Anthropic models offer an "Extended Thinking" feature, designed to give them enhanced reasoning capabilities for complex tasks. This feature allows the model to output its step-by-step thought process before delivering a final answer, providing transparency and enabling more thorough analysis for challenging prompts.
When extended thinking is in Cline, the model generates `thinking` content blocks that detail its internal reasoning. These insights are then incorporated into its final response.
Cline users can leverage this by checking the `Enable Extended Thinking` box below the model selection menu after selecting a Claude Model from any provider.
**Key Aspects of Extended Thinking:**
- **Supported Models:** This feature is available for select models, including variants of Claude Opus 4, Claude Sonnet 4, and Claude Sonnet 3.7. The specific models listed in the "Supported Models" section above with the `:thinking` suffix are pre-configured in Cline to utilize this.
- **Summarized Thinking (Claude 4):** For Claude 4 models, the API returns a summary of the full thinking process to balance insight with efficiency and prevent misuse. You are billed for the full thinking tokens, not just the summary.
- **Streaming:** Extended thinking responses, including the `thinking` blocks, can be streamed.
- **Tool Use & Prompt Caching:** Extended thinking interacts with tool use (requiring thinking blocks to be passed back) and prompt caching (with specific behaviors around cache invalidation and context).
For comprehensive details on how extended thinking works, including API examples, interaction with tool use, prompt caching, and pricing, please refer to the [official Anthropic documentation on Extended Thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking).
### Tips and Notes
- **Prompt Caching:** Claude 3 models support [prompt caching](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching), which can significantly reduce costs and latency for repeated prompts.
- **Context Window:** Claude models have large context windows (200,000 tokens), allowing you to include a significant amount of code and context in your prompts.
- **Pricing:** Refer to the [Anthropic Pricing](https://www.anthropic.com/pricing) page for the latest pricing information.
- **Rate Limits:** Anthropic has strict rate limits based on [usage tiers](https://docs.anthropic.com/en/api/rate-limits#requirements-to-advance-tier). If you're repeatedly hitting rate limits, consider contacting Anthropic sales or accessing Claude through a different provider like [OpenRouter](/provider-config/openrouter) or [Requesty](/provider-config/requesty).
@@ -1,135 +0,0 @@
---
title: "AWS Bedrock"
description: "Learn how to set up AWS Bedrock with Cline using credentials authentication. This guide covers AWS environment setup, regional access verification, and secure integration with the Cline VS Code extension."
---
### Overview
- **AWS Bedrock:** A fully managed service that offers access to leading generative AI models (e.g., Anthropic Claude, Amazon Nova) through AWS.\
[Learn more about AWS Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html).
- **Cline:** A VS Code extension that acts as a coding assistant by integrating with AI models—empowering developers to generate code, debug, and analyze data.
- **Developer Focus:** This guide is tailored for individual developers that want to enable access to frontier models via AWS Bedrock with a simplified setup using API Keys.
---
### Step 1: Prepare Your AWS Environment
#### 1.1 Individual user setup - Create a Bedrock API Key
For more detailed instructions check the [documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html).
1. **Sign in to the AWS Management Console:**\
[AWS Console](https://aws.amazon.com/console/)
2. **Access Bedrock Console:**
- [Bedrock Console](https://console.aws.amazon.com/bedrock)
- Create a new Long Lived API Key. This API Key will have by default the `AmazonBedrockLimitedAccess` IAM policy
[View AmazonBedrockLimitedAccess Policy Details](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html)
#### 1.2 Create or Modify the Policy
To ensure Cline can interact with AWS Bedrock, your IAM user or role needs specific permissions. While the `AmazonBedrockLimitedAccess` managed policy provides comprehensive access, for a more restricted and secure setup adhering to the principle of least privilege, the following minimal permissions are sufficient for Cline's core model invocation functionality:
- `bedrock:InvokeModel`
- `bedrock:InvokeModelWithResponseStream`
- `bedrock:CallWithBearerToken`
You can create a custom IAM policy with these permissions and attach it to your IAM user or role.
1. In the AWS IAM console, create a new policy.
2. Use the JSON editor to add the following policy document:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream", "bedrock:CallWithBearerToken"],
"Resource": "*" // For enhanced security, scope this to specific model ARNs if possible.
}
]
}
```
3. Name the policy (e.g., `ClineBedrockInvokeAccess`) and attach it to the IAM user associated with the key you created. The IAM user and the API key have the same prefix.
**Important Considerations:**
- **Model Listing in Cline:** The minimal permissions (`bedrock:InvokeModel`, `bedrock:InvokeModelWithResponseStream`) are sufficient for Cline to _use_ a model if you specify the model ID directly in Cline's settings. If you rely on Cline to dynamically list available Bedrock models, you might need additional permissions like `bedrock:ListFoundationModels`.
- **AWS Marketplace Subscriptions:** For third-party models (e.g., Anthropic Claude), the **`AmazonBedrockLimitedAccess`** policy grants you the necessary permissions to subscribe via the AWS Marketplace. There is no explicit access to be enabled. For Anthropic models you are still required to submit a First Time Use (FTU) form via the Console. If you get the following message in the Cline chat `[ERROR] Failed to process response: Model use case details have not been submitted for this account. Fill out the Anthropic use case details form before using the model.` then open the [Playground in the AWS Bedrock Console](https://console.aws.amazon.com/bedrock/home?#/text-generation-playground), select any Anthropic model and fill in the form (you might need to send a prompt first)
---
### Step 2: Verify Regional and Model Access
#### 2.1 Choose and Confirm a Region
1. **Select a Region:**\
AWS Bedrock is available in multiple regions (e.g., US East, Europe, Asia Pacific). Choose the region that meets your latency and compliance needs.\
[AWS Global Infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/)
2. **Verify Model Access:**
- **Note:** Some models are only accessible via an [Inference Profile](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html). In such case check the box "Cross Region Inference".
---
### Step 3: Configure the Cline VS Code Extension
#### 3.1 Install and Open Cline
1. **Install VS Code:**\
Download from the [VS Code website](https://code.visualstudio.com/).
2. **Install the Cline Extension:**
- Open VS Code.
- Go to the Extensions Marketplace (`Ctrl+Shift+X` or `Cmd+Shift+X`).
- Search for **Cline** and install it.
#### 3.2 Configure Cline Settings
1. **Open Cline Settings:**
- Click on the settings ⚙️ to select your API Provider.
2. **Select AWS Bedrock as the API Provider:**
- From the API Provider dropdown, choose **AWS Bedrock**.
3. **Enter Your AWS API Key:**
- Input your **API Key**
- Specify the correct **AWS Region** (e.g., `us-east-1` or your enterprise-approved region).
4. **Select a Model:**
- Choose an on-demand model (e.g., **anthropic.claude-3-5-sonnet-20241022-v2:0**).
5. **Save and Test:**
- Click **Done/Save** to apply your settings.
- Test the integration by sending a simple prompt (e.g., "Generate a Python function to check if a number is prime.").
---
### Step 4: Security, Monitoring, and Best Practices
1. **Secure Access:**
- Prefer AWS SSO/federated roles over long-lived API Key when possible.
- [AWS IAM Best Practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
2. **Enhance Network Security:**
- Consider setting up [AWS PrivateLink](https://docs.aws.amazon.com/vpc/latest/userguide/endpoint-services-overview.html) to securely connect to Bedrock.
3. **Monitor and Log Activity:**
- Enable AWS CloudTrail to log Bedrock API calls.
- Use CloudWatch to monitor metrics like invocation count, latency, and token usage.
- Set up alerts for abnormal activity.
4. **Handle Errors and Manage Costs:**
- Implement exponential backoff for throttling errors.
- Use AWS Cost Explorer and set billing alerts to track usage.\
[AWS Cost Management](https://docs.aws.amazon.com/cost-management/latest/userguide/what-is-aws-cost-management.html)
5. **Regular Audits and Compliance:**
- Periodically review IAM roles and CloudTrail logs.
- Follow internal data privacy and governance policies.
---
### Conclusion
By following these steps, your enterprise team can securely integrate AWS Bedrock with the Cline VS Code extension to accelerate development:
1. **Prepare Your AWS Environment:** Create or use a secure IAM role/user, attach the `AmazonBedrockLimitedAccess` policy, and ensure necessary permissions.
2. **Verify Region and Model Access:** Confirm that your selected region supports your required models.
3. **Configure Cline in VS Code:** Install and set up Cline with your AWS credentials and choose an appropriate model.
4. **Implement Security and Monitoring:** Use best practices for IAM, network security, monitoring, and cost management.
For further details, consult the [AWS Bedrock Documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html) and coordinate with your internal cloud team. Happy coding!
---
_This guide will be updated as AWS Bedrock and Cline evolve. Always refer to the latest documentation and internal policies for up-to-date practices._
-93
View File
@@ -1,93 +0,0 @@
---
title: "Claude Code"
description: "Use your Claude Max or Pro subscription with Cline instead of paying per token. Learn how to set up and configure the Claude Code provider."
---
**Website:** [https://docs.anthropic.com/en/docs/claude-code/setup](https://docs.anthropic.com/en/docs/claude-code/setup)
The Claude Code provider lets you use your existing Claude subscription with Cline. If you have Claude Max or Pro, this means you can use Claude in Cline without paying extra API costs.
<Frame>
<img
src="https://storage.googleapis.com/cline_public_images/docs/assets/claude-code-use-opus.gif"
alt="Using the Claude Code provider in Cline with Opus model"
/>
</Frame>
## Setup
First, you'll need to install and authenticate Claude Code on your system:
1. **Install Claude Code**: Follow Anthropic's [official setup guide](https://docs.anthropic.com/en/docs/claude-code/setup) to install and authenticate the Claude CLI.
2. **Configure in Cline**:
- Open Cline settings (⚙️ icon)
- Select **Claude Code** from the **API Provider** dropdown
- Set the path to your Claude CLI executable (usually just `claude` if it's in your PATH)
<Frame>
<img
src="https://storage.googleapis.com/cline_public_images/docs/assets/claude-code-setup.gif"
alt="Setting up the Claude Code provider in Cline"
/>
</Frame>
<br />
<Accordion title="Windows Setup">
Anthropic introduced full support for Claude Code on Windows. Follow the [instructions on how to set up Claude Code
normally](#setup) and make sure you have the latest Claude Code and Cline versions.
</Accordion>
### Finding your Claude Code path
If you're not sure where Claude Code is installed:
- **macOS / Linux**: Run `which claude` in your terminal
- **Windows (Command Prompt)**: Run `where claude`
- **Windows (PowerShell)**: Run `Get-Command claude`
## Supported Models
The Claude Code provider supports these models:
- `claude-sonnet-4-20250514` (Recommended)
- `claude-opus-4-20250514`
- `claude-3-7-sonnet-20250219`
- `claude-3-5-sonnet-20241022`
- `claude-3-5-haiku-20241022`
## How it works
When you use Claude Code with Cline, here's what happens behind the scenes:
Cline wraps the Claude Code CLI to handle your requests. Each time you send a message, Cline starts a new `claude` process, sends your conversation, and streams the response back. The AI reasoning comes from Claude Code, but all the actual file editing, terminal commands, and other tools are handled by Cline.
The main difference you'll notice is that responses don't stream character-by-character like other providers. Instead, Claude Code processes your full request before sending back the complete response.
## Limitations
There are a few things to keep in mind with Claude Code:
- Images in your messages get converted to text placeholders since Claude Code doesn't support image uploads through the CLI
- Prompt caching isn't available with this provider
- Responses don't stream in real-time like other providers
## Troubleshooting
If you run into issues:
**Authentication problems**: Make sure you're logged into Claude Code with your subscription account. Run `claude auth status` to check.
**Path issues**: Double-check that the Claude CLI path in Cline's settings is correct. Try running `claude --version` in your terminal to verify it's working.
**Still having trouble?** We're actively improving this integration. Report issues on our [GitHub](https://github.com/cline/cline/issues) or ask for help in our [Discord](https://discord.gg/cline).
## Usage with subscriptions
If you have a Claude Max subscription, your usage in Cline shows up as $0.00 in the billing interface since you're not paying additional API costs. Your usage still counts against your subscription limits, but you won't see per-token charges.
For more details about using Claude Code with your subscription, check out Anthropic's documentation:
- [Claude Code Setup Guide](https://docs.anthropic.com/en/docs/claude-code/setup)
- [Using Claude Code with Pro/Max Plans](https://support.anthropic.com/en/articles/11145838-using-claude-code-with-your-pro-or-max-plan)
-33
View File
@@ -1,33 +0,0 @@
---
title: "DeepSeek"
description: "Learn how to configure and use DeepSeek models like deepseek-chat and deepseek-reasoner with Cline."
---
Cline supports accessing models through the DeepSeek API, including `deepseek-chat` and `deepseek-reasoner`.
**Website:** [https://platform.deepseek.com/](https://platform.deepseek.com/)
### Getting an API Key
1. **Sign Up/Sign In:** Go to the [DeepSeek Platform](https://platform.deepseek.com/). Create an account or sign in.
2. **Navigate to API Keys:** Find your API keys in the [API keys](https://platform.deepseek.com/api_keys) section of the platform.
3. **Create a Key:** Click "Create new API key". Give your key a descriptive name (e.g., "Cline").
4. **Copy the Key:** **Important:** Copy the API key _immediately_. You will not be able to see it again. Store it securely.
### Supported Models
Cline supports the following DeepSeek models:
- `deepseek-v3-0324` (Recommended for coding tasks)
- `deepseek-r1` (Recommended for reasoning tasks)
### Configuration in Cline
1. **Open Cline Settings:** Click the ⚙️ icon in the Cline panel.
2. **Select Provider:** Choose "DeepSeek" from the "API Provider" dropdown.
3. **Enter API Key:** Paste your DeepSeek API key into the "DeepSeek API Key" field.
4. **Select Model:** Choose your desired model from the "Model" dropdown.
### Tips and Notes
- **Pricing:** Refer to the [DeepSeek Pricing](https://api-docs.deepseek.com/quick_start/pricing/) page for details on model costs.
-53
View File
@@ -1,53 +0,0 @@
---
title: "Mistral"
description: "Learn how to configure and use Mistral AI models, including Codestral, with Cline. Covers API key setup and model selection."
---
Cline supports accessing models through the Mistral AI API, including both standard Mistral models and the code-specialized Codestral model.
**Website:** [https://mistral.ai/](https://mistral.ai/)
### Getting an API Key
1. **Sign Up/Sign In:** Go to the [Mistral Platform](https://console.mistral.ai/). Create an account or sign in. You may need to go through a verification process.
2. **Create an API Key:**
- [La Plateforme API Key](https://console.mistral.ai/api-keys/) and/or
- [Codestral API Key](https://console.mistral.ai/codestral)
### Supported Models
Cline supports the following Mistral models:
- pixtral-large-2411
- ministral-3b-2410
- ministral-8b-2410
- mistral-small-latest
- mistral-medium-latest
- mistral-small-2501
- pixtral-12b-2409
- open-mistral-nemo-2407
- open-codestral-mamba
- codestral-2501
- devstral-small-2505
**Note:** Model availability and specifications may change.
Refer to the [Mistral AI documentation](https://docs.mistral.ai/api/) and [Mistral Model Overview](https://docs.mistral.ai/getting-started/models/models_overview/) for the most current information.
### Configuration in Cline
1. **Open Cline Settings:** Click the settings icon (⚙️) in the Cline panel.
2. **Select Provider:** Choose "Mistral" from the "API Provider" dropdown.
3. **Enter API Key:** Paste your Mistral API key into the "Mistral API Key" field if you're using a standard `mistral` model. If you intend to use `codestral-latest`, see the "Using Codestral" section below.
4. **Select Model:** Choose your desired model from the "Model" dropdown.
### Using Codestral
[Codestral](https://docs.mistral.ai/capabilities/code_generation/) is a model specifically designed for code generation and interaction.
For Codestral, you can use different endpoints (Default: codestral.mistral.ai).
If using the La Plateforme API Key for Codestral, change the **Codestral Base Url** to: `https://api.mistral.ai`
To use Codestral with Cline:
1. **Select "Mistral" as the API Provider in Cline Settings.**
2. **Select a Codestral Model** (e.g., `codestral-latest`) from the "Model" dropdown.
3. **Enter your Codestral API Key** (from `codestral.mistral.ai`) or your La Plateforme API Key (from `api.mistral.ai`) into the appropriate API key field in Cline.
-78
View File
@@ -1,78 +0,0 @@
---
title: "Ollama"
---
Cline supports running models locally using Ollama. This approach offers privacy, offline access, and potentially reduced costs. It requires some initial setup and a sufficiently powerful computer. Because of the present state of consumer hardware, it's not recommended to use Ollama with Cline as performance will likely be poor for average hardware configurations.
**Website:** [https://ollama.com/](https://ollama.com/)
### Setting up Ollama
1. **Download and Install Ollama:**
Obtain the Ollama installer for your operating system from the [Ollama website](https://ollama.com/) and follow their installation guide. Ensure Ollama is running. You can typically start it with:
```bash
ollama serve
```
2. **Download a Model:**
Ollama supports a wide variety of models. A list of available models can be found on the [Ollama model library](https://ollama.com/library). Some models recommended for coding tasks include:
- `codellama:7b-code` (a good, smaller starting point)
- `codellama:13b-code` (offers better quality, larger size)
- `codellama:34b-code` (provides even higher quality, very large)
- `qwen2.5-coder:32b`
- `mistralai/Mistral-7B-Instruct-v0.1` (a solid general-purpose model)
- `deepseek-coder:6.7b-base` (effective for coding)
- `llama3:8b-instruct-q5_1` (suitable for general tasks)
To download a model, open your terminal and execute:
```bash
ollama pull <model_name>
```
For instance:
```bash
ollama pull qwen2.5-coder:32b
```
3. **Configure the Model's Context Window:**
By default, Ollama models often use a context window of 2048 tokens, which can be insufficient for many Cline requests. A minimum of 12,000 tokens is advisable for decent results, with 32,000 tokens being ideal. To adjust this, you'll modify the model's parameters and save it as a new version.
First, load the model (using `qwen2.5-coder:32b` as an example):
```bash
ollama run qwen2.5-coder:32b
```
Once the model is loaded within the Ollama interactive session, set the context size parameter:
```
/set parameter num_ctx 32768
```
Then, save this configured model with a new name:
```
/save your_custom_model_name
```
(Replace `your_custom_model_name` with a name of your choice.)
4. **Configure Cline:**
- Open the Cline sidebar (usually indicated by the Cline icon).
- Click the settings gear icon (⚙️).
- Select "ollama" as the API Provider.
- Enter the Model name you saved in the previous step (e.g., `your_custom_model_name`).
- (Optional) Adjust the base URL if Ollama is running on a different machine or port. The default is `http://localhost:11434`.
- (Optional) Configure the Model context size in Cline's Advanced settings. This helps Cline manage its context window effectively with your customized Ollama model.
### Tips and Notes
- **Resource Demands:** Running large language models locally can be demanding on system resources. Ensure your computer meets the requirements for your chosen model.
- **Model Choice:** Experiment with various models to discover which best fits your specific tasks and preferences.
- **Offline Capability:** After downloading a model, you can use Cline with that model even without an internet connection.
- **Token Usage Tracking:** Cline tracks token usage for models accessed via Ollama, allowing you to monitor consumption.
- **Ollama's Own Documentation:** For more detailed information, consult the official [Ollama documentation](https://ollama.com/docs).
@@ -1,72 +0,0 @@
---
title: "OpenAI Compatible"
description: "Learn how to configure Cline with various AI model providers that offer OpenAI-compatible APIs."
---
Cline supports a wide range of AI model providers that offer APIs compatible with the OpenAI API standard. This allows you to use models from providers _other than_ OpenAI, while still utilizing a familiar API interface. This includes providers such as:
- **Local models** running through tools like Ollama and LM Studio (which are covered in their respective sections).
- **Cloud providers** like Perplexity, Together AI, Anyscale, and many others.
- **Any other provider** that offers an OpenAI-compatible API endpoint.
This document focuses on setting up providers _other than_ the official OpenAI API (which has its own [dedicated configuration page](/provider-config/openai)).
### General Configuration
The key to using an OpenAI-compatible provider with Cline is to configure these main settings:
1. **Base URL:** This is the API endpoint specific to the provider. It will _not_ be `https://api.openai.com/v1` (that URL is for the official OpenAI API).
2. **API Key:** This is the secret key you obtain from your chosen provider.
3. **Model ID:** This is the specific name or identifier for the model you wish to use.
You'll find these settings in the Cline settings panel (click the ⚙️ icon):
- **API Provider:** Select "OpenAI Compatible".
- **Base URL:** Enter the base URL provided by your chosen provider. **This is a crucial step.**
- **API Key:** Enter your API key from the provider.
- **Model:** Choose or enter the model ID.
- **Model Configuration:** This section allows you to customize advanced parameters for the model, such as:
- Max Output Tokens
- Context Window size
- Image Support capabilities
- Computer Use (e.g., for models with tool/function calling)
- Input Price (per token/million tokens)
- Output Price (per token/million tokens)
### Supported Models (for OpenAI Native Endpoint)
While the "OpenAI Compatible" provider type allows connecting to various endpoints, if you are connecting directly to the official OpenAI API (or an endpoint that mirrors it exactly), Cline recognizes the following model IDs based on the `openAiNativeModels` definition in its source code:
- `o3-mini`
- `o3-mini-high`
- `o3-mini-low`
- `o1`
- `o1-preview`
- `o1-mini`
- `gpt-4.5-preview`
- `gpt-4o`
- `gpt-4o-mini`
**Note:** If you are using a different OpenAI-compatible provider (such as Together AI, Anyscale, etc.), the available model IDs will differ. Always refer to your specific provider's documentation for their supported model names and any unique configuration details.
### v0 (Vercel SDK) in Cline:
- For developers working with v0, their [AI SDK documentation](https://vercel.com/docs/v0/cline) provides valuable insights and examples for integrating various models, many of which are OpenAI-compatible. This can be a helpful resource for understanding how to structure calls and manage configurations when using Cline with services deployed on or integrated with Vercel.
- v0 can be used in Cline with the OpenAI Compatible provider.
- ### Quickstart
- 1. With the OpenAI Compatible provider selected, set the Base URL to https://api.v0.dev/v1.
- 2. Paste in your v0 API Key
- 3. Set the Model ID: v0-1.0-md
- 4. Click Verify to confirm the connection.
### Troubleshooting
- **"Invalid API Key":** Double-check that you've entered the API key correctly and that it's for the correct provider.
- **"Model Not Found":** Ensure you're using a valid model ID for your chosen provider and that it's available at the specified Base URL.
- **Connection Errors:** Verify the Base URL is correct, that your provider's API is accessible from your machine, and that there are no firewall or network issues.
- **Unexpected Results:** If you're getting unexpected outputs, try a different model or double-check all configuration parameters.
By using an OpenAI-compatible provider, you can leverage the flexibility of Cline with a wider array of AI models. Remember to always consult your provider's documentation for the most accurate and up-to-date information.
-48
View File
@@ -1,48 +0,0 @@
---
title: "OpenAI"
description: "Learn how to configure and use official OpenAI models with Cline."
---
Cline supports accessing models directly through the official OpenAI API.
**Website:** [https://openai.com/](https://openai.com/)
### Getting an API Key
1. **Sign Up/Sign In:** Visit the [OpenAI Platform](https://platform.openai.com/). You'll need to create an account or sign in if you already have one.
2. **Navigate to API Keys:** Once logged in, go to the [API keys section](https://platform.openai.com/api-keys) of your account.
3. **Create a Key:** Click on "Create new secret key". It's good practice to give your key a descriptive name (e.g., "Cline API Key").
4. **Copy the Key:** **Crucial:** Copy the generated API key immediately. For security reasons, OpenAI will not show it to you again. Store this key in a safe and secure location.
### Supported Models
Cline is compatible with a variety of OpenAI models, including but not limited to:
- 'o3'
- `o3-mini` (medium reasoning effort)
- 'o4-mini'
- `o3-mini-high` (high reasoning effort)
- `o3-mini-low` (low reasoning effort)
- `o1`
- `o1-preview`
- `o1-mini`
- `gpt-4.5-preview`
- `gpt-4o`
- `gpt-4o-mini`
- 'gpt-4.1'
- 'gpt-4.1-mini'
For the most current list of available models and their capabilities, please refer to the official [OpenAI Models documentation](https://platform.openai.com/docs/models).
### Configuration in Cline
1. **Open Cline Settings:** Click the settings gear icon (⚙️) in the Cline panel.
2. **Select Provider:** Choose "OpenAI" from the "API Provider" dropdown menu.
3. **Enter API Key:** Paste your OpenAI API key into the "OpenAI API Key" field.
4. **Select Model:** Choose your desired model from the "Model" dropdown list.
5. **(Optional) Base URL:** If you need to use a proxy or a custom base URL for the OpenAI API, you can enter it here. Most users will not need to change this from the default.
### Tips and Notes
- **Pricing:** Be sure to review the [OpenAI Pricing page](https://openai.com/pricing) for detailed information on the costs associated with different models.
- **Azure OpenAI Service:** If you are looking to use the Azure OpenAI service, please note that specific documentation for Azure OpenAI with Cline may be found separately, or you might need to configure it as an OpenAI-compatible endpoint if such functionality is supported by Cline for custom configurations.
-40
View File
@@ -1,40 +0,0 @@
---
title: "OpenRouter"
description: "Learn how to use OpenRouter with Cline to access a wide variety of language models through a single API."
---
OpenRouter is an AI platform that provides access to a wide variety of language models from different providers, all through a single API. This can simplify setup and allow you to easily experiment with different models.
**Website:** [https://openrouter.ai/](https://openrouter.ai/)
### Getting an API Key
1. **Sign Up/Sign In:** Go to the [OpenRouter website](https://openrouter.ai/). Sign in with your Google or GitHub account.
2. **Get an API Key:** Go to the [keys page](https://openrouter.ai/keys). You should see an API key listed. If not, create a new key.
3. **Copy the Key:** Copy the API key.
### Supported Models
OpenRouter supports a large and growing number of models. Cline automatically fetches the list of available models. Refer to the [OpenRouter Models page](https://openrouter.ai/models) for the complete and up-to-date list.
### Configuration in Cline
1. **Open Cline Settings:** Click the settings icon (⚙️) in the Cline panel.
2. **Select Provider:** Choose "OpenRouter" from the "API Provider" dropdown.
3. **Enter API Key:** Paste your OpenRouter API key into the "OpenRouter API Key" field.
4. **Select Model:** Choose your desired model from the "Model" dropdown.
5. **(Optional) Custom Base URL:** If you need to use a custom base URL for the OpenRouter API, check "Use custom base URL" and enter the URL. Leave this blank for most users.
### Supported Transforms
OpenRouter provides an [optional "middle-out" message transform](https://openrouter.ai/docs/features/message-transforms) to help with prompts that exceed the maximum context size of a model. You can enable it by checking the "Compress prompts and message chains to the context size" box.
### Tips and Notes
- **Model Selection:** OpenRouter offers a wide range of models. Experiment to find the best one for your needs.
- **Pricing:** OpenRouter charges based on the underlying model's pricing. See the [OpenRouter Models page](https://openrouter.ai/models) for details.
- **Prompt Caching:**
- OpenRouter passes caching requests to underlying models that support it. Check the [OpenRouter Models page](https://openrouter.ai/models) to see which models offer caching.
- For most models, caching should activate automatically if supported by the model itself (similar to how Requesty works).
- **Exception for Gemini Models via OpenRouter:** Due to potential response delays sometimes observed with Google's caching mechanism when accessed via OpenRouter, a manual activation step is required _specifically for Gemini models_.
- If using a **Gemini model** via OpenRouter, you **must manually check** the "Enable Prompt Caching" box in the provider settings to activate caching for that model. This checkbox serves as a temporary workaround. For non-Gemini models on OpenRouter, this checkbox is not necessary for caching.
-38
View File
@@ -1,38 +0,0 @@
---
title: "Requesty"
description: "Learn how to use Requesty with Cline to access and optimize over 150 large language models."
---
Cline supports accessing models through the [Requesty](https://www.requesty.ai/) AI platform. Requesty provides an easy and optimized API for interacting with 150+ large language models (LLMs).
**Website:** [https://www.requesty.ai/](https://www.requesty.ai/)
### Getting an API Key
1. **Sign Up/Sign In:** Go to the [Requesty website](https://www.requesty.ai/) and create an account or sign in.
2. **Get API Key:** You can get an API key from the [API Management](https://app.requesty.ai/manage-api) section of your Requesty dashboard.
### Supported Models
Requesty provides access to a wide range of models. Cline will automatically fetch the latest list of available models. You can see the full list of available models on the [Model List](https://app.requesty.ai/router/list) page.
### Configuration in Cline
1. **Open Cline Settings:** Click the settings icon (⚙️) in the Cline panel.
2. **Select Provider:** Choose "Requesty" from the "API Provider" dropdown.
3. **Enter API Key:** Paste your Requesty API key into the "Requesty API Key" field.
4. **Select Model:** Choose your desired model from the "Model" dropdown.
### Tips and Notes
- **Optimizations**: Requesty offers a range of in-flight cost optimizations to lower your costs.
- **Unified and simplified billing**: Unrestricted access to all providers and models, automatic balance top ups and more via a single [API key](https://app.requesty.ai/manage-api).
- **Cost tracking**: Track cost per model, coding language, changed file, and more via the [Cost dashboard](https://app.requesty.ai/cost-management) or the [Requesty VS Code extension](https://marketplace.visualstudio.com/items?itemName=Requesty.requesty).
- **Stats and logs**: See your [coding stats dashboard](https://app.requesty.ai/usage-stats) or go through your [LLM interaction logs](https://app.requesty.ai/logs).
- **Fallback policies**: Keep your LLM working for you with fallback policies when providers are down.
- **Prompt Caching:** Some providers support prompt caching. [Search models with caching](https://app.requesty.ai/router/list).
### Relevant resources
- [Requesty Youtube channel](https://www.youtube.com/@requestyAI)
- [Requesty Discord](https://requesty.ai/discord)
-39
View File
@@ -1,39 +0,0 @@
---
title: "SAP AI Core"
description: "Learn how to configure and use LLM models from Generative AI Hub in SAP AI Core with Cline."
---
SAP AI Core and the generative AI hub help you to integrate LLMs and AI into new business processes in a cost-efficient manner.
**Website:** [SAP Help Portal](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/what-is-sap-ai-core)
### Getting a Service Binding
> 💡 **Information**
>
> SAP AI Core, and Generative AI Hub, are offerings from SAP BTP.
> You need an active SAP BTP contract and a existing subaccount with a SAP AI Core instance to perform these steps.
1. **Access:** Go to your subaccount via [BTP Cloud Cockpit](cockpit.btp.cloud.sap/cockpit)
2. **Create a Service Binding:** Go to "Instances and Subscriptions", select your SAP AI Core service instance and click on Service Bindings > Create.
3. **Copy the Service Binding:** Copy the service binding values.
### Supported Models
SAP AI Core supports a large and growing number of models.
Refer to the [Generative AI Hub Supported Models page](https://me.sap.com/notes/3437766) for the complete and up-to-date list.
### Configuration in Cline
1. **Open Cline Settings:** Click the settings icon (⚙️) in the Cline panel.
2. **Select Provider:** Choose "SAP AI Core" from the "API Provider" dropdown.
3. **Enter Client Id:** Add the `.clientid` field from the service binding into the "AI Core Client Id" field.
4. **Enter Client Secret:** Add the `.clientsecret` field from the service binding into the "AI Core Client Secret" field.
5. **Enter Base URL:** Add the `.serviceurls.AI_API_URL` field from the service binding into the "AI Core Base URL" field.
6. **Enter Auth URL:** Add the `.url` field from the service binding into the "AI Core Auth URL" field.
7. **Enter Resource Group:** Add the resource group where you have your model deployments. See [Create a Deployment for a Generative AI Model](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-generative-ai-model-in-sap-ai-core).
8. **Select Model:** Choose your desired model from the "Model" dropdown.
### Tips and Notes
- **Model Selection:** SAP AI Core offers a wide range of models. You won't be able to use the model, even if selected, if a deployment doesn't exist in the provided resource group.
@@ -1,51 +0,0 @@
---
title: "VS Code Language Model API"
description: "Learn how to use Cline with the experimental VS Code Language Model API, enabling access to models from GitHub Copilot and other compatible extensions."
---
Cline offers _experimental_ support for the [VS Code Language Model API](https://code.visualstudio.com/api/extension-guides/language-model). This API enables extensions to grant access to language models directly within the VS Code environment. Consequently, you might be able to leverage models from:
- **GitHub Copilot:** Provided you have an active Copilot subscription and the extension installed.
- **Other VS Code Extensions:** Any extension that implements the Language Model API.
**Important Note:** This integration is currently in an experimental phase and might not perform as anticipated. Its functionality relies on other extensions correctly implementing the VS Code Language Model API.
### Prerequisites
- **VS Code:** The Language Model API is accessible via VS Code (it is not currently supported by Cursor).
- **A Language Model Provider Extension:** An extension that furnishes a language model is required. Examples include:
- **GitHub Copilot:** With a Copilot subscription, the GitHub Copilot and GitHub Copilot Chat extensions can serve as model providers.
- **Alternative Extensions:** Explore the VS Code Marketplace for extensions mentioning "Language Model API" or "lm". Other experimental options may be available
### Configuration Steps
1. **Ensure Copilot Account is Active and Extensions are installed:** User logged into either the Copilot or Copilot Chat extension should be able to gain access via Cline.
2. **Access Cline Settings:** Click the gear icon (⚙️) located in the Cline panel.
3. **Choose Provider:** Select "VS Code LM API" from the "API Provider" dropdown menu.
4. **Select Model:** If the Copilot extension(s) are installed and the user is logged into their Copilot account, the "Language Model" dropdown will populate with available models after a short time. The naming convention is `vendor/family`. For instance, if Copilot is active, you might encounter options such as:
- `copilot - gpt-3.5-turbo`
- `copilot - gpt-4o-mini`
- `copilot - gpt-4`
- `copilot - gpt-4-turbo`
- `copilot - gpt-4o`
- `copilot - claude-3.5-sonnet` **NOTE:** this model does not work.
- `copilot - gemini-2.0-flash`
- `copilot - gpt-4.1`
For best results with the VSCode LM API Provider, we suggest using the OpenAI Models (GPT 3, 4, 4.1, 4o etc.)
### Current Limitations
- **Experimental API Status:** The VS Code Language Model API is still under active development. Anticipate potential changes and instability.
- **Dependency on Extensions:** This feature is entirely contingent on other extensions making models available. Cline does not directly control the list of accessible models.
- **Restricted Functionality:** The VS Code Language Model API might not encompass all features available through other API providers (e.g., image input capabilities, streaming responses, detailed usage metrics).
- **No Direct Cost Management:** Users are subject to the pricing structures and terms of service of the extension providing the model. Cline cannot directly monitor or regulate associated costs.
- **GitHub Copilot Rate Throttling:** When employing the VS Code LM API with GitHub Copilot, be mindful that GitHub may enforce rate limits on Copilot usage. These limitations are governed by GitHub, not Cline.
### Troubleshooting Tips
- **Models Not Appearing:**
- Confirm that VS Code is installed.
- Verify that a language model provider extension (e.g., GitHub Copilot, GitHub Copilot Chat) is installed and enabled.
- If utilizing Copilot, ensure you have previously sent a Copilot Chat message using the desired model.
- **Unexpected Operation:** Should you encounter unforeseen behavior, it is likely an issue stemming from the underlying Language Model API or the provider extension. Consider reporting the problem to the developers of the provider extension.
-85
View File
@@ -1,85 +0,0 @@
---
title: "xAI (Grok)"
description: "Learn how to configure and use xAI's Grok models with Cline, including API key setup, supported models, and reasoning capabilities."
---
xAI is the company behind Grok, a large language model known for its conversational abilities and large context window. Grok models are designed to provide helpful, informative, and contextually relevant responses.
**Website:** [https://x.ai/](https://x.ai/)
### Getting an API Key
1. **Sign Up/Sign In:** Go to the [xAI Console](https://console.x.ai/). Create an account or sign in.
2. **Navigate to API Keys:** Go to the API keys section in your dashboard.
3. **Create a Key:** Click to create a new API key. Give your key a descriptive name (e.g., "Cline").
4. **Copy the Key:** **Important:** Copy the API key _immediately_. You will not be able to see it again. Store it securely.
### Supported Models
Cline supports the following xAI Grok models:
#### Grok-3 Models
- `grok-3-beta` (Default) - xAI's Grok-3 beta model with 131K context window
- `grok-3-fast-beta` - xAI's Grok-3 fast beta model with 131K context window
- `grok-3-mini-beta` - xAI's Grok-3 mini beta model with 131K context window
- `grok-3-mini-fast-beta` - xAI's Grok-3 mini fast beta model with 131K context window
#### Grok-2 Models
- `grok-2-latest` - xAI's Grok-2 model - latest version with 131K context window
- `grok-2` - xAI's Grok-2 model with 131K context window
- `grok-2-1212` - xAI's Grok-2 model (version 1212) with 131K context window
#### Grok Vision Models
- `grok-2-vision-latest` - xAI's Grok-2 Vision model - latest version with image support and 32K context window
- `grok-2-vision` - xAI's Grok-2 Vision model with image support and 32K context window
- `grok-2-vision-1212` - xAI's Grok-2 Vision model (version 1212) with image support and 32K context window
- `grok-vision-beta` - xAI's Grok Vision Beta model with image support and 8K context window
#### Legacy Models
- `grok-beta` - xAI's Grok Beta model (legacy) with 131K context window
### Configuration in Cline
1. **Open Cline Settings:** Click the settings icon (⚙️) in the Cline panel.
2. **Select Provider:** Choose "xAI" from the "API Provider" dropdown.
3. **Enter API Key:** Paste your xAI API key into the "xAI API Key" field.
4. **Select Model:** Choose your desired Grok model from the "Model" dropdown.
### Reasoning Capabilities
Grok 3 Mini models feature specialized reasoning capabilities, allowing them to "think before responding" - particularly useful for complex problem-solving tasks.
#### Reasoning-Enabled Models
Reasoning is only supported by:
- `grok-3-mini-beta`
- `grok-3-mini-fast-beta`
The Grok 3 models `grok-3-beta` and `grok-3-fast-beta` do not support reasoning.
#### Controlling Reasoning Effort
When using reasoning-enabled models, you can control how hard the model thinks with the `reasoning_effort` parameter:
- `low`: Minimal thinking time, using fewer tokens for quick responses
- `high`: Maximum thinking time, leveraging more tokens for complex problems
Choose `low` for simple queries that should complete quickly, and `high` for harder problems where response latency is less important.
#### Key Features
- **Step-by-Step Problem Solving**: The model thinks through problems methodically before delivering an answer
- **Math & Quantitative Strength**: Excels at numerical challenges and logic puzzles
- **Reasoning Trace Access**: The model's thinking process is available via the `reasoning_content` field in the response completion object
### Tips and Notes
- **Context Window:** Most Grok models feature large context windows (up to 131K tokens), allowing you to include substantial amounts of code and context in your prompts.
- **Vision Capabilities:** Select vision-enabled models (`grok-2-vision-latest`, `grok-2-vision`, etc.) when you need to process or analyze images.
- **Pricing:** Pricing varies by model, with input costs ranging from $0.3 to $5.0 per million tokens and output costs from $0.5 to $25.0 per million tokens. Refer to the xAI documentation for the most current pricing information.
- **Performance Tradeoffs:** "Fast" variants typically offer quicker response times but may have higher costs, while "mini" variants are more economical but may have reduced capabilities.
@@ -1,446 +0,0 @@
---
title: "Terminal Integration Troubleshooting Guide"
sidebarTitle: "Terminal Troubleshooting"
description: "Complete guide to resolving terminal integration issues in Cline"
---
This guide helps you resolve terminal integration issues in Cline. Terminal integration is crucial for Cline to execute commands and read their output, enabling it to understand errors, test results, and command responses.
<Tip>
If you're experiencing terminal issues, try switching to a simpler shell like `bash` in the Cline settings, under "Terminal Settings"
This resolves most terminal integration problems.
</Tip>
## Quick Diagnosis Flowchart
Follow this flowchart to quickly identify your issue:
```mermaid
graph TD
A[Terminal Issue] --> B{Can Cline execute commands?}
B -->|No| C[Shell Integration Unavailable]
B -->|Yes| D{Can Cline see the output?}
D -->|No| E[Output Capture Failed]
D -->|Yes| F{Is the output corrupted?}
F -->|Yes| G[Character Filtering Issue]
F -->|No| H{Does the command hang?}
H -->|Yes| I[Long-Running Command Issue]
H -->|No| J[Check Terminal Settings]
C --> K[Try Solution 1]
E --> L[Try Solution 2]
G --> M[Try Solution 3]
I --> N[Try Solution 4]
style A fill:#f9f,stroke:#333,stroke-width:2px
style K fill:#9f9,stroke:#333,stroke-width:2px
style L fill:#9f9,stroke:#333,stroke-width:2px
style M fill:#9f9,stroke:#333,stroke-width:2px
style N fill:#9f9,stroke:#333,stroke-width:2px
```
## Common Issues & Quick Solutions
### 1. Shell Integration Unavailable
**Symptoms:**
- Message: "Shell Integration Unavailable"
- Commands execute but Cline can't read output
- Terminal works fine manually but not with Cline
**Quick Solutions:**
#### macOS
- **Switch to bash**
1. Go to Cline Settings
2. Left-Click the **"Terminal Settings"** tab
3. Navigate to **"Default Terminal Profile"** and select **"bash"** from the drop-down menu
- **Disable Oh-My-Zsh temporarily**:
1. If using zsh, enter `mv ~/.zshrc ~/.zshrc.backup` into the terminal
2. Restart VSCode
- **Set environment**:
1.a For Zsh users, use one of the following Zsh commands to edit your shell profile:
- `nano ~/.zshrc`
- `vim ~/.zshrc`
- `code ~/.zshrc`
1.b For Bash users
- nano ~/.bash_profile
2. Add the following to your shell config: `export TERM=xterm-256color`
3. Save your configuration
#### Windows
- **Use PowerShell 7**
1. Install from Microsoft Store
2. Go to Cline Settings
3. Left-Click the **"Terminal Settings"** tab
4. Navigate to **"Default Terminal Profile"** and select **"PowerShell 7"** from the drop-down menu
- **Disable Windows ConPTY**
1. Navigate to your VSCode Settings
2. Enter "Integrated: Windows Enable Conpty" into the Settings searchbar
3. Uncheck the option
- **Try Command Prompt**
1. Go to Cline Settings
2. Left-Click the **"Terminal Settings"** tab
3. Navigate to **"Default Terminal Profile"** and select **"Command Prompt"** from the drop-down menu
#### Linux
- **Use bash**
1. Go to Cline Settings
2. Left-Click the **"Terminal Settings"** tab
3. Navigate to **"Default Terminal Profile"** and select **"bash"** from the drop-down menu
- **Check permissions**
1. Ensure VSCode has terminal access permissions
- **Disable custom prompts**
1. Comment out prompt customizations in `.bashrc`
### 2. Command Output Not Visible
**Symptoms:**
- Cline states in chat: "[Command is running but producing no output]"
- Commands complete but Cline doesn't see results
- Commands work sometimes but not consistently
**Solutions:**
- **Increase Shell Integration Timeout**
1. Within Cline, left-click the **Settings** button in the top right-hand corner of the chat window
2. Once in the **Settings** window, left-click the **"Terminal Settings"** tab from the left-hand column
3. Navigate to "Shell integration timeout (seconds)" and enter **"10"** into the text field
- **Disable Terminal Reuse**
1. Within Cline, left-click the **Settings** button in the top right-hand corner of the chat window
2. Once in the **Settings** window, left-click the **"Terminal Settings"** tab from the left-hand column
3. Look for **"Enable aggressive terminal reuse"**, and **uncheck** this option
- **Check for interfering extensions**
1. Disable other terminal-related VSCode extensions
### 3. Character Filtering Issues
**Symptoms:**
- Commas missing from output (JSON appears corrupted)
- Special characters stripped from terminal output
- Syntax errors that don't appear when running manually
**Solution:**
This is a known bug in output processing. Workarounds:
- Recommend AI to use file output instead
1. Tell Cline in chat or Cline rules, to use `command > output.txt` before reading the file/s
<Tip>
This family of issues is only partially solved in the latest Cline versions, so if you still face this, create a GitHub issue
if it is a persistent problem.
</Tip>
### 4. Long-Running Commands & Progress Bars
**Symptoms:**
- Docker builds never complete in Cline
- Progress bars consume thousands of tokens
- The Cline button "Proceed while running" doesn't work properly in chat
<Tip>
This family of issues has been solved in latest Cline versions but if you still face any issues, then create a GitHub issue
for this.
</Tip>
## Terminal Settings Explained
Access these in Cline by clicking the settings icon, and navigating to the "Terminal Settings" section:
### Default Terminal Profile
- **What it does**: Selects which shell Cline uses for commands
- **When to change**: If experiencing shell integration issues with your default shell
- **Recommended**: - macOS: bash (if zsh has issues) - Windows: PowerShell 7 - Linux: bash
### Shell Integration Timeout
- **What it does**: How long Cline waits for the terminal to be ready
- **Default**: 4 seconds
- **When to increase**:
- Slow shell startup (heavy .zshrc/.bashrc)
- WSL environments
- SSH connections
- **Recommended**: - Start with 10 seconds if having issues
### Enable Aggressive Terminal Reuse
- **What it does**: Reuses existing terminals even if not in the correct directory
- **When to disable**:
- Commands execute in wrong directory
- Virtual environment issues
- Terminal state corruption
- **Trade-off**: - Disabling creates more terminals but ensures clean state
### Terminal Output Line Limit
- **What it does**: Limits how many lines Cline reads from terminal output
- **Default**: 500 lines
- **When to adjust**:
- Increase for verbose build outputs
- Decrease if hitting token limits
- Set to 100 for commands with progress bars
## Platform-Specific Solutions
### macOS Issues
#### Oh-My-Zsh Conflicts
Oh-My-Zsh often interferes with shell integration. Solutions:
1. Create a minimal `.zshrc` for VSCode:
```bash
# ~/.zshrc-vscode
export TERM=xterm-256color
export PAGER=cat
# Minimal PATH and environment setup
```
2. Configure VSCode to use it:
```json
{
"terminal.integrated.env.osx": {
"ZDOTDIR": "~/.zshrc-vscode"
}
}
```
#### macOS 15+ Issues
Recent macOS versions have stricter terminal permissions:
1. System Preferences → Privacy & Security → Developer Tools
2. Add Visual Studio Code
3. Restart VSCode completely
### Windows Issues
If you're using Windows and still experiencing issues with shell integration after trying the previous steps, it's recommended you use Git Bash (or PowerShell).
### Git Bash
Git Bash is a terminal emulator that provides a Unix-like command line experience on Windows. To use Git Bash, you need to:
1. Download and run the Git for Windows installer from [https://git-scm.com/downloads/win](https://git-scm.com/downloads/win)
2. Quit and re-open VSCode
3. Press `Ctrl + Shift + P` to open the Command Palette
4. Type "Terminal: Select Default Profile" and choose it
5. Select "Git Bash"
### PowerShell
If you'd still like to use PowerShell, make sure you're using an updated version (at least v7+).
- Check your current PowerShell version by running: `$PSVersionTable.PSVersion`
- If your version is below 7, [update PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.4#installing-powershell-7).
You may also need to adjust your PowerShell execution policy. By default, PowerShell restricts script execution for security reasons.
#### Understanding PowerShell Execution Policies
PowerShell uses execution policies to determine which scripts can run on your system. Here are the most common policies:
- `Restricted`: No PowerShell scripts can run. This is the default setting.
- `AllSigned`: All scripts, including local ones, must be signed by a trusted publisher.
- `RemoteSigned`: Scripts created locally can run, but scripts downloaded from the internet must be signed.
- `Unrestricted`: No restrictions. Any script can run, though you will be warned before running internet-downloaded scripts.
For development work in VSCode, the `RemoteSigned` policy is generally recommended. It allows locally created scripts to run without restrictions while maintaining security for downloaded scripts. To learn more about PowerShell execution policies and understand the security implications of changing them, visit Microsoft's documentation: [About Execution Policies](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies).
#### Steps to Change the Execution Policy
1. Open PowerShell as an Administrator: Press `Win + X` and select "Windows PowerShell (Administrator)" or "Windows Terminal (Administrator)".
2. Check Current Execution Policy by running this command:
```powershell
Get-ExecutionPolicy
```
- If the output is already `RemoteSigned`, `Unrestricted`, or `Bypass`, you likely don't need to change your execution policy. These policies should allow shell integration to work.
- If the output is `Restricted` or `AllSigned`, you may need to change your policy to enable shell integration.
3. Change the Execution Policy by running the following command:
```powershell
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
```
- This sets the policy to `RemoteSigned` for the current user only, which is safer than changing it system-wide.
4. Confirm the Change by typing `Y` and pressing Enter when prompted.
5. Verify the Policy Change by running `Get-ExecutionPolicy` again to confirm the new setting.
6. Restart VSCode and try the shell integration again.
#### WSL Integration
For WSL issues:
1. Use WSL extension for VSCode
2. Open folder in WSL: `code .` from WSL terminal
3. Select "WSL Bash" as terminal profile in Cline
#### Path Issues
Windows path problems:
1. Use forward slashes in Cline: `C:/Users/...`
2. Quote paths with spaces: `"C:/Program Files/..."`
3. Avoid `~` - use full paths
### Linux/SSH/Container Issues
#### SSH Connections
For remote development:
1. Install Cline on the remote machine, not locally
2. Use SSH extension's integrated terminal
3. Increase timeout to 15+ seconds
#### Docker Containers
When developing in containers:
1. Install Cline in the container
2. Use Dev Containers extension
3. Ensure shell integration scripts are available
## Shell-Specific Fixes
### Zsh
```bash
# Add to ~/.zshrc
export TERM=xterm-256color
export PAGER=cat
# Disable fancy prompts for VSCode
if [[ "$TERM_PROGRAM" == "vscode" ]]; then
PS1="%n@%m %1~ %# "
fi
```
### Bash
```bash
# Add to ~/.bashrc
export TERM=xterm-256color
export PAGER=cat
# Simple prompt for VSCode
if [[ "$TERM_PROGRAM" == "vscode" ]]; then
PS1='\u@\h:\w\$ '
fi
```
### Fish
```fish
# Add to ~/.config/fish/config.fish
set -x TERM xterm-256color
set -x PAGER cat
# Disable fancy features in VSCode
if test "$TERM_PROGRAM" = "vscode"
function fish_prompt
echo (whoami)'@'(hostname)':'(pwd)'> '
end
end
```
### PowerShell
```powershell
# Add to $PROFILE
$env:PAGER = "cat"
# Disable progress bars
$ProgressPreference = 'SilentlyContinue'
```
## Advanced Troubleshooting
### Debug Mode
Enable terminal debugging to see what's happening:
1. Open VSCode Command Palette (Cmd/Ctrl+Shift+P)
2. Run: "Developer: Set Log Level..."
3. Choose "Trace"
4. Check Output panel → "Cline" for terminal logs
### Manual Shell Integration Test
Test if shell integration works at all:
```bash
# In VSCode terminal
echo $TERM_PROGRAM # Should show "vscode"
echo $VSCODE_SHELL_INTEGRATION # Should be "1"
```
## FAQ
### Why does Cline create so many terminals?
When shell integration fails, Cline can't reuse terminals safely (they might be running long processes). Enable shell integration or adjust the terminal reuse setting.
### Can I use my custom shell (nushell, xonsh, etc.)?
Cline officially supports bash, zsh, fish, and PowerShell. Custom shells may work but aren't guaranteed. Use bash as a fallback.
### Why do some commands work but others don't?
Commands that use interactive features (pagers, progress bars, curses) often fail. Set `PAGER=cat` and use non-interactive flags.
### How do I know if shell integration is working?
Working integration shows command output in Cline's chat. Failed integration shows "Shell Integration Unavailable" or "[Command is running but producing no output]".
## Still Having Issues?
If you've tried everything:
1. **Collect Debug Info**:
```bash
echo "Shell: $SHELL"
echo "Term: $TERM"
echo "VSCode: $TERM_PROGRAM"
which bash
bash --version
```
2. **Report the Issue**:
- Use `/reportbug` in Cline github issues
- Include your debug info
- Mention which solutions you tried
<Tip>
Remember: Most terminal issues are resolved by switching to bash and increasing the timeout. Start there before trying complex
solutions.
</Tip>
@@ -1,51 +0,0 @@
---
title: "Terminal Quick Fixes"
sidebarTitle: "Terminal Quick Fixes"
description: "Quick solutions for common terminal issues"
---
**Here is a list of common fixes, starting with the most applicable:**
- **Switch to bash** (solves most instances)
1. Within Cline, left-click the **Settings** button in the top right-hand corner of the chat window
2. Once in the **Settings** window, left-click the **"Terminal Settings"** tab from the left-hand column
3. Navigate to **"Default Terminal Profile"** and select **"bash"** from the drop-down
- **Increase timeout**
1. Within Cline, left-click the **Settings** button in the top right-hand corner of the chat window
2. Once in the **Settings** window, left-click the **"Terminal Settings"** tab from the left-hand column
3. Navigate to "Shell integration timeout (seconds)" and enter **"10"** into the text field
- **Disable terminal reuse**
1. Within Cline, left-click the **Settings** button in the top right-hand corner of the chat window
2. Once in the **Settings** window, left-click the **"Terminal Settings"** tab from the left-hand column
3. Look for **"Enable aggressive terminal reuse"**, and **uncheck** this option
## Platform-Specific Fixes
### macOS + Oh-My-Zsh
```bash
# Create minimal config for VSCode
echo 'export TERM=xterm-256color' > ~/.zshrc-vscode
echo 'export PAGER=cat' >> ~/.zshrc-vscode
```
### Windows PowerShell
```powershell
# Run as Administrator
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
### WSL
- Open folder from WSL: `code .`
- Select **"WSL Bash"** in Cline settings, under **"Terminal Settings"**
- Increase **"Shell integration timeout (seconds)"** to **15**
## Full Guide
For detailed troubleshooting, see the [Complete Terminal Troubleshooting Guide](/troubleshooting/terminal-integration-guide).
+9 -27
View File
@@ -1,15 +1,10 @@
import fs from "node:fs"
import * as esbuild from "esbuild"
import path from "node:path"
import { fileURLToPath } from "node:url"
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const esbuild = require("esbuild")
const fs = require("fs")
const path = require("path")
const production = process.argv.includes("--production")
const watch = process.argv.includes("--watch")
const standalone = process.argv.includes("--standalone")
const e2eBuild = process.argv.includes("--e2e-build")
const destDir = standalone ? "dist-standalone" : "dist"
/**
@@ -130,9 +125,9 @@ const baseConfig = {
minify: production,
sourcemap: !production,
logLevel: "silent",
define: production
? { "import.meta.url": "_importMetaUrl", "process.env.IS_DEV": JSON.stringify(!production) }
: { "import.meta.url": "_importMetaUrl" },
define: {
"process.env.IS_DEV": JSON.stringify(!production),
},
tsconfig: path.resolve(__dirname, "tsconfig.json"),
plugins: [
copyWasmFiles,
@@ -143,9 +138,6 @@ const baseConfig = {
format: "cjs",
sourcesContent: false,
platform: "node",
banner: {
js: "const _importMetaUrl=require('url').pathToFileURL(__filename)",
},
}
// Extension-specific configuration
@@ -159,25 +151,15 @@ const extensionConfig = {
// Standalone-specific configuration
const standaloneConfig = {
...baseConfig,
entryPoints: ["src/standalone/cline-core.ts"],
outfile: `${destDir}/cline-core.js`,
entryPoints: ["src/standalone/standalone.ts"],
outfile: `${destDir}/standalone.js`,
// These gRPC protos need to load files from the module directory at runtime,
// so they cannot be bundled.
external: ["vscode", "@grpc/reflection", "grpc-health-check"],
}
// E2E build script configuration
const e2eBuildConfig = {
...baseConfig,
entryPoints: ["src/test/e2e/utils/build.ts"],
outfile: `${destDir}/e2e-build.js`,
external: ["@vscode/test-electron", "execa"],
sourcemap: false,
plugins: [aliasResolverPlugin, esbuildProblemMatcherPlugin],
}
async function main() {
const config = standalone ? standaloneConfig : e2eBuild ? e2eBuildConfig : extensionConfig
const config = standalone ? standaloneConfig : extensionConfig
const extensionCtx = await esbuild.context(config)
if (watch) {
await extensionCtx.watch()
@@ -1,123 +0,0 @@
const { RuleTester: DirectApiRuleTester } = require("eslint")
const noDirectVscodeApiRule = require("../no-direct-vscode-api")
const directApiRuleTester = new DirectApiRuleTester({
parser: require.resolve("@typescript-eslint/parser"),
parserOptions: {
ecmaVersion: 2020,
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
})
directApiRuleTester.run("no-direct-vscode-api", noDirectVscodeApiRule, {
valid: [
// Should allow vscode.postMessage in grpc-client-base.ts
{
code: `vscode.postMessage({ type: "grpc_request", data: {} })`,
filename: "grpc-client-base.ts",
},
{
code: `vscode.postMessage({ type: "grpc_request_cancel" })`,
filename: "/path/to/grpc-client-base.ts",
},
// Should allow in exception directories
{
code: `vscode.workspace.workspaceFolders`,
filename: "/src/hosts/vscode/host-bridge.ts",
},
{
code: `vscode.workspace.fs.stat(uri)`,
filename: "/standalone/runtime-files/helpers.ts",
},
// Should allow other vscode API calls
{
code: `vscode.window.showInformationMessage("Hello")`,
filename: "test.ts",
},
// Should allow postMessage calls on other objects
{
code: `window.postMessage({ type: "test" }, "*")`,
filename: "test.ts",
},
// Should allow variables named vscode but not calling postMessage
{
code: `const vscode = { other: "method" }; vscode.other()`,
filename: "test.ts",
},
],
invalid: [
// Should disallow vscode.postMessage in regular files
{
code: `vscode.postMessage({ type: "test", data: {} })`,
filename: "test.ts",
errors: [
{
messageId: "useGrpcClient",
},
],
},
// Should disallow vscode.postMessage in components
{
code: `vscode.postMessage({ type: "apiConfiguration", apiConfiguration })`,
filename: "ApiOptions.tsx",
errors: [
{
messageId: "useGrpcClient",
},
],
},
// Should disallow vscode.postMessage in test files
{
code: `vscode.postMessage({ type: "newTask", text: message.text })`,
filename: "test.test.ts",
errors: [
{
messageId: "useGrpcClient",
},
],
},
// Should disallow property access for disallowed APIs
{
code: `const folders = vscode.workspace.workspaceFolders;`,
filename: "workspace.ts",
errors: [
{
messageId: "useHostBridge",
},
],
},
// Should disallow method calls for disallowed APIs
{
code: `const relativePath = vscode.workspace.asRelativePath(filePath);`,
filename: "path-utils.ts",
errors: [
{
messageId: "usePathUtils",
},
],
},
// Should disallow nested property access
{
code: `const stats = await vscode.workspace.fs.stat(uri);`,
filename: "file-utils.ts",
errors: [
{
messageId: "useFsUtils",
},
],
},
// Should disallow getting a workspace folder
{
code: `const folder = vscode.workspace.getWorkspaceFolder(uri);`,
filename: "path-helper.ts",
errors: [
{
messageId: "usePathUtils",
},
],
},
],
})
-16
View File
@@ -1,16 +0,0 @@
// eslint-rules/index.js
const noDirectVscodeApi = require("./no-direct-vscode-api")
module.exports = {
rules: {
"no-direct-vscode-api": noDirectVscodeApi,
},
configs: {
recommended: {
plugins: ["local"],
rules: {
"local/no-direct-vscode-api": "warn",
},
},
},
}
-214
View File
@@ -1,214 +0,0 @@
const { ESLintUtils } = require("@typescript-eslint/utils")
const path = require("path")
const createRule = ESLintUtils.RuleCreator((name) => `https://cline.bot/eslint-rules/${name}`)
// Configuration of disallowed VSCode APIs and their recommended alternatives
const disallowedApis = {
"vscode.postMessage": {
messageId: "useGrpcClient",
},
"vscode.workspace.fs.stat": {
messageId: "useFsUtils",
},
"vscode.workspace.fs.writeFile": {
messageId: "useFsUtils",
},
"vscode.workspace.workspaceFolders": {
messageId: "useHostBridgeWorkspace",
},
"vscode.workspace.asRelativePath": {
messageId: "usePathUtils",
},
"vscode.workspace.getWorkspaceFolder": {
messageId: "usePathUtils",
},
"vscode.window.showTextDocument": {
messageId: "useHostBridge",
},
"vscode.workspace.applyEdit": {
messageId: "useHostBridge",
},
"vscode.window.onDidChangeActiveTextEditor": {
messageId: "useHostBridge",
},
"vscode.env.openExternal": {
messageId: "useUtils",
},
// "vscode.window.showWarningMessage": {
// messageId: "useHostBridgeShowMessage",
// },
"vscode.window.showOpenDialog": {
messageId: "useHostBridgeShowMessage",
},
"vscode.window.showErrorMessage": {
messageId: "useHostBridgeShowMessage",
},
// "vscode.window.showInformationMessage": {
// messageId: "useHostBridgeShowMessage",
// },
}
module.exports = createRule({
name: "no-direct-vscode-api",
meta: {
type: "problem",
docs: {
description:
"Disallow direct VSCode API usage in favor of Cline's abstraction layers, except in src/hosts/vscode and standalone/runtime-files directories",
recommended: "error",
},
messages: {
useGrpcClient:
"Use gRPC service clients instead of vscode.postMessage().\n" +
"Example: AccountServiceClient.methodName(RequestType.create({...})) instead of vscode.postMessage({type: '...'}).\n" +
"Found: {{code}}",
useFsUtils:
"Use utilities in @/utils/fs instead of vscode.workspace.fs\n" +
"Example: import { isDirectory } from '@/utils/fs' or use the file system methods from the host bridge provider.\n" +
"Found: {{code}}",
usePathUtils:
"Use path utilities from @/utils/path instead of VSCode workspace path methods.\n" +
"This provides consistent path handling across different environments.\n" +
"Found: {{code}}",
useHostBridgeWorkspace:
"Use HostProvider.workspace.getWorkspacePaths({}) instead of vscode.workspace.workspaceFolders.\n" +
"This provides a consistent abstraction across VSCode and standalone environments.\n" +
"Found: {{code}}",
useHostBridgeShowMessage:
"Use HostProvider.window.showMessage instead of the vscode.window.showMessage.\n" +
"This provides a consistent abstraction across VSCode and standalone environments.\n" +
"Found: {{code}}",
useHostBridge:
"Use the host bridge instead of calling vscode APIs directly.\n" +
"This provides a consistent abstraction across VSCode and standalone environments.\n" +
"Found: {{code}}",
useUtils:
"Use utilities in @/utils instead of calling vscode APIs directly.\n" +
"This provides a consistent abstraction across VSCode and standalone environments.\n" +
"Found: {{code}}",
},
schema: [],
},
defaultOptions: [],
create(context) {
// Pattern for checking memberExpressions like vscode.workspace.fs.stat
function checkMemberExpression(node) {
if (isExcluded(context.filename)) {
// Skip if this file is being excluded.
return
}
// For handling nested properties like vscode.workspace.fs.stat
function getFullPropertyPath(node) {
if (node.type !== "MemberExpression") {
return node.name || ""
}
const objectPart = getFullPropertyPath(node.object)
const propertyPart = node.property.name || ""
return objectPart ? `${objectPart}.${propertyPart}` : propertyPart
}
// Check if the expression matches one of our disallowed patterns
if (node.object && node.object.type === "Identifier" && node.object.name === "vscode") {
const fullPath = `vscode.${node.property.name}`
checkDisallowedApi(fullPath, node)
}
// Handle nested expressions like vscode.workspace.fs.stat
else if (node.object && node.object.type === "MemberExpression") {
const fullPath = getFullPropertyPath(node)
// Only proceed if it starts with vscode
if (fullPath.startsWith("vscode.")) {
checkDisallowedApi(fullPath, node)
}
}
}
// Check if an expression matches a disallowed API and report if it does
function checkDisallowedApi(expressionPath, node) {
// Check exact matches
if (disallowedApis[expressionPath]) {
reportViolation(expressionPath, node)
return
}
// Check prefix matches (for nested properties)
for (const disallowedApi in disallowedApis) {
// For direct property access like vscode.workspace.workspaceFolders
if (expressionPath === disallowedApi) {
reportViolation(disallowedApi, node)
return
}
// For method calls like vscode.workspace.asRelativePath(...)
if (expressionPath.startsWith(`${disallowedApi}.`) || expressionPath.startsWith(`${disallowedApi}(`)) {
reportViolation(disallowedApi, node)
return
}
}
}
// Report a violation with the appropriate message
function reportViolation(disallowedApi, node) {
const sourceCode = context.sourceCode
const config = disallowedApis[disallowedApi]
// For method calls, get the whole call expression
let reportNode = node
let parentNode = sourceCode.getAncestors(node).pop()
if (parentNode && parentNode.type === "CallExpression" && parentNode.callee === node) {
reportNode = parentNode
}
const callText = sourceCode.getText(reportNode).trim()
context.report({
node: reportNode,
messageId: config.messageId,
data: {
code: callText,
},
})
}
function isExcluded(filename) {
// Check if current file is in an exception directory or is grpc-client-base.ts
if (path.basename(filename) === "grpc-client-base.ts") {
return true
}
// Skip checking files in src/hosts/vscode or standalone/runtime-files
if (filename.includes("/src/hosts/vscode/")) {
return true
}
if (filename.includes("/standalone/runtime-files/")) {
return true
}
// Skip unit tests
if (filename.endsWith(".test.ts")) {
return true
}
}
return {
// Detect basic member expressions (e.g., vscode.postMessage)
MemberExpression(node) {
checkMemberExpression(node)
},
// Detect property access through destructuring
VariableDeclarator(node) {
// Skip if this file is in an exception directory or is grpc-client-base.ts
if (isExcluded(context.filename)) {
return
}
// Destructuring pattern checks removed as developers don't use the API this way
// They always use direct imports: import * as vscode from "vscode" and direct access: vscode.thing.foo
},
}
},
})
-2479
View File
File diff suppressed because it is too large Load Diff
-31
View File
@@ -1,31 +0,0 @@
{
"name": "eslint-plugin-eslint-rules",
"version": "1.0.0",
"description": "Custom ESLint rules for Cline",
"main": "index.js",
"scripts": {
"test": "mocha --no-config --require ts-node/register __tests__/**/*.test.ts"
},
"keywords": [
"eslint",
"eslintplugin"
],
"author": "Cline Bot Inc.",
"license": "Apache-2.0",
"dependencies": {
"@typescript-eslint/utils": "^8.33.0"
},
"devDependencies": {
"@types/eslint": "^8.0.0",
"@types/mocha": "^10.0.7",
"@types/node": "^20.0.0",
"@typescript-eslint/parser": "^7.14.1",
"eslint": "^8.57.0",
"mocha": "^10.0.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
},
"peerDependencies": {
"eslint": ">=8.0.0"
}
}
-16
View File
@@ -1,16 +0,0 @@
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "dist",
"resolveJsonModule": true,
"declaration": true
},
"include": ["**/*.ts", "**/*.js", "**/*.tsx", "__tests__/**/*"],
"exclude": ["node_modules", "dist"]
}
+1 -22
View File
@@ -1,24 +1,3 @@
repositories
results/evals.db
diff-edits/cases/
diff-edits/results/
# Environment variables
.env
# backwards compatible
diff_editing/test_cases/
diff_editing/test_outputs/
*.db
*.db-wal
*.db-shm
.cache
# Python bytecode cache
*__pycache__/
diff-edits/cases.zip
results/evals.db
-193
View File
@@ -17,7 +17,6 @@ The evaluation system consists of two main components:
1. **Test Server**: Enhanced HTTP server in `src/services/test/TestServer.ts` that provides detailed task results
2. **CLI Tool**: Command-line interface in `evals/cli/` for orchestrating evaluations
3. **Diff Edit Benchmark**: Separate command using the CLI tool that runs a comprehensive diff editing benchmark suite on real world cases, along with a streamlit dashboard displaying the results. For more details, see the [Diff Edit Benchmark README](./diff-edits/README.md). Make sure you add a `evals/diff-edits/cases` folder with all the conversation jsons.
## Directory Structure
@@ -41,12 +40,6 @@ cline-repo/
│ │ │ └── utils/ # Utility functions
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── diff-edits/ # Diff editing evaluation suite
│ │ ├── cases/ # Test case JSON files
│ │ ├── results/ # Evaluation results
│ │ ├── diff-apply/ # Diff application logic
│ │ ├── parsing/ # Assistant message parsing
│ │ └── prompts/ # System prompts
│ ├── repositories/ # Cloned benchmark repositories
│ │ ├── exercism/ # Modified Exercism (from pashpashpash/evals)
│ │ ├── swe-bench/ # SWE-Bench repository
@@ -155,192 +148,6 @@ Freelance-style programming tasks from the SWELancer benchmark.
Multi-file software engineering tasks from the Multi-SWE-Bench repository.
## Diff Edit Evaluations
The Cline Evaluation System includes a specialized suite for evaluating how well models can make precise edits to files using the `replace_in_file` tool.
### Overview
Diff edit evaluations test a model's ability to:
1. Understand file content and identify specific sections to modify
2. Generate correct SEARCH/REPLACE blocks for targeted edits
3. Successfully apply changes without introducing errors
### Directory Structure
```
diff-edits/
├── cases/ # Test case JSON files
├── results/ # Evaluation results
├── ClineWrapper.ts # Wrapper for model interaction
├── TestRunner.ts # Main test execution logic
├── types.ts # Type definitions
├── diff-apply/ # Diff application logic
├── parsing/ # Assistant message parsing
└── prompts/ # System prompts
```
### Creating Test Cases
Test cases are defined as JSON files in the `diff-edits/cases/` directory. Each test case should include:
```json
{
"test_id": "example_test_1",
"messages": [
{
"role": "user",
"text": "Please fix the bug in this code...",
"images": []
},
{
"role": "assistant",
"text": "I'll help you fix that bug..."
}
],
"file_contents": "// Original file content here\nfunction example() {\n // Code with bug\n}",
"file_path": "src/example.js",
"system_prompt_details": {
"mcp_string": "",
"cwd_value": "/path/to/working/directory",
"browser_use": false,
"width": 900,
"height": 600,
"os_value": "macOS",
"shell_value": "/bin/zsh",
"home_value": "/Users/username",
"user_custom_instructions": ""
},
"original_diff_edit_tool_call_message": ""
}
```
### Running Diff Edit Evaluations
#### Single Model Evaluation
```bash
cd evals/cli
node dist/index.js run-diff-eval --model-ids "anthropic/claude-3-5-sonnet-20241022"
```
#### Multi-Model Evaluation
Compare multiple models in a single evaluation run:
```bash
# Compare Claude and Grok models
node dist/index.js run-diff-eval \
--model-ids "anthropic/claude-3-5-sonnet-20241022,x-ai/grok-beta" \
--max-cases 10 \
--valid-attempts-per-case 3 \
--verbose
# Compare multiple Claude variants
node dist/index.js run-diff-eval \
--model-ids "anthropic/claude-3-5-sonnet-20241022,anthropic/claude-3-5-haiku-20241022,anthropic/claude-3-opus-20240229" \
--max-cases 5 \
--valid-attempts-per-case 2 \
--parallel
```
#### Options
- `--model-ids`: Comma-separated list of model IDs to evaluate (required)
- `--system-prompt-name`: System prompt to use (default: "basicSystemPrompt")
- `--valid-attempts-per-case`: Number of attempts per test case per model (default: 1)
- `--max-cases`: Maximum number of test cases to run (default: all available)
- `--parsing-function`: Function to parse assistant messages (default: "parseAssistantMessageV2")
- `--diff-edit-function`: Function to apply diffs (default: "constructNewFileContentV2")
- `--test-path`: Path to test cases (default: diff-edits/cases)
- `--thinking-budget`: Tokens allocated for thinking (default: 0)
- `--parallel`: Run tests in parallel (flag)
- `--replay`: Use pre-recorded LLM output (flag)
- `--verbose`: Enable detailed logging (flag)
#### Examples
```bash
# Quick test with 2 models, 4 cases, 2 attempts each
node dist/index.js run-diff-eval \
--model-ids "anthropic/claude-3-5-sonnet-20241022,x-ai/grok-beta" \
--max-cases 4 \
--valid-attempts-per-case 2 \
--verbose
# Comprehensive evaluation with parallel execution
node dist/index.js run-diff-eval \
--model-ids "anthropic/claude-3-5-sonnet-20241022,anthropic/claude-3-5-haiku-20241022" \
--system-prompt-name claude4SystemPrompt \
--valid-attempts-per-case 5 \
--max-cases 20 \
--parallel \
--verbose
```
### Database Storage & Analytics
All evaluation results are automatically stored in a SQLite database (`diff-edits/evals.db`) for advanced analytics and comparison. The database includes:
- **System Prompts**: Versioned system prompt content with hashing for deduplication
- **Processing Functions**: Versioned parsing and diff-edit function configurations
- **Files**: Original and edited file content with content-based hashing
- **Runs**: Evaluation run metadata and configuration
- **Cases**: Individual test case information with context tokens
- **Results**: Detailed results with timing, cost, and success metrics
### Interactive Dashboard
Launch the Streamlit dashboard to visualize and analyze evaluation results:
```bash
cd diff-edits/dashboard
streamlit run app.py
```
The dashboard provides:
- **Model Performance Comparison**: Side-by-side comparison of success rates, latency, and costs
- **Interactive Charts**: Success rate trends, latency vs cost analysis, and performance metrics
- **Detailed Drill-Down**: Individual result analysis with file content viewing
- **Run Selection**: Browse and compare different evaluation runs
- **Real-time Updates**: Automatically refreshes with new evaluation data
#### Dashboard Features
1. **Hero Section**: Overview of current run with key metrics
2. **Model Cards**: Performance cards with grades and detailed metrics
3. **Comparison Charts**: Interactive Plotly charts for visual analysis
4. **Result Explorer**: Detailed view of individual test results including:
- Original and edited file content
- Raw model output
- Parsed tool calls
- Timing and cost metrics
- Error analysis
#### Quick Start Dashboard
```bash
# Run a quick evaluation
node cli/dist/index.js run-diff-eval \
--model-ids "anthropic/claude-3-5-sonnet-20241022,x-ai/grok-beta" \
--max-cases 4 \
--valid-attempts-per-case 2 \
--verbose
# Launch dashboard to view results
cd diff-edits/dashboard && streamlit run app.py
```
### Legacy Results
For backward compatibility, results are also saved as JSON files in the `diff-edits/results/` directory. The JSON results include:
- Success/failure status
- Extracted tool calls
- Diff edit content
- Token usage and cost metrics
## Metrics
The evaluation system collects the following metrics:
+2455
View File
File diff suppressed because it is too large Load Diff
+39
View File
@@ -0,0 +1,39 @@
{
"name": "cline-evaluation-cli",
"version": "0.1.0",
"description": "CLI tool for orchestrating Cline evaluations across multiple benchmarks",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"cline",
"evaluation",
"benchmark"
],
"author": "",
"license": "MIT",
"dependencies": {
"better-sqlite3": "^8.0.0",
"chalk": "^4.1.2",
"commander": "^9.4.1",
"execa": "^5.1.1",
"node-fetch": "^2.7.0",
"ora": "^5.4.1",
"sqlite": "^4.1.2",
"uuid": "^9.0.0",
"yargs": "^17.6.2"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.3",
"@types/node": "^18.11.18",
"@types/node-fetch": "^2.6.12",
"@types/uuid": "^9.0.0",
"@types/yargs": "^17.0.19",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
}
}
-104
View File
@@ -1,104 +0,0 @@
import execa from "execa"
import chalk from "chalk"
import path from "path"
interface RunDiffEvalOptions {
modelIds: string
systemPromptName: string
validAttemptsPerCase: number
maxAttemptsPerCase?: number
parsingFunction: string
diffEditFunction: string
thinkingBudget: number
parallel: boolean
verbose: boolean
testPath: string
outputPath: string
replay: boolean
replayRunId?: string
diffApplyFile?: string
saveLocally: boolean
maxCases?: number
}
export async function runDiffEvalHandler(options: RunDiffEvalOptions) {
console.log(chalk.blue("Starting diff editing evaluation..."))
// Resolve the path to the TestRunner.ts script relative to the current file
const scriptPath = path.resolve(__dirname, "../../../diff-edits/TestRunner.ts")
// Construct the arguments array for the execa call
const args = [
"--model-ids",
options.modelIds,
"--system-prompt-name",
options.systemPromptName,
"--valid-attempts-per-case",
String(options.validAttemptsPerCase),
"--parsing-function",
options.parsingFunction,
"--diff-edit-function",
options.diffEditFunction,
]
// Conditionally add the optional arguments
if (options.testPath) {
args.push("--test-path", options.testPath)
}
if (options.outputPath) {
args.push("--output-path", options.outputPath)
}
if (options.thinkingBudget > 0) {
args.push("--thinking-budget", String(options.thinkingBudget))
}
if (options.parallel) {
args.push("--parallel")
}
if (options.replay) {
args.push("--replay")
}
if (options.replayRunId) {
args.push("--replay-run-id", options.replayRunId)
}
if (options.diffApplyFile) {
args.push("--diff-apply-file", options.diffApplyFile)
}
if (options.verbose) {
args.push("--verbose")
}
if (options.maxAttemptsPerCase) {
args.push("--max-attempts-per-case", String(options.maxAttemptsPerCase))
}
if (options.maxCases) {
args.push("--max-cases", String(options.maxCases))
}
if (options.saveLocally) {
args.push("--save-locally")
}
try {
console.log(chalk.gray(`Executing: npx tsx ${scriptPath} ${args.join(" ")}`))
// Execute the script as a child process
// We use 'inherit' to stream the stdout/stderr directly to the user's terminal
const subprocess = execa("npx", ["tsx", "--tsconfig", path.resolve(__dirname, "../../../tsconfig.json"), scriptPath, ...args], {
stdio: "inherit",
})
await subprocess
console.log(chalk.green("Diff editing evaluation completed successfully."))
} catch (error) {
console.error(chalk.red("An error occurred during the diff editing evaluation."))
// The 'inherit' stdio will have already printed the error details from the script
process.exit(1)
}
}
-37
View File
@@ -5,7 +5,6 @@ import { setupHandler } from "./commands/setup"
import { runHandler } from "./commands/run"
import { reportHandler } from "./commands/report"
import { evalsEnvHandler } from "./commands/evals-env"
import { runDiffEvalHandler } from "./commands/runDiffEval"
// Create the CLI program
const program = new Command()
@@ -78,42 +77,6 @@ program
}
})
// Run-diff-eval command
program
.command("run-diff-eval")
.description("Run the diff editing evaluation suite")
.option("--test-path <path>", "Path to the directory containing test case JSON files")
.option("--output-path <path>", "Path to the directory to save the test output JSON files")
.option("--model-ids <model_ids>", "Comma-separated list of model IDs to test")
.option("--system-prompt-name <name>", "The name of the system prompt to use", "basicSystemPrompt")
.option("-n, --valid-attempts-per-case <number>", "Number of valid attempts per test case per model (will retry until this many valid attempts are collected)", "1")
.option("--max-attempts-per-case <number>", "Maximum total attempts per test case (default: 10x valid attempts)")
.option("--max-cases <number>", "Maximum number of test cases to run (limits total cases loaded)")
.option("--parsing-function <name>", "The parsing function to use", "parseAssistantMessageV2")
.option("--diff-edit-function <name>", "The diff editing function to use", "constructNewFileContentV2")
.option("--thinking-budget <tokens>", "Set the thinking tokens budget", "0")
.option("--parallel", "Run tests in parallel", false)
.option("--replay", "Run evaluation from a pre-recorded LLM output, skipping the API call", false)
.option("--replay-run-id <run_id>", "The ID of the run to replay from the database")
.option("--diff-apply-file <filename>", "The name of the diff apply file to use for the replay")
.option("--save-locally", "Save results to local JSON files in addition to database", false)
.option("-v, --verbose", "Enable verbose logging", false)
.action(async (options) => {
try {
const fullOptions = {
...options,
validAttemptsPerCase: parseInt(options.validAttemptsPerCase, 10),
maxAttemptsPerCase: options.maxAttemptsPerCase ? parseInt(options.maxAttemptsPerCase, 10) : undefined,
thinkingBudget: parseInt(options.thinkingBudget, 10),
maxCases: options.maxCases ? parseInt(options.maxCases, 10) : undefined,
}
await runDiffEvalHandler(fullOptions)
} catch (error) {
console.error(chalk.red(`Error during diff eval run: ${error instanceof Error ? error.message : String(error)}`))
process.exit(1)
}
})
// Parse command line arguments
program.parse(process.argv)
-343
View File
@@ -1,343 +0,0 @@
import { OpenRouterHandler } from "../../src/api/providers/openrouter"
import { ApiHandlerOptions } from "../../src/shared/api"
import { Anthropic } from "@anthropic-ai/sdk"
import {
parseAssistantMessageV1,
parseAssistantMessageV2,
parseAssistantMessageV3,
AssistantMessageContent,
} from "./parsing/parse-assistant-message-06-06-25" // "../../src/core/assistant-message"
import { constructNewFileContent as constructNewFileContent_06_06_25 } from "./diff-apply/diff-06-06-25"
import { constructNewFileContent as constructNewFileContent_06_23_25 } from "./diff-apply/diff-06-23-25"
import { constructNewFileContent as constructNewFileContent_06_25_25 } from "./diff-apply/diff-06-25-25"
import { constructNewFileContent as constructNewFileContent_06_26_25 } from "./diff-apply/diff-06-26-25"
type ParseAssistantMessageFn = (message: string) => AssistantMessageContent[]
type ConstructNewFileContentFn = (diff: string, original: string, strict: boolean) => Promise<string | any>
const parsingFunctions: Record<string, ParseAssistantMessageFn> = {
parseAssistantMessageV1: parseAssistantMessageV1,
parseAssistantMessageV2: parseAssistantMessageV2,
parseAssistantMessageV3: parseAssistantMessageV3,
}
const diffEditingFunctions: Record<string, ConstructNewFileContentFn> = {
"diff-06-06-25": constructNewFileContent_06_06_25,
"diff-06-23-25": constructNewFileContent_06_23_25,
"diff-06-25-25": constructNewFileContent_06_25_25,
"diff-06-26-25": constructNewFileContent_06_26_25,
}
import { TestInput, TestResult, ExtractedToolCall } from "./types"
import { log } from "./helpers"
export { TestInput, TestResult, ExtractedToolCall }
interface StreamResult {
assistantMessage: string
reasoningMessage: string
usage: {
inputTokens: number
outputTokens: number
cacheWriteTokens: number
cacheReadTokens: number
totalCost: number
}
timing?: {
timeToFirstTokenMs: number
timeToFirstEditMs?: number
totalRoundTripMs: number
}
}
/**
* Process the stream and return full response with timing data
*/
async function processStream(
handler: OpenRouterHandler,
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
): Promise<StreamResult> {
const startTime = Date.now()
const stream = handler.createMessage(systemPrompt, messages)
let assistantMessage = ""
let reasoningMessage = ""
let inputTokens = 0
let outputTokens = 0
let cacheWriteTokens = 0
let cacheReadTokens = 0
let totalCost = 0
// Timing tracking
let timeToFirstTokenMs: number | null = null
let timeToFirstEditMs: number | null = null
for await (const chunk of stream) {
if (!chunk) {
continue
}
// Capture time to first token (any chunk type)
if (timeToFirstTokenMs === null) {
timeToFirstTokenMs = Date.now() - startTime
}
switch (chunk.type) {
case "usage":
inputTokens += chunk.inputTokens
outputTokens += chunk.outputTokens
cacheWriteTokens += chunk.cacheWriteTokens ?? 0
cacheReadTokens += chunk.cacheReadTokens ?? 0
if (chunk.totalCost) {
totalCost = chunk.totalCost
}
break
case "reasoning":
reasoningMessage += chunk.reasoning
break
case "text":
assistantMessage += chunk.text
// Try to detect first tool call by parsing accumulated message
if (timeToFirstEditMs === null) {
try {
const parsed = parseAssistantMessageV2(assistantMessage)
const hasToolCall = parsed.some(block => block.type === "tool_use")
if (hasToolCall) {
timeToFirstEditMs = Date.now() - startTime
}
} catch {
// Parsing failed, continue accumulating
}
}
break
}
}
const totalRoundTripMs = Date.now() - startTime
return {
assistantMessage,
reasoningMessage,
usage: {
inputTokens,
outputTokens,
cacheWriteTokens,
cacheReadTokens,
totalCost,
},
timing: {
timeToFirstTokenMs: timeToFirstTokenMs || 0,
timeToFirstEditMs: timeToFirstEditMs || undefined,
totalRoundTripMs,
},
}
}
/**
* Main evaluation function:
* 1. create and process stream
* 2. extract any tool calls from the stream
* 3. if no diff edit, considered a failure (or rerun) - otherwise attempt to apply the diff edit
*/
export async function runSingleEvaluation(input: TestInput): Promise<TestResult> {
try {
// Extract parameters
const {
apiKey,
systemPrompt,
messages,
modelId,
originalFile,
originalFilePath,
parsingFunction,
diffEditFunction,
thinkingBudgetTokens,
originalDiffEditToolCallMessage,
diffApplyFile,
} = input
const requiredParams = {
systemPrompt,
messages,
modelId,
originalFile,
originalFilePath,
parsingFunction,
diffEditFunction,
}
const missingParams = Object.entries(requiredParams)
.filter(([, value]) => !value)
.map(([key]) => key)
if (missingParams.length > 0) {
return {
success: false,
error: "missing_required_parameters",
errorString: `Missing required parameters: ${missingParams.join(", ")}`,
}
}
const parseAssistantMessage = parsingFunctions[parsingFunction]
const constructNewFileContent = diffEditingFunctions[diffApplyFile || diffEditFunction]
if (!parseAssistantMessage || !constructNewFileContent) {
return {
success: false,
error: "invalid_functions",
}
}
const options: ApiHandlerOptions = {
openRouterApiKey: apiKey,
openRouterModelId: modelId,
thinkingBudgetTokens: thinkingBudgetTokens,
openRouterModelInfo: {
maxTokens: 10_000,
contextWindow: 1_000_000,
supportsImages: true,
supportsPromptCache: true, // may need to turn this on
inputPrice: 0,
outputPrice: 0,
},
}
// Get the output of streaming output of this llm call
let streamResult: StreamResult
if (originalDiffEditToolCallMessage !== undefined) {
// Replay mode: mock the stream result
streamResult = {
assistantMessage: originalDiffEditToolCallMessage,
reasoningMessage: "",
usage: { inputTokens: 0, outputTokens: 0, cacheWriteTokens: 0, cacheReadTokens: 0, totalCost: 0 },
}
} else {
// Live mode: existing API call logic
try {
const openRouterHandler = new OpenRouterHandler(options)
streamResult = await processStream(openRouterHandler, systemPrompt, messages)
} catch (error: any) {
return {
success: false,
error: "llm_stream_error",
errorString: error.message || error.toString(),
}
}
}
// process the assistant message into its constituent tool calls & text blocks
const assistantContentBlocks: AssistantMessageContent[] = parseAssistantMessage(streamResult.assistantMessage)
const detectedToolCalls: ExtractedToolCall[] = []
for (const block of assistantContentBlocks) {
if (block.type === "tool_use") {
detectedToolCalls.push({
name: block.name,
input: block.params,
})
}
}
// check if there are any tool calls, if there are none then its a clear error
if (detectedToolCalls.length === 0) {
return {
success: false,
streamResult: streamResult,
toolCalls: detectedToolCalls,
error: "no_tool_calls",
}
}
// check that there is exactly one tool call, otherwise an error
if (detectedToolCalls.length > 1) {
return {
success: false,
streamResult: streamResult,
toolCalls: detectedToolCalls,
error: "multi_tool_calls",
}
}
// check that the tool call is diff edit tool call
if (detectedToolCalls[0].name !== "replace_in_file") {
return {
success: false,
streamResult: streamResult,
toolCalls: detectedToolCalls,
error: "wrong_tool_call",
}
}
const toolCall = detectedToolCalls[0]
const diffToolPath = toolCall.input.path
const diffToolContent = toolCall.input.diff
if (!diffToolPath || !diffToolContent) {
return {
success: false,
streamResult: streamResult,
toolCalls: detectedToolCalls,
error: "tool_call_params_undefined",
}
}
// check that we are editing the correct file path
log(input.isVerbose, `Expected file path: "${originalFilePath}"`)
log(input.isVerbose, `Actual file path used: "${diffToolPath}"`)
if (diffToolPath !== originalFilePath) {
log(input.isVerbose, `❌ File path mismatch detected!`)
// Enhanced logging:
if (streamResult?.assistantMessage) {
log(input.isVerbose, ` Full model output (assistantMessage):`)
log(input.isVerbose, ` -----------------------------------------`)
log(input.isVerbose, ` ${streamResult.assistantMessage}`)
log(input.isVerbose, ` -----------------------------------------`)
}
if (toolCall) {
log(input.isVerbose, ` Parsed tool call that caused mismatch:`)
log(input.isVerbose, ` ${JSON.stringify(toolCall, null, 2)}`)
log(input.isVerbose, ` -----------------------------------------`)
}
return {
success: false,
streamResult: streamResult,
toolCalls: detectedToolCalls,
error: "wrong_file_edited",
}
}
// checking if the diff edit succeeds, if it failed it will throw an error
let diffSuccess = true
let replacementData: any = undefined
try {
const result = await constructNewFileContent(diffToolContent, originalFile, true)
// Check if result is an object with replacements (new format)
if (typeof result === 'object' && result !== null && 'replacements' in result) {
replacementData = result.replacements
}
// If it's just a string, diffSuccess stays true and replacementData stays undefined
} catch (error: any) {
diffSuccess = false
log(input.isVerbose, `ERROR: ${error}`)
}
return {
success: true,
streamResult: streamResult,
toolCalls: detectedToolCalls,
diffEdit: diffToolContent,
diffEditSuccess: diffSuccess,
replacementData: replacementData,
}
} catch (error: any) {
return {
success: false,
error: "other_error",
errorString: error.message || error.toString(),
}
}
}
-84
View File
@@ -1,84 +0,0 @@
# A Note on Cline's Diff Evaluation Setup
Hey there, this note explains what we're doing with Cline's diff evaluation (evals) system. It's all about checking how well various AI models (which users connect to Cline via their own API keys), prompts, and diffing tools can handle file changes.
## What We're Trying to Figure Out
The main idea here is to figure out which AI models (configured by users) are best at making `replace_in_file` tool calls that work correctly. This helps us understand model capabilities and also speeds up our own experiments with prompts and diffing algorithms to make Cline better over time. We want to know a few key things.
First, can the model create diffs, which are just sets of SEARCH and REPLACE blocks, that apply cleanly to a file? This is what we call `diffEditSuccess`.
Second, how do different LLMs, like Claude or Grok, stack up against each other when they try to make these diff edits? We use a standard set of real-world test cases for this.
Third, do different system prompts, say our `basicSystemPrompt` versus the `claude4SystemPrompt`, change how well a model does at diff editing?
Fourth, we're also looking at different ways to apply the diffs themselves. We have a few algorithms like `constructNewFileContentV1`, `V2`, and `V3`, and we want to see which ones are more robust when fed model-generated diffs.
Fifth, we track how fast the model starts making an edit. The `timeToFirstEditMs` metric gives us a hint about how quickly a user would see changes happening in their editor.
And finally, we keep an eye on how many tokens are used and what it costs for each model and each try. This helps us compare how efficient they are.
Right now, these evals are mostly about whether the diff *applies* correctly. That means, do the SEARCH blocks find a match, and can the REPLACE blocks be put in without an error? We're not yet deeply analyzing if the change is valid code or matches what the user *wanted* semantically. That's a problem for another day, and will require a lot more scaffolding.
## How We Run These Tests
Two prerequisites:
1. Make sure you have an `evals/.env` file with `OPENROUTER_API_KEY=<your-openrouter-key>`
2. Make sure you add a `evals/diff-edits/cases` folder with all the conversation jsons prior to running this.
Our testing strategy is based on replaying situations from actual user sessions where diff edits were tried.
It starts with our test cases. Each one is a JSON file in `./cases` that has the conversation history that led to a diff edit, the original file content and its path, and the info needed to rebuild the system prompt from that original session.
Then, for every test run, we set up a specific configuration. This includes which LLM we're testing, which system prompt it gets, which function we use to parse the model's raw output, and which function we use to actually apply the diff. Here's the command I've been using:
```bash
npm run diff-eval -- --model-ids "anthropic/claude-3-5-sonnet,x-ai/grok-3-beta,anthropic/claude-3.7-sonnet,anthropic/claude-sonnet-4,google/gemini-2.5-pro-preview,google/gemini-2.5-flash" --max-cases 5 --valid-attempts-per-case 5 --parallel --diff-edit-function diff-06-26-25 --verbose
```
This will build the eval script, run it, and then open the streamlit dashboard to show the results.
The `TestRunner.ts` script is the main coordinator. For each test case and setup, `ClineWrapper.ts` takes over and sends the conversation and system prompt to the LLM. We then watch the model's response as it streams in and parse it to find any tool calls.
We're specifically looking for the model to make a single `replace_in_file` tool call. Multiple edits in one tool call are allowed, and recorded (in case you want to filter results by number of edits in a single tool call and compare success rate for that slice across different models/system prompts/etc). If it does, and it's for the correct file, we grab the diff content it produced. Then, the chosen diff application algorithm tries to apply that diff to the original file. We record whether this worked or not as `diffEditSuccess`.
We record a bunch of data for every attempt into a database. This includes details about the model and prompt, token counts, costs, the raw output from the model, the parsed tool calls, whether it succeeded or failed, any error messages, and timing info. For a detailed explanation of the database schema, see [database.md](./database.md).
A big part of this is how we handle "valid attempts," which I'll explain next.
## Keeping it Fair with "Valid Attempts"
LLMs can be unpredictable. If we replay an old scenario, a new model, or even the same model later, might do something completely different than what happened originally. It might call another tool or ask a question instead of trying a diff edit.
Since we really want to test the *diff editing* part, we need a way to make sure we're comparing fairly. That's why we have this idea of "valid attempts."
An attempt is "valid" for this benchmark if the model actually tries to do what we're interested in. This means two things. One, it must call the `replace_in_file` tool. Two, it must target the *same file path* that was targeted in the original recorded conversation for that test case.
If the model does something else, like calling a different tool or picking the wrong file, we don't count that attempt against its diff editing score. Instead, we consider it an "invalid attempt" for *this specific benchmark* and simply re-run that test case with that model. We keep doing this until we've collected a set number of these "valid attempts."
For example, if we ask for 5 valid attempts per test case, the system will keep re-rolling for that case until the model has tried to edit the correct file using the `replace_in_file` tool 5 times. Only then do we look at how many of those 5 valid attempts actually resulted in a successful diff application (`diffEditSuccess`).
This way, if we're comparing two models and one gets a 10% success rate on its valid diff edit attempts, and another gets 90%, we have a much clearer picture of their actual diff-generating capabilities. It avoids muddying the waters with attempts where the model didn't even try to perform the specific action we're evaluating. This approach helps us isolate and measure the diff-editing skill more directly, despite the non-deterministic nature of these models.
## Replays
You can also use the replay argument to replay a previous benchmark run. This is super useful for iterating on our diffing algorithms without having to re-run expensive and time-consuming LLM calls.
When you run an evaluation, every detail is stored in the database—including the raw, unmodified output from the model. The replay feature takes advantage of this by pulling that raw output and feeding it into a *different* diffing algorithm. This lets you isolate the performance of the diffing logic itself. We can see if a new algorithm is better at applying the exact same set of diffs that a model generated in a previous run.
This process is blazingly fast and free, as it completely bypasses the need to make new API calls. It ensures a true apples-to-apples comparison between diffing strategies, since the model's output—the "ground truth" for the evaluation—remains identical.
Heres an example of how you would replay a previous run with a new diffing algorithm:
```shell
cd evals && npm run diff-eval -- --replay-run-id 9902189e-63a8-4210-a4fc-fe59e2eaf2c2 --diff-apply-file diff-06-23-25 --verbose
```
In this command:
- `--replay-run-id` specifies the original run we want to use as our ground truth.
- `--diff-apply-file` tells the script to use the new diffing logic from the `diff-06-23-25.ts` file.
The script will then create a new run in the database that mirrors the original, but with the results of applying the new diffing algorithm. This allows for a direct comparison in the dashboard, helping us quickly see which of our diffing strategies is the most robust.
File diff suppressed because it is too large Load Diff
@@ -1,8 +0,0 @@
[theme]
base="dark"
[browser]
gatherUsageStats = false
[server]
headless = true
-159
View File
@@ -1,159 +0,0 @@
# 🚀 The Sickest Diff Edits Evaluation Dashboard Ever!
A beautiful, modern Streamlit dashboard for visualizing and analyzing diff editing evaluation results with deep drill-down capabilities.
## ✨ Features
### 🎯 **Smart Model Comparison**
- **Latest Run Focus**: Automatically loads and displays your most recent evaluation run
- **Beautiful Performance Cards**: Each model gets a stunning card with performance grades (A+ to C)
- **Best Performer Highlighting**: The top model gets special styling and a trophy 🏆
- **Interactive Charts**: Success rate comparisons and latency vs cost analysis
### 🔍 **Deep Drill-Down Analysis**
- **Individual Result Inspection**: Click any model to see detailed results
- **Side-by-Side File Views**: See original file content with line numbers
- **Parsed Tool Call Analysis**: View exactly what the model tried to do
- **Error Analysis**: Detailed error information for failed attempts
- **Success Metrics**: Line changes, edit counts, and timing breakdowns
### 🎨 **Aesthetic Design**
- **Modern UI**: Custom CSS with Inter font, gradients, and shadows
- **Responsive Layout**: Looks great on any screen size
- **Color-Coded Performance**: Green for excellent, yellow for good, red for poor
- **Smooth Animations**: Hover effects and transitions
- **Professional Styling**: Clean, modern design that looks amazing
### 📊 **Comprehensive Metrics**
- **Success Rates**: Color-coded percentages with performance grades
- **Timing Analysis**: First token, first edit, and round trip times
- **Cost Tracking**: Per-result and total cost analysis
- **Token Metrics**: Context tokens and completion tokens
- **Edit Statistics**: Number of edits, lines added/deleted
## 🚀 Quick Start
1. **Install dependencies**:
```bash
cd diff-edits/dashboard
pip install -r requirements.txt
```
2. **Launch the dashboard**:
```bash
streamlit run app.py
```
Or use the convenient launch script:
```bash
./launch.sh
```
3. **Open your browser** to http://localhost:8501
## 🎯 Dashboard Sections
### **Hero Section**
- Beautiful gradient header with run information
- Key metrics overview (models tested, total results, success rate, cost)
### **Model Performance Cards**
- Each model displayed as a beautiful card
- Large success rate display with color coding
- Performance grade badges (A+, A, B+, B, C+, C)
- Key metrics: latency, cost, results count, first token time
- "Drill Down" button for detailed analysis
### **Performance Analytics**
- Interactive bar chart showing success rates
- Scatter plot of latency vs cost with bubble sizes
- Hover details and zoom capabilities
### **Detailed Analysis (Drill-Down)**
- Model-specific success rate, latency, and cost metrics
- Individual result selector with status icons
- Tabbed interface for different views:
#### 📄 **File & Edits Tab**
- **Side-by-side view**: Original file content with line numbers
- **Edit analysis**: Success/failure status with detailed metrics
- **Error display**: Clear error information for failed attempts
- **Success metrics**: Lines added/deleted, number of edits
- **Parsed tool calls**: JSON view of what the model attempted
#### 🤖 **Raw Output Tab**
- Complete raw model output in a code viewer
- Monospace font for easy reading
#### 🔧 **Parsed Tool Call Tab**
- Pretty-printed JSON of parsed tool calls
- Diff block visualization for replace_in_file calls
- Error handling for malformed JSON
#### 📊 **Metrics Tab**
- Detailed timing metrics (first token, first edit, round trip)
- Token and cost information
- Context size and completion tokens
## 🛠 **Technical Features**
### **Smart Data Loading**
- Automatic latest run detection
- Efficient SQL queries with proper JOINs
- Streamlit caching for performance
- Error handling for missing data
### **Interactive Navigation**
- Session state management for drill-down views
- Back button to return to overview
- Smooth transitions between views
### **Beautiful Styling**
- Custom CSS with Google Fonts (Inter)
- Gradient backgrounds and shadows
- Hover effects and animations
- Color-coded performance indicators
- Professional card-based layout
### **Responsive Design**
- Works on desktop, tablet, and mobile
- Flexible column layouts
- Scalable text and metrics
## 🎨 **Design Philosophy**
This dashboard follows modern design principles:
- **Clarity**: Information is easy to find and understand
- **Beauty**: Visually appealing with professional styling
- **Functionality**: Deep drill-down capabilities for detailed analysis
- **Performance**: Fast loading with efficient data queries
- **Usability**: Intuitive navigation and clear visual hierarchy
## 📊 **Data Visualization**
- **Plotly Charts**: Interactive, professional-looking visualizations
- **Color Coding**: Consistent color scheme for performance levels
- **Performance Badges**: A+ to C grading system
- **Status Icons**: ✅ for success, ❌ for failure
- **Metric Cards**: Clean, card-based metric display
## 🔧 **Customization**
The dashboard is highly customizable:
- **CSS Styling**: Easy to modify colors, fonts, and layouts
- **Performance Grades**: Adjustable thresholds for A/B/C grades
- **Metrics Display**: Add or remove metrics as needed
- **Chart Types**: Easily swap chart types or add new visualizations
## 🚀 **Future Enhancements**
Potential additions:
- **Historical Trends**: Compare performance across multiple runs
- **Export Functionality**: Download results as CSV/PDF
- **Real-time Updates**: Auto-refresh for ongoing evaluations
- **Custom Filters**: Filter by date range, model type, etc.
- **Comparison Mode**: Side-by-side model comparisons
---
**This is the sickest eval dashboard ever!** 🔥 It combines beautiful design with powerful analysis capabilities, making it easy to understand model performance at a glance while providing deep drill-down capabilities for detailed investigation.
File diff suppressed because it is too large Load Diff
-33
View File
@@ -1,33 +0,0 @@
#!/bin/bash
# Diff Edits Evaluation Dashboard Launcher
echo "🚀 Starting Diff Edits Evaluation Dashboard..."
# Check if we're in the right directory
if [ ! -f "app.py" ]; then
echo "❌ Error: app.py not found. Please run this script from the dashboard directory."
exit 1
fi
# Check if database exists
if [ ! -f "../evals.db" ]; then
echo "⚠️ Warning: Database file ../evals.db not found."
echo " Make sure you've run some evaluations first to populate the database."
echo " You can run: node ../cli/dist/index.js run-diff-eval --model-id anthropic/claude-sonnet-4 --max-cases 1"
echo ""
fi
# Check if requirements are installed
echo "📦 Checking Python dependencies..."
if ! python -c "import streamlit, plotly, pandas" 2>/dev/null; then
echo "📥 Installing required packages..."
pip install -r requirements.txt
fi
echo "🌐 Launching Streamlit dashboard..."
echo " Dashboard will open in your browser at http://localhost:8501"
echo " Press Ctrl+C to stop the dashboard"
echo ""
# Launch Streamlit
streamlit run app.py
@@ -1,183 +0,0 @@
import streamlit as st
import pandas as pd
import json
import os # Need to import os for load_case_raw_data
from utils import get_database_connection, guess_language_from_filepath # Absolute import
st.set_page_config(
page_title="Case Health Inspector",
page_icon="🧑‍⚕️",
layout="wide"
)
st.title("Case Health Inspector")
st.markdown("Identify test cases that are frequently problematic across different models and runs.")
@st.cache_data
def load_problematic_cases_summary():
conn = get_database_connection()
query = """
WITH case_attempts AS (
SELECT
c.task_id,
c.description AS case_description,
f_orig.filepath AS original_filepath, -- Get from files table
r.run_id,
r.model_id,
r.result_id,
(CASE WHEN (r.error_enum NOT IN (1, 6, 7) OR r.error_enum IS NULL) THEN 1 ELSE 0 END) AS is_valid_attempt,
(CASE WHEN (r.error_enum NOT IN (1, 6, 7) OR r.error_enum IS NULL) THEN r.succeeded ELSE NULL END) AS succeeded_on_valid
FROM cases c
JOIN results r ON c.case_id = r.case_id
LEFT JOIN files f_orig ON c.file_hash = f_orig.hash -- Join to get original filepath
),
case_summary AS (
SELECT
task_id,
case_description,
original_filepath, -- This is now f_orig.filepath
COUNT(DISTINCT run_id) AS num_benchmark_runs,
COUNT(result_id) AS total_attempts,
SUM(is_valid_attempt) AS total_valid_attempts,
SUM(succeeded_on_valid) AS total_successful_valid_attempts
FROM case_attempts
GROUP BY task_id, case_description, original_filepath -- original_filepath is f_orig.filepath
)
SELECT
task_id,
case_description,
original_filepath, -- This is f_orig.filepath from case_summary
num_benchmark_runs,
total_attempts,
total_valid_attempts,
CAST(total_valid_attempts AS REAL) * 100.0 / total_attempts AS percent_valid_attempts,
CASE
WHEN total_valid_attempts > 0 THEN CAST(total_successful_valid_attempts AS REAL) * 100.0 / total_valid_attempts
ELSE 0
END AS success_rate_on_valid
FROM case_summary
ORDER BY percent_valid_attempts ASC, success_rate_on_valid ASC;
"""
df = pd.read_sql_query(query, conn)
return df
@st.cache_data
def load_case_raw_data(task_id):
"""Loads the original JSON data for a given task_id."""
# This assumes test cases are stored in ../cases relative to this script's parent (dashboard)
# So, ../../cases from this script's location (pages/02_Bad_Cases.py)
# Correct path from this script (pages/02_Bad_Cases.py) to cases/
# os.path.dirname(__file__) -> pages
# os.path.join(..., '..') -> dashboard
# os.path.join(..., '..', '..') -> diff-edits
# os.path.join(..., '..', '..', 'cases') -> diff-edits/cases
cases_dir = os.path.join(os.path.dirname(__file__), '..', '..', 'cases')
# The task_id is usually the filename without .json
# However, some task_ids might have suffixes or be different.
# We need a robust way to find the file. For now, assume task_id is filename base.
# This might need adjustment if task_id format varies significantly from filename.
# Try direct match first
potential_filename = f"{task_id}.json"
filepath = os.path.join(cases_dir, potential_filename)
if not os.path.exists(filepath):
# If direct match fails, list files and try to find one that starts with task_id
# This is a simple fallback, might need more robust matching if task_ids are complex
try:
for f_name in os.listdir(cases_dir):
if f_name.startswith(task_id) and f_name.endswith(".json"):
filepath = os.path.join(cases_dir, f_name)
break
else: # No break means no file found
return None # File not found
except FileNotFoundError:
return None # Cases directory itself not found
if not os.path.exists(filepath): # Check again after potential find
return None
try:
with open(filepath, 'r') as f:
return json.load(f)
except Exception as e:
st.error(f"Error loading case file {filepath}: {e}")
return None
def render_problematic_cases_page():
summary_df = load_problematic_cases_summary()
if summary_df.empty:
st.warning("No case summary data found. Run some evaluations first.")
return
st.markdown("### Cases Overview")
st.dataframe(summary_df.style.format({
"percent_valid_attempts": "{:.1f}%",
"success_rate_on_valid": "{:.1f}%"
}), use_container_width=True)
st.markdown("---")
st.markdown("### Case Drill Down")
selected_task_id = st.selectbox(
"Select a Case ID (task_id) to inspect:",
options=[""] + summary_df['task_id'].tolist() # Add a blank option
)
if selected_task_id:
case_data = summary_df[summary_df['task_id'] == selected_task_id].iloc[0]
st.subheader(f"Details for Case: {case_data['task_id']}")
st.markdown(f"**Description:** {case_data['case_description']}")
st.markdown(f"**Original Filepath:** `{case_data['original_filepath']}`")
raw_json_data = load_case_raw_data(selected_task_id)
if raw_json_data:
with st.expander("View Raw Case JSON Data", expanded=False):
st.json(raw_json_data)
if 'file_contents' in raw_json_data and raw_json_data['file_contents']:
with st.expander("View Original File Content (from Case JSON)", expanded=True):
# Prepare content for the copy button
raw_content_for_copy = raw_json_data['file_contents']
js_escaped_content = raw_content_for_copy.replace('\\', '\\\\') \
.replace('`', '\\`') \
.replace('\r\n', '\\n') \
.replace('\n', '\\n') \
.replace('\r', '\\n')
button_id = f"copyBtnCase_{selected_task_id.replace('-', '_').replace('.', '_')}"
copy_button_html = f"""
<button id="{button_id}" onclick="copyCaseContentToClipboard(`{js_escaped_content}`, '{button_id}')" style="margin-bottom: 10px; padding: 5px 10px; border-radius: 5px; border: 1px solid #ccc; cursor: pointer;">Copy File Content</button>
<script>
if (!window.copyCaseContentToClipboard) {{
window.copyCaseContentToClipboard = async function(text, buttonId) {{
try {{
await navigator.clipboard.writeText(text);
const button = document.getElementById(buttonId);
button.innerText = 'Copied!';
setTimeout(() => {{ button.innerText = 'Copy File Content'; }}, 2000);
}} catch (err) {{ console.error('Failed to copy: ', err); const button = document.getElementById(buttonId); button.innerText = 'Copy Failed!'; setTimeout(() => {{ button.innerText = 'Copy File Content'; }}, 2000); }}
}}
}}
</script>
"""
st.components.v1.html(copy_button_html, height=50)
# Prepare content for st.code
content_for_display = raw_json_data['file_contents']
content_for_display = content_for_display.replace('\\\\r\\\\n', '\r\n').replace('\\\\n', '\n')
content_for_display = content_for_display.replace('\\r\\n', '\r\n').replace('\\n', '\n')
language = guess_language_from_filepath(case_data['original_filepath'])
st.code(content_for_display, language=language, line_numbers=False)
else:
st.warning("Original file content not found in case JSON.")
else:
st.error(f"Could not load raw JSON data for case: {selected_task_id}")
# Placeholder for more detailed stats (per-model performance on this case, error breakdown)
st.markdown("*(Further per-model statistics and error breakdowns for this case can be added here.)*")
if __name__ == "__main__":
render_problematic_cases_page()
@@ -1,4 +0,0 @@
streamlit>=1.28.0
plotly>=5.17.0
pandas>=2.0.0
numpy>=1.24.0
-51
View File
@@ -1,51 +0,0 @@
import streamlit as st
import sqlite3
import pandas as pd
import os
@st.cache_resource
def get_database_connection():
# Assuming the script is run from the dashboard directory,
# evals.db is two levels up from there.
# __file__ is utils.py, its dirname is dashboard.
# os.path.dirname(__file__) -> dashboard/
# os.path.join(..., '..') -> diff-edits/
# os.path.join(..., '..', 'evals.db') -> diff-edits/evals.db
db_path = os.path.join(os.path.dirname(__file__), '..', 'evals.db')
if not os.path.exists(db_path):
st.error(f"Database not found. Expected at: {os.path.abspath(db_path)}")
st.stop()
return sqlite3.connect(db_path, check_same_thread=False)
def guess_language_from_filepath(filepath):
"""Guess the language for syntax highlighting from filepath."""
if not filepath or pd.isna(filepath):
return None
extension_map = {
'.py': 'python',
'.js': 'javascript',
'.ts': 'typescript',
'.java': 'java',
'.cs': 'csharp',
'.cpp': 'cpp',
'.c': 'c',
'.html': 'html',
'.css': 'css',
'.json': 'json',
'.sql': 'sql',
'.md': 'markdown',
'.rb': 'ruby',
'.php': 'php',
'.go': 'go',
'.rs': 'rust',
'.swift': 'swift',
'.kt': 'kotlin',
'.sh': 'bash',
'.yaml': 'yaml',
'.yml': 'yaml',
'.xml': 'xml',
}
_, ext = os.path.splitext(str(filepath)) # Ensure filepath is string
return extension_map.get(ext.lower(), None)
-96
View File
@@ -1,96 +0,0 @@
# Diff Edit Evaluation Database Schema
This document provides an overview of the SQLite database schema used for the diff edit evaluation suite. The database is designed to capture every aspect of the evaluation runs in a structured way, allowing for detailed, multi-dimensional analysis and ensuring full reproducibility of our findings.
## Data Model Overview
The database is composed of several interconnected tables that work together to provide a comprehensive picture of each evaluation. The core of the model revolves around `runs`, `cases`, and `results`.
### `runs`
A `run` represents a single, top-level execution of the evaluation script (e.g., one invocation of `npm run diff-eval`). It serves as the main container for a complete benchmark session.
- **Purpose**: To group all the results from a single benchmark execution, allowing for high-level comparison between different runs over time.
- **Key Columns**:
- `run_id`: A unique identifier for the entire run.
- `description`: A human-readable summary of the run's configuration (e.g., which models were tested, how many cases, etc.).
- `system_prompt_hash`: A foreign key that links this run to the specific system prompt that was used, ensuring we can track performance changes based on prompt modifications.
### `cases`
A `case` represents a single test scenario that is presented to a model. It corresponds to one of the JSON files in the `cases/` directory and links that static definition to a specific benchmark `run`.
- **Purpose**: To track the individual test scenarios within a given run.
- **Key Columns**:
- `case_id`: A unique identifier for the case *within* a specific run.
- `run_id`: A foreign key linking back to the parent `run`.
- `task_id`: The original, persistent identifier for the test case (typically from the JSON filename).
- `file_hash`: A foreign key linking to the original, un-edited file content for this case.
### `results`
This is the most granular and important table in the database. A `result` represents the outcome of a single attempt by a specific model on a specific case.
- **Purpose**: To store the detailed outcome of every single model attempt, providing the raw data for all quantitative and qualitative analysis.
- **Key Columns**:
- `result_id`: The primary key for the result.
- `run_id`, `case_id`, `model_id`, `processing_functions_hash`: A set of foreign keys that precisely situate this result within the context of a specific run, case, model, and set of helper functions.
- `succeeded`: A boolean indicating if the generated diff was applied successfully.
- `error_enum`: A numeric code representing the specific type of error if the attempt failed (e.g., `1` for `no_tool_calls`, `7` for `wrong_file_edited`).
- `num_edits`, `num_lines_deleted`, `num_lines_added`: Quantitative metrics about the structure of the generated diff.
- `time_to_first_token_ms`, `time_to_first_edit_ms`, `time_round_trip_ms`: High-precision timing data to measure model latency.
- `cost_usd`, `completion_tokens`: Cost and token usage metrics for efficiency analysis.
- `raw_model_output`, `file_edited_hash`, `parsed_tool_call_json`: The rich, qualitative data. This includes the model's full, raw response and the parsed tool calls, which are invaluable for debugging and understanding the model's reasoning.
---
## Supporting Tables
The following tables store versioned, deduplicated content to ensure data integrity and efficiency.
### `system_prompts`
- **Purpose**: Stores the versioned content of the system prompts used in evaluations.
- **Key Columns**:
- `hash`: A unique hash of the prompt's content, which acts as the primary key. This prevents duplicate storage of the same prompt.
- `name`: A human-readable name for the prompt (e.g., `basicSystemPrompt`, `claude4SystemPrompt`).
- `content`: The full text of the system prompt.
### `processing_functions`
- **Purpose**: Stores the versioned combinations of parsing and diff-editing functions.
- **Key Columns**:
- `hash`: A unique hash of the function combination name.
- `name`: A human-readable name (e.g., `parseV2-diffV2`).
- `parsing_function`: The name of the function used to parse the model's output.
- `diff_edit_function`: The name of the function used to apply the diff.
### `files`
- **Purpose**: Stores the content of all files involved in the tests, including the original source files and the diffs generated by the models.
- **Key Columns**:
- `hash`: A content-based hash of the file, ensuring that identical files are only stored once.
- `filepath`: The original path of the file.
- `content`: The full content of the file.
## The Bigger Picture
This relational schema provides a powerful foundation for sophisticated analysis. It moves beyond simple pass/fail metrics and allows us to explore the nuanced interactions between models, prompts, and the code they operate on. With this database, we can answer critical questions like:
- "How does prompt engineering affect not just success rate, but also latency and cost?"
- "Are certain models more prone to specific types of errors (e.g., hallucinating file paths vs. failing to call a tool)?"
- "Which of our internal diffing algorithms is the most robust against a wide range of model-generated edits?"
Ultimately, this data model enables us to move from simply *measuring* performance to truly *understanding* it, providing the insights needed to build more capable and reliable AI engineering systems.
---
## Viewing the Full Schema
To see the most up-to-date and detailed schema for the database, you can use the `sqlite3` command-line tool. From the `evals/diff-edits` directory, run the following command:
```bash
sqlite3 evals.db .schema
```
This will print the complete `CREATE TABLE` statements for all tables in the database, providing a definitive reference for the database structure.
-135
View File
@@ -1,135 +0,0 @@
import Database from 'better-sqlite3';
import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
export class DatabaseClient {
private static instance: DatabaseClient;
private db: Database.Database;
private dbPath: string;
private constructor() {
// Get database path from environment or use default
this.dbPath = process.env.DIFF_EVALS_DB_PATH || path.join(__dirname, '../evals.db');
// Ensure directory exists
const dbDir = path.dirname(this.dbPath);
if (!fs.existsSync(dbDir)) {
fs.mkdirSync(dbDir, { recursive: true });
}
// Initialize database connection
this.db = new Database(this.dbPath);
// Enable WAL mode for concurrent access
this.db.pragma('journal_mode = WAL');
// Enable foreign key constraints
this.db.pragma('foreign_keys = ON');
// Initialize schema if needed
this.initializeSchema();
}
static getInstance(): DatabaseClient {
if (!DatabaseClient.instance) {
DatabaseClient.instance = new DatabaseClient();
}
return DatabaseClient.instance;
}
private initializeSchema(): void {
// Check if tables exist by trying to query one of them
try {
this.db.prepare('SELECT COUNT(*) FROM system_prompts LIMIT 1').get();
// If we get here, tables exist
return;
} catch (error) {
// Tables don't exist, create them
console.log('Initializing database schema...');
this.createTables();
}
}
private createTables(): void {
const schemaPath = path.join(__dirname, 'schema.sql');
const schema = fs.readFileSync(schemaPath, 'utf8');
// Execute the entire schema as one block
this.db.transaction(() => {
this.db.exec(schema);
})();
console.log('Database schema initialized successfully');
}
getDatabase(): Database.Database {
return this.db;
}
getDatabasePath(): string {
return this.dbPath;
}
// Utility method to generate SHA-256 hash
static generateHash(content: string): string {
return crypto.createHash('sha256').update(content).digest('hex');
}
// Utility method to generate UUID-like ID
static generateId(): string {
return crypto.randomUUID();
}
// Transaction wrapper
transaction<T>(fn: () => T): T {
return this.db.transaction(fn)();
}
// Close database connection (for cleanup)
close(): void {
if (this.db) {
this.db.close();
}
}
// Get database info
getInfo(): { path: string; size: number; tables: string[] } {
const stats = fs.statSync(this.dbPath);
const tables = this.db
.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
.all()
.map((row: any) => row.name);
return {
path: this.dbPath,
size: stats.size,
tables
};
}
// Vacuum database (cleanup and optimize)
vacuum(): void {
this.db.exec('VACUUM');
}
// Get database statistics
getStats(): { [tableName: string]: number } {
const tables = ['system_prompts', 'processing_functions', 'files', 'runs', 'cases', 'results'];
const stats: { [tableName: string]: number } = {};
for (const table of tables) {
try {
const result = this.db.prepare(`SELECT COUNT(*) as count FROM ${table}`).get() as { count: number };
stats[table] = result.count;
} catch (error) {
stats[table] = 0;
}
}
return stats;
}
}
// Export singleton instance getter
export const getDatabase = () => DatabaseClient.getInstance();
-23
View File
@@ -1,23 +0,0 @@
// Main database module exports
export { DatabaseClient, getDatabase } from './client';
export * from './types';
export * from './operations';
export * from './queries';
// Re-export commonly used functions for convenience
export {
upsertSystemPrompt,
upsertProcessingFunctions,
upsertFile,
createBenchmarkRun,
createCase,
insertResult,
getRunStats
} from './operations';
export {
getSuccessRatesByModel,
getModelComparisons,
getDatabaseSummary,
getErrorDistribution
} from './queries';
-348
View File
@@ -1,348 +0,0 @@
import { DatabaseClient } from './client';
import {
SystemPrompt,
ProcessingFunctions,
FileRecord,
BenchmarkRun,
Case,
Result,
CreateSystemPromptInput,
CreateProcessingFunctionsInput,
CreateFileInput,
CreateBenchmarkRunInput,
CreateCaseInput,
CreateResultInput
} from './types';
const db = DatabaseClient.getInstance();
// System Prompts Operations
export async function upsertSystemPrompt(input: CreateSystemPromptInput): Promise<string> {
const hash = DatabaseClient.generateHash(input.content);
const stmt = db.getDatabase().prepare(`
INSERT OR IGNORE INTO system_prompts (hash, name, content)
VALUES (?, ?, ?)
`);
stmt.run(hash, input.name, input.content);
return hash;
}
export async function getSystemPromptByHash(hash: string): Promise<SystemPrompt | null> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM system_prompts WHERE hash = ?
`);
const result = stmt.get(hash) as SystemPrompt | undefined;
return result || null;
}
// Processing Functions Operations
export async function upsertProcessingFunctions(input: CreateProcessingFunctionsInput): Promise<string> {
const hash = DatabaseClient.generateHash(input.parsing_function + input.diff_edit_function);
const stmt = db.getDatabase().prepare(`
INSERT OR IGNORE INTO processing_functions (hash, name, parsing_function, diff_edit_function)
VALUES (?, ?, ?, ?)
`);
stmt.run(hash, input.name, input.parsing_function, input.diff_edit_function);
return hash;
}
export async function getProcessingFunctionsByHash(hash: string): Promise<ProcessingFunctions | null> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM processing_functions WHERE hash = ?
`);
const result = stmt.get(hash) as ProcessingFunctions | undefined;
return result || null;
}
// Files Operations
export async function upsertFile(input: CreateFileInput): Promise<string> {
const hash = DatabaseClient.generateHash(input.content);
const stmt = db.getDatabase().prepare(`
INSERT OR IGNORE INTO files (hash, filepath, content, tokens)
VALUES (?, ?, ?, ?)
`);
stmt.run(hash, input.filepath, input.content, input.tokens || null);
return hash;
}
export async function getFileByHash(hash: string): Promise<FileRecord | null> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM files WHERE hash = ?
`);
const result = stmt.get(hash) as FileRecord | undefined;
return result || null;
}
// Benchmark Runs Operations
export async function createBenchmarkRun(input: CreateBenchmarkRunInput): Promise<string> {
const runId = DatabaseClient.generateId();
const stmt = db.getDatabase().prepare(`
INSERT INTO runs (run_id, description, system_prompt_hash)
VALUES (?, ?, ?)
`);
stmt.run(runId, input.description || null, input.system_prompt_hash);
return runId;
}
export async function getBenchmarkRun(runId: string): Promise<BenchmarkRun | null> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM runs WHERE run_id = ?
`);
const result = stmt.get(runId) as BenchmarkRun | undefined;
return result || null;
}
export async function getAllBenchmarkRuns(): Promise<BenchmarkRun[]> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM runs ORDER BY created_at DESC
`);
return stmt.all() as BenchmarkRun[];
}
// Cases Operations
export async function createCase(input: CreateCaseInput): Promise<string> {
const caseId = DatabaseClient.generateId();
const stmt = db.getDatabase().prepare(`
INSERT INTO cases (case_id, run_id, description, system_prompt_hash, task_id, tokens_in_context, file_hash)
VALUES (?, ?, ?, ?, ?, ?, ?)
`);
stmt.run(
caseId,
input.run_id,
input.description,
input.system_prompt_hash,
input.task_id,
input.tokens_in_context,
input.file_hash || null
);
return caseId;
}
export async function getCasesByRun(runId: string): Promise<Case[]> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM cases WHERE run_id = ? ORDER BY created_at
`);
return stmt.all(runId) as Case[];
}
export async function getCaseById(caseId: string): Promise<Case | null> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM cases WHERE case_id = ?
`);
const result = stmt.get(caseId) as Case | undefined;
return result || null;
}
// Results Operations
export async function insertResult(input: CreateResultInput): Promise<string> {
const resultId = DatabaseClient.generateId();
const stmt = db.getDatabase().prepare(`
INSERT INTO results (
result_id, run_id, case_id, model_id, processing_functions_hash,
succeeded, error_enum, num_edits, num_lines_deleted, num_lines_added,
time_to_first_token_ms, time_to_first_edit_ms, time_round_trip_ms,
cost_usd, completion_tokens, raw_model_output, file_edited_hash,
parsed_tool_call_json
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
stmt.run(
resultId,
input.run_id,
input.case_id,
input.model_id,
input.processing_functions_hash,
input.succeeded ? 1 : 0, // Convert boolean to integer
input.error_enum || null,
input.num_edits || null,
input.num_lines_deleted || null,
input.num_lines_added || null,
input.time_to_first_token_ms || null,
input.time_to_first_edit_ms || null,
input.time_round_trip_ms || null,
input.cost_usd || null,
input.completion_tokens || null,
input.raw_model_output || null,
input.file_edited_hash || null,
input.parsed_tool_call_json || null
);
return resultId;
}
export async function getResultsByRun(runId: string): Promise<Result[]> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM results WHERE run_id = ? ORDER BY created_at
`);
return stmt.all(runId) as Result[];
}
export async function getResultsByCase(caseId: string): Promise<Result[]> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM results WHERE case_id = ? ORDER BY created_at
`);
return stmt.all(caseId) as Result[];
}
export async function getResultById(resultId: string): Promise<Result | null> {
const stmt = db.getDatabase().prepare(`
SELECT * FROM results WHERE result_id = ?
`);
const result = stmt.get(resultId) as Result | undefined;
return result || null;
}
// Batch operations for performance
export async function insertResultsBatch(inputs: CreateResultInput[]): Promise<string[]> {
const stmt = db.getDatabase().prepare(`
INSERT INTO results (
result_id, run_id, case_id, model_id, processing_functions_hash,
succeeded, error_enum, num_edits, num_lines_deleted, num_lines_added,
time_to_first_token_ms, time_to_first_edit_ms, time_round_trip_ms,
cost_usd, completion_tokens, raw_model_output, file_edited_hash,
parsed_tool_call_json
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
return db.transaction(() => {
const resultIds: string[] = [];
for (const input of inputs) {
const resultId = DatabaseClient.generateId();
stmt.run(
resultId,
input.run_id,
input.case_id,
input.model_id,
input.processing_functions_hash,
input.succeeded ? 1 : 0, // Convert boolean to integer
input.error_enum || null,
input.num_edits || null,
input.num_lines_deleted || null,
input.num_lines_added || null,
input.time_to_first_token_ms || null,
input.time_to_first_edit_ms || null,
input.time_round_trip_ms || null,
input.cost_usd || null,
input.completion_tokens || null,
input.raw_model_output || null,
input.file_edited_hash || null,
input.parsed_tool_call_json || null
);
resultIds.push(resultId);
}
return resultIds;
});
}
export async function createCasesBatch(inputs: CreateCaseInput[]): Promise<string[]> {
const stmt = db.getDatabase().prepare(`
INSERT INTO cases (case_id, run_id, description, system_prompt_hash, task_id, tokens_in_context)
VALUES (?, ?, ?, ?, ?, ?)
`);
return db.transaction(() => {
const caseIds: string[] = [];
for (const input of inputs) {
const caseId = DatabaseClient.generateId();
stmt.run(
caseId,
input.run_id,
input.description,
input.system_prompt_hash,
input.task_id,
input.tokens_in_context
);
caseIds.push(caseId);
}
return caseIds;
});
}
// Utility functions
export async function getRunStats(runId: string): Promise<{
total_cases: number;
total_results: number;
success_rate: number;
avg_cost: number;
avg_latency: number;
}> {
const stmt = db.getDatabase().prepare(`
SELECT
COUNT(DISTINCT c.case_id) as total_cases,
COUNT(r.result_id) as total_results,
AVG(CASE WHEN r.succeeded THEN 1.0 ELSE 0.0 END) as success_rate,
AVG(r.cost_usd) as avg_cost,
AVG(r.time_round_trip_ms) as avg_latency
FROM cases c
LEFT JOIN results r ON c.case_id = r.case_id
WHERE c.run_id = ?
`);
const result = stmt.get(runId) as any;
return {
total_cases: result.total_cases || 0,
total_results: result.total_results || 0,
success_rate: result.success_rate || 0,
avg_cost: result.avg_cost || 0,
avg_latency: result.avg_latency || 0
};
}
// Count valid attempts for a specific case and model
export async function getValidAttemptCount(caseId: string, modelId: string): Promise<number> {
const stmt = db.getDatabase().prepare(`
SELECT COUNT(*) as count
FROM results
WHERE case_id = ?
AND model_id = ?
AND error_enum NOT IN (1, 6, 7) -- Exclude: no_tool_calls, wrong_tool_call, wrong_file_edited
`);
const result = stmt.get(caseId, modelId) as { count: number };
return result.count;
}
// Get valid results for a specific case and model (for analysis)
export async function getValidResults(caseId: string, modelId: string, limit?: number): Promise<Result[]> {
const limitClause = limit ? `LIMIT ${limit}` : '';
const stmt = db.getDatabase().prepare(`
SELECT * FROM results
WHERE case_id = ?
AND model_id = ?
AND error_enum NOT IN (1, 6, 7) -- Only valid attempts
ORDER BY created_at
${limitClause}
`);
return stmt.all(caseId, modelId) as Result[];
}
-309
View File
@@ -1,309 +0,0 @@
import { DatabaseClient } from './client';
import {
ModelSuccessRate,
ModelLatency,
CostAnalysis,
ErrorDistribution,
FailedCase,
PerformanceTrend,
ModelComparison
} from './types';
const db = DatabaseClient.getInstance();
// Performance analysis queries
export async function getSuccessRatesByModel(): Promise<ModelSuccessRate[]> {
const stmt = db.getDatabase().prepare(`
SELECT
model_id,
COUNT(*) as total_runs,
SUM(CASE WHEN succeeded THEN 1 ELSE 0 END) as successful_runs,
ROUND(AVG(CASE WHEN succeeded THEN 1.0 ELSE 0.0 END) * 100, 2) as success_rate
FROM results
WHERE error_enum NOT IN (1, 6, 7) OR error_enum IS NULL -- Exclude: no_tool_calls, wrong_tool_call, wrong_file_edited
GROUP BY model_id
ORDER BY success_rate DESC, total_runs DESC
`);
return stmt.all() as ModelSuccessRate[];
}
export async function getAverageLatencyByModel(): Promise<ModelLatency[]> {
const stmt = db.getDatabase().prepare(`
SELECT
model_id,
ROUND(AVG(time_to_first_token_ms), 2) as avg_time_to_first_token_ms,
ROUND(AVG(time_to_first_edit_ms), 2) as avg_time_to_first_edit_ms,
ROUND(AVG(time_round_trip_ms), 2) as avg_time_round_trip_ms
FROM results
WHERE time_to_first_token_ms IS NOT NULL
GROUP BY model_id
ORDER BY avg_time_round_trip_ms ASC
`);
return stmt.all() as ModelLatency[];
}
export async function getCostAnalysisByRun(): Promise<CostAnalysis[]> {
const stmt = db.getDatabase().prepare(`
SELECT
run_id,
model_id,
ROUND(SUM(cost_usd), 4) as total_cost_usd,
ROUND(AVG(cost_usd), 4) as avg_cost_per_case,
SUM(completion_tokens) as total_completion_tokens
FROM results
WHERE cost_usd IS NOT NULL
GROUP BY run_id, model_id
ORDER BY total_cost_usd DESC
`);
return stmt.all() as CostAnalysis[];
}
// Error analysis queries
export async function getErrorDistribution(): Promise<ErrorDistribution[]> {
const stmt = db.getDatabase().prepare(`
SELECT
error_enum,
COUNT(*) as count,
ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM results WHERE succeeded = 0), 2) as percentage
FROM results
WHERE succeeded = 0 AND error_enum IS NOT NULL
GROUP BY error_enum
ORDER BY count DESC
`);
return stmt.all() as ErrorDistribution[];
}
export async function getFailedCasesByError(errorEnum?: number): Promise<FailedCase[]> {
let query = `
SELECT
r.case_id,
r.model_id,
r.error_enum,
c.description,
r.raw_model_output
FROM results r
JOIN cases c ON r.case_id = c.case_id
WHERE r.succeeded = 0
`;
const params: any[] = [];
if (errorEnum !== undefined) {
query += ` AND r.error_enum = ?`;
params.push(errorEnum);
}
query += ` ORDER BY r.created_at DESC LIMIT 100`;
const stmt = db.getDatabase().prepare(query);
return stmt.all(...params) as FailedCase[];
}
// Trend analysis queries
export async function getPerformanceTrends(days: number = 30): Promise<PerformanceTrend[]> {
const stmt = db.getDatabase().prepare(`
SELECT
DATE(r.created_at) as date,
r.model_id,
ROUND(AVG(CASE WHEN r.succeeded THEN 1.0 ELSE 0.0 END) * 100, 2) as success_rate,
ROUND(AVG(r.time_round_trip_ms), 2) as avg_latency_ms,
ROUND(AVG(r.cost_usd), 4) as avg_cost_usd
FROM results r
WHERE r.created_at >= datetime('now', '-' || ? || ' days')
AND (r.error_enum NOT IN (1, 6, 7) OR r.error_enum IS NULL) -- Exclude: no_tool_calls, wrong_tool_call, wrong_file_edited
GROUP BY DATE(r.created_at), r.model_id
ORDER BY date DESC, model_id
`);
return stmt.all(days) as PerformanceTrend[];
}
export async function getModelComparisons(): Promise<ModelComparison[]> {
const stmt = db.getDatabase().prepare(`
SELECT
model_id,
ROUND(AVG(CASE WHEN succeeded THEN 1.0 ELSE 0.0 END) * 100, 2) as success_rate,
ROUND(AVG(time_round_trip_ms), 2) as avg_latency_ms,
ROUND(AVG(cost_usd), 4) as avg_cost_usd,
COUNT(*) as total_runs
FROM results
WHERE error_enum NOT IN (1, 6, 7) OR error_enum IS NULL -- Exclude: no_tool_calls, wrong_tool_call, wrong_file_edited
GROUP BY model_id
HAVING total_runs >= 10
ORDER BY success_rate DESC, avg_latency_ms ASC
`);
return stmt.all() as ModelComparison[];
}
// Advanced analysis queries
export async function getTopPerformingCases(limit: number = 10): Promise<Array<{
case_id: string;
description: string;
success_rate: number;
avg_latency_ms: number;
total_runs: number;
}>> {
const stmt = db.getDatabase().prepare(`
SELECT
c.case_id,
c.description,
ROUND(AVG(CASE WHEN r.succeeded THEN 1.0 ELSE 0.0 END) * 100, 2) as success_rate,
ROUND(AVG(r.time_round_trip_ms), 2) as avg_latency_ms,
COUNT(r.result_id) as total_runs
FROM cases c
JOIN results r ON c.case_id = r.case_id
WHERE r.error_enum NOT IN (1, 6, 7) OR r.error_enum IS NULL -- Exclude: no_tool_calls, wrong_tool_call, wrong_file_edited
GROUP BY c.case_id, c.description
HAVING total_runs >= 5
ORDER BY success_rate DESC, avg_latency_ms ASC
LIMIT ?
`);
return stmt.all(limit) as Array<{
case_id: string;
description: string;
success_rate: number;
avg_latency_ms: number;
total_runs: number;
}>;
}
export async function getWorstPerformingCases(limit: number = 10): Promise<Array<{
case_id: string;
description: string;
success_rate: number;
avg_latency_ms: number;
total_runs: number;
}>> {
const stmt = db.getDatabase().prepare(`
SELECT
c.case_id,
c.description,
ROUND(AVG(CASE WHEN r.succeeded THEN 1.0 ELSE 0.0 END) * 100, 2) as success_rate,
ROUND(AVG(r.time_round_trip_ms), 2) as avg_latency_ms,
COUNT(r.result_id) as total_runs
FROM cases c
JOIN results r ON c.case_id = r.case_id
WHERE r.error_enum NOT IN (1, 6, 7) OR r.error_enum IS NULL -- Exclude: no_tool_calls, wrong_tool_call, wrong_file_edited
GROUP BY c.case_id, c.description
HAVING total_runs >= 5
ORDER BY success_rate ASC, avg_latency_ms DESC
LIMIT ?
`);
return stmt.all(limit) as Array<{
case_id: string;
description: string;
success_rate: number;
avg_latency_ms: number;
total_runs: number;
}>;
}
export async function getModelPerformanceByTimeOfDay(): Promise<Array<{
model_id: string;
hour: number;
success_rate: number;
avg_latency_ms: number;
total_runs: number;
}>> {
const stmt = db.getDatabase().prepare(`
SELECT
model_id,
CAST(strftime('%H', created_at) AS INTEGER) as hour,
ROUND(AVG(CASE WHEN succeeded THEN 1.0 ELSE 0.0 END) * 100, 2) as success_rate,
ROUND(AVG(time_round_trip_ms), 2) as avg_latency_ms,
COUNT(*) as total_runs
FROM results
GROUP BY model_id, hour
HAVING total_runs >= 5
ORDER BY model_id, hour
`);
return stmt.all() as Array<{
model_id: string;
hour: number;
success_rate: number;
avg_latency_ms: number;
total_runs: number;
}>;
}
export async function getRunComparison(runId1: string, runId2: string): Promise<{
run1: { run_id: string; success_rate: number; avg_latency_ms: number; avg_cost_usd: number; total_cases: number };
run2: { run_id: string; success_rate: number; avg_latency_ms: number; avg_cost_usd: number; total_cases: number };
}> {
const stmt = db.getDatabase().prepare(`
SELECT
run_id,
ROUND(AVG(CASE WHEN succeeded THEN 1.0 ELSE 0.0 END) * 100, 2) as success_rate,
ROUND(AVG(time_round_trip_ms), 2) as avg_latency_ms,
ROUND(AVG(cost_usd), 4) as avg_cost_usd,
COUNT(DISTINCT case_id) as total_cases
FROM results
WHERE run_id IN (?, ?)
GROUP BY run_id
`);
const results = stmt.all(runId1, runId2) as Array<{
run_id: string;
success_rate: number;
avg_latency_ms: number;
avg_cost_usd: number;
total_cases: number;
}>;
const run1 = results.find(r => r.run_id === runId1);
const run2 = results.find(r => r.run_id === runId2);
if (!run1 || !run2) {
throw new Error('One or both runs not found');
}
return { run1, run2 };
}
// Summary statistics
export async function getDatabaseSummary(): Promise<{
total_runs: number;
total_cases: number;
total_results: number;
valid_results: number;
unique_models: number;
overall_success_rate: number;
date_range: { earliest: string; latest: string };
}> {
const stmt = db.getDatabase().prepare(`
SELECT
(SELECT COUNT(*) FROM runs) as total_runs,
(SELECT COUNT(*) FROM cases) as total_cases,
(SELECT COUNT(*) FROM results) as total_results,
(SELECT COUNT(*) FROM results WHERE error_enum NOT IN (1, 6, 7) OR error_enum IS NULL) as valid_results,
(SELECT COUNT(DISTINCT model_id) FROM results) as unique_models,
(SELECT ROUND(AVG(CASE WHEN succeeded THEN 1.0 ELSE 0.0 END) * 100, 2)
FROM results
WHERE error_enum NOT IN (1, 6, 7) OR error_enum IS NULL) as overall_success_rate,
(SELECT MIN(created_at) FROM results) as earliest,
(SELECT MAX(created_at) FROM results) as latest
FROM results
LIMIT 1
`);
const result = stmt.get() as any;
return {
total_runs: result.total_runs || 0,
total_cases: result.total_cases || 0,
total_results: result.total_results || 0,
valid_results: result.valid_results || 0,
unique_models: result.unique_models || 0,
overall_success_rate: result.overall_success_rate || 0,
date_range: {
earliest: result.earliest || '',
latest: result.latest || ''
}
};
}
-78
View File
@@ -1,78 +0,0 @@
PRAGMA foreign_keys = ON;
CREATE TABLE system_prompts (
hash TEXT PRIMARY KEY,
name TEXT NOT NULL,
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE processing_functions (
hash TEXT PRIMARY KEY,
name TEXT NOT NULL,
parsing_function TEXT NOT NULL,
diff_edit_function TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE files (
hash TEXT PRIMARY KEY,
filepath TEXT NOT NULL,
content TEXT NOT NULL,
tokens INTEGER,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE runs (
run_id TEXT PRIMARY KEY,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
description TEXT,
system_prompt_hash TEXT NOT NULL,
FOREIGN KEY (system_prompt_hash) REFERENCES system_prompts(hash)
);
CREATE TABLE cases (
case_id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
description TEXT NOT NULL,
system_prompt_hash TEXT NOT NULL,
task_id TEXT NOT NULL,
tokens_in_context INTEGER,
file_hash TEXT,
FOREIGN KEY (run_id) REFERENCES runs(run_id),
FOREIGN KEY (system_prompt_hash) REFERENCES system_prompts(hash),
FOREIGN KEY (file_hash) REFERENCES files(hash)
);
CREATE TABLE results (
result_id TEXT PRIMARY KEY,
run_id TEXT NOT NULL,
case_id TEXT NOT NULL,
model_id TEXT NOT NULL,
processing_functions_hash TEXT NOT NULL,
succeeded BOOLEAN NOT NULL,
error_enum INTEGER,
num_edits INTEGER,
num_lines_deleted INTEGER,
num_lines_added INTEGER,
time_to_first_token_ms INTEGER,
time_to_first_edit_ms INTEGER,
time_round_trip_ms INTEGER,
cost_usd REAL,
completion_tokens INTEGER,
raw_model_output TEXT,
file_edited_hash TEXT,
parsed_tool_call_json TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (run_id) REFERENCES runs(run_id),
FOREIGN KEY (case_id) REFERENCES cases(case_id),
FOREIGN KEY (processing_functions_hash) REFERENCES processing_functions(hash)
);
CREATE INDEX idx_results_run_model ON results(run_id, model_id);
CREATE INDEX idx_results_case_model ON results(case_id, model_id);
CREATE INDEX idx_results_success ON results(succeeded);
CREATE INDEX idx_cases_run ON cases(run_id);
CREATE INDEX idx_results_created_at ON results(created_at);
CREATE INDEX idx_runs_created_at ON runs(created_at);
-53
View File
@@ -1,53 +0,0 @@
// Simple test to verify database functionality
import { getDatabase } from './client';
import { upsertSystemPrompt, createBenchmarkRun, getDatabaseSummary } from './index';
async function testDatabase() {
console.log('Testing database functionality...');
try {
// Test database connection
const db = getDatabase();
console.log('✓ Database connection established');
console.log('Database path:', db.getDatabasePath());
// Test database info
const info = db.getInfo();
console.log('✓ Database info:', info);
// Test database stats
const stats = db.getStats();
console.log('✓ Database stats:', stats);
// Test system prompt creation
const systemPromptHash = await upsertSystemPrompt({
name: 'test-prompt',
content: 'This is a test system prompt for database verification.'
});
console.log('✓ System prompt created with hash:', systemPromptHash);
// Test benchmark run creation
const runId = await createBenchmarkRun({
description: 'Test run for database verification',
system_prompt_hash: systemPromptHash
});
console.log('✓ Benchmark run created with ID:', runId);
// Test database summary
const summary = await getDatabaseSummary();
console.log('✓ Database summary:', summary);
console.log('\n🎉 All database tests passed!');
} catch (error) {
console.error('❌ Database test failed:', error);
process.exit(1);
}
}
// Run test if this file is executed directly
if (require.main === module) {
testDatabase();
}
export { testDatabase };
-169
View File
@@ -1,169 +0,0 @@
// Database type definitions for diff-edits evaluation system
export interface SystemPrompt {
hash: string;
name: string;
content: string;
created_at: string;
}
export interface ProcessingFunctions {
hash: string;
name: string;
parsing_function: string;
diff_edit_function: string;
created_at: string;
}
export interface FileRecord {
hash: string;
filepath: string;
content: string;
tokens?: number;
created_at: string;
}
export interface BenchmarkRun {
run_id: string;
created_at: string;
description?: string;
system_prompt_hash: string;
}
export interface Case {
case_id: string
run_id: string
created_at: string
description: string
system_prompt_hash: string
task_id: string
tokens_in_context: number
file_hash?: string
}
export interface Result {
result_id: string;
run_id: string;
case_id: string;
model_id: string;
processing_functions_hash: string;
succeeded: boolean;
error_enum?: number;
num_edits?: number;
num_lines_deleted?: number;
num_lines_added?: number;
time_to_first_token_ms?: number;
time_to_first_edit_ms?: number;
time_round_trip_ms?: number;
cost_usd?: number;
completion_tokens?: number;
raw_model_output?: string;
file_edited_hash?: string;
parsed_tool_call_json?: string;
created_at: string;
}
// Input types for creating records
export interface CreateSystemPromptInput {
name: string;
content: string;
}
export interface CreateProcessingFunctionsInput {
name: string;
parsing_function: string;
diff_edit_function: string;
}
export interface CreateFileInput {
filepath: string;
content: string;
tokens?: number;
}
export interface CreateBenchmarkRunInput {
description?: string;
system_prompt_hash: string;
}
export interface CreateCaseInput {
run_id: string;
description: string;
system_prompt_hash: string;
task_id: string;
tokens_in_context: number;
file_hash?: string;
}
export interface CreateResultInput {
run_id: string;
case_id: string;
model_id: string;
processing_functions_hash: string;
succeeded: boolean;
error_enum?: number;
num_edits?: number;
num_lines_deleted?: number;
num_lines_added?: number;
time_to_first_token_ms?: number;
time_to_first_edit_ms?: number;
time_round_trip_ms?: number;
cost_usd?: number;
completion_tokens?: number;
raw_model_output?: string;
file_edited_hash?: string;
parsed_tool_call_json?: string;
}
// Analysis result types
export interface ModelSuccessRate {
model_id: string;
total_runs: number;
successful_runs: number;
success_rate: number;
}
export interface ModelLatency {
model_id: string;
avg_time_to_first_token_ms: number;
avg_time_to_first_edit_ms: number;
avg_time_round_trip_ms: number;
}
export interface CostAnalysis {
run_id: string;
model_id: string;
total_cost_usd: number;
avg_cost_per_case: number;
total_completion_tokens: number;
}
export interface ErrorDistribution {
error_enum: number;
count: number;
percentage: number;
}
export interface FailedCase {
case_id: string;
model_id: string;
error_enum: number;
description: string;
raw_model_output?: string;
}
export interface PerformanceTrend {
date: string;
model_id: string;
success_rate: number;
avg_latency_ms: number;
avg_cost_usd: number;
}
export interface ModelComparison {
model_id: string;
success_rate: number;
avg_latency_ms: number;
avg_cost_usd: number;
total_runs: number;
}

Some files were not shown because too many files have changed in this diff Show More