mirror of
https://github.com/cline/cline.git
synced 2026-09-01 23:19:18 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bdf6566655 | |||
| 2bbd6e0307 | |||
| 37b4dc477c | |||
| 9d49e95295 | |||
| 221b083588 | |||
| d7e73b4ada | |||
| 3299201cec | |||
| d88aab6090 | |||
| 8ae5ee6bf3 |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix showing the ai core exisiting models when resource group field is empty (using the default resource group)
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix: make AWS Bedrock authentication predictable
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix issue on Account view where balance is fetched twice that cause janky UI
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
Add "Add Memory Bank" button in settings
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fixes an issue where thinking text from litellm was not being passed through to Cline thinking UI
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Add translation to CODE_OF_CONDUCT, CONTRIBUTING and README to Arabic ar-sa.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
A new MCP Marketplace display setting has been added to VSCode settings. (It is defaulted to "true")
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix Ollama connection issue to default endpoint at port 11434
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Optimized Cline for GPT-5 model family with an aligned system prompt
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
REfactoring Tool Executor
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Add search functionality to API provider dropdown
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
.clineignore should be included in .gitignore
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Remove disabled approve / reject buttons from UI.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Migrate webview from CRA to Vite
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
Include optional telemetry to help cline improve
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
Add rich MCP responses with images and link previews
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
Add preferred language option to settings
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Add "Use custom prompt" option to Ollama provider
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
- **Branch-Per-Task:** Each repo now has a single Shadow Git repo, with separate branches per task (instead of one Shadow Git repo per task).
|
||||
- **Legacy Support:** Existing Checkpoints remain functional, while all new Checkpoints use branch-per-task.
|
||||
|
||||
- **Commits:** Legacy tasks commit to legacy Checkpoints; new tasks commit using branch-per-task.
|
||||
- **Diffing & Deletions:** Both legacy and branch-per-task Checkpoints support diffing and deletion.
|
||||
|
||||
No migration needed—existing tasks stay as-is, and new tasks adopt **branch-per-task** automatically.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix AutoApproveModal overflowing issue
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Dify.ai api integration
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
support orchestration mode for sap provider
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Improve Gemini Rate Limit handling
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix: Support Anthropic Caching when using LiteLLM
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Adjustment to MCP server installation prompt
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Prompt changes for deep-planning in windows/powershell
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
ADD IS_DEV and Hot Reloading to debug
|
||||
@@ -1,764 +0,0 @@
|
||||
# Cline Extension Architecture & Development Guide
|
||||
|
||||
## Project Overview
|
||||
|
||||
Cline is a VSCode extension that provides AI assistance through a combination of a core extension backend and a React-based webview frontend. The extension is built with TypeScript and follows a modular architecture pattern.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph VSCodeExtensionHost[VSCode Extension Host]
|
||||
subgraph CoreExtension[Core Extension]
|
||||
ExtensionEntry[Extension Entry<br/>src/extension.ts]
|
||||
WebviewProvider[WebviewProvider<br/>src/core/webview/index.ts]
|
||||
Controller[Controller<br/>src/core/controller/index.ts]
|
||||
Task[Task<br/>src/core/task/index.ts]
|
||||
GlobalState[VSCode Global State]
|
||||
SecretsStorage[VSCode Secrets Storage]
|
||||
McpHub[McpHub<br/>src/services/mcp/McpHub.ts]
|
||||
end
|
||||
|
||||
subgraph WebviewUI[Webview UI]
|
||||
WebviewApp[React App<br/>webview-ui/src/App.tsx]
|
||||
ExtStateContext[ExtensionStateContext<br/>webview-ui/src/context/ExtensionStateContext.tsx]
|
||||
ReactComponents[React Components]
|
||||
end
|
||||
|
||||
subgraph Storage
|
||||
TaskStorage[Task Storage<br/>Per-Task Files & History]
|
||||
CheckpointSystem[Git-based Checkpoints]
|
||||
end
|
||||
|
||||
subgraph apiProviders[API Providers]
|
||||
AnthropicAPI[Anthropic]
|
||||
OpenRouterAPI[OpenRouter]
|
||||
BedrockAPI[AWS Bedrock]
|
||||
OtherAPIs[Other Providers]
|
||||
end
|
||||
|
||||
subgraph MCPServers[MCP Servers]
|
||||
ExternalMcpServers[External MCP Servers]
|
||||
end
|
||||
end
|
||||
|
||||
%% Core Extension Data Flow
|
||||
ExtensionEntry --> WebviewProvider
|
||||
WebviewProvider --> Controller
|
||||
Controller --> Task
|
||||
Controller --> McpHub
|
||||
Task --> GlobalState
|
||||
Task --> SecretsStorage
|
||||
Task --> TaskStorage
|
||||
Task --> CheckpointSystem
|
||||
Task --> |API Requests| apiProviders
|
||||
McpHub --> |Connects to| ExternalMcpServers
|
||||
Task --> |Uses| McpHub
|
||||
|
||||
%% Webview Data Flow
|
||||
WebviewApp --> ExtStateContext
|
||||
ExtStateContext --> ReactComponents
|
||||
|
||||
%% Bidirectional Communication
|
||||
WebviewProvider <-->|postMessage| ExtStateContext
|
||||
|
||||
style GlobalState fill:#f9f,stroke:#333,stroke-width:2px
|
||||
style SecretsStorage fill:#f9f,stroke:#333,stroke-width:2px
|
||||
style ExtStateContext fill:#bbf,stroke:#333,stroke-width:2px
|
||||
style WebviewProvider fill:#bfb,stroke:#333,stroke-width:2px
|
||||
style McpHub fill:#bfb,stroke:#333,stroke-width:2px
|
||||
style apiProviders fill:#fdb,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
## Definitions
|
||||
|
||||
- **Core Extension**: Anything inside the src folder, organized into modular components
|
||||
- **Core Extension State**: Managed by the Controller class in src/core/controller/index.ts, which serves as the single source of truth for the extension's state. It manages multiple types of persistent storage (global state, workspace state, and secrets), handles state distribution to both the core extension and webview components, and coordinates state across multiple extension instances. This includes managing API configurations, task history, settings, and MCP configurations.
|
||||
- **Webview**: Anything inside the webview-ui. All the react or view's seen by the user and user interaction components
|
||||
- **Webview State**: Managed by ExtensionStateContext in webview-ui/src/context/ExtensionStateContext.tsx, which provides React components with access to the extension's state through a context provider pattern. It maintains local state for UI components, handles real-time updates through message events, manages partial message updates, and provides methods for state modifications. The context includes extension version, messages, task history, theme, API configurations, MCP servers, marketplace catalog, and workspace file paths. It synchronizes with the core extension through VSCode's message passing system and provides type-safe access to state through a custom hook (useExtensionState).
|
||||
|
||||
### Core Extension Architecture
|
||||
|
||||
The core extension follows a clear hierarchical structure:
|
||||
|
||||
1. **WebviewProvider** (src/core/webview/index.ts): Manages the webview lifecycle and communication
|
||||
2. **Controller** (src/core/controller/index.ts): Handles webview messages and task management
|
||||
3. **Task** (src/core/task/index.ts): Executes API requests and tool operations
|
||||
|
||||
This architecture provides clear separation of concerns:
|
||||
- WebviewProvider focuses on VSCode webview integration
|
||||
- Controller manages state and coordinates tasks
|
||||
- Task handles the execution of AI requests and tool operations
|
||||
|
||||
### WebviewProvider Implementation
|
||||
|
||||
The WebviewProvider class in `src/core/webview/index.ts` is responsible for:
|
||||
|
||||
- Managing multiple active instances through a static set (`activeInstances`)
|
||||
- Handling webview lifecycle events (creation, visibility changes, disposal)
|
||||
- Implementing HTML content generation with proper CSP headers
|
||||
- Supporting Hot Module Replacement (HMR) for development
|
||||
- Setting up message listeners between the webview and extension
|
||||
|
||||
The WebviewProvider maintains a reference to the Controller and delegates message handling to it. It also handles the creation of both sidebar and tab panel webviews, allowing Cline to be used in different contexts within VSCode.
|
||||
|
||||
### Core Extension State
|
||||
|
||||
The `Controller` class manages multiple types of persistent storage:
|
||||
|
||||
- **Global State:** Stored across all VSCode instances. Used for settings and data that should persist globally.
|
||||
- **Workspace State:** Specific to the current workspace. Used for task-specific data and settings.
|
||||
- **Secrets:** Secure storage for sensitive information like API keys.
|
||||
|
||||
The `Controller` handles the distribution of state to both the core extension and webview components. It also coordinates state across multiple extension instances, ensuring consistency.
|
||||
|
||||
State synchronization between instances is handled through:
|
||||
- File-based storage for task history and conversation data
|
||||
- VSCode's global state API for settings and configuration
|
||||
- Secrets storage for sensitive information
|
||||
- Event listeners for file changes and configuration updates
|
||||
|
||||
The Controller implements methods for:
|
||||
- Saving and loading task state
|
||||
- Managing API configurations
|
||||
- Handling user authentication
|
||||
- Coordinating MCP server connections
|
||||
- Managing task history and checkpoints
|
||||
|
||||
### Webview State
|
||||
|
||||
The `ExtensionStateContext` in `webview-ui/src/context/ExtensionStateContext.tsx` provides React components with access to the extension's state. It uses a context provider pattern and maintains local state for UI components. The context includes:
|
||||
|
||||
- Extension version
|
||||
- Messages
|
||||
- Task history
|
||||
- Theme
|
||||
- API configurations
|
||||
- MCP servers
|
||||
- Marketplace catalog
|
||||
- Workspace file paths
|
||||
|
||||
It synchronizes with the core extension through VSCode's message passing system and provides type-safe access to the state via a custom hook (`useExtensionState`).
|
||||
|
||||
The ExtensionStateContext handles:
|
||||
- Real-time updates through message events
|
||||
- Partial message updates for streaming content
|
||||
- State modifications through setter methods
|
||||
- Type-safe access to state through a custom hook
|
||||
|
||||
## API Provider System
|
||||
|
||||
Cline supports multiple AI providers through a modular API provider system. Each provider is implemented as a separate module in the `src/api/providers/` directory and follows a common interface.
|
||||
|
||||
### API Provider Architecture
|
||||
|
||||
The API system consists of:
|
||||
|
||||
1. **API Handlers**: Provider-specific implementations in `src/api/providers/`
|
||||
2. **API Transformers**: Stream transformation utilities in `src/api/transform/`
|
||||
3. **API Configuration**: User settings for API keys and endpoints
|
||||
4. **API Factory**: Builder function to create the appropriate handler
|
||||
|
||||
Key providers include:
|
||||
- **Anthropic**: Direct integration with Claude models
|
||||
- **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
|
||||
|
||||
### API Configuration Management
|
||||
|
||||
API configurations are stored securely:
|
||||
- API keys are stored in VSCode's secrets storage
|
||||
- Model selections and non-sensitive settings are stored in global state
|
||||
- The Controller manages switching between providers and updating configurations
|
||||
|
||||
The system supports:
|
||||
- Secure storage of API keys
|
||||
- Model selection and configuration
|
||||
- Automatic retry and error handling
|
||||
- Token usage tracking and cost calculation
|
||||
- Context window management
|
||||
|
||||
### Plan/Act Mode API Configuration
|
||||
|
||||
Cline supports separate model configurations for Plan and Act modes:
|
||||
- Different models can be used for planning vs. execution
|
||||
- The system preserves model selections when switching modes
|
||||
- The Controller handles the transition between modes and updates the API configuration accordingly
|
||||
|
||||
## Task Execution System
|
||||
|
||||
The Task class is responsible for executing AI requests and tool operations. Each task runs in its own instance of the Task class, ensuring isolation and proper state management.
|
||||
|
||||
### Task Execution Loop
|
||||
|
||||
The core task execution loop follows this pattern:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async initiateTaskLoop(userContent: UserContent, isNewTask: boolean) {
|
||||
while (!this.abort) {
|
||||
// 1. Make API request and stream response
|
||||
const stream = this.attemptApiRequest()
|
||||
|
||||
// 2. Parse and present content blocks
|
||||
for await (const chunk of stream) {
|
||||
switch (chunk.type) {
|
||||
case "text":
|
||||
// Parse into content blocks
|
||||
this.assistantMessageContent = parseAssistantMessageV2(chunk.text)
|
||||
// Present blocks to user
|
||||
await this.presentAssistantMessage()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Wait for tool execution to complete
|
||||
await pWaitFor(() => this.userMessageContentReady)
|
||||
|
||||
// 4. Continue loop with tool result
|
||||
const recDidEndLoop = await this.recursivelyMakeClineRequests(
|
||||
this.userMessageContent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Message Streaming System
|
||||
|
||||
The streaming system handles real-time updates and partial content:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async presentAssistantMessage() {
|
||||
// Handle streaming locks to prevent race conditions
|
||||
if (this.presentAssistantMessageLocked) {
|
||||
this.presentAssistantMessageHasPendingUpdates = true
|
||||
return
|
||||
}
|
||||
this.presentAssistantMessageLocked = true
|
||||
|
||||
// Present current content block
|
||||
const block = this.assistantMessageContent[this.currentStreamingContentIndex]
|
||||
|
||||
// Handle different types of content
|
||||
switch (block.type) {
|
||||
case "text":
|
||||
await this.say("text", content, undefined, block.partial)
|
||||
break
|
||||
case "tool_use":
|
||||
// Handle tool execution
|
||||
break
|
||||
}
|
||||
|
||||
// Move to next block if complete
|
||||
if (!block.partial) {
|
||||
this.currentStreamingContentIndex++
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Tool Execution Flow
|
||||
|
||||
Tools follow a strict execution pattern:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async executeToolWithApproval(block: ToolBlock) {
|
||||
// 1. Check auto-approval settings
|
||||
if (this.shouldAutoApproveTool(block.name)) {
|
||||
await this.say("tool", message)
|
||||
this.consecutiveAutoApprovedRequestsCount++
|
||||
} else {
|
||||
// 2. Request user approval
|
||||
const didApprove = await askApproval("tool", message)
|
||||
if (!didApprove) {
|
||||
this.didRejectTool = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Execute tool
|
||||
const result = await this.executeTool(block)
|
||||
|
||||
// 4. Save checkpoint
|
||||
await this.saveCheckpoint()
|
||||
|
||||
// 5. Return result to API
|
||||
return result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling & Recovery
|
||||
|
||||
The system includes robust error handling:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async handleError(action: string, error: Error) {
|
||||
// 1. Check if task was abandoned
|
||||
if (this.abandoned) return
|
||||
|
||||
// 2. Format error message
|
||||
const errorString = `Error ${action}: ${error.message}`
|
||||
|
||||
// 3. Present error to user
|
||||
await this.say("error", errorString)
|
||||
|
||||
// 4. Add error to tool results
|
||||
pushToolResult(formatResponse.toolError(errorString))
|
||||
|
||||
// 5. Cleanup resources
|
||||
await this.diffViewProvider.revertChanges()
|
||||
await this.browserSession.closeBrowser()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### API Request & Token Management
|
||||
|
||||
The Task class handles API requests with built-in retry, streaming, and token management:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async *attemptApiRequest(previousApiReqIndex: number): ApiStream {
|
||||
// 1. Wait for MCP servers to connect
|
||||
await pWaitFor(() => this.controllerRef.deref()?.mcpHub?.isConnecting !== true)
|
||||
|
||||
// 2. Manage context window
|
||||
const previousRequest = this.clineMessages[previousApiReqIndex]
|
||||
if (previousRequest?.text) {
|
||||
const { tokensIn, tokensOut } = JSON.parse(previousRequest.text || "{}")
|
||||
const totalTokens = (tokensIn || 0) + (tokensOut || 0)
|
||||
|
||||
// Truncate conversation if approaching context limit
|
||||
if (totalTokens >= maxAllowedSize) {
|
||||
this.conversationHistoryDeletedRange = this.contextManager.getNextTruncationRange(
|
||||
this.apiConversationHistory,
|
||||
this.conversationHistoryDeletedRange,
|
||||
totalTokens / 2 > maxAllowedSize ? "quarter" : "half"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Handle streaming with automatic retry
|
||||
try {
|
||||
this.isWaitingForFirstChunk = true
|
||||
const firstChunk = await iterator.next()
|
||||
yield firstChunk.value
|
||||
this.isWaitingForFirstChunk = false
|
||||
|
||||
// Stream remaining chunks
|
||||
yield* iterator
|
||||
} catch (error) {
|
||||
// 4. Error handling with retry
|
||||
if (isOpenRouter && !this.didAutomaticallyRetryFailedApiRequest) {
|
||||
await setTimeoutPromise(1000)
|
||||
this.didAutomaticallyRetryFailedApiRequest = true
|
||||
yield* this.attemptApiRequest(previousApiReqIndex)
|
||||
return
|
||||
}
|
||||
|
||||
// 5. Ask user to retry if automatic retry failed
|
||||
const { response } = await this.ask(
|
||||
"api_req_failed",
|
||||
this.formatErrorWithStatusCode(error)
|
||||
)
|
||||
if (response === "yesButtonClicked") {
|
||||
await this.say("api_req_retried")
|
||||
yield* this.attemptApiRequest(previousApiReqIndex)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Key features:
|
||||
|
||||
1. **Context Window Management**
|
||||
- Tracks token usage across requests
|
||||
- Automatically truncates conversation when needed
|
||||
- Preserves important context while freeing space
|
||||
- Handles different model context sizes
|
||||
|
||||
2. **Streaming Architecture**
|
||||
- Real-time chunk processing
|
||||
- Partial content handling
|
||||
- Race condition prevention
|
||||
- Error recovery during streaming
|
||||
|
||||
3. **Error Handling**
|
||||
- Automatic retry for transient failures
|
||||
- User-prompted retry for persistent issues
|
||||
- Detailed error reporting
|
||||
- State cleanup on failure
|
||||
|
||||
4. **Token Tracking**
|
||||
- Per-request token counting
|
||||
- Cumulative usage tracking
|
||||
- Cost calculation
|
||||
- Cache hit monitoring
|
||||
|
||||
### Context Management System
|
||||
|
||||
The Context Management System handles conversation history truncation to prevent context window overflow errors. Implemented in the `ContextManager` class, it ensures long-running conversations remain within model context limits while preserving critical context.
|
||||
|
||||
Key features:
|
||||
|
||||
1. **Model-Aware Sizing**: Dynamically adjusts based on different model context windows (64K for DeepSeek, 128K for most models, 200K for Claude).
|
||||
|
||||
2. **Proactive Truncation**: Monitors token usage and preemptively truncates conversations when approaching limits, maintaining buffers of 27K-40K tokens depending on the model.
|
||||
|
||||
3. **Intelligent Preservation**: Always preserves the original task message and maintains the user-assistant conversation structure when truncating.
|
||||
|
||||
4. **Adaptive Strategies**: Uses different truncation strategies based on context pressure - removing half of the conversation for moderate pressure or three-quarters for severe pressure.
|
||||
|
||||
5. **Error Recovery**: Includes specialized detection for context window errors from different providers with automatic retry and more aggressive truncation when needed.
|
||||
|
||||
### Task State & Resumption
|
||||
|
||||
The Task class provides robust task state management and resumption capabilities:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async resumeTaskFromHistory() {
|
||||
// 1. Load saved state
|
||||
this.clineMessages = await getSavedClineMessages(this.getContext(), this.taskId)
|
||||
this.apiConversationHistory = await getSavedApiConversationHistory(this.getContext(), this.taskId)
|
||||
|
||||
// 2. Handle interrupted tool executions
|
||||
const lastMessage = this.apiConversationHistory[this.apiConversationHistory.length - 1]
|
||||
if (lastMessage.role === "assistant") {
|
||||
const toolUseBlocks = content.filter(block => block.type === "tool_use")
|
||||
if (toolUseBlocks.length > 0) {
|
||||
// Add interrupted tool responses
|
||||
const toolResponses = toolUseBlocks.map(block => ({
|
||||
type: "tool_result",
|
||||
tool_use_id: block.id,
|
||||
content: "Task was interrupted before this tool call could be completed."
|
||||
}))
|
||||
modifiedOldUserContent = [...toolResponses]
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Notify about interruption
|
||||
const agoText = this.getTimeAgoText(lastMessage?.ts)
|
||||
newUserContent.push({
|
||||
type: "text",
|
||||
text: `[TASK RESUMPTION] This task was interrupted ${agoText}. It may or may not be complete, so please reassess the task context.`
|
||||
})
|
||||
|
||||
// 4. Resume task execution
|
||||
await this.initiateTaskLoop(newUserContent, false)
|
||||
}
|
||||
|
||||
private async saveTaskState() {
|
||||
// Save conversation history
|
||||
await saveApiConversationHistory(this.getContext(), this.taskId, this.apiConversationHistory)
|
||||
await saveClineMessages(this.getContext(), this.taskId, this.clineMessages)
|
||||
|
||||
// Create checkpoint
|
||||
const commitHash = await this.checkpointTracker?.commit()
|
||||
|
||||
// Update task history
|
||||
await this.controllerRef.deref()?.updateTaskHistory({
|
||||
id: this.taskId,
|
||||
ts: lastMessage.ts,
|
||||
task: taskMessage.text,
|
||||
// ... other metadata
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Key aspects of task state management:
|
||||
|
||||
1. **Task Persistence**
|
||||
- Each task has a unique ID and dedicated storage directory
|
||||
- Conversation history is saved after each message
|
||||
- File changes are tracked through Git-based checkpoints
|
||||
- Terminal output and browser state are preserved
|
||||
|
||||
2. **State Recovery**
|
||||
- Tasks can be resumed from any point
|
||||
- Interrupted tool executions are handled gracefully
|
||||
- File changes can be restored from checkpoints
|
||||
- Context is preserved across VSCode sessions
|
||||
|
||||
3. **Workspace Synchronization**
|
||||
- File changes are tracked through Git
|
||||
- Checkpoints are created after tool executions
|
||||
- State can be restored to any checkpoint
|
||||
- Changes can be compared between checkpoints
|
||||
|
||||
4. **Error Recovery**
|
||||
- Failed API requests can be retried
|
||||
- Interrupted tool executions are marked
|
||||
- Resources are cleaned up properly
|
||||
- User is notified of state changes
|
||||
|
||||
## Plan/Act Mode System
|
||||
|
||||
Cline implements a dual-mode system that separates planning from execution:
|
||||
|
||||
### Mode Architecture
|
||||
|
||||
The Plan/Act mode system consists of:
|
||||
|
||||
1. **Mode State**: Stored in `chatSettings.mode` in the Controller's state
|
||||
2. **Mode Switching**: Handled by `togglePlanActModeWithChatSettings` in the Controller
|
||||
3. **Mode-specific Models**: Optional configuration to use different models for each mode
|
||||
4. **Mode-specific Prompting**: Different system prompts for planning vs. execution
|
||||
|
||||
### Mode Switching Process
|
||||
|
||||
When switching between modes:
|
||||
|
||||
1. The current model configuration is saved to mode-specific state
|
||||
2. The previous mode's model configuration is restored
|
||||
3. The Task instance is updated with the new mode
|
||||
4. The webview is notified of the mode change
|
||||
5. Telemetry events are captured for analytics
|
||||
|
||||
### Plan Mode
|
||||
|
||||
Plan mode is designed for:
|
||||
- Information gathering and context building
|
||||
- Asking clarifying questions
|
||||
- Creating detailed execution plans
|
||||
- Discussing approaches with the user
|
||||
|
||||
In Plan mode, the AI uses the `plan_mode_respond` tool to engage in conversational planning without executing actions.
|
||||
|
||||
### Act Mode
|
||||
|
||||
Act mode is designed for:
|
||||
- Executing the planned actions
|
||||
- Using tools to modify files, run commands, etc.
|
||||
- Implementing the solution
|
||||
- Providing results and completion feedback
|
||||
|
||||
In Act mode, the AI has access to all tools except `plan_mode_respond` and focuses on implementation rather than discussion.
|
||||
|
||||
## Data Flow & State Management
|
||||
|
||||
### Core Extension Role
|
||||
|
||||
The Controller acts as the single source of truth for all persistent state. It:
|
||||
- Manages VSCode global state and secrets storage
|
||||
- Coordinates state updates between components
|
||||
- Ensures state consistency across webview reloads
|
||||
- Handles task-specific state persistence
|
||||
- Manages checkpoint creation and restoration
|
||||
|
||||
### Terminal Management
|
||||
|
||||
The Task class manages terminal instances and command execution:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async executeCommandTool(command: string): Promise<[boolean, ToolResponse]> {
|
||||
// 1. Get or create terminal
|
||||
const terminalInfo = await this.terminalManager.getOrCreateTerminal(cwd)
|
||||
terminalInfo.terminal.show()
|
||||
|
||||
// 2. Execute command with output streaming
|
||||
const process = this.terminalManager.runCommand(terminalInfo, command)
|
||||
|
||||
// 3. Handle real-time output
|
||||
let result = ""
|
||||
process.on("line", (line) => {
|
||||
result += line + "\n"
|
||||
if (!didContinue) {
|
||||
sendCommandOutput(line)
|
||||
} else {
|
||||
this.say("command_output", line)
|
||||
}
|
||||
})
|
||||
|
||||
// 4. Wait for completion or user feedback
|
||||
let completed = false
|
||||
process.once("completed", () => {
|
||||
completed = true
|
||||
})
|
||||
|
||||
await process
|
||||
|
||||
// 5. Return result
|
||||
if (completed) {
|
||||
return [false, `Command executed.\n${result}`]
|
||||
} else {
|
||||
return [
|
||||
false,
|
||||
`Command is still running in the user's terminal.\n${result}\n\nYou will be updated on the terminal status and new output in the future.`
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Key features:
|
||||
1. **Terminal Instance Management**
|
||||
- Multiple terminal support
|
||||
- Terminal state tracking (busy/inactive)
|
||||
- Process cooldown monitoring
|
||||
- Output history per terminal
|
||||
|
||||
2. **Command Execution**
|
||||
- Real-time output streaming
|
||||
- User feedback handling
|
||||
- Process state monitoring
|
||||
- Error recovery
|
||||
|
||||
### Browser Session Management
|
||||
|
||||
The Task class handles browser automation through Puppeteer:
|
||||
|
||||
```typescript
|
||||
class Task {
|
||||
async executeBrowserAction(action: BrowserAction): Promise<BrowserActionResult> {
|
||||
switch (action) {
|
||||
case "launch":
|
||||
// 1. Launch browser with fixed resolution
|
||||
await this.browserSession.launchBrowser()
|
||||
return await this.browserSession.navigateToUrl(url)
|
||||
|
||||
case "click":
|
||||
// 2. Handle click actions with coordinates
|
||||
return await this.browserSession.click(coordinate)
|
||||
|
||||
case "type":
|
||||
// 3. Handle keyboard input
|
||||
return await this.browserSession.type(text)
|
||||
|
||||
case "close":
|
||||
// 4. Clean up resources
|
||||
return await this.browserSession.closeBrowser()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Key aspects:
|
||||
1. **Browser Control**
|
||||
- Fixed 900x600 resolution window
|
||||
- Single instance per task lifecycle
|
||||
- Automatic cleanup on task completion
|
||||
- Console log capture
|
||||
|
||||
2. **Interaction Handling**
|
||||
- Coordinate-based clicking
|
||||
- Keyboard input simulation
|
||||
- Screenshot capture
|
||||
- Error recovery
|
||||
|
||||
## MCP (Model Context Protocol) Integration
|
||||
|
||||
### MCP Architecture
|
||||
|
||||
The MCP system consists of:
|
||||
|
||||
1. **McpHub Class**: Central manager in `src/services/mcp/McpHub.ts`
|
||||
2. **MCP Connections**: Manages connections to external MCP servers
|
||||
3. **MCP Settings**: Configuration stored in a JSON file
|
||||
4. **MCP Marketplace**: Online catalog of available MCP servers
|
||||
5. **MCP Tools & Resources**: Capabilities exposed by connected servers
|
||||
|
||||
The McpHub class:
|
||||
- Manages the lifecycle of MCP server connections
|
||||
- Handles server configuration through a settings file
|
||||
- Provides methods for calling tools and accessing resources
|
||||
- Implements auto-approval settings for MCP tools
|
||||
- Monitors server health and handles reconnection
|
||||
|
||||
### MCP Server Types
|
||||
|
||||
Cline supports two types of MCP server connections:
|
||||
- **Stdio**: Command-line based servers that communicate via standard I/O
|
||||
- **SSE**: HTTP-based servers that communicate via Server-Sent Events
|
||||
|
||||
### MCP Server Management
|
||||
|
||||
The McpHub class provides methods for:
|
||||
- Discovering and connecting to MCP servers
|
||||
- Monitoring server health and status
|
||||
- Restarting servers when needed
|
||||
- Managing server configurations
|
||||
- Setting timeouts and auto-approval rules
|
||||
|
||||
### MCP Tool Integration
|
||||
|
||||
MCP tools are integrated into the Task execution system:
|
||||
- Tools are discovered and registered at connection time
|
||||
- The Task class can call MCP tools through the McpHub
|
||||
- Tool results are streamed back to the AI
|
||||
- Auto-approval settings can be configured per tool
|
||||
|
||||
### MCP Marketplace
|
||||
|
||||
The MCP Marketplace provides:
|
||||
- A catalog of available MCP servers
|
||||
- One-click installation
|
||||
- README previews
|
||||
- Server status monitoring
|
||||
|
||||
The Controller class manages MCP servers through the McpHub service:
|
||||
|
||||
```typescript
|
||||
class Controller {
|
||||
mcpHub?: McpHub
|
||||
|
||||
constructor(context: vscode.ExtensionContext, webviewProvider: WebviewProvider) {
|
||||
this.mcpHub = new McpHub(this)
|
||||
}
|
||||
|
||||
async downloadMcp(mcpId: string) {
|
||||
// Fetch server details from marketplace
|
||||
const response = await axios.post<McpDownloadResponse>(
|
||||
"https://api.cline.bot/v1/mcp/download",
|
||||
{ mcpId },
|
||||
{
|
||||
headers: { "Content-Type": "application/json" },
|
||||
timeout: 10000,
|
||||
}
|
||||
)
|
||||
|
||||
// Create task with context from README
|
||||
const task = `Set up the MCP server from ${mcpDetails.githubUrl}...`
|
||||
|
||||
// Initialize task and show chat view
|
||||
await this.initClineWithTask(task)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
This guide provides a comprehensive overview of the Cline extension architecture, with special focus on state management, data persistence, and code organization. Following these patterns ensures robust feature implementation with proper state handling across the extension's components.
|
||||
|
||||
Remember:
|
||||
- Always persist important state in the extension
|
||||
- The core extension follows a WebviewProvider -> Controller -> Task flow
|
||||
- Use proper typing for all state and messages
|
||||
- Handle errors and edge cases
|
||||
- Test state persistence across webview reloads
|
||||
- Follow the established patterns for consistency
|
||||
- Place new code in appropriate directories
|
||||
- Maintain clear separation of concerns
|
||||
- Install dependencies in correct package.json
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions to the Cline extension are welcome! Please follow these guidelines:
|
||||
|
||||
When adding new tools or API providers, follow the existing patterns in the `src/integrations/` and `src/api/providers/` directories, respectively. Ensure that your code is well-documented and includes appropriate error handling.
|
||||
|
||||
The `.clineignore` file allows users to specify files and directories that Cline should not access. When implementing new features, respect the `.clineignore` rules and ensure that your code does not attempt to read or modify ignored files.
|
||||
@@ -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
|
||||
|
||||
Here’s 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,549 +0,0 @@
|
||||
The goal of this workflow is to take a changeset for a release of Cline, an autonomous coding agent extension that plugs right into your IDE, and write the updated announcement component, and the updated changelog.
|
||||
|
||||
|
||||
For reference, here are some examples of how we converted previous changesets to announcement components / changelogs.
|
||||
|
||||
|
||||
- 3.14
|
||||
<changeset>
|
||||
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
|
||||
|
||||
Releases
|
||||
claude-dev@3.14.0
|
||||
Minor Changes
|
||||
77c9863: create clinerules folder if its currently a file and creating new rule
|
||||
0ffb7dd: disabling shift hint for now & improving tooltip behavior
|
||||
79b76fd: Add support for custom model ID in AWS Bedrock provider, enabling use of Application Inference Profile.
|
||||
eb6e481: Full support for LaTeX rendering
|
||||
df37f29: Add support for custom API request timeout. Previously, timeouts were hardcoded to 30 seconds for providers like Ollama or 15 seconds for OpenRouter and Cline. Now users can set a custom timeout value in milliseconds through the settings interface.
|
||||
e4d26be: allow cursorrules and windsurfrules
|
||||
c5de50f: Fix Handle @withRetry() SyntaxError when running extension locally issue
|
||||
61d2f42: enabled pricing calculation for gemini and vertex + more robust caching & cache tracking for gemini & vertex
|
||||
aed152b: add truncation notice when truncating manually
|
||||
2fe2405: Migrate Cline Tools Section to new docs
|
||||
19cc8bc: Add a timeout setting for the terminal connection, allowing users to adjust this if they are having timeout issues
|
||||
03d4410: Added copy button to code blocks.
|
||||
c78fe23: addressed race condition in terminal command usage
|
||||
91e222f: add checkpoints after more messages
|
||||
14230e7: add newrule slash command
|
||||
1c7d33a: Add remote config with posthog allowing for disabling new features until they're reading, making for a better developer experience.
|
||||
4196c14: add cache ui for open router and cline provider
|
||||
d97424f: showing expanded task by default
|
||||
5294e78: Refactor to not pass a message for showing the MCP View from the servers modal
|
||||
70cc437: Fix Windows path issue: Correct handling of import.meta.url to avoid leading slash in pathname
|
||||
4b697d8: Migrate the addRemoteServer to protobus
|
||||
Patch Changes
|
||||
c63d9a1: updated drag and drop text to say "drop" instead of "drag"
|
||||
459adf0: Add markdown copy to chat
|
||||
74ec823: Minor UX improvement to drag and drop ux
|
||||
b0961f4: Remove linear pull request action
|
||||
e9ce384: searchCommits protobus migration
|
||||
5802b68: createRuleFile protobus migration
|
||||
df7f9fc: Add dependsOn to more blocks in the tasks.json
|
||||
41ae732: Fix for git commit mentions in repos with no git commits
|
||||
7e78445: Adding args to allow Cursor to open workspaces (for checkpoint testing/development)
|
||||
bdfda6f: feat(bedrock): Introduce Amazon Nova Premier
|
||||
65243ad: Introduce UI library for future UI development
|
||||
4565e06: checkIsImageURL migrated to protobus
|
||||
5a8e9d8: protobus migration for openImage
|
||||
deeda6e: Lowering Gemini cache TTL time
|
||||
db0b022: Adding UI to show openrouter balance next to provider
|
||||
4650ffa: deleteRuleFile protobus migration
|
||||
d4bd755: fix cost calculation
|
||||
</changeset>
|
||||
|
||||
<changelog>
|
||||
## [3.14.0]
|
||||
|
||||
- Add UI to show openrouter balance next to provider
|
||||
- Add support for custom model ID in AWS Bedrock provider, enabling use of Application Inference Profile (Thanks @clicube!)
|
||||
- Add more robust caching & cache tracking for gemini & vertex providers
|
||||
- Add support for LaTeX rendering
|
||||
- Add support for custom API request timeout. Timeouts were 15-30s, but can now be configured via settings for OpenRouter/Cline & Ollama (Thanks @WingsDrafterwork!)
|
||||
- Add truncation notice when truncating manually
|
||||
- Add a timeout setting for the terminal connection, allowing users to set a time to wait for terminal startup
|
||||
- Add copy button to code blocks
|
||||
- Add copy button to markdown blocks (Thanks @weshoke!)
|
||||
- Add checkpoints to more messages
|
||||
- Add slash command to create a new rules file (/newrule)
|
||||
- Add cache ui for open router and cline provider
|
||||
- Add Amazon Nova Premier model to Bedrock (Thanks @watany!)
|
||||
- Add support for cursorrules and windsurfrules
|
||||
- Add support for batch history deletion (Thanks @danix800!)
|
||||
- Improve Drag & Drop experience
|
||||
- Create clinerules folder creating new rule if it's needed
|
||||
- Enable pricing calculation for gemini and vertex providers
|
||||
- Refactor message handling to not show the MCP View of the server modal
|
||||
- Migrate the addRemoteServer to protobus (Thanks @DaveFres!)
|
||||
- Update task header to be expanded by default
|
||||
- Update Gemini cache TTL time to 15 minutes
|
||||
- Fix race condition in terminal command usage
|
||||
- Fix to correctly handle `import.meta.url`, avoiding leading slash in pathname for Windows (Thanks @DaveFres!)
|
||||
- Fix @withRetry() decoration syntax error when running extension locally (Thanks @DaveFres!)
|
||||
- Fix for git commit mentions in repos with no git commits
|
||||
- Fix cost calculation (Thanks @BarreiroT!)
|
||||
</changelog>
|
||||
|
||||
|
||||
<announcement-component>
|
||||
const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
|
||||
const minorVersion = version.split(".").slice(0, 2).join(".") // 2.0.0 -> 2.0
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<VSCodeButton appearance="icon" onClick={hideAnnouncement} style={closeIconStyle}>
|
||||
<span className="codicon codicon-close"></span>
|
||||
</VSCodeButton>
|
||||
<h3 style={h3TitleStyle}>
|
||||
🎉{" "}New in v{minorVersion}
|
||||
</h3>
|
||||
<ul style={ulStyle}>
|
||||
<li>
|
||||
<b>Gemini prompt caching:</b> Gemini and Vertex providers now support prompt caching and price tracking for
|
||||
Gemini models.
|
||||
</li>
|
||||
<li>
|
||||
<b>Copy Buttons:</b> Buttons were added to Markdown and Code blocks that allow you to copy their contents
|
||||
easily.
|
||||
</li>
|
||||
<li>
|
||||
<b>/newrule command:</b> New slash command to have cline write your .clinerules for you based on your
|
||||
workflow.
|
||||
</li>
|
||||
<li>
|
||||
<b>Drag and drop improvements:</b> Don't forget to hold shift while dragging files!
|
||||
</li>
|
||||
<li>Added more checkpoints across the task, allowing you to restore from more than just file changes.</li>
|
||||
<li>Added support for rendering LaTeX in message responses. (Try asking Cline to show the quadratic formula)</li>
|
||||
</ul>
|
||||
<Accordion isCompact className="pl-0">
|
||||
<AccordionItem
|
||||
key="1"
|
||||
aria-label="Previous Updates"
|
||||
title="Previous Updates:"
|
||||
classNames={{
|
||||
trigger: "bg-transparent border-0 pl-0 pb-0 w-fit",
|
||||
title: "font-bold text-[var(--vscode-foreground)]",
|
||||
indicator:
|
||||
"text-[var(--vscode-foreground)] mb-0.5 -rotate-180 data-[open=true]:-rotate-90 rtl:rotate-0 rtl:data-[open=true]:-rotate-90",
|
||||
}}>
|
||||
<ul style={ulStyle}>
|
||||
<li>
|
||||
<b>Global Cline Rules:</b> store multiple rules files in Documents/Cline/Rules to share between
|
||||
projects.
|
||||
</li>
|
||||
<li>
|
||||
<b>Cline Rules Popup:</b> New button in the chat area to view workspace and global cline rules files
|
||||
to plug and play specific rules for the task
|
||||
</li>
|
||||
<li>
|
||||
<b>Slash Commands:</b> Type <code>/</code> in chat to see the list of quick actions, like starting a
|
||||
new task (more coming soon!)
|
||||
</li>
|
||||
<li>
|
||||
<b>Edit Messages:</b> You can now edit a message you sent previously by clicking on it. Optionally
|
||||
restore your project when the message was sent!
|
||||
</li>
|
||||
</ul>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
|
||||
{/*
|
||||
// Leave this here for an example of how to structure the announcement
|
||||
<ul style={{ margin: "0 0 8px", paddingLeft: "12px" }}>
|
||||
<li>
|
||||
OpenRouter now supports prompt caching! They also have much higher rate limits than other providers,
|
||||
so I recommend trying them out.
|
||||
<br />
|
||||
{!apiConfiguration?.openRouterApiKey && (
|
||||
<VSCodeButtonLink
|
||||
href={getOpenRouterAuthUrl(vscodeUriScheme)}
|
||||
style={{
|
||||
transform: "scale(0.85)",
|
||||
transformOrigin: "left center",
|
||||
margin: "4px -30px 2px 0",
|
||||
}}>
|
||||
Get OpenRouter API Key
|
||||
</VSCodeButtonLink>
|
||||
)}
|
||||
{apiConfiguration?.openRouterApiKey && apiConfiguration?.apiProvider !== "openrouter" && (
|
||||
<VSCodeButton
|
||||
onClick={() => {
|
||||
vscode.postMessage({
|
||||
type: "apiConfiguration",
|
||||
apiConfiguration: { ...apiConfiguration, apiProvider: "openrouter" },
|
||||
})
|
||||
}}
|
||||
style={{
|
||||
transform: "scale(0.85)",
|
||||
transformOrigin: "left center",
|
||||
margin: "4px -30px 2px 0",
|
||||
}}>
|
||||
Switch to OpenRouter
|
||||
</VSCodeButton>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<b>Edit Cline's changes before accepting!</b> When he creates or edits a file, you can modify his
|
||||
changes directly in the right side of the diff view (+ hover over the 'Revert Block' arrow button in
|
||||
the center to undo "<code>{"// rest of code here"}</code>" shenanigans)
|
||||
</li>
|
||||
<li>
|
||||
New <code>search_files</code> tool that lets Cline perform regex searches in your project, letting
|
||||
him refactor code, address TODOs and FIXMEs, remove dead code, and more!
|
||||
</li>
|
||||
<li>
|
||||
When Cline runs commands, you can now type directly in the terminal (+ support for Python
|
||||
environments)
|
||||
</li>
|
||||
</ul>*/}
|
||||
<div style={hrStyle} />
|
||||
<p style={linkContainerStyle}>
|
||||
Join us on{" "}
|
||||
<VSCodeLink style={linkStyle} href="https://x.com/cline">
|
||||
X,
|
||||
</VSCodeLink>{" "}
|
||||
<VSCodeLink style={linkStyle} href="https://discord.gg/cline">
|
||||
discord,
|
||||
</VSCodeLink>{" "}
|
||||
or{" "}
|
||||
<VSCodeLink style={linkStyle} href="https://www.reddit.com/r/cline/">
|
||||
r/cline
|
||||
</VSCodeLink>
|
||||
for more updates!
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</announcement-component>
|
||||
|
||||
- 3.13
|
||||
|
||||
<changeset>
|
||||
Minor Changes
|
||||
2964388: Added copy button to MermaidBlock component
|
||||
75143a7: Add the ability to fetch from global cline rules files
|
||||
Patch Changes
|
||||
a0252e7: convert inline style to tailwind css of file SettingsView.tsx
|
||||
ab59bd9: Add stream options back to xai provider
|
||||
7276f50: Icons to indicate an action is occuring outside of the users workspace
|
||||
0b19ba6: update to NEW model
|
||||
</changeset>
|
||||
|
||||
<changelog>
|
||||
## [3.13.0]
|
||||
|
||||
- Add Cline rules popover under the chat field, allowing you to easily add, enable & disable workspace level or global rule files
|
||||
- Add new slash command menu letting you type “/“ to do quick actions like creating new tasks
|
||||
- Add ability to edit past messages, with options to restore your workspace back to that point
|
||||
- Allow sending a message when selecting an option provided by the question or plan tool
|
||||
- Add command to jump to Cline's chat input
|
||||
- Add support for OpenAI o3 & 4o-mini (Thanks @PeterDaveHello and @arafatkatze!)
|
||||
- Add baseURL option for Google Gemini provider (Thanks @owengo and @olivierhub!)
|
||||
- Add support for Azure's DeepSeek model. (Thanks @yt3trees!)
|
||||
- Add ability for models that support it to receive image responses from MCP servers (Thanks @rikaaa0928!)
|
||||
- Improve search and replace diff editing by making it more flexible with models that fail to follow structured output instructions. (Thanks @chi-cat!)
|
||||
- Add detection of Ctrl+C termination in terminal, improving output reading issues
|
||||
- Fix issue where some commands with large output would cause UI to freeze
|
||||
- Fix token usage tracking issues with vertex provider (Thanks @mzsima!)
|
||||
- Fix issue with xAI reasoning content not being parsed (Thanks @mrubens!)
|
||||
</changelog>
|
||||
|
||||
<announcement-component>
|
||||
const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
|
||||
const minorVersion = version.split(".").slice(0, 2).join(".") // 2.0.0 -> 2.0
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<VSCodeButton appearance="icon" onClick={hideAnnouncement} style={closeIconStyle}>
|
||||
<span className="codicon codicon-close"></span>
|
||||
</VSCodeButton>
|
||||
<h3 style={h3TitleStyle}>
|
||||
🎉{" "}New in v{minorVersion}
|
||||
</h3>
|
||||
<ul style={ulStyle}>
|
||||
<li>
|
||||
<b>Global Cline Rules:</b> store multiple rules files in Documents/Cline/Rules to share between projects.
|
||||
</li>
|
||||
<li>
|
||||
<b>Cline Rules Popup:</b> New button in the chat area to view workspace and global cline rules files to plug
|
||||
and play specific rules for the task
|
||||
</li>
|
||||
<li>
|
||||
<b>Slash Commands:</b> Type <code>/</code> in chat to see the list of quick actions, like starting a new task
|
||||
(more coming soon!)
|
||||
</li>
|
||||
<li>
|
||||
<b>Edit Messages:</b> You can now edit a message you sent previously by clicking on it. Optionally restore
|
||||
your project when the message was sent!
|
||||
</li>
|
||||
</ul>
|
||||
<h4 style={{ margin: "5px 0 5px" }}>Previous Updates:</h4>
|
||||
<ul style={ulStyle}>
|
||||
<li>
|
||||
<b>Model Favorites:</b> You can now mark your favorite models when using Cline & OpenRouter providers for
|
||||
quick access!
|
||||
</li>
|
||||
<li>
|
||||
<b>Faster Diff Editing:</b> Improved animation performance for large files, plus a new indicator in chat
|
||||
showing the number of edits Cline makes.
|
||||
</li>
|
||||
<li>
|
||||
<b>New Auto-Approve Options:</b> Turn off Cline's ability to read and edit files outside your workspace.
|
||||
</li>
|
||||
</ul>
|
||||
{/*
|
||||
// Leave this here for an example of how to structure the announcement
|
||||
<ul style={{ margin: "0 0 8px", paddingLeft: "12px" }}>
|
||||
<li>
|
||||
OpenRouter now supports prompt caching! They also have much higher rate limits than other providers,
|
||||
so I recommend trying them out.
|
||||
<br />
|
||||
{!apiConfiguration?.openRouterApiKey && (
|
||||
<VSCodeButtonLink
|
||||
href={getOpenRouterAuthUrl(vscodeUriScheme)}
|
||||
style={{
|
||||
transform: "scale(0.85)",
|
||||
transformOrigin: "left center",
|
||||
margin: "4px -30px 2px 0",
|
||||
}}>
|
||||
Get OpenRouter API Key
|
||||
</VSCodeButtonLink>
|
||||
)}
|
||||
{apiConfiguration?.openRouterApiKey && apiConfiguration?.apiProvider !== "openrouter" && (
|
||||
<VSCodeButton
|
||||
onClick={() => {
|
||||
vscode.postMessage({
|
||||
type: "apiConfiguration",
|
||||
apiConfiguration: { ...apiConfiguration, apiProvider: "openrouter" },
|
||||
})
|
||||
}}
|
||||
style={{
|
||||
transform: "scale(0.85)",
|
||||
transformOrigin: "left center",
|
||||
margin: "4px -30px 2px 0",
|
||||
}}>
|
||||
Switch to OpenRouter
|
||||
</VSCodeButton>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<b>Edit Cline's changes before accepting!</b> When he creates or edits a file, you can modify his
|
||||
changes directly in the right side of the diff view (+ hover over the 'Revert Block' arrow button in
|
||||
the center to undo "<code>{"// rest of code here"}</code>" shenanigans)
|
||||
</li>
|
||||
<li>
|
||||
New <code>search_files</code> tool that lets Cline perform regex searches in your project, letting
|
||||
him refactor code, address TODOs and FIXMEs, remove dead code, and more!
|
||||
</li>
|
||||
<li>
|
||||
When Cline runs commands, you can now type directly in the terminal (+ support for Python
|
||||
environments)
|
||||
</li>
|
||||
</ul>*/}
|
||||
<div style={hrStyle} />
|
||||
<p style={linkContainerStyle}>
|
||||
Join us on{" "}
|
||||
<VSCodeLink style={linkStyle} href="https://x.com/cline">
|
||||
X,
|
||||
</VSCodeLink>{" "}
|
||||
<VSCodeLink style={linkStyle} href="https://discord.gg/cline">
|
||||
discord,
|
||||
</VSCodeLink>{" "}
|
||||
or{" "}
|
||||
<VSCodeLink style={linkStyle} href="https://www.reddit.com/r/cline/">
|
||||
r/cline
|
||||
</VSCodeLink>
|
||||
for more updates!
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</announcement-component>
|
||||
|
||||
|
||||
We have a changeset PR that automatically generated as new unreleased PRs are merged into main, the PR is always called "Changeset version bump" and the author is github-actions.
|
||||
|
||||
The Changeset PR description looks something like this:
|
||||
|
||||
<changeset-pr-description>
|
||||
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
|
||||
|
||||
|
||||
# Releases
|
||||
## claude-dev@3.16.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- c6e8b04: Recent task list is now collapsible, allowing users to hide their recent tasks (e.g. when sharing their screen).
|
||||
- aabe4ae: Add detection for new users to display special components
|
||||
- 6c18d51: adds global endpoint for vertex ai users
|
||||
- 080ed7c: Add Tailwind CSS IntelliSense to the the recommended extensions list
|
||||
- 5147e28: new workflow feature
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- c0b3c69: fix eternal loading states when the last message is a checkpoint
|
||||
- 570ece3: selectImages protos migration
|
||||
- 8d8452e: askResponse protobus migration
|
||||
- cd1ff2a: Finishing the migration of Vscode Advanced settings to Settings Webview
|
||||
</changeset-pr-description>
|
||||
|
||||
The changeset pr is ALWAYS on the following branch: `changeset-release/main`.
|
||||
|
||||
I have the `gh` command line tool set up and authenticated, so you have everything you need.
|
||||
|
||||
The first step is to get the full diff from the changeset PR to look at the changes that were automatically made to the `CHANGELOG.md` file. By default it will automatically add a new section to the changelog.md file with the new version. The problem with the automatically generated section is that it just takes the text that the developers threw into their changeset files for each corresponding PR, and they can be pretty vague and bad. Additionally there's some stuff that is totally irrelevant for the end user, like minor refactoring changes. So I manually typically go in and update this section to be a proper changelog that will show up in our patchnotes. You can look at how the rest of the file is done because those are all good examples of us updating this to use good language for the end user. We usually put new features up top (and the most exciting flagship features at the very top), and then bug fixes/improvements at the bottom. Having some basic organization to the ordering of the bullet points by content is nice. But use common sense.
|
||||
|
||||
To handle this process effectively, do the following:
|
||||
|
||||
For each of the automatically generated bullet points in the Changelog.md, you should
|
||||
1. Take the commit hash at the start of the bullet point, and use the `gh` command line tool find the PR that it was associated with.
|
||||
2. Use the `gh` command to get the PR title/description/discussion to understand the context surrounding the PR.
|
||||
3. Use the `gh` command line tool to get the full PR diff to fully understand the changes made in the code.
|
||||
4. Synthesize that knowledge to determine (a) whether or not this change is relevant to end users and (b) what the text & ordering of the line should be.
|
||||
5. Update the `CHANGELOG.md` accordingly
|
||||
|
||||
Do this for every single item in the list from the autogenerated bullet points. We want to be diligent and have a full understanding of every feature so we can make the best changelog ever!
|
||||
|
||||
Here are some principles for good changelogs from keepchangelog.com, a handy guide:
|
||||
|
||||
<keepachangelog-pinciples-for-good-changelogs>
|
||||
### Guiding Principles
|
||||
- Changelogs are for humans, not machines.
|
||||
- There should be an entry for every single version.
|
||||
- The same types of changes should be grouped.
|
||||
- The latest version comes first.
|
||||
|
||||
### Bullet points in the changelog should follow these principles:
|
||||
- Types of changes
|
||||
- Added for new features.
|
||||
- Changed for changes in existing functionality.
|
||||
- Deprecated for soon-to-be removed features.
|
||||
- Removed for now removed features.
|
||||
- Fixed for any bug fixes.
|
||||
- Security in case of vulnerabilities.
|
||||
</keepachangelog-pinciples-for-good-changelogs>
|
||||
|
||||
Lastly, when developers make a PR, they typically make a changeset. And they have 3 options when making the changeset:
|
||||
|
||||
1. Patch
|
||||
2. Minor
|
||||
3. Major
|
||||
|
||||
Sometimes they label something as minor when really it should just be a patch. Or vice versa. Because of this, the automatic version bump may be incorrect. So when starting out this workflow, you should use the <ask_followup_question> tool to confirm with me whether or not this should be a patch bump (show the old version number and what the proposed new version number would be) or a minor bump. Part of the release process is making sure the version in package.json that is automatically changed actually corresponds with what we decided the bump should actually be based on the features. ALL these modifications happen in the `changeset-release/main` branch btw.
|
||||
|
||||
<important_note>
|
||||
Before doing any of this, make sure you check out the `changeset-release/main` and pull the most recent up to date changes. Then perform all this work in that branch.
|
||||
|
||||
New announcement banners should ONLY be made for minor version bumps or higher. That's another reason why double checking if the changelog warrants the bump is important.
|
||||
|
||||
Also, SUPER important: For any external contributors that aren't part of the cline github organization, we always want to add a (Thanks @username!) at the end of the changelog to attribute them properly. We're an open source project and it's ethical to do this.
|
||||
</important_note>
|
||||
|
||||
Once the changelog looks good, and the version number looks good, we gotta double check that the version number in the changelog has the brackets around it. And as a final step, double check the package.json version number matches the latest number in the changelog. And as the ultimate final step we run `npm run install:all` to make sure the package version number permiates through the lock file.
|
||||
|
||||
|
||||
<detailed_sequence_of_steps>
|
||||
# Cline Release Process - Detailed Sequence of Steps
|
||||
|
||||
## Before Starting
|
||||
1. First, examine the changeset PR without checking it out:
|
||||
```bash
|
||||
gh pr view changeset-release/main
|
||||
```
|
||||
|
||||
2. View the PR diff to see the auto-generated CHANGELOG.md changes:
|
||||
```bash
|
||||
gh pr diff changeset-release/main > changeset-diff.txt
|
||||
cat changeset-diff.txt | grep -A 50 "CHANGELOG.md"
|
||||
```
|
||||
|
||||
## Initial Setup
|
||||
3. Once you're ready to start, checkout and update the changeset release branch:
|
||||
```bash
|
||||
git checkout changeset-release/main
|
||||
git pull origin changeset-release/main
|
||||
```
|
||||
|
||||
## Analyzing Each Change
|
||||
4. For each commit hash in the auto-generated changelog entries:
|
||||
|
||||
a. Find the PR number associated with a commit hash:
|
||||
```bash
|
||||
gh pr list --search "<commit-hash>" --state merged
|
||||
```
|
||||
|
||||
b. Get PR details for better context:
|
||||
```bash
|
||||
gh pr view <PR-number>
|
||||
```
|
||||
|
||||
c. Check if the contributor is external to determine if attribution is needed:
|
||||
```bash
|
||||
# Extract username from PR
|
||||
USERNAME=$(gh pr view <PR-number> --json author --jq .author.login)
|
||||
|
||||
# Check if user is a member of the Cline organization
|
||||
# this command is a bit finnicky, but it 100% works.
|
||||
# if you see a `Error executing command: The command ran successfully, but we couldn't capture its output. Please proceed accordingly.` error, just retry it until you actually get the output
|
||||
# don't make any assumptions, just retry the command to actually get the output and determine if they're external or not.
|
||||
# no output means they are an external contributor, otherwise if there is output they are an internal contributor (part of our github org)
|
||||
gh api "orgs/cline/members" --jq "map(.login)" | grep -i "pashpashpash"
|
||||
```
|
||||
|
||||
d. View the full PR diff to understand code changes:
|
||||
```bash
|
||||
gh pr diff <PR-number> > pr-diff-<PR-number>.txt
|
||||
cat pr-diff-<PR-number>.txt
|
||||
```
|
||||
|
||||
## Updating the Changelog
|
||||
5. Based on PR analysis, update the CHANGELOG.md with user-friendly descriptions:
|
||||
- Use the `<replace_in_file>` tool to edit the CHANGELOG.md file
|
||||
- Group by feature type (Added, Changed, Fixed)
|
||||
- Put most exciting features at the top
|
||||
- Move bug fixes and small improvements to the bottom
|
||||
- Use clear, end-user focused language
|
||||
- For external contributors, add attribution at the end of the relevant entry: `(Thanks @username!)`
|
||||
|
||||
## Version Number Verification
|
||||
6. Confirm the version bump is appropriate:
|
||||
- Check package.json to verify the auto-generated version number:
|
||||
```bash
|
||||
cat package.json | grep "\"version\""
|
||||
```
|
||||
- If the feature set doesn't warrant a minor bump, use the `<replace_in_file>` tool to modify package.json
|
||||
|
||||
7. Ensure the version in CHANGELOG.md has brackets around it:
|
||||
```
|
||||
## [3.16.0]
|
||||
```
|
||||
|
||||
## Creating the Announcement (for minor/major versions only)
|
||||
8. If this is a minor version bump, create/update the announcement component:
|
||||
- Use the `<replace_in_file>` tool to edit the src/views/components/announcement.tsx file
|
||||
- Update the highlights based on key features
|
||||
- Move previous version highlights to the "Previous Updates" section
|
||||
- Use the previous announcement components as reference for structure
|
||||
|
||||
## Finalizing the Release
|
||||
9. Update dependencies with the new version number:
|
||||
```bash
|
||||
npm run install:all
|
||||
```
|
||||
|
||||
10. Commit your changes:
|
||||
```bash
|
||||
git add CHANGELOG.md package.json package-lock.json src/views/components/announcement.tsx
|
||||
git commit -m "Update CHANGELOG.md and announcement for version 3.16.0"
|
||||
```
|
||||
|
||||
11. Push your changes to the changeset branch:
|
||||
```bash
|
||||
git push origin changeset-release/main
|
||||
```
|
||||
|
||||
12. Check that your changes pushed successfully:
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
</detailed_sequence_of_steps>
|
||||
@@ -1,61 +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>
|
||||
|
||||
**Run the following command to get the latest changes (bash):**
|
||||
```bash
|
||||
B=$(for c in main master origin/main origin/master; do git rev-parse --verify -q "$c" >/dev/null && echo "$c" && break; done); B=${B:-HEAD}; r(){ git branch --show-current; printf "=== STATUS ===\n"; git status --porcelain | cat; printf "=== COMMIT MESSAGES ===\n"; git log "$B"..HEAD --oneline | cat; printf "=== CHANGED FILES ===\n"; git diff "$B" --name-only | cat; printf "=== FULL DIFF ===\n"; git diff "$B" | cat; }; L=$(r | wc -l); if [ "$L" -gt 500 ]; then r > cline-git-analysis.temp && echo "::OUTPUT_FILE=cline-git-analysis.temp"; else r; fi
|
||||
```
|
||||
|
||||
```powershell
|
||||
$B=$null;foreach($c in 'main','master','origin/main','origin/master'){git rev-parse --verify -q $c *> $null;if($LASTEXITCODE -eq 0){$B=$c;break}};if(-not $B){$B='HEAD'};function r([string]$b){git rev-parse --abbrev-ref HEAD; '=== STATUS ==='; git status --porcelain | cat; '=== COMMIT MESSAGES ==='; git log "$b"..HEAD --oneline | cat; '=== CHANGED FILES ==='; git diff "$b" --name-only | cat; '=== FULL DIFF ==='; git diff "$b" | cat};$out=r $B|Out-String;$lines=($out -split "`r?`n").Count;if($lines -gt 500){$out|Set-Content -NoNewline cline-git-analysis.temp; '::OUTPUT_FILE=cline-git-analysis.temp'}else{$out}
|
||||
```
|
||||
|
||||
## 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,354 +0,0 @@
|
||||
You have access to the `gh` terminal command. I already authenticated it for you. Please review it to use the PR that I asked you to review. You're already in the `cline` repo.
|
||||
|
||||
<detailed_sequence_of_steps>
|
||||
# GitHub PR Review Process - Detailed Sequence of Steps
|
||||
|
||||
## 1. Gather PR Information
|
||||
1. Get the PR title, description, and comments:
|
||||
```bash
|
||||
gh pr view <PR-number> --json title,body,comments
|
||||
```
|
||||
|
||||
2. Get the full diff of the PR:
|
||||
```bash
|
||||
gh pr diff <PR-number>
|
||||
```
|
||||
|
||||
## 2. Understand the Context
|
||||
1. Identify which files were modified in the PR:
|
||||
```bash
|
||||
gh pr view <PR-number> --json files
|
||||
```
|
||||
|
||||
2. Examine the original files in the main branch to understand the context:
|
||||
```xml
|
||||
<read_file>
|
||||
<path>path/to/file</path>
|
||||
</read_file>
|
||||
```
|
||||
|
||||
3. For specific sections of a file, you can use search_files:
|
||||
```xml
|
||||
<search_files>
|
||||
<path>path/to/directory</path>
|
||||
<regex>search term</regex>
|
||||
<file_pattern>*.ts</file_pattern>
|
||||
</search_files>
|
||||
```
|
||||
|
||||
## 3. Analyze the Changes
|
||||
1. For each modified file, understand:
|
||||
- What was changed
|
||||
- Why it was changed (based on PR description)
|
||||
- How it affects the codebase
|
||||
- Potential side effects
|
||||
|
||||
2. Look for:
|
||||
- Code quality issues
|
||||
- Potential bugs
|
||||
- Performance implications
|
||||
- Security concerns
|
||||
- Test coverage
|
||||
|
||||
## 4. Ask for User Confirmation
|
||||
1. Before making a decision, ask the user if you should approve the PR, providing your assessment and justification:
|
||||
```xml
|
||||
<ask_followup_question>
|
||||
<question>Based on my review of PR #<PR-number>, I recommend [approving/requesting changes]. Here's my justification:
|
||||
|
||||
[Detailed justification with key points about the PR quality, implementation, and any concerns]
|
||||
|
||||
Would you like me to proceed with this recommendation?</question>
|
||||
<options>["Yes, approve the PR", "Yes, request changes", "No, I'd like to discuss further"]</options>
|
||||
</ask_followup_question>
|
||||
```
|
||||
|
||||
## 5. Ask if User Wants a Comment Drafted
|
||||
1. After the user decides on approval/rejection, ask if they would like a comment drafted:
|
||||
```xml
|
||||
<ask_followup_question>
|
||||
<question>Would you like me to draft a comment for this PR that you can copy and paste?</question>
|
||||
<options>["Yes, please draft a comment", "No, I'll handle the comment myself"]</options>
|
||||
</ask_followup_question>
|
||||
```
|
||||
|
||||
2. If the user wants a comment drafted, provide a well-structured comment they can copy:
|
||||
```
|
||||
Thank you for this PR! Here's my assessment:
|
||||
|
||||
[Detailed assessment with key points about the PR quality, implementation, and any suggestions]
|
||||
|
||||
[Include specific feedback on code quality, functionality, and testing]
|
||||
```
|
||||
|
||||
## 6. Make a Decision
|
||||
1. Approve the PR if it meets quality standards:
|
||||
```bash
|
||||
# For single-line comments:
|
||||
gh pr review <PR-number> --approve --body "Your approval message"
|
||||
|
||||
# For multi-line comments with proper whitespace formatting:
|
||||
cat << EOF | gh pr review <PR-number> --approve --body-file -
|
||||
Thanks @username for this PR! The implementation looks good.
|
||||
|
||||
I particularly like how you've handled X and Y.
|
||||
|
||||
Great work!
|
||||
EOF
|
||||
```
|
||||
|
||||
2. Request changes if improvements are needed:
|
||||
```bash
|
||||
# For single-line comments:
|
||||
gh pr review <PR-number> --request-changes --body "Your feedback message"
|
||||
|
||||
# For multi-line comments with proper whitespace formatting:
|
||||
cat << EOF | gh pr review <PR-number> --request-changes --body-file -
|
||||
Thanks @username for this PR!
|
||||
|
||||
The implementation looks promising, but there are a few things to address:
|
||||
|
||||
1. Issue one
|
||||
2. Issue two
|
||||
|
||||
Please make these changes and we can merge this.
|
||||
EOF
|
||||
```
|
||||
|
||||
Note: The `cat << EOF | ... --body-file -` approach preserves all whitespace and formatting without requiring temporary files. The `-` parameter tells the command to read from standard input.
|
||||
</detailed_sequence_of_steps>
|
||||
|
||||
<example_review_process>
|
||||
# Example PR Review Process
|
||||
|
||||
Let's walk through a real example of reviewing PR #3627 which fixes the thinking mode calculation for Claude 3.7 models.
|
||||
|
||||
## Step 1: Gather PR Information
|
||||
|
||||
```bash
|
||||
# Get PR details
|
||||
gh pr view 3627 --json title,body,comments
|
||||
|
||||
# Get the full diff
|
||||
gh pr diff 3627
|
||||
```
|
||||
|
||||
## Step 2: Understand the Context
|
||||
|
||||
```xml
|
||||
# Examine the original files to understand what's being changed
|
||||
<read_file>
|
||||
<path>src/shared/api.ts</path>
|
||||
</read_file>
|
||||
|
||||
# Look at the ThinkingBudgetSlider component implementation
|
||||
<read_file>
|
||||
<path>webview-ui/src/components/settings/ThinkingBudgetSlider.tsx</path>
|
||||
</read_file>
|
||||
|
||||
# Check how thinking mode is currently handled in API providers
|
||||
<search_files>
|
||||
<path>src/api/providers</path>
|
||||
<regex>reasoningOn</regex>
|
||||
<file_pattern>*.ts</file_pattern>
|
||||
</search_files>
|
||||
```
|
||||
|
||||
## Step 3: Analyze the Changes
|
||||
|
||||
From the PR information and code examination, we can see that:
|
||||
|
||||
1. The PR fixes an issue with the thinking mode budget calculation for Claude 3.7 models
|
||||
2. Currently, the thinking budget is incorrectly calculated as 80% of maxTokens (8192), resulting in 6553 tokens
|
||||
3. Claude 3.7 actually supports a much larger thinking budget (up to 64000 tokens)
|
||||
4. The PR adds a `thinkingConfig` property with `maxBudget: 64000` to model definitions
|
||||
5. It updates API handlers to use this value when reasoning mode is enabled
|
||||
6. It enhances the slider component to calculate max values based on model-specific percentages
|
||||
7. Comprehensive tests were added to verify the calculations
|
||||
|
||||
## Step 4: Ask for User Confirmation
|
||||
|
||||
```xml
|
||||
<ask_followup_question>
|
||||
<question>Based on my review of PR #3627, I recommend approving this PR. Here's my justification:
|
||||
|
||||
1. The PR correctly fixes the thinking mode budget calculation for Claude 3.7 models
|
||||
2. It properly implements the thinkingConfig.maxBudget property (64000) for Claude 3.7 models
|
||||
3. It applies the appropriate percentage (50%) for the slider calculation
|
||||
4. The changes are well-tested with comprehensive unit tests
|
||||
5. The implementation is clean and follows the project's coding standards
|
||||
6. The PR includes helpful screenshots demonstrating the fix
|
||||
|
||||
Would you like me to proceed with approving this PR?</question>
|
||||
<options>["Yes, approve the PR", "No, I'd like to discuss further", "Let me review it myself first"]</options>
|
||||
</ask_followup_question>
|
||||
```
|
||||
|
||||
## Step 5: Ask if User Wants a Comment Drafted
|
||||
|
||||
```xml
|
||||
<ask_followup_question>
|
||||
<question>Would you like me to draft a comment for this PR that you can copy and paste?</question>
|
||||
<options>["Yes, please draft a comment", "No, I'll handle the comment myself"]</options>
|
||||
</ask_followup_question>
|
||||
```
|
||||
|
||||
## Step 6: Make a Decision
|
||||
|
||||
```bash
|
||||
# Option 1: Simple one-line comment
|
||||
gh pr review 3627 --approve --body "This PR looks good! It correctly fixes the thinking mode budget calculation for Claude 3.7 models."
|
||||
|
||||
# Option 2: Multi-line comment with proper whitespace formatting
|
||||
cat << EOF | gh pr review 3627 --approve --body-file -
|
||||
This PR looks good! It correctly fixes the thinking mode budget calculation for Claude 3.7 models.
|
||||
|
||||
I particularly like:
|
||||
1. The proper implementation of thinkingConfig.maxBudget property (64000)
|
||||
2. The appropriate percentage (50%) for the slider calculation
|
||||
3. The comprehensive unit tests
|
||||
4. The clean implementation that follows project coding standards
|
||||
|
||||
Great work!
|
||||
EOF
|
||||
```
|
||||
</example_review_process>
|
||||
|
||||
<common_gh_commands>
|
||||
# Common GitHub CLI Commands for PR Review
|
||||
|
||||
## Basic PR Commands
|
||||
```bash
|
||||
# Get current PR number
|
||||
gh pr view --json number -q .number
|
||||
|
||||
# List open PRs
|
||||
gh pr list
|
||||
|
||||
# View a specific PR
|
||||
gh pr view <PR-number>
|
||||
|
||||
# View PR with specific fields
|
||||
gh pr view <PR-number> --json title,body,comments,files,commits
|
||||
|
||||
# Check PR status
|
||||
gh pr status
|
||||
```
|
||||
|
||||
## Diff and File Commands
|
||||
```bash
|
||||
# Get the full diff of a PR
|
||||
gh pr diff <PR-number>
|
||||
|
||||
# List files changed in a PR
|
||||
gh pr view <PR-number> --json files
|
||||
|
||||
# Check out a PR locally
|
||||
gh pr checkout <PR-number>
|
||||
```
|
||||
|
||||
## Review Commands
|
||||
```bash
|
||||
# Approve a PR (single-line comment)
|
||||
gh pr review <PR-number> --approve --body "Your approval message"
|
||||
|
||||
# Approve a PR (multi-line comment with proper whitespace)
|
||||
cat << EOF | gh pr review <PR-number> --approve --body-file -
|
||||
Your multi-line
|
||||
approval message with
|
||||
|
||||
proper whitespace formatting
|
||||
EOF
|
||||
|
||||
# Request changes on a PR (single-line comment)
|
||||
gh pr review <PR-number> --request-changes --body "Your feedback message"
|
||||
|
||||
# Request changes on a PR (multi-line comment with proper whitespace)
|
||||
cat << EOF | gh pr review <PR-number> --request-changes --body-file -
|
||||
Your multi-line
|
||||
change request with
|
||||
|
||||
proper whitespace formatting
|
||||
EOF
|
||||
|
||||
# Add a comment review (without approval/rejection)
|
||||
gh pr review <PR-number> --comment --body "Your comment message"
|
||||
|
||||
# Add a comment review with proper whitespace
|
||||
cat << EOF | gh pr review <PR-number> --comment --body-file -
|
||||
Your multi-line
|
||||
comment with
|
||||
|
||||
proper whitespace formatting
|
||||
EOF
|
||||
```
|
||||
|
||||
## Additional Commands
|
||||
```bash
|
||||
# View PR checks status
|
||||
gh pr checks <PR-number>
|
||||
|
||||
# View PR commits
|
||||
gh pr view <PR-number> --json commits
|
||||
|
||||
# Merge a PR (if you have permission)
|
||||
gh pr merge <PR-number> --merge
|
||||
```
|
||||
</common_gh_commands>
|
||||
|
||||
<general_guidelines_for_commenting>
|
||||
When reviewing a PR, please talk normally and like a friendly reviwer. You should keep it short, and start out by thanking the author of the pr and @ mentioning them.
|
||||
|
||||
Whether or not you approve the PR, you should then give a quick summary of the changes without being too verbose or definitive, staying humble like that this is your understanding of the changes. Kind of how I'm talking to you right now.
|
||||
|
||||
If you have any suggestions, or things that need to be changed, request changes instead of approving the PR.
|
||||
|
||||
Leaving inline comments in code is good, but only do so if you have something specific to say about the code. And make sure you leave those comments first, and then request changes in the PR with a short comment explaining the overall theme of what you're asking them to change.
|
||||
</general_guidelines_for_commenting>
|
||||
|
||||
<example_comments_that_i_have_written_before>
|
||||
<brief_approve_comment>
|
||||
Looks good, though we should make this generic for all providers & models at some point
|
||||
</brief_approve_comment>
|
||||
<brief_approve_comment>
|
||||
Will this work for models that may not match across OR/Gemini? Like the thinking models?
|
||||
</brief_approve_comment>
|
||||
<approve_comment>
|
||||
This looks great! I like how you've handled the global endpoint support - adding it to the ModelInfo interface makes total sense since it's just another capability flag, similar to how we handle other model features.
|
||||
|
||||
The filtered model list approach is clean and will be easier to maintain than hardcoding which models work with global endpoints. And bumping the genai library was obviously needed for this to work.
|
||||
|
||||
Thanks for adding the docs about the limitations too - good for users to know they can't use context caches with global endpoints but might get fewer 429 errors.
|
||||
</approve_comment>
|
||||
<requesst_changes_comment>
|
||||
This is awesome. Thanks @scottsus.
|
||||
|
||||
My main concern though - does this work for all the possible VS Code themes? We struggled with this initially which is why it's not super styled currently. Please test and share screenshots with the different themes to make sure before we can merge
|
||||
</request_changes_comment>
|
||||
<request_changes_comment>
|
||||
Hey, the PR looks good overall but I'm concerned about removing those timeouts. Those were probably there for a reason - VSCode's UI can be finicky with timing.
|
||||
|
||||
Could you add back the timeouts after focusing the sidebar? Something like:
|
||||
|
||||
```typescript
|
||||
await vscode.commands.executeCommand("claude-dev.SidebarProvider.focus")
|
||||
await setTimeoutPromise(100) // Give UI time to update
|
||||
visibleWebview = WebviewProvider.getSidebarInstance()
|
||||
```
|
||||
</request_changes_comment>
|
||||
<request_changes_comment>
|
||||
Heya @alejandropta thanks for working on this!
|
||||
|
||||
A few notes:
|
||||
1 - Adding additional info to the environment variables is fairly problematic because env variables get appended to **every single message**. I don't think this is justifiable for a somewhat niche use case.
|
||||
2 - Adding this option to settings to include that could be an option, but we want our options to be simple and straightforward for new users
|
||||
3 - We're working on revisualizing the way our settings page is displayed/organized, and this could potentially be reconciled once that is in and our settings page is more clearly delineated.
|
||||
|
||||
So until the settings page is update, and this is added to settings in a way that's clean and doesn't confuse new users, I don't think we can merge this. Please bear with us.
|
||||
</request_changes_comment>
|
||||
<request_changes_comment>
|
||||
Also, don't forget to add a changeset since this fixes a user-facing bug.
|
||||
|
||||
The architectural change is solid - moving the focus logic to the command handlers makes sense. Just don't want to introduce subtle timing issues by removing those timeouts.
|
||||
</request_changes_comment>
|
||||
</example_comments_that_i_have_written_before>
|
||||
@@ -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 isn’t 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 can’t execute commands or read their output, you lose access to one of its most powerful capabilities.
|
||||
|
||||
Good Example:
|
||||
|
||||
- When Cline can’t 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.
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"rules": {
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"warn",
|
||||
{
|
||||
"selector": "import",
|
||||
"format": ["camelCase", "PascalCase"]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/semi": "off",
|
||||
"curly": "warn",
|
||||
"eqeqeq": "warn",
|
||||
"no-throw-literal": "warn",
|
||||
"semi": "off",
|
||||
"react-hooks/exhaustive-deps": "off"
|
||||
},
|
||||
"ignorePatterns": ["out", "dist", "**/*.d.ts"]
|
||||
}
|
||||
@@ -1,4 +1,2 @@
|
||||
demo.gif filter=lfs diff=lfs merge=lfs -text
|
||||
assets/docs/demo.gif filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
* text=auto eol=lf
|
||||
|
||||
+1
-3
@@ -1,3 +1 @@
|
||||
/docs/
|
||||
/.github/ @saoudrizwan @dcbartlett
|
||||
/README.md @saoudrizwan @nickbaumann98
|
||||
* @saoudrizwan @ocasta181 @NightTrek @pashpashpash
|
||||
|
||||
@@ -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:
|
||||
@@ -32,26 +32,11 @@ body:
|
||||
description: Please copy and paste any relevant output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
- type: input
|
||||
id: provider-model
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: Provider/Model
|
||||
description: What provider and model were you using when the issue occurred?
|
||||
placeholder: "e.g., cline:anthropic/claude-3.7-sonnet, gemini:gemini-2.5-pro-exp-03-25"
|
||||
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: Operating System
|
||||
description: What operating system are you using?
|
||||
placeholder: "e.g., Windows 11, macOS Sonoma, Ubuntu 22.04"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
@@ -62,3 +47,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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -49,10 +13,7 @@ We're not looking for exhaustive documentation - just evidence that you've thoug
|
||||
- [ ] 🐛 Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] ✨ New feature (non-breaking change which adds functionality)
|
||||
- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] ♻️ Refactor Changes
|
||||
- [ ] 💅 Cosmetic Changes
|
||||
- [ ] 📚 Documentation update
|
||||
- [ ] 🏃 Workflow Changes
|
||||
|
||||
### Pre-flight Checklist
|
||||
|
||||
@@ -65,15 +26,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
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
"""
|
||||
Coverage utility package for GitHub Actions workflows.
|
||||
This package handles extracting coverage percentages, comparing them, and generating PR comments.
|
||||
"""
|
||||
|
||||
# Import external dependencies
|
||||
import requests
|
||||
|
||||
# Import main function for CLI usage
|
||||
from .__main__ import main
|
||||
|
||||
# Import functions from extraction module
|
||||
from .extraction import extract_coverage, compare_coverage, run_coverage, set_verbose
|
||||
|
||||
# Import functions from github_api module
|
||||
from .github_api import generate_comment, post_comment, set_github_output
|
||||
|
||||
# Import functions from workflow module
|
||||
from .workflow import process_coverage_workflow
|
||||
@@ -1,154 +0,0 @@
|
||||
"""
|
||||
Main module.
|
||||
This module provides the CLI interface for the coverage utility script.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
from .extraction import extract_coverage, compare_coverage, run_coverage, set_verbose
|
||||
from .github_api import generate_comment, post_comment, set_github_output
|
||||
from .workflow import process_coverage_workflow
|
||||
from .util import log
|
||||
|
||||
def setup_verbose_mode(args):
|
||||
"""
|
||||
Set up verbose mode based on command line arguments.
|
||||
|
||||
Args:
|
||||
args: Parsed command line arguments
|
||||
"""
|
||||
if getattr(args, 'verbose', False):
|
||||
set_verbose(True)
|
||||
log("Verbose mode enabled")
|
||||
|
||||
def main():
|
||||
# Create parent parser with common arguments
|
||||
parent_parser = argparse.ArgumentParser(add_help=False)
|
||||
parent_parser.add_argument('-v', '--verbose', action='store_true', help='Enable verbose output')
|
||||
|
||||
# Create main parser that inherits common arguments
|
||||
parser = argparse.ArgumentParser(description='Coverage utility script for GitHub Actions workflows', parents=[parent_parser])
|
||||
subparsers = parser.add_subparsers(dest='command', help='Command to run')
|
||||
|
||||
# extract-coverage command - used directly in workflow
|
||||
extract_parser = subparsers.add_parser('extract-coverage', help='Extract coverage percentage from a file', parents=[parent_parser])
|
||||
extract_parser.add_argument('file_path', help='Path to the coverage report file')
|
||||
extract_parser.add_argument('--type', choices=['extension', 'webview'], default='extension',
|
||||
help='Type of coverage report')
|
||||
extract_parser.add_argument('--github-output', action='store_true', help='Output in GitHub Actions format')
|
||||
|
||||
# compare-coverage command - used by process-workflow
|
||||
compare_parser = subparsers.add_parser('compare-coverage', help='Compare coverage percentages', parents=[parent_parser])
|
||||
compare_parser.add_argument('base_cov', help='Base branch coverage percentage')
|
||||
compare_parser.add_argument('pr_cov', help='PR branch coverage percentage')
|
||||
compare_parser.add_argument('--output-prefix', default='', help='Prefix for GitHub Actions output variables')
|
||||
compare_parser.add_argument('--github-output', action='store_true', help='Output in GitHub Actions format')
|
||||
|
||||
# generate-comment command - used by process-workflow
|
||||
comment_parser = subparsers.add_parser('generate-comment', help='Generate PR comment with coverage comparison', parents=[parent_parser])
|
||||
comment_parser.add_argument('base_ext_cov', help='Base branch extension coverage')
|
||||
comment_parser.add_argument('pr_ext_cov', help='PR branch extension coverage')
|
||||
comment_parser.add_argument('ext_decreased', help='Whether extension coverage decreased (true/false)')
|
||||
comment_parser.add_argument('ext_diff', help='Extension coverage difference')
|
||||
comment_parser.add_argument('base_web_cov', help='Base branch webview coverage')
|
||||
comment_parser.add_argument('pr_web_cov', help='PR branch webview coverage')
|
||||
comment_parser.add_argument('web_decreased', help='Whether webview coverage decreased (true/false)')
|
||||
comment_parser.add_argument('web_diff', help='Webview coverage difference')
|
||||
|
||||
# post-comment command - used by process-workflow
|
||||
post_parser = subparsers.add_parser('post-comment', help='Post a comment to a GitHub PR', parents=[parent_parser])
|
||||
post_parser.add_argument('comment_path', help='Path to the file containing the comment text')
|
||||
post_parser.add_argument('pr_number', help='PR number')
|
||||
post_parser.add_argument('repo', help='Repository in the format "owner/repo"')
|
||||
post_parser.add_argument('--token', help='GitHub token')
|
||||
|
||||
# run-coverage command - used by process-workflow
|
||||
run_parser = subparsers.add_parser('run-coverage', help='Run a coverage command and extract the coverage percentage', parents=[parent_parser])
|
||||
run_parser.add_argument('coverage_cmd', help='Command to run')
|
||||
run_parser.add_argument('output_file', help='File to save the output to')
|
||||
run_parser.add_argument('--type', choices=['extension', 'webview'], default='extension',
|
||||
help='Type of coverage report')
|
||||
run_parser.add_argument('--github-output', action='store_true', help='Output in GitHub Actions format')
|
||||
|
||||
# process-workflow command - used directly in workflow
|
||||
workflow_parser = subparsers.add_parser('process-workflow', help='Process the entire coverage workflow', parents=[parent_parser])
|
||||
workflow_parser.add_argument('--base-branch', required=True, help='Base branch name')
|
||||
workflow_parser.add_argument('--pr-number', help='PR number')
|
||||
workflow_parser.add_argument('--repo', help='Repository in the format "owner/repo"')
|
||||
workflow_parser.add_argument('--token', help='GitHub token')
|
||||
|
||||
# set-github-output command - used by process-workflow
|
||||
output_parser = subparsers.add_parser('set-github-output', help='Set GitHub Actions output variable', parents=[parent_parser])
|
||||
output_parser.add_argument('name', help='Output variable name')
|
||||
output_parser.add_argument('value', help='Output variable value')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Set up verbose mode
|
||||
setup_verbose_mode(args)
|
||||
|
||||
if args.command == 'extract-coverage':
|
||||
log(f"Extracting coverage from file: {args.file_path} (type: {args.type})")
|
||||
coverage_pct = extract_coverage(args.file_path, args.type)
|
||||
if args.github_output:
|
||||
set_github_output(f"{args.type}_coverage", coverage_pct)
|
||||
else:
|
||||
log(f"Coverage: {coverage_pct}%")
|
||||
|
||||
elif args.command == 'compare-coverage':
|
||||
log(f"Comparing coverage: base={args.base_cov}%, PR={args.pr_cov}%")
|
||||
decreased, diff = compare_coverage(args.base_cov, args.pr_cov)
|
||||
if args.github_output:
|
||||
prefix = args.output_prefix
|
||||
set_github_output(f"{prefix}decreased", str(decreased).lower())
|
||||
set_github_output(f"{prefix}diff", diff)
|
||||
log(f"Coverage difference: {diff}%")
|
||||
log(f"Coverage decreased: {decreased}")
|
||||
else:
|
||||
log(f"decreased={str(decreased).lower()}")
|
||||
log(f"diff={diff}")
|
||||
|
||||
elif args.command == 'generate-comment':
|
||||
log("Generating coverage comparison comment")
|
||||
comment = generate_comment(
|
||||
args.base_ext_cov, args.pr_ext_cov, args.ext_decreased, args.ext_diff,
|
||||
args.base_web_cov, args.pr_web_cov, args.web_decreased, args.web_diff
|
||||
)
|
||||
# Output the comment to stdout
|
||||
log(comment)
|
||||
|
||||
elif args.command == 'post-comment':
|
||||
log(f"Posting comment from {args.comment_path} to PR #{args.pr_number} in {args.repo}")
|
||||
post_comment(args.comment_path, args.pr_number, args.repo, args.token)
|
||||
|
||||
elif args.command == 'run-coverage':
|
||||
log(f"Running coverage command: {args.coverage_cmd}")
|
||||
log(f"Output file: {args.output_file}")
|
||||
log(f"Coverage type: {args.type}")
|
||||
coverage_pct = run_coverage(args.coverage_cmd, args.output_file, args.type)
|
||||
if args.github_output:
|
||||
set_github_output(f"{args.type}_coverage", coverage_pct)
|
||||
else:
|
||||
log(f"Coverage: {coverage_pct}%")
|
||||
|
||||
elif args.command == 'process-workflow':
|
||||
log("Processing coverage workflow")
|
||||
log(f"Base branch: {args.base_branch}")
|
||||
if args.pr_number:
|
||||
log(f"PR number: {args.pr_number}")
|
||||
if args.repo:
|
||||
log(f"Repository: {args.repo}")
|
||||
process_coverage_workflow(args)
|
||||
|
||||
elif args.command == 'set-github-output':
|
||||
log(f"Setting GitHub output: {args.name}={args.value}")
|
||||
set_github_output(args.name, args.value)
|
||||
|
||||
else:
|
||||
log("No command specified")
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,265 +0,0 @@
|
||||
"""
|
||||
Coverage extraction module.
|
||||
This module handles extracting coverage percentages from coverage report files.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import shlex
|
||||
import subprocess
|
||||
import traceback
|
||||
from .util import log, file_exists, get_file_size, list_directory, is_safe_command, run_command
|
||||
|
||||
# Global verbose flag
|
||||
verbose = False
|
||||
|
||||
def set_verbose(value):
|
||||
"""Set the global verbose flag."""
|
||||
global verbose
|
||||
verbose = value
|
||||
|
||||
def print_debug_output(content, coverage_type):
|
||||
"""
|
||||
Print debug information about the coverage output.
|
||||
|
||||
Args:
|
||||
content: The content of the coverage file
|
||||
coverage_type: Type of coverage report (extension or webview)
|
||||
"""
|
||||
if not verbose:
|
||||
return
|
||||
|
||||
# Extract and print only the coverage summary section
|
||||
if coverage_type == "extension":
|
||||
# Look for the coverage summary section
|
||||
summary_match = re.search(r'=============================== Coverage summary ===============================\n(.*?)\n=+', content, re.DOTALL)
|
||||
if summary_match:
|
||||
sys.stdout.write("\n##[group]EXTENSION COVERAGE SUMMARY\n")
|
||||
sys.stdout.write("=============================== Coverage summary ===============================\n")
|
||||
sys.stdout.write(summary_match.group(1) + "\n")
|
||||
sys.stdout.write("================================================================================\n")
|
||||
sys.stdout.write("##[endgroup]\n")
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
sys.stdout.write("\n##[warning]No coverage summary found in extension coverage file\n")
|
||||
sys.stdout.flush()
|
||||
else: # webview
|
||||
# Look for the coverage table - specifically the "All files" row
|
||||
table_match = re.search(r'% Coverage report from v8.*?-+\|.*?\n.*?\n(All files.*?)(?:\n[^\n]*\|)', content, re.DOTALL)
|
||||
if table_match:
|
||||
sys.stdout.write("\n##[group]WEBVIEW COVERAGE SUMMARY\n")
|
||||
sys.stdout.write("% Coverage report from v8\n")
|
||||
sys.stdout.write("-------------------|---------|----------|---------|---------|-------------------\n")
|
||||
sys.stdout.write("File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n")
|
||||
sys.stdout.write("-------------------|---------|----------|---------|---------|-------------------\n")
|
||||
sys.stdout.write(table_match.group(1) + "\n")
|
||||
sys.stdout.write("-------------------|---------|----------|---------|---------|-------------------\n")
|
||||
sys.stdout.write("##[endgroup]\n")
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
sys.stdout.write("\n##[warning]No coverage table found in webview coverage file\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
def extract_coverage(file_path, coverage_type="extension"):
|
||||
"""
|
||||
Extract coverage percentage from a coverage report file.
|
||||
|
||||
Args:
|
||||
file_path: Path to the coverage report file
|
||||
coverage_type: Type of coverage report (extension or webview)
|
||||
|
||||
Returns:
|
||||
Coverage percentage as a float
|
||||
"""
|
||||
|
||||
# Always print file path for debugging
|
||||
log(f"Checking coverage file: {file_path}")
|
||||
|
||||
# Check if file exists and get its size
|
||||
if not file_exists(file_path):
|
||||
sys.stdout.write(f"\n##[error]File {file_path} does not exist\n")
|
||||
sys.stdout.flush()
|
||||
log(f"Error: File {file_path} does not exist")
|
||||
|
||||
# Check if the directory exists
|
||||
dir_path = os.path.dirname(file_path)
|
||||
if not os.path.exists(dir_path):
|
||||
sys.stdout.write(f"\n##[error]Directory {dir_path} does not exist\n")
|
||||
sys.stdout.flush()
|
||||
log(f"Error: Directory {dir_path} does not exist")
|
||||
else:
|
||||
# List directory contents for debugging
|
||||
log(f"Directory {dir_path} exists, listing contents:")
|
||||
try:
|
||||
dir_contents = list_directory(dir_path)
|
||||
for name, size in dir_contents:
|
||||
log(f" {name} - {size}")
|
||||
sys.stdout.write(f" {name} - {size}\n")
|
||||
sys.stdout.flush()
|
||||
except Exception as e:
|
||||
log(f"Error listing directory: {e}")
|
||||
|
||||
return 0.0
|
||||
|
||||
file_size = get_file_size(file_path)
|
||||
log(f"File size: {file_size} bytes")
|
||||
sys.stdout.write(f"\n##[info]Coverage file {file_path} exists, size: {file_size} bytes\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
if file_size == 0:
|
||||
sys.stdout.write(f"\n##[warning]File {file_path} is empty\n")
|
||||
sys.stdout.flush()
|
||||
log(f"Warning: File {file_path} is empty")
|
||||
return 0.0
|
||||
|
||||
# List directory contents for debugging
|
||||
dir_path = os.path.dirname(file_path)
|
||||
log(f"Directory contents of {dir_path}:")
|
||||
try:
|
||||
dir_contents = list_directory(dir_path)
|
||||
for name, size in dir_contents:
|
||||
log(f" {name} - {size}")
|
||||
except Exception as e:
|
||||
log(f"Error listing directory: {e}")
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Print debug information if verbose
|
||||
print_debug_output(content, coverage_type)
|
||||
|
||||
# Extract coverage percentage based on coverage type
|
||||
if coverage_type == "extension":
|
||||
# Extract the percentage from the "Lines" row in the coverage summary
|
||||
# Pattern: Lines : xx.xx% ( xxxxxxx/xxxxxxx )
|
||||
lines_match = re.search(r'Lines\s*:\s*(\d+\.\d+)%', content)
|
||||
if lines_match:
|
||||
coverage_pct = float(lines_match.group(1))
|
||||
if verbose:
|
||||
sys.stdout.write(f"Pattern matched (Lines percentage): {coverage_pct}\n")
|
||||
sys.stdout.flush()
|
||||
return coverage_pct
|
||||
else:
|
||||
# No coverage data found, log full content for debugging
|
||||
log("No coverage data found. Full file content:")
|
||||
log("=== Full file content ===")
|
||||
log(content)
|
||||
log("=== End file content ===")
|
||||
else: # webview
|
||||
# Extract the percentage from the "% Lines" column in the "All files" row
|
||||
# Pattern: All files | xx.xx | xx.xx | xx.xx | xx.xx |
|
||||
all_files_match = re.search(r'All files\s+\|\s+\d+\.\d+\s+\|\s+\d+\.\d+\s+\|\s+\d+\.\d+\s+\|\s+(\d+\.\d+)', content)
|
||||
if all_files_match:
|
||||
coverage_pct = float(all_files_match.group(1))
|
||||
if verbose:
|
||||
sys.stdout.write(f"Pattern matched (All files % Lines): {coverage_pct}\n")
|
||||
sys.stdout.flush()
|
||||
return coverage_pct
|
||||
else:
|
||||
# No coverage data found, log full content for debugging
|
||||
log("No coverage data found. Full file content:")
|
||||
log("=== Full file content ===")
|
||||
log(content)
|
||||
log("=== End file content ===")
|
||||
|
||||
# If no match found, return 0.0
|
||||
return 0.0
|
||||
|
||||
def compare_coverage(base_cov, pr_cov):
|
||||
"""
|
||||
Compare coverage percentages between base and PR branches.
|
||||
|
||||
Args:
|
||||
base_cov: Base branch coverage percentage
|
||||
pr_cov: PR branch coverage percentage
|
||||
|
||||
Returns:
|
||||
Tuple of (decreased, diff)
|
||||
"""
|
||||
try:
|
||||
base_cov = float(base_cov)
|
||||
pr_cov = float(pr_cov)
|
||||
except ValueError:
|
||||
sys.stdout.write(f"Error: Invalid coverage values - base: {base_cov}, PR: {pr_cov}\n")
|
||||
sys.stdout.flush()
|
||||
return False, 0
|
||||
|
||||
diff = pr_cov - base_cov
|
||||
decreased = diff < 0
|
||||
|
||||
return decreased, abs(diff)
|
||||
|
||||
def run_coverage(command, output_file, coverage_type="extension"):
|
||||
"""
|
||||
Run a coverage command and extract the coverage percentage.
|
||||
|
||||
Args:
|
||||
command: Command to run
|
||||
output_file: File to save the output to
|
||||
coverage_type: Type of coverage report (extension or webview)
|
||||
|
||||
Returns:
|
||||
Coverage percentage as a float
|
||||
|
||||
Raises:
|
||||
SystemExit: If the output file is not created or is empty
|
||||
"""
|
||||
|
||||
try:
|
||||
# Run the command and capture output
|
||||
if not is_safe_command(command):
|
||||
error_msg = f"ERROR: Unsafe command detected: {command}"
|
||||
log(error_msg)
|
||||
sys.stdout.write(f"\n##[error]{error_msg}\n")
|
||||
sys.stdout.flush()
|
||||
sys.exit(1)
|
||||
|
||||
# Run command using safe execution from util
|
||||
returncode, stdout, stderr = run_command(command)
|
||||
|
||||
# Log command result
|
||||
log(f"Command exit code: {returncode}")
|
||||
log(f"Command stdout length: {len(stdout)} bytes")
|
||||
log(f"Command stderr length: {len(stderr)} bytes")
|
||||
|
||||
# Save output to file
|
||||
log(f"Saving command output to {output_file}")
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(stdout)
|
||||
if stderr:
|
||||
f.write("\n\n=== STDERR ===\n")
|
||||
f.write(stderr)
|
||||
|
||||
# Verify file was created and has content
|
||||
if not file_exists(output_file):
|
||||
error_msg = f"ERROR: Output file {output_file} was not created"
|
||||
log(error_msg)
|
||||
sys.stdout.write(f"\n##[error]{error_msg}\n")
|
||||
sys.stdout.flush()
|
||||
sys.exit(1) # Exit with error code to fail the workflow
|
||||
|
||||
file_size = get_file_size(output_file)
|
||||
if file_size == 0:
|
||||
error_msg = f"ERROR: Output file {output_file} is empty"
|
||||
log(error_msg)
|
||||
sys.stdout.write(f"\n##[error]{error_msg}\n")
|
||||
sys.stdout.flush()
|
||||
sys.exit(1) # Exit with error code to fail the workflow
|
||||
|
||||
log(f"Output file size: {file_size} bytes")
|
||||
|
||||
# Extract coverage percentage
|
||||
coverage_pct = extract_coverage(output_file, coverage_type)
|
||||
|
||||
log(f"{coverage_type.capitalize()} coverage: {coverage_pct}%")
|
||||
return coverage_pct
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error running coverage command: {e}"
|
||||
log(error_msg)
|
||||
sys.stdout.write(f"\n##[error]{error_msg}\n")
|
||||
sys.stdout.flush()
|
||||
# Print stack trace for debugging
|
||||
log(traceback.format_exc())
|
||||
sys.exit(1) # Exit with error code to fail the workflow
|
||||
@@ -1,177 +0,0 @@
|
||||
"""
|
||||
GitHub API module.
|
||||
This module handles interactions with the GitHub API for posting comments to PRs.
|
||||
"""
|
||||
|
||||
import os
|
||||
import requests
|
||||
from .util import log, file_exists
|
||||
|
||||
def generate_comment(base_ext_cov, pr_ext_cov, ext_decreased, ext_diff,
|
||||
base_web_cov, pr_web_cov, web_decreased, web_diff):
|
||||
"""
|
||||
Generate a PR comment with coverage comparison.
|
||||
|
||||
Args:
|
||||
base_ext_cov: Base branch extension coverage
|
||||
pr_ext_cov: PR branch extension coverage
|
||||
ext_decreased: Whether extension coverage decreased
|
||||
ext_diff: Extension coverage difference
|
||||
base_web_cov: Base branch webview coverage
|
||||
pr_web_cov: PR branch webview coverage
|
||||
web_decreased: Whether webview coverage decreased
|
||||
web_diff: Webview coverage difference
|
||||
|
||||
Returns:
|
||||
Comment text
|
||||
"""
|
||||
from datetime import datetime
|
||||
|
||||
# Convert string inputs to appropriate types
|
||||
try:
|
||||
base_ext_cov = float(base_ext_cov)
|
||||
pr_ext_cov = float(pr_ext_cov)
|
||||
# Handle ext_decreased as either string or boolean
|
||||
if isinstance(ext_decreased, str):
|
||||
ext_decreased = ext_decreased.lower() == 'true'
|
||||
else:
|
||||
ext_decreased = bool(ext_decreased)
|
||||
ext_diff = float(ext_diff)
|
||||
base_web_cov = float(base_web_cov)
|
||||
pr_web_cov = float(pr_web_cov)
|
||||
# Handle web_decreased as either string or boolean
|
||||
if isinstance(web_decreased, str):
|
||||
web_decreased = web_decreased.lower() == 'true'
|
||||
else:
|
||||
web_decreased = bool(web_decreased)
|
||||
web_diff = float(web_diff)
|
||||
except ValueError as e:
|
||||
log(f"Error converting input values: {e}")
|
||||
return ""
|
||||
|
||||
# Add a unique identifier to find this comment later
|
||||
comment = '<!-- COVERAGE_REPORT -->\n'
|
||||
comment += '## Coverage Report\n\n'
|
||||
|
||||
# Extension coverage
|
||||
comment += '### Extension Coverage\n\n'
|
||||
comment += f'Base branch: {base_ext_cov:.0f}%\n\n'
|
||||
comment += f'PR branch: {pr_ext_cov:.0f}%\n\n'
|
||||
|
||||
if ext_decreased:
|
||||
comment += f'⚠️ **Warning: Coverage decreased by {ext_diff:.2f}%**\n\n'
|
||||
comment += 'Consider adding tests to cover your changes.\n\n'
|
||||
else:
|
||||
comment += '✅ Coverage increased or remained the same\n\n'
|
||||
|
||||
# Webview coverage
|
||||
comment += '### Webview Coverage\n\n'
|
||||
comment += f'Base branch: {base_web_cov:.0f}%\n\n'
|
||||
comment += f'PR branch: {pr_web_cov:.0f}%\n\n'
|
||||
|
||||
if web_decreased:
|
||||
comment += f'⚠️ **Warning: Coverage decreased by {web_diff:.2f}%**\n\n'
|
||||
comment += 'Consider adding tests to cover your changes.\n\n'
|
||||
else:
|
||||
comment += '✅ Coverage increased or remained the same\n\n'
|
||||
|
||||
# Overall assessment
|
||||
comment += '### Overall Assessment\n\n'
|
||||
if ext_decreased or web_decreased:
|
||||
comment += '⚠️ **Test coverage has decreased in this PR**\n\n'
|
||||
comment += 'Please consider adding tests to maintain or improve coverage.\n\n'
|
||||
else:
|
||||
comment += '✅ **Test coverage has been maintained or improved**\n\n'
|
||||
|
||||
# Add timestamp
|
||||
comment += f'\n\n<sub>Last updated: {datetime.now().isoformat()}</sub>'
|
||||
|
||||
return comment
|
||||
|
||||
def post_comment(comment_path, pr_number, repo, token=None):
|
||||
"""
|
||||
Post a comment to a GitHub PR.
|
||||
|
||||
Args:
|
||||
comment_path: Path to the file containing the comment text
|
||||
pr_number: PR number
|
||||
repo: Repository in the format "owner/repo"
|
||||
token: GitHub token
|
||||
"""
|
||||
if not file_exists(comment_path):
|
||||
log(f"Error: Comment file {comment_path} does not exist")
|
||||
return
|
||||
|
||||
with open(comment_path, 'r') as f:
|
||||
comment_body = f.read()
|
||||
|
||||
if not token:
|
||||
token = os.environ.get('GITHUB_TOKEN')
|
||||
if not token:
|
||||
log("Error: GitHub token not provided")
|
||||
return
|
||||
|
||||
# Find existing comment
|
||||
headers = {
|
||||
'Authorization': f'token {token}',
|
||||
'Accept': 'application/vnd.github.v3+json'
|
||||
}
|
||||
|
||||
# Get all comments
|
||||
comments_url = f'https://api.github.com/repos/{repo}/issues/{pr_number}/comments'
|
||||
log(f"Getting comments from: {comments_url}")
|
||||
response = requests.get(comments_url, headers=headers)
|
||||
|
||||
if response.status_code != 200:
|
||||
log(f"Error getting comments: {response.status_code} - {response.text}")
|
||||
return
|
||||
|
||||
comments = response.json()
|
||||
log(f"Found {len(comments)} existing comments")
|
||||
|
||||
# Find comment with our identifier
|
||||
comment_id = None
|
||||
for comment in comments:
|
||||
if '<!-- COVERAGE_REPORT -->' in comment['body']:
|
||||
comment_id = comment['id']
|
||||
log(f"Found existing coverage report comment with ID: {comment_id}")
|
||||
break
|
||||
|
||||
if comment_id:
|
||||
# Update existing comment
|
||||
update_url = f'https://api.github.com/repos/{repo}/issues/comments/{comment_id}'
|
||||
log(f"Updating existing comment at: {update_url}")
|
||||
response = requests.patch(update_url, headers=headers, json={'body': comment_body})
|
||||
|
||||
if response.status_code == 200:
|
||||
log(f"Successfully updated existing comment: {comment_id}")
|
||||
else:
|
||||
log(f"Error updating comment: {response.status_code} - {response.text}")
|
||||
else:
|
||||
# Create new comment
|
||||
log(f"Creating new comment at: {comments_url}")
|
||||
response = requests.post(comments_url, headers=headers, json={'body': comment_body})
|
||||
|
||||
if response.status_code == 201:
|
||||
log("Successfully created new comment")
|
||||
else:
|
||||
log(f"Error creating comment: {response.status_code} - {response.text}")
|
||||
|
||||
def set_github_output(name, value):
|
||||
"""
|
||||
Set GitHub Actions output variable.
|
||||
|
||||
Args:
|
||||
name: Output variable name
|
||||
value: Output variable value
|
||||
"""
|
||||
# Write to the GitHub output file if available
|
||||
if 'GITHUB_OUTPUT' in os.environ:
|
||||
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
|
||||
f.write(f"{name}={value}\n")
|
||||
else:
|
||||
# Fallback to the deprecated method for backward compatibility
|
||||
log(f"::set-output name={name}::{value}")
|
||||
|
||||
# Also print for human readability
|
||||
log(f"{name}: {value}")
|
||||
@@ -1,245 +0,0 @@
|
||||
"""
|
||||
Utility module.
|
||||
This module provides utility functions used across the coverage check scripts.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import shlex
|
||||
import subprocess
|
||||
import traceback
|
||||
from typing import List, Tuple, Dict, Any, Optional, Union
|
||||
|
||||
# List of allowed commands and their arguments
|
||||
ALLOWED_COMMANDS = {
|
||||
'xvfb-run': ['-a'],
|
||||
'npm': ['run', 'test:coverage', 'ci', 'install', '--no-save', '@vitest/coverage-v8', 'check-types', 'lint', 'format', 'compile'],
|
||||
'cd': ['webview-ui'],
|
||||
'python': ['-m', 'coverage_check'],
|
||||
'git': ['fetch', 'checkout', 'origin'],
|
||||
}
|
||||
|
||||
def is_safe_command(command: Union[str, List[str]]) -> bool:
|
||||
"""
|
||||
Check if a command is safe to execute.
|
||||
|
||||
Args:
|
||||
command: Command to check (string or list)
|
||||
|
||||
Returns:
|
||||
True if command is safe, False otherwise
|
||||
"""
|
||||
# Convert string command to list
|
||||
if isinstance(command, str):
|
||||
try:
|
||||
cmd_parts = shlex.split(command)
|
||||
except ValueError:
|
||||
return False
|
||||
else:
|
||||
cmd_parts = command
|
||||
|
||||
if not cmd_parts:
|
||||
return False
|
||||
|
||||
# Get base command
|
||||
base_cmd = os.path.basename(cmd_parts[0])
|
||||
|
||||
# Check if command is in allowed list
|
||||
if base_cmd not in ALLOWED_COMMANDS:
|
||||
return False
|
||||
|
||||
# For each argument, check for suspicious patterns
|
||||
for arg in cmd_parts[1:]:
|
||||
# Check for shell metacharacters
|
||||
if re.search(r'[;&|`$]', arg):
|
||||
return False
|
||||
# Check for path traversal
|
||||
if '..' in arg and not (base_cmd == 'npm' and arg.startswith('@')):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def log(message: str) -> None:
|
||||
"""
|
||||
Write a message to stdout and flush.
|
||||
|
||||
Args:
|
||||
message: The message to write
|
||||
"""
|
||||
sys.stdout.write(f"{message}\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
def file_exists(file_path: str) -> bool:
|
||||
"""
|
||||
Check if a file exists.
|
||||
|
||||
Args:
|
||||
file_path: Path to the file
|
||||
|
||||
Returns:
|
||||
True if the file exists, False otherwise
|
||||
"""
|
||||
return os.path.exists(file_path) and os.path.isfile(file_path)
|
||||
|
||||
def get_file_size(file_path: str) -> int:
|
||||
"""
|
||||
Get the size of a file in bytes.
|
||||
|
||||
Args:
|
||||
file_path: Path to the file
|
||||
|
||||
Returns:
|
||||
Size of the file in bytes, or 0 if the file doesn't exist
|
||||
"""
|
||||
if file_exists(file_path):
|
||||
return os.path.getsize(file_path)
|
||||
return 0
|
||||
|
||||
def list_directory(dir_path: str) -> List[Tuple[str, Union[int, str]]]:
|
||||
"""
|
||||
List the contents of a directory.
|
||||
|
||||
Args:
|
||||
dir_path: Path to the directory
|
||||
|
||||
Returns:
|
||||
List of (name, size) tuples for each file/directory in the directory
|
||||
"""
|
||||
if not os.path.exists(dir_path) or not os.path.isdir(dir_path):
|
||||
return []
|
||||
|
||||
contents = []
|
||||
for item in os.listdir(dir_path):
|
||||
item_path = os.path.join(dir_path, item)
|
||||
if os.path.isfile(item_path):
|
||||
contents.append((item, os.path.getsize(item_path)))
|
||||
else:
|
||||
contents.append((item, "DIR"))
|
||||
|
||||
return contents
|
||||
|
||||
def read_file_content(file_path: str, default: str = "") -> str:
|
||||
"""
|
||||
Read file content with error handling.
|
||||
|
||||
Args:
|
||||
file_path: Path to the file
|
||||
default: Default value to return if file cannot be read
|
||||
|
||||
Returns:
|
||||
File content or default value
|
||||
"""
|
||||
if not file_exists(file_path):
|
||||
log(f"File does not exist: {file_path}")
|
||||
return default
|
||||
|
||||
try:
|
||||
with open(file_path, 'r') as f:
|
||||
return f.read()
|
||||
except Exception as e:
|
||||
log(f"Error reading file {file_path}: {e}")
|
||||
return default
|
||||
|
||||
def write_file_content(file_path: str, content: str) -> bool:
|
||||
"""
|
||||
Write content to file with error handling.
|
||||
|
||||
Args:
|
||||
file_path: Path to the file
|
||||
content: Content to write
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Create directory if it doesn't exist
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
|
||||
with open(file_path, 'w') as f:
|
||||
f.write(content)
|
||||
return True
|
||||
except Exception as e:
|
||||
log(f"Error writing to file {file_path}: {e}")
|
||||
return False
|
||||
|
||||
def run_command(command: Union[str, List[str]], capture_output: bool = True) -> Tuple[int, str, str]:
|
||||
"""
|
||||
Run a command and return the result.
|
||||
|
||||
Args:
|
||||
command: Command to run (string or list)
|
||||
capture_output: Whether to capture stdout/stderr
|
||||
|
||||
Returns:
|
||||
Tuple of (returncode, stdout, stderr)
|
||||
"""
|
||||
if not is_safe_command(command):
|
||||
error_msg = f"Unsafe command detected: {command}"
|
||||
log(error_msg)
|
||||
return 1, "", error_msg
|
||||
|
||||
log(f"Running command: {command}")
|
||||
try:
|
||||
# Convert string command to list
|
||||
if isinstance(command, str):
|
||||
cmd_list = shlex.split(command)
|
||||
else:
|
||||
cmd_list = command
|
||||
|
||||
result = subprocess.run(
|
||||
cmd_list,
|
||||
shell=False, # Never use shell=True for security
|
||||
capture_output=capture_output,
|
||||
text=True
|
||||
)
|
||||
log(f"Command exit code: {result.returncode}")
|
||||
return result.returncode, result.stdout, result.stderr
|
||||
except Exception as e:
|
||||
log(f"Error running command: {e}")
|
||||
log(traceback.format_exc())
|
||||
return 1, "", str(e)
|
||||
|
||||
def find_pattern(content: str, pattern: str, group: int = 0,
|
||||
default: Optional[str] = None) -> Optional[str]:
|
||||
"""
|
||||
Find a pattern in content and return the specified group.
|
||||
|
||||
Args:
|
||||
content: Text content to search
|
||||
pattern: Regex pattern to search for
|
||||
group: Group number to return (default: 0 for entire match)
|
||||
default: Default value to return if pattern not found
|
||||
|
||||
Returns:
|
||||
Matched text or default value
|
||||
"""
|
||||
match = re.search(pattern, content, re.DOTALL)
|
||||
if match:
|
||||
return match.group(group)
|
||||
return default
|
||||
|
||||
def get_env_var(name: str, default: Optional[str] = None) -> Optional[str]:
|
||||
"""
|
||||
Get environment variable with default value.
|
||||
|
||||
Args:
|
||||
name: Environment variable name
|
||||
default: Default value if not set
|
||||
|
||||
Returns:
|
||||
Environment variable value or default
|
||||
"""
|
||||
return os.environ.get(name, default)
|
||||
|
||||
def format_exception(e: Exception) -> str:
|
||||
"""
|
||||
Format an exception with traceback for logging.
|
||||
|
||||
Args:
|
||||
e: Exception to format
|
||||
|
||||
Returns:
|
||||
Formatted exception string
|
||||
"""
|
||||
return f"{type(e).__name__}: {str(e)}\n{traceback.format_exc()}"
|
||||
@@ -1,432 +0,0 @@
|
||||
"""
|
||||
Workflow module.
|
||||
This module handles the main workflow logic for running coverage tests and processing results.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import subprocess
|
||||
import traceback
|
||||
|
||||
from .extraction import run_coverage, compare_coverage, extract_coverage
|
||||
from .github_api import generate_comment, post_comment, set_github_output
|
||||
from .util import log, file_exists, get_file_size, list_directory, run_command
|
||||
|
||||
def is_valid_branch_name(branch_name: str) -> bool:
|
||||
"""
|
||||
Validate a git branch name.
|
||||
|
||||
Args:
|
||||
branch_name: Branch name to validate
|
||||
|
||||
Returns:
|
||||
True if valid, False otherwise
|
||||
"""
|
||||
# Check for common branch name patterns
|
||||
if not re.match(r'^[a-zA-Z0-9_\-./]+$', branch_name):
|
||||
return False
|
||||
|
||||
# Check for path traversal
|
||||
if '..' in branch_name:
|
||||
return False
|
||||
|
||||
# Check for shell metacharacters
|
||||
if re.search(r'[;&|`$]', branch_name):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def checkout_branch(branch_name: str) -> None:
|
||||
"""
|
||||
Checkout a branch for testing.
|
||||
|
||||
Args:
|
||||
branch_name: Branch name to checkout
|
||||
|
||||
Raises:
|
||||
RuntimeError: If branch checkout fails
|
||||
ValueError: If branch name is invalid
|
||||
"""
|
||||
if not is_valid_branch_name(branch_name):
|
||||
raise ValueError(f"Invalid branch name: {branch_name}")
|
||||
|
||||
log(f"=== Checking out branch: {branch_name} ===")
|
||||
|
||||
# Fetch the branch
|
||||
returncode, stdout, stderr = run_command(['git', 'fetch', 'origin', branch_name])
|
||||
if returncode != 0:
|
||||
log(f"ERROR: Failed to fetch branch {branch_name}")
|
||||
log(f"Error details: {stderr}")
|
||||
raise RuntimeError(f"Git fetch failed: {stderr}")
|
||||
|
||||
# Checkout the branch
|
||||
returncode, stdout, stderr = run_command(['git', 'checkout', branch_name])
|
||||
if returncode != 0:
|
||||
log(f"ERROR: Failed to checkout branch {branch_name}")
|
||||
log(f"Error details: {stderr}")
|
||||
raise RuntimeError(f"Git checkout failed: {stderr}")
|
||||
|
||||
log(f"Successfully checked out branch: {branch_name}")
|
||||
|
||||
def extract_extension_coverage_from_file(file_path):
|
||||
"""Extract extension coverage from file when run_coverage returns 0."""
|
||||
if not file_exists(file_path):
|
||||
log(f"File {file_path} does not exist, cannot extract extension coverage")
|
||||
return 0.0
|
||||
|
||||
file_size = get_file_size(file_path)
|
||||
if file_size == 0:
|
||||
log(f"File {file_path} is empty, cannot extract extension coverage")
|
||||
return 0.0
|
||||
|
||||
log(f"Extension coverage is 0.0, trying to read from file directly: {file_path} (size: {file_size} bytes)")
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
# Extract the percentage from the "Lines" row in the coverage summary
|
||||
# Pattern: Lines : xx.xx% ( xxxxxxx/xxxxxxx )
|
||||
lines_match = re.search(r'Lines\s*:\s*(\d+\.\d+)%', content)
|
||||
if lines_match:
|
||||
coverage = float(lines_match.group(1))
|
||||
log(f"Found extension coverage in file: {coverage}%")
|
||||
return coverage
|
||||
return 0.0
|
||||
|
||||
def extract_webview_coverage_from_file(file_path):
|
||||
"""Extract webview coverage from file when run_coverage returns 0."""
|
||||
if not file_exists(file_path):
|
||||
log(f"File {file_path} does not exist, cannot extract webview coverage")
|
||||
return 0.0
|
||||
|
||||
file_size = get_file_size(file_path)
|
||||
if file_size == 0:
|
||||
log(f"File {file_path} is empty, cannot extract webview coverage")
|
||||
return 0.0
|
||||
|
||||
log(f"Webview coverage is 0.0, trying to read from file directly: {file_path} (size: {file_size} bytes)")
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
# Extract the percentage from the "% Lines" column in the "All files" row
|
||||
# Pattern: All files | xx.xx | xx.xx | xx.xx | xx.xx |
|
||||
all_files_match = re.search(r'All files\s+\|\s+\d+\.\d+\s+\|\s+\d+\.\d+\s+\|\s+\d+\.\d+\s+\|\s+(\d+\.\d+)', content)
|
||||
if all_files_match:
|
||||
coverage = float(all_files_match.group(1))
|
||||
log(f"Found webview coverage in file: {coverage}%")
|
||||
return coverage
|
||||
return 0.0
|
||||
|
||||
def run_extension_coverage(branch_name=None):
|
||||
"""Run extension coverage tests and extract results."""
|
||||
prefix = 'base_' if branch_name else ''
|
||||
file_path = f"{prefix}extension_coverage.txt"
|
||||
|
||||
# Run coverage tests
|
||||
ext_cov = run_coverage(
|
||||
["xvfb-run", "-a", "npm", "run", "test:coverage"],
|
||||
file_path,
|
||||
"extension"
|
||||
)
|
||||
|
||||
# If coverage is 0.0, try to extract from file directly
|
||||
if ext_cov == 0.0:
|
||||
ext_cov = extract_extension_coverage_from_file(file_path)
|
||||
|
||||
return ext_cov
|
||||
|
||||
def run_webview_coverage(branch_name=None):
|
||||
"""Run webview coverage tests and extract results."""
|
||||
prefix = 'base_' if branch_name else ''
|
||||
file_path = f"{prefix}webview_coverage.txt"
|
||||
|
||||
# Save current directory
|
||||
original_dir = os.getcwd()
|
||||
|
||||
try:
|
||||
# Change to webview-ui directory
|
||||
os.chdir('webview-ui')
|
||||
|
||||
# Install coverage dependency
|
||||
returncode, stdout, stderr = run_command(["npm", "install", "--no-save", "@vitest/coverage-v8"])
|
||||
if returncode != 0:
|
||||
log(f"Failed to install coverage dependency: {stderr}")
|
||||
return 0.0
|
||||
|
||||
# Run coverage tests from webview-ui directory
|
||||
web_cov = run_coverage(
|
||||
["npm", "run", "test:coverage"],
|
||||
os.path.join('..', file_path),
|
||||
"webview"
|
||||
)
|
||||
finally:
|
||||
# Always change back to original directory
|
||||
os.chdir(original_dir)
|
||||
|
||||
# If coverage is 0.0, try to extract from file directly
|
||||
if web_cov == 0.0:
|
||||
web_cov = extract_webview_coverage_from_file(file_path)
|
||||
|
||||
return web_cov
|
||||
|
||||
def run_branch_coverage(branch_name=None):
|
||||
"""
|
||||
Run coverage tests for a branch.
|
||||
|
||||
Args:
|
||||
branch_name: Name of the branch to checkout before running tests (optional)
|
||||
|
||||
Returns:
|
||||
Tuple of (extension_coverage, webview_coverage)
|
||||
"""
|
||||
# Checkout branch if specified
|
||||
if branch_name:
|
||||
checkout_branch(branch_name)
|
||||
|
||||
# Run coverage tests
|
||||
log(f"=== Running coverage tests{' for ' + branch_name if branch_name else ''} ===")
|
||||
|
||||
# Run extension and webview coverage
|
||||
ext_cov = run_extension_coverage(branch_name)
|
||||
web_cov = run_webview_coverage(branch_name)
|
||||
|
||||
return ext_cov, web_cov
|
||||
|
||||
def find_potential_coverage_files():
|
||||
"""Find potential coverage files in the current directory and webview-ui."""
|
||||
log("Searching for potential coverage files...")
|
||||
|
||||
# Find files in current directory
|
||||
current_dir_files = list_directory('.')
|
||||
for name, size in current_dir_files:
|
||||
if 'coverage' in name.lower() and size != "DIR":
|
||||
log(f"Found potential coverage file: {name} (size: {size} bytes)")
|
||||
|
||||
# Find files in webview-ui directory
|
||||
if os.path.exists('webview-ui') and os.path.isdir('webview-ui'):
|
||||
webview_files = list_directory('webview-ui')
|
||||
for name, size in webview_files:
|
||||
if 'coverage' in name.lower() and size != "DIR":
|
||||
log(f"Found potential webview coverage file: webview-ui/{name} (size: {size} bytes)")
|
||||
else:
|
||||
log("webview-ui directory not found")
|
||||
|
||||
def generate_warnings(base_ext_cov, pr_ext_cov, ext_decreased, ext_diff,
|
||||
base_web_cov, pr_web_cov, web_decreased, web_diff):
|
||||
"""Generate warnings for coverage decreases."""
|
||||
if not (ext_decreased or web_decreased):
|
||||
return []
|
||||
|
||||
warnings = [
|
||||
"Test coverage has decreased in this PR",
|
||||
f"Extension coverage: {base_ext_cov}% -> {pr_ext_cov}% (Diff: {ext_diff}%)",
|
||||
f"Webview coverage: {base_web_cov}% -> {pr_web_cov}% (Diff: {web_diff}%)"
|
||||
]
|
||||
|
||||
# Additional warning for significant decrease (more than 1%)
|
||||
if ext_decreased and ext_diff > 1.0:
|
||||
warnings.append(f"Extension coverage decreased by more than 1% ({ext_diff}%). Consider adding tests to cover your changes.")
|
||||
|
||||
if web_decreased and web_diff > 1.0:
|
||||
warnings.append(f"Webview coverage decreased by more than 1% ({web_diff}%). Consider adding tests to cover your changes.")
|
||||
|
||||
return warnings
|
||||
|
||||
def output_warnings(warnings):
|
||||
"""Output warnings to GitHub step summary and console."""
|
||||
if not warnings:
|
||||
return
|
||||
|
||||
# Get the GitHub step summary file path from environment variable
|
||||
github_step_summary = os.environ.get('GITHUB_STEP_SUMMARY')
|
||||
|
||||
# Write to GitHub step summary if available
|
||||
if github_step_summary:
|
||||
with open(github_step_summary, 'a') as f:
|
||||
f.write("## Coverage Warnings\n\n")
|
||||
for warning in warnings:
|
||||
f.write(f"⚠️ {warning}\n\n")
|
||||
|
||||
# Also output to console with ::warning:: syntax for backward compatibility
|
||||
for warning in warnings:
|
||||
log(f"::warning::{warning}")
|
||||
|
||||
def output_github_results(pr_ext_cov, pr_web_cov, base_ext_cov, base_web_cov,
|
||||
ext_decreased, ext_diff, web_decreased, web_diff):
|
||||
"""Output results for GitHub Actions."""
|
||||
set_github_output("pr_extension_coverage", pr_ext_cov)
|
||||
set_github_output("pr_webview_coverage", pr_web_cov)
|
||||
set_github_output("base_extension_coverage", base_ext_cov)
|
||||
set_github_output("base_webview_coverage", base_web_cov)
|
||||
set_github_output("extension_decreased", str(ext_decreased).lower())
|
||||
set_github_output("extension_diff", ext_diff)
|
||||
set_github_output("webview_decreased", str(web_decreased).lower())
|
||||
set_github_output("webview_diff", web_diff)
|
||||
|
||||
def extract_pr_coverage_from_artifacts():
|
||||
"""
|
||||
Extract PR branch coverage from artifact files.
|
||||
|
||||
Returns:
|
||||
Tuple of (extension_coverage, webview_coverage)
|
||||
|
||||
Raises:
|
||||
SystemExit: If the coverage files don't exist
|
||||
"""
|
||||
log("=== Extracting PR branch coverage from artifacts ===")
|
||||
|
||||
# Check if the coverage files exist
|
||||
ext_file_path = "extension_coverage.txt"
|
||||
web_file_path = "webview-ui/webview_coverage.txt"
|
||||
|
||||
# Extract extension coverage
|
||||
log(f"Extracting extension coverage from {ext_file_path}")
|
||||
if not file_exists(ext_file_path):
|
||||
error_msg = f"ERROR: PR extension coverage file {ext_file_path} not found"
|
||||
log(error_msg)
|
||||
|
||||
# List directory contents for debugging
|
||||
log("Current directory contents:")
|
||||
try:
|
||||
dir_contents = list_directory('.')
|
||||
for name, size in dir_contents:
|
||||
log(f" {name} - {size}\n")
|
||||
except Exception as e:
|
||||
log(f"Error listing directory: {e}")
|
||||
|
||||
sys.exit(1) # Exit with error code to fail the workflow
|
||||
|
||||
ext_cov = extract_extension_coverage_from_file(ext_file_path)
|
||||
log(f"PR extension coverage from artifact: {ext_cov}%")
|
||||
|
||||
# Extract webview coverage
|
||||
log(f"Extracting webview coverage from {web_file_path}")
|
||||
if not file_exists(web_file_path):
|
||||
error_msg = f"ERROR: PR webview coverage file {web_file_path} not found"
|
||||
log(error_msg)
|
||||
|
||||
# Check if the webview-ui directory exists
|
||||
if not os.path.exists('webview-ui'):
|
||||
log("ERROR: webview-ui directory not found")
|
||||
else:
|
||||
# List webview-ui directory contents for debugging
|
||||
log("webview-ui directory contents:")
|
||||
try:
|
||||
dir_contents = list_directory('webview-ui')
|
||||
for name, size in dir_contents:
|
||||
log(f" {name} - {size}")
|
||||
except Exception as e:
|
||||
log(f"Error listing directory: {e}")
|
||||
|
||||
sys.exit(1) # Exit with error code to fail the workflow
|
||||
|
||||
web_cov = extract_webview_coverage_from_file(web_file_path)
|
||||
log(f"PR webview coverage from artifact: {web_cov}%")
|
||||
|
||||
return ext_cov, web_cov
|
||||
|
||||
def process_coverage_workflow(args):
|
||||
"""
|
||||
Process the entire coverage workflow.
|
||||
|
||||
Args:
|
||||
args: Command line arguments
|
||||
"""
|
||||
# Initialize all variables at the start
|
||||
pr_ext_cov = 0.0
|
||||
pr_web_cov = 0.0
|
||||
base_ext_cov = 0.0
|
||||
base_web_cov = 0.0
|
||||
ext_decreased = False
|
||||
ext_diff = 0.0
|
||||
web_decreased = False
|
||||
web_diff = 0.0
|
||||
|
||||
try:
|
||||
# Validate branch name
|
||||
if not is_valid_branch_name(args.base_branch):
|
||||
raise ValueError(f"Invalid base branch name: {args.base_branch}")
|
||||
|
||||
# Check if we're running in GitHub Actions
|
||||
is_github_actions = 'GITHUB_ACTIONS' in os.environ
|
||||
if is_github_actions:
|
||||
log("Running in GitHub Actions environment")
|
||||
|
||||
# Extract PR branch coverage from artifacts (from test job)
|
||||
pr_ext_cov, pr_web_cov = extract_pr_coverage_from_artifacts()
|
||||
|
||||
# Verify PR coverage values
|
||||
if pr_ext_cov == 0.0:
|
||||
log("WARNING: PR extension coverage is 0.0, this may indicate an issue with the coverage report")
|
||||
find_potential_coverage_files()
|
||||
|
||||
if pr_web_cov == 0.0:
|
||||
log("WARNING: PR webview coverage is 0.0, this may indicate an issue with the coverage report")
|
||||
find_potential_coverage_files()
|
||||
|
||||
# Run base branch coverage
|
||||
log(f"=== Running base branch coverage for {args.base_branch} ===")
|
||||
base_ext_cov, base_web_cov = run_branch_coverage(args.base_branch)
|
||||
|
||||
# Verify base coverage values
|
||||
if base_ext_cov == 0.0:
|
||||
log("WARNING: Base extension coverage is 0.0, this may indicate an issue with the coverage report")
|
||||
|
||||
if base_web_cov == 0.0:
|
||||
log("WARNING: Base webview coverage is 0.0, this may indicate an issue with the coverage report")
|
||||
|
||||
# Compare coverage
|
||||
log("=== Comparing extension coverage ===")
|
||||
ext_decreased, ext_diff = compare_coverage(base_ext_cov, pr_ext_cov)
|
||||
|
||||
log("=== Comparing webview coverage ===")
|
||||
web_decreased, web_diff = compare_coverage(base_web_cov, pr_web_cov)
|
||||
|
||||
# Print summary of coverage values
|
||||
log("\n=== Coverage Summary ===")
|
||||
log(f"PR extension coverage: {pr_ext_cov}%")
|
||||
log(f"Base extension coverage: {base_ext_cov}%")
|
||||
log(f"Extension coverage change: {'+' if not ext_decreased else '-'}{ext_diff}%")
|
||||
log(f"PR webview coverage: {pr_web_cov}%")
|
||||
log(f"Base webview coverage: {base_web_cov}%")
|
||||
log(f"Webview coverage change: {'+' if not web_decreased else '-'}{web_diff}%")
|
||||
|
||||
# Generate and output warnings
|
||||
warnings = generate_warnings(
|
||||
base_ext_cov, pr_ext_cov, ext_decreased, ext_diff,
|
||||
base_web_cov, pr_web_cov, web_decreased, web_diff
|
||||
)
|
||||
output_warnings(warnings)
|
||||
|
||||
# Generate comment
|
||||
log("=== Generating comment ===")
|
||||
comment = generate_comment(
|
||||
base_ext_cov, pr_ext_cov, str(ext_decreased).lower(), ext_diff,
|
||||
base_web_cov, pr_web_cov, str(web_decreased).lower(), web_diff
|
||||
)
|
||||
|
||||
# Save comment to file
|
||||
with open("coverage_comment.md", "w") as f:
|
||||
f.write(comment)
|
||||
|
||||
# Post comment if PR number is provided
|
||||
if args.pr_number:
|
||||
log(f"=== Posting comment to PR #{args.pr_number} ===")
|
||||
post_comment("coverage_comment.md", args.pr_number, args.repo, args.token)
|
||||
|
||||
# Output results for GitHub Actions
|
||||
output_github_results(
|
||||
pr_ext_cov, pr_web_cov, base_ext_cov, base_web_cov,
|
||||
ext_decreased, ext_diff, web_decreased, web_diff
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
log(f"ERROR in process_coverage_workflow: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
# Try to output results even if there was an error
|
||||
try:
|
||||
output_github_results(
|
||||
pr_ext_cov, pr_web_cov, base_ext_cov, base_web_cov,
|
||||
ext_decreased, ext_diff, web_decreased, web_diff
|
||||
)
|
||||
except Exception as e2:
|
||||
log(f"ERROR outputting GitHub results: {e2}")
|
||||
@@ -22,6 +22,7 @@ Environment Variables:
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
CHANGELOG_PATH = os.environ.get("CHANGELOG_PATH", "CHANGELOG.md")
|
||||
VERSION = os.environ['VERSION']
|
||||
@@ -31,49 +32,72 @@ NEW_CONTENT = os.environ.get("NEW_CONTENT", "")
|
||||
def overwrite_changelog_section(changelog_text: str, new_content: str):
|
||||
# Find the section for the specified version
|
||||
version_pattern = f"## {VERSION}\n"
|
||||
unformmatted_prev_version_pattern = f"## {PREV_VERSION}\n"
|
||||
bracketed_version_pattern = f"## [{VERSION}]\n"
|
||||
prev_version_pattern = f"## [{PREV_VERSION}]\n"
|
||||
print(f"latest version: {VERSION}")
|
||||
print(f"prev_version: {PREV_VERSION}")
|
||||
|
||||
notes_start_index = changelog_text.find(version_pattern) + len(version_pattern)
|
||||
notes_end_index = changelog_text.find(prev_version_pattern, notes_start_index) if PREV_VERSION and (prev_version_pattern in changelog_text or unformmatted_prev_version_pattern in changelog_text) else len(changelog_text)
|
||||
# Try both unbracketed and bracketed version patterns
|
||||
version_index = changelog_text.find(version_pattern)
|
||||
if version_index == -1:
|
||||
version_index = changelog_text.find(bracketed_version_pattern)
|
||||
if version_index == -1:
|
||||
# If version not found, add it at the top (after the first line)
|
||||
first_newline = changelog_text.find('\n')
|
||||
if first_newline == -1:
|
||||
# If no newline found, just prepend
|
||||
return f"## [{VERSION}]\n\n{changelog_text}"
|
||||
return f"{changelog_text[:first_newline + 1]}## [{VERSION}]\n\n{changelog_text[first_newline + 1:]}"
|
||||
else:
|
||||
# Using bracketed version
|
||||
version_pattern = bracketed_version_pattern
|
||||
|
||||
notes_start_index = version_index + len(version_pattern)
|
||||
notes_end_index = changelog_text.find(prev_version_pattern, notes_start_index) if PREV_VERSION and prev_version_pattern in changelog_text else len(changelog_text)
|
||||
|
||||
if new_content:
|
||||
return changelog_text[:notes_start_index] + f"{new_content}\n" + changelog_text[notes_end_index:]
|
||||
else:
|
||||
changeset_lines = changelog_text[notes_start_index:notes_end_index].split("\n")
|
||||
filtered_lines = []
|
||||
for line in changeset_lines:
|
||||
# If the previous line is a changeset format
|
||||
if len(filtered_lines) > 1 and filtered_lines[-1].startswith("### "):
|
||||
# Remove the last two lines from the filted_lines
|
||||
filtered_lines.pop()
|
||||
filtered_lines.pop()
|
||||
else:
|
||||
filtered_lines.append(line.strip())
|
||||
|
||||
# Prepend a new line to the first line of filtered_lines
|
||||
if filtered_lines:
|
||||
filtered_lines[0] = "\n" + filtered_lines[0]
|
||||
|
||||
# Print filted_lines wiht a "\n" at the end of each line
|
||||
for line in filtered_lines:
|
||||
print(line.strip())
|
||||
|
||||
parsed_lines = "\n".join(line for line in filtered_lines)
|
||||
# Ensure we have at least 2 lines before removing them
|
||||
if len(changeset_lines) < 2:
|
||||
print("Warning: Changeset content has fewer than 2 lines")
|
||||
parsed_lines = "\n".join(changeset_lines)
|
||||
else:
|
||||
# Remove the first two lines from the regular changeset format, ex: \n### Patch Changes
|
||||
parsed_lines = "\n".join(changeset_lines[2:])
|
||||
updated_changelog = changelog_text[:notes_start_index] + parsed_lines + changelog_text[notes_end_index:]
|
||||
# Ensure version number is bracketed
|
||||
updated_changelog = updated_changelog.replace(f"## {VERSION}", f"## [{VERSION}]")
|
||||
return updated_changelog
|
||||
|
||||
with open(CHANGELOG_PATH, 'r') as f:
|
||||
changelog_content = f.read()
|
||||
try:
|
||||
print(f"Reading changelog from: {CHANGELOG_PATH}")
|
||||
with open(CHANGELOG_PATH, 'r') as f:
|
||||
changelog_content = f.read()
|
||||
|
||||
new_changelog = overwrite_changelog_section(changelog_content, NEW_CONTENT)
|
||||
# print("----------------------------------------------------------------------------------")
|
||||
# print(new_changelog)
|
||||
# print("----------------------------------------------------------------------------------")
|
||||
# Write back to CHANGELOG.md
|
||||
with open(CHANGELOG_PATH, 'w') as f:
|
||||
f.write(new_changelog)
|
||||
print(f"Changelog content length: {len(changelog_content)} characters")
|
||||
print("First 200 characters of changelog:")
|
||||
print(changelog_content[:200])
|
||||
print("----------------------------------------------------------------------------------")
|
||||
|
||||
print(f"{CHANGELOG_PATH} updated successfully!")
|
||||
new_changelog = overwrite_changelog_section(changelog_content, NEW_CONTENT)
|
||||
|
||||
print("New changelog content:")
|
||||
print("----------------------------------------------------------------------------------")
|
||||
print(new_changelog)
|
||||
print("----------------------------------------------------------------------------------")
|
||||
|
||||
print(f"Writing updated changelog back to: {CHANGELOG_PATH}")
|
||||
with open(CHANGELOG_PATH, 'w') as f:
|
||||
f.write(new_changelog)
|
||||
|
||||
print(f"{CHANGELOG_PATH} updated successfully!")
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: Changelog file not found at {CHANGELOG_PATH}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error updating changelog: {str(e)}")
|
||||
print(f"Current working directory: {os.getcwd()}")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Tests for coverage_check script.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import subprocess
|
||||
import tempfile
|
||||
from unittest.mock import patch, MagicMock, call, mock_open
|
||||
|
||||
# Add parent directory to path so we can import coverage modules
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
from coverage_check import extract_coverage, compare_coverage, set_verbose, generate_comment, post_comment, set_github_output
|
||||
from coverage_check.util import log, file_exists, get_file_size, list_directory
|
||||
|
||||
|
||||
class TestCoverage(unittest.TestCase):
|
||||
# Class variables to store coverage files
|
||||
temp_dir = None
|
||||
extension_coverage_file = None
|
||||
webview_coverage_file = None
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Set up test environment once for all tests."""
|
||||
# Create temporary directory for test files
|
||||
cls.temp_dir = tempfile.TemporaryDirectory()
|
||||
cls.extension_coverage_file = os.path.join(cls.temp_dir.name, 'extension_coverage.txt')
|
||||
cls.webview_coverage_file = os.path.join(cls.temp_dir.name, 'webview_coverage.txt')
|
||||
|
||||
# Run actual tests to generate coverage reports
|
||||
cls.generate_coverage_reports()
|
||||
|
||||
# Verify files exist and are not empty
|
||||
assert os.path.exists(cls.extension_coverage_file), \
|
||||
f"Extension coverage file {cls.extension_coverage_file} does not exist"
|
||||
assert os.path.getsize(cls.extension_coverage_file) > 0, \
|
||||
f"Extension coverage file {cls.extension_coverage_file} is empty"
|
||||
assert os.path.exists(cls.webview_coverage_file), \
|
||||
f"Webview coverage file {cls.webview_coverage_file} does not exist"
|
||||
assert os.path.getsize(cls.webview_coverage_file) > 0, \
|
||||
f"Webview coverage file {cls.webview_coverage_file} is empty"
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
"""Clean up test environment after all tests."""
|
||||
if cls.temp_dir:
|
||||
cls.temp_dir.cleanup()
|
||||
|
||||
@classmethod
|
||||
def generate_coverage_reports(cls):
|
||||
"""Generate real coverage reports by running tests."""
|
||||
log("Generating coverage reports (this may take a while)...")
|
||||
|
||||
# Run extension tests with coverage
|
||||
try:
|
||||
# Get absolute paths
|
||||
root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))
|
||||
webview_dir = os.path.join(root_dir, 'webview-ui')
|
||||
|
||||
# Use xvfb-run on Linux
|
||||
if sys.platform.startswith('linux'):
|
||||
cmd = f"cd {root_dir} && xvfb-run -a npm run test:coverage > {cls.extension_coverage_file} 2>&1"
|
||||
else:
|
||||
cmd = f"cd {root_dir} && npm run test:coverage > {cls.extension_coverage_file} 2>&1"
|
||||
|
||||
log("Running extension tests...")
|
||||
log(f"Command: {cmd}")
|
||||
result = subprocess.run(cmd, shell=True, check=False, capture_output=True, text=True)
|
||||
log(f"Extension tests exit code: {result.returncode}")
|
||||
|
||||
# Run webview tests with coverage
|
||||
log("Running webview tests...")
|
||||
cmd = f"cd {webview_dir} && npm run test:coverage > {cls.webview_coverage_file} 2>&1"
|
||||
log(f"Command: {cmd}")
|
||||
result = subprocess.run(cmd, shell=True, check=False, capture_output=True, text=True)
|
||||
log(f"Webview tests exit code: {result.returncode}")
|
||||
|
||||
# Verify files were created
|
||||
if file_exists(cls.extension_coverage_file):
|
||||
ext_size = get_file_size(cls.extension_coverage_file)
|
||||
log(f"Extension coverage file created: {cls.extension_coverage_file} (size: {ext_size} bytes)")
|
||||
else:
|
||||
log(f"WARNING: Extension coverage file was not created: {cls.extension_coverage_file}")
|
||||
|
||||
if file_exists(cls.webview_coverage_file):
|
||||
web_size = get_file_size(cls.webview_coverage_file)
|
||||
log(f"Webview coverage file created: {cls.webview_coverage_file} (size: {web_size} bytes)")
|
||||
else:
|
||||
log(f"WARNING: Webview coverage file was not created: {cls.webview_coverage_file}")
|
||||
|
||||
log("Coverage reports generation completed.")
|
||||
except Exception as e:
|
||||
log(f"Error generating coverage reports: {e}")
|
||||
import traceback
|
||||
log(traceback.format_exc())
|
||||
|
||||
# Create empty files if tests fail
|
||||
log("Creating fallback coverage files...")
|
||||
with open(cls.extension_coverage_file, 'w') as f:
|
||||
f.write("No coverage data available")
|
||||
with open(cls.webview_coverage_file, 'w') as f:
|
||||
f.write("No coverage data available")
|
||||
|
||||
def test_extract_coverage(self):
|
||||
"""Test extract_coverage function with both extension and webview coverage."""
|
||||
# Check if verbose mode is enabled
|
||||
if '-v' in sys.argv or '--verbose' in sys.argv:
|
||||
set_verbose(True)
|
||||
|
||||
# Verify files exist before testing
|
||||
self.assertTrue(file_exists(self.extension_coverage_file),
|
||||
f"Extension coverage file does not exist: {self.extension_coverage_file}")
|
||||
self.assertTrue(file_exists(self.webview_coverage_file),
|
||||
f"Webview coverage file does not exist: {self.webview_coverage_file}")
|
||||
|
||||
# Log file sizes
|
||||
ext_size = get_file_size(self.extension_coverage_file)
|
||||
web_size = get_file_size(self.webview_coverage_file)
|
||||
log(f"Extension coverage file size: {ext_size} bytes")
|
||||
log(f"Webview coverage file size: {web_size} bytes")
|
||||
|
||||
# Test extension coverage
|
||||
log("Testing extension coverage extraction...")
|
||||
ext_coverage_pct = extract_coverage(self.extension_coverage_file, 'extension')
|
||||
|
||||
# Check that coverage percentage is a float
|
||||
self.assertIsInstance(ext_coverage_pct, float)
|
||||
|
||||
# Check that coverage percentage is between 0 and 100
|
||||
self.assertGreaterEqual(ext_coverage_pct, 0)
|
||||
self.assertLessEqual(ext_coverage_pct, 100)
|
||||
|
||||
# Log coverage percentage for debugging
|
||||
log(f"Extension coverage: {ext_coverage_pct}%")
|
||||
|
||||
# Test webview coverage
|
||||
log("Testing webview coverage extraction...")
|
||||
web_coverage_pct = extract_coverage(self.webview_coverage_file, 'webview')
|
||||
|
||||
# Convert to float if it's an integer
|
||||
if isinstance(web_coverage_pct, int):
|
||||
web_coverage_pct = float(web_coverage_pct)
|
||||
|
||||
# Check that coverage percentage is a float
|
||||
self.assertIsInstance(web_coverage_pct, float)
|
||||
|
||||
# Check that coverage percentage is between 0 and 100
|
||||
self.assertGreaterEqual(web_coverage_pct, 0)
|
||||
self.assertLessEqual(web_coverage_pct, 100)
|
||||
|
||||
# Log coverage percentage for debugging
|
||||
log(f"Webview coverage: {web_coverage_pct}%")
|
||||
|
||||
def test_compare_coverage(self):
|
||||
"""Test compare_coverage function."""
|
||||
# Test with coverage increase
|
||||
decreased, diff = compare_coverage(80, 90)
|
||||
self.assertFalse(decreased)
|
||||
self.assertEqual(diff, 10)
|
||||
|
||||
# Test with coverage decrease
|
||||
decreased, diff = compare_coverage(90, 80)
|
||||
self.assertTrue(decreased)
|
||||
self.assertEqual(diff, 10)
|
||||
|
||||
# Test with no change
|
||||
decreased, diff = compare_coverage(80, 80)
|
||||
self.assertFalse(decreased)
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_generate_comment(self):
|
||||
"""Test generate_comment function."""
|
||||
comment = generate_comment(
|
||||
80, 90, 'false', 10,
|
||||
70, 75, 'false', 5
|
||||
)
|
||||
|
||||
# Check that comment contains expected sections
|
||||
self.assertIn('Coverage Report', comment)
|
||||
self.assertIn('Extension Coverage', comment)
|
||||
self.assertIn('Webview Coverage', comment)
|
||||
self.assertIn('Overall Assessment', comment)
|
||||
|
||||
# Check that comment contains coverage percentages
|
||||
self.assertIn('Base branch: 80%', comment)
|
||||
self.assertIn('PR branch: 90%', comment)
|
||||
self.assertIn('Base branch: 70%', comment)
|
||||
self.assertIn('PR branch: 75%', comment)
|
||||
|
||||
# Check that comment contains correct assessment
|
||||
self.assertIn('Coverage increased or remained the same', comment)
|
||||
self.assertIn('Test coverage has been maintained or improved', comment)
|
||||
|
||||
@patch('coverage_check.requests.get')
|
||||
@patch('coverage_check.requests.post')
|
||||
@patch('coverage_check.requests.patch')
|
||||
def test_post_comment_new(self, mock_patch, mock_post, mock_get):
|
||||
"""Test post_comment function when creating a new comment."""
|
||||
# Create a temporary comment file
|
||||
comment_file = os.path.join(self.temp_dir.name, 'comment.md')
|
||||
with open(comment_file, 'w') as f:
|
||||
f.write('<!-- COVERAGE_REPORT -->\nTest comment')
|
||||
|
||||
# Mock the API responses
|
||||
mock_get.return_value = MagicMock(status_code=200, json=lambda: [])
|
||||
mock_post.return_value = MagicMock(status_code=201)
|
||||
|
||||
# Test post_comment function
|
||||
post_comment(comment_file, '123', 'owner/repo', 'token')
|
||||
|
||||
# Check that the correct API calls were made
|
||||
mock_get.assert_called_once()
|
||||
mock_post.assert_called_once()
|
||||
mock_patch.assert_not_called()
|
||||
|
||||
@patch('coverage_check.requests.get')
|
||||
@patch('coverage_check.requests.post')
|
||||
@patch('coverage_check.requests.patch')
|
||||
def test_post_comment_update(self, mock_patch, mock_post, mock_get):
|
||||
"""Test post_comment function when updating an existing comment."""
|
||||
# Create a temporary comment file
|
||||
comment_file = os.path.join(self.temp_dir.name, 'comment.md')
|
||||
with open(comment_file, 'w') as f:
|
||||
f.write('<!-- COVERAGE_REPORT -->\nTest comment')
|
||||
|
||||
# Mock the API responses
|
||||
mock_get.return_value = MagicMock(
|
||||
status_code=200,
|
||||
json=lambda: [{'id': 456, 'body': '<!-- COVERAGE_REPORT -->\nOld comment'}]
|
||||
)
|
||||
mock_patch.return_value = MagicMock(status_code=200)
|
||||
|
||||
# Test post_comment function
|
||||
post_comment(comment_file, '123', 'owner/repo', 'token')
|
||||
|
||||
# Check that the correct API calls were made
|
||||
mock_get.assert_called_once()
|
||||
mock_patch.assert_called_once()
|
||||
mock_post.assert_not_called()
|
||||
|
||||
def test_set_github_output(self):
|
||||
"""Test set_github_output function."""
|
||||
# Capture stdout
|
||||
with patch('sys.stdout', new=MagicMock()) as mock_stdout:
|
||||
# Mock environment without GITHUB_OUTPUT
|
||||
with patch.dict('os.environ', {}, clear=True):
|
||||
set_github_output('test_name', 'test_value')
|
||||
|
||||
# Check that the correct output was printed to stdout
|
||||
mock_stdout.assert_has_calls([
|
||||
# GitHub Actions output format (deprecated method)
|
||||
call.write('::set-output name=test_name::test_value\n'),
|
||||
call.flush(),
|
||||
# Human readable format
|
||||
call.write('test_name: test_value\n'),
|
||||
call.flush()
|
||||
], any_order=False)
|
||||
|
||||
# Reset mock for next test
|
||||
mock_stdout.reset_mock()
|
||||
|
||||
# Test with GITHUB_OUTPUT environment variable
|
||||
with patch.dict('os.environ', {'GITHUB_OUTPUT': '/tmp/github_output'}), \
|
||||
patch('builtins.open', mock_open()) as mock_file:
|
||||
set_github_output('test_name', 'test_value')
|
||||
|
||||
# Check that file was written to
|
||||
mock_file.assert_called_once_with('/tmp/github_output', 'a')
|
||||
mock_file().write.assert_called_once_with('test_name=test_value\n')
|
||||
|
||||
# Check that human readable output was printed
|
||||
mock_stdout.assert_has_calls([
|
||||
call.write('test_name: test_value\n'),
|
||||
call.flush()
|
||||
], any_order=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,113 +0,0 @@
|
||||
name: Changeset Converter
|
||||
run-name: Changeset Conversion
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
env:
|
||||
REPO_PATH: ${{ github.repository }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
|
||||
NODE_VERSION: 20.18.1
|
||||
|
||||
jobs:
|
||||
# Job 1: Create version bump PR when changesets are merged to main
|
||||
changeset-pr-version-bump:
|
||||
if: |
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.merged == true &&
|
||||
github.event.pull_request.base.ref == 'main' &&
|
||||
github.actor != 'github-actions'
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check user for team affiliation
|
||||
id: team_check
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: morfien101/actions-authorized-user@4a3cfbf0bcb3cafe4a71710a278920c5d94bb38b
|
||||
with:
|
||||
username: ${{ github.actor }}
|
||||
org: ${{ github.repository_owner }}
|
||||
team: "deployer"
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check if user is authorized
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |
|
||||
if [ "${{ steps.team_check.outputs.authorized }}" != "true" ]; then
|
||||
echo "User is not authorized to run this workflow."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Git Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ env.GIT_REF }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install changeset
|
||||
|
||||
# Check if there are any new changesets to process
|
||||
- name: Check for changesets
|
||||
id: check-changesets
|
||||
run: |
|
||||
NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ')
|
||||
echo "Changesets diff with previous version: $NEW_CHANGESETS"
|
||||
echo "new_changesets=$NEW_CHANGESETS" >> $GITHUB_OUTPUT
|
||||
|
||||
# Create version bump PR using changesets/action if there are new changesets
|
||||
- name: Create Changeset Pull Request
|
||||
if: steps.check-changesets.outputs.new_changesets != '0'
|
||||
uses: changesets/action@v1
|
||||
with:
|
||||
commit: "changeset version bump"
|
||||
title: "Changeset version bump"
|
||||
version: npm run version-packages # This performs the changeset version bump
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Get current and previous versions to edit changelog entry
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
VERSION=$(git show HEAD:package.json | jq -r '.version')
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
PREV_VERSION=$(git show origin/main:package.json | jq -r '.version')
|
||||
echo "prev_version=$PREV_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION"
|
||||
echo "prev_version=$PREV_VERSION"
|
||||
|
||||
# Update CHANGELOG.md with proper format
|
||||
- name: Update Changelog Format
|
||||
env:
|
||||
VERSION: ${{ steps.get_version.outputs.version }}
|
||||
PREV_VERSION: ${{ steps.get_version.outputs.prev_version }}
|
||||
run: python .github/scripts/overwrite_changeset_changelog.py
|
||||
|
||||
# Commit and push changelog updates
|
||||
- name: Push Changelog updates to Pull Request
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email github-actions@github.com
|
||||
echo "Running git add and commit..."
|
||||
git add CHANGELOG.md
|
||||
git commit -m "Updating CHANGELOG.md format"
|
||||
git status
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo "Pushing to remote..."
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
git push origin $CURRENT_BRANCH
|
||||
@@ -0,0 +1,162 @@
|
||||
name: Changeset Release
|
||||
run-name: Changeset Release ${{ github.actor != 'cline-bot' && '- Create PR' || '- Update Changelog' }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [closed, opened, labeled]
|
||||
|
||||
env:
|
||||
REPO_PATH: ${{ github.repository }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
|
||||
|
||||
jobs:
|
||||
# Job 1: Create version bump PR when changesets are merged to main
|
||||
changeset-pr-version-bump:
|
||||
if: >
|
||||
( github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.merged == true &&
|
||||
github.event.pull_request.base.ref == 'main' &&
|
||||
github.actor != 'cline-bot' ) ||
|
||||
github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Git Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ env.GIT_REF }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm run install:all
|
||||
|
||||
# Check if there are any new changesets to process
|
||||
- name: Check for changesets
|
||||
id: check-changesets
|
||||
run: |
|
||||
NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ')
|
||||
echo "Changesets diff with previous version: $NEW_CHANGESETS"
|
||||
echo "new_changesets=$NEW_CHANGESETS" >> $GITHUB_OUTPUT
|
||||
|
||||
# Create version bump PR using changesets/action if there are new changesets
|
||||
- name: Changeset Pull Request
|
||||
if: steps.check-changesets.outputs.new_changesets != '0'
|
||||
id: changesets
|
||||
uses: changesets/action@e9cc34b540dd3ad1b030c57fd97269e8f6ad905a # v1
|
||||
with:
|
||||
commit: "changeset version bump"
|
||||
title: "Changeset version bump"
|
||||
version: npm run version-packages # This performs the changeset version bump
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Job 2: Process version bump PR created by cline-bot
|
||||
changeset-pr-edit-approve:
|
||||
name: Auto approve and merge Bump version PRs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
if: >
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.base.ref == 'main' &&
|
||||
github.actor == 'cline-bot' &&
|
||||
contains(github.event.pull_request.title, 'Changeset version bump')
|
||||
steps:
|
||||
- name: Determine checkout ref
|
||||
id: checkout-ref
|
||||
run: |
|
||||
echo "Event action: ${{ github.event.action }}"
|
||||
echo "Actor: ${{ github.actor }}"
|
||||
echo "Head ref: ${{ github.head_ref }}"
|
||||
echo "PR SHA: ${{ github.event.pull_request.head.sha }}"
|
||||
|
||||
if [[ "${{ github.event.action }}" == "opened" && "${{ github.actor }}" == "cline-bot" ]]; then
|
||||
echo "Using branch ref: ${{ github.head_ref }}"
|
||||
echo "git_ref=${{ github.head_ref }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Using SHA ref: ${{ github.event.pull_request.head.sha }}"
|
||||
echo "git_ref=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
ref: ${{ steps.checkout-ref.outputs.git_ref }}
|
||||
|
||||
# Get current and previous versions to edit changelog entry
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
VERSION=$(git show HEAD:package.json | jq -r '.version')
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
PREV_VERSION=$(git show origin/main:package.json | jq -r '.version')
|
||||
echo "prev_version=$PREV_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION"
|
||||
echo "prev_version=$PREV_VERSION"
|
||||
|
||||
# Update CHANGELOG.md with proper format
|
||||
- name: Update Changelog Format
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }}
|
||||
env:
|
||||
VERSION: ${{ steps.get_version.outputs.version }}
|
||||
PREV_VERSION: ${{ steps.get_version.outputs.prev_version }}
|
||||
run: python .github/scripts/overwrite_changeset_changelog.py
|
||||
|
||||
# Commit and push changelog updates
|
||||
- name: Push Changelog updates
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }}
|
||||
run: |
|
||||
git config user.name "cline-bot"
|
||||
git config user.email github-actions@github.com
|
||||
echo "Running git add and commit..."
|
||||
git add CHANGELOG.md
|
||||
git commit -m "Updating CHANGELOG.md format"
|
||||
git status
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo "Pushing to remote..."
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
git push
|
||||
|
||||
# Add label to indicate changelog has been formatted
|
||||
- name: Add changelog-ready label
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }}
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['changelog-ready']
|
||||
});
|
||||
|
||||
# Auto-approve PR only after it has been labeled
|
||||
- name: Auto approve PR
|
||||
if: contains(github.event.pull_request.labels.*.name, 'changelog-ready')
|
||||
uses: hmarr/auto-approve-action@de8bf34d0402c38aa2c8346973342b2cb02c4435 # v4
|
||||
with:
|
||||
review-message: "I'm approving since it's a bump version PR"
|
||||
|
||||
# Auto-merge PR
|
||||
- name: Automerge on PR
|
||||
if: false # Needs enablePullRequestAutoMerge in repo settings to work contains(github.event.pull_request.labels.*.name, 'changelog-ready')
|
||||
run: gh pr merge --auto --merge ${{ github.event.pull_request.number }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,117 @@
|
||||
name: Check Changeset
|
||||
run-name: Check for Changeset in PR
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
check-changeset:
|
||||
# Skip draft PRs and dependabot PRs
|
||||
if: github.event.pull_request.draft == false && github.actor != 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Check for changeset
|
||||
id: check-changeset
|
||||
run: |
|
||||
# Debug info
|
||||
echo "Current directory: $(pwd)"
|
||||
echo "PR Base Ref: ${{ github.event.pull_request.base.ref }}"
|
||||
echo "PR Head Ref: ${{ github.event.pull_request.head.ref }}"
|
||||
echo "PR Head SHA: ${{ github.event.pull_request.head.sha }}"
|
||||
echo "Git status:"
|
||||
git status
|
||||
|
||||
# Get list of changed files
|
||||
git fetch origin ${{ github.event.pull_request.base.ref }}
|
||||
CHANGED_FILES=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }} HEAD)
|
||||
echo "Changed files:"
|
||||
echo "$CHANGED_FILES"
|
||||
|
||||
# Check if any of the changed files are in docs/ or .github/
|
||||
echo "Checking if changes are docs-only..."
|
||||
DOCS_ONLY=true
|
||||
while IFS= read -r file; do
|
||||
if [[ ! "$file" =~ ^(docs/|.github/) ]]; then
|
||||
echo "Found non-docs change: $file"
|
||||
DOCS_ONLY=false
|
||||
break
|
||||
fi
|
||||
done <<< "$CHANGED_FILES"
|
||||
|
||||
# If changes are docs-only, skip changeset check
|
||||
if [ "$DOCS_ONLY" = true ]; then
|
||||
echo "All changes are in docs/ or .github/, skipping changeset check"
|
||||
exit 0
|
||||
else
|
||||
echo "Changes include non-docs files, checking for changeset..."
|
||||
fi
|
||||
|
||||
# Check if any changeset files are in the changed files
|
||||
echo "Checking for changeset files in changed files..."
|
||||
CHANGESET_IN_PR=false
|
||||
while IFS= read -r file; do
|
||||
if [[ "$file" =~ ^\.changeset/.*\.md$ && "$file" != ".changeset/README.md" && "$file" != ".changeset/config.json" ]]; then
|
||||
echo "Found changeset file in PR: $file"
|
||||
CHANGESET_IN_PR=true
|
||||
break
|
||||
fi
|
||||
done <<< "$CHANGED_FILES"
|
||||
|
||||
if [ "$CHANGESET_IN_PR" = false ]; then
|
||||
echo "No changeset files found in changed files. Changed files in .changeset/:"
|
||||
echo "$CHANGED_FILES" | grep "^\.changeset/" || true
|
||||
echo "::error::No changeset file found in PR changes. Please run 'npm run changeset' to create one."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Comment on PR
|
||||
if: failure()
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
with:
|
||||
script: |
|
||||
const message = `This PR requires a changeset since it includes user-facing changes. Please:
|
||||
|
||||
1. Run \`npm run changeset\` locally
|
||||
2. Choose the appropriate version bump:
|
||||
- \`major\` for breaking changes (1.0.0 → 2.0.0)
|
||||
- \`minor\` for new features (1.0.0 → 1.1.0)
|
||||
- \`patch\` for bug fixes (1.0.0 → 1.0.1)
|
||||
3. Write a clear description of your changes
|
||||
4. Commit the generated changeset file
|
||||
|
||||
Note: Documentation-only changes do not require a changeset.`;
|
||||
|
||||
// Get existing comments
|
||||
const comments = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number
|
||||
});
|
||||
|
||||
// Check if we already commented
|
||||
const botComment = comments.data.find(comment =>
|
||||
comment.user.login === 'github-actions[bot]' &&
|
||||
comment.body.includes('This PR requires a changeset')
|
||||
);
|
||||
|
||||
if (!botComment) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: message
|
||||
});
|
||||
}
|
||||
@@ -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/
|
||||
@@ -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,13 +30,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.tag }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
node-version: 20.15.1
|
||||
|
||||
# Cache root dependencies - only reuse if package-lock.json exactly matches
|
||||
- name: Cache root dependencies
|
||||
@@ -60,14 +54,14 @@ jobs:
|
||||
|
||||
- name: Install root dependencies
|
||||
if: steps.root-cache.outputs.cache-hit != 'true'
|
||||
run: npm ci --include=optional
|
||||
run: npm ci
|
||||
|
||||
- name: Install webview-ui dependencies
|
||||
if: steps.webview-cache.outputs.cache-hit != 'true'
|
||||
run: cd webview-ui && npm ci --include=optional
|
||||
run: cd webview-ui && npm ci
|
||||
|
||||
- name: Install Publishing Tools
|
||||
run: npm install -g @vscode/vsce ovsx
|
||||
run: npm install -g vsce ovsx
|
||||
|
||||
- name: Get Version
|
||||
id: get_version
|
||||
@@ -75,29 +69,22 @@ 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 --allow-package-secrets sendgrid --out "cline-${{ steps.get_version.outputs.version }}.vsix"
|
||||
vsce package --out "cline-${{ steps.get_version.outputs.version }}.vsix"
|
||||
|
||||
if [ "${{ github.event.inputs.release-type }}" = "pre-release" ]; then
|
||||
npm run publish:marketplace:prerelease
|
||||
@@ -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
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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
|
||||
+6
-165
@@ -15,15 +15,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os == 'ubuntu-latest' && 'test' || format('test ({0})', matrix.os) }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -31,18 +23,7 @@ jobs:
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
# Setup Python for coverage script
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install requests
|
||||
node-version: 20.15.1
|
||||
|
||||
# Cache root dependencies - only reuse if package-lock.json exactly matches
|
||||
- name: Cache root dependencies
|
||||
@@ -68,154 +49,14 @@ 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: Set up NPM on Windows
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
npm config set script-shell "C:\\Program Files\\Git\\bin\\bash.exe"
|
||||
|
||||
- name: Type Check
|
||||
run: npm run check-types
|
||||
|
||||
- name: Lint Check
|
||||
- name: ESLint Check
|
||||
run: npm run lint
|
||||
|
||||
- name: Format Check
|
||||
- name: Prettier / Format Check
|
||||
run: npm run format
|
||||
|
||||
# Build the extension before running tests
|
||||
- name: Build Tests and Extension
|
||||
run: npm run pretest
|
||||
|
||||
- name: Unit Tests
|
||||
run: npm run test:unit
|
||||
|
||||
# Run extension tests with coverage
|
||||
- name: Extension Integration Tests with Coverage
|
||||
id: extension_coverage
|
||||
continue-on-error: true
|
||||
run: |
|
||||
node ./scripts/test-ci.js 2>&1 | tee extension_coverage.txt
|
||||
# Default the encoding to UTF-8 - It's not the default on Windows
|
||||
PYTHONUTF8=1 PYTHONPATH=.github/scripts python -m coverage_check extract-coverage extension_coverage.txt --type=extension --github-output --verbose
|
||||
|
||||
# Run webview tests with coverage
|
||||
- name: Webview Tests with Coverage
|
||||
id: webview_coverage
|
||||
continue-on-error: true
|
||||
run: |
|
||||
cd webview-ui
|
||||
# Ensure coverage dependency is installed
|
||||
npm install --no-save @vitest/coverage-v8
|
||||
npm run test:coverage 2>&1 | tee webview_coverage.txt
|
||||
cd ..
|
||||
# Default the encoding to UTF-8 - It's not the default on Windows
|
||||
PYTHONUTF8=1 PYTHONPATH=.github/scripts python -m coverage_check extract-coverage webview-ui/webview_coverage.txt --type=webview --github-output --verbose
|
||||
|
||||
# Save coverage reports as artifacts (workflow-scoped)
|
||||
- name: Save Coverage Reports
|
||||
uses: actions/upload-artifact@v4
|
||||
# Only upload artifacts on Linux - We only need coverage from one OS
|
||||
if: runner.os == 'Linux'
|
||||
with:
|
||||
name: pr-coverage-reports
|
||||
path: |
|
||||
extension_coverage.txt
|
||||
webview-ui/webview_coverage.txt
|
||||
|
||||
# Set the check as failed if any of the tests failed
|
||||
- name: Check for test failures
|
||||
run: |
|
||||
# Check if any of the test steps failed
|
||||
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#steps-context
|
||||
if [ "${{ steps.extension_coverage.outcome }}" != "success" ]; then
|
||||
echo "Extension Integration Tests failed, see previous step for test output."
|
||||
fi
|
||||
if [ "${{ steps.webview_coverage.outcome }}" != "success" ]; then
|
||||
echo "Webview Tests failed, see previous step for test output."
|
||||
fi
|
||||
if [ "${{ steps.extension_coverage.outcome }}" != "success" ] || [ "${{ steps.webview_coverage.outcome }}" != "success" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
coverage:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
# Only run on PRs to main branch
|
||||
if: github.event_name == 'pull_request' && github.base_ref == 'main'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for accurate comparison
|
||||
|
||||
# Setup Python for coverage script
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install requests
|
||||
|
||||
- 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') }}
|
||||
|
||||
- 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
|
||||
|
||||
# Build the extension before running tests
|
||||
- name: Build Extension
|
||||
run: npm run compile
|
||||
|
||||
# Download coverage artifacts from test job
|
||||
- name: Download Coverage Reports
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pr-coverage-reports
|
||||
path: . # Download to root directory to match expected paths
|
||||
|
||||
# Process coverage workflow
|
||||
- name: Process coverage workflow
|
||||
id: coverage
|
||||
run: |
|
||||
# Extract PR number from GITHUB_REF
|
||||
PR_NUMBER=$(echo "$GITHUB_REF" | sed -e 's/refs\/pull\///' -e 's/\/merge//')
|
||||
|
||||
# Run the coverage workflow from root directory
|
||||
PYTHONPATH=.github/scripts python -m coverage_check process-workflow \
|
||||
--base-branch ${{ github.base_ref }} \
|
||||
--pr-number $PR_NUMBER \
|
||||
--repo $GITHUB_REPOSITORY \
|
||||
--token ${{ secrets.GITHUB_TOKEN }} \
|
||||
--verbose
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Extension Tests
|
||||
run: xvfb-run -a npm run test
|
||||
|
||||
+1
-26
@@ -1,37 +1,12 @@
|
||||
out
|
||||
dist
|
||||
dist-standalone
|
||||
node_modules
|
||||
tmp
|
||||
.vscode-test/
|
||||
*.vsix
|
||||
|
||||
.DS_Store
|
||||
.idea
|
||||
|
||||
pnpm-lock.yaml
|
||||
|
||||
.clineignore
|
||||
.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/
|
||||
!.github/scripts/coverage/
|
||||
|
||||
*evals.env
|
||||
|
||||
## Generated files ##
|
||||
src/generated/
|
||||
src/shared/proto/
|
||||
webview-ui/src/services/grpc-client.ts
|
||||
|
||||
# E2E Tests
|
||||
test-results
|
||||
|
||||
## CLI pre-release ##
|
||||
/cli
|
||||
.clineignore
|
||||
Regular → Executable
+17
-1
@@ -1 +1,17 @@
|
||||
lint-staged --no-stash
|
||||
echo "Running pre-commit checks..."
|
||||
|
||||
# Run ESLint
|
||||
echo "Running ESLint..."
|
||||
npm run lint || {
|
||||
echo "❌ ESLint check failed. Please fix the errors and try committing again."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Run Prettier
|
||||
echo "Running Prettier..."
|
||||
npm run format || {
|
||||
echo "❌ Prettier check failed. Run 'npm run format:fix' to automatically fix formatting issues."
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "✅ All checks passed!"
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"extension": [
|
||||
"ts"
|
||||
],
|
||||
"spec": [
|
||||
"src/**/__tests__/*.ts"
|
||||
],
|
||||
"require": [
|
||||
"ts-node/register",
|
||||
"source-map-support/register",
|
||||
"./src/test/requires.ts"
|
||||
],
|
||||
"recursive": true,
|
||||
"exit": true
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
dist/
|
||||
node_modules
|
||||
webview-ui/build/
|
||||
*.md
|
||||
package-lock.json
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": true,
|
||||
"printWidth": 130,
|
||||
"semi": false,
|
||||
"bracketSameLine": true
|
||||
}
|
||||
+1
-5
@@ -2,14 +2,10 @@ 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
|
||||
/** Set up alias path resolution during tests
|
||||
* @See {@link file://./test-setup.js}
|
||||
*/
|
||||
require: ["./test-setup.js"],
|
||||
},
|
||||
workspaceFolder: "test-workspace",
|
||||
version: "stable",
|
||||
|
||||
Vendored
+1
-6
@@ -1,10 +1,5 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"connor4312.esbuild-problem-matchers",
|
||||
"ms-vscode.extension-test-runner",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"biomejs.biome"
|
||||
]
|
||||
"recommendations": ["dbaeumer.vscode-eslint", "connor4312.esbuild-problem-matchers", "ms-vscode.extension-test-runner"]
|
||||
}
|
||||
|
||||
Vendored
+4
-100
@@ -6,112 +6,16 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Extension (production)",
|
||||
"name": "Run Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--disable-workspace-trust",
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
|
||||
"preLaunchTask": "${defaultBuildTask}",
|
||||
"env": {
|
||||
"IS_DEV": "true",
|
||||
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}",
|
||||
"CLINE_ENVIRONMENT": "production"
|
||||
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Run Extension (Fresh Install Mode)",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--user-data-dir=${workspaceFolder}/dist/tmp/user",
|
||||
"--profile-temp",
|
||||
"--sync=off",
|
||||
"--disable-extensions",
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "clean-tmp-user",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"postDebugTask": "stop",
|
||||
"env": {
|
||||
"IS_DEV": "true",
|
||||
"TEMP_PROFILE": "true",
|
||||
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}",
|
||||
"CLINE_ENVIRONMENT": "production"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Run cline-core service",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"resolveSourceMapLocations": [
|
||||
"${workspaceFolder}/**",
|
||||
"!**/node_modules/**"
|
||||
],
|
||||
"cwd": "${workspaceFolder}/dist-standalone",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist-standalone/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "compile-standalone",
|
||||
"env": {
|
||||
// Turns on grpc debug log.
|
||||
//"GRPC_TRACE": "all",
|
||||
//"GRPC_VERBOSITY": "DEBUG",
|
||||
"NODE_PATH": "${workspaceFolder}/dist-standalone/node_modules"
|
||||
},
|
||||
"program": "cline-core.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+2
-25
@@ -6,31 +6,8 @@
|
||||
},
|
||||
"search.exclude": {
|
||||
"out": true, // set this to false to include "out" folder in search results
|
||||
"dist": true, // set this to false to include "dist" folder in search results,
|
||||
"node_modules": true,
|
||||
"dist-standalone": true
|
||||
"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",
|
||||
"typescript.preferences.quoteStyle": "double",
|
||||
// Protobuf settings
|
||||
"protoc": {
|
||||
"options": [
|
||||
"--proto_path=proto"
|
||||
]
|
||||
},
|
||||
// Enable Lint and format using Biome
|
||||
"biome.enabled": true,
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
}
|
||||
"typescript.tsc.autoDetect": "off"
|
||||
}
|
||||
|
||||
Vendored
+13
-164
@@ -3,62 +3,17 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "compile-standalone",
|
||||
"type": "npm",
|
||||
"script": "compile-standalone",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"presentation": {
|
||||
"reveal": "always"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "npm: protos",
|
||||
"type": "npm",
|
||||
"script": "protos",
|
||||
"problemMatcher": [],
|
||||
"isBackground": false,
|
||||
"presentation": {
|
||||
"reveal": "always"
|
||||
},
|
||||
"options": {
|
||||
"env": {
|
||||
"IS_DEV": "true"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"dependsOn": [
|
||||
"npm: protos",
|
||||
"npm: build:webview",
|
||||
"npm: dev:webview",
|
||||
"npm: watch:tsc",
|
||||
"npm: watch:esbuild"
|
||||
],
|
||||
"dependsOn": ["npm: build:webview", "npm: dev:webview", "npm: watch:tsc", "npm: watch:esbuild"],
|
||||
"presentation": {
|
||||
"reveal": "always"
|
||||
"reveal": "never"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "watch:test",
|
||||
"dependsOn": [
|
||||
"npm: protos",
|
||||
"npm: build:webview:test",
|
||||
"npm: dev:webview",
|
||||
"npm: watch:tsc",
|
||||
"npm: watch:esbuild:test"
|
||||
],
|
||||
"presentation": {
|
||||
"reveal": "always"
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build:webview",
|
||||
@@ -66,12 +21,10 @@
|
||||
"problemMatcher": [],
|
||||
"isBackground": true,
|
||||
"label": "npm: build:webview",
|
||||
"dependsOn": [
|
||||
"npm: protos"
|
||||
],
|
||||
"presentation": {
|
||||
"group": "watch",
|
||||
"reveal": "always"
|
||||
"reveal": "never",
|
||||
"close": true
|
||||
},
|
||||
"options": {
|
||||
"env": {
|
||||
@@ -79,27 +32,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build:webview:test",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"isBackground": true,
|
||||
"label": "npm: build:webview:test",
|
||||
"dependsOn": [
|
||||
"npm: protos"
|
||||
],
|
||||
"presentation": {
|
||||
"group": "watch",
|
||||
"reveal": "always"
|
||||
},
|
||||
"options": {
|
||||
"env": {
|
||||
"IS_DEV": "true",
|
||||
"IS_TEST": "true"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "dev:webview",
|
||||
@@ -123,12 +55,10 @@
|
||||
],
|
||||
"isBackground": true,
|
||||
"label": "npm: dev:webview",
|
||||
"dependsOn": [
|
||||
"npm: protos"
|
||||
],
|
||||
"presentation": {
|
||||
"group": "watch",
|
||||
"reveal": "always"
|
||||
"reveal": "never",
|
||||
"close": true
|
||||
},
|
||||
"options": {
|
||||
"env": {
|
||||
@@ -140,77 +70,13 @@
|
||||
"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"
|
||||
],
|
||||
"presentation": {
|
||||
"group": "watch",
|
||||
"reveal": "always"
|
||||
},
|
||||
"options": {
|
||||
"env": {
|
||||
"IS_DEV": "true"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"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$"
|
||||
}
|
||||
},
|
||||
"isBackground": true,
|
||||
"label": "npm: watch:esbuild:test",
|
||||
"dependsOn": [
|
||||
"npm: protos"
|
||||
],
|
||||
"presentation": {
|
||||
"group": "watch",
|
||||
"reveal": "always"
|
||||
},
|
||||
"options": {
|
||||
"env": {
|
||||
"IS_DEV": "true",
|
||||
"IS_TEST": "true"
|
||||
}
|
||||
"reveal": "never",
|
||||
"close": true
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -220,12 +86,10 @@
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"label": "npm: watch:tsc",
|
||||
"dependsOn": [
|
||||
"npm: protos"
|
||||
],
|
||||
"presentation": {
|
||||
"group": "watch",
|
||||
"reveal": "always"
|
||||
"reveal": "never",
|
||||
"close": true
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -233,36 +97,21 @@
|
||||
"script": "watch-tests",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"dependsOn": [
|
||||
"npm: protos"
|
||||
],
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"reveal": "never",
|
||||
"group": "watchers"
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "tasks: watch-tests",
|
||||
"dependsOn": [
|
||||
"npm: protos",
|
||||
"npm: watch",
|
||||
"npm: watch-tests"
|
||||
],
|
||||
"dependsOn": ["npm: watch", "npm: watch-tests"],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "stop",
|
||||
"command": "echo ${input:terminate}",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"label": "clean-tmp-user",
|
||||
"type": "shell",
|
||||
"dependsOn": [
|
||||
"watch"
|
||||
],
|
||||
"command": "rm -rf ${workspaceFolder}/dist/tmp/user && mkdir -p ${workspaceFolder}/dist/tmp/user"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
|
||||
+5
-27
@@ -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,7 +32,6 @@ 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
|
||||
@@ -58,9 +41,4 @@ old_docs/**
|
||||
!src/integrations/theme/default-themes/**
|
||||
|
||||
# Include icons
|
||||
!assets/icons/**
|
||||
|
||||
# Ignore E2E build files
|
||||
e2e-build.mjs
|
||||
e2e.vsix
|
||||
test-results/
|
||||
!assets/icons/**
|
||||
+164
-994
File diff suppressed because it is too large
Load Diff
+3
-104
@@ -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,51 +29,8 @@ 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`
|
||||
- `libx11-xcb1`
|
||||
- `libxcomposite1`
|
||||
- `libxdamage1`
|
||||
- `libxfixes3`
|
||||
- `libxkbfile1`
|
||||
- `libxrandr2`
|
||||
- `xvfb`
|
||||
|
||||
These libraries provide necessary GUI components and system services for the test environment.
|
||||
|
||||
For example, on Debian-based distributions (e.g., Ubuntu), you can install these libraries using apt:
|
||||
```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
|
||||
```
|
||||
|
||||
## 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:
|
||||
@@ -147,7 +46,7 @@ Anyone can contribute code to Cline, but we ask that you follow these guidelines
|
||||
- Run `npm run lint` to check code style
|
||||
- Run `npm run format` to automatically format code
|
||||
- All PRs must pass CI checks which include both linting and formatting
|
||||
- Address any warnings or errors from linter before submitting
|
||||
- Address any ESLint warnings or errors before submitting
|
||||
- Follow TypeScript best practices and maintain type safety
|
||||
|
||||
3. **Testing**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div align="center"><sub>
|
||||
English | <a href="https://github.com/cline/cline/blob/main/locales/es/README.md" target="_blank">Español</a> | <a href="https://github.com/cline/cline/blob/main/locales/de/README.md" target="_blank">Deutsch</a> | <a href="https://github.com/cline/cline/blob/main/locales/ja/README.md" target="_blank">日本語</a> | <a href="https://github.com/cline/cline/blob/main/locales/zh-cn/README.md" target="_blank">简体中文</a> | <a href="https://github.com/cline/cline/blob/main/locales/zh-tw/README.md" target="_blank">繁體中文</a> | <a href="https://github.com/cline/cline/blob/main/locales/ko/README.md" target="_blank">한국어</a>
|
||||
English | <a href="https://github.com/cline/cline/blob/main/locales/es/README.md" target="_blank">Español</a> | <a href="https://github.com/cline/cline/blob/main/locales/de/README.md" target="_blank">Deutsch</a> | <a href="https://github.com/cline/cline/blob/main/locales/ja/README.md" target="_blank">日本語</a> | <a href="https://github.com/cline/cline/blob/main/locales/zh-cn/README.md" target="_blank">简体中文</a> | <a href="https://github.com/cline/cline/blob/main/locales/zh-tw/README.md" target="_blank">繁體中文</a>
|
||||
</sub></div>
|
||||
|
||||
# Cline – \#1 on OpenRouter
|
||||
@@ -24,7 +24,7 @@ English | <a href="https://github.com/cline/cline/blob/main/locales/es/README.md
|
||||
<a href="https://github.com/cline/cline/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop" target="_blank"><strong>Feature Requests</strong></a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://docs.cline.bot/getting-started/for-new-coders" target="_blank"><strong>Getting Started</strong></a>
|
||||
<a href="https://docs.cline.bot/getting-started/getting-started-new-coders" target="_blank"><strong>Getting Started</strong></a>
|
||||
</td>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -32,7 +32,7 @@ English | <a href="https://github.com/cline/cline/blob/main/locales/es/README.md
|
||||
|
||||
Meet Cline, an AI assistant that can use your **CLI** a**N**d **E**ditor.
|
||||
|
||||
Thanks to [Claude 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.
|
||||
Thanks to [Claude 3.5 Sonnet's agentic coding capabilities](https://www-cdn.anthropic.com/fed9cc193a14b84131812372d8d5857f8f304c52/Model_Card_Claude_3_Addendum.pdf), 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.
|
||||
|
||||
1. Enter your task and add images to convert mockups into functional apps or fix bugs with screenshots.
|
||||
2. Cline starts by analyzing your file structure & source code ASTs, running regex searches, and reading relevant files to get up to speed in existing projects. By carefully managing what information is added to context, Cline can provide valuable assistance even for large, complex projects without overwhelming the context window.
|
||||
@@ -51,7 +51,7 @@ Thanks to [Claude Sonnet's agentic coding capabilities](https://www.anthropic.c
|
||||
|
||||
### 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.
|
||||
|
||||
@@ -87,7 +87,7 @@ All changes made by Cline are recorded in your file's Timeline, providing an eas
|
||||
|
||||
### Use the Browser
|
||||
|
||||
With Claude Sonnet's new [Computer Use](https://www.anthropic.com/news/3-5-models-and-computer-use) capability, Cline can launch a browser, click elements, type text, and scroll, capturing screenshots and console logs at each step. This allows for interactive debugging, end-to-end testing, and even general web use! This gives him autonomy to fixing visual bugs and runtime issues without you needing to handhold and copy-pasting error logs yourself.
|
||||
With Claude 3.5 Sonnet's new [Computer Use](https://www.anthropic.com/news/3-5-models-and-computer-use) capability, Cline can launch a browser, click elements, type text, and scroll, capturing screenshots and console logs at each step. This allows for interactive debugging, end-to-end testing, and even general web use! This gives him autonomy to fixing visual bugs and runtime issues without you needing to handhold and copy-pasting error logs yourself.
|
||||
|
||||
Try asking Cline to "test the app", and watch as he runs a command like `npm run dev`, launches your locally running dev server in a browser, and performs a series of tests to confirm that everything works. [See a demo here.](https://x.com/sdrzn/status/1850880547825823989)
|
||||
|
||||
@@ -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)
|
||||
|
||||
-159
@@ -1,159 +0,0 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.1.4/schema.json",
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": true,
|
||||
"defaultBranch": "main"
|
||||
},
|
||||
"assist": {
|
||||
"enabled": true,
|
||||
"actions": {
|
||||
"source": {
|
||||
"organizeImports": "on",
|
||||
"useSortedAttributes": "on"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"domains": {
|
||||
"react": "recommended"
|
||||
},
|
||||
// Ideally we would want to turn on all the rules that are currently off,
|
||||
// keeping them off currently to make sure only changes on the migrations
|
||||
// are included in the initial PR before we apply the format and lint changes.
|
||||
// TODO: turn on all rules that are currently off if applicable.
|
||||
// TODO: Remove --diagnostic-level=error from CI commands.
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"correctness": {
|
||||
"useExhaustiveDependencies": "off",
|
||||
"noUndeclaredVariables": "off",
|
||||
"noEmptyPattern": "off",
|
||||
"useJsxKeyInIterable": "off",
|
||||
"noInnerDeclarations": "off",
|
||||
"useHookAtTopLevel": "off",
|
||||
"useYield": "off",
|
||||
"noConstructorReturn": "off",
|
||||
"noInvalidPositionAtImportRule": "off",
|
||||
"noSwitchDeclarations": "off",
|
||||
"noUnusedImports": "error"
|
||||
},
|
||||
"a11y": "off",
|
||||
"style": {
|
||||
"useNodejsImportProtocol": "off",
|
||||
"useImportType": "off",
|
||||
"useBlockStatements": "warn",
|
||||
"useNamingConvention": "off",
|
||||
"useThrowOnlyError": "info",
|
||||
"useConsistentArrayType": "off",
|
||||
"noParameterAssign": "off",
|
||||
"useAsConstAssertion": "off",
|
||||
"useDefaultParameterLast": "off",
|
||||
"noNonNullAssertion": "off",
|
||||
"useEnumInitializers": "off",
|
||||
"useSelfClosingElements": "off",
|
||||
"useSingleVarDeclarator": "off",
|
||||
"useNumberNamespace": "off",
|
||||
"noInferrableTypes": "off",
|
||||
"useTemplate": "off",
|
||||
"noUselessElse": "off"
|
||||
},
|
||||
"suspicious": {
|
||||
"noDoubleEquals": "warn",
|
||||
"noImplicitAnyLet": "info",
|
||||
"noThenProperty": "off",
|
||||
"noAsyncPromiseExecutor": "off",
|
||||
"noImportAssign": "off",
|
||||
"noExplicitAny": "off",
|
||||
"noControlCharactersInRegex": "off",
|
||||
"noShadowRestrictedNames": "off",
|
||||
"noArrayIndexKey": "info",
|
||||
"noAssignInExpressions": "warn"
|
||||
},
|
||||
"complexity": {
|
||||
"noUselessConstructor": "off",
|
||||
"useOptionalChain": "off",
|
||||
"noBannedTypes": "off",
|
||||
"useLiteralKeys": "off",
|
||||
"noUselessCatch": "off",
|
||||
"noUselessSwitchCase": "off",
|
||||
"noStaticOnlyClass": "off"
|
||||
},
|
||||
"security": {
|
||||
"noDangerouslySetInnerHtml": "warn"
|
||||
}
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "tab",
|
||||
"indentWidth": 4,
|
||||
"lineWidth": 130,
|
||||
"lineEnding": "lf",
|
||||
"formatWithErrors": true
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"semicolons": "asNeeded",
|
||||
"arrowParentheses": "always",
|
||||
"bracketSameLine": true,
|
||||
"bracketSpacing": true,
|
||||
"jsxQuoteStyle": "double",
|
||||
"quoteProperties": "asNeeded",
|
||||
"trailingCommas": "all"
|
||||
}
|
||||
},
|
||||
"json": {
|
||||
"formatter": {
|
||||
"trailingCommas": "none",
|
||||
"expand": "always"
|
||||
}
|
||||
},
|
||||
"files": {
|
||||
"includes": [
|
||||
"**",
|
||||
"!**/dist/**",
|
||||
"!**/dist-*/**",
|
||||
"!**/out/**",
|
||||
"!**/evals/**",
|
||||
"!**/playwright/**",
|
||||
"!**/test-results/**",
|
||||
"!**/node_modules/**",
|
||||
"!**/webview-ui/build/**",
|
||||
"!**/generated/**",
|
||||
"!**/proto/**"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
"src/dev/grit/process-env.grit"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"includes": [
|
||||
"**",
|
||||
"!**/hosts/vscode/**",
|
||||
"!**/test/**",
|
||||
"!src/extension.ts"
|
||||
],
|
||||
"plugins": [
|
||||
"src/dev/grit/vscode-api.grit"
|
||||
]
|
||||
},
|
||||
{
|
||||
"includes": [
|
||||
"**",
|
||||
"!src/core/storage/state-migrations.ts",
|
||||
"!src/core/storage/FileContextTracker.ts",
|
||||
"!src/core/context/context-tracking/FileContextTracker.ts",
|
||||
"!src/common.ts",
|
||||
"!src/core/storage/utils/state-helpers.ts",
|
||||
"!src/extension.ts"
|
||||
],
|
||||
"plugins": [
|
||||
"src/dev/grit/use-cache-service.grit"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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.)
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
# Cline Privacy Policy
|
||||
|
||||
Cline Bot Inc. ("Cline," "we," "our," and/or "us") values the privacy of individuals who use our VS Code extension and related services (collectively, our "Services"). This privacy policy explains how we collect, use, and disclose information from users of our Services.
|
||||
|
||||
## Key Points
|
||||
|
||||
- Cline operates entirely client-side as a VS Code extension
|
||||
- No code or data is collected, stored, or transmitted to Cline's servers
|
||||
- Your data is only sent to your chosen AI provider (e.g., Anthropic, OpenAI) when you explicitly request assistance
|
||||
- All processing happens locally on your machine
|
||||
- API keys are stored securely in VS Code's built-in settings storage
|
||||
- Telemetry is collected anonymously via PostHog if the user opts in
|
||||
|
||||
## Information We Process
|
||||
|
||||
### A. Information You Provide
|
||||
|
||||
- **API Keys**: When you choose to use certain AI model providers (OpenRouter, Anthropic, OpenAI, etc.), you provide API keys. These are stored securely and locally in your VS Code settings.
|
||||
- **Communications**: If you contact us directly (e.g., via Discord or email), we may receive information like your name, email address, and message contents.
|
||||
|
||||
### B. Information Processing
|
||||
|
||||
Cline functions solely as a client-side VS Code extension that facilitates communication between your editor and your chosen AI model provider:
|
||||
|
||||
1. **File Contents**:
|
||||
|
||||
- Only sent to your chosen AI provider when you explicitly request assistance
|
||||
- Never stored or transmitted to Cline's servers
|
||||
- Only the specific files/content you select are included
|
||||
|
||||
2. **Terminal Commands**:
|
||||
|
||||
- Processed entirely locally on your machine
|
||||
- Require explicit user confirmation before execution
|
||||
- No command history is transmitted to Cline
|
||||
|
||||
3. **Browser Integration**:
|
||||
- Screenshots and console logs are processed locally
|
||||
- Temporary data is cleared after task completion
|
||||
|
||||
## Data Security
|
||||
|
||||
1. **Local-Only Processing**:
|
||||
|
||||
- All operations happen on your local machine
|
||||
- No central servers or data collection
|
||||
- No telemetry or usage statistics gathered unless the user opts in
|
||||
- No account creation required
|
||||
|
||||
2. **API Key Security**:
|
||||
|
||||
- Stored using VS Code's secure settings storage system
|
||||
- Never transmitted to Cline's servers
|
||||
- You can remove/modify keys at any time
|
||||
|
||||
3. **User Control**:
|
||||
- Explicit approval required for file changes
|
||||
- Terminal commands require confirmation
|
||||
- Browser actions need explicit permission
|
||||
- You control which AI provider to use
|
||||
|
||||
## Communication with AI Providers
|
||||
|
||||
When you request assistance:
|
||||
|
||||
1. Selected content is sent directly to your chosen AI provider
|
||||
2. No data passes through Cline's servers
|
||||
3. Provider's own privacy policy applies to this communication:
|
||||
- [Anthropic Privacy Policy](https://www.anthropic.com/privacy)
|
||||
- [OpenAI Privacy Policy](https://openai.com/privacy)
|
||||
- [OpenRouter Privacy Policy](https://openrouter.ai/privacy)
|
||||
|
||||
## Error Handling & Debugging
|
||||
|
||||
- Error logs are processed locally
|
||||
- No automatic error reporting to Cline
|
||||
- You control what information to include when reporting issues
|
||||
|
||||
## Children's Privacy
|
||||
|
||||
We do not knowingly collect, maintain, or use personal information from children under 18 years of age, and no part of our Service(s) is directed to children. If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at support@cline.bot.
|
||||
|
||||
## Changes to Privacy Policy
|
||||
|
||||
We will post any changes to this policy on our GitHub repository. Significant changes will be announced in our Discord community.
|
||||
|
||||
## Security Concerns & Auditing
|
||||
|
||||
- Cline is open source and available for security audit
|
||||
- Our client-side architecture ensures no central point of data collection
|
||||
- You can inspect exactly what data is being sent to AI providers
|
||||
- Enterprise users can implement additional access controls through VS Code
|
||||
|
||||
## Contact Us
|
||||
|
||||
For privacy-related questions or concerns:
|
||||
|
||||
- Open an issue on our [GitHub repository](https://github.com/cline/cline)
|
||||
- Join our [Discord community](https://discord.gg/cline)
|
||||
- Email: support@cline.bot
|
||||
@@ -0,0 +1,38 @@
|
||||
# Cline Documentation
|
||||
|
||||
Welcome to the Cline documentation - your comprehensive guide to using and extending Cline's capabilities. Here you'll find resources to help you get started, improve your skills, and contribute to the project.
|
||||
|
||||
## Getting Started
|
||||
|
||||
- **New to coding?** We've prepared a gentle introduction:
|
||||
- [Getting Started for New Coders](getting-started-new-coders/README.md)
|
||||
|
||||
## Improving Your Prompting Skills
|
||||
|
||||
- **Want to communicate more effectively with Cline?** Explore:
|
||||
- [Prompt Engineering Guide](prompting/README.md)
|
||||
- [Cline Memory Bank](prompting/custom%20instructions%20library/cline-memory-bank.md)
|
||||
|
||||
## Exploring Cline's Tools
|
||||
|
||||
- **Understand Cline's capabilities:**
|
||||
|
||||
- [Cline Tools Guide](tools/cline-tools-guide.md)
|
||||
|
||||
- **Extend Cline with MCP Servers:**
|
||||
- [MCP Overview](mcp/README.md)
|
||||
- [Building MCP Servers from GitHub](mcp/mcp-server-from-github.md)
|
||||
- [Building Custom MCP Servers](mcp/mcp-server-from-scratch.md)
|
||||
|
||||
## Contributing to Cline
|
||||
|
||||
- **Interested in contributing?** We welcome your input:
|
||||
- Feel free to submit a pull request
|
||||
- [Contribution Guidelines](../CONTRIBUTING.md)
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- **Cline GitHub Repository:** [https://github.com/cline/cline](https://github.com/cline/cline)
|
||||
- **MCP Documentation:** [https://modelcontextprotocol.org/docs](https://modelcontextprotocol.org/docs)
|
||||
|
||||
We're always looking to improve this documentation. If you have suggestions or find areas that could be enhanced, please let us know. Your feedback helps make Cline better for everyone.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 902 B |
Binary file not shown.
|
Before Width: | Height: | Size: 666 B |
@@ -0,0 +1,54 @@
|
||||
### .clineignore Support
|
||||
|
||||
To give you more control over which files are accessible to Cline, we've implemented `.clineignore` functionality, similar to `.gitignore`. This allows you to specify files and directories that Cline should **not** access or process. This is useful for:
|
||||
|
||||
* **Privacy:** Preventing Cline from accessing sensitive or private files in your workspace.
|
||||
* **Performance:** Excluding large directories or files that are irrelevant to your tasks, potentially improving the efficiency of Cline.
|
||||
* **Context Management:** Focusing Cline's attention on the relevant parts of your project.
|
||||
|
||||
**How to use `.clineignore`**
|
||||
|
||||
1. **Create a `.clineignore` file:** In the root directory of your workspace (the same level as your `.vscode` folder, or the top level folder you opened in VS Code), create a new file named `.clineignore`.
|
||||
|
||||
2. **Define ignore patterns:** Open the `.clineignore` file and specify the patterns for files and directories you want Cline to ignore. The syntax is the same as `.gitignore`:
|
||||
|
||||
* Each line in the file represents a pattern.
|
||||
* **Standard glob patterns are supported:**
|
||||
* `*` matches zero or more characters
|
||||
* `?` matches one character
|
||||
* `[]` matches a character range
|
||||
* `**` matches any number of directories and subdirectories.
|
||||
|
||||
* **Directory patterns:** Append `/` to the end of a pattern to specify a directory.
|
||||
* **Negation patterns:** Start a pattern with `!` to negate (un-ignore) a previously ignored pattern.
|
||||
* **Comments:** Start a line with `#` to add comments.
|
||||
|
||||
**Example `.clineignore` file:**
|
||||
|
||||
```
|
||||
# Ignore log files
|
||||
*.log
|
||||
|
||||
# Ignore the entire 'node_modules' directory
|
||||
node_modules/
|
||||
|
||||
# Ignore all files in the 'temp' directory and its subdirectories
|
||||
temp/**
|
||||
|
||||
# But DO NOT ignore 'important.log' even if it's in the root
|
||||
!important.log
|
||||
|
||||
# Ignore any file named 'secret.txt' in any subdirectory
|
||||
**/secret.txt
|
||||
```
|
||||
|
||||
3. **Cline respects your `.clineignore`:** Once you save the `.clineignore` file, Cline will automatically recognize and apply these rules.
|
||||
|
||||
* **File Access Control:** Cline will not be able to read the content of ignored files using tools like `read_file`. If you attempt to use a tool on an ignored file, Cline will inform you that access is blocked due to `.clineignore` settings.
|
||||
* **File Listing:** When you ask Cline to list files in a directory (e.g., using `list_files`), ignored files and directories will still be listed, but they will be marked with a **🔒** symbol next to their name to indicate that they are ignored. This helps you understand which files Cline can and cannot interact with.
|
||||
|
||||
4. **Dynamic Updates:** Cline monitors your `.clineignore` file for changes. If you modify, create, or delete your `.clineignore` file, Cline will automatically update its ignore rules without needing to restart VS Code or the extension.
|
||||
|
||||
**In Summary**
|
||||
|
||||
The `.clineignore` file provides a powerful and flexible way to control Cline's access to your workspace files, enhancing privacy, performance, and context management. By leveraging familiar `.gitignore` syntax, you can easily tailor Cline's focus to the most relevant parts of your projects.
|
||||
-234
@@ -1,234 +0,0 @@
|
||||
{
|
||||
"$schema": "https://mintlify.com/docs.json",
|
||||
"theme": "linden",
|
||||
"name": "Cline",
|
||||
"description": "AI-powered coding assistant for VSCode",
|
||||
"colors": {
|
||||
"primary": "#9D4EDD",
|
||||
"light": "#F0E6FF",
|
||||
"dark": "#000000"
|
||||
},
|
||||
"logo": {
|
||||
"light": "/assets/robot_panel_light.png",
|
||||
"dark": "/assets/robot_panel_dark.png"
|
||||
},
|
||||
"favicon": {
|
||||
"light": "/assets/robot_panel_light.png",
|
||||
"dark": "/assets/robot_panel_dark.png"
|
||||
},
|
||||
"background": {
|
||||
"color": {
|
||||
"light": "#F0E6FF",
|
||||
"dark": "#000000"
|
||||
},
|
||||
"decoration": "gradient"
|
||||
},
|
||||
"styling": {
|
||||
"eyebrows": "breadcrumbs",
|
||||
"codeblocks": "system"
|
||||
},
|
||||
"appearance": {
|
||||
"default": "system",
|
||||
"strict": false
|
||||
},
|
||||
"fonts": {
|
||||
"family": "Roboto",
|
||||
"weight": 400
|
||||
},
|
||||
"navbar": {
|
||||
"links": [
|
||||
{
|
||||
"label": "GitHub",
|
||||
"href": "https://github.com/cline/cline"
|
||||
},
|
||||
{
|
||||
"label": "Discord",
|
||||
"href": "https://discord.gg/cline"
|
||||
}
|
||||
],
|
||||
"primary": {
|
||||
"type": "button",
|
||||
"label": "Install Cline",
|
||||
"href": "https://cline.bot/install?utm_source=website&utm_medium=header"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"groups": [
|
||||
{
|
||||
"group": "Getting Started",
|
||||
"pages": [
|
||||
"getting-started/what-is-cline",
|
||||
"getting-started/model-selection-guide",
|
||||
"getting-started/installing-cline",
|
||||
"getting-started/installing-cline-jetbrains",
|
||||
"getting-started/task-management",
|
||||
"getting-started/understanding-context-management",
|
||||
{
|
||||
"group": "For New Coders",
|
||||
"pages": [
|
||||
"getting-started/for-new-coders",
|
||||
"getting-started/installing-dev-essentials"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Improving Your Prompting Skills",
|
||||
"pages": [
|
||||
"prompting/prompt-engineering-guide",
|
||||
"prompting/cline-memory-bank"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"features/auto-approve",
|
||||
"features/checkpoints",
|
||||
"features/cline-rules",
|
||||
"features/drag-and-drop",
|
||||
"features/plan-and-act",
|
||||
"features/slash-commands/workflows",
|
||||
"features/focus-chain",
|
||||
"features/auto-compact",
|
||||
"features/editing-messages",
|
||||
{
|
||||
"group": "@ Mentions",
|
||||
"pages": [
|
||||
"features/at-mentions/overview",
|
||||
"features/at-mentions/file-mentions",
|
||||
"features/at-mentions/terminal-mentions",
|
||||
"features/at-mentions/problem-mentions",
|
||||
"features/at-mentions/git-mentions",
|
||||
"features/at-mentions/url-mentions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Slash Commands",
|
||||
"pages": [
|
||||
"features/slash-commands/new-task",
|
||||
"features/slash-commands/new-rule",
|
||||
"features/slash-commands/smol",
|
||||
"features/slash-commands/report-bug",
|
||||
"features/slash-commands/deep-planning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Commands & Shortcuts",
|
||||
"pages": [
|
||||
"features/commands-and-shortcuts/overview",
|
||||
"features/commands-and-shortcuts/code-commands",
|
||||
"features/commands-and-shortcuts/terminal-integration",
|
||||
"features/commands-and-shortcuts/git-integration",
|
||||
"features/commands-and-shortcuts/keyboard-shortcuts"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Exploring Cline's Tools",
|
||||
"pages": [
|
||||
"exploring-clines-tools/cline-tools-guide",
|
||||
"exploring-clines-tools/new-task-tool",
|
||||
"exploring-clines-tools/remote-browser-support"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Enterprise Solutions",
|
||||
"pages": [
|
||||
"enterprise-solutions/cloud-provider-integration",
|
||||
"enterprise-solutions/custom-instructions",
|
||||
"enterprise-solutions/mcp-servers",
|
||||
"enterprise-solutions/security-concerns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "MCP Servers",
|
||||
"pages": [
|
||||
"mcp/mcp-overview",
|
||||
"mcp/adding-mcp-servers-from-github",
|
||||
"mcp/configuring-mcp-servers",
|
||||
"mcp/connecting-to-a-remote-server",
|
||||
"mcp/mcp-marketplace",
|
||||
"mcp/mcp-server-development-protocol",
|
||||
"mcp/mcp-transport-mechanisms"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Provider Configuration",
|
||||
"pages": [
|
||||
"provider-config/anthropic",
|
||||
"provider-config/claude-code",
|
||||
{
|
||||
"group": "AWS Bedrock",
|
||||
"pages": [
|
||||
"provider-config/aws-bedrock/api-key",
|
||||
"provider-config/aws-bedrock/iam-credentials",
|
||||
"provider-config/aws-bedrock/cli-profile"
|
||||
]
|
||||
},
|
||||
"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/groq",
|
||||
"provider-config/cerebras",
|
||||
"provider-config/doubao",
|
||||
"provider-config/fireworks",
|
||||
"provider-config/zai",
|
||||
"provider-config/ollama",
|
||||
"provider-config/openai",
|
||||
"provider-config/openai-compatible",
|
||||
"provider-config/openrouter",
|
||||
"provider-config/sap-aicore",
|
||||
"provider-config/vercel-ai-gateway",
|
||||
"provider-config/requesty"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Running Models Locally",
|
||||
"pages": [
|
||||
"running-models-locally/read-me-first",
|
||||
"running-models-locally/lm-studio",
|
||||
"running-models-locally/ollama"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Troubleshooting",
|
||||
"pages": [
|
||||
"troubleshooting/terminal-quick-fixes",
|
||||
"troubleshooting/terminal-integration-guide"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "More Info",
|
||||
"pages": [
|
||||
"more-info/telemetry"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"footer": {
|
||||
"socials": {
|
||||
"x": "https://x.com/cline",
|
||||
"github": "https://github.com/cline/cline",
|
||||
"discord": "https://discord.gg/cline"
|
||||
}
|
||||
},
|
||||
"anchors": [
|
||||
{
|
||||
"name": "What is Cline",
|
||||
"icon": "house",
|
||||
"url": "getting-started/what-is-cline"
|
||||
}
|
||||
],
|
||||
"search": {
|
||||
"prompt": "Search Cline documentation..."
|
||||
},
|
||||
"contextual": {
|
||||
"options": [
|
||||
"copy"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
title: "Cloud Provider Integration"
|
||||
---
|
||||
|
||||
Cline supports major cloud providers like AWS Bedrock and Google's Cloud Vertex; whichever your team currently uses is appropriate, and there's no need to change providers to utilize Cline's features.
|
||||
|
||||
For the purpose of this document, we assume your organization will use cloud-based frontier models. Cloud inference providers offer cutting-edge capabilities and the flexibility to select models which best suit your needs.
|
||||
|
||||
Certain scenarios may warrant using local models, including handling highly sensitive data, applications requiring consistent low-latency responses, or compliance with strict data sovereignty requirements. If your team needs to utilize local models, see [Running Local Models ](/running-models-locally/read-me-first.mdx)with Cline.
|
||||
|
||||
---
|
||||
|
||||
## AWS Bedrock Setup Guides
|
||||
|
||||
#### [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)](/provider-config/aws-bedrock-with-credentials-authentication)
|
||||
|
||||
#### [AWS Bedrock setup for SSO token (AWS Profile)](/provider-config/aws-bedrock-with-profile-authentication)
|
||||
|
||||
#### VPC Endpoint Setup
|
||||
|
||||
To protect your team's data, Cline supports VPC (Virtual Private Cloud) endpoints, which create private connections between your data and AWS Bedrock. AWS VPCs enhance security by eliminating the need for public IP addresses, network gateways, or complex firewall rules—essentially creating a private highway for data that bypasses the public internet entirely. By keeping traffic within AWS's private network, teams also benefit from lower latency and more predictable performance when accessing services like AWS Bedrock or custom APIs. For those working with confidential information or operating in highly regulated industries like healthcare or finance, VPCs offers the perfect balance between the accessibility of cloud services and the security of private infrastructure.
|
||||
|
||||
---
|
||||
|
||||
1. Consult the [AWS guide](https://docs.aws.amazon.com/bedrock/latest/userguide/vpc-interface-endpoints.html) to creating VPC endpoints. This document specifies pre-requisites and describes the syntax used for creating VPC endpoints.
|
||||
2. Follow the directions for [creating a VPC endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#create-interface-endpoint-aws) in the AWS console. The image below pertains to steps 4 and 5 of the AWS guide linked above.
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/vpc-console.png" alt="VPC Console" />
|
||||
</Frame>
|
||||
|
||||
3. Note the IP address of your VPC endpoint, open Cline's settings menu, and select `AWS Bedrock`from the API Provider dropdown.
|
||||
4. Click the `Use Custom VPC endpoint`checkbox and enter the IP address of your VPC endpoint
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/vpc-settings-menu.png" alt="VPC Settings Menu" />
|
||||
</Frame>
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: "Custom Instructions"
|
||||
---
|
||||
|
||||
## Building Custom Instructions for Teams
|
||||
|
||||
**Creating standardized project instructions ensures that all team members work within consistent guidelines. Start by documenting your project's technical foundation, then identify which information needs to be included in the instructions. The exact scope will vary depending on your team's needs, but generally it's best to provide as much information as possible. By creating comprehensive instructions that all team members follow, you establish a shared understanding of how code should be written, tested, and deployed across your project, resulting in more maintainable and consistent software.**
|
||||
|
||||
---
|
||||
|
||||
Here are a few topics and examples to consider for your team's custom instructions:
|
||||
|
||||
1. **Testing framework and specific commands**
|
||||
- "All components must include Jest tests with at least 85% coverage. Run tests using `npm run test:coverage` before submitting any pull request."
|
||||
2. **Explicit library preferences**
|
||||
- "Use React Query for data fetching and state management. Avoid Redux unless specifically required for complex global state. For styling, use Tailwind CSS with our custom theme configuration found in `src/styles/theme.js.`"
|
||||
3. **Where to find documentation**
|
||||
- "All API documentation is available in our internal Notion workspace under 'Engineering > API Reference'. For component usage examples, refer to our Storybook instance at `https://storybook.internal.company.com`"
|
||||
4. **Which MCP servers to use, and for which purposes**
|
||||
- "For database operations, use the Postgres MCP server with credentials stored in 1Password under 'Development > Database'. For deployments, use the AWS MCP server which requires the deployment role from IAM. Refer to `docs/mcp-setup.md` for configuration instructions."
|
||||
5. **Coding conventions specific to your project**
|
||||
- "Name all React components using PascalCase and all helper functions using camelCase. Place components in the `src/components` directory organized by feature, not by type. Always use TypeScript interfaces for prop definitions."
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
title: "MCP Servers"
|
||||
---
|
||||
|
||||
**Model Context Protocol (MCP) servers expand Cline's capabilities by providing standardized access to external data sources and executable functions. By implementing MCP servers, LLM tools can dynamically retrieve and incorporate relevant information from both local and remote data sources. This capability ensures that the models operate with the most current and contextually appropriate data, improving the accuracy and relevance of their outputs.**
|
||||
|
||||
---
|
||||
|
||||
### Secure Architecture Fundamentals
|
||||
|
||||
MCP servers follow a client-server architecture where hosts (LLM applications like Cline) initiate connections through a transport layer to MCP servers. This architecture inherently provides security benefits as it maintains clear separation between components. Enterprise deployments should focus on the proper implementation of this architecture to ensure secure operations, particularly regarding the message exchange patterns and connection lifecycle management. For MCP architecture details, see [MCP Architecture](https://modelcontextprotocol.io/docs/concepts/architecture), and for latest specifications, see [MCP Specifications](https://spec.modelcontextprotocol.io/specification/2024-11-05/).
|
||||
|
||||
### Transport Layer Security
|
||||
|
||||
For enterprise environments, selecting the appropriate transport mechanism is crucial. While stdio transport works efficiently for local processes, HTTP with Server-Sent Events (SSE) transport requires additional security measures. TLS should be used for all remote connections whenever possible. This is especially important when MCP servers are deployed across different network segments within corporate infrastructure.
|
||||
|
||||
### Message Validation and Access Control
|
||||
|
||||
The MCP architecture defines standard error codes and message types (Requests, Results, Errors, and Notifications), providing a structured framework for secure communication. Security teams should consider message validation, sanitizing inputs, checking message size limits, and verifying JSON-RPC format. Additionally, implementing resource protection through access controls, path validation, and request rate limiting helps prevent potential abuse of MCP server capabilities.
|
||||
|
||||
### Monitoring and Compliance
|
||||
|
||||
For enterprise compliance requirements, implementing comprehensive logging of protocol events, message flows, and errors is essential. The MCP architecture supports diagnostic capabilities including health checks, connection state monitoring, and resource usage tracking. Organizations should extend these capabilities to meet their specific compliance needs, particularly for audit trails of all MCP server interactions and resource access patterns.
|
||||
|
||||
By leveraging the client-server design of the MCP architecture and implementing appropriate security controls at each layer, enterprises can safely integrate MCP servers into their environments while maintaining their security posture and meeting regulatory requirements.
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
title: "Security Concerns"
|
||||
---
|
||||
|
||||
## Enterprise Security with Cline
|
||||
|
||||
#### Cline addresses enterprise security concerns through its unique client-side architecture that prioritizes data privacy, secure cloud integration, and transparent operations. Below is a comprehensive overview of how Cline maintains robust security measures for enterprise environments.
|
||||
|
||||
---
|
||||
|
||||
### Client-Side Architecture
|
||||
|
||||
Cline operates exclusively as a client-side VSCode extension with zero server-side components. This fundamental design choice ensures that your code and data remain within your secure environment at all times. Unlike traditional AI assistants that send data to external servers for processing, Cline connects directly to your chosen cloud provider's AI endpoints, keeping all sensitive information within your infrastructure boundaries.
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/cline-arch.png"
|
||||
alt="Cline's relationship to local and remote assets"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
### Data Privacy Commitment
|
||||
|
||||
Cline implements a strict zero data retention policy, meaning your intellectual property never leaves your secure environment. The extension does not collect, store, or transmit your code to any central servers. This approach significantly reduces potential attack vectors that might otherwise be introduced through data transmission to third-party systems. Telemetry collection is optional and requires explicit consent.
|
||||
|
||||
### Cloud Provider Integration
|
||||
|
||||
Enterprise teams can access cutting-edge AI models through their existing cloud deployments. Cline supports seamless integration with:
|
||||
|
||||
- AWS Bedrock
|
||||
- Google Cloud Vertex AI
|
||||
- Microsoft Azure
|
||||
|
||||
These integrations utilize your organization's existing security credentials, including native IAM role assumption for AWS. This ensures that all AI processing occurs within your corporate cloud environment, maintaining compliance with your established security protocols.
|
||||
|
||||
### Open-Source Transparency
|
||||
|
||||
Cline's codebase is completely open-source, allowing for comprehensive security auditing by your internal teams. This transparency enables security professionals to verify exactly how the extension functions and confirm that it adheres to your organization's security requirements. Organizations can review the code to ensure it aligns with their security policies before deployment.
|
||||
|
||||
### Controlled Modifications
|
||||
|
||||
The extension implements safeguards against unauthorized changes to your codebase. Cline requires explicit user approval for all file modifications and terminal commands, preventing accidental or unwanted alterations. This approval-based workflow maintains the integrity of your projects while still providing AI assistance.
|
||||
|
||||
### Enterprise Deployment Support
|
||||
|
||||
For organizations with strict security review processes, Cline provides comprehensive documentation including detailed deployment diagrams, sequence diagrams illustrating all data flows, and complete security posture documentation. These materials facilitate thorough security reviews and help demonstrate compliance with enterprise data handling standards and regulations.
|
||||
|
||||
### Access Control
|
||||
|
||||
Enterprise editions of Cline (planned for Q2 2025) will include centralized administration features that allow organizations to:
|
||||
|
||||
- Manage user access with customizable permission levels
|
||||
- Provision accounts with corporate credentials
|
||||
- Immediately revoke access when needed
|
||||
- Control which AI providers and LLM endpoints can be used
|
||||
- Deploy standardized settings across the organization
|
||||
- Prevent unauthorized use of personal API keys
|
||||
|
||||
### Compliance and Governance
|
||||
|
||||
Cline's architecture supports compliance with data sovereignty requirements and enterprise data handling regulations. The planned Enterprise Complete edition will further enhance governance with detailed audit logging, compliance reporting, and automated policy enforcement mechanisms.
|
||||
|
||||
By combining client-side processing, direct cloud provider integration, and transparent operations, Cline offers enterprise teams a secure way to leverage AI assistance while maintaining strict control over their sensitive code and data.
|
||||
@@ -1,386 +0,0 @@
|
||||
---
|
||||
title: "New Task Tool"
|
||||
---
|
||||
|
||||
### The `new_task` Tool & Context Management Strategies
|
||||
|
||||
#### Overview
|
||||
|
||||
Cline includes a powerful internal tool, `new_task`, designed to help manage workflow continuity and context preservation, especially during complex or long-running tasks. This tool, combined with Cline's awareness of its own context window usage and the flexibility of `.clinerules`, enables sophisticated strategies for breaking down work and ensuring seamless transitions between task sessions.
|
||||
|
||||
Understanding the core capabilities and how they interact with custom rules is key to leveraging this feature effectively.
|
||||
|
||||
#### Core Capabilities
|
||||
|
||||
Two fundamental capabilities enable advanced context management:
|
||||
|
||||
1. **The `new_task` Tool:**
|
||||
- **Function:** Allows Cline, upon user approval, to end the current task session and immediately start a new one.
|
||||
- **Context Preloading:** Crucially, Cline can **preload** this new task session with specific context provided within the tool's `<context>` block. This context can be anything Cline or a `.clinerules` file defines – summaries, code snippets, next steps, project state, etc.
|
||||
2. **Context Window Awareness:**
|
||||
- **Tracking:** Cline internally tracks the percentage of its available context window currently being used during a task.
|
||||
- **Visibility:** This information is visible in the `environment_details` provided to Cline in its prompt.
|
||||
|
||||
#### Using the `/newtask` Slash Command
|
||||
|
||||
As a quick alternative to Cline suggesting the `newtask` tool or defining complex rules, you can directly initiate the process using a Slash Command.
|
||||
|
||||
- **How:** Simply type `/newtask` in the chat input field.
|
||||
- **Action:** Cline will propose creating a new task, typically suggesting context based on the current session (similar to its default behavior when using the tool). You will still get the `ask_followup_question` prompt to confirm and potentially modify the context before the new task is created.
|
||||
- **Benefit:** Provides a fast, user-initiated way to leverage the `new_task` functionality for branching explorations or managing long sessions without waiting for Cline to suggest it.
|
||||
|
||||
<Note>
|
||||
For more details on using the `/newtask` slash command, see the [New Task Command](/features/slash-commands/new-task)
|
||||
documentation.
|
||||
</Note>
|
||||
|
||||
#### Default Behavior (Without `.clinerules`)
|
||||
|
||||
By default, without specific `.clinerules` dictating its behavior:
|
||||
|
||||
- **Tool Availability:** The `new_task` tool exists, and Cline _can_ choose to use it.
|
||||
- **Context Awareness:** Cline _is_ aware of its context usage percentage.
|
||||
- **No Automatic Trigger:** Cline **will not** automatically initiate a task handoff _solely_ based on context usage reaching a specific percentage (like 50%). The decision to suggest using `new_task` comes from the AI model's reasoning based on the overall task progress and prompt instructions.
|
||||
- **Basic Context Preloading:** If `new_task` is used without specific rules defining the `<context>` block structure, Cline will attempt to preload relevant information based on its current understanding (e.g., a basic summary of progress and next steps), but this may be less comprehensive than a rule-driven approach.
|
||||
|
||||
#### The Power of `.clinerules`: Enabling Custom Workflows
|
||||
|
||||
While the core capabilities exist by default, the true power, automation, and customization emerge when you combine `new_task` and context awareness with custom workflows defined in `.clinerules`. This allows you to precisely control _when_ and _how_ Cline manages context and task continuity.
|
||||
|
||||
Key benefits of using `.clinerules` with `new_task`:
|
||||
|
||||
- **Automated Context Management:** Define rules to automatically trigger handoffs at specific context percentages (e.g., >50%, >70%) or token counts, ensuring optimal performance and preventing context loss.
|
||||
- **Model-Specific Optimization:** Tailor handoff triggers based on known thresholds for different LLMs (e.g., trigger earlier for models known to degrade past a certain token count).
|
||||
- **Intelligent Breakpoints:** Instruct Cline via rules to find logical stopping points (e.g., after completing a function or test) _after_ a context threshold is passed, ensuring cleaner handoffs.
|
||||
- **Structured Task Decomposition:** Use Plan Mode to define subtasks, then use `.clinerules` to have Cline automatically create a new task via `new_task` upon completing each subtask, preloading the context for the _next_ subtask.
|
||||
- **Custom Context Packaging:** Mandate the exact structure and content of the `<context>` block in `.clinerules` for highly detailed and consistent handoffs (see example below).
|
||||
- **Improved Memory Persistence:** Use `new_task` context blocks as a primary, integrated way to persist information across sessions, potentially replacing or supplementing file-based memory systems.
|
||||
- **Workflow Automation:** Define rules for specific scenarios, like always preloading certain setup instructions or project boilerplate when starting tasks of a particular type.
|
||||
|
||||
#### Example Rule-Driven Workflow: Task Handoff Process
|
||||
|
||||
A common workflow, **driven by specific `.clinerules` like the example below**, involves these steps:
|
||||
|
||||
1. **Trigger Identification (Rule-Based):** Cline monitors for handoff points defined in the rules (e.g., context usage > 50%, task completion).
|
||||
2. **User Confirmation:** Cline uses `ask_followup_question` to propose creating a new task, often showing the intended context defined by the rules.
|
||||
|
||||
```xml
|
||||
<ask_followup_question>
|
||||
<question>I've completed [specific accomplishment] and context usage is high (XX%). Would you like me to create a new task to continue with [remaining work], preloading the following context?</question>
|
||||
<options>["Yes, create new task", "Modify context first", "No, continue this session"]</options>
|
||||
</ask_followup_question>
|
||||
```
|
||||
|
||||
3. **User Control:** You can approve, deny, or ask Cline to modify the context before the new task is created.
|
||||
4. **Context Packaging (`new_task` Tool):** If approved, Cline uses `new_task`, packaging the context according to the structure mandated by the `.clinerules`.
|
||||
5. **New Task Creation:** The current task ends, and a new session begins immediately, preloaded with the specified context.
|
||||
|
||||
#### The Handoff Context Block (Rule-Defined Structure)
|
||||
|
||||
The effectiveness of rule-driven handoffs depends heavily on how `.clinerules` define the `<context>` block. A comprehensive structure often includes:
|
||||
|
||||
- **`## Completed Work`**: Detailed list of accomplishments, files modified/created, key decisions.
|
||||
- **`## Current State`**: Project status, running processes, key file states.
|
||||
- **`## Next Steps`**: Clear, prioritized list of remaining tasks, implementation details, known challenges.
|
||||
- **`## Reference Information`**: Links, code snippets, patterns, user preferences.
|
||||
- **Actionable Start:** A clear instruction for the immediate next action.
|
||||
|
||||
#### Potential Use Cases & Workflows
|
||||
|
||||
The flexibility of `new_task` combined with `.clinerules` opens up many possibilities:
|
||||
|
||||
- **Proactive Context Window Management:** Automatically trigger handoffs at specific percentages (e.g., 50%, 70%) or token counts to maintain optimal performance.
|
||||
- **Intelligent Breakpoints:** Instruct Cline to find logical stopping points (e.g., after completing a function or test) _after_ a context threshold is passed, ensuring cleaner handoffs.
|
||||
- **Structured Task Decomposition:** Use Plan Mode to define subtasks, then use `.clinerules` to have Cline automatically create a new task via `new_task` upon completing each subtask.
|
||||
- **Automated Session Summaries:** Configure the `<context>` block to always include a summary of the previous session's key discussion points.
|
||||
- **Preloading Boilerplate/Setup:** Start new tasks related to specific projects preloaded with standard setup instructions or file templates.
|
||||
- **"Memory Bank" Alternative:** Use `new_task` context blocks as the primary way to persist information across sessions, potentially replacing file-based memory systems.
|
||||
|
||||
Experimenting with `.clinerules` is encouraged to discover workflows that best suit your needs!
|
||||
|
||||
#### Example `.clinerules`: Task Handoff Strategy Guide
|
||||
|
||||
Below is an example `.clinerules` file focused specifically on using `new_task` for context window management. **Remember, this is just one specific strategy; the core `new_task` tool can be used differently with other custom rules.**
|
||||
|
||||
````markdown
|
||||
# You MUST use the `new_task` tool: Task Handoff Strategy Guide
|
||||
|
||||
**⚠️ CRITICAL INSTRUCTIONS - YOU MUST FOLLOW THESE GUIDELINES ⚠️**
|
||||
|
||||
This guide provides **MANDATORY** instructions for effectively breaking down complex tasks and implementing a smooth handoff process between tasks. You **MUST** follow these guidelines to ensure continuity, context preservation, and efficient task completion.
|
||||
|
||||
## ⚠️ CONTEXT WINDOW MONITORING - MANDATORY ACTION REQUIRED ⚠️
|
||||
|
||||
You **MUST** monitor the context window usage displayed in the environment details. When usage exceeds 50% of the available context window, you **MUST** initiate a task handoff using the `new_task` tool.
|
||||
|
||||
Example of context window usage over 50% with a 200K context window:
|
||||
|
||||
\`\`\`text
|
||||
|
||||
# Context Window Usage
|
||||
|
||||
105,000 / 200,000 tokens (53%)
|
||||
Model: anthropic/claude-sonnet-4 (200K context window)
|
||||
\`\`\`
|
||||
|
||||
**IMPORTANT**: When you see context window usage at or above 50%, you MUST:
|
||||
|
||||
1. Complete your current logical step
|
||||
2. Use the `ask_followup_question` tool to offer creating a new task
|
||||
3. If approved, use the `new_task` tool with comprehensive handoff instructions
|
||||
|
||||
## Task Breakdown in Plan Mode - REQUIRED PROCESS
|
||||
|
||||
Plan Mode is specifically designed for analyzing complex tasks and breaking them into manageable subtasks. When in Plan Mode, you **MUST**:
|
||||
|
||||
### 1. Initial Task Analysis - REQUIRED
|
||||
|
||||
- **MUST** begin by thoroughly understanding the full scope of the user's request
|
||||
- **MUST** identify all major components and dependencies of the task
|
||||
- **MUST** consider potential challenges, edge cases, and prerequisites
|
||||
|
||||
### 2. Strategic Task Decomposition - REQUIRED
|
||||
|
||||
- **MUST** break the overall task into logical, discrete subtasks
|
||||
- **MUST** prioritize subtasks based on dependencies (what must be completed first)
|
||||
- **MUST** aim for subtasks that can be completed within a single session (15-30 minutes of work)
|
||||
- **MUST** consider natural breaking points where context switching makes sense
|
||||
|
||||
### 3. Creating a Task Roadmap - REQUIRED
|
||||
|
||||
- **MUST** present a clear, numbered list of subtasks to the user
|
||||
- **MUST** explain dependencies between subtasks
|
||||
- **MUST** provide time estimates for each subtask when possible
|
||||
- **MUST** use Mermaid diagrams to visualize task flow and dependencies when helpful
|
||||
|
||||
\`\`\`mermaid
|
||||
graph TD
|
||||
A[Main Task] --> B[Subtask 1: Setup]
|
||||
A --> C[Subtask 2: Core Implementation]
|
||||
A --> D[Subtask 3: Testing]
|
||||
A --> E[Subtask 4: Documentation]
|
||||
B --> C
|
||||
C --> D
|
||||
\`\`\`
|
||||
|
||||
### 4. Getting User Approval - REQUIRED
|
||||
|
||||
- **MUST** ask for user feedback on the proposed task breakdown
|
||||
- **MUST** adjust the plan based on user priorities or additional requirements
|
||||
- **MUST** confirm which subtask to begin with
|
||||
- **MUST** request the user to toggle to Act Mode when ready to implement
|
||||
|
||||
## Task Implementation and Handoff Process - MANDATORY PROCEDURES
|
||||
|
||||
When implementing tasks in Act Mode, you **MUST** follow these guidelines for effective task handoff:
|
||||
|
||||
### 1. Focused Implementation - REQUIRED
|
||||
|
||||
- **MUST** focus on completing the current subtask fully
|
||||
- **MUST** document progress clearly through comments and commit messages
|
||||
- **MUST** create checkpoints at logical completion points
|
||||
|
||||
### 2. Recognizing Completion Points - CRITICAL
|
||||
|
||||
You **MUST** identify natural handoff points when:
|
||||
|
||||
- The current subtask is fully completed
|
||||
- You've reached a logical stopping point in a larger subtask
|
||||
- The implementation is taking longer than expected and can be continued later
|
||||
- The task scope has expanded beyond the original plan
|
||||
- **CRITICAL**: The context window usage exceeds 50% (e.g., 100,000+ tokens for a 200K context window)
|
||||
|
||||
### 3. Initiating the Handoff Process - MANDATORY ACTION
|
||||
|
||||
When you've reached a completion point, you **MUST**:
|
||||
|
||||
1. Summarize what has been accomplished so far
|
||||
2. Clearly state what remains to be done
|
||||
3. **MANDATORY**: Use the `ask_followup_question` tool to offer creating a new task:
|
||||
|
||||
\`\`\`xml
|
||||
<ask_followup_question>
|
||||
<question>I've completed [specific accomplishment]. Would you like me to create a new task to continue with [remaining work]?</question>
|
||||
<options>["Yes, create a new task", "No, continue in this session", "Let me think about it"]</options>
|
||||
</ask_followup_question>
|
||||
\`\`\`
|
||||
|
||||
### 4. Creating a New Task with Context - REQUIRED ACTION
|
||||
|
||||
If the user agrees to create a new task, you **MUST** use the `new_task` tool with comprehensive handoff instructions:
|
||||
|
||||
\`\`\`xml
|
||||
<new_task>
|
||||
<context>
|
||||
|
||||
# Task Continuation: [Brief Task Title]
|
||||
|
||||
## Completed Work
|
||||
|
||||
- [Detailed list of completed items]
|
||||
- [Include specific files modified/created]
|
||||
- [Note any important decisions made]
|
||||
|
||||
## Current State
|
||||
|
||||
- [Description of the current state of the project]
|
||||
- [Any running processes or environment setup]
|
||||
- [Key files and their current state]
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Detailed list of remaining tasks]
|
||||
- [Specific implementation details to address]
|
||||
- [Any known challenges to be aware of]
|
||||
|
||||
## Reference Information
|
||||
|
||||
- [Links to relevant documentation]
|
||||
- [Important code snippets or patterns to follow]
|
||||
- [Any user preferences noted during the current session]
|
||||
|
||||
Please continue the implementation by [specific next action].
|
||||
</context>
|
||||
</new_task>
|
||||
\`\`\`
|
||||
|
||||
### 5. Detailed Context Transfer - MANDATORY COMPONENTS
|
||||
|
||||
When creating a new task, you **MUST** always include:
|
||||
|
||||
#### Project Context - REQUIRED
|
||||
|
||||
- **MUST** include the overall goal and purpose of the project
|
||||
- **MUST** include key architectural decisions and patterns
|
||||
- **MUST** include technology stack and dependencies
|
||||
|
||||
#### Implementation Details - REQUIRED
|
||||
|
||||
- **MUST** list files created or modified in the current session
|
||||
- **MUST** describe specific functions, classes, or components implemented
|
||||
- **MUST** explain design patterns being followed
|
||||
- **MUST** outline testing approach
|
||||
|
||||
#### Progress Tracking - REQUIRED
|
||||
|
||||
- **MUST** provide checklist of completed items
|
||||
- **MUST** provide checklist of remaining items
|
||||
- **MUST** note any blockers or challenges encountered
|
||||
|
||||
#### User Preferences - REQUIRED
|
||||
|
||||
- **MUST** note coding style preferences mentioned by the user
|
||||
- **MUST** document specific approaches requested by the user
|
||||
- **MUST** highlight priority areas identified by the user
|
||||
|
||||
## Best Practices for Effective Handoffs - MANDATORY GUIDELINES
|
||||
|
||||
### 1. Maintain Continuity - REQUIRED
|
||||
|
||||
- **MUST** use consistent terminology between tasks
|
||||
- **MUST** reference previous decisions and their rationale
|
||||
- **MUST** maintain the same architectural approach unless explicitly changing direction
|
||||
|
||||
### 2. Preserve Context - REQUIRED
|
||||
|
||||
- **MUST** include relevant code snippets in the handoff
|
||||
- **MUST** summarize key discussions from the previous session
|
||||
- **MUST** reference specific files and line numbers when applicable
|
||||
|
||||
### 3. Set Clear Next Actions - REQUIRED
|
||||
|
||||
- **MUST** begin the handoff with a clear, actionable next step
|
||||
- **MUST** prioritize remaining tasks
|
||||
- **MUST** highlight any decisions that need to be made
|
||||
|
||||
### 4. Document Assumptions - REQUIRED
|
||||
|
||||
- **MUST** clearly state any assumptions made during implementation
|
||||
- **MUST** note areas where user input might be needed
|
||||
- **MUST** identify potential alternative approaches
|
||||
|
||||
### 5. Optimize for Resumability - REQUIRED
|
||||
|
||||
- **MUST** structure the handoff so the next session can begin working immediately
|
||||
- **MUST** include setup instructions if environment configuration is needed
|
||||
- **MUST** provide a quick summary at the top for rapid context restoration
|
||||
|
||||
## Example Task Handoff
|
||||
|
||||
### Example #1 of an effective task handoff:
|
||||
|
||||
\`\`\`xml
|
||||
<new_task>
|
||||
<context>
|
||||
|
||||
# Task Continuation: Implement User Authentication System
|
||||
|
||||
## Completed Work
|
||||
|
||||
- Created basic Express.js server structure
|
||||
- Implemented MongoDB connection and user schema
|
||||
- Completed user registration endpoint with password hashing
|
||||
- Added input validation using Joi
|
||||
- Created initial test suite for registration endpoint
|
||||
|
||||
## Current State
|
||||
|
||||
- Server runs successfully on port 3000
|
||||
- MongoDB connection is established
|
||||
- Registration endpoint (/api/users/register) is fully functional
|
||||
- Test suite passes for all registration scenarios
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Implement login endpoint (/api/users/login)
|
||||
- Use bcrypt to compare passwords
|
||||
- Generate JWT token upon successful login
|
||||
- Add proper error handling for invalid credentials
|
||||
2. Create authentication middleware
|
||||
- Verify JWT tokens
|
||||
- Extract user information
|
||||
- Handle expired tokens
|
||||
3. Add protected routes that require authentication
|
||||
4. Implement password reset functionality
|
||||
|
||||
## Reference Information
|
||||
|
||||
- JWT secret should be stored in .env file
|
||||
- Follow the existing error handling pattern in routes/users.js
|
||||
- User schema is defined in models/User.js
|
||||
- Test patterns are established in tests/auth.test.js
|
||||
|
||||
Please continue by implementing the login endpoint following the same patterns established in the registration endpoint.
|
||||
</context>
|
||||
</new_task>
|
||||
\`\`\`
|
||||
|
||||
### Example #2 of an ineffective task handoff:
|
||||
|
||||
_(Note: The example provided in the original rules showing "YOLO MODE Implementation" seems less like a direct handoff context block and more like a general status update with future considerations. A true ineffective handoff might lack detail in 'Current State' or 'Next Steps')._
|
||||
|
||||
## When to Use Task Handoffs - MANDATORY TRIGGERS
|
||||
|
||||
You **MUST** initiate task handoffs in these scenarios:
|
||||
|
||||
1. **CRITICAL**: When context window usage exceeds 50% (e.g., 100,000+ tokens for a 200K context window)
|
||||
2. **Long-running projects** that exceed a single session
|
||||
3. **Complex implementations** with multiple distinct phases
|
||||
4. **When context window limitations** are approaching
|
||||
5. **When switching focus areas** within a larger project
|
||||
6. **When different expertise** might be beneficial for different parts of the task
|
||||
|
||||
**⚠️ FINAL REMINDER - CRITICAL INSTRUCTION ⚠️**
|
||||
|
||||
You **MUST** monitor the context window usage in the environment details section. When it exceeds 50% (e.g., "105,000 / 200,000 tokens (53%)"), you **MUST** proactively initiate the task handoff process using the `ask_followup_question` tool followed by the `new_task` tool. You MUST use the `new_task` tool.
|
||||
|
||||
By strictly following these guidelines, you'll ensure smooth transitions between tasks, maintain project momentum, and provide the best possible experience for users working on complex, multi-session projects.
|
||||
|
||||
```markdown
|
||||
## User Interaction & Workflow Considerations
|
||||
|
||||
- **Linear Flow:** Currently, using `new_task` creates a linear sequence. The old task ends, and the new one begins. The old task history remains accessible for backtracking.
|
||||
- **User Approval:** You always have control, approving the handoff and having the chance to modify the context Cline proposes to carry forward.
|
||||
- **Flexibility:** The core `new_task` tool is a flexible building block. Experiment with `.clinerules` to create workflows that best suit your needs, whether for strict context management, task decomposition, or other creative uses.
|
||||
```
|
||||
````
|
||||
@@ -1,114 +0,0 @@
|
||||
---
|
||||
title: "Remote Browser Support"
|
||||
description: "Remote browser support allows Cline to utilize a remote Chrome instance, leveraging authentication tokens and session cookies relevant to certain web development test cases."
|
||||
icon: globe-pointer
|
||||
---
|
||||
|
||||
The Remote Browser feature in Cline allows the AI assistant to interact with web content directly through a controlled browser instance. This enables several powerful capabilities:
|
||||
|
||||
- Viewing and interacting with websites
|
||||
- Testing locally running web applications
|
||||
- Monitoring console logs and errors
|
||||
- Performing browser actions like clicking, typing, and scrolling
|
||||
|
||||
## Remote Browser in Cline
|
||||
|
||||
### What is Remote Browser?
|
||||
|
||||
Remote Browser allows Cline to view and interact with websites directly. This feature enables Cline to:
|
||||
|
||||
- Visit websites and view their content
|
||||
- Test your locally running web applications
|
||||
- Fill out forms and click on elements
|
||||
- Capture screenshots of what it sees
|
||||
- Scroll through pages to see more content
|
||||
|
||||
### How to Use Remote Browser
|
||||
|
||||
#### Basic Commands
|
||||
|
||||
You can ask Cline to use the browser with simple instructions:
|
||||
|
||||
- **Open a website**: "Use the browser to check the website at [https://example.com](https://example.com/)"
|
||||
- **Click on elements**: "Click the login button"
|
||||
- **Type text**: "Type 'Hello world' in the search box"
|
||||
- **Scroll the page**: "Scroll down to see more content"
|
||||
- **Close the browser**: "Close the browser now"
|
||||
|
||||
#### Example Workflows
|
||||
|
||||
**Testing a Web Application:**
|
||||
|
||||
```javascript
|
||||
Can you start my React app with "npm start" and then check if it's working properly at http://localhost:3000?
|
||||
```
|
||||
|
||||
**Analyzing a Website:**
|
||||
|
||||
```javascript
|
||||
Can you visit https://example.com and tell me what you think about its design and layout?
|
||||
```
|
||||
|
||||
**Filling Out a Form:**
|
||||
|
||||
```javascript
|
||||
Please go to https://example.com/contact, fill out the contact form with some test data, and submit it.
|
||||
```
|
||||
|
||||
### Important Things to Know
|
||||
|
||||
#### One Browser at a Time
|
||||
|
||||
Cline can only use one browser at a time. If you want to visit a different website, you can either:
|
||||
|
||||
- Ask Cline to navigate to a new URL within the same browser session
|
||||
- Ask Cline to close the current browser and open a new one
|
||||
|
||||
#### Browser Must Be Closed Before Using Other Tools
|
||||
|
||||
If you want Cline to edit files or run commands after using the browser, you must first ask it to close the browser:
|
||||
|
||||
```javascript
|
||||
Close the browser and then update the CSS file to fix the alignment issue we saw.
|
||||
```
|
||||
|
||||
#### What Cline Sees
|
||||
|
||||
The browser has a fixed viewport size (900x600 pixels by default), similar to a small laptop screen. Cline will share screenshots after each action so you can see exactly what it sees.
|
||||
|
||||
#### Console Logs
|
||||
|
||||
Cline captures browser console logs, which can be helpful for debugging web applications. These logs are included with each screenshot.
|
||||
|
||||
### Common Use Cases
|
||||
|
||||
- **Web Development**: Test your websites and web applications
|
||||
- **UI/UX Review**: Get feedback on website design and usability
|
||||
- **Content Research**: Have Cline browse websites to gather information
|
||||
- **Form Testing**: Verify that forms work correctly
|
||||
- **Responsive Design Testing**: Check how websites look at different screen sizes
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- **If a website doesn't load**: Try providing a direct URL with the http:// or https:// prefix
|
||||
- **If clicking doesn't work**: Try describing the location of the element more precisely
|
||||
- **If the browser seems stuck**: Ask Cline to close the browser and try again
|
||||
|
||||
### Using Remote Browser with VS Code in WSL
|
||||
|
||||
When running VS Code in WSL, you'll need to configure Windows to allow WSL to connect to Chrome. Follow these steps:
|
||||
|
||||
#### Open PowerShell as Administrator and Run:
|
||||
|
||||
```powershell
|
||||
# Allow WSL to connect to Chrome's debugging port
|
||||
New-NetFirewallRule -DisplayName "WSL Chrome Debug" -Direction Inbound -LocalPort 9222 -Protocol TCP -Action Allow
|
||||
```
|
||||
|
||||
#### Configure Cline in VS Code:
|
||||
|
||||
1. Open VS Code settings
|
||||
2. Search for "Cline: Chrome Executable Path"
|
||||
3. Set the value to the path of your Chrome executable (e.g., `C:\Program Files\Google\Chrome\Application\chrome.exe`)
|
||||
|
||||
Cline should now be able to use the Remote Browser feature from within WSL.
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
title: "File Mentions"
|
||||
sidebarTitle: "File Mentions"
|
||||
---
|
||||
|
||||
File mentions let you pull any file from your workspace directly into your conversation with Cline. No more copying and pasting code snippets - just type `@/` and point to the file you need help with.
|
||||
|
||||
When you type `@/` in the chat, Cline shows your workspace files. Navigate through folders, select the file you want, and it's instantly available to Cline - complete with all imports, related functions, and surrounding context.
|
||||
|
||||
I use file mentions constantly when debugging. Instead of trying to figure out which parts of my code to copy over, I just reference the file directly:
|
||||
|
||||
```
|
||||
I'm getting this error when my form submits: @terminal
|
||||
|
||||
Here's my component: @/src/components/ContactForm.jsx
|
||||
|
||||
And the API endpoint: @/src/api/contact.js
|
||||
|
||||
What am I missing?
|
||||
```
|
||||
|
||||
This gives Cline everything it needs - the error message, the component code, and the API endpoint - all without me having to copy anything. Cline can see imports, dependencies, and all the surrounding context that might be causing the issue.
|
||||
|
||||
File mentions shine when you're dealing with complex bugs that span multiple files. Before, I'd have to carefully copy each relevant file, making sure I didn't miss anything important. Now I just reference each file with `@/` and Cline gets the complete picture.
|
||||
|
||||
Next time you're stuck on a problem, try using file mentions instead of copying code. You'll save time and get better answers because Cline has all the context it needs.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use a file mention in your message, here's what happens behind the scenes:
|
||||
|
||||
1. When you send your message, Cline detects the `@/path/to/file` pattern in your text
|
||||
2. The extension resolves the file path relative to your workspace root
|
||||
3. It checks if the file is binary (like an image) or text-based
|
||||
4. For text files, it reads the complete file content
|
||||
5. The file content is appended to your message in a structured format:
|
||||
```
|
||||
<file_content path="path/to/file">
|
||||
[Complete file content]
|
||||
</file_content>
|
||||
```
|
||||
6. This enhanced message with the embedded file content is sent to the AI
|
||||
7. The AI can now "see" the complete file content as if you had copied and pasted it
|
||||
|
||||
This seamless process happens automatically whenever you use a file mention, giving the AI full context without you having to manually copy anything.
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
title: "Folder Mentions"
|
||||
sidebarTitle: "Folder Mentions"
|
||||
---
|
||||
|
||||
Folder mentions let you bring entire directories into your conversation with Cline. Just type `@/` followed by a folder path ending with a slash, and Cline gets access to the folder structure and its contents.
|
||||
|
||||
When you type `@/` in chat, Cline shows your workspace files and folders. Navigate to the folder you want, make sure to include the trailing slash, and Cline will see the folder's structure and contents.
|
||||
|
||||
I use folder mentions when I need help understanding or refactoring a whole section of my codebase. Instead of referencing individual files one by one, I can just point to the entire directory:
|
||||
|
||||
```
|
||||
I'm trying to understand how the authentication flow works in my app.
|
||||
Can you explain the structure and relationships between the files in @/src/auth/?
|
||||
```
|
||||
|
||||
Cline can then see all the files in the auth directory, their contents, and how they relate to each other. This gives it the full context to explain complex interactions between multiple files.
|
||||
|
||||
Folder mentions are also perfect for getting help with project organization. When I'm unsure if my project structure makes sense, I'll ask Cline to review it:
|
||||
|
||||
```
|
||||
I'm setting up a new React project. Does this folder structure make sense? @/src/
|
||||
What would you change to make it more maintainable as the project grows?
|
||||
```
|
||||
|
||||
Next time you're working with multiple related files, try using folder mentions instead of referencing each file individually. You'll get more comprehensive help because Cline can see the bigger picture of how everything fits together.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use a folder mention in your message, here's what happens behind the scenes:
|
||||
|
||||
1. When you send your message, Cline detects the `@/path/to/folder/` pattern (with trailing slash) in your text
|
||||
2. The extension resolves the folder path relative to your workspace root
|
||||
3. It calls `fs.readdir()` to get a list of all files and subdirectories in that folder
|
||||
4. For each file in the directory, it checks if it's binary or text-based
|
||||
5. For text files, it extracts the complete content
|
||||
6. The folder structure and file contents are appended to your message in a structured format:
|
||||
|
||||
```
|
||||
<folder_content path="path/to/folder">
|
||||
├── file1.txt
|
||||
├── file2.js
|
||||
└── subfolder/
|
||||
|
||||
<file_content path="path/to/folder/file1.txt">
|
||||
[File content]
|
||||
</file_content>
|
||||
|
||||
<file_content path="path/to/folder/file2.js">
|
||||
[File content]
|
||||
</file_content>
|
||||
</folder_content>
|
||||
```
|
||||
|
||||
7. This enhanced message with the embedded folder structure and file contents is sent to the AI
|
||||
8. The AI can now "see" both the directory structure and the content of files within that directory
|
||||
|
||||
This process happens automatically whenever you use a folder mention, giving the AI a comprehensive view of your project structure and file contents.
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
title: "Git Mentions"
|
||||
sidebarTitle: "Git Mentions"
|
||||
---
|
||||
|
||||
Git mentions let you bring your repository's history and changes directly into your conversation with Cline. You can reference uncommitted changes with `@git-changes` or specific commits with `@[commit-hash]`.
|
||||
|
||||
When you type `@` in chat, you can select "Git Changes" from the menu or type `@git-changes` directly. For specific commits, type `@` followed by the commit hash (at least 7 characters). Cline will immediately see the git status, diffs, commit messages, and other relevant information.
|
||||
|
||||
I use git mentions constantly when I'm trying to understand code changes or troubleshoot issues introduced by recent commits. Instead of trying to copy and paste diffs or commit logs, I just ask:
|
||||
|
||||
```
|
||||
I think this commit broke our authentication flow: @a1b2c3d
|
||||
|
||||
Can you explain what changed and why it might be causing the issue?
|
||||
```
|
||||
|
||||
This gives Cline the complete commit information, including the commit message, author, date, and the full diff. Cline can then analyze exactly what changed and how it might affect other parts of the codebase.
|
||||
|
||||
The `@git-changes` mention is perfect when you're working on changes and want feedback before committing:
|
||||
|
||||
```
|
||||
Here are my current changes: @git-changes
|
||||
|
||||
I'm trying to implement a new feature for user profiles. Does my approach make sense?
|
||||
Are there any potential issues or improvements you'd suggest?
|
||||
```
|
||||
|
||||
This shows Cline all your uncommitted changes, including new files, modified files, and their diffs. Cline can then review your changes and provide feedback on your implementation.
|
||||
|
||||
Git mentions are especially powerful when combined with file mentions. When I'm investigating a bug, I'll often reference both:
|
||||
|
||||
```
|
||||
I think this commit introduced a bug: @a1b2c3d
|
||||
|
||||
Here's the current implementation: @/src/components/Auth.jsx
|
||||
|
||||
How can I fix the issue while preserving the intended functionality?
|
||||
```
|
||||
|
||||
Next time you're working with code changes or investigating issues, try using git mentions instead of manually describing or copying changes. You'll get more accurate help because Cline can see exactly what changed and in what context.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use git mentions in your message, here's what happens behind the scenes:
|
||||
|
||||
### For Git Changes (`@git-changes`)
|
||||
|
||||
1. When you send your message, Cline detects the `@git-changes` pattern in your text
|
||||
2. The extension runs git commands to get the current working state of your repository
|
||||
3. It captures the output of `git status` and `git diff` to see all uncommitted changes
|
||||
4. This information is appended to your message in a structured format:
|
||||
|
||||
```
|
||||
<git_working_state>
|
||||
On branch main
|
||||
Changes not staged for commit:
|
||||
modified: src/components/Button.jsx
|
||||
modified: src/styles/main.css
|
||||
|
||||
[Complete diff output with all changes]
|
||||
</git_working_state>
|
||||
```
|
||||
|
||||
### For Specific Commits (`@[commit-hash]`)
|
||||
|
||||
1. When you send your message, Cline detects the `@` followed by a commit hash pattern
|
||||
2. The extension runs `git show` and related commands to get information about that commit
|
||||
3. It retrieves the commit message, author, date, and the complete diff
|
||||
4. This information is appended to your message in a structured format:
|
||||
|
||||
```
|
||||
<git_commit hash="a1b2c3d">
|
||||
commit a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t
|
||||
Author: Developer Name <dev@example.com>
|
||||
Date: Mon May 20 14:30:45 2025 -0700
|
||||
|
||||
Fix authentication bug in login form
|
||||
|
||||
[Complete diff output showing all changes in the commit]
|
||||
</git_commit>
|
||||
```
|
||||
|
||||
This process happens automatically whenever you use git mentions, giving the AI complete visibility into your code changes without you having to copy and paste diffs or commit logs.
|
||||
@@ -1,118 +0,0 @@
|
||||
---
|
||||
title: "@ Mentions Overview"
|
||||
sidebarTitle: "Overview"
|
||||
---
|
||||
|
||||
@ mentions are one of Cline's most powerful features, letting you seamlessly bring external context into your conversations. Instead of copying and pasting code, error messages, or documentation, you can simply reference them with an @ symbol.
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/at-mentions.png" alt="@ Mentions Overview" />
|
||||
</Frame>
|
||||
|
||||
When you type `@` in the chat input, Cline shows a menu of available mention types. These mentions let you reference files, folders, problems, terminal output, git changes, and even web content directly in your conversations.
|
||||
|
||||
## Available @ Mentions
|
||||
|
||||
Cline supports several types of @ mentions, each designed to bring different kinds of context into your conversations:
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="File Mentions" icon="file" href="/features/at-mentions/file-mentions">
|
||||
Reference any file in your workspace with `@/path/to/file`. Cline sees the complete file content, including imports, related
|
||||
functions, and surrounding context.
|
||||
</Card>
|
||||
|
||||
{" "}
|
||||
|
||||
<Card title="Folder Mentions" icon="folder" href="/features/at-mentions/folder-mentions">
|
||||
Reference entire directories with `@/path/to/folder/`. Cline sees the folder structure and all file contents, perfect for
|
||||
understanding complex interactions between multiple files.
|
||||
</Card>
|
||||
|
||||
{" "}
|
||||
|
||||
<Card title="Problem Mentions" icon="triangle-exclamation" href="/features/at-mentions/problem-mentions">
|
||||
Use `@problems` to show Cline all the errors and warnings in your workspace. Cline sees the complete list with file locations
|
||||
and error messages.
|
||||
</Card>
|
||||
|
||||
{" "}
|
||||
|
||||
<Card title="Terminal Mentions" icon="terminal" href="/features/at-mentions/terminal-mentions">
|
||||
Use `@terminal` to share your recent terminal output. Cline sees the complete output with formatting preserved, perfect for
|
||||
debugging build errors or test failures.
|
||||
</Card>
|
||||
|
||||
{" "}
|
||||
|
||||
<Card title="Git Mentions" icon="code-branch" href="/features/at-mentions/git-mentions">
|
||||
Reference uncommitted changes with `@git-changes` or specific commits with `@[commit-hash]`. Cline sees the complete diff,
|
||||
commit message, and other relevant information.
|
||||
</Card>
|
||||
|
||||
<Card title="URL Mentions" icon="globe" href="/features/at-mentions/url-mentions">
|
||||
Reference web content with `@https://example.com`. Cline fetches and sees the complete webpage content, perfect for
|
||||
referencing documentation or GitHub issues.
|
||||
</Card>
|
||||
</Columns>
|
||||
|
||||
## Why @ Mentions Matter
|
||||
|
||||
@ mentions transform how you interact with Cline by:
|
||||
|
||||
1. **Eliminating copy-paste**: No more copying and pasting code, error messages, or terminal output. Just reference them directly.
|
||||
|
||||
2. **Preserving context**: Cline sees the complete context, including imports, related functions, and surrounding code that might be relevant.
|
||||
|
||||
3. **Maintaining formatting**: Terminal output, error messages, and web content keep their formatting, making them easier to understand.
|
||||
|
||||
4. **Enabling complex workflows**: Combine multiple @ mentions to give Cline a complete picture of your problem:
|
||||
|
||||
```
|
||||
I'm getting these errors: @problems
|
||||
|
||||
Here's my component: @/src/components/Form.jsx
|
||||
And the API endpoint: @/src/api/users.js
|
||||
|
||||
The error happens when I submit: @terminal
|
||||
|
||||
I think this commit might have caused it: @a1b2c3d
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
To use @ mentions:
|
||||
|
||||
1. Type `@` in the chat input
|
||||
2. Select the type of mention from the menu or continue typing
|
||||
3. For files and folders, navigate through your workspace structure
|
||||
4. Send your message as usual
|
||||
|
||||
Cline will automatically process the mentions and include the referenced content in the context sent to the AI.
|
||||
|
||||
Try using @ mentions in your next conversation with Cline - you'll be amazed at how much more efficient and effective your interactions become when you can seamlessly bring in external context.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use @ mentions in your messages, there's a sophisticated process happening behind the scenes:
|
||||
|
||||
1. **Detection**: When you send a message, Cline scans the text for @ mention patterns using regular expressions
|
||||
2. **Processing**: For each detected mention, Cline:
|
||||
- Determines the mention type (file, folder, problems, terminal, git, URL)
|
||||
- Fetches the relevant content (file contents, terminal output, etc.)
|
||||
- Formats the content appropriately
|
||||
3. **Enhancement**: The original message is enhanced with structured data:
|
||||
|
||||
```
|
||||
Your original message with @/path/to/file
|
||||
|
||||
<file_content path="/path/to/file">
|
||||
[Complete file content]
|
||||
</file_content>
|
||||
```
|
||||
|
||||
4. **Context Inclusion**: This enhanced message with all the embedded content is sent to the AI model
|
||||
5. **Seamless Response**: The AI can now "see" all the referenced content as if you had manually copied and pasted it
|
||||
|
||||
This entire process happens automatically and seamlessly whenever you use @ mentions, giving the AI complete context without you having to manually copy anything.
|
||||
|
||||
Each type of @ mention has its own specific implementation details, which you can find in their respective documentation pages.
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
title: "Problem Mentions"
|
||||
sidebarTitle: "Problem Mentions"
|
||||
---
|
||||
|
||||
The problems mention gives Cline instant access to all the errors and warnings in your workspace. Just type `@problems` and Cline can see every diagnostic issue VSCode has detected.
|
||||
|
||||
When you type `@` in chat, select "Problems" from the menu or just type `@problems` directly. Cline will immediately see all the errors and warnings from your workspace, complete with file locations and error messages.
|
||||
|
||||
I use the problems mention constantly when I'm stuck on build errors or TypeScript issues. Instead of trying to describe the errors or copy them one by one, I just ask:
|
||||
|
||||
```
|
||||
I'm getting these TypeScript errors and I'm not sure how to fix them: @problems
|
||||
|
||||
Can you help me understand what's wrong and how to fix it?
|
||||
```
|
||||
|
||||
This gives Cline the complete list of errors with their exact locations and messages. Cline can then analyze the patterns across multiple errors and suggest comprehensive solutions.
|
||||
|
||||
The problems mention is especially powerful when combined with file mentions. When I'm dealing with complex type errors, I'll reference both:
|
||||
|
||||
```
|
||||
I'm getting these type errors: @problems
|
||||
|
||||
Here's my component: @/src/components/DataTable.tsx
|
||||
And the types file: @/src/types/api.ts
|
||||
|
||||
How can I fix these issues?
|
||||
```
|
||||
|
||||
This approach gives Cline everything it needs - the exact errors, the component code, and the type definitions - all without me having to copy anything manually.
|
||||
|
||||
Next time you're stuck on errors, try using `@problems` instead of copying error messages. You'll get more accurate help because Cline can see the complete error context and locations.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use the problems mention in your message, here's what happens behind the scenes:
|
||||
|
||||
1. When you send your message, Cline detects the `@problems` pattern in your text
|
||||
2. The extension calls VSCode's built-in `vscode.languages.getDiagnostics()` API to get all errors and warnings
|
||||
3. It formats these diagnostics into a structured text representation with file paths, line numbers, and error messages
|
||||
4. The formatted problems list is appended to your message in a structured format:
|
||||
```
|
||||
<workspace_diagnostics>
|
||||
/path/to/file.js:10:5 - error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
/path/to/file.js:15:3 - warning: This variable is never used.
|
||||
</workspace_diagnostics>
|
||||
```
|
||||
5. This enhanced message with the embedded diagnostics is sent to the AI
|
||||
6. The AI can now "see" all the errors and warnings in your workspace, complete with their locations and messages
|
||||
|
||||
This process happens automatically whenever you use the problems mention, giving the AI a comprehensive view of all the issues in your workspace without you having to copy them manually.
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
title: "Terminal Mentions"
|
||||
sidebarTitle: "Terminal Mentions"
|
||||
---
|
||||
|
||||
The terminal mention lets you bring your terminal output directly into your conversation with Cline. Just type `@terminal` and Cline can see the recent output from your terminal.
|
||||
|
||||
When you type `@` in chat, select "Terminal" from the menu or just type `@terminal` directly. Cline will immediately see the recent output from your active terminal, including error messages, build logs, or command results.
|
||||
|
||||
I use the terminal mention all the time when I'm dealing with build errors, test failures, or debugging output. Instead of trying to copy and paste terminal output (which often loses formatting), I just ask:
|
||||
|
||||
```
|
||||
I'm getting this error when running my tests: @terminal
|
||||
|
||||
What's causing this and how can I fix it?
|
||||
```
|
||||
|
||||
This gives Cline the complete terminal output with all its formatting intact. Cline can then analyze the error messages, stack traces, and surrounding context to provide more accurate help.
|
||||
|
||||
The terminal mention is especially powerful when combined with file mentions. When I'm debugging a failed API call, I'll reference both:
|
||||
|
||||
```
|
||||
I'm getting this error when calling my API: @terminal
|
||||
|
||||
Here's my API client code: @/src/api/client.js
|
||||
And the endpoint implementation: @/src/server/routes/users.js
|
||||
|
||||
What am I doing wrong?
|
||||
```
|
||||
|
||||
This approach gives Cline everything it needs - the exact error output, the client code, and the server implementation - all without me having to copy anything manually.
|
||||
|
||||
Next time you're running into issues with command output or build errors, try using `@terminal` instead of copying the output. You'll get more accurate help because Cline can see the complete terminal context with proper formatting.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use the terminal mention in your message, here's what happens behind the scenes:
|
||||
|
||||
1. When you send your message, Cline detects the `@terminal` pattern in your text
|
||||
2. The extension calls `getLatestTerminalOutput()` which accesses VSCode's terminal API
|
||||
3. It captures the recent output buffer from your active terminal
|
||||
4. The terminal output is appended to your message in a structured format:
|
||||
|
||||
```
|
||||
<terminal_output>
|
||||
$ npm run test
|
||||
> project@1.0.0 test
|
||||
> jest
|
||||
|
||||
FAIL src/components/__tests__/Button.test.js
|
||||
● Button component › renders correctly
|
||||
|
||||
[Complete terminal output with formatting preserved]
|
||||
</terminal_output>
|
||||
```
|
||||
|
||||
5. This enhanced message with the embedded terminal output is sent to the AI
|
||||
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,65 +0,0 @@
|
||||
---
|
||||
title: "URL Mentions"
|
||||
sidebarTitle: "URL Mentions"
|
||||
---
|
||||
|
||||
URL mentions let you bring web content directly into your conversation with Cline. Just type `@` followed by any URL, and Cline can see the content of that webpage without you having to copy and paste anything.
|
||||
|
||||
When you type `@` in chat followed by a URL (like `@https://example.com`), Cline will fetch the content of that webpage and include it in the context. This works for documentation pages, GitHub issues, Stack Overflow questions, or any other web content you want to reference.
|
||||
|
||||
I use URL mentions constantly when I'm working with external APIs or libraries. Instead of trying to explain how an API works or copying documentation snippets, I just reference the docs directly:
|
||||
|
||||
```
|
||||
I'm trying to implement authentication with this API: @https://api.example.com/docs/auth
|
||||
|
||||
Can you help me write the code to get an access token based on these docs?
|
||||
```
|
||||
|
||||
This gives Cline the complete documentation page, so it can see all the authentication requirements, endpoints, parameters, and examples. Cline can then provide more accurate and comprehensive help based on the official documentation.
|
||||
|
||||
URL mentions are especially useful for referencing GitHub issues or discussions:
|
||||
|
||||
```
|
||||
I'm trying to fix this issue in our project: @https://github.com/our-org/our-repo/issues/123
|
||||
|
||||
Here's my current implementation: @/src/components/Feature.jsx
|
||||
|
||||
What changes do I need to make to address the issue?
|
||||
```
|
||||
|
||||
This shows Cline the complete GitHub issue, including the description, comments, and any code snippets or screenshots. Cline can then help you implement a solution that directly addresses the reported issue.
|
||||
|
||||
Next time you're working with external documentation or online resources, try using URL mentions instead of copying and pasting content. You'll get more accurate help because Cline can see the complete context of the webpage, including formatting, code examples, and surrounding information.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use a URL mention in your message, here's what happens behind the scenes:
|
||||
|
||||
1. When you send your message, Cline detects the `@http://...` or `@https://...` pattern in your text
|
||||
2. The extension launches a headless browser (Puppeteer) in the background
|
||||
3. It navigates to the URL and waits for the page to load completely
|
||||
4. The browser captures the page content, including text, formatting, and code examples
|
||||
5. The content is converted to a Markdown format that preserves the structure
|
||||
6. This content is appended to your message in a structured format:
|
||||
|
||||
```
|
||||
<url_content url="https://example.com/docs">
|
||||
# Example API Documentation
|
||||
|
||||
## Authentication
|
||||
|
||||
To authenticate with the API, you need to...
|
||||
|
||||
const token = await api.authenticate({
|
||||
username: 'user',
|
||||
password: 'pass'
|
||||
});
|
||||
|
||||
[Complete webpage content in Markdown format]
|
||||
</url_content>
|
||||
```
|
||||
|
||||
7. The browser is then closed to free up resources
|
||||
8. This enhanced message with the embedded webpage content is sent to the AI
|
||||
|
||||
This process happens automatically whenever you use a URL mention, giving the AI access to the complete content of the webpage without you having to copy and paste anything.
|
||||
@@ -1,59 +0,0 @@
|
||||
The Auto Approve menu lets you set fine-grained permissions on what you allow Cline to do in an automated way.
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/auto-approve.png" alt="Auto Approve" />
|
||||
</Frame>
|
||||
|
||||
## How it works
|
||||
|
||||
By default, Cline will ask for your permission before calling any tool, including reading or writing files.
|
||||
|
||||
If you want to allow Cline to do something without asking, you can set the Auto Approve permission for that tool.
|
||||
|
||||
## Permission Options
|
||||
|
||||
- **Read project files**
|
||||
|
||||
- Allows Cline to read files within your current workspace without asking
|
||||
- **Read all files**
|
||||
- Extends read permission to files outside your workspace (system files, config files, etc.)
|
||||
|
||||
- **Edit project files**
|
||||
|
||||
- Allows Cline to modify files within your current workspace without confirmation
|
||||
- **Edit all files**
|
||||
- Extends modification permission to files outside your workspace
|
||||
|
||||
- **Execute safe commands**
|
||||
|
||||
- Allows execution of terminal commands that the model deems non-destructive
|
||||
- **Execute all commands**
|
||||
- Permits execution of any terminal command without asking
|
||||
|
||||
- **Use the browser**
|
||||
|
||||
- Allows Cline to use the browser tool to fetch web content
|
||||
|
||||
- **Use MCP servers**
|
||||
|
||||
- Permits connection to and usage of MCP servers for extended functionality
|
||||
|
||||
- **Maximum requests**
|
||||
- Sets the number of consecutive automated actions Cline can take before requiring your input
|
||||
|
||||
## Best Practices
|
||||
|
||||
Personally, I like to keep auto-editing disabled because it gives me a chance to review changes every step of the way.
|
||||
|
||||
For most serious development workflows, I recommend starting with:
|
||||
|
||||
- Auto-approving read access to project files
|
||||
- Setting a reasonable maximum request limit (10-20)
|
||||
|
||||
This gives Cline enough freedom to explore your codebase without constant interruptions, while still requiring permission for edits or potentially destructive actions.
|
||||
|
||||
As you build more trust in Cline's capabilities with your specific projects, you can gradually increase the permissions to match your comfort level.
|
||||
|
||||
Remember that you can always adjust these settings as your needs change - tighten permissions for critical production work, or loosen them when prototyping and exploring.
|
||||
|
||||
You can even use the quick "star" actions to quickly toggle your auto-approved selections on and off as you go.
|
||||
@@ -1,75 +0,0 @@
|
||||
---
|
||||
title: "Automatic Context Summarization"
|
||||
sidebarTitle: "Auto Compact"
|
||||
---
|
||||
|
||||
When your conversation approaches the model's context window limit, Cline automatically summarizes it to free up space and keep working.
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/condensing.png"
|
||||
alt="Auto-compact feature condensing conversation context"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
## How It Works
|
||||
|
||||
Cline monitors token usage during your conversation. When you're getting close to the limit, he:
|
||||
|
||||
1. Creates a comprehensive summary of everything that's happened
|
||||
2. Preserves all the technical details, code changes, and decisions
|
||||
3. Replaces the conversation history with the summary
|
||||
4. Continues exactly where he left off
|
||||
|
||||
You'll see a summarization tool call when this happens, showing the total cost like any other api call in the chat view.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
Previously, Cline would truncate older messages when hitting context limits. This meant losing important context from earlier in the conversation.
|
||||
|
||||
Now with summarization:
|
||||
- All technical decisions and code patterns are preserved
|
||||
- File changes and project context remain intact
|
||||
- Cline remembers everything he's done
|
||||
- You can work on much larger projects without interruption
|
||||
|
||||
<Tip>
|
||||
Context Summarization synergizes beautifully with [Focus Chain](/features/focus-chain). When Focus Chain is enabled, todo lists persist across summarizations. This means Cline can work on long-horizon tasks that span multiple context windows while staying on track with the todo list guiding him through each reset.
|
||||
</Tip>
|
||||
|
||||
## Technical Details
|
||||
|
||||
The summarization happens through your configured API provider using the same model you're already using. It leverages prompt caching to minimize costs.
|
||||
|
||||
1. Cline uses a [summarization prompt](https://github.com/cline/cline/blob/main/src/core/prompts/contextManagement.ts) to request a summary of the conversation.
|
||||
|
||||
2. Once the summary is generated, Cline replaces the conversation history with a [continuation prompt](https://github.com/cline/cline/blob/main/src/core/prompts/contextManagement.ts#L69) that asks Cline to keep working and provides the summary as context.
|
||||
|
||||
Different models have different context window thresholds for when auto-summarization kicks in. You can see how thresholds are determined in [context-window-utils.ts](https://github.com/cline/cline/blob/main/src/core/context/context-management/context-window-utils.ts).
|
||||
|
||||
## Cost Considerations
|
||||
|
||||
Summarization leverages your existing prompt cache from the conversation, so it costs about the same as any other tool call.
|
||||
|
||||
Since most input tokens are already cached, you're primarily paying for the summary generation (output tokens), making it very cost-effective.
|
||||
|
||||
## Restoring Context with Checkpoints
|
||||
|
||||
You can use [checkpoints](/features/checkpoints) to restore your task state from before a summarization occurred. This means you never truly lose context - you can always roll back to previous versions of your conversation.
|
||||
|
||||
<Note>
|
||||
Editing a message before a summarization tool call will work similarly to a checkpoint, allowing you to restore the conversation to that point.
|
||||
</Note>
|
||||
|
||||
## Next Generation Model Support
|
||||
|
||||
Auto Compact uses advanced LLM-based summarization which we've found works significantly better for next-generation models. We currently support this feature for the following models:
|
||||
|
||||
- **Claude 4 series**
|
||||
- **Gemini 2.5 series**
|
||||
- **GPT-5**
|
||||
- **Grok 4**
|
||||
|
||||
<Note>
|
||||
When using other models, Cline automatically falls back to the standard rule-based context truncation method, even if Auto Compact is enabled in settings.
|
||||
</Note>
|
||||
@@ -1,79 +0,0 @@
|
||||
---
|
||||
title: "Checkpoints"
|
||||
sidebarTitle: "Checkpoints"
|
||||
---
|
||||
|
||||
Checkpoints automatically save snapshots of your workspace after each step in a task. This feature lets you track changes, roll back when needed, and experiment confidently with your code.
|
||||
|
||||
## How Checkpoints Work
|
||||
|
||||
Cline creates a checkpoint after each tool use (file edits, commands, etc.). These checkpoints:
|
||||
|
||||
- Work alongside your Git workflow without interference
|
||||
- Maintain context between restores
|
||||
- Use a shadow Git repository to track changes
|
||||
|
||||
For example, if you're working on a feature and Cline makes multiple file changes, each change creates a checkpoint. This means you can review each modification and, if needed, roll back to any point without affecting your main Git repository.
|
||||
|
||||
## Viewing Changes & Restoring
|
||||
|
||||
After each tool use, you can:
|
||||
|
||||
1. Click the "Compare" button to see modified files
|
||||
2. Click the "Restore" button to open restore options
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/image%20(13).png"
|
||||
alt="Checkpoint comparison and restore options"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
## Restore Options
|
||||
|
||||
To restore to a previous point:
|
||||
|
||||
1. Click the "Restore" button next to any step
|
||||
2. Choose from three options:
|
||||
- **Restore Task and Workspace**: Reset both codebase and task to that point
|
||||
- **Restore Task Only**: Keep codebase changes but revert task context
|
||||
- **Restore Workspace Only**: Reset codebase while preserving task context
|
||||
|
||||
Example: If Cline makes changes you don't like while styling a component, you can use "Restore Workspace Only" to revert the code changes while keeping the conversation context, allowing you to try a different approach.
|
||||
|
||||
<Frame caption="Reverting both codebase and task to before any changes were made to start fresh">
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/checkpointsDemo.gif" alt="Checkpoint restore demo" />
|
||||
</Frame>
|
||||
|
||||
## Use Cases
|
||||
|
||||
Checkpoints let you be more experimental with Cline. While human coding is often methodical and iterative, AI can make substantial changes quickly. Checkpoints help you track these changes and revert if needed.
|
||||
|
||||
### Using Auto-Approve Mode
|
||||
|
||||
- Provides safety net for rapid iterations
|
||||
- Makes it easy to undo unexpected results
|
||||
|
||||
### Testing Different Approaches
|
||||
|
||||
- Try multiple solutions confidently
|
||||
- Compare different implementations
|
||||
- Quickly revert to working states
|
||||
- Ideal for exploring different design patterns or architectural approaches
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Use checkpoints as safety nets when experimenting
|
||||
2. Leverage auto-approve mode more confidently, knowing you can always roll back
|
||||
3. Restore selectively based on needs:
|
||||
- Use "Restore Task and Workspace" for a fresh start
|
||||
- Use "Restore Task Only" to try different prompts, but keep file changes
|
||||
- Use "Restore Workspace Only" to attempt different implementations while preserving conversation context
|
||||
|
||||
## Relationship with Message Editing
|
||||
|
||||
The [message editing feature](/features/editing-messages) uses checkpoints under the hood when you select the "Restore All" option. This allows you to not only edit and resubmit your message but also restore your workspace to the state it was in at that point in the conversation.
|
||||
|
||||
## Deleting Checkpoints
|
||||
|
||||
You can delete all checkpoints by using the **"Delete All History"** button in the task history menu. Note that this will also delete all tasks. Checkpoints are stored in VS Code's globalStorage.
|
||||
@@ -1,174 +0,0 @@
|
||||
Cline Rules allow you to provide Cline with system-level guidance. Think of them as a persistent way to include context and preferences for your projects or globally for every conversation.
|
||||
|
||||
## Creating a Rule
|
||||
|
||||
You can create a rule by clicking the `+` button in the Rules tab. This will open a new file in your IDE which you can use to write your rule.
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/cline-rules.png" alt="Create a Rule" />
|
||||
</Frame>
|
||||
|
||||
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.
|
||||
|
||||
You can also have Cline create a rule for you by using the [`/newrule` slash command](/features/slash-commands/new-rule) in the chat.
|
||||
|
||||
```markdown Example Cline Rule Structure [expandable]
|
||||
# Project Guidelines
|
||||
|
||||
## Documentation Requirements
|
||||
|
||||
- Update relevant documentation in /docs when modifying features
|
||||
- Keep README.md in sync with new capabilities
|
||||
- Maintain changelog entries in CHANGELOG.md
|
||||
|
||||
## Architecture Decision Records
|
||||
|
||||
Create ADRs in /docs/adr for:
|
||||
|
||||
- Major dependency changes
|
||||
- Architectural pattern changes
|
||||
- New integration patterns
|
||||
- Database schema changes
|
||||
Follow template in /docs/adr/template.md
|
||||
|
||||
## Code Style & Patterns
|
||||
|
||||
- Generate API clients using OpenAPI Generator
|
||||
- Use TypeScript axios template
|
||||
- Place generated code in /src/generated
|
||||
- Prefer composition over inheritance
|
||||
- Use repository pattern for data access
|
||||
- Follow error handling pattern in /src/utils/errors.ts
|
||||
|
||||
## Testing Standards
|
||||
|
||||
- Unit tests required for business logic
|
||||
- Integration tests for API endpoints
|
||||
- E2E tests for critical user flows
|
||||
```
|
||||
|
||||
### Key Benefits
|
||||
|
||||
1. **Version Controlled**: The `.clinerules` file becomes part of your project's source code
|
||||
2. **Team Consistency**: Ensures consistent behavior across all team members
|
||||
3. **Project-Specific**: Rules and standards tailored to each project's needs
|
||||
4. **Institutional Knowledge**: Maintains project standards and practices in code
|
||||
|
||||
Place the `.clinerules` file in your project's root directory:
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── .clinerules
|
||||
├── src/
|
||||
├── docs/
|
||||
└── ...
|
||||
```
|
||||
|
||||
Cline's system prompt, on the other hand, is not user-editable ([here's where you can find it](https://github.com/cline/cline/blob/main/src/core/prompts/system.ts)). For a broader look at prompt engineering best practices, check out [this resource](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview).
|
||||
|
||||
### Tips for Writing Effective Cline Rules
|
||||
|
||||
- Be Clear and Concise: Use simple language and avoid ambiguity.
|
||||
- Focus on Desired Outcomes: Describe the results you want, not the specific steps.
|
||||
- Test and Iterate: Experiment to find what works best for your workflow.
|
||||
|
||||
### .clinerules/ Folder System
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── .clinerules/ # Folder containing active rules
|
||||
│ ├── 01-coding.md # Core coding standards
|
||||
│ ├── 02-documentation.md # Documentation requirements
|
||||
│ └── current-sprint.md # Rules specific to current work
|
||||
├── src/
|
||||
└── ...
|
||||
```
|
||||
|
||||
Cline automatically processes **all Markdown files** inside the `.clinerules/` directory, combining them into a unified set of rules. The numeric prefixes (optional) help organize files in a logical sequence.
|
||||
|
||||
#### Using a Rules Bank
|
||||
|
||||
For projects with multiple contexts or teams, maintain a rules bank directory:
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── .clinerules/ # Active rules - automatically applied
|
||||
│ ├── 01-coding.md
|
||||
│ └── client-a.md
|
||||
│
|
||||
├── clinerules-bank/ # Repository of available but inactive rules
|
||||
│ ├── clients/ # Client-specific rule sets
|
||||
│ │ ├── client-a.md
|
||||
│ │ └── client-b.md
|
||||
│ ├── frameworks/ # Framework-specific rules
|
||||
│ │ ├── react.md
|
||||
│ │ └── vue.md
|
||||
│ └── project-types/ # Project type standards
|
||||
│ ├── api-service.md
|
||||
│ └── frontend-app.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
#### Benefits of the Folder Approach
|
||||
|
||||
1. **Contextual Activation**: Copy only relevant rules from the bank to the active folder
|
||||
2. **Easier Maintenance**: Update individual rule files without affecting others
|
||||
3. **Team Flexibility**: Different team members can activate rules specific to their current task
|
||||
4. **Reduced Noise**: Keep the active ruleset focused and relevant
|
||||
|
||||
#### Usage Examples
|
||||
|
||||
Switch between client projects:
|
||||
|
||||
```bash
|
||||
# Switch to Client B project
|
||||
rm .clinerules/client-a.md
|
||||
cp clinerules-bank/clients/client-b.md .clinerules/
|
||||
```
|
||||
|
||||
Adapt to different tech stacks:
|
||||
|
||||
```bash
|
||||
# Frontend React project
|
||||
cp clinerules-bank/frameworks/react.md .clinerules/
|
||||
```
|
||||
|
||||
#### Implementation Tips
|
||||
|
||||
- Keep individual rule files focused on specific concerns
|
||||
- Use descriptive filenames that clearly indicate the rule's purpose
|
||||
- Consider git-ignoring the active `.clinerules/` folder while tracking the `clinerules-bank/`
|
||||
- Create team scripts to quickly activate common rule combinations
|
||||
|
||||
The folder system transforms your Cline rules from a static document into a dynamic knowledge system that adapts to your team's changing contexts and requirements.
|
||||
|
||||
### Managing Rules with the Toggleable Popover
|
||||
|
||||
To make managing both single `.clinerules` files and the folder system even easier, Cline v3.13 introduces a dedicated popover UI directly accessible from the chat interface.
|
||||
|
||||
Located conveniently under the chat input field, this popover allows you to:
|
||||
|
||||
- **Instantly See Active Rules:** View which global rules (from your user settings) and workspace rules (`.clinerules` file or folder contents) are currently active.
|
||||
- **Quickly Toggle Rules:** Enable or disable specific rule files within your workspace `.clinerules/` folder with a single click. This is perfect for activating context-specific rules (like `react-rules.md` or `memory-bank.md`) only when needed.
|
||||
- **Easily Add/Manage Rules:** Quickly create a workspace `.clinerules` file or folder if one doesn't exist, or add new rule files to an existing folder.
|
||||
|
||||
This UI significantly simplifies switching contexts and managing different sets of instructions without needing to manually edit files or configurations during a conversation.
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/image%20(1).png" alt="Cline Logo" />
|
||||
</Frame>
|
||||
@@ -1,129 +0,0 @@
|
||||
---
|
||||
title: "Code Commands"
|
||||
sidebarTitle: "Code Commands"
|
||||
---
|
||||
|
||||
Cline's code commands bring AI assistance directly into your editor, letting you interact with your code without leaving your workflow. With a simple right-click, you can add code to Cline, and through the lightbulb menu, you can fix errors, get explanations, or improve your code.
|
||||
|
||||
## Available Code Commands
|
||||
|
||||
When you interact with code in your editor, you can access Cline commands in two ways:
|
||||
|
||||
### Right-Click Context Menu
|
||||
|
||||
When you right-click on selected code, you'll see:
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/code-commands.png" alt="Right Click Menu" />
|
||||
</Frame>
|
||||
|
||||
#### Add to Cline
|
||||
|
||||
The "Add to Cline" command sends your selected code to the Cline chat panel. This is perfect for:
|
||||
|
||||
- Asking questions about specific code snippets
|
||||
- Requesting improvements or optimizations
|
||||
- Getting explanations of complex logic
|
||||
|
||||
When you use this command, Cline automatically includes:
|
||||
|
||||
- The file path (as a file mention)
|
||||
- The selected code with proper formatting
|
||||
- The programming language for accurate syntax highlighting
|
||||
|
||||
### Lightbulb Menu (Code Actions)
|
||||
|
||||
When you see a lightbulb icon in your editor, click it to access these Cline commands:
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/docs/assets/lightbulb-actions.png" alt="Lightbulb Menu" />
|
||||
</Frame>
|
||||
|
||||
#### Fix with Cline
|
||||
|
||||
The "Fix with Cline" command appears in the lightbulb menu when your code has errors or warnings. This command:
|
||||
|
||||
1. Captures the selected code
|
||||
2. Identifies the errors or warnings from VSCode's diagnostics
|
||||
3. Sends both to Cline with a request to fix the issues
|
||||
4. Provides a solution that addresses the specific problems
|
||||
|
||||
This is incredibly useful for quickly resolving syntax errors, linter warnings, or type issues without having to manually describe the problem.
|
||||
|
||||
#### Explain with Cline
|
||||
|
||||
The "Explain with Cline" command helps you understand complex code. When you select code and use this command from the lightbulb menu, Cline:
|
||||
|
||||
1. Analyzes the selected code
|
||||
2. Provides a clear explanation of what the code does
|
||||
3. Breaks down complex logic into understandable parts
|
||||
4. Highlights important patterns or techniques used
|
||||
|
||||
#### Improve with Cline
|
||||
|
||||
The "Improve with Cline" command helps you enhance your code. When you select code and use this command from the lightbulb menu, Cline:
|
||||
|
||||
1. Analyzes the selected code for potential improvements
|
||||
2. Suggests optimizations, refactorings, or better practices
|
||||
3. Explains the reasoning behind the suggested changes
|
||||
4. Provides improved code that maintains the original functionality
|
||||
|
||||
## How to Use Code Commands
|
||||
|
||||
Using Cline's code commands is simple:
|
||||
|
||||
### For Right-Click Commands:
|
||||
|
||||
1. Select the code you want to work with
|
||||
2. Right-click to open the context menu
|
||||
3. Choose "Add to Cline"
|
||||
4. View the result in the Cline chat panel
|
||||
|
||||
### For Lightbulb Menu Commands:
|
||||
|
||||
1. Select the code you want to work with
|
||||
2. Look for the lightbulb icon that appears in the editor gutter
|
||||
3. Click the lightbulb to see available actions
|
||||
4. Choose the appropriate Cline command (Fix, Explain, or Improve)
|
||||
5. View the result in the Cline chat panel
|
||||
|
||||
After using any command, you can:
|
||||
|
||||
- Ask follow-up questions
|
||||
- Request modifications to the solution
|
||||
- Apply the changes back to your code
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
When you use a code command, here's what happens behind the scenes:
|
||||
|
||||
1. **Code Selection**: The extension captures your selected code and its context
|
||||
2. **Metadata Collection**: Cline gathers important metadata:
|
||||
|
||||
- File path and name
|
||||
- Programming language
|
||||
- Any associated diagnostics (errors/warnings)
|
||||
- Surrounding code context when relevant
|
||||
|
||||
3. **Command Processing**:
|
||||
|
||||
- For "Add to Cline," the code is formatted and sent to the chat panel
|
||||
- For "Fix with Cline," the code and diagnostics are analyzed and a fix is generated
|
||||
- For "Explain with Cline," the code is analyzed to provide a clear explanation
|
||||
- For "Improve with Cline," the code is analyzed for potential optimizations and improvements
|
||||
|
||||
4. **Integration with Chat**: The results appear in the Cline chat panel, where you can:
|
||||
- See the AI's response
|
||||
- Ask follow-up questions
|
||||
- Apply suggested changes
|
||||
|
||||
This seamless integration between your editor and Cline's AI capabilities makes it easy to get assistance without disrupting your coding flow.
|
||||
|
||||
## Tips for Effective Use
|
||||
|
||||
- **Select complete logical units**: When possible, select entire functions, classes, or modules to give Cline complete context
|
||||
- **Include imports**: For language-specific help, include relevant imports so Cline understands dependencies
|
||||
- **Combine with @ mentions**: For complex issues, use code commands along with file or problem mentions for more context
|
||||
- **Use keyboard shortcuts**: Speed up your workflow by [assigning keyboard shortcuts](/features/commands-and-shortcuts/keyboard-shortcuts) to common code commands
|
||||
|
||||
Next time you're struggling with a piece of code, try using Cline's code commands instead of switching to a separate chat interface. You'll be amazed at how much more efficient your workflow becomes when AI assistance is integrated directly into your editor.
|
||||
@@ -1,71 +0,0 @@
|
||||
---
|
||||
title: "Generate Commit Message"
|
||||
sidebarTitle: "Generate Commit Message"
|
||||
---
|
||||
|
||||
Cline's Git integration brings AI assistance directly to your version control workflow. Generate commit messages without leaving your editor.
|
||||
|
||||
## Generate Commit Message
|
||||
|
||||
One of the most useful Git integrations is the ability to automatically generate meaningful commit messages:
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/generate-commit-message-with-cline.png"
|
||||
alt="Generate Commit Message with Cline"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
1. Make your changes and stage them in Git
|
||||
2. Click the robot icon in the Source Control view or run the "Generate Commit Message with Cline" command
|
||||
3. Cline analyzes your changes and generates a descriptive commit message
|
||||
4. The message is automatically inserted into the commit message input box
|
||||
|
||||
The generated commit messages:
|
||||
|
||||
- Start with a concise summary (50-72 characters)
|
||||
- Use imperative mood (e.g., "Add feature" not "Added feature")
|
||||
- Describe what was changed and why
|
||||
- Follow Git best practices
|
||||
|
||||
This feature saves time and ensures your commit history is consistent and informative.
|
||||
|
||||
<Tip>
|
||||
For information about using `@git-changes` and `@[commit-hash]` mentions in your chat messages, see the [Git
|
||||
Mentions](/features/at-mentions/git-mentions) documentation.
|
||||
</Tip>
|
||||
|
||||
## How It Works
|
||||
|
||||
When you use Cline's commit message generation feature, here's what happens behind the scenes:
|
||||
|
||||
1. Cline retrieves the current Git diff using `getWorkingState()`
|
||||
2. It formats this diff into a specialized prompt for the AI
|
||||
3. The AI analyzes the changes and generates an appropriate commit message
|
||||
4. The message is extracted and inserted into the Git commit message input box
|
||||
|
||||
This process uses your current Cline API configuration, so the quality of the generated messages matches your chosen AI model.
|
||||
|
||||
## Tips for Effective Use
|
||||
|
||||
- **Generate commit messages for complex changes**: The AI excels at summarizing multiple related changes into a coherent message.
|
||||
|
||||
- **Review and edit generated messages**: While the AI generates high-quality messages, it's always good practice to review and adjust them if needed.
|
||||
|
||||
- **Stage related changes together**: For the best results, stage related changes together so the AI can generate a cohesive message.
|
||||
|
||||
- **Use for consistent commit history**: Using the generate commit message feature helps maintain a consistent style across your commit history.
|
||||
|
||||
## How It Works Under the Hood
|
||||
|
||||
The commit message generation leverages VSCode's Git extension API to access repository information:
|
||||
|
||||
1. When you trigger the command:
|
||||
- Cline gets the current diff
|
||||
- It sends this to the AI with specific instructions for commit message formatting
|
||||
- It parses the AI's response
|
||||
- It accesses the Git extension API to set the commit message
|
||||
|
||||
This integration with Git makes it easy to generate high-quality commit messages without disrupting your workflow.
|
||||
|
||||
Next time you're struggling to write a good commit message, try using Cline's commit message generation. You'll save time and improve your version control workflow with AI assistance right where you need it.
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
title: "Keyboard Shortcuts"
|
||||
sidebarTitle: "Keyboard Shortcuts"
|
||||
---
|
||||
|
||||
Cline's keyboard shortcuts let you access AI assistance without taking your hands off the keyboard. Speed up your workflow by using hotkeys for common Cline actions.
|
||||
|
||||
## Default Keyboard Shortcuts
|
||||
|
||||
Cline comes with the following built-in keyboard shortcuts to streamline your workflow:
|
||||
|
||||
| Action | Windows/Linux | macOS | Condition | Description |
|
||||
| ----------------------- | ------------- | ------- | ---------------------------- | ----------------------------------------- |
|
||||
| Add to Cline | `Ctrl+'` | `Cmd+'` | When text is selected | Adds selected code to Cline chat |
|
||||
| Focus Chat Input | `Ctrl+'` | `Cmd+'` | When no text is selected | Focuses the Cline chat input field |
|
||||
| Generate Commit Message | (unset) | (unset) | When Git is the SCM provider | Available through the Source Control view |
|
||||
|
||||
## Available Commands for Custom Shortcuts
|
||||
|
||||
While Cline has only a few default keyboard shortcuts, you can assign your own shortcuts to any of these commands:
|
||||
|
||||
| Command ID | Description |
|
||||
| ---------------------------------------------------------------------------------------- | --------------------------------------------- |
|
||||
| [`cline.openInNewTab`](/features/commands-and-shortcuts/overview) | Opens Cline in a new editor tab |
|
||||
| [`cline.addToChat`](/features/commands-and-shortcuts/code-commands) | Adds selected code to Cline chat |
|
||||
| [`cline.addTerminalOutputToChat`](/features/commands-and-shortcuts/terminal-integration) | Adds terminal output to Cline |
|
||||
| `cline.focusChatInput` | Focuses the Cline chat input field |
|
||||
| [`cline.generateGitCommitMessage`](/features/commands-and-shortcuts/git-integration) | Generates a commit message for staged changes |
|
||||
| [`cline.explainCode`](/features/commands-and-shortcuts/code-commands) | Explains selected code |
|
||||
| [`cline.improveCode`](/features/commands-and-shortcuts/code-commands) | Suggests improvements for selected code |
|
||||
| [`cline.fixWithCline`](/features/commands-and-shortcuts/code-commands) | Fixes code with errors |
|
||||
| `claude-dev.SidebarProvider.focus` | Opens and focuses the Cline sidebar |
|
||||
|
||||
## Customizing Keyboard Shortcuts
|
||||
|
||||
You can customize Cline's keyboard shortcuts to match your preferences:
|
||||
|
||||
1. Open the Keyboard Shortcuts editor in VSCode:
|
||||
|
||||
- Press `Ctrl+K Ctrl+S` (Windows/Linux) or `Cmd+K Cmd+S` (macOS)
|
||||
- Or go to File > Preferences > Keyboard Shortcuts
|
||||
|
||||
2. Search for "Cline" to see all available commands
|
||||
|
||||
3. Click on the pencil icon next to any command to change its shortcut
|
||||
|
||||
4. Press the keys you want to assign to that command
|
||||
|
||||
5. Press Enter to save the new shortcut
|
||||
|
||||
## Suggested Custom Shortcuts
|
||||
|
||||
Here are some suggested shortcuts you might find useful:
|
||||
|
||||
| Action | Suggested Shortcut | Command ID | Description |
|
||||
| --------------------- | ------------------------------ | ----------------------------------------- | ----------------------------- |
|
||||
| Open Cline Sidebar | `Ctrl+Shift+C` / `Cmd+Shift+C` | `claude-dev.SidebarProvider.focus` | Opens the Cline sidebar panel |
|
||||
| New Task | `Alt+N` | `cline.plusButtonClicked` | Starts a new Cline task |
|
||||
| Add Terminal to Cline | `Alt+T` | `cline.addTerminalOutputToChat` | Adds terminal output to Cline |
|
||||
| Clear Current Task | `Alt+C` | (Requires custom keybinding to UI action) | Clears the current task |
|
||||
|
||||
## Keyboard-Only Workflow
|
||||
|
||||
With the right shortcuts, you can use Cline without ever touching the mouse:
|
||||
|
||||
1. Select code with keyboard navigation (`Shift+Arrow` keys)
|
||||
2. Send to Cline with `Ctrl+'` / `Cmd+'`
|
||||
3. Type your question and press Enter
|
||||
4. Review the response and apply suggestions
|
||||
|
||||
## Editor Integration Shortcuts
|
||||
|
||||
Cline's keyboard shortcuts integrate seamlessly with VSCode's built-in shortcuts:
|
||||
|
||||
- Use VSCode's selection shortcuts (`Ctrl+L` / `Cmd+L` to select line, etc.) before sending code to Cline
|
||||
- Combine with VSCode's split editor shortcuts to view code and Cline side by side
|
||||
- Use VSCode's terminal focus shortcut (`` Ctrl+` `` / `` Cmd+` ``) before capturing terminal output
|
||||
|
||||
## Tips for Effective Use
|
||||
|
||||
- **Learn the default shortcut first**: The `Ctrl+'` / `Cmd+'` shortcut is versatile - it adds selected code to chat when text is selected, or focuses the chat input when nothing is selected
|
||||
- **Create muscle memory**: Use keyboard shortcuts consistently to build habits
|
||||
- **Customize for your workflow**: Assign shortcuts to commands you use frequently
|
||||
- **Consider ergonomics**: Choose shortcuts that are comfortable for your keyboard layout
|
||||
|
||||
Keyboard shortcuts may seem like a small optimization, but they can significantly speed up your workflow when using Cline regularly. By keeping your hands on the keyboard, you maintain your coding flow while still getting AI assistance exactly when you need it.
|
||||
|
||||
## How to Find All Available Commands
|
||||
|
||||
To see all Cline commands that can be assigned shortcuts:
|
||||
|
||||
1. Open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`)
|
||||
2. Type "Cline" to filter the list
|
||||
3. Browse the available commands
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/editor-integration.png"
|
||||
alt="Editor Integration Overview"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
This helps you discover features you might not have known about and assign shortcuts to the ones you use most frequently.
|
||||
@@ -1,65 +0,0 @@
|
||||
---
|
||||
title: "Commands & Shortcuts Overview"
|
||||
sidebarTitle: "Overview"
|
||||
---
|
||||
|
||||
Cline integrates directly into VSCode's interface, letting you access AI assistance without disrupting your workflow. These integrations appear as commands in context menus, keyboard shortcuts, and quick fixes throughout the editor.
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/editor-integration.png"
|
||||
alt="Editor Integration Overview"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
### What are Editor Integrations?
|
||||
|
||||
Editor integrations are commands and shortcuts that let you use Cline right where you're working. Instead of switching to the Cline panel first, you can select code, right-click, and immediately send it to Cline for help.
|
||||
These integrations appear in different places throughout VSCode:
|
||||
|
||||
- In the editor context menu (right-click menu) - "Add to Cline"
|
||||
- In the terminal context menu - "Add to Cline"
|
||||
- In the Source Control view - "Generate Commit Message"
|
||||
- As keyboard shortcuts - Various Cline commands
|
||||
- As Quick Fix options (lightbulb menu) - "Fix with Cline", "Explain with Cline", "Improve with Cline"
|
||||
|
||||
### Available Editor Integrations
|
||||
|
||||
Cline offers several editor integrations, each designed to enhance different aspects of your development workflow:
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Code Commands" icon="code" href="/features/commands-and-shortcuts/code-commands">
|
||||
Right-click on code to add it to Cline, or use the lightbulb menu to fix errors, explain code, or improve it. Cline sees the complete code context, including imports and surrounding functions.
|
||||
</Card>
|
||||
|
||||
{" "}
|
||||
|
||||
<Card title="Terminal Integration" icon="terminal" href="/features/commands-and-shortcuts/terminal-integration">
|
||||
Add terminal output to Cline with a right-click or use `@terminal` mentions. Perfect for debugging build errors, test
|
||||
failures, or runtime issues.
|
||||
</Card>
|
||||
|
||||
{" "}
|
||||
|
||||
<Card title="Git Integration" icon="code-branch" href="/features/commands-and-shortcuts/git-integration">
|
||||
Generate commit messages, explain diffs, or analyze changes with Cline's Git integration. Cline understands your version
|
||||
control context.
|
||||
</Card>
|
||||
|
||||
{" "}
|
||||
|
||||
<Card title="Keyboard Shortcuts" icon="keyboard" href="/features/commands-and-shortcuts/keyboard-shortcuts">
|
||||
Speed up your workflow with keyboard shortcuts for common Cline actions. Quickly add code to chat, fix errors, or improve your code.
|
||||
</Card>
|
||||
</Columns>
|
||||
|
||||
### How They Work
|
||||
|
||||
When you use these commands, Cline:
|
||||
|
||||
- Captures the relevant context (selected code, file path, terminal output, etc.)
|
||||
- Focuses the Cline interface
|
||||
- Creates a conversation with the captured context
|
||||
- In some cases, automatically generates a suggested prompt
|
||||
|
||||
Behind the scenes, these commands use VSCode's extension API to register commands, access editor state, and control VSCode's interface.
|
||||
@@ -1,98 +0,0 @@
|
||||
---
|
||||
title: "Terminal Integration"
|
||||
sidebarTitle: "Terminal Integration"
|
||||
---
|
||||
|
||||
Cline's terminal integration lets you bring your terminal output directly into your conversations with Cline. Instead of copying and pasting error messages or command results, you can send them to Cline with a simple right-click in the terminal.
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/terminal-integration.png"
|
||||
alt="Terminal Integration"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
## Right-Click Terminal Integration
|
||||
|
||||
When you're working in the VSCode terminal and see output you want to discuss with Cline:
|
||||
|
||||
1. Right-click in the terminal
|
||||
2. Select "Add to Cline" from the context menu
|
||||
3. The terminal output is immediately sent to the Cline chat panel
|
||||
|
||||
This is perfect for:
|
||||
|
||||
- Debugging build errors
|
||||
- Understanding test failures
|
||||
- Analyzing command output
|
||||
- Getting help with error messages
|
||||
|
||||
The right-click terminal integration is especially useful when you're already working in the terminal and encounter an issue.
|
||||
|
||||
Instead of switching context to the Cline chat panel and typing a description of the problem, you can send the terminal output directly to Cline with just a couple of clicks.
|
||||
|
||||
Alternatively, you can use the [`@terminal`](/features/at-mentions/terminal-mentions) mention to send the full terminal output to Cline.
|
||||
|
||||
<Tip>
|
||||
For information about using `@terminal` mentions in your chat messages, see the [Terminal
|
||||
Mentions](/features/at-mentions/terminal-mentions) documentation.
|
||||
</Tip>
|
||||
|
||||
## How Terminal Integration Works
|
||||
|
||||
When you use the right-click terminal integration, Cline:
|
||||
|
||||
1. Captures the terminal output with all formatting preserved
|
||||
2. Includes the complete context, including command history and results
|
||||
3. Formats it appropriately for the AI to understand
|
||||
4. Enables the AI to see exactly what you're seeing
|
||||
|
||||
This gives Cline the full context it needs to provide accurate help with terminal-related issues.
|
||||
|
||||
## Behind the Scenes
|
||||
|
||||
The terminal integration uses a clever technique to capture terminal output:
|
||||
|
||||
1. When you trigger the integration, Cline:
|
||||
|
||||
- Temporarily saves your current clipboard content
|
||||
- Selects all terminal content (or uses your existing selection)
|
||||
- Copies it to the clipboard
|
||||
- Reads the clipboard to get the terminal content
|
||||
- Restores your original clipboard content
|
||||
|
||||
2. The terminal content is then:
|
||||
- Formatted with proper syntax highlighting
|
||||
- Added to your message or sent as a new message
|
||||
- Enhanced with additional context when needed
|
||||
|
||||
This approach ensures that all terminal output, including colors and formatting, is accurately captured without affecting your clipboard.
|
||||
|
||||
## Tips for Effective Use
|
||||
|
||||
- **Use terminal integration for error messages**: When you encounter an error in the terminal, sending it to Cline often results in faster resolution than trying to describe the error.
|
||||
|
||||
- **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.
|
||||
|
||||
- **Contextualize build & test outputs with the terminal**: 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>
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
title: "Drag & Drop"
|
||||
sidebarTitle: "Drag & Drop"
|
||||
---
|
||||
|
||||
Dragging and dropping files into Cline is a quick way to add images, code, and other files to your conversations.
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/dran-n-drop.gif"
|
||||
alt="Dragging and dropping files into Cline chat"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
<Note>Due to VS Code quirks, to drag and drop files into the Cline chat input, you need to hold `Shift` while dragging.</Note>
|
||||
|
||||
Dragging and dropping workspace files into Cline will automatically create a [file mention](/features/at-mentions/file-mentions). This allows you to reference the file in your conversation without needing to type out the path.
|
||||
|
||||
### Dragging from Finder/File Explorer
|
||||
|
||||
You can drag files directly from your system's file manager into Cline:
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/drag-n-drop-finder.gif"
|
||||
alt="Dragging files from Finder into Cline"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
### Supported File Types
|
||||
|
||||
Cline supports dragging external images, pdfs, csv, excel, and other text files from your file system, as well as files from your workspace.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user