mirror of
https://github.com/cline/cline.git
synced 2026-09-14 10:41:33 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71da25835a | ||
|
|
8f79c7a714 | ||
|
|
db4bd8b24c | ||
|
|
1d8b99f900 | ||
|
|
b6e6d7afad | ||
|
|
a616b4c5f8 | ||
|
|
16774c7cd2 | ||
|
|
d5a577389d | ||
|
|
bba90e9af4 | ||
|
|
d566a79929 | ||
|
|
2484d24f97 | ||
|
|
b8f40f4edc | ||
|
|
f936d53d25 | ||
|
|
7dfe88072e | ||
|
|
90c8112257 | ||
|
|
83a2824103 | ||
|
|
86f463496c | ||
|
|
5198db81f7 | ||
|
|
576d126208 | ||
|
|
c878c663eb | ||
|
|
72562ea74e | ||
|
|
562b636481 | ||
|
|
544e3aa240 | ||
|
|
beb3ad78dc | ||
|
|
82faedead3 | ||
|
|
770f3e0807 | ||
|
|
79c6381893 | ||
|
|
c9d051cc0b | ||
|
|
a5d6bcecea | ||
|
|
289ddd6922 | ||
|
|
65d93eedab | ||
|
|
2928f68fd0 | ||
|
|
c1e07f26a9 | ||
|
|
17018066a7 | ||
|
|
54fc8e2a7e | ||
|
|
af35bd28b2 | ||
|
|
bce75f9821 | ||
|
|
ee1d4b4dcf | ||
|
|
f2eda58c70 | ||
|
|
4afc973f7d | ||
|
|
5fe6c9a8ce | ||
|
|
901d1b5c97 | ||
|
|
c139f7a4d5 | ||
|
|
07593bb42a | ||
|
|
fd21c314c1 | ||
|
|
32ca1cad9a | ||
|
|
e272a8dfbb | ||
|
|
c516230809 | ||
|
|
50021c8c5a | ||
|
|
b953c3682a | ||
|
|
852c65b70c | ||
|
|
70f0e8d548 | ||
|
|
f3f5bdd902 | ||
|
|
1d91dbc894 | ||
|
|
5accd88d73 | ||
|
|
5b29be63b8 | ||
|
|
401abd9434 | ||
|
|
79e99eb526 | ||
|
|
f1d2569931 | ||
|
|
efbacbbf33 | ||
|
|
69e6ab9069 | ||
|
|
9dea336ced | ||
|
|
697f801937 | ||
|
|
6be35bfcea | ||
|
|
5a91800b6c | ||
|
|
dacadbaae0 | ||
|
|
cfc5abca02 | ||
|
|
4da5614863 | ||
|
|
cef0da35e2 | ||
|
|
62fa67d833 | ||
|
|
4a57450c07 | ||
|
|
8d020e89e6 | ||
|
|
c6dbc8bcb0 | ||
|
|
1862f15955 | ||
|
|
f6a9a02500 | ||
|
|
10af2439be | ||
|
|
9a8fbf9852 | ||
|
|
c5657a14bb | ||
|
|
955ae8df7a | ||
|
|
9405419efe | ||
|
|
f53dcb3096 | ||
|
|
afa32bf801 | ||
|
|
2d2d9d829a | ||
|
|
27a1b3da8a | ||
|
|
f5c8cd4384 | ||
|
|
fddabb6b8d | ||
|
|
071f32ec92 | ||
|
|
9bdb8a9362 | ||
|
|
2d994530fd | ||
|
|
e477f8fa04 | ||
|
|
36b0baec81 | ||
|
|
a0faf7c677 | ||
|
|
1dcf356f98 | ||
|
|
71d795eec8 | ||
|
|
792b9e89a1 | ||
|
|
10197b038d | ||
|
|
9390d3f933 | ||
|
|
5df470bf48 | ||
|
|
034c4342d1 | ||
|
|
349295ab2c | ||
|
|
841402c178 | ||
|
|
e52a052c81 | ||
|
|
7a91a9be2e | ||
|
|
93a494d009 | ||
|
|
2bd21f8a45 | ||
|
|
2f33f71ebd | ||
|
|
dec10aaec3 | ||
|
|
c09705a45f | ||
|
|
73058c871a | ||
|
|
03211f1364 | ||
|
|
65e9727c65 | ||
|
|
884fbfb21e | ||
|
|
0c880c7bb1 | ||
|
|
a915122c6d | ||
|
|
835ed94736 | ||
|
|
00ca3d13fa | ||
|
|
3f3a87aed9 | ||
|
|
7a0f11837e | ||
|
|
03d2d01eed | ||
|
|
db1b1c45bd | ||
|
|
a4131e57d8 | ||
|
|
683dd9a741 | ||
|
|
0d437f71b0 | ||
|
|
fc77c0faea | ||
|
|
12c85c4233 | ||
|
|
d6b7a1ab41 | ||
|
|
3926e7b404 | ||
|
|
5ba4314b9a | ||
|
|
9ccad7f764 | ||
|
|
3562f54dbf | ||
|
|
d427d5d76a | ||
|
|
072e2887b0 | ||
|
|
9c71a6f021 | ||
|
|
7627a382aa | ||
|
|
978c633c90 | ||
|
|
e807b520e0 | ||
|
|
f3a3f30db5 | ||
|
|
f1c7934064 | ||
|
|
1d42da5248 | ||
|
|
7f3974a827 | ||
|
|
d40ab56aff | ||
|
|
bbdf445db7 | ||
|
|
d992a3bf21 | ||
|
|
ace95988f8 | ||
|
|
54726f1677 | ||
|
|
6308fef0a9 | ||
|
|
b3fc79b8ce | ||
|
|
ff05ec3bbe | ||
|
|
bde7049c01 | ||
|
|
7cd06744ad | ||
|
|
c88d3238cf | ||
|
|
852ca2348f | ||
|
|
7091ccf2c7 | ||
|
|
ad6c33ac5b | ||
|
|
71e312e92a | ||
|
|
5903840f79 | ||
|
|
0c677b63db |
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "PostToolUse running inside local cline/.clinerules/hooks/ directory"
|
||||
|
||||
input=$(cat)
|
||||
echo $input | jq .
|
||||
|
||||
for i in {1..5}; do
|
||||
sleep 1
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"cancel": false,
|
||||
"contextModification": "PostToolUse response from the local cline/.clinerules/hooks/ directory.",
|
||||
"errorMessage": "PostToolUse hook custom errorMessage"
|
||||
}
|
||||
EOF
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "PreToolUse running inside local cline/.clinerules/hooks/ directory"
|
||||
|
||||
input=$(cat)
|
||||
echo $input | jq .
|
||||
|
||||
for i in {1..5}; do
|
||||
sleep 1
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"cancel": false,
|
||||
"contextModification": "PreToolUse response from the local cline/.clinerules/hooks/ directory.",
|
||||
"errorMessage": "PreToolUse hook custom errorMessage"
|
||||
}
|
||||
EOF
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "TaskCancel running inside local cline/.clinerules/hooks/ directory"
|
||||
|
||||
input=$(cat)
|
||||
echo $input | jq .
|
||||
|
||||
for i in {1..5}; do
|
||||
sleep 1
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"cancel": false,
|
||||
"contextModification": "TaskCancel response from the local cline/.clinerules/hooks/ directory.",
|
||||
"errorMessage": "TaskCancel hook custom errorMessage"
|
||||
}
|
||||
EOF
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "TaskResume running inside local cline/.clinerules/hooks/ directory"
|
||||
|
||||
input=$(cat)
|
||||
echo $input | jq .
|
||||
|
||||
for i in {1..5}; do
|
||||
sleep 1
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"cancel": false,
|
||||
"contextModification": "TaskResume response from the local cline/.clinerules/hooks/ directory.",
|
||||
"errorMessage": "TaskResume hook custom errorMessage"
|
||||
}
|
||||
EOF
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "TaskStart running inside local cline/.clinerules/hooks/ directory"
|
||||
|
||||
input=$(cat)
|
||||
echo $input | jq .
|
||||
|
||||
for i in {1..5}; do
|
||||
sleep 1
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"cancel": false,
|
||||
"contextModification": "TaskStart response from the local cline/.clinerules/hooks/ directory.",
|
||||
"errorMessage": "TaskStart hook custom errorMessage"
|
||||
}
|
||||
EOF
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "UserPromptSubmit running inside local cline/.clinerules/hooks/ directory"
|
||||
|
||||
input=$(cat)
|
||||
echo $input | jq .
|
||||
|
||||
for i in {1..5}; do
|
||||
sleep 1
|
||||
echo "$i"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"cancel": false,
|
||||
"contextModification": "UserPromptSubmit response from the local cline/.clinerules/hooks/ directory.",
|
||||
"errorMessage": "UserPromptSubmit hook custom errorMessage"
|
||||
}
|
||||
EOF
|
||||
@@ -125,38 +125,6 @@ ERROR_SERVICE_API_KEY=your-posthog-error-tracking-api-key
|
||||
# E2E_TEST=true
|
||||
# IS_TEST=true
|
||||
|
||||
# ============================================================================
|
||||
# REMOTE WORKSPACE LATENCY TUNING / DEBUGGING
|
||||
# ============================================================================
|
||||
# These are internal rollout/debug flags for the remote-workspace latency work.
|
||||
# Leave them unset unless you're explicitly validating latency behavior.
|
||||
|
||||
# Enable extra scheduler latency debug logging
|
||||
# CLINE_DEBUG_LATENCY=1
|
||||
|
||||
# Disable individual latency features for A/B validation
|
||||
# CLINE_DISABLE_PRESENTATION_SCHEDULER=true
|
||||
# CLINE_DISABLE_EPHEMERAL_MESSAGE_PERSISTENCE=true
|
||||
# CLINE_DISABLE_TASK_UI_DELTA_SYNC=true
|
||||
|
||||
# Override scheduler cadences (milliseconds)
|
||||
# CLINE_PRESENTATION_CADENCE_MS=40
|
||||
# CLINE_PRESENTATION_LOW_CADENCE_MS=125
|
||||
# CLINE_REMOTE_PRESENTATION_CADENCE_MS=90
|
||||
# CLINE_REMOTE_PRESENTATION_LOW_CADENCE_MS=125
|
||||
# CLINE_STATE_UPDATE_CADENCE_MS=16
|
||||
# CLINE_STATE_UPDATE_LOW_CADENCE_MS=150
|
||||
# CLINE_REMOTE_STATE_UPDATE_CADENCE_MS=110
|
||||
# CLINE_REMOTE_STATE_UPDATE_LOW_CADENCE_MS=150
|
||||
# CLINE_USAGE_UPDATE_CADENCE_MS=250
|
||||
# CLINE_REMOTE_USAGE_UPDATE_CADENCE_MS=400
|
||||
|
||||
# Override request-boundary cache TTLs (milliseconds)
|
||||
# CLINE_REQUEST_BOUNDARY_CACHE_TTL_MS=500
|
||||
# CLINE_REMOTE_REQUEST_BOUNDARY_CACHE_TTL_MS=1000
|
||||
# CLINE_ENVIRONMENT_DETAILS_STATIC_CACHE_TTL_MS=30000
|
||||
# CLINE_REMOTE_ENVIRONMENT_DETAILS_STATIC_CACHE_TTL_MS=60000
|
||||
|
||||
# ============================================================================
|
||||
# USAGE INSTRUCTIONS
|
||||
# ============================================================================
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
demo.gif filter=lfs diff=lfs merge=lfs -text
|
||||
assets/docs/demo.gif filter=lfs diff=lfs merge=lfs -text
|
||||
webview-ui/src/assets/cline_kanban_demo.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
webview-ui/src/assets/cline_kanban_demo.webm filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
* text=auto eol=lf
|
||||
|
||||
@@ -26,6 +26,12 @@ body:
|
||||
placeholder: 'e.g., 1.2.3'
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: beta
|
||||
attributes:
|
||||
label: Beta version
|
||||
options:
|
||||
- label: I am using a beta version of Cline
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
|
||||
@@ -51,3 +51,15 @@ jobs:
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check if beta version checkbox is checked
|
||||
if (body.includes('- [X] I am using a beta version of Cline') || body.includes('- [x] I am using a beta version of Cline')) {
|
||||
if (!labels.includes('beta')) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['beta']
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,3 +91,21 @@ jobs:
|
||||
echo ""
|
||||
echo "📦 Install with: npm install -g cline"
|
||||
echo "🔗 NPM: https://www.npmjs.com/package/cline/v/${{ steps.version.outputs.version }}"
|
||||
|
||||
- name: Post release to Slack
|
||||
uses: slackapi/slack-github-action@v3.0.1
|
||||
with:
|
||||
method: chat.postMessage
|
||||
token: ${{ secrets.SLACK_RELEASE_BOT_TOKEN }}
|
||||
payload: |
|
||||
channel: "C0APVKGGZFC"
|
||||
text: "Cline CLI v${{ steps.version.outputs.version }}"
|
||||
blocks:
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: "*Cline CLI v${{ steps.version.outputs.version }}*"
|
||||
- type: "context"
|
||||
elements:
|
||||
- type: "mrkdwn"
|
||||
text: "<https://www.npmjs.com/package/cline/v/${{ steps.version.outputs.version }}|View on npm>"
|
||||
|
||||
@@ -31,8 +31,10 @@ jobs:
|
||||
|
||||
- name: Check for recent commits
|
||||
id: check_commits
|
||||
env:
|
||||
FORCE_PUBLISH: ${{ inputs.force_publish }}
|
||||
run: |
|
||||
if [ "${{ inputs.force_publish }}" = "true" ]; then
|
||||
if [ "$FORCE_PUBLISH" = "true" ]; then
|
||||
echo "force_publish enabled, proceeding with publish"
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
name: "Publish SDK Nightly Release"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 12 * * *' # 4 AM PST (UTC-8) = 12 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
checks: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
# Keep the publish source pinned to one reviewed branch instead of accepting arbitrary refs.
|
||||
SDK_NIGHTLY_REF: dpc/sdk-migration-simpler-login
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish Cline (Nightly SDK) Extension
|
||||
if: github.repository == 'cline/cline' && github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
environment: PublishNightly
|
||||
|
||||
steps:
|
||||
- name: Checkout trusted SDK nightly branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ env.SDK_NIGHTLY_REF }}
|
||||
lfs: true
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
# Keep publish environment aligned with test workflow/tooling lockfile expectations.
|
||||
# Newer LTS (Node 24 / npm 11) can make `npm list` fail with ELSPROBLEMS during vsce packaging.
|
||||
node-version: 22
|
||||
|
||||
- name: Install root dependencies
|
||||
run: npm ci --include=optional
|
||||
|
||||
- name: Install webview-ui dependencies
|
||||
run: cd webview-ui && npm ci --include=optional
|
||||
|
||||
- name: Install Publishing Tools
|
||||
run: npm install -g @vscode/vsce ovsx
|
||||
|
||||
- name: Verify LFS media assets are resolved
|
||||
run: |
|
||||
for FILE in webview-ui/src/assets/cline_kanban_demo.mp4 webview-ui/src/assets/cline_kanban_demo.webm; do
|
||||
if grep -q "git-lfs.github.com/spec/v1" "$FILE"; then
|
||||
echo "Error: $FILE is still a Git LFS pointer in CI checkout"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Publish SDK nightly extension
|
||||
env:
|
||||
VSCE_PAT: ${{ secrets.VSCE_PAT }}
|
||||
OVSX_PAT: ${{ secrets.OVSX_PAT }}
|
||||
TELEMETRY_SERVICE_API_KEY: ${{ secrets.TELEMETRY_SERVICE_API_KEY }}
|
||||
ERROR_SERVICE_API_KEY: ${{ secrets.ERROR_SERVICE_API_KEY }}
|
||||
CLINE_ENVIRONMENT: production
|
||||
# OpenTelemetry production defaults (can be overridden at runtime)
|
||||
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
|
||||
OTEL_LOGS_EXPORTER: otlp
|
||||
OTEL_METRICS_EXPORTER: otlp
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
|
||||
run: npm run publish:marketplace:nightly
|
||||
@@ -1,8 +1,6 @@
|
||||
name: "Publish Nightly Release"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 12 * * *' # 4 AM PST (UTC-8) = 12 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -24,6 +22,8 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
- name: Check for recent commits
|
||||
run: |
|
||||
@@ -49,7 +49,16 @@ jobs:
|
||||
- name: Install Publishing Tools
|
||||
run: npm install -g @vscode/vsce ovsx
|
||||
|
||||
- name: Publish Extension as Pre-release
|
||||
- name: Verify LFS media assets are resolved
|
||||
run: |
|
||||
for FILE in webview-ui/src/assets/cline_kanban_demo.mp4 webview-ui/src/assets/cline_kanban_demo.webm; do
|
||||
if grep -q "git-lfs.github.com/spec/v1" "$FILE"; then
|
||||
echo "Error: $FILE is still a Git LFS pointer in CI checkout"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Publish Nightly Extension
|
||||
env:
|
||||
VSCE_PAT: ${{ secrets.VSCE_PAT }}
|
||||
OVSX_PAT: ${{ secrets.OVSX_PAT }}
|
||||
|
||||
@@ -43,12 +43,14 @@ jobs:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
lfs: true
|
||||
|
||||
- name: Resolve Release Tag
|
||||
id: resolve_tag
|
||||
env:
|
||||
TAG: ${{ github.event.inputs.tag }}
|
||||
AUTO_CREATE: ${{ github.event.inputs.auto_create_tag_from_main }}
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.tag }}"
|
||||
AUTO_CREATE="${{ github.event.inputs.auto_create_tag_from_main }}"
|
||||
TESTED_SHA="${{ github.sha }}"
|
||||
WORKFLOW_REF="${{ github.ref }}"
|
||||
|
||||
@@ -133,6 +135,15 @@ jobs:
|
||||
fi
|
||||
echo "Tag and package version match: $TAG"
|
||||
|
||||
- name: Verify LFS media assets are resolved
|
||||
run: |
|
||||
for FILE in webview-ui/src/assets/cline_kanban_demo.mp4 webview-ui/src/assets/cline_kanban_demo.webm; do
|
||||
if grep -q "git-lfs.github.com/spec/v1" "$FILE"; then
|
||||
echo "Error: $FILE is still a Git LFS pointer in CI checkout"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Package and Publish Extension
|
||||
env:
|
||||
VSCE_PAT: ${{ secrets.VSCE_PAT }}
|
||||
@@ -147,11 +158,12 @@ jobs:
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
|
||||
RELEASE_TYPE: ${{ github.event.inputs.release-type }}
|
||||
run: |
|
||||
# Required to generate the .vsix
|
||||
vsce package --allow-package-secrets sendgrid --out "cline-${{ steps.get_version.outputs.version }}.vsix"
|
||||
|
||||
if [ "${{ github.event.inputs.release-type }}" = "pre-release" ]; then
|
||||
if [ "$RELEASE_TYPE" = "pre-release" ]; then
|
||||
npm run publish:marketplace:prerelease
|
||||
echo "Successfully published pre-release version ${{ steps.get_version.outputs.version }} to VS Code Marketplace and Open VSX Registry"
|
||||
else
|
||||
@@ -187,3 +199,25 @@ jobs:
|
||||
prerelease: ${{ github.event.inputs.release-type == 'pre-release' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Post release to Slack
|
||||
uses: slackapi/slack-github-action@v3.0.1
|
||||
with:
|
||||
method: chat.postMessage
|
||||
token: ${{ secrets.SLACK_RELEASE_BOT_TOKEN }}
|
||||
payload: |
|
||||
channel: "C0APVKGGZFC"
|
||||
text: "Cline ${{ steps.resolve_tag.outputs.tag }}"
|
||||
blocks:
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: "*Cline ${{ steps.resolve_tag.outputs.tag }}*"
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: ${{ toJSON(steps.changelog.outputs.content) }}
|
||||
- type: "context"
|
||||
elements:
|
||||
- type: "mrkdwn"
|
||||
text: "Full Changelog: https://github.com/${{ github.repository }}/compare/${{ steps.prev_tag.outputs.prev_tag }}...${{ steps.resolve_tag.outputs.tag }}"
|
||||
|
||||
@@ -46,6 +46,8 @@ jobs:
|
||||
|
||||
test:
|
||||
needs: quality-checks
|
||||
env:
|
||||
VSCODE_TEST_VERSION: 1.103.0
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -81,6 +83,13 @@ jobs:
|
||||
run: |
|
||||
npm config set script-shell "C:\\Program Files\\Git\\bin\\bash.exe"
|
||||
|
||||
- name: Cache VS Code test runtime
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .vscode-test
|
||||
key: vscode-test-runtime-${{ runner.os }}-${{ env.VSCODE_TEST_VERSION }}
|
||||
|
||||
# Build the extension and tests (without redundant checks)
|
||||
- name: Build Tests and Extension
|
||||
id: build_step
|
||||
@@ -106,7 +115,21 @@ jobs:
|
||||
- name: Extension Integration Tests - Non-Linux
|
||||
id: integration_tests_non_linux
|
||||
if: ${{ !cancelled() && steps.build_step.outcome == 'success' && runner.os != 'Linux' }}
|
||||
run: npm run test:integration
|
||||
run: |
|
||||
for attempt in 1 2 3; do
|
||||
echo "Running extension integration tests (attempt ${attempt}/3)"
|
||||
if npm run test:integration; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$attempt" -eq 3 ]; then
|
||||
echo "Extension integration tests failed after 3 attempts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Extension integration tests failed; retrying after short delay"
|
||||
sleep 5
|
||||
done
|
||||
|
||||
- name: Webview Tests with Coverage
|
||||
id: webview_tests
|
||||
|
||||
+2
-1
@@ -3,7 +3,8 @@
|
||||
"ts"
|
||||
],
|
||||
"spec": [
|
||||
"src/**/__tests__/*.ts"
|
||||
"src/**/__tests__/*.ts",
|
||||
"src/test/services/**/*.test.ts"
|
||||
],
|
||||
"require": [
|
||||
"ts-node/register",
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
import { defineConfig } from "@vscode/test-cli"
|
||||
import path from "path"
|
||||
|
||||
const vscodeTestVersion = process.env.VSCODE_TEST_VERSION ?? "stable"
|
||||
|
||||
export default defineConfig({
|
||||
files: "{out/**/*.test.js,src/**/*.test.js,!src/test/e2e/**/*.test.js,!out/src/test/e2e/**/*.test.js}",
|
||||
mocha: {
|
||||
@@ -12,7 +14,7 @@ export default defineConfig({
|
||||
require: ["./test-setup.js"],
|
||||
},
|
||||
workspaceFolder: "test-workspace",
|
||||
version: "stable",
|
||||
version: vscodeTestVersion,
|
||||
extensionDevelopmentPath: path.resolve("./"),
|
||||
launchArgs: ["--disable-extensions"],
|
||||
})
|
||||
|
||||
+140
@@ -1,5 +1,145 @@
|
||||
# Changelog
|
||||
|
||||
## [3.82.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Restore VS Code foreground terminal support and settings.
|
||||
- Add latest OpenAI, SAP AI Core, and Z AI models.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix hook template JSON escaping.
|
||||
- Improve ripgrep file search error handling.
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove hardcoded model lists from docs.
|
||||
|
||||
## [3.81.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Add GPT-5.5 model support for OpenAI Codex subscription users.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Remove hardcoded "What’s New" fallback items in webview; only remote-configured welcome banners are shown.
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve cline-core memory diagnostics used by the extension runtime:
|
||||
- enable near-heap-limit heap snapshots
|
||||
- add periodic memory usage logging
|
||||
- log discovered heap snapshots on abnormal exits for easier OOM debugging
|
||||
|
||||
## [3.80.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Wire up remote `globalSkills` from enterprise remote config with full UI, toggle support, and system prompt integration — enterprise-managed skills now appear under a dedicated "Enterprise Skills" section and support `alwaysEnabled` enforcement
|
||||
- Onboarding flow now uses dynamically fetched recommended models instead of a hardcoded list, with a fallback to the welcome view on failure
|
||||
- Add dedicated "Quota Exceeded" error message in the chat error UI when Cline account spend caps are hit
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix OOM crashes during long conversations by setting `--max-old-space-size=8192` for the cline-core Node.js process (was defaulting to ~2 GB)
|
||||
- Show detailed error information in the chat error row instead of a generic caught error message
|
||||
- Update `axios` to 1.15.0 across all packages
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove foreground terminal mode — all task command execution now defaults to background mode, removing the VS Code integrated terminal dependency and related settings UI
|
||||
- Remove old hardcoded announcement banners
|
||||
|
||||
## [3.79.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Add Claude Opus 4.7 model support
|
||||
- Add Azure Blob Storage as a storage provider
|
||||
- Add `globalSkills` to remote config
|
||||
- Inline value reuse in user-level remote-config discovery
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix cache reflection for Cline and Vercel API handlers
|
||||
- Fix stuck `command_output` ask when terminal command ends unexpectedly
|
||||
- Add `use_subagents` to system prompt for GLM, Hermes, and XS models
|
||||
- Fix action injection security risk
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove deprecated evals tool
|
||||
|
||||
## [3.78.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Add a dedicated "Spend Limit Reached" error UI when spend caps are hit
|
||||
- Docs updates
|
||||
|
||||
### Fixed
|
||||
|
||||
- Show actual `read_file` line ranges in chat UI
|
||||
|
||||
## [3.77.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Add "Lazy Teammate Mode" experimental toggle
|
||||
- `read_file` tool now supports chunked reading for targeted file access
|
||||
|
||||
### Fixed
|
||||
|
||||
- Exclude `new_task` tool from system prompt in yolo/headless mode
|
||||
- Fix Kanban demo video formatting
|
||||
|
||||
### Changed
|
||||
|
||||
- Polish `Notification` hook functionality
|
||||
|
||||
## [3.76.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Add Cline Kanban launch modal in webview; CLI now launches Kanban by default with a migration view
|
||||
- Add toggle to disable feature tips in chat
|
||||
- Add repeated tool call loop detection to prevent infinite loops wasting tokens
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix CLI Kanban spawn on Windows by enabling shell mode for `npx.cmd`
|
||||
|
||||
## [3.75.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Latency improvements for remote workspaces
|
||||
|
||||
### Fixed
|
||||
|
||||
- Stabilize flaky hooks tests
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove example hooks in favor of reading the docs
|
||||
|
||||
## [3.74.0]
|
||||
|
||||
### Added
|
||||
- Implement dynamic free model detection for Cline API
|
||||
- Add file read deduplication cache to prevent repeated reads
|
||||
- Add feature tips tooltip during thinking state
|
||||
|
||||
### Fixed
|
||||
- Replace error message when not logged in to Cline
|
||||
- Align ClineRulesToggleModal padding with ServersToggleModal
|
||||
- Skip WebP for GLM and Devstral models running through llama.cpp
|
||||
- Respect user-configured context window in LiteLLM getModel()
|
||||
- Honor explicit model IDs outside static catalog in W&B provider
|
||||
- Add missing Fireworks serverless models and pricing
|
||||
|
||||
## [3.73.0]
|
||||
|
||||
### Added
|
||||
|
||||
@@ -3,11 +3,6 @@ English | <a href="https://github.com/cline/cline/blob/main/locales/es/README.md
|
||||
</sub></div>
|
||||
|
||||
# Cline
|
||||
|
||||
<p align="center">
|
||||
<img src="https://media.githubusercontent.com/media/cline/cline/main/assets/docs/demo.gif" width="100%" />
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
<table>
|
||||
<tbody>
|
||||
|
||||
+3
-5
@@ -8,9 +8,7 @@ We actively patch only the most recent minor release of Cline. Older versions re
|
||||
|
||||
We appreciate your efforts to responsibly disclose your findings and will make every effort to acknowledge your contributions.
|
||||
|
||||
To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/cline/cline/security/advisories/new) tab.
|
||||
|
||||
The team will send a response indicating the next steps in handling your report. After the initial reply, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
|
||||
To report a security issue, please submit your report through our [Bugcrowd Vulnerability Disclosure Program](https://bugcrowd.com/engagements/clinebot-vdp-ess). Bugcrowd will manage communication and triage on our behalf.
|
||||
|
||||
When reporting, please include:
|
||||
|
||||
@@ -18,10 +16,10 @@ When reporting, please include:
|
||||
- Steps to reproduce or a proof of concept
|
||||
- Any logs, stack traces, or screenshots that might help us understand the problem
|
||||
|
||||
We acknowledge reports within 48 hours and aim to release a fix or mitigation within 30 days. While we work on a resolution, please keep the details private.
|
||||
Please keep the details private until a resolution has been reached.
|
||||
|
||||
## Escalation
|
||||
|
||||
If you do not receive an acknowledgement of your report within 5 business days, you may send an email to security@cline.bot.
|
||||
If you are unable to submit through Bugcrowd, you may send an email to security@cline.bot.
|
||||
|
||||
Thank you for helping us keep Cline users safe.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 512 535">
|
||||
<!-- Generator: Adobe Illustrator 29.8.5, SVG Export Plug-In . SVG Version: 2.1.1 Build 2) -->
|
||||
<defs>
|
||||
<style>
|
||||
.st0 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="st0" d="M500.6,300.5c-9-20.7-17.9-41.4-26.9-62.1-.7-2-.3-4.4-.3-6.4.4-9,1.1-18,1.4-27,2.8-28.4-6.5-58-25.2-79.6-15.1-18.1-36.6-30.7-59.6-35.5-8.1-1.8-16.6-1.6-25-2.1-10-.7-20-1-30-1.7,2-11.9,1-24.1-3.7-35.3-5.8-14.1-16.8-25.9-30.6-32.5-14.4-7-31.5-8.2-46.7-3.1-16,5.2-29.5,17-36.8,32.1-4.9,10-6.8,21.2-6.1,32.2-19.7-1-39.4-2.2-59.1-3.1-26.8.5-53,11.7-72,30.6-20.2,19.5-31.7,47-32.3,75-.5,9.3-1,18.7-1.5,28-.2,2.1,0,4.1-1.2,6-9.8,16.8-19.5,33.7-29.4,50.6-2.2,4.1-4.9,8-6.6,12.3-2,5.7-1.2,12.2,1.3,17.6,8.9,19.5,17.6,39.2,26.5,58.7.8,1.9,1.5,3.7,1.3,5.8-.6,10.3-1.1,20.7-1.7,31-1.5,21.2,3,42.6,13.5,61.1,8.8,15.8,21.6,29.4,37.1,38.9,13.9,8.7,29.7,13.9,46,15.4,72,3.9,144,7.7,216,11.5,20.1,1.8,40.8-2.8,58.5-12.5,18.8-10.1,34.2-26,44.1-44.9,6.5-12.6,10.5-26.4,11.7-40.5.7-12.4,1.2-24.7,2-37.1,0-3.3,1.9-5.5,3.3-8.2,6.6-11.8,13.5-23.4,20.1-35.2,3.7-6.9,8.1-13.4,11.6-20.4,3.2-6.1,3.2-13.5.3-19.7ZM218.5,316.5c-9.7,7.1-21.3,12.3-33.5,12.5-17.6,1-35.1-5.3-49-16-4.6-3.2-8.1-7.5-9.6-13,0-1.8-.7-3.6,1.7-3.8,4,1,7.9,2.6,12,3.5,22.8,5.6,47.6,5.9,71,4.8,6.5-.2,13-1.3,19.5-.9-2.7,5.6-7.1,9.2-12,12.9ZM276,449.7c-14,.5-28,.1-42-.2-2.1,0-4.3,0-6.4-.4-.9-2.1.6-3.2,1.7-4.8,4.8-5.9,11-11,18.7-12.4,8.4-1.6,16.5,1.2,23.5,5.5,4.7,3,9.2,6.3,12.6,10.8-2.6,1.1-5.3,1.4-8.1,1.4ZM390.4,319.4c-16.4,14.2-38.8,21.8-60.4,18.4-13.2-1.6-24.7-8.6-34.1-17.7-3-3-6.2-6.5-8.1-10.4.5-1,1.2-1.6,2.2-1.6,2.8-.2,5.7.7,8.5,1.1,16,2.9,32.3,4.9,48.5,5.5,14.3.4,28.2-.2,42.2-3.6,2.2-.6,3.7-.3,5.8.5-1.1,2.9-2.2,5.7-4.6,7.8Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -1,5 +1,115 @@
|
||||
# cline
|
||||
|
||||
## [2.18.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Restore foreground terminal support and settings.
|
||||
- Add latest OpenAI, SAP AI Core, and Z AI models.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix hook template JSON escaping.
|
||||
- Improve ripgrep file search error handling.
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove hardcoded model lists from docs.
|
||||
|
||||
## [2.17.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Add GPT-5.5 model support for OpenAI Codex subscription users.
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve `cline-core` runtime memory diagnostics used by CLI:
|
||||
- enable near-heap-limit heap snapshots
|
||||
- add periodic memory usage logging
|
||||
- log discovered heap snapshots on abnormal exits for easier OOM debugging
|
||||
|
||||
## [2.16.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Wire up remote `globalSkills` from enterprise remote config with full toggle support and system prompt integration — enterprise-managed skills now support `alwaysEnabled` enforcement
|
||||
- Add dedicated "Quota Exceeded" error message when Cline account spend caps are hit
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix OOM crashes during long conversations by setting `--max-old-space-size=8192` for the cline-core Node.js process (was defaulting to ~2 GB)
|
||||
- Show detailed error information instead of a generic caught error message
|
||||
- Update `axios` to 1.15.0 across all packages
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove dead ACP terminal setter stubs as part of foreground terminal mode removal
|
||||
|
||||
## [2.15.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Add Claude Opus 4.7 model support
|
||||
- Inline value reuse in user-level remote-config discovery
|
||||
- Add `globalSkills` to remote config
|
||||
|
||||
### Fixed
|
||||
|
||||
- Stabilize Windows CI test path handling
|
||||
|
||||
## [2.14.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Simplify unified `cline update` flow for `cline` and `kanban`
|
||||
- Docs updates
|
||||
|
||||
### Fixed
|
||||
|
||||
- Update Kanban migration view copy
|
||||
|
||||
## [2.12.0]
|
||||
|
||||
### Added
|
||||
|
||||
- `read_file` tool now supports chunked reading for targeted file access
|
||||
|
||||
### Fixed
|
||||
|
||||
- Exclude `new_task` tool from system prompt in yolo/headless mode
|
||||
|
||||
### Changed
|
||||
|
||||
- Polish `Notification` hook functionality
|
||||
|
||||
## [2.9.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Latency improvements for remote workspaces
|
||||
|
||||
## [2.8.2]
|
||||
|
||||
### Fixed
|
||||
- Use `kanban@latest` in `cline kanban` to always fetch the newest version
|
||||
|
||||
## [2.8.1]
|
||||
|
||||
### Added
|
||||
- Implement dynamic free model detection for Cline API
|
||||
- Add file read deduplication cache to prevent repeated reads
|
||||
- Add feature tips tooltip during thinking state
|
||||
|
||||
### Fixed
|
||||
- Fix flaky CLI Enter-key handling across Windows/test environments
|
||||
- Replace error message when not logged in to Cline
|
||||
- Align ClineRulesToggleModal padding with ServersToggleModal
|
||||
- Skip WebP for GLM and Devstral models running through llama.cpp
|
||||
- Respect user-configured context window in LiteLLM getModel()
|
||||
- Honor explicit model IDs outside static catalog in W&B provider
|
||||
- Add missing Fireworks serverless models and pricing
|
||||
|
||||
## [2.8.0]
|
||||
|
||||
### Added
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cline",
|
||||
"version": "2.8.0",
|
||||
"version": "2.18.0",
|
||||
"description": "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
|
||||
"main": "dist/lib.mjs",
|
||||
"types": "dist/lib.d.ts",
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Box, Text, useInput } from "ink"
|
||||
import React from "react"
|
||||
import { COLORS } from "../constants/colors"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { isMouseEscapeSequence } from "../utils/input"
|
||||
import { isEnterKey, isMouseEscapeSequence } from "../utils/input"
|
||||
|
||||
interface ApiKeyInputProps {
|
||||
providerName: string
|
||||
@@ -39,7 +39,7 @@ export const ApiKeyInput: React.FC<ApiKeyInputProps> = ({
|
||||
onCancel()
|
||||
return
|
||||
}
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
onSubmit(value)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import React, { useCallback, useEffect, useRef, useState } from "react"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { useTaskController } from "../context/TaskContext"
|
||||
import { useLastCompletedAskMessage } from "../hooks/useStateSubscriber"
|
||||
import { isMouseEscapeSequence } from "../utils/input"
|
||||
import { isEnterKey, isMouseEscapeSequence } from "../utils/input"
|
||||
import { jsonParseSafe } from "../utils/parser"
|
||||
|
||||
interface AskPromptProps {
|
||||
@@ -136,7 +136,7 @@ export const AskPrompt: React.FC<AskPromptProps> = ({ onRespond }) => {
|
||||
} else if (promptType === "options") {
|
||||
// Number selection for options, or free text input
|
||||
const parts = jsonParseSafe(text, { options: [] as string[] })
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
// Submit free text on Enter
|
||||
if (textInput.trim()) {
|
||||
sendResponse("messageResponse", textInput.trim())
|
||||
@@ -145,7 +145,7 @@ export const AskPrompt: React.FC<AskPromptProps> = ({ onRespond }) => {
|
||||
setTextInput((prev) => prev.slice(0, -1))
|
||||
} else if (input && !key.ctrl && !key.meta) {
|
||||
// Check if it's a number for option selection (only when no text typed yet)
|
||||
const num = parseInt(input, 10)
|
||||
const num = Number.parseInt(input, 10)
|
||||
if (textInput === "" && !Number.isNaN(num) && num >= 1 && num <= parts.options.length) {
|
||||
const selectedOption = parts.options[num - 1]
|
||||
sendResponse("messageResponse", selectedOption)
|
||||
@@ -156,7 +156,7 @@ export const AskPrompt: React.FC<AskPromptProps> = ({ onRespond }) => {
|
||||
}
|
||||
} else if (promptType === "text") {
|
||||
// Text input mode
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
// Submit on Enter
|
||||
if (textInput.trim()) {
|
||||
sendResponse("messageResponse", textInput.trim())
|
||||
@@ -169,7 +169,7 @@ export const AskPrompt: React.FC<AskPromptProps> = ({ onRespond }) => {
|
||||
}
|
||||
} else if (promptType === "plan_mode_text") {
|
||||
// Plan mode text input - allows text response or toggle to Act mode
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
// Submit on Enter
|
||||
if (textInput.trim()) {
|
||||
sendResponse("messageResponse", textInput.trim())
|
||||
@@ -185,7 +185,7 @@ export const AskPrompt: React.FC<AskPromptProps> = ({ onRespond }) => {
|
||||
}
|
||||
} else if (promptType === "completion") {
|
||||
// Task completed - allow follow-up question or exit
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
if (textInput.trim()) {
|
||||
// Send follow-up question
|
||||
sendResponse("messageResponse", textInput.trim())
|
||||
@@ -401,43 +401,42 @@ function getCliMessagePrefixIcon(message: ClineMessage): string {
|
||||
default:
|
||||
return "❔"
|
||||
}
|
||||
} else {
|
||||
switch (message.say) {
|
||||
case "task":
|
||||
return "📋"
|
||||
case "error":
|
||||
return "❌"
|
||||
case "text":
|
||||
return "💬"
|
||||
case "reasoning":
|
||||
return "🧠"
|
||||
case "completion_result":
|
||||
return "✅"
|
||||
case "user_feedback":
|
||||
return "👤"
|
||||
case "command":
|
||||
case "command_output":
|
||||
return "⚙️"
|
||||
case "tool":
|
||||
return "🔧"
|
||||
case "browser_action":
|
||||
case "browser_action_launch":
|
||||
case "browser_action_result":
|
||||
return "🌐"
|
||||
case "mcp_server_request_started":
|
||||
case "mcp_server_response":
|
||||
return "🔌"
|
||||
case "api_req_started":
|
||||
case "api_req_finished":
|
||||
return "🔄"
|
||||
case "checkpoint_created":
|
||||
return "💾"
|
||||
case "info":
|
||||
return "ℹ️"
|
||||
case "generate_explanation":
|
||||
return "📝"
|
||||
default:
|
||||
return " "
|
||||
}
|
||||
}
|
||||
switch (message.say) {
|
||||
case "task":
|
||||
return "📋"
|
||||
case "error":
|
||||
return "❌"
|
||||
case "text":
|
||||
return "💬"
|
||||
case "reasoning":
|
||||
return "🧠"
|
||||
case "completion_result":
|
||||
return "✅"
|
||||
case "user_feedback":
|
||||
return "👤"
|
||||
case "command":
|
||||
case "command_output":
|
||||
return "⚙️"
|
||||
case "tool":
|
||||
return "🔧"
|
||||
case "browser_action":
|
||||
case "browser_action_launch":
|
||||
case "browser_action_result":
|
||||
return "🌐"
|
||||
case "mcp_server_request_started":
|
||||
case "mcp_server_response":
|
||||
return "🔌"
|
||||
case "api_req_started":
|
||||
case "api_req_finished":
|
||||
return "🔄"
|
||||
case "checkpoint_created":
|
||||
return "💾"
|
||||
case "info":
|
||||
return "ℹ️"
|
||||
case "generate_explanation":
|
||||
return "📝"
|
||||
default:
|
||||
return " "
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { useClineFeaturedModels } from "../hooks/useClineFeaturedModels"
|
||||
import { useOcaAuth } from "../hooks/useOcaAuth"
|
||||
import { useScrollableList } from "../hooks/useScrollableList"
|
||||
import { type DetectedSources, detectImportSources, type ImportSource } from "../utils/import-configs"
|
||||
import { isMouseEscapeSequence } from "../utils/input"
|
||||
import { isEnterKey, isMouseEscapeSequence } from "../utils/input"
|
||||
import { applyBedrockConfig, applyProviderConfig } from "../utils/provider-config"
|
||||
import { useValidProviders } from "../utils/providers"
|
||||
import { ApiKeyInput } from "./ApiKeyInput"
|
||||
@@ -79,12 +79,12 @@ const Select: React.FC<{
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
|
||||
useInput(
|
||||
(_, key) => {
|
||||
(input, key) => {
|
||||
if (key.upArrow) {
|
||||
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1))
|
||||
} else if (key.downArrow) {
|
||||
setSelectedIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
onSelect(items[selectedIndex].value)
|
||||
}
|
||||
},
|
||||
@@ -130,7 +130,7 @@ const TextInput: React.FC<{
|
||||
return
|
||||
}
|
||||
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
onSubmit(value)
|
||||
} else if (key.backspace || key.delete) {
|
||||
onChange(value.slice(0, -1))
|
||||
@@ -853,7 +853,7 @@ export const AuthView: React.FC<AuthViewProps> = ({ controller, onComplete, onEr
|
||||
setMenuIndex((prev) => (prev > 0 ? prev - 1 : mainMenuItems.length - 1))
|
||||
} else if (key.downArrow) {
|
||||
setMenuIndex((prev) => (prev < mainMenuItems.length - 1 ? prev + 1 : 0))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
handleMainMenuSelect(mainMenuItems[menuIndex].value)
|
||||
}
|
||||
} else if (step === "provider") {
|
||||
@@ -861,7 +861,7 @@ export const AuthView: React.FC<AuthViewProps> = ({ controller, onComplete, onEr
|
||||
setProviderIndex((prev) => (prev > 0 ? prev - 1 : providerItems.length - 1))
|
||||
} else if (key.downArrow) {
|
||||
setProviderIndex((prev) => (prev < providerItems.length - 1 ? prev + 1 : 0))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
if (providerItems[providerIndex]) {
|
||||
handleProviderSelect(providerItems[providerIndex].value)
|
||||
}
|
||||
@@ -877,7 +877,7 @@ export const AuthView: React.FC<AuthViewProps> = ({ controller, onComplete, onEr
|
||||
setClineModelIndex((prev) => (prev > 0 ? prev - 1 : maxIndex))
|
||||
} else if (key.downArrow) {
|
||||
setClineModelIndex((prev) => (prev < maxIndex ? prev + 1 : 0))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
if (isBrowseAllSelected(clineModelIndex, featuredModels)) {
|
||||
setStep("modelid")
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Box, Text, useInput } from "ink"
|
||||
import React, { useCallback, useState } from "react"
|
||||
import { COLORS } from "../constants/colors"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { isEnterKey } from "../utils/input"
|
||||
import { getModelList } from "./ModelPicker"
|
||||
import { SearchableList } from "./SearchableList"
|
||||
|
||||
@@ -43,7 +44,7 @@ export const BedrockCustomModelFlow: React.FC<BedrockCustomModelFlowProps> = ({
|
||||
if (step === "arn_input") {
|
||||
if (key.escape) {
|
||||
onCancel()
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
handleArnSubmit()
|
||||
} else if (key.backspace || key.delete) {
|
||||
setCustomArn((prev) => prev.slice(0, -1))
|
||||
|
||||
@@ -1492,13 +1492,12 @@ export const ChatView: React.FC<ChatViewProps> = ({
|
||||
if (item.type === "header") {
|
||||
// Show static robot frame in header (first frame, looking straight ahead)
|
||||
return (
|
||||
<Box flexDirection="column" key="header">
|
||||
<Box flexDirection="column" key="header" marginBottom={1}>
|
||||
<StaticRobotFrame />
|
||||
<Text> </Text>
|
||||
<Text bold color="white">
|
||||
{centerText("What can I do for you?")}
|
||||
</Text>
|
||||
<Text> </Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { ClineMessage } from "@shared/ExtensionMessage"
|
||||
import { Box, Text, useInput } from "ink"
|
||||
import React, { useState } from "react"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { isEnterKey } from "../utils/input"
|
||||
|
||||
export type RestoreType = "task" | "workspace" | "taskAndWorkspace"
|
||||
|
||||
@@ -101,7 +102,7 @@ export const CheckpointMenu: React.FC<CheckpointMenuProps> = ({ messages, onSele
|
||||
setSelectedCheckpoint((i) => Math.max(0, i - 1))
|
||||
} else if (key.downArrow) {
|
||||
setSelectedCheckpoint((i) => Math.min(checkpoints.length - 1, i + 1))
|
||||
} else if (key.return && checkpoints.length > 0) {
|
||||
} else if (isEnterKey(input, key) && checkpoints.length > 0) {
|
||||
setStage("restoreType")
|
||||
}
|
||||
} else if (stage === "restoreType") {
|
||||
@@ -109,7 +110,7 @@ export const CheckpointMenu: React.FC<CheckpointMenuProps> = ({ messages, onSele
|
||||
setSelectedRestoreType((i) => Math.max(0, i - 1))
|
||||
} else if (key.downArrow) {
|
||||
setSelectedRestoreType((i) => Math.min(RESTORE_TYPE_OPTIONS.length - 1, i + 1))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
const checkpoint = checkpoints[selectedCheckpoint]
|
||||
const restoreType = RESTORE_TYPE_OPTIONS[selectedRestoreType]
|
||||
if (checkpoint && restoreType) {
|
||||
@@ -120,7 +121,7 @@ export const CheckpointMenu: React.FC<CheckpointMenuProps> = ({ messages, onSele
|
||||
|
||||
// Quick number selection for checkpoints
|
||||
if (stage === "checkpoint") {
|
||||
const num = parseInt(input, 10)
|
||||
const num = Number.parseInt(input, 10)
|
||||
if (!Number.isNaN(num) && num >= 1 && num <= checkpoints.length) {
|
||||
setSelectedCheckpoint(num - 1)
|
||||
setStage("restoreType")
|
||||
|
||||
@@ -56,7 +56,13 @@ export interface ObjectEditorState {
|
||||
editValue: string
|
||||
}
|
||||
|
||||
export const EXCLUDED_KEYS = new Set(["taskHistory", "primaryRootIndex", "welcomeViewCompleted", "isNewUser"])
|
||||
export const EXCLUDED_KEYS = new Set([
|
||||
"taskHistory",
|
||||
"primaryRootIndex",
|
||||
"welcomeViewCompleted",
|
||||
"isNewUser",
|
||||
"cliKanbanMigrationAnnouncementShown",
|
||||
])
|
||||
|
||||
export const EDITABLE_TYPES: Set<ValueType> = new Set(["string", "number", "boolean", "object"])
|
||||
export const MAX_VISIBLE = 12
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Rotating feature tips shown during thinking/acting phases.
|
||||
* Appears after a brief delay and cycles through tips to educate users
|
||||
* about Cline features while they wait.
|
||||
*/
|
||||
|
||||
import { Box, Text } from "ink"
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react"
|
||||
|
||||
interface FeatureTipItem {
|
||||
text: string
|
||||
}
|
||||
|
||||
const FEATURE_TIPS: FeatureTipItem[] = [
|
||||
{
|
||||
text: 'Enable "Double-Check Completion" in settings to have Cline verify its work before finishing a task.',
|
||||
},
|
||||
{
|
||||
text: "Add a .clinerules file to your project root to give Cline project-specific instructions.",
|
||||
},
|
||||
{
|
||||
text: "Press Tab to switch between Plan and Act mode — plan an approach before Cline takes action.",
|
||||
},
|
||||
{
|
||||
text: "Use @ in the chat input to add files, folders, or URLs as context for your task.",
|
||||
},
|
||||
{
|
||||
text: "Set up MCP Servers to give Cline access to external tools and APIs.",
|
||||
},
|
||||
{
|
||||
text: "Cline creates checkpoints after changes — you can always restore to a previous state.",
|
||||
},
|
||||
{
|
||||
text: "Use /compact to condense long conversations and free up context window space.",
|
||||
},
|
||||
{
|
||||
text: "Enable auto-approve for read-only tools like file reads to speed up exploration.",
|
||||
},
|
||||
{
|
||||
text: "Use /settings to configure your API provider and model without leaving the terminal.",
|
||||
},
|
||||
{
|
||||
text: "You can pass images with --images flag or paste image file paths in the chat.",
|
||||
},
|
||||
{
|
||||
text: "Cline can browse websites — ask it to test your local dev server in the browser.",
|
||||
},
|
||||
{
|
||||
text: "Use /reportbug to quickly file a GitHub issue with diagnostic context included.",
|
||||
},
|
||||
{
|
||||
text: "Try 'npm i -g cline' to manage tasks on a Kankan board — orchestrate coding agents across worktrees.",
|
||||
},
|
||||
{
|
||||
text: "Use Shift+Tab to toggle auto-approve all — let Cline work uninterrupted on trusted tasks.",
|
||||
},
|
||||
{
|
||||
text: "Press Up/Down arrows in an empty input to browse your previous task prompts.",
|
||||
},
|
||||
{
|
||||
text: "Type / to see all available commands — /history, /compact, /settings, and more.",
|
||||
},
|
||||
{
|
||||
text: "Use /skills to browse and attach reusable skill files that guide Cline's behavior.",
|
||||
},
|
||||
{
|
||||
text: 'You can disable these tips in /settings → Features → "Feature tips".',
|
||||
},
|
||||
]
|
||||
|
||||
const SHOW_DELAY_MS = 2000
|
||||
const CYCLE_INTERVAL_MS = 8000
|
||||
|
||||
/**
|
||||
* Shows rotating feature tips below the thinking indicator.
|
||||
* Appears after a brief delay and cycles through tips while Cline is thinking/acting.
|
||||
*/
|
||||
export const FeatureTip: React.FC = React.memo(() => {
|
||||
const [isVisible, setIsVisible] = useState(false)
|
||||
const [tipIndex, setTipIndex] = useState(Math.floor(Math.random() * FEATURE_TIPS.length))
|
||||
const cycleTimerRef = useRef<ReturnType<typeof setInterval> | null>(null)
|
||||
const showTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
|
||||
const currentTip = FEATURE_TIPS[tipIndex]
|
||||
|
||||
const advanceTip = useCallback(() => {
|
||||
setTipIndex((prev) => (prev + 1) % FEATURE_TIPS.length)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
showTimerRef.current = setTimeout(() => {
|
||||
setIsVisible(true)
|
||||
cycleTimerRef.current = setInterval(advanceTip, CYCLE_INTERVAL_MS)
|
||||
}, SHOW_DELAY_MS)
|
||||
|
||||
return () => {
|
||||
if (showTimerRef.current) {
|
||||
clearTimeout(showTimerRef.current)
|
||||
}
|
||||
if (cycleTimerRef.current) {
|
||||
clearInterval(cycleTimerRef.current)
|
||||
}
|
||||
}
|
||||
}, [advanceTip])
|
||||
|
||||
if (!isVisible) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Box paddingLeft={1}>
|
||||
<Text color="gray">
|
||||
💡 <Text bold>Tip:</Text> {currentTip.text}
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
@@ -13,7 +13,7 @@ import { showTaskWithId } from "@/core/controller/task/showTaskWithId"
|
||||
import { COLORS } from "../constants/colors"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { useTerminalSize } from "../hooks/useTerminalSize"
|
||||
import { isMouseEscapeSequence } from "../utils/input"
|
||||
import { isEnterKey, isMouseEscapeSequence } from "../utils/input"
|
||||
import { Panel } from "./Panel"
|
||||
|
||||
interface TaskHistoryItem {
|
||||
@@ -142,7 +142,7 @@ export const HistoryPanelContent: React.FC<HistoryPanelContentProps> = ({ onClos
|
||||
return
|
||||
}
|
||||
|
||||
if (key.return && items[selectedIndex]) {
|
||||
if (isEnterKey(input, key) && items[selectedIndex]) {
|
||||
handleSelect(items[selectedIndex])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { showTaskWithId } from "@/core/controller/task/showTaskWithId"
|
||||
import { StringRequest } from "@/shared/proto/cline/common"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { useTerminalSize } from "../hooks/useTerminalSize"
|
||||
import { isEnterKey } from "../utils/input"
|
||||
|
||||
interface TaskHistoryItem {
|
||||
id: string
|
||||
@@ -40,7 +41,7 @@ interface HistoryViewProps {
|
||||
/**
|
||||
* Format separator
|
||||
*/
|
||||
function formatSeparator(char: string = "─", width: number = 80): string {
|
||||
function formatSeparator(char = "─", width = 80): string {
|
||||
return char.repeat(Math.max(width, 10))
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ export const HistoryView: React.FC<HistoryViewProps> = ({
|
||||
setSelectedIndex((prev) => Math.max(0, prev - 1))
|
||||
} else if (key.downArrow || input === "j") {
|
||||
setSelectedIndex((prev) => Math.min(pageItems.length - 1, prev + 1))
|
||||
} else if (key.return && pageItems[selectedIndex]) {
|
||||
} else if (isEnterKey(input, key) && pageItems[selectedIndex]) {
|
||||
onSelect(pageItems[selectedIndex])
|
||||
} else if (key.leftArrow && hasPrevPage) {
|
||||
handlePageChange(currentPage - 1)
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
importFromCodex,
|
||||
importFromOpenCode,
|
||||
} from "../utils/import-configs"
|
||||
import { isEnterKey } from "../utils/input"
|
||||
import { applyProviderConfig } from "../utils/provider-config"
|
||||
|
||||
type ImportStep = "select" | "confirm" | "saving" | "error"
|
||||
@@ -95,13 +96,13 @@ export const ImportView: React.FC<ImportViewProps> = ({ source, onComplete, onCa
|
||||
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : keys.length - 1))
|
||||
} else if (key.downArrow) {
|
||||
setSelectedIndex((prev) => (prev < keys.length - 1 ? prev + 1 : 0))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
setStep("confirm")
|
||||
}
|
||||
} else if (step === "confirm") {
|
||||
if (key.upArrow || key.downArrow) {
|
||||
setConfirmIndex((prev) => (prev === 0 ? 1 : 0))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(input, key)) {
|
||||
if (confirmIndex === 0) {
|
||||
handleConfirm()
|
||||
} else {
|
||||
@@ -109,7 +110,7 @@ export const ImportView: React.FC<ImportViewProps> = ({ source, onComplete, onCa
|
||||
}
|
||||
}
|
||||
} else if (step === "error") {
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
onCancel()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { render } from "ink-testing-library"
|
||||
import { createElement } from "react"
|
||||
import { describe, expect, it, vi } from "vitest"
|
||||
import { KanbanMigrationView } from "./KanbanMigrationView"
|
||||
|
||||
describe("KanbanMigrationView", () => {
|
||||
it("renders the migration options", () => {
|
||||
const onSelect = vi.fn()
|
||||
const { lastFrame } = render(createElement(KanbanMigrationView, { isRawModeSupported: true, onSelect }))
|
||||
|
||||
expect(lastFrame()).toContain("Introducing Cline Kanban!")
|
||||
expect(lastFrame()).toContain("Open the new experience")
|
||||
expect(lastFrame()).toContain("Launch Cline Kanban and start there by default.")
|
||||
expect(lastFrame()).toContain("cline --tui")
|
||||
expect(lastFrame()).toContain("You can always run cline --tui for the terminal experience.")
|
||||
expect(lastFrame()).toContain("Exit")
|
||||
})
|
||||
|
||||
it("selects the highlighted option with Enter", () => {
|
||||
const onSelect = vi.fn()
|
||||
const { stdin } = render(createElement(KanbanMigrationView, { isRawModeSupported: true, onSelect }))
|
||||
|
||||
stdin.write("\r")
|
||||
|
||||
expect(onSelect).toHaveBeenCalledWith("kanban")
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Box, Text, useApp, useInput } from "ink"
|
||||
import React, { useMemo, useState } from "react"
|
||||
import { COLORS } from "../constants/colors"
|
||||
import { StdinProvider, useStdinContext } from "../context/StdinContext"
|
||||
import { isEnterKey } from "../utils/input"
|
||||
import { type KanbanMigrationAction } from "../utils/kanban"
|
||||
import { StaticRobotFrame } from "./AsciiMotionCli"
|
||||
import { ErrorBoundary } from "./ErrorBoundary"
|
||||
|
||||
interface KanbanMigrationViewProps {
|
||||
isRawModeSupported: boolean
|
||||
onSelect: (action: KanbanMigrationAction) => void
|
||||
}
|
||||
|
||||
interface MigrationMenuItem {
|
||||
label: string
|
||||
description: string
|
||||
value: KanbanMigrationAction
|
||||
}
|
||||
|
||||
const InternalKanbanMigrationView: React.FC<Pick<KanbanMigrationViewProps, "onSelect">> = ({ onSelect }) => {
|
||||
const { exit } = useApp()
|
||||
const { isRawModeSupported } = useStdinContext()
|
||||
const items = useMemo<MigrationMenuItem[]>(
|
||||
() => [
|
||||
{
|
||||
label: "Open the new experience",
|
||||
description: "Launch Cline Kanban and start there by default.",
|
||||
value: "kanban",
|
||||
},
|
||||
{
|
||||
label: "Exit",
|
||||
description: "You can always run cline --tui for the terminal experience.",
|
||||
value: "exit",
|
||||
},
|
||||
],
|
||||
[],
|
||||
)
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
|
||||
useInput(
|
||||
(input, key) => {
|
||||
if (key.escape) {
|
||||
onSelect("exit")
|
||||
exit()
|
||||
} else if (key.upArrow) {
|
||||
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1))
|
||||
} else if (key.downArrow) {
|
||||
setSelectedIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0))
|
||||
} else if (isEnterKey(input, key)) {
|
||||
onSelect(items[selectedIndex].value)
|
||||
exit()
|
||||
}
|
||||
},
|
||||
{ isActive: isRawModeSupported },
|
||||
)
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" width="100%">
|
||||
<StaticRobotFrame />
|
||||
<Text> </Text>
|
||||
<Text bold color="white">
|
||||
Introducing Cline Kanban!
|
||||
</Text>
|
||||
<Text color="gray">A board for orchestrating coding agents across worktrees, right from your browser.</Text>
|
||||
<Text> </Text>
|
||||
{items.map((item, index) => {
|
||||
const isSelected = index === selectedIndex
|
||||
return (
|
||||
<Box flexDirection="column" key={item.value} marginBottom={1}>
|
||||
<Text color={isSelected ? COLORS.primaryBlue : undefined}>
|
||||
{isSelected ? "❯ " : " "}
|
||||
{item.label}
|
||||
</Text>
|
||||
<Text color="gray"> {item.description}</Text>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
<Text> </Text>
|
||||
<Text color="gray">Use arrow keys to navigate, Enter to select, Esc or Ctrl+C to exit</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export const KanbanMigrationView: React.FC<KanbanMigrationViewProps> = ({ isRawModeSupported, onSelect }) => {
|
||||
const { exit } = useApp()
|
||||
|
||||
return (
|
||||
<ErrorBoundary exit={exit}>
|
||||
<StdinProvider isRawModeSupported={isRawModeSupported}>
|
||||
<InternalKanbanMigrationView onSelect={onSelect} />
|
||||
</StdinProvider>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { Box, Text, useInput } from "ink"
|
||||
import React, { useState } from "react"
|
||||
import { COLORS } from "../constants/colors"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { isEnterKey } from "../utils/input"
|
||||
|
||||
export interface SelectListItem {
|
||||
id: string
|
||||
@@ -31,7 +32,7 @@ export function SelectList<T extends SelectListItem>({ items, onSelect, isActive
|
||||
setSelectedIndex((i) => (i > 0 ? i - 1 : items.length - 1))
|
||||
} else if (key.downArrow) {
|
||||
setSelectedIndex((i) => (i < items.length - 1 ? i + 1 : 0))
|
||||
} else if (key.return) {
|
||||
} else if (isEnterKey(_input, key)) {
|
||||
const item = items[selectedIndex]
|
||||
if (item) {
|
||||
onSelect(item)
|
||||
|
||||
@@ -129,6 +129,12 @@ const FEATURE_SETTINGS = {
|
||||
label: "Double-check completion",
|
||||
description: "Reject first completion attempt and require re-verification",
|
||||
},
|
||||
showFeatureTips: {
|
||||
stateKey: "showFeatureTips",
|
||||
default: true,
|
||||
label: "Feature tips",
|
||||
description: "Show tips during thinking phases",
|
||||
},
|
||||
} as const
|
||||
|
||||
type FeatureKey = keyof typeof FEATURE_SETTINGS
|
||||
|
||||
@@ -38,6 +38,46 @@ import { SkillsPanelContent } from "./SkillsPanelContent"
|
||||
// Helper to wait for async state updates
|
||||
const delay = (ms = 60) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
type WaitForConditionOptions = {
|
||||
timeoutMs?: number
|
||||
intervalMs?: number
|
||||
errorMessage: string
|
||||
}
|
||||
|
||||
const waitForCondition = async (
|
||||
condition: () => boolean,
|
||||
{ timeoutMs = 1000, intervalMs = 25, errorMessage }: WaitForConditionOptions,
|
||||
) => {
|
||||
const start = Date.now()
|
||||
while (Date.now() - start < timeoutMs) {
|
||||
if (condition()) {
|
||||
return
|
||||
}
|
||||
await delay(intervalMs)
|
||||
}
|
||||
throw new Error(errorMessage)
|
||||
}
|
||||
|
||||
const waitForFrameToInclude = async (lastFrame: () => string | undefined, text: string) =>
|
||||
waitForCondition(() => (lastFrame() || "").includes(text), {
|
||||
errorMessage: `Expected frame to include: ${text}`,
|
||||
})
|
||||
|
||||
const waitForFrameToExclude = async (lastFrame: () => string | undefined, text: string) =>
|
||||
waitForCondition(() => !(lastFrame() || "").includes(text), {
|
||||
errorMessage: `Expected frame to exclude: ${text}`,
|
||||
})
|
||||
|
||||
const waitForMockToBeCalled = async (mockFn: { mock: { calls: unknown[] } }) =>
|
||||
waitForCondition(() => mockFn.mock.calls.length > 0, {
|
||||
errorMessage: "Expected mock to be called",
|
||||
})
|
||||
|
||||
const waitForSkillsPanelReady = async (lastFrame: () => string | undefined, expectedText: string) => {
|
||||
await waitForFrameToExclude(lastFrame, "Loading skills...")
|
||||
await waitForFrameToInclude(lastFrame, expectedText)
|
||||
}
|
||||
|
||||
describe("SkillsPanelContent", () => {
|
||||
const mockController = {} as any
|
||||
const mockOnClose = vi.fn()
|
||||
@@ -64,11 +104,11 @@ describe("SkillsPanelContent", () => {
|
||||
localSkills: [],
|
||||
})
|
||||
|
||||
const { stdin } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForSkillsPanelReady(lastFrame, "No skills installed.")
|
||||
|
||||
stdin.write("\x1B") // Escape
|
||||
await delay()
|
||||
await waitForMockToBeCalled(mockOnClose)
|
||||
|
||||
expect(mockOnClose).toHaveBeenCalled()
|
||||
})
|
||||
@@ -79,11 +119,11 @@ describe("SkillsPanelContent", () => {
|
||||
localSkills: [],
|
||||
})
|
||||
|
||||
const { stdin } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForSkillsPanelReady(lastFrame, "test-skill")
|
||||
|
||||
stdin.write("\r") // Enter
|
||||
await delay()
|
||||
await waitForMockToBeCalled(mockOnUseSkill)
|
||||
|
||||
expect(mockOnUseSkill).toHaveBeenCalledWith("/test/path/SKILL.md")
|
||||
})
|
||||
@@ -94,11 +134,11 @@ describe("SkillsPanelContent", () => {
|
||||
localSkills: [],
|
||||
})
|
||||
|
||||
const { stdin } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForSkillsPanelReady(lastFrame, "test-skill")
|
||||
|
||||
stdin.write(" ") // Space
|
||||
await delay()
|
||||
await waitForMockToBeCalled(mockToggleSkill)
|
||||
|
||||
expect(mockToggleSkill).toHaveBeenCalledWith(
|
||||
mockController,
|
||||
@@ -116,17 +156,17 @@ describe("SkillsPanelContent", () => {
|
||||
localSkills: [],
|
||||
})
|
||||
|
||||
const { stdin } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForSkillsPanelReady(lastFrame, "skill")
|
||||
|
||||
// Navigate down to marketplace (past the one skill)
|
||||
// Use vim-style navigation here because it's more deterministic in the
|
||||
// full suite than raw arrow escape sequences on Windows.
|
||||
stdin.write("j")
|
||||
await delay()
|
||||
await waitForFrameToInclude(lastFrame, "❯ Browse more skills at https://skills.sh/")
|
||||
|
||||
stdin.write("\r") // Enter
|
||||
await delay()
|
||||
await waitForMockToBeCalled(mockExec)
|
||||
|
||||
// Should have called exec with open command
|
||||
expect(mockExec).toHaveBeenCalled()
|
||||
@@ -143,16 +183,16 @@ describe("SkillsPanelContent", () => {
|
||||
localSkills: [],
|
||||
})
|
||||
|
||||
const { stdin } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForSkillsPanelReady(lastFrame, "skill-1")
|
||||
|
||||
// Navigate down
|
||||
stdin.write("\x1B[B") // Down arrow
|
||||
await delay()
|
||||
await waitForFrameToInclude(lastFrame, "❯ ● skill-2")
|
||||
|
||||
// Press Enter - should use second skill
|
||||
stdin.write("\r")
|
||||
await delay()
|
||||
await waitForMockToBeCalled(mockOnUseSkill)
|
||||
|
||||
expect(mockOnUseSkill).toHaveBeenCalledWith("/path2")
|
||||
})
|
||||
@@ -166,16 +206,16 @@ describe("SkillsPanelContent", () => {
|
||||
localSkills: [],
|
||||
})
|
||||
|
||||
const { stdin } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForSkillsPanelReady(lastFrame, "skill-1")
|
||||
|
||||
// Navigate down with j
|
||||
stdin.write("j")
|
||||
await delay()
|
||||
await waitForFrameToInclude(lastFrame, "❯ ● skill-2")
|
||||
|
||||
// Press Enter - should use second skill
|
||||
stdin.write("\r")
|
||||
await delay()
|
||||
await waitForMockToBeCalled(mockOnUseSkill)
|
||||
|
||||
expect(mockOnUseSkill).toHaveBeenCalledWith("/path2")
|
||||
})
|
||||
@@ -188,10 +228,11 @@ describe("SkillsPanelContent", () => {
|
||||
mockToggleSkill.mockRejectedValueOnce(new Error("toggle failed"))
|
||||
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
await waitForSkillsPanelReady(lastFrame, "test-skill")
|
||||
|
||||
stdin.write(" ") // Space to toggle
|
||||
await delay(100)
|
||||
await waitForMockToBeCalled(mockToggleSkill)
|
||||
await waitForFrameToInclude(lastFrame, "● test-skill")
|
||||
|
||||
// toggleSkill was called with enabled: false (toggled from true)
|
||||
expect(mockToggleSkill).toHaveBeenCalledWith(mockController, expect.objectContaining({ enabled: false }))
|
||||
@@ -206,15 +247,15 @@ describe("SkillsPanelContent", () => {
|
||||
localSkills: [],
|
||||
})
|
||||
|
||||
const { stdin } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { stdin, lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForSkillsPanelReady(lastFrame, "only-skill")
|
||||
|
||||
// Navigate up from first item (should wrap to last - marketplace)
|
||||
stdin.write("\x1B[A") // Up arrow
|
||||
await delay()
|
||||
await waitForFrameToInclude(lastFrame, "❯ Browse more skills at https://skills.sh/")
|
||||
|
||||
stdin.write("\r") // Enter
|
||||
await delay()
|
||||
await waitForMockToBeCalled(mockExec)
|
||||
|
||||
// Should have opened marketplace (wrapped to last item)
|
||||
expect(mockExec).toHaveBeenCalled()
|
||||
@@ -223,8 +264,9 @@ describe("SkillsPanelContent", () => {
|
||||
|
||||
describe("skill loading", () => {
|
||||
it("should call refreshSkills on mount", async () => {
|
||||
render(<SkillsPanelContent {...defaultProps} />)
|
||||
await delay()
|
||||
const { lastFrame } = render(<SkillsPanelContent {...defaultProps} />)
|
||||
await waitForMockToBeCalled(mockRefreshSkills)
|
||||
await waitForFrameToExclude(lastFrame, "Loading skills...")
|
||||
|
||||
expect(mockRefreshSkills).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
import { exec } from "node:child_process"
|
||||
import os from "node:os"
|
||||
import { Box, Text, useInput } from "ink"
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react"
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import type { Controller } from "@/core/controller"
|
||||
import { refreshSkills } from "@/core/controller/file/refreshSkills"
|
||||
import { toggleSkill } from "@/core/controller/file/toggleSkill"
|
||||
import { COLORS } from "../constants/colors"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import { isMouseEscapeSequence } from "../utils/input"
|
||||
import { isEnterKey, isMouseEscapeSequence } from "../utils/input"
|
||||
import { Panel } from "./Panel"
|
||||
|
||||
const SKILLS_MARKETPLACE_URL = "https://skills.sh/"
|
||||
@@ -38,6 +38,14 @@ export const SkillsPanelContent: React.FC<SkillsPanelContentProps> = ({ controll
|
||||
const [localSkills, setLocalSkills] = useState<SkillInfo[]>([])
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const inputStateRef = useRef({
|
||||
isLoading: true,
|
||||
selectedIndex: 0,
|
||||
skillEntries: [] as Array<{ skill: SkillInfo; isGlobal: boolean }>,
|
||||
})
|
||||
const handleToggleRef = useRef<() => Promise<void>>(async () => {})
|
||||
const handleUseRef = useRef<() => void>(() => {})
|
||||
const openMarketplaceRef = useRef<() => void>(() => {})
|
||||
|
||||
// Load skills on mount
|
||||
useEffect(() => {
|
||||
@@ -58,8 +66,12 @@ export const SkillsPanelContent: React.FC<SkillsPanelContentProps> = ({ controll
|
||||
// Build flat list of skills with source info (global first, then local, alphabetical within each)
|
||||
const skillEntries = useMemo(() => {
|
||||
const entries: { skill: SkillInfo; isGlobal: boolean }[] = []
|
||||
globalSkills.forEach((skill) => entries.push({ skill, isGlobal: true }))
|
||||
localSkills.forEach((skill) => entries.push({ skill, isGlobal: false }))
|
||||
globalSkills.forEach((skill) => {
|
||||
entries.push({ skill, isGlobal: true })
|
||||
})
|
||||
localSkills.forEach((skill) => {
|
||||
entries.push({ skill, isGlobal: false })
|
||||
})
|
||||
return entries.sort((a, b) => {
|
||||
if (a.isGlobal !== b.isGlobal) return a.isGlobal ? -1 : 1
|
||||
return a.skill.name.localeCompare(b.skill.name)
|
||||
@@ -117,6 +129,14 @@ export const SkillsPanelContent: React.FC<SkillsPanelContentProps> = ({ controll
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
handleToggleRef.current = handleToggle
|
||||
handleUseRef.current = handleUse
|
||||
openMarketplaceRef.current = openMarketplace
|
||||
inputStateRef.current = {
|
||||
isLoading,
|
||||
selectedIndex,
|
||||
skillEntries,
|
||||
}
|
||||
|
||||
// Total items = skills + 1 for marketplace link
|
||||
const totalItems = skillEntries.length + 1
|
||||
@@ -132,6 +152,14 @@ export const SkillsPanelContent: React.FC<SkillsPanelContentProps> = ({ controll
|
||||
return
|
||||
}
|
||||
|
||||
const { isLoading, selectedIndex, skillEntries } = inputStateRef.current
|
||||
if (isLoading) {
|
||||
return
|
||||
}
|
||||
|
||||
const totalItems = skillEntries.length + 1
|
||||
const isMarketplaceSelected = selectedIndex === skillEntries.length
|
||||
|
||||
// Navigation
|
||||
if (key.upArrow || input === "k") {
|
||||
setSelectedIndex((i) => (i > 0 ? i - 1 : totalItems - 1))
|
||||
@@ -143,16 +171,16 @@ export const SkillsPanelContent: React.FC<SkillsPanelContentProps> = ({ controll
|
||||
}
|
||||
|
||||
// Actions
|
||||
if (key.return) {
|
||||
if (isEnterKey(input, key)) {
|
||||
if (isMarketplaceSelected) {
|
||||
openMarketplace()
|
||||
openMarketplaceRef.current()
|
||||
} else {
|
||||
handleUse()
|
||||
handleUseRef.current()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (input === " " && !isMarketplaceSelected) {
|
||||
handleToggle()
|
||||
void handleToggleRef.current()
|
||||
return
|
||||
}
|
||||
},
|
||||
@@ -248,7 +276,7 @@ const SkillRow: React.FC<{ skill: SkillInfo; isSelected: boolean }> = ({ skill,
|
||||
{skill.description && (
|
||||
<Box marginLeft={4}>
|
||||
<Text color="gray">
|
||||
{skill.description.length > 60 ? skill.description.slice(0, 57) + "..." : skill.description}
|
||||
{skill.description.length > 60 ? `${skill.description.slice(0, 57)}...` : skill.description}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
import { Box, Text, useInput } from "ink"
|
||||
import React, { useEffect, useMemo, useState } from "react"
|
||||
import { StateManager } from "@/core/storage/StateManager"
|
||||
import { COLORS } from "../constants/colors"
|
||||
import { FeatureTip } from "./FeatureTip"
|
||||
|
||||
interface ThinkingIndicatorProps {
|
||||
mode?: "act" | "plan"
|
||||
@@ -52,6 +54,7 @@ const ShimmerText: React.FC<{ text: string; color: string; shimmerPos: number }>
|
||||
}
|
||||
|
||||
export const ThinkingIndicator: React.FC<ThinkingIndicatorProps> = ({ mode = "act", startTime, onCancel }) => {
|
||||
const showFeatureTips = StateManager.get().getGlobalSettingsKey("showFeatureTips") ?? true
|
||||
const message = mode === "plan" ? "Planning" : "Acting"
|
||||
const color = mode === "plan" ? "yellow" : COLORS.primaryBlue
|
||||
|
||||
@@ -118,9 +121,12 @@ export const ThinkingIndicator: React.FC<ThinkingIndicatorProps> = ({ mode = "ac
|
||||
}, [startTime, elapsedMs])
|
||||
|
||||
return (
|
||||
<Box paddingLeft={1}>
|
||||
<ShimmerText color={color} shimmerPos={shimmerPos} text={fullText} />
|
||||
{elapsedStr && <Text color="gray"> ({elapsedStr} · esc to interrupt)</Text>}
|
||||
<Box flexDirection="column">
|
||||
<Box paddingLeft={1}>
|
||||
<ShimmerText color={color} shimmerPos={shimmerPos} text={fullText} />
|
||||
{elapsedStr && <Text color="gray"> ({elapsedStr} · esc to interrupt)</Text>}
|
||||
</Box>
|
||||
{showFeatureTips && <FeatureTip />}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
/**
|
||||
* Welcome view component
|
||||
* Shows an interactive prompt when user starts cline without a command
|
||||
* Supports file mentions with @
|
||||
*/
|
||||
|
||||
import { Box, Text, useInput } from "ink"
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { StateManager } from "@/core/storage/StateManager"
|
||||
import type { ApiProvider } from "@/shared/api"
|
||||
import { getProviderDefaultModelId, getProviderModelIdKey, Mode, SettingsKey } from "@/shared/storage"
|
||||
import { useStdinContext } from "../context/StdinContext"
|
||||
import {
|
||||
checkAndWarnRipgrepMissing,
|
||||
extractMentionQuery,
|
||||
type FileSearchResult,
|
||||
getRipgrepInstallInstructions,
|
||||
insertMention,
|
||||
searchWorkspaceFiles,
|
||||
} from "../utils/file-search"
|
||||
import { isMouseEscapeSequence } from "../utils/input"
|
||||
import { parseImagesFromInput } from "../utils/parser"
|
||||
import { AccountInfoView } from "./AccountInfoView"
|
||||
import { FileMentionMenu } from "./FileMentionMenu"
|
||||
|
||||
interface WelcomeViewProps {
|
||||
onSubmit: (prompt: string, imagePaths: string[]) => void
|
||||
onExit?: () => void
|
||||
controller?: any
|
||||
}
|
||||
|
||||
// ASCII art Cline logo
|
||||
const CLINE_LOGO = [
|
||||
" ::::::: ",
|
||||
" ::::::::: ",
|
||||
" ::::::::::::::::: ",
|
||||
" ::::::::::::::::::::::: ",
|
||||
" ::::::::::::::::::::::::: ",
|
||||
" ::::::::::::::::::::::::::: ",
|
||||
" ::::::: ::::::: ::::::: ",
|
||||
" ::::::: ::::: ::::::: ",
|
||||
":::::::: ::::: ::::::::",
|
||||
":::::::: ::::: ::::::::",
|
||||
" ::::::: ::::: ::::::: ",
|
||||
" ::::::: ::::::: ::::::: ",
|
||||
" ::::::::::::::::::::::::::: ",
|
||||
" ::::::::::::::::::::::::: ",
|
||||
" ::::::::::::::::::::::: ",
|
||||
" :::::::::::::::: ",
|
||||
]
|
||||
|
||||
const SEARCH_DEBOUNCE_MS = 150
|
||||
const RIPGREP_WARNING_DURATION_MS = 5000
|
||||
const MAX_SEARCH_RESULTS = 15
|
||||
|
||||
export const WelcomeView: React.FC<WelcomeViewProps> = ({ onSubmit, onExit, controller }) => {
|
||||
const { isRawModeSupported } = useStdinContext()
|
||||
const [textInput, setTextInput] = useState("")
|
||||
const [fileResults, setFileResults] = useState<FileSearchResult[]>([])
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
const [isSearching, setIsSearching] = useState(false)
|
||||
const [showRipgrepWarning, setShowRipgrepWarning] = useState(false)
|
||||
const [escPressedOnce, setEscPressedOnce] = useState(false)
|
||||
const [mode, setMode] = useState<Mode>(() => {
|
||||
const stateManager = StateManager.get()
|
||||
return stateManager.getGlobalSettingsKey("mode") || "act"
|
||||
})
|
||||
|
||||
const provider = useMemo(() => {
|
||||
const stateManager = StateManager.get()
|
||||
const mode = stateManager.getGlobalSettingsKey("mode") as string
|
||||
const providerKey = mode === "act" ? "actModeApiProvider" : "planModeApiProvider"
|
||||
const currentProvider = stateManager.getGlobalSettingsKey(providerKey) as string
|
||||
return currentProvider || "cline"
|
||||
}, [controller])
|
||||
|
||||
// Get model ID based on current mode and provider
|
||||
// Different providers use different state keys (e.g., cline uses actModeOpenRouterModelId)
|
||||
const modelId = useMemo(() => {
|
||||
const stateManager = StateManager.get()
|
||||
const modelKey = getProviderModelIdKey(provider as ApiProvider, mode)
|
||||
return (
|
||||
(stateManager.getGlobalSettingsKey(modelKey as SettingsKey) as string) ||
|
||||
getProviderDefaultModelId(provider as ApiProvider)
|
||||
)
|
||||
}, [mode, provider])
|
||||
|
||||
const toggleMode = useCallback(() => {
|
||||
const newMode: Mode = mode === "act" ? "plan" : "act"
|
||||
setMode(newMode)
|
||||
const stateManager = StateManager.get()
|
||||
stateManager.setGlobalState("mode", newMode)
|
||||
}, [mode])
|
||||
|
||||
const refs = useRef({
|
||||
searchTimeout: null as NodeJS.Timeout | null,
|
||||
lastQuery: "",
|
||||
hasCheckedRipgrep: false,
|
||||
})
|
||||
|
||||
const { prompt, imagePaths } = parseImagesFromInput(textInput)
|
||||
|
||||
const mentionInfo = useMemo(() => extractMentionQuery(textInput), [textInput])
|
||||
|
||||
const workspacePath = useMemo(() => {
|
||||
try {
|
||||
const root = controller?.getWorkspaceManagerSync?.()?.getPrimaryRoot?.()
|
||||
if (root?.path) {
|
||||
return root.path
|
||||
}
|
||||
} catch {
|
||||
// Fallback to cwd
|
||||
}
|
||||
return process.cwd()
|
||||
}, [controller])
|
||||
|
||||
// Search for files when in mention mode
|
||||
useEffect(() => {
|
||||
const { current: r } = refs
|
||||
|
||||
if (!mentionInfo.inMentionMode) {
|
||||
setFileResults([])
|
||||
setSelectedIndex(0)
|
||||
if (r.searchTimeout) {
|
||||
clearTimeout(r.searchTimeout)
|
||||
r.searchTimeout = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Check for ripgrep on first mention trigger
|
||||
if (!r.hasCheckedRipgrep) {
|
||||
r.hasCheckedRipgrep = true
|
||||
if (checkAndWarnRipgrepMissing()) {
|
||||
setShowRipgrepWarning(true)
|
||||
setTimeout(() => setShowRipgrepWarning(false), RIPGREP_WARNING_DURATION_MS)
|
||||
}
|
||||
}
|
||||
|
||||
const { query } = mentionInfo
|
||||
if (query === r.lastQuery) {
|
||||
return
|
||||
}
|
||||
r.lastQuery = query
|
||||
|
||||
if (r.searchTimeout) {
|
||||
clearTimeout(r.searchTimeout)
|
||||
}
|
||||
setIsSearching(true)
|
||||
|
||||
r.searchTimeout = setTimeout(async () => {
|
||||
try {
|
||||
const results = await searchWorkspaceFiles(query, workspacePath, MAX_SEARCH_RESULTS)
|
||||
setFileResults(results)
|
||||
setSelectedIndex(0)
|
||||
} catch {
|
||||
setFileResults([])
|
||||
} finally {
|
||||
setIsSearching(false)
|
||||
}
|
||||
}, SEARCH_DEBOUNCE_MS)
|
||||
|
||||
return () => {
|
||||
if (r.searchTimeout) {
|
||||
clearTimeout(r.searchTimeout)
|
||||
}
|
||||
}
|
||||
}, [mentionInfo.inMentionMode, mentionInfo.query, workspacePath])
|
||||
|
||||
useInput(
|
||||
(input, key) => {
|
||||
// Filter out mouse escape sequences
|
||||
if (isMouseEscapeSequence(input)) {
|
||||
return
|
||||
}
|
||||
|
||||
const inMenu = mentionInfo.inMentionMode && fileResults.length > 0
|
||||
|
||||
// Menu navigation
|
||||
if (inMenu) {
|
||||
if (key.upArrow) {
|
||||
setSelectedIndex((i) => (i > 0 ? i - 1 : fileResults.length - 1))
|
||||
return
|
||||
}
|
||||
if (key.downArrow) {
|
||||
setSelectedIndex((i) => (i < fileResults.length - 1 ? i + 1 : 0))
|
||||
return
|
||||
}
|
||||
if (key.tab || key.return) {
|
||||
const file = fileResults[selectedIndex]
|
||||
if (file) {
|
||||
setTextInput(insertMention(textInput, mentionInfo.atIndex, file.path))
|
||||
setFileResults([])
|
||||
setSelectedIndex(0)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (key.escape) {
|
||||
setFileResults([])
|
||||
setSelectedIndex(0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Normal input handling
|
||||
if (key.tab && !mentionInfo.inMentionMode) {
|
||||
toggleMode()
|
||||
return
|
||||
}
|
||||
if (key.return && !mentionInfo.inMentionMode) {
|
||||
if (prompt.trim() || imagePaths.length > 0) {
|
||||
onSubmit(prompt.trim(), imagePaths)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (key.escape && !mentionInfo.inMentionMode) {
|
||||
if (escPressedOnce) {
|
||||
onExit?.()
|
||||
} else {
|
||||
setEscPressedOnce(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (key.backspace || key.delete) {
|
||||
setTextInput((prev) => prev.slice(0, -1))
|
||||
setEscPressedOnce(false)
|
||||
return
|
||||
}
|
||||
if (input && !key.ctrl && !key.meta && !key.upArrow && !key.downArrow && !key.tab) {
|
||||
setTextInput((prev) => prev + input)
|
||||
setEscPressedOnce(false)
|
||||
}
|
||||
},
|
||||
{ isActive: isRawModeSupported },
|
||||
)
|
||||
|
||||
const borderColor = mode === "act" ? "blue" : "yellow"
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" width="100%">
|
||||
{/* Account/Provider info at top */}
|
||||
{controller && (
|
||||
<Box marginBottom={1}>
|
||||
<AccountInfoView controller={controller} />
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Cline logo - centered */}
|
||||
<Box alignItems="center" flexDirection="column">
|
||||
{CLINE_LOGO.map((line, idx) => (
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: static array that never changes
|
||||
<Text color="white" key={idx}>
|
||||
{line}
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
{/* Main prompt - centered, bold */}
|
||||
<Box justifyContent="center" marginTop={1}>
|
||||
<Text bold color="white">
|
||||
What can I do for you?
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* Ripgrep warning if needed */}
|
||||
{showRipgrepWarning && (
|
||||
<Box marginTop={1}>
|
||||
<Text color="yellow">⚠ ripgrep not found - file search will be slower. </Text>
|
||||
<Text color="gray">Install: {getRipgrepInstallInstructions()}</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Input field with border */}
|
||||
<Box
|
||||
borderColor={borderColor}
|
||||
borderStyle="round"
|
||||
flexDirection="row"
|
||||
marginTop={1}
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
width="100%">
|
||||
<Text>{textInput}</Text>
|
||||
<Text inverse> </Text>
|
||||
</Box>
|
||||
|
||||
{/* Model ID and Mode toggle row */}
|
||||
<Box justifyContent="space-between" width="100%">
|
||||
{/* Model ID on left */}
|
||||
<Text color="gray">{modelId}</Text>
|
||||
|
||||
{/* Mode toggle on right */}
|
||||
<Box gap={1}>
|
||||
<Box>
|
||||
<Text bold={mode === "plan"} color={mode === "plan" ? "yellow" : "gray"}>
|
||||
{mode === "plan" ? "●" : "○"} Plan
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text bold={mode === "act"} color={mode === "act" ? "blue" : "gray"}>
|
||||
{mode === "act" ? "●" : "○"} Act
|
||||
</Text>
|
||||
</Box>
|
||||
<Text color="gray">(Tab)</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* File mention menu - below input */}
|
||||
{mentionInfo.inMentionMode && (
|
||||
<FileMentionMenu
|
||||
isLoading={isSearching}
|
||||
query={mentionInfo.query}
|
||||
results={fileResults}
|
||||
selectedIndex={selectedIndex}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Attached images */}
|
||||
{imagePaths.length > 0 && (
|
||||
<Text color="magenta">
|
||||
📎 {imagePaths.length} image{imagePaths.length > 1 ? "s" : ""} attached
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* Help text */}
|
||||
<Box>
|
||||
<Text color="gray">Enter to submit · @ to mention files · </Text>
|
||||
<Text bold={escPressedOnce} color={escPressedOnce ? "white" : "gray"}>
|
||||
{escPressedOnce ? "Press Esc again to exit" : "Esc to exit"}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -79,7 +79,7 @@ export class CliDiffServiceClient implements DiffServiceClientInterface {
|
||||
* CLI implementation of EnvService - handles environment operations
|
||||
*/
|
||||
export class CliEnvServiceClient implements EnvServiceClientInterface {
|
||||
private clipboardContent: string = ""
|
||||
private clipboardContent = ""
|
||||
|
||||
private getTelemetrySetting(): proto.host.Setting {
|
||||
// Read from StateManager - defaults to ENABLED if not set or "unset"
|
||||
@@ -102,6 +102,8 @@ export class CliEnvServiceClient implements EnvServiceClientInterface {
|
||||
version: CLI_VERSION,
|
||||
platform: "Cline CLI - Node.js",
|
||||
clineType: ClineClient.Cli,
|
||||
// remoteName is intentionally omitted — the CLI runs locally on the user's machine.
|
||||
// If CLI-in-container scenarios arise, populate this field to enable remote cadence tuning.
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+83
-36
@@ -11,6 +11,22 @@ import { captureUnhandledException } from "."
|
||||
describe("CLI Commands", () => {
|
||||
let program: Command
|
||||
|
||||
function getCommand(name: string): Command {
|
||||
const command = program.commands.find((candidate) => candidate.name() === name)
|
||||
if (!command) {
|
||||
throw new Error(`Missing command: ${name}`)
|
||||
}
|
||||
return command
|
||||
}
|
||||
|
||||
function getSubcommand(commandName: string, subcommandName: string): Command {
|
||||
const subcommand = getCommand(commandName).commands.find((candidate) => candidate.name() === subcommandName)
|
||||
if (!subcommand) {
|
||||
throw new Error(`Missing subcommand: ${commandName} ${subcommandName}`)
|
||||
}
|
||||
return subcommand
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
// Create a fresh program instance for each test
|
||||
program = new Command()
|
||||
@@ -80,7 +96,13 @@ describe("CLI Commands", () => {
|
||||
|
||||
program
|
||||
.command("kanban")
|
||||
.description("Run npx kanban --agent cline")
|
||||
.description("Run kanban")
|
||||
.action(() => {})
|
||||
|
||||
program
|
||||
.command("update")
|
||||
.description("Check for updates and install if available")
|
||||
.option("-v, --verbose", "Show verbose output")
|
||||
.action(() => {})
|
||||
|
||||
// Default command for interactive mode
|
||||
@@ -97,7 +119,9 @@ describe("CLI Commands", () => {
|
||||
.option("--auto-condense", "Enable AI-powered context compaction instead of mechanical truncation")
|
||||
.option("--hooks-dir <path>", "Additional hooks directory")
|
||||
.option("--auto-approve-all", "Enable auto-approve all")
|
||||
.option("--kanban", "Run npx kanban --agent cline")
|
||||
.option("--update", "Check for updates and install if available")
|
||||
.option("--kanban", "Run kanban")
|
||||
.option("--tui", "Open the legacy terminal UI instead of the kanban experience")
|
||||
.action(() => {})
|
||||
})
|
||||
|
||||
@@ -114,119 +138,119 @@ describe("CLI Commands", () => {
|
||||
})
|
||||
|
||||
it("should parse --act flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--act"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().act).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --plan flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--plan"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().plan).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --yolo flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--yolo"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().yolo).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --auto-approve-all flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--auto-approve-all"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().autoApproveAll).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --model option", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--model", "claude-sonnet-4-20250514"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().model).toBe("claude-sonnet-4-20250514")
|
||||
})
|
||||
|
||||
it("should parse --images option with multiple paths", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--images", "/path/to/img1.png", "/path/to/img2.jpg"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().images).toEqual(["/path/to/img1.png", "/path/to/img2.jpg"])
|
||||
})
|
||||
|
||||
it("should parse --verbose flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--verbose"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().verbose).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --cwd option", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--cwd", "/some/path"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().cwd).toBe("/some/path")
|
||||
})
|
||||
|
||||
it("should parse --config option", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--config", "/custom/config"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().config).toBe("/custom/config")
|
||||
})
|
||||
|
||||
it("should parse --thinking flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--thinking"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().thinking).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --thinking with token budget", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--thinking", "8000"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().thinking).toBe("8000")
|
||||
})
|
||||
|
||||
it("should parse --reasoning-effort option", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--reasoning-effort", "high"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().reasoningEffort).toBe("high")
|
||||
})
|
||||
|
||||
it("should parse --max-consecutive-mistakes option", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--max-consecutive-mistakes", "999"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().maxConsecutiveMistakes).toBe("999")
|
||||
})
|
||||
|
||||
it("should parse --hooks-dir option", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--hooks-dir", "/tmp/hooks"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().hooksDir).toBe("/tmp/hooks")
|
||||
})
|
||||
|
||||
it("should parse --double-check-completion flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--double-check-completion"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().doubleCheckCompletion).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --auto-condense flag", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "--auto-condense"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().autoCondense).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse short flags", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const taskCmd = getCommand("task")
|
||||
const args = ["test prompt", "-a", "-v", "-m", "gpt-4"]
|
||||
taskCmd.parse(args, { from: "user" })
|
||||
expect(taskCmd.opts().act).toBe(true)
|
||||
@@ -237,26 +261,26 @@ describe("CLI Commands", () => {
|
||||
|
||||
describe("history command", () => {
|
||||
it("should have default limit of 10", () => {
|
||||
const historyCmd = program.commands.find((c) => c.name() === "history")!
|
||||
const historyCmd = getCommand("history")
|
||||
historyCmd.parse([], { from: "user" })
|
||||
expect(historyCmd.opts().limit).toBe("10")
|
||||
})
|
||||
|
||||
it("should have default page of 1", () => {
|
||||
const historyCmd = program.commands.find((c) => c.name() === "history")!
|
||||
const historyCmd = getCommand("history")
|
||||
historyCmd.parse([], { from: "user" })
|
||||
expect(historyCmd.opts().page).toBe("1")
|
||||
})
|
||||
|
||||
it("should parse --limit option", () => {
|
||||
const historyCmd = program.commands.find((c) => c.name() === "history")!
|
||||
const historyCmd = getCommand("history")
|
||||
const args = ["--limit", "20"]
|
||||
historyCmd.parse(args, { from: "user" })
|
||||
expect(historyCmd.opts().limit).toBe("20")
|
||||
})
|
||||
|
||||
it("should parse --page option", () => {
|
||||
const historyCmd = program.commands.find((c) => c.name() === "history")!
|
||||
const historyCmd = getCommand("history")
|
||||
const args = ["--page", "3"]
|
||||
historyCmd.parse(args, { from: "user" })
|
||||
expect(historyCmd.opts().page).toBe("3")
|
||||
@@ -269,7 +293,7 @@ describe("CLI Commands", () => {
|
||||
})
|
||||
|
||||
it("should parse short flags", () => {
|
||||
const historyCmd = program.commands.find((c) => c.name() === "history")!
|
||||
const historyCmd = getCommand("history")
|
||||
const args = ["-n", "5", "-p", "2"]
|
||||
historyCmd.parse(args, { from: "user" })
|
||||
expect(historyCmd.opts().limit).toBe("5")
|
||||
@@ -284,7 +308,7 @@ describe("CLI Commands", () => {
|
||||
})
|
||||
|
||||
it("should parse --config option", () => {
|
||||
const configCmd = program.commands.find((c) => c.name() === "config")!
|
||||
const configCmd = getCommand("config")
|
||||
const args = ["--config", "/custom/path"]
|
||||
configCmd.parse(args, { from: "user" })
|
||||
expect(configCmd.opts().config).toBe("/custom/path")
|
||||
@@ -298,6 +322,20 @@ describe("CLI Commands", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("update command", () => {
|
||||
it("should parse update command", () => {
|
||||
const args = ["node", "cli", "update"]
|
||||
program.parse(args)
|
||||
})
|
||||
|
||||
it("should parse --verbose on update command", () => {
|
||||
const updateCmd = getCommand("update")
|
||||
const args = ["--verbose"]
|
||||
updateCmd.parse(args, { from: "user" })
|
||||
expect(updateCmd.opts().verbose).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("auth command", () => {
|
||||
it("should parse auth command", () => {
|
||||
const args = ["node", "cli", "auth"]
|
||||
@@ -305,35 +343,35 @@ describe("CLI Commands", () => {
|
||||
})
|
||||
|
||||
it("should parse --provider option", () => {
|
||||
const authCmd = program.commands.find((c) => c.name() === "auth")!
|
||||
const authCmd = getCommand("auth")
|
||||
const args = ["--provider", "openai"]
|
||||
authCmd.parse(args, { from: "user" })
|
||||
expect(authCmd.opts().provider).toBe("openai")
|
||||
})
|
||||
|
||||
it("should parse --apikey option", () => {
|
||||
const authCmd = program.commands.find((c) => c.name() === "auth")!
|
||||
const authCmd = getCommand("auth")
|
||||
const args = ["--apikey", "sk-test-key"]
|
||||
authCmd.parse(args, { from: "user" })
|
||||
expect(authCmd.opts().apikey).toBe("sk-test-key")
|
||||
})
|
||||
|
||||
it("should parse --modelid option", () => {
|
||||
const authCmd = program.commands.find((c) => c.name() === "auth")!
|
||||
const authCmd = getCommand("auth")
|
||||
const args = ["--modelid", "gpt-4"]
|
||||
authCmd.parse(args, { from: "user" })
|
||||
expect(authCmd.opts().modelid).toBe("gpt-4")
|
||||
})
|
||||
|
||||
it("should parse --baseurl option", () => {
|
||||
const authCmd = program.commands.find((c) => c.name() === "auth")!
|
||||
const authCmd = getCommand("auth")
|
||||
const args = ["--baseurl", "https://api.example.com"]
|
||||
authCmd.parse(args, { from: "user" })
|
||||
expect(authCmd.opts().baseurl).toBe("https://api.example.com")
|
||||
})
|
||||
|
||||
it("should parse short flags", () => {
|
||||
const authCmd = program.commands.find((c) => c.name() === "auth")!
|
||||
const authCmd = getCommand("auth")
|
||||
const args = ["-p", "anthropic", "-k", "key123", "-m", "claude-sonnet-4-20250514"]
|
||||
authCmd.parse(args, { from: "user" })
|
||||
expect(authCmd.opts().provider).toBe("anthropic")
|
||||
@@ -354,15 +392,13 @@ describe("CLI Commands", () => {
|
||||
})
|
||||
|
||||
it("should default mcp add type to stdio", () => {
|
||||
const mcpCmd = program.commands.find((c) => c.name() === "mcp")!
|
||||
const addCmd = mcpCmd.commands.find((c) => c.name() === "add")!
|
||||
const addCmd = getSubcommand("mcp", "add")
|
||||
addCmd.parse(["kanban", "--", "kanban", "mcp"], { from: "user" })
|
||||
expect(addCmd.opts().type).toBe("stdio")
|
||||
})
|
||||
|
||||
it("should parse mcp add type option", () => {
|
||||
const mcpCmd = program.commands.find((c) => c.name() === "mcp")!
|
||||
const addCmd = mcpCmd.commands.find((c) => c.name() === "add")!
|
||||
const addCmd = getSubcommand("mcp", "add")
|
||||
addCmd.parse(["linear", "https://mcp.linear.app/mcp", "--type", "http"], { from: "user" })
|
||||
expect(addCmd.opts().type).toBe("http")
|
||||
})
|
||||
@@ -423,6 +459,16 @@ describe("CLI Commands", () => {
|
||||
program.parse(["node", "cli", "--kanban"])
|
||||
expect(program.opts().kanban).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --update flag", () => {
|
||||
program.parse(["node", "cli", "--update"])
|
||||
expect(program.opts().update).toBe(true)
|
||||
})
|
||||
|
||||
it("should parse --tui flag", () => {
|
||||
program.parse(["node", "cli", "--tui"])
|
||||
expect(program.opts().tui).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("command structure", () => {
|
||||
@@ -434,11 +480,12 @@ describe("CLI Commands", () => {
|
||||
expect(commandNames).toContain("auth")
|
||||
expect(commandNames).toContain("mcp")
|
||||
expect(commandNames).toContain("kanban")
|
||||
expect(commandNames).toContain("update")
|
||||
})
|
||||
|
||||
it("should have correct aliases", () => {
|
||||
const taskCmd = program.commands.find((c) => c.name() === "task")!
|
||||
const historyCmd = program.commands.find((c) => c.name() === "history")!
|
||||
const taskCmd = getCommand("task")
|
||||
const historyCmd = getCommand("history")
|
||||
expect(taskCmd.aliases()).toContain("t")
|
||||
expect(historyCmd.aliases()).toContain("h")
|
||||
})
|
||||
|
||||
+194
-16
@@ -2,7 +2,7 @@
|
||||
* Cline CLI - TypeScript implementation with React Ink
|
||||
*/
|
||||
|
||||
import { spawn } from "node:child_process"
|
||||
import type { ChildProcess } from "node:child_process"
|
||||
import { exit } from "node:process"
|
||||
import type { ApiProvider } from "@shared/api"
|
||||
import { Command } from "commander"
|
||||
@@ -28,6 +28,7 @@ import { isOpenaiReasoningEffort, OPENAI_REASONING_EFFORT_OPTIONS, type OpenaiRe
|
||||
import { version as CLI_VERSION } from "../package.json"
|
||||
import { runAcpMode } from "./acp/index.js"
|
||||
import { App } from "./components/App"
|
||||
import { KanbanMigrationView } from "./components/KanbanMigrationView"
|
||||
import { checkRawModeSupport } from "./context/StdinContext"
|
||||
import { createCliHostBridgeProvider } from "./controllers"
|
||||
import { CliCommentReviewController } from "./controllers/CliCommentReviewController"
|
||||
@@ -35,6 +36,20 @@ import { CliWebviewProvider } from "./controllers/CliWebviewProvider"
|
||||
import { isAuthConfigured } from "./utils/auth"
|
||||
import { restoreConsole, suppressConsoleUnlessVerbose } from "./utils/console"
|
||||
import { printInfo, printWarning } from "./utils/display"
|
||||
import {
|
||||
forwardSignalToKanbanProcess,
|
||||
isKanbanCommandAvailable,
|
||||
KANBAN_LAUNCH_COMMAND,
|
||||
KANBAN_SHUTDOWN_TIMEOUT_MS,
|
||||
type KanbanMigrationAction,
|
||||
LEGACY_TUI_FLAG,
|
||||
markKanbanMigrationAnnouncementShown,
|
||||
resolveKanbanInstallCommand,
|
||||
shouldLaunchKanbanByDefault,
|
||||
shouldShowKanbanMigrationAnnouncementForCurrentUser,
|
||||
spawnKanbanInstallProcess,
|
||||
spawnKanbanProcess,
|
||||
} from "./utils/kanban"
|
||||
import { addMcpServerShortcut, type McpAddOptions } from "./utils/mcp"
|
||||
import { selectOutputMode } from "./utils/mode-selection"
|
||||
import { parseImagesFromInput, processImagePaths } from "./utils/parser"
|
||||
@@ -59,6 +74,7 @@ interface TaskOptions {
|
||||
act?: boolean
|
||||
plan?: boolean
|
||||
kanban?: boolean
|
||||
tui?: boolean
|
||||
model?: string
|
||||
verbose?: boolean
|
||||
cwd?: string
|
||||
@@ -251,25 +267,72 @@ function getPlainTextModeReason(options: TaskOptions): string {
|
||||
return getModeSelection(options).reason
|
||||
}
|
||||
|
||||
function getNpxCommand(): string {
|
||||
return process.platform === "win32" ? "npx.cmd" : "npx"
|
||||
}
|
||||
function runKanbanAlias(spawnOptions?: Parameters<typeof spawnKanbanProcess>[0]): void {
|
||||
const launchKanban = () => {
|
||||
const child = spawnKanbanProcess(spawnOptions)
|
||||
activeKanbanProcess = child
|
||||
|
||||
function runKanbanAlias(): void {
|
||||
const child = spawn(getNpxCommand(), ["-y", "kanban", "--agent", "cline"], {
|
||||
stdio: "inherit",
|
||||
})
|
||||
child.on("error", (error) => {
|
||||
clearActiveKanbanProcess()
|
||||
const errorMessage = error instanceof Error ? ` ${error.message}` : ""
|
||||
printWarning(`Failed to run '${KANBAN_LAUNCH_COMMAND}'.${errorMessage}`)
|
||||
exit(1)
|
||||
})
|
||||
|
||||
child.on("error", () => {
|
||||
printWarning("Failed to run 'npx kanban --agent cline'. Make sure npx is installed and available in PATH.")
|
||||
child.on("close", (code, signal) => {
|
||||
clearActiveKanbanProcess()
|
||||
exit(resolveProcessExitCode(code, signal))
|
||||
})
|
||||
}
|
||||
|
||||
if (isKanbanCommandAvailable()) {
|
||||
launchKanban()
|
||||
return
|
||||
}
|
||||
|
||||
const installCommand = resolveKanbanInstallCommand()
|
||||
if (!installCommand) {
|
||||
printWarning(
|
||||
`'${KANBAN_LAUNCH_COMMAND}' not found and no supported package manager was detected in PATH (npm, pnpm, bun). Install Kanban globally and try again.`,
|
||||
)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
const installProcess = spawnKanbanInstallProcess(installCommand)
|
||||
|
||||
installProcess.on("error", (error) => {
|
||||
const errorMessage = error instanceof Error ? ` ${error.message}` : ""
|
||||
printWarning(`Failed to run '${installCommand.displayCommand}'.${errorMessage}`)
|
||||
exit(1)
|
||||
})
|
||||
|
||||
child.on("close", (code) => {
|
||||
exit(code ?? 1)
|
||||
installProcess.on("close", (code, signal) => {
|
||||
const installExitCode = resolveProcessExitCode(code, signal)
|
||||
if (installExitCode !== 0) {
|
||||
printWarning(`Failed to install Kanban automatically. Please run '${installCommand.displayCommand}' manually.`)
|
||||
exit(installExitCode)
|
||||
}
|
||||
|
||||
launchKanban()
|
||||
})
|
||||
}
|
||||
|
||||
async function showKanbanMigrationView(): Promise<KanbanMigrationAction> {
|
||||
let selectedAction: KanbanMigrationAction = "exit"
|
||||
|
||||
await runInkApp(
|
||||
React.createElement(KanbanMigrationView, {
|
||||
isRawModeSupported: checkRawModeSupport(),
|
||||
onSelect: (action: KanbanMigrationAction) => {
|
||||
selectedAction = action
|
||||
},
|
||||
}),
|
||||
async () => {},
|
||||
)
|
||||
|
||||
return selectedAction
|
||||
}
|
||||
|
||||
async function addMcpServer(name: string, targetOrCommand: string[] = [], options: McpAddOptions): Promise<void> {
|
||||
try {
|
||||
const result = await addMcpServerShortcut(name, targetOrCommand, options)
|
||||
@@ -347,6 +410,62 @@ let activeContext: CliContext | null = null
|
||||
let isShuttingDown = false
|
||||
// Track if we're in plain text mode (no Ink UI) - set by runTask when piped stdin detected
|
||||
let isPlainTextMode = false
|
||||
let activeKanbanProcess: ChildProcess | null = null
|
||||
let activeKanbanShutdownTimer: NodeJS.Timeout | null = null
|
||||
|
||||
function clearActiveKanbanProcess(): void {
|
||||
activeKanbanProcess = null
|
||||
if (activeKanbanShutdownTimer) {
|
||||
clearTimeout(activeKanbanShutdownTimer)
|
||||
activeKanbanShutdownTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
function requestKanbanProcessShutdown(signal: NodeJS.Signals): void {
|
||||
if (!activeKanbanProcess) {
|
||||
return
|
||||
}
|
||||
|
||||
forwardSignalToKanbanProcess({
|
||||
child: activeKanbanProcess,
|
||||
signal,
|
||||
})
|
||||
|
||||
if (activeKanbanShutdownTimer) {
|
||||
clearTimeout(activeKanbanShutdownTimer)
|
||||
}
|
||||
|
||||
if (signal === "SIGKILL") {
|
||||
activeKanbanShutdownTimer = null
|
||||
return
|
||||
}
|
||||
|
||||
activeKanbanShutdownTimer = setTimeout(() => {
|
||||
if (!activeKanbanProcess) {
|
||||
return
|
||||
}
|
||||
forwardSignalToKanbanProcess({
|
||||
child: activeKanbanProcess,
|
||||
signal: "SIGKILL",
|
||||
})
|
||||
}, KANBAN_SHUTDOWN_TIMEOUT_MS)
|
||||
activeKanbanShutdownTimer.unref?.()
|
||||
}
|
||||
|
||||
function resolveProcessExitCode(code: number | null, signal: NodeJS.Signals | null): number {
|
||||
if (code !== null) {
|
||||
return code
|
||||
}
|
||||
|
||||
switch (signal) {
|
||||
case "SIGINT":
|
||||
return 130
|
||||
case "SIGTERM":
|
||||
return 143
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for stdout to fully drain before exiting.
|
||||
@@ -402,6 +521,17 @@ function onUnhandledException(reason: unknown, context: string) {
|
||||
|
||||
function setupSignalHandlers() {
|
||||
const shutdown = async (signal: string) => {
|
||||
if (activeKanbanProcess) {
|
||||
if (isShuttingDown) {
|
||||
requestKanbanProcessShutdown("SIGKILL")
|
||||
return
|
||||
}
|
||||
|
||||
isShuttingDown = true
|
||||
requestKanbanProcessShutdown(signal === "SIGTERM" ? "SIGTERM" : "SIGINT")
|
||||
return
|
||||
}
|
||||
|
||||
if (isShuttingDown) {
|
||||
// Force exit on second signal
|
||||
process.exit(1)
|
||||
@@ -897,9 +1027,12 @@ program
|
||||
.command("update")
|
||||
.description("Check for updates and install if available")
|
||||
.option("-v, --verbose", "Show verbose output")
|
||||
.action(() => checkForUpdates(CLI_VERSION))
|
||||
.action((options) => checkForUpdates(CLI_VERSION, { verbose: options.verbose, includeKanban: true }))
|
||||
|
||||
program.command("kanban").description("Run npx kanban --agent cline").action(runKanbanAlias)
|
||||
program
|
||||
.command("kanban")
|
||||
.description(`Run ${KANBAN_LAUNCH_COMMAND}`)
|
||||
.action(() => runKanbanAlias())
|
||||
|
||||
// Dev command with subcommands
|
||||
const devCommand = program.command("dev").description("Developer tools and utilities")
|
||||
@@ -1050,17 +1183,34 @@ program
|
||||
.option("--auto-condense", "Enable AI-powered context compaction instead of mechanical truncation")
|
||||
.option("--hooks-dir <path>", "Path to additional hooks directory for runtime hook injection")
|
||||
.option("--acp", "Run in ACP (Agent Client Protocol) mode for editor integration")
|
||||
.option("--kanban", "Run npx kanban --agent cline")
|
||||
.option("--update", "Check for updates and install if available")
|
||||
.option("--kanban", `Run ${KANBAN_LAUNCH_COMMAND}`)
|
||||
.option("--tui", "Open the legacy terminal UI instead of the kanban experience")
|
||||
.option("-T, --taskId <id>", "Resume an existing task by ID")
|
||||
.option("--continue", "Resume the most recent task from the current working directory")
|
||||
.action(async (prompt, options) => {
|
||||
if (options.kanban && options.tui) {
|
||||
printWarning(`Use either --kanban or ${LEGACY_TUI_FLAG}, not both.`)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
if (options.update) {
|
||||
if (prompt || options.taskId || options.continue || options.kanban || options.tui || options.acp) {
|
||||
printWarning("Use --update without a prompt or task flags.")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
await checkForUpdates(CLI_VERSION, { verbose: options.verbose, includeKanban: true })
|
||||
return
|
||||
}
|
||||
|
||||
if (options.kanban) {
|
||||
if (prompt) {
|
||||
printWarning("Use --kanban without a prompt.")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
runKanbanAlias()
|
||||
runKanbanAlias({ cwd: options.cwd })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1084,6 +1234,34 @@ program
|
||||
// stdinInput has content means stdin was piped with data
|
||||
const stdinWasPiped = stdinInput !== null
|
||||
|
||||
if (
|
||||
shouldLaunchKanbanByDefault({
|
||||
prompt,
|
||||
stdinWasPiped,
|
||||
taskId: options.taskId,
|
||||
continue: options.continue,
|
||||
tui: options.tui,
|
||||
})
|
||||
) {
|
||||
let migrationAction: "kanban" | "exit" = "kanban"
|
||||
const ctx = await initializeCli({ ...options, enableAuth: true })
|
||||
try {
|
||||
if (await shouldShowKanbanMigrationAnnouncementForCurrentUser()) {
|
||||
migrationAction = await showKanbanMigrationView()
|
||||
await markKanbanMigrationAnnouncementShown()
|
||||
}
|
||||
} finally {
|
||||
await disposeCliContext(ctx)
|
||||
}
|
||||
|
||||
if (migrationAction === "exit") {
|
||||
exit(0)
|
||||
}
|
||||
|
||||
runKanbanAlias({ cwd: options.cwd })
|
||||
return
|
||||
}
|
||||
|
||||
if (options.taskId && options.continue) {
|
||||
printWarning("Use either --taskId or --continue, not both.")
|
||||
exit(1)
|
||||
|
||||
@@ -15,3 +15,13 @@ export function isMouseEscapeSequence(input: string): boolean {
|
||||
// They contain [< followed by numbers, semicolons, and end with M or m
|
||||
return input.includes("[<") && /\[<\d+;\d+;\d+[Mm]/.test(input)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ink's key metadata can be inconsistent across platforms/test environments for Enter.
|
||||
* In particular, some Windows CI/test runs surface Enter as raw "\r" input without
|
||||
* setting key.return. Treat either representation as Enter so keyboard handlers remain
|
||||
* stable in production and in tests across platforms.
|
||||
*/
|
||||
export function isEnterKey(input: string, key: { return?: boolean }): boolean {
|
||||
return key.return === true || input === "\r" || input === "\n"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"
|
||||
import { tmpdir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
import { describe, expect, it, vi } from "vitest"
|
||||
import {
|
||||
buildKanbanInstallSpawnOptions,
|
||||
buildKanbanSpawnOptions,
|
||||
forwardSignalToKanbanProcess,
|
||||
hasUsedLegacyCli,
|
||||
isKanbanCommandAvailable,
|
||||
resolveKanbanInstallCommand,
|
||||
shouldDetachKanbanProcess,
|
||||
shouldLaunchKanbanByDefault,
|
||||
shouldShowKanbanMigrationAnnouncement,
|
||||
} from "./kanban"
|
||||
|
||||
describe("shouldLaunchKanbanByDefault", () => {
|
||||
it("launches kanban for a bare interactive run", () => {
|
||||
expect(
|
||||
shouldLaunchKanbanByDefault({
|
||||
stdinWasPiped: false,
|
||||
}),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it("does not launch kanban when a prompt is provided", () => {
|
||||
expect(
|
||||
shouldLaunchKanbanByDefault({
|
||||
prompt: "fix the tests",
|
||||
stdinWasPiped: false,
|
||||
}),
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it("does not launch kanban when stdin is piped", () => {
|
||||
expect(
|
||||
shouldLaunchKanbanByDefault({
|
||||
stdinWasPiped: true,
|
||||
}),
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it("does not launch kanban when the legacy tui is requested", () => {
|
||||
expect(
|
||||
shouldLaunchKanbanByDefault({
|
||||
stdinWasPiped: false,
|
||||
tui: true,
|
||||
}),
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("hasUsedLegacyCli", () => {
|
||||
it("treats task history as legacy usage", () => {
|
||||
expect(
|
||||
hasUsedLegacyCli({
|
||||
taskHistoryCount: 1,
|
||||
isNewUser: true,
|
||||
welcomeViewCompleted: undefined,
|
||||
hasConfiguredAuth: false,
|
||||
}),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it("treats configured auth as legacy usage", () => {
|
||||
expect(
|
||||
hasUsedLegacyCli({
|
||||
taskHistoryCount: 0,
|
||||
isNewUser: true,
|
||||
welcomeViewCompleted: undefined,
|
||||
hasConfiguredAuth: true,
|
||||
}),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it("skips the announcement for fresh installs", () => {
|
||||
expect(
|
||||
hasUsedLegacyCli({
|
||||
taskHistoryCount: 0,
|
||||
isNewUser: true,
|
||||
welcomeViewCompleted: undefined,
|
||||
hasConfiguredAuth: false,
|
||||
}),
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("kanban process launch", () => {
|
||||
it("detaches the kanban process on unix-like platforms", () => {
|
||||
expect(shouldDetachKanbanProcess("darwin")).toBe(true)
|
||||
expect(shouldDetachKanbanProcess("linux")).toBe(true)
|
||||
})
|
||||
|
||||
it("keeps the kanban process attached on windows", () => {
|
||||
expect(shouldDetachKanbanProcess("win32")).toBe(false)
|
||||
})
|
||||
|
||||
it("uses a detached process group by default on unix-like platforms", () => {
|
||||
expect(buildKanbanSpawnOptions({}, "darwin")).toMatchObject({
|
||||
stdio: "inherit",
|
||||
detached: true,
|
||||
})
|
||||
})
|
||||
|
||||
it("does not detach the process on windows", () => {
|
||||
expect(buildKanbanSpawnOptions({}, "win32")).toMatchObject({
|
||||
stdio: "inherit",
|
||||
detached: false,
|
||||
})
|
||||
})
|
||||
|
||||
it("enables shell mode on windows for command launches", () => {
|
||||
expect(buildKanbanSpawnOptions({}, "win32")).toMatchObject({
|
||||
shell: true,
|
||||
})
|
||||
})
|
||||
|
||||
it("does not set shell mode on unix-like platforms", () => {
|
||||
expect(buildKanbanSpawnOptions({}, "darwin")).not.toHaveProperty("shell")
|
||||
})
|
||||
})
|
||||
|
||||
describe("kanban command availability", () => {
|
||||
it("returns false when PATH is empty", () => {
|
||||
expect(isKanbanCommandAvailable({ PATH: "" }, "darwin")).toBe(false)
|
||||
})
|
||||
|
||||
it("detects the kanban command in PATH", () => {
|
||||
const tempDirectory = mkdtempSync(join(tmpdir(), "kanban-cli-test-"))
|
||||
const commandPath = join(tempDirectory, process.platform === "win32" ? "kanban.cmd" : "kanban")
|
||||
writeFileSync(commandPath, process.platform === "win32" ? "@echo off\r\necho ok\r\n" : "#!/bin/sh\necho ok\n")
|
||||
if (process.platform !== "win32") {
|
||||
chmodSync(commandPath, 0o755)
|
||||
}
|
||||
|
||||
try {
|
||||
expect(isKanbanCommandAvailable({ PATH: tempDirectory }, process.platform)).toBe(true)
|
||||
} finally {
|
||||
rmSync(tempDirectory, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("kanban install process launch", () => {
|
||||
it("does not detach the install process on unix-like platforms", () => {
|
||||
expect(buildKanbanInstallSpawnOptions({}, "darwin")).toMatchObject({
|
||||
stdio: "inherit",
|
||||
detached: false,
|
||||
})
|
||||
})
|
||||
|
||||
it("enables shell mode on windows for npm.cmd launches", () => {
|
||||
expect(buildKanbanInstallSpawnOptions({}, "win32")).toMatchObject({
|
||||
shell: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("kanban installer resolution", () => {
|
||||
it("prefers npm when available", () => {
|
||||
const tempDirectory = mkdtempSync(join(tmpdir(), "kanban-installer-test-"))
|
||||
writeFileSync(join(tempDirectory, "npm"), "#!/bin/sh\necho npm\n")
|
||||
writeFileSync(join(tempDirectory, "pnpm"), "#!/bin/sh\necho pnpm\n")
|
||||
writeFileSync(join(tempDirectory, "bun"), "#!/bin/sh\necho bun\n")
|
||||
chmodSync(join(tempDirectory, "npm"), 0o755)
|
||||
chmodSync(join(tempDirectory, "pnpm"), 0o755)
|
||||
chmodSync(join(tempDirectory, "bun"), 0o755)
|
||||
|
||||
try {
|
||||
expect(resolveKanbanInstallCommand({ PATH: tempDirectory }, "darwin")?.packageManager).toBe("npm")
|
||||
} finally {
|
||||
rmSync(tempDirectory, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
it("falls back to pnpm when npm is unavailable", () => {
|
||||
const tempDirectory = mkdtempSync(join(tmpdir(), "kanban-installer-test-"))
|
||||
writeFileSync(join(tempDirectory, "pnpm"), "#!/bin/sh\necho pnpm\n")
|
||||
chmodSync(join(tempDirectory, "pnpm"), 0o755)
|
||||
|
||||
try {
|
||||
const installer = resolveKanbanInstallCommand({ PATH: tempDirectory }, "darwin")
|
||||
expect(installer?.packageManager).toBe("pnpm")
|
||||
expect(installer?.displayCommand).toBe("pnpm add -g kanban@latest")
|
||||
} finally {
|
||||
rmSync(tempDirectory, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
it("falls back to bun when npm and pnpm are unavailable", () => {
|
||||
const tempDirectory = mkdtempSync(join(tmpdir(), "kanban-installer-test-"))
|
||||
writeFileSync(join(tempDirectory, "bun"), "#!/bin/sh\necho bun\n")
|
||||
chmodSync(join(tempDirectory, "bun"), 0o755)
|
||||
|
||||
try {
|
||||
const installer = resolveKanbanInstallCommand({ PATH: tempDirectory }, "darwin")
|
||||
expect(installer?.packageManager).toBe("bun")
|
||||
expect(installer?.displayCommand).toBe("bun add -g kanban@latest")
|
||||
} finally {
|
||||
rmSync(tempDirectory, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
it("returns null when no supported package manager is available", () => {
|
||||
expect(resolveKanbanInstallCommand({ PATH: "" }, "darwin")).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe("forwardSignalToKanbanProcess", () => {
|
||||
it("signals the detached kanban process group on unix-like platforms", () => {
|
||||
const killProcess = vi.fn()
|
||||
const child = {
|
||||
pid: 4321,
|
||||
kill: vi.fn(),
|
||||
}
|
||||
|
||||
forwardSignalToKanbanProcess({
|
||||
child,
|
||||
signal: "SIGINT",
|
||||
platform: "darwin",
|
||||
killProcess,
|
||||
})
|
||||
|
||||
expect(killProcess).toHaveBeenCalledWith(-4321, "SIGINT")
|
||||
expect(child.kill).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("signals the child process directly on windows", () => {
|
||||
const killProcess = vi.fn()
|
||||
const child = {
|
||||
pid: 4321,
|
||||
kill: vi.fn(),
|
||||
}
|
||||
|
||||
forwardSignalToKanbanProcess({
|
||||
child,
|
||||
signal: "SIGTERM",
|
||||
platform: "win32",
|
||||
killProcess,
|
||||
})
|
||||
|
||||
expect(killProcess).not.toHaveBeenCalled()
|
||||
expect(child.kill).toHaveBeenCalledWith("SIGTERM")
|
||||
})
|
||||
})
|
||||
|
||||
describe("shouldShowKanbanMigrationAnnouncement", () => {
|
||||
it("shows the announcement once for legacy users", () => {
|
||||
expect(
|
||||
shouldShowKanbanMigrationAnnouncement({
|
||||
announcementShown: false,
|
||||
hasUsedLegacyCli: true,
|
||||
}),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it("does not show the announcement twice", () => {
|
||||
expect(
|
||||
shouldShowKanbanMigrationAnnouncement({
|
||||
announcementShown: true,
|
||||
hasUsedLegacyCli: true,
|
||||
}),
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,246 @@
|
||||
import { type ChildProcess, type SpawnOptions, spawn } from "node:child_process"
|
||||
import { accessSync, constants as fsConstants } from "node:fs"
|
||||
import { delimiter, extname, join } from "node:path"
|
||||
import { StateManager } from "@/core/storage/StateManager"
|
||||
import { checkAnyProviderConfigured } from "./auth"
|
||||
|
||||
export const KANBAN_LAUNCH_COMMAND = "kanban"
|
||||
export const KANBAN_SHUTDOWN_TIMEOUT_MS = 10_000
|
||||
export const LEGACY_TUI_FLAG = "--tui"
|
||||
export type KanbanMigrationAction = "kanban" | "exit"
|
||||
type KanbanInstaller = "npm" | "pnpm" | "bun"
|
||||
|
||||
interface KanbanInstallCommand {
|
||||
packageManager: KanbanInstaller
|
||||
command: string
|
||||
args: readonly string[]
|
||||
displayCommand: string
|
||||
}
|
||||
|
||||
interface SignalableKanbanProcess {
|
||||
pid?: number
|
||||
kill: (signal?: NodeJS.Signals | number) => boolean
|
||||
}
|
||||
|
||||
function getKanbanCommand(platform: NodeJS.Platform = process.platform): string {
|
||||
return platform === "win32" ? "kanban.cmd" : "kanban"
|
||||
}
|
||||
|
||||
function getPackageManagerCommand(packageManager: KanbanInstaller, platform: NodeJS.Platform = process.platform): string {
|
||||
if (platform !== "win32") {
|
||||
return packageManager
|
||||
}
|
||||
|
||||
return packageManager === "bun" ? "bun" : `${packageManager}.cmd`
|
||||
}
|
||||
|
||||
const KANBAN_INSTALL_COMMANDS: ReadonlyArray<Omit<KanbanInstallCommand, "displayCommand">> = [
|
||||
{
|
||||
packageManager: "npm",
|
||||
command: "npm",
|
||||
args: ["install", "-g", "kanban@latest"],
|
||||
},
|
||||
{
|
||||
packageManager: "pnpm",
|
||||
command: "pnpm",
|
||||
args: ["add", "-g", "kanban@latest"],
|
||||
},
|
||||
{
|
||||
packageManager: "bun",
|
||||
command: "bun",
|
||||
args: ["add", "-g", "kanban@latest"],
|
||||
},
|
||||
]
|
||||
|
||||
function toDisplayCommand(command: string, args: readonly string[]): string {
|
||||
return `${command} ${args.join(" ")}`
|
||||
}
|
||||
|
||||
export function shouldDetachKanbanProcess(platform: NodeJS.Platform = process.platform): boolean {
|
||||
return platform !== "win32"
|
||||
}
|
||||
|
||||
export function buildKanbanSpawnOptions(options: SpawnOptions = {}, platform: NodeJS.Platform = process.platform): SpawnOptions {
|
||||
return {
|
||||
stdio: "inherit",
|
||||
detached: shouldDetachKanbanProcess(platform),
|
||||
...(platform === "win32" ? { shell: true } : {}),
|
||||
...options,
|
||||
}
|
||||
}
|
||||
|
||||
export function buildKanbanInstallSpawnOptions(
|
||||
options: SpawnOptions = {},
|
||||
platform: NodeJS.Platform = process.platform,
|
||||
): SpawnOptions {
|
||||
return {
|
||||
stdio: "inherit",
|
||||
detached: false,
|
||||
...(platform === "win32" ? { shell: true } : {}),
|
||||
...options,
|
||||
}
|
||||
}
|
||||
|
||||
export function spawnKanbanProcess(options: SpawnOptions = {}): ChildProcess {
|
||||
return spawn(getKanbanCommand(), [], buildKanbanSpawnOptions(options))
|
||||
}
|
||||
|
||||
export function spawnKanbanInstallProcess(installCommand: KanbanInstallCommand, options: SpawnOptions = {}): ChildProcess {
|
||||
return spawn(
|
||||
getPackageManagerCommand(installCommand.packageManager),
|
||||
[...installCommand.args],
|
||||
buildKanbanInstallSpawnOptions(options),
|
||||
)
|
||||
}
|
||||
|
||||
function getPathEntries(env: NodeJS.ProcessEnv): string[] {
|
||||
const pathValue = env.PATH ?? env.Path ?? env.path
|
||||
if (!pathValue) {
|
||||
return []
|
||||
}
|
||||
|
||||
return pathValue
|
||||
.split(delimiter)
|
||||
.map((entry) => entry.trim().replace(/^"(.*)"$/u, "$1"))
|
||||
.filter((entry) => entry.length > 0)
|
||||
}
|
||||
|
||||
function pathExists(candidatePath: string, platform: NodeJS.Platform): boolean {
|
||||
try {
|
||||
if (platform === "win32") {
|
||||
accessSync(candidatePath, fsConstants.F_OK)
|
||||
} else {
|
||||
accessSync(candidatePath, fsConstants.X_OK)
|
||||
}
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function isCommandAvailable(
|
||||
command: string,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
platform: NodeJS.Platform = process.platform,
|
||||
): boolean {
|
||||
const commandHasExtension = extname(command).length > 0
|
||||
const pathExtensions =
|
||||
platform === "win32" ? (env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").filter((ext) => ext.length > 0) : []
|
||||
|
||||
for (const pathEntry of getPathEntries(env)) {
|
||||
const commandPath = join(pathEntry, command)
|
||||
if (pathExists(commandPath, platform)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!commandHasExtension && platform === "win32") {
|
||||
for (const extension of pathExtensions) {
|
||||
if (pathExists(`${commandPath}${extension}`, platform)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function isKanbanCommandAvailable(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
platform: NodeJS.Platform = process.platform,
|
||||
): boolean {
|
||||
return isCommandAvailable(getKanbanCommand(platform), env, platform)
|
||||
}
|
||||
|
||||
export function resolveKanbanInstallCommand(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
platform: NodeJS.Platform = process.platform,
|
||||
): KanbanInstallCommand | null {
|
||||
for (const installCommand of KANBAN_INSTALL_COMMANDS) {
|
||||
if (isCommandAvailable(installCommand.command, env, platform)) {
|
||||
return {
|
||||
...installCommand,
|
||||
displayCommand: toDisplayCommand(installCommand.command, installCommand.args),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function forwardSignalToKanbanProcess(options: {
|
||||
child: SignalableKanbanProcess
|
||||
signal: NodeJS.Signals
|
||||
platform?: NodeJS.Platform
|
||||
killProcess?: (pid: number, signal: NodeJS.Signals | number) => boolean
|
||||
}): void {
|
||||
if (options.child.pid == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (shouldDetachKanbanProcess(options.platform)) {
|
||||
try {
|
||||
;(options.killProcess ?? process.kill)(-options.child.pid, options.signal)
|
||||
return
|
||||
} catch (error) {
|
||||
if (error && typeof error === "object" && "code" in error && error.code === "ESRCH") {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
options.child.kill(options.signal)
|
||||
}
|
||||
|
||||
export function shouldLaunchKanbanByDefault(options: {
|
||||
prompt?: string
|
||||
stdinWasPiped: boolean
|
||||
taskId?: string
|
||||
continue?: boolean
|
||||
tui?: boolean
|
||||
}): boolean {
|
||||
return !options.prompt && !options.stdinWasPiped && !options.taskId && !options.continue && !options.tui
|
||||
}
|
||||
|
||||
export function hasUsedLegacyCli(options: {
|
||||
taskHistoryCount: number
|
||||
isNewUser: boolean
|
||||
welcomeViewCompleted: boolean | undefined
|
||||
hasConfiguredAuth: boolean
|
||||
}): boolean {
|
||||
return (
|
||||
options.taskHistoryCount > 0 ||
|
||||
options.isNewUser === false ||
|
||||
options.welcomeViewCompleted !== undefined ||
|
||||
options.hasConfiguredAuth
|
||||
)
|
||||
}
|
||||
|
||||
export function shouldShowKanbanMigrationAnnouncement(options: {
|
||||
announcementShown: boolean
|
||||
hasUsedLegacyCli: boolean
|
||||
}): boolean {
|
||||
return !options.announcementShown && options.hasUsedLegacyCli
|
||||
}
|
||||
|
||||
export async function shouldShowKanbanMigrationAnnouncementForCurrentUser(): Promise<boolean> {
|
||||
const stateManager = StateManager.get()
|
||||
const hasConfiguredAuth = await checkAnyProviderConfigured()
|
||||
const hasUsedLegacy = hasUsedLegacyCli({
|
||||
taskHistoryCount: stateManager.getGlobalStateKey("taskHistory")?.length ?? 0,
|
||||
isNewUser: stateManager.getGlobalStateKey("isNewUser"),
|
||||
welcomeViewCompleted: stateManager.getGlobalStateKey("welcomeViewCompleted"),
|
||||
hasConfiguredAuth,
|
||||
})
|
||||
|
||||
return shouldShowKanbanMigrationAnnouncement({
|
||||
announcementShown: stateManager.getGlobalStateKey("cliKanbanMigrationAnnouncementShown"),
|
||||
hasUsedLegacyCli: hasUsedLegacy,
|
||||
})
|
||||
}
|
||||
|
||||
export async function markKanbanMigrationAnnouncementShown(): Promise<void> {
|
||||
const stateManager = StateManager.get()
|
||||
stateManager.setGlobalState("cliKanbanMigrationAnnouncementShown", true)
|
||||
await stateManager.flushPendingState()
|
||||
}
|
||||
+198
-70
@@ -1,9 +1,10 @@
|
||||
import { spawn } from "node:child_process"
|
||||
import { type ChildProcess, spawn, spawnSync } from "node:child_process"
|
||||
import { realpathSync } from "node:fs"
|
||||
import { exit } from "node:process"
|
||||
import { ClineEndpoint } from "@/config"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { printInfo, printWarning } from "./display"
|
||||
import { printInfo, printSuccess, printWarning } from "./display"
|
||||
import { resolveKanbanInstallCommand, spawnKanbanInstallProcess } from "./kanban"
|
||||
|
||||
export enum PackageManager {
|
||||
NPM = "npm",
|
||||
@@ -19,6 +20,11 @@ interface InstallationInfo {
|
||||
updateCommand?: string
|
||||
}
|
||||
|
||||
interface CheckForUpdatesOptions {
|
||||
verbose?: boolean
|
||||
includeKanban?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a version string is a nightly build.
|
||||
*/
|
||||
@@ -91,9 +97,12 @@ function getInstallationInfo(currentVersion: string): InstallationInfo {
|
||||
* Uses the appropriate tag based on whether the current version is nightly.
|
||||
*/
|
||||
async function getLatestVersion(currentVersion: string): Promise<string | null> {
|
||||
return getLatestPackageVersion("cline", getNpmTag(currentVersion))
|
||||
}
|
||||
|
||||
async function getLatestPackageVersion(packageName: string, tag = "latest"): Promise<string | null> {
|
||||
try {
|
||||
const tag = getNpmTag(currentVersion)
|
||||
const response = await fetch(`https://registry.npmjs.org/cline/${tag}`)
|
||||
const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/${tag}`)
|
||||
if (!response.ok) return null
|
||||
const data = (await response.json()) as { version: string }
|
||||
return data.version || null
|
||||
@@ -102,6 +111,29 @@ async function getLatestVersion(currentVersion: string): Promise<string | null>
|
||||
}
|
||||
}
|
||||
|
||||
async function getLatestKanbanVersion(): Promise<string | null> {
|
||||
return getLatestPackageVersion("kanban")
|
||||
}
|
||||
|
||||
function getInstalledKanbanVersion(): string | null {
|
||||
try {
|
||||
const command = process.platform === "win32" ? "kanban.cmd" : "kanban"
|
||||
const result = spawnSync(command, ["--version"], {
|
||||
encoding: "utf8",
|
||||
shell: process.platform === "win32",
|
||||
})
|
||||
if (result.status !== 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`.trim()
|
||||
const versionMatch = output.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/)
|
||||
return versionMatch?.[0] ?? null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-update check that runs on CLI startup.
|
||||
* Checks for updates asynchronously (non-blocking), then spawns a detached
|
||||
@@ -157,85 +189,181 @@ async function checkAndUpdate(currentVersion: string, updateCommand: string): Pr
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForProcessExit(updateProcess: ChildProcess): Promise<number> {
|
||||
return new Promise<number>((resolve, reject) => {
|
||||
updateProcess.once("close", (code) => {
|
||||
resolve(code ?? 1)
|
||||
})
|
||||
|
||||
updateProcess.once("error", (error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function runClineUpdate(updateCommand: string): Promise<number> {
|
||||
const updateProcess = spawn(updateCommand, {
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
env: process.env,
|
||||
windowsHide: true,
|
||||
})
|
||||
|
||||
return waitForProcessExit(updateProcess)
|
||||
}
|
||||
|
||||
type KanbanInstallCommand = NonNullable<ReturnType<typeof resolveKanbanInstallCommand>>
|
||||
|
||||
async function runKanbanUpdate(installCommand: KanbanInstallCommand): Promise<number> {
|
||||
const updateProcess = spawnKanbanInstallProcess(installCommand, {
|
||||
env: process.env,
|
||||
windowsHide: true,
|
||||
})
|
||||
return waitForProcessExit(updateProcess)
|
||||
}
|
||||
|
||||
function formatUpdateSummaryTargets(targets: string[]): string {
|
||||
if (targets.length === 0) {
|
||||
return ""
|
||||
}
|
||||
if (targets.length === 1) {
|
||||
return targets[0]
|
||||
}
|
||||
if (targets.length === 2) {
|
||||
return `${targets[0]} and ${targets[1]}`
|
||||
}
|
||||
return `${targets.slice(0, -1).join(", ")}, and ${targets.at(-1)}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for updates and install if available (manual command)
|
||||
*/
|
||||
export async function checkForUpdates(currentVersion: string, options?: { verbose?: boolean }) {
|
||||
printInfo("Checking for updates...")
|
||||
export async function checkForUpdates(currentVersion: string, options: CheckForUpdatesOptions = {}) {
|
||||
const includeKanban = options.includeKanban ?? true
|
||||
|
||||
printInfo("Checking for updates to cline and kanban packages...")
|
||||
|
||||
const { updateCommand, packageManager } = getInstallationInfo(currentVersion)
|
||||
|
||||
try {
|
||||
const latestVersion = await getLatestVersion(currentVersion)
|
||||
if (!latestVersion) {
|
||||
printWarning("Failed to check for updates: could not fetch latest version")
|
||||
exit(1)
|
||||
}
|
||||
const latestClineVersion = await getLatestVersion(currentVersion)
|
||||
const canCheckClineVersion = latestClineVersion !== null
|
||||
|
||||
if (options?.verbose) {
|
||||
printInfo(`Current version: ${currentVersion}`)
|
||||
printInfo(`Latest version: ${latestVersion}`)
|
||||
printInfo(`Package manager: ${packageManager}`)
|
||||
}
|
||||
|
||||
// Compare versions
|
||||
if (latestVersion === currentVersion) {
|
||||
printInfo(`You are already on the latest version (${currentVersion})`)
|
||||
exit(0)
|
||||
}
|
||||
|
||||
// Check if current is newer (dev version)
|
||||
if (compareVersions(currentVersion, latestVersion) > 0) {
|
||||
printInfo(`You are already on a newer version ${currentVersion} (latest: ${latestVersion})`)
|
||||
exit(0)
|
||||
}
|
||||
|
||||
printInfo(`New version available: ${latestVersion} (current: ${currentVersion})`)
|
||||
|
||||
if (!updateCommand) {
|
||||
printInfo("Unable to determine update command for your installation.")
|
||||
printInfo("Please update manually using your package manager.")
|
||||
exit(0)
|
||||
}
|
||||
|
||||
// Ask user to confirm update
|
||||
const userConfirmed = new Promise<boolean>((resolve) => {
|
||||
process.stdout.write("Do you want to update now? (y/N): ")
|
||||
process.stdin.setEncoding("utf-8")
|
||||
process.stdin.once("data", (dataBuff) => {
|
||||
const input = dataBuff.toString().trim().toLowerCase()
|
||||
resolve(input === "y" || input === "yes")
|
||||
})
|
||||
})
|
||||
|
||||
if (!(await userConfirmed)) {
|
||||
exit(0)
|
||||
}
|
||||
|
||||
printInfo(`Installing update via ${packageManager}...`)
|
||||
|
||||
const updateProcess = spawn(updateCommand, {
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
env: process.env,
|
||||
windowsHide: true,
|
||||
})
|
||||
|
||||
updateProcess.on("close", (code) => {
|
||||
if (code === 0) {
|
||||
printInfo(`Successfully updated to version ${latestVersion}`)
|
||||
exit(0)
|
||||
} else {
|
||||
printWarning(`Update failed. Please try running: ${updateCommand}`)
|
||||
exit(1)
|
||||
if (canCheckClineVersion) {
|
||||
printInfo(`Latest version: ${latestClineVersion}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
updateProcess.on("error", (err) => {
|
||||
printWarning(`Failed to run update: ${err.message}`)
|
||||
printInfo(`Please try running manually: ${updateCommand}`)
|
||||
if (!canCheckClineVersion) {
|
||||
printWarning("Failed to check for Cline updates: could not fetch latest version")
|
||||
}
|
||||
|
||||
const clineComparison = latestClineVersion ? compareVersions(currentVersion, latestClineVersion) : null
|
||||
const clineUpdateAvailable = clineComparison !== null && clineComparison < 0
|
||||
const clineIsUpToDate = clineComparison !== null && clineComparison === 0
|
||||
const canUpdateCline = clineUpdateAvailable && Boolean(updateCommand)
|
||||
|
||||
if (clineUpdateAvailable && latestClineVersion) {
|
||||
printInfo(`New version available: ${latestClineVersion} (current: ${currentVersion})`)
|
||||
}
|
||||
|
||||
if (clineUpdateAvailable && !updateCommand) {
|
||||
printInfo("Unable to determine Cline update command for your installation.")
|
||||
printInfo("Please update Cline manually using your package manager.")
|
||||
}
|
||||
|
||||
const kanbanInstallCommand = includeKanban ? resolveKanbanInstallCommand() : null
|
||||
const kanbanInstallerAvailable = kanbanInstallCommand !== null
|
||||
if (includeKanban && !kanbanInstallerAvailable && options.verbose) {
|
||||
printWarning("Unable to determine Kanban update command (npm, pnpm, or bun not found in PATH).")
|
||||
}
|
||||
const latestKanbanVersion = kanbanInstallerAvailable ? await getLatestKanbanVersion() : null
|
||||
const installedKanbanVersion = includeKanban ? getInstalledKanbanVersion() : null
|
||||
const kanbanIsUpToDate =
|
||||
latestKanbanVersion !== null &&
|
||||
installedKanbanVersion !== null &&
|
||||
compareVersions(installedKanbanVersion, latestKanbanVersion) >= 0
|
||||
const shouldInstallKanban =
|
||||
kanbanInstallerAvailable &&
|
||||
latestKanbanVersion !== null &&
|
||||
(installedKanbanVersion === null || compareVersions(installedKanbanVersion, latestKanbanVersion) < 0)
|
||||
|
||||
if (!canCheckClineVersion && !shouldInstallKanban) {
|
||||
exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
if (!canUpdateCline && !shouldInstallKanban) {
|
||||
if (clineIsUpToDate && kanbanIsUpToDate && installedKanbanVersion) {
|
||||
printInfo(`You are already on the latest version cline@${currentVersion} and kanban@${installedKanbanVersion}`)
|
||||
} else if (clineIsUpToDate) {
|
||||
printInfo(`You are already on the latest version cline@${currentVersion}`)
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
|
||||
let hadFailure = false
|
||||
const installedUpdates: string[] = []
|
||||
|
||||
if (canUpdateCline && updateCommand && latestClineVersion) {
|
||||
printInfo(`Installing cline@${latestClineVersion}...`)
|
||||
try {
|
||||
const clineUpdateCode = await runClineUpdate(updateCommand)
|
||||
if (clineUpdateCode === 0) {
|
||||
installedUpdates.push(`cline@${latestClineVersion}`)
|
||||
} else {
|
||||
printWarning(`Cline update failed. Please try running: ${updateCommand}`)
|
||||
hadFailure = true
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
printWarning(`Failed to run Cline update: ${message}`)
|
||||
printInfo(`Please try running manually: ${updateCommand}`)
|
||||
hadFailure = true
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldInstallKanban && kanbanInstallCommand && latestKanbanVersion) {
|
||||
const kanbanTargetVersion = latestKanbanVersion ?? "latest"
|
||||
printInfo(`Installing kanban@${kanbanTargetVersion}...`)
|
||||
try {
|
||||
const kanbanUpdateCode = await runKanbanUpdate(kanbanInstallCommand)
|
||||
if (kanbanUpdateCode === 0) {
|
||||
installedUpdates.push(`kanban@${kanbanTargetVersion}`)
|
||||
} else {
|
||||
printWarning(`Kanban update failed. Please try running: ${kanbanInstallCommand.displayCommand}`)
|
||||
hadFailure = true
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
printWarning(`Failed to run Kanban update: ${message}`)
|
||||
if (kanbanInstallCommand) {
|
||||
printInfo(`Please try running manually: ${kanbanInstallCommand.displayCommand}`)
|
||||
}
|
||||
hadFailure = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!hadFailure) {
|
||||
if (installedUpdates.length > 1) {
|
||||
printSuccess(`Installed updates for ${formatUpdateSummaryTargets(installedUpdates)}`)
|
||||
} else if (installedUpdates.length === 1) {
|
||||
printSuccess(`Installed update for ${installedUpdates[0]}`)
|
||||
} else {
|
||||
printInfo("No updates were installed.")
|
||||
}
|
||||
}
|
||||
|
||||
if (hadFailure) {
|
||||
exit(1)
|
||||
}
|
||||
|
||||
if (canUpdateCline || shouldInstallKanban) {
|
||||
exit(0)
|
||||
}
|
||||
exit(1)
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
printWarning(`Error checking for updates: ${message}`)
|
||||
@@ -259,7 +387,7 @@ function parseVersion(version: string): ParsedVersion {
|
||||
return {
|
||||
base: nightlyMatch[1].split(".").map(Number),
|
||||
isNightly: true,
|
||||
timestamp: parseInt(nightlyMatch[2], 10),
|
||||
timestamp: Number.parseInt(nightlyMatch[2], 10),
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -69,7 +69,7 @@ cline auth
|
||||
cline auth -p cline -k "YOUR_API_KEY" -m anthropic/claude-sonnet-4-6
|
||||
```
|
||||
|
||||
See the [CLI Reference](/cline-cli/cli-reference#cline-auth) for all auth options.
|
||||
See the [CLI Reference](/cli/cli-reference#cline-auth) for all auth options.
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
|
||||
+4
-29
@@ -21,32 +21,7 @@ For example:
|
||||
|
||||
Pass this string as the `model` parameter in your [Chat Completions](/api/chat-completions) request.
|
||||
|
||||
## Popular Models
|
||||
|
||||
| Model ID | Provider | Context Window | Reasoning | Best For |
|
||||
|----------|----------|---------------|-----------|----------|
|
||||
| `anthropic/claude-sonnet-4-6` | Anthropic | 200K | Yes | General coding, analysis, complex tasks |
|
||||
| `anthropic/claude-sonnet-4-5` | Anthropic | 200K | Yes | Balanced performance and cost |
|
||||
| `openai/gpt-4o` | OpenAI | 128K | No | Multimodal tasks, fast responses |
|
||||
| `google/gemini-2.5-pro` | Google | 1M | Yes | Very long context, document analysis |
|
||||
| `deepseek/deepseek-chat` | DeepSeek | 64K | No | Cost-effective coding tasks |
|
||||
| `x-ai/grok-3` | xAI | 128K | Yes | Reasoning-heavy tasks |
|
||||
|
||||
<Note>
|
||||
Model availability and pricing change over time. Check [app.cline.bot](https://app.cline.bot) for the latest catalog.
|
||||
</Note>
|
||||
|
||||
## Free Models
|
||||
|
||||
These models are available at no cost. They are a good starting point for experimentation and lightweight tasks:
|
||||
|
||||
| Model ID | Provider | Context Window |
|
||||
|----------|----------|---------------|
|
||||
| `minimax/minimax-m2.5` | MiniMax | 1M |
|
||||
| `kwaipilot/kat-coder-pro` | Kwaipilot | 32K |
|
||||
| `z-ai/glm-5` | Z-AI | 128K |
|
||||
|
||||
Free models have the same API interface as paid models. Just use their model ID:
|
||||
Example:
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.cline.bot/api/v1/chat/completions \
|
||||
@@ -79,7 +54,7 @@ Models with reasoning support include most Claude, Gemini 2.5, and Grok 3 models
|
||||
| Multi-modal (text + images) | `openai/gpt-4o` or `anthropic/claude-sonnet-4-6` |
|
||||
| Complex reasoning | Any model with reasoning support |
|
||||
|
||||
For a deeper comparison of model capabilities and pricing, see the [Model Selection Guide](/core-features/model-selection-guide).
|
||||
For setup and account flow details, see the [Cline provider guide](/getting-started/cline-provider).
|
||||
|
||||
## Image Support
|
||||
|
||||
@@ -108,7 +83,7 @@ Not all models support images. Check the model's `supportsImages` capability bef
|
||||
<Card title="Chat Completions" icon="message" href="/api/chat-completions">
|
||||
Use these models in your API requests.
|
||||
</Card>
|
||||
<Card title="Model Selection Guide" icon="scale-balanced" href="/core-features/model-selection-guide">
|
||||
In-depth comparison for choosing the right model.
|
||||
<Card title="Cline provider" icon="scale-balanced" href="/getting-started/cline-provider">
|
||||
Fastest setup path with built-in authentication and billing.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -24,7 +24,7 @@ Your App → Cline API (api.cline.bot) → Anthropic / OpenAI / Google / etc
|
||||
<Card title="Chat Completions" icon="message" href="/api/chat-completions">
|
||||
Full endpoint reference with request schemas, streaming, and tool calling.
|
||||
</Card>
|
||||
<Card title="SDK Examples" icon="code" href="/api/sdk-examples">
|
||||
<Card title="Code Examples" icon="code" href="/api/sdk-examples">
|
||||
Ready-to-copy examples for Python, Node.js, curl, and the Cline CLI.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
---
|
||||
title: "Cline API Reference"
|
||||
sidebarTitle: "API Reference"
|
||||
description: "Reference for the Cline Chat Completions API, an OpenAI-compatible endpoint for programmatic access."
|
||||
---
|
||||
|
||||
The Cline API provides an OpenAI-compatible Chat Completions endpoint. You can use it from the Cline extension, the CLI, or any HTTP client that speaks the OpenAI format.
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
https://api.cline.bot/api/v1
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
All requests require a Bearer token in the `Authorization` header. You can use either:
|
||||
|
||||
- **API key** created at [app.cline.bot](https://app.cline.bot) (Settings > API Keys)
|
||||
- **Account auth token** (used automatically by the Cline extension and CLI when you sign in)
|
||||
|
||||
```bash
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```
|
||||
|
||||
### Getting an API Key
|
||||
|
||||
<Steps>
|
||||
<Step title="Go to app.cline.bot">
|
||||
Open [app.cline.bot](https://app.cline.bot) and sign in.
|
||||
</Step>
|
||||
<Step title="Open Settings > API Keys">
|
||||
Navigate to **Settings**, then **API Keys**.
|
||||
</Step>
|
||||
<Step title="Create and copy your key">
|
||||
Create a new key and copy it. Store it securely. You will not be able to see it again.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Chat Completions
|
||||
|
||||
Create a chat completion with streaming support. This endpoint follows the [OpenAI Chat Completions](https://platform.openai.com/docs/api-reference/chat/create) format.
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
POST /chat/completions
|
||||
```
|
||||
|
||||
**Headers:**
|
||||
|
||||
| Header | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `Authorization` | Yes | `Bearer YOUR_API_KEY` |
|
||||
| `Content-Type` | Yes | `application/json` |
|
||||
| `HTTP-Referer` | No | Your application URL |
|
||||
| `X-Title` | No | Your application name |
|
||||
|
||||
**Body parameters:**
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `model` | string | Yes | Model ID in `provider/model` format (e.g., `anthropic/claude-sonnet-4-6`) |
|
||||
| `messages` | array | Yes | Array of message objects with `role` and `content` |
|
||||
| `stream` | boolean | No | Enable SSE streaming (default: `true`) |
|
||||
| `tools` | array | No | Tool definitions in OpenAI function calling format |
|
||||
| `temperature` | number | No | Sampling temperature |
|
||||
|
||||
### Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.cline.bot/api/v1/chat/completions \
|
||||
-H "Authorization: Bearer YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
"messages": [
|
||||
{"role": "system", "content": "You are a helpful assistant."},
|
||||
{"role": "user", "content": "Explain what a context window is in 2 sentences."}
|
||||
],
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Response (Streaming)
|
||||
|
||||
When `stream: true`, the response is a series of [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-Sent_Events). Each event contains a JSON chunk:
|
||||
|
||||
```json
|
||||
data: {"id":"gen-abc123","choices":[{"delta":{"content":"A context"},"index":0}],"model":"anthropic/claude-sonnet-4-6"}
|
||||
|
||||
data: {"id":"gen-abc123","choices":[{"delta":{"content":" window is"},"index":0}],"model":"anthropic/claude-sonnet-4-6"}
|
||||
|
||||
data: [DONE]
|
||||
```
|
||||
|
||||
The final chunk includes a `usage` object with token counts and cost:
|
||||
|
||||
```json
|
||||
{
|
||||
"usage": {
|
||||
"prompt_tokens": 25,
|
||||
"completion_tokens": 42,
|
||||
"prompt_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"cost": 0.000315
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Response (Non-Streaming)
|
||||
|
||||
When `stream: false`, the response is a single JSON object:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "gen-abc123",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
"choices": [
|
||||
{
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "A context window is the maximum amount of text..."
|
||||
},
|
||||
"finish_reason": "stop",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 25,
|
||||
"completion_tokens": 42
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Models
|
||||
|
||||
Model IDs use the `provider/model-name` format, the same format used by [OpenRouter](https://openrouter.ai). Some examples:
|
||||
|
||||
| Model ID | Description |
|
||||
|----------|-------------|
|
||||
| `anthropic/claude-sonnet-4-6` | Claude Sonnet 4.6 |
|
||||
| `anthropic/claude-sonnet-4-5` | Claude Sonnet 4.5 |
|
||||
| `google/gemini-2.5-pro` | Gemini 2.5 Pro |
|
||||
| `openai/gpt-4o` | GPT-4o |
|
||||
|
||||
### Free Models
|
||||
|
||||
The following models are available at no cost:
|
||||
|
||||
| Model ID | Provider |
|
||||
|----------|----------|
|
||||
| `minimax/minimax-m2.5` | MiniMax |
|
||||
| `kwaipilot/kat-coder-pro` | Kwaipilot |
|
||||
| `z-ai/glm-5` | Z-AI |
|
||||
|
||||
<Note>
|
||||
Model availability and pricing may change. Check [app.cline.bot](https://app.cline.bot) for the latest list.
|
||||
</Note>
|
||||
|
||||
## Error Handling
|
||||
|
||||
Errors follow the OpenAI error format:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": 401,
|
||||
"message": "Invalid API key",
|
||||
"metadata": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Common error codes:
|
||||
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| `401` | Invalid or missing API key |
|
||||
| `402` | Insufficient credits |
|
||||
| `429` | Rate limit exceeded |
|
||||
| `500` | Server error |
|
||||
| `error` (finish_reason) | Mid-stream error from the upstream model provider |
|
||||
|
||||
## Using with Cline
|
||||
|
||||
The easiest way to use the Cline API is through the Cline extension or CLI, which handle authentication and streaming for you.
|
||||
|
||||
### VS Code / JetBrains
|
||||
|
||||
Select **Cline** as your provider in the model picker dropdown. Sign in with your Cline account and your API key is managed automatically.
|
||||
|
||||
### Cline CLI
|
||||
|
||||
Configure the CLI with your API key in one command:
|
||||
|
||||
```bash
|
||||
cline auth -p cline -k "YOUR_API_KEY" -m anthropic/claude-sonnet-4-6
|
||||
```
|
||||
|
||||
Then run tasks normally:
|
||||
|
||||
```bash
|
||||
cline "Write a one-line hello world in Python."
|
||||
```
|
||||
|
||||
See the [CLI Reference](/cline-cli/cli-reference) for all available commands and options.
|
||||
|
||||
## Using with Other Tools
|
||||
|
||||
Because the Cline API is OpenAI-compatible, you can use it with any library or tool that supports custom OpenAI endpoints.
|
||||
|
||||
### Python (OpenAI SDK)
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
|
||||
client = OpenAI(
|
||||
base_url="https://api.cline.bot/api/v1",
|
||||
api_key="YOUR_API_KEY",
|
||||
)
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model="anthropic/claude-sonnet-4-6",
|
||||
messages=[{"role": "user", "content": "Hello!"}],
|
||||
)
|
||||
print(response.choices[0].message.content)
|
||||
```
|
||||
|
||||
### Node.js (OpenAI SDK)
|
||||
|
||||
```typescript
|
||||
import OpenAI from "openai"
|
||||
|
||||
const client = new OpenAI({
|
||||
baseURL: "https://api.cline.bot/api/v1",
|
||||
apiKey: "YOUR_API_KEY",
|
||||
})
|
||||
|
||||
const response = await client.chat.completions.create({
|
||||
model: "anthropic/claude-sonnet-4-6",
|
||||
messages: [{ role: "user", content: "Hello!" }],
|
||||
})
|
||||
console.log(response.choices[0].message.content)
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="CLI Reference" icon="terminal" href="/cline-cli/cli-reference">
|
||||
Full command reference for the Cline CLI, including auth setup.
|
||||
</Card>
|
||||
<Card title="Enterprise API" icon="building" href="/enterprise-solutions/api-reference">
|
||||
Admin endpoints for user management, organizations, billing, and API keys.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "SDK Examples"
|
||||
sidebarTitle: "SDK Examples"
|
||||
title: "Code Examples"
|
||||
sidebarTitle: "Code Examples"
|
||||
description: "Use the Cline API from Python, Node.js, curl, the Cline CLI, and the VS Code extension."
|
||||
---
|
||||
|
||||
@@ -214,7 +214,7 @@ console.log(data.choices[0].message.content)
|
||||
|
||||
## Cline CLI
|
||||
|
||||
The [Cline CLI](/cline-cli/cli-reference) is the fastest way to use the Cline API from your terminal. It handles authentication, streaming, and tool execution for you.
|
||||
The [Cline CLI](/cli/cli-reference) is the fastest way to use the Cline API from your terminal. It handles authentication, streaming, and tool execution for you.
|
||||
|
||||
### Setup
|
||||
|
||||
@@ -242,7 +242,7 @@ cline -m google/gemini-2.5-pro "Analyze this codebase."
|
||||
cline -y "Run tests and fix failures."
|
||||
```
|
||||
|
||||
See the [CLI Reference](/cline-cli/cli-reference) for all commands and options.
|
||||
See the [CLI Reference](/cli/cli-reference) for all commands and options.
|
||||
|
||||
## VS Code / JetBrains
|
||||
|
||||
@@ -269,7 +269,7 @@ For setup instructions, see [Installing Cline](/getting-started/installing-cline
|
||||
<Card title="Models" icon="brain" href="/api/models">
|
||||
Browse available models.
|
||||
</Card>
|
||||
<Card title="CLI Reference" icon="terminal" href="/cline-cli/cli-reference">
|
||||
<Card title="CLI Reference" icon="terminal" href="/cli/cli-reference">
|
||||
Complete Cline CLI command reference.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -198,11 +198,11 @@ If Cline can't access files or run commands:
|
||||
## Learn More
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="CLI Overview" icon="terminal" href="/cline-cli/overview">
|
||||
<Card title="CLI Overview" icon="terminal" href="/usage/cli-overview">
|
||||
Learn about Cline CLI's core capabilities and use cases.
|
||||
</Card>
|
||||
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
<Card title="Headless Mode" icon="robot" href="/usage/cli-overview#headless-mode">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "Agent Teams"
|
||||
sidebarTitle: "Agent Teams"
|
||||
description: "Coordinate multiple agents working together on complex tasks from the CLI."
|
||||
---
|
||||
<Warning>
|
||||
This feature currently only applies to Cline SDK, CLI, and Kanban. This feature is not applicable on VSCode and JetBrains Extension for now.
|
||||
</Warning>
|
||||
|
||||
|
||||
Agent teams let you break complex work across multiple agents that coordinate through a shared task board. One agent acts as the coordinator, delegating subtasks to specialist agents.
|
||||
|
||||
## Starting a Team
|
||||
|
||||
```bash
|
||||
cline --team-name auth-sprint "Plan and implement user authentication with tests"
|
||||
```
|
||||
|
||||
The `--team-name` flag enables team mode. The coordinator agent gets additional tools for spawning teammates and delegating tasks.
|
||||
|
||||
## Resuming Team Work
|
||||
|
||||
Team state persists across sessions. Resume where you left off:
|
||||
|
||||
```bash
|
||||
cline --team-name auth-sprint "Continue with incomplete tasks"
|
||||
```
|
||||
|
||||
## Interactive Mode
|
||||
|
||||
In interactive mode, use the `/team` slash command:
|
||||
|
||||
```
|
||||
/team Plan and implement a REST API with tests
|
||||
```
|
||||
|
||||
## Team State
|
||||
|
||||
Team state is stored at `~/.cline/data/teams/[team-name]/` and includes:
|
||||
|
||||
- Task board with current tasks and status
|
||||
- Inter-agent mailbox
|
||||
- Mission log with activity history
|
||||
|
||||
## Disabling Teams
|
||||
|
||||
Teams are enabled by default. Disable them with:
|
||||
|
||||
```bash
|
||||
cline --no-teams "your prompt"
|
||||
```
|
||||
|
||||
## Sub-Agents
|
||||
|
||||
For simpler delegation within a single session (no persistent state), use [sub-agents](/features/subagents). Sub-agents run in parallel for read-only research and return focused reports to the main agent.
|
||||
|
||||
See the [SDK Multi-Agent Teams guide](/sdk/guides/multi-agent-teams) for the programmatic API.
|
||||
@@ -0,0 +1,305 @@
|
||||
---
|
||||
title: "CLI Reference"
|
||||
description: "Complete command reference for Cline CLI including all commands, flags, and configuration options."
|
||||
---
|
||||
|
||||
```bash
|
||||
cline --help # Show all commands
|
||||
cline <command> --help # Show help for a specific command
|
||||
```
|
||||
|
||||
## Synopsis
|
||||
|
||||
```bash
|
||||
cline [options] [command] [prompt]
|
||||
```
|
||||
|
||||
## Help Menu (Source of Truth)
|
||||
|
||||
```text
|
||||
Usage: cline [options] [command] [prompt]
|
||||
|
||||
Cline CLI - AI coding assistant in your terminal
|
||||
|
||||
Arguments:
|
||||
prompt Your prompt. Default to start in act mode with auto-approve enabled.
|
||||
|
||||
Options:
|
||||
-V, --version Output the version number
|
||||
-p, --plan Run in plan mode
|
||||
--json Output messages as JSON instead of styled text
|
||||
--auto-approve <boolean> Set tool auto-approval for all tools (default: true)
|
||||
-t, --timeout <seconds> Optional timeout in seconds (default: 0 for no timeout)
|
||||
-m, --model <model-id> Model to use for the session with the selected provider
|
||||
-v, --verbose Show verbose output
|
||||
-c, --cwd <path> Working directory
|
||||
--config <path> Configuration directory (default: ~/.cline/data/settings)
|
||||
--data-dir <path> Use isolated local state at this directory path (default: ~/.cline)
|
||||
--thinking <level> Set reasoning effort level between none|low|medium|high|xhigh (default: medium)
|
||||
--retries <count> Maximum consecutive mistakes (retries) before halting
|
||||
--hooks-dir <path> Directory path to additional hooks for runtime hook injection (default: ~/.cline/hooks)
|
||||
--acp Run in Agent Client Protocol (ACP) mode for editor integration
|
||||
-i, --tui Open the terminal user interface (TUI) for interactive sessions
|
||||
--id <session-id> Resume an existing session by ID
|
||||
-k, --key <api-key> API key override for this run
|
||||
-P, --provider <id> Provider id (default: cline)
|
||||
-s, --system <system-prompt> Override the default system prompt
|
||||
-z, --zen Start a session that runs in the background hub
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
auth [options] [provider] Authenticate a provider and configure what model is used
|
||||
config [options] Show current configuration
|
||||
connect [options] [adapter] Connect to an editor or IDE adapter
|
||||
mcp Manage MCP servers
|
||||
dev Developer tools and utilities
|
||||
doctor Diagnose and fix configuration issues
|
||||
history|h [options] List session history or manage saved sessions
|
||||
hook Handle a hook payload from stdin
|
||||
plugin Manage Cline Plugins
|
||||
schedule Manage scheduled tasks
|
||||
hub Manage the local hub daemon
|
||||
update [options] Check for updates and install if available
|
||||
version Show Cline CLI version number
|
||||
kanban Launch the kanban app and exit
|
||||
```
|
||||
|
||||
## Global Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-V, --version` | Output the version number |
|
||||
| `-p, --plan` | Run in plan mode |
|
||||
| `--json` | Output messages as JSON instead of styled text |
|
||||
| `--auto-approve <boolean>` | Set tool auto-approval for all tools (default: `true`) |
|
||||
| `-t, --timeout <seconds>` | Optional timeout in seconds (default: `0` for no timeout) |
|
||||
| `-m, --model <model-id>` | Model to use for the session with the selected provider |
|
||||
| `-v, --verbose` | Show verbose output |
|
||||
| `-c, --cwd <path>` | Working directory |
|
||||
| `--config <path>` | Configuration directory (default: `~/.cline/data/settings`) |
|
||||
| `--data-dir <path>` | Use isolated local state at this directory path (default: `~/.cline`) |
|
||||
| `--thinking <level>` | Set reasoning effort: `none\|low\|medium\|high\|xhigh` (default `medium`) |
|
||||
| `--retries <count>` | Maximum consecutive mistakes (retries) before halting |
|
||||
| `--hooks-dir <path>` | Directory path to additional hooks for runtime hook injection (default: `~/.cline/hooks`) |
|
||||
| `--acp` | Run in Agent Client Protocol (ACP) mode for editor integration |
|
||||
| `-i, --tui` | Open the terminal user interface (TUI) for interactive sessions |
|
||||
| `--id <session-id>` | Resume an existing session by ID |
|
||||
| `-k, --key <api-key>` | API key override for this run |
|
||||
| `-P, --provider <id>` | Provider id (default: `cline`) |
|
||||
| `-s, --system <system-prompt>` | Override the default system prompt |
|
||||
| `-z, --zen` | Start a session that runs in the background hub |
|
||||
| `-h, --help` | Display help for command |
|
||||
|
||||
## Commands
|
||||
|
||||
### `cline` (default)
|
||||
|
||||
Start a task or enter interactive mode.
|
||||
|
||||
```bash
|
||||
cline
|
||||
cline "your prompt here"
|
||||
cline "Run tests and fix failures"
|
||||
echo "prompt" | cline
|
||||
```
|
||||
|
||||
### `auth [options] [provider]`
|
||||
|
||||
Configure authentication with an AI provider.
|
||||
|
||||
```bash
|
||||
cline auth
|
||||
```
|
||||
|
||||
### `config [options]`
|
||||
|
||||
Show current configuration.
|
||||
|
||||
```bash
|
||||
cline config
|
||||
```
|
||||
|
||||
### `connect [options] [adapter]`
|
||||
|
||||
Connect to messaging platforms. See [Connectors](/cli/connectors).
|
||||
|
||||
```bash
|
||||
cline connect
|
||||
cline connect [adapter]
|
||||
```
|
||||
|
||||
### `mcp`
|
||||
|
||||
Manage MCP servers. See [MCP](/mcp/mcp-overview).
|
||||
|
||||
```bash
|
||||
cline mcp
|
||||
```
|
||||
|
||||
### `dev`
|
||||
|
||||
Developer tools and utilities.
|
||||
|
||||
```bash
|
||||
cline dev
|
||||
```
|
||||
|
||||
### `doctor`
|
||||
|
||||
Diagnose and fix configuration issues.
|
||||
|
||||
```bash
|
||||
cline doctor
|
||||
```
|
||||
|
||||
### `history|h [options]`
|
||||
|
||||
List session history or manage saved sessions.
|
||||
|
||||
```bash
|
||||
cline history
|
||||
cline h
|
||||
```
|
||||
|
||||
### `hook`
|
||||
|
||||
Handle a hook payload from stdin.
|
||||
|
||||
```bash
|
||||
cat payload.json | cline hook
|
||||
```
|
||||
|
||||
### `plugin`
|
||||
|
||||
Manage Cline plugins. Install plugins from npm, git repositories, or local paths. See [Plugins](/customization/plugins) for full details and the plugin manifest format.
|
||||
|
||||
```bash
|
||||
cline plugin install <source> # Install a plugin
|
||||
cline plugin i <source> # Shorthand alias
|
||||
```
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--npm` | Treat source as an npm package |
|
||||
| `--git` | Treat source as a git repository |
|
||||
| `--force` | Replace an existing install for the same source |
|
||||
| `--json` | Output result as JSON |
|
||||
| `--cwd <path>` | Install to `<path>/.cline/plugins` instead of the global directory |
|
||||
|
||||
Try it with the [TypeScript Navigation Plugin](https://github.com/cline/typescript-lsp-plugin):
|
||||
|
||||
```bash
|
||||
cline plugin install https://github.com/cline/typescript-lsp-plugin.git
|
||||
```
|
||||
|
||||
### `schedule`
|
||||
|
||||
Manage scheduled agents. See [Scheduling](/cli/scheduling).
|
||||
|
||||
```bash
|
||||
cline schedule
|
||||
```
|
||||
|
||||
### `hub`
|
||||
|
||||
Manage the local hub daemon.
|
||||
|
||||
```bash
|
||||
cline hub
|
||||
```
|
||||
|
||||
### `update [options]`
|
||||
|
||||
Check for updates and install if available.
|
||||
|
||||
```bash
|
||||
cline update
|
||||
```
|
||||
|
||||
### `version`
|
||||
|
||||
Show Cline CLI version number.
|
||||
|
||||
```bash
|
||||
cline version
|
||||
cline -V
|
||||
```
|
||||
|
||||
### `kanban`
|
||||
|
||||
Launch the kanban app and exit.
|
||||
|
||||
```bash
|
||||
cline kanban
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `CLINE_DATA_DIR` | Custom configuration directory (replaces `~/.cline/data/`) |
|
||||
| `CLINE_HUB_ADDRESS` | Override hub address (default: `127.0.0.1:25463`) |
|
||||
| `CLINE_SESSION_BACKEND_MODE` | Force backend mode (`local`, `hub`, `remote`, `auto`) |
|
||||
| `CLINE_SANDBOX_DATA_DIR` | Sandbox session storage directory |
|
||||
| `CLINE_SANDBOX` | Enable sandbox mode |
|
||||
| `CLINE_HOOKS_DIR` | Additional hooks directory |
|
||||
| `CLINE_BUILD_ENV` | Set to `development` for debug features |
|
||||
| `CLINE_DEBUG_PORT_BASE` | Base port for Node.js inspector |
|
||||
| `CLINE_COMMAND_PERMISSIONS` | JSON policy restricting shell commands (see below) |
|
||||
|
||||
### CLINE_COMMAND_PERMISSIONS
|
||||
|
||||
Restrict which shell commands the agent can execute:
|
||||
|
||||
```bash
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *"], "deny": ["rm -rf *", "sudo *"]}'
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `allow` | `string[]` | Glob patterns for allowed commands. If set, only matching commands are permitted. |
|
||||
| `deny` | `string[]` | Glob patterns for denied commands. Deny rules always take precedence. |
|
||||
| `allowRedirects` | `boolean` | Whether to allow shell redirects (`>`, `>>`, `<`). Default: `false`. |
|
||||
|
||||
## JSON Output Format
|
||||
|
||||
When using `--json`, each message is a JSON object on its own line:
|
||||
|
||||
```json
|
||||
{"type": "say", "text": "I'll create the file now.", "ts": 1760501486669, "say": "text"}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `type` | `"ask"` or `"say"` | Message category |
|
||||
| `text` | `string` | Message content |
|
||||
| `ts` | `number` | Unix timestamp in milliseconds |
|
||||
| `say` | `string` | Subtype when `type` is `"say"` |
|
||||
| `ask` | `string` | Subtype when `type` is `"ask"` |
|
||||
| `reasoning` | `string` | Model reasoning (if available) |
|
||||
| `partial` | `boolean` | `true` while streaming |
|
||||
|
||||
## Configuration Files
|
||||
|
||||
```
|
||||
~/.cline/
|
||||
data/
|
||||
settings/
|
||||
providers.json # API keys and provider config
|
||||
rules/ # Global rules
|
||||
skills/ # Global skills
|
||||
teams/ # Team state
|
||||
sessions/ # Session database (SQLite)
|
||||
logs/
|
||||
hub-daemon.log # Hub logs
|
||||
plugins/ # Global plugins
|
||||
_installed/ # Managed by `cline plugin install`
|
||||
|
||||
.cline/ # Project root
|
||||
rules/ # Project rules
|
||||
skills/ # Project skills
|
||||
hooks/ # Lifecycle hooks
|
||||
plugins/ # Project plugins
|
||||
mcp.json # MCP server config
|
||||
agents.yaml # Agent definitions
|
||||
```
|
||||
@@ -0,0 +1,156 @@
|
||||
---
|
||||
title: "Connectors"
|
||||
sidebarTitle: "Connectors"
|
||||
description: "Connect the CLI to Telegram, Slack, Discord, Google Chat, WhatsApp, etc."
|
||||
---
|
||||
<Warning>
|
||||
This feature currently only applies to Cline CLI.
|
||||
</Warning>
|
||||
|
||||
Connectors let you chat with your agent from messaging platforms. Each incoming message creates or continues an agent session, and the agent's response is sent back to the conversation.
|
||||
|
||||
## Setup Wizard
|
||||
|
||||
Run `cline connect` to open an interactive wizard that guides you through platform selection, credential entry, security configuration, and advanced options (provider, model, system prompt, agent mode).
|
||||
|
||||
```bash
|
||||
cline connect
|
||||
```
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
| Platform | Direct Command | Required Credentials |
|
||||
|----------|---------------|---------------------|
|
||||
| Telegram | `cline connect telegram` | Bot username, bot token |
|
||||
| Slack | `cline connect slack` | Bot token, signing secret, base URL |
|
||||
| Discord | `cline connect discord` | Application ID, bot token, public key, base URL |
|
||||
| Google Chat | `cline connect gchat` | Service account credentials JSON, base URL |
|
||||
| WhatsApp | `cline connect whatsapp` | Phone number ID, access token, app secret, verify token, base URL |
|
||||
| Linear | `cline connect linear` | API key, webhook signing secret, base URL |
|
||||
|
||||
## Telegram
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a Telegram bot">
|
||||
Open Telegram and start a chat with [@BotFather](https://t.me/BotFather). Send `/newbot` and follow the prompts:
|
||||
|
||||
1. Enter a display name (e.g., "Cline")
|
||||
2. Enter a username ending in `bot` (e.g., `cline_myname_bot`). Must be unique across Telegram.
|
||||
3. BotFather responds with your bot token (looks like `7123456789:AAH...`)
|
||||
</Step>
|
||||
|
||||
<Step title="Start the connector">
|
||||
```bash
|
||||
cline connect telegram -m <BOT-USERNAME> -k <BOT-TOKEN>
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Chat with your bot">
|
||||
Open Telegram, search for your bot's username, and send a message. The agent processes it and replies in the chat.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Security
|
||||
|
||||
By default, anyone who finds your bot can message it and it will execute tasks on your machine. Lock it down with the `--hook-command` flag.
|
||||
|
||||
<Steps>
|
||||
<Step title="Get your Telegram user ID">
|
||||
Message [@userinfobot](https://t.me/userinfobot) on Telegram. It replies with your user ID immediately.
|
||||
</Step>
|
||||
|
||||
<Step title="Start with access control">
|
||||
Replace `12345` with your actual Telegram user ID:
|
||||
|
||||
```bash
|
||||
cline connect telegram -m <BOT-USERNAME> -k <BOT-TOKEN> \
|
||||
--hook-command 'jq -r ".payload.actor.participantKey" | grep -q "telegram:id:12345" && echo "{\"action\":\"allow\"}" || echo "{\"action\":\"deny\",\"message\":\"unauthorized\"}"'
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
The `--hook-command` receives each incoming message with sender info via stdin. Your script returns `{"action": "allow"}` or `{"action": "deny", "message": "reason"}`. Without `--hook-command`, everything is auto-approved.
|
||||
|
||||
## Slack
|
||||
|
||||
Requires a bot token, signing secret, and public base URL.
|
||||
|
||||
```bash
|
||||
cline connect slack --token <BOT-TOKEN> --signing-secret <SECRET> --base-url <URL>
|
||||
```
|
||||
|
||||
Each Slack thread maps to an agent session, so the agent maintains conversation context within a thread.
|
||||
|
||||
## Discord
|
||||
|
||||
Requires an application ID, bot token, public key, and public base URL.
|
||||
|
||||
```bash
|
||||
cline connect discord --app-id <ID> --token <TOKEN> --public-key <KEY> --base-url <URL>
|
||||
```
|
||||
|
||||
## Google Chat
|
||||
|
||||
Requires a service account credentials JSON file and public base URL.
|
||||
|
||||
```bash
|
||||
cline connect gchat --credentials <JSON> --base-url <URL>
|
||||
```
|
||||
|
||||
## WhatsApp
|
||||
|
||||
Requires a phone number ID, access token, app secret, webhook verify token, and public base URL.
|
||||
|
||||
```bash
|
||||
cline connect whatsapp --phone-id <ID> --token <TOKEN> --app-secret <SECRET> --base-url <URL>
|
||||
```
|
||||
|
||||
## Linear
|
||||
|
||||
Requires an API key, webhook signing secret, and public base URL.
|
||||
|
||||
```bash
|
||||
cline connect linear --api-key <KEY> --signing-secret <SECRET> --base-url <URL>
|
||||
```
|
||||
|
||||
## Managing Connectors
|
||||
|
||||
```bash
|
||||
# Stop all connectors
|
||||
cline connect --stop
|
||||
|
||||
# Stop a specific connector
|
||||
cline connect telegram --stop
|
||||
```
|
||||
|
||||
## Hook Command Protocol
|
||||
|
||||
The `--hook-command` pattern works across all connectors. The script receives a JSON payload via stdin:
|
||||
|
||||
```json
|
||||
{
|
||||
"payload": {
|
||||
"actor": {
|
||||
"participantKey": "telegram:id:12345",
|
||||
"displayName": "User Name"
|
||||
},
|
||||
"message": "The incoming message text"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Return `{"action": "allow"}` or `{"action": "deny", "message": "reason"}`.
|
||||
|
||||
## Running Multiple Connectors
|
||||
|
||||
Multiple connectors can run simultaneously. They all share the same hub:
|
||||
|
||||
```bash
|
||||
# Terminal 1
|
||||
cline connect telegram -m my_bot -k $TELEGRAM_TOKEN
|
||||
|
||||
# Terminal 2
|
||||
cline connect slack --token $SLACK_TOKEN --signing-secret $SECRET --base-url $URL
|
||||
```
|
||||
|
||||
Connectors require the hub. Start it with `cline hub start` if it doesn't auto-start.
|
||||
+8
-11
@@ -7,7 +7,7 @@ Automate GitHub issue analysis with AI. Mention `@cline` in any issue comment to
|
||||
|
||||
|
||||
<Note>
|
||||
**New to Cline CLI?** This sample assumes you understand Cline CLI basics and have completed the [Installation Guide](https://docs.cline.bot/cline-cli/installation). If you're new to Cline CLI, we recommend starting with the [GitHub RCA sample](./github-issue-rca) first, as it's simpler and will help you understand the fundamentals before setting up GitHub Actions.
|
||||
**New to Cline CLI?** This sample assumes you understand Cline CLI basics and have completed the [Installation Guide](https://docs.cline.bot/getting-started/installing-cline). If you're new to Cline CLI, we recommend starting with the [GitHub RCA sample](./github-issue-rca) first, as it's simpler and will help you understand the fundamentals before setting up GitHub Actions.
|
||||
</Note>
|
||||
|
||||
## The Workflow
|
||||
@@ -32,7 +32,7 @@ Let's configure your repository.
|
||||
|
||||
Before you begin, you'll need:
|
||||
|
||||
- **Cline CLI knowledge** - Completed the [Installation Guide](https://docs.cline.bot/cline-cli/installation) and understand basic usage
|
||||
- **Cline CLI knowledge** - Completed the [Installation Guide](https://docs.cline.bot/getting-started/installing-cline) and understand basic usage
|
||||
- **GitHub repository** - With admin access to configure Actions and secrets
|
||||
- **GitHub Actions familiarity** - Basic understanding of workflows and CI/CD
|
||||
- **API provider account** - OpenRouter, Anthropic, or similar with API key
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
|
||||
- name: Install Cline CLI
|
||||
if: steps.detect.outputs.hit == 'true'
|
||||
run: npm install -g cline
|
||||
run: npm install -g @cline/cli
|
||||
|
||||
- name: Configure Cline Authentication
|
||||
if: steps.detect.outputs.hit == 'true'
|
||||
@@ -120,7 +120,6 @@ jobs:
|
||||
env:
|
||||
ISSUE_URL: ${{ steps.detect.outputs.issue_url }}
|
||||
COMMENT: ${{ steps.detect.outputs.comment_body }}
|
||||
CLINE_ADDRESS: ${{ env.CLINE_ADDRESS }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
@@ -231,10 +230,9 @@ nano git-scripts/analyze-issue.sh # or use vim, code, etc.
|
||||
# Analyze a GitHub issue using Cline CLI
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <github-issue-url> [prompt] [address]"
|
||||
echo "Usage: $0 <github-issue-url> [prompt]"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123 'What is the root cause of this issue?'"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123 'What is the root cause of this issue?'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -243,9 +241,8 @@ ISSUE_URL="$1"
|
||||
PROMPT="${2:-What is the root cause of this issue?}"
|
||||
|
||||
# Ask Cline for its analysis, showing only the summary
|
||||
cline -y "$PROMPT: $ISSUE_URL" --mode act -F json | \
|
||||
sed -n '/^{/,$p' | \
|
||||
jq -r 'select(.say == "completion_result") | .text' | \
|
||||
cline --auto-approve true --json "$PROMPT: $ISSUE_URL" | \
|
||||
jq -r 'select(.type == "agent_event" and .event.type == "done") | .event.text' | \
|
||||
sed 's/\\n/\n/g'
|
||||
```
|
||||
|
||||
@@ -283,7 +280,7 @@ GitHub Actions will:
|
||||
1. Detect the `@cline` mention
|
||||
2. Start a Cline CLI instance
|
||||
3. Download the analysis script
|
||||
4. Analyze the issue using act mode with yolo (fully autonomous)
|
||||
4. Analyze the issue using Act mode with auto-approval enabled
|
||||
5. Post Cline's analysis as a new comment
|
||||
|
||||
**Note**: The workflow only triggers on issue comments, not pull request
|
||||
@@ -296,7 +293,7 @@ The workflow (`cline-responder.yml`):
|
||||
1. **Triggers** on issue comments (created or edited)
|
||||
2. **Detects** `@cline` mentions (case-insensitive)
|
||||
3. **Installs** Cline CLI globally using npm
|
||||
4. **Configures** authentication using `cline config set open-router-api-key=...`
|
||||
4. **Configures** authentication using `cline auth --provider openrouter --apikey ...`
|
||||
6. **Downloads** the reusable `analyze-issue.sh` script from the
|
||||
`github-issue-rca` sample
|
||||
7. **Runs** analysis in Cline CLI
|
||||
+21
-62
@@ -6,7 +6,7 @@ description: "Automated GitHub issue analysis using Cline CLI to identify root c
|
||||
Automated GitHub issue analysis using Cline CLI. This script uses Cline's autonomous AI capabilities to fetch, analyze, and identify root causes of GitHub issues, outputting clean, parseable results that can be easily integrated into your development workflows.
|
||||
|
||||
<Note>
|
||||
**New to Cline CLI?** This sample assumes you have already completed the [Installation Guide](https://docs.cline.bot/cline-cli/installation) and authenticated with `cline auth`. If you haven't set up Cline CLI yet, please start there first.
|
||||
**New to Cline CLI?** This sample assumes you have already completed the [Installation Guide](https://docs.cline.bot/getting-started/installing-cline) and authenticated with `cline auth`. If you haven't set up Cline CLI yet, please start there first.
|
||||
</Note>
|
||||
|
||||
<Frame>
|
||||
@@ -17,7 +17,7 @@ Automated GitHub issue analysis using Cline CLI. This script uses Cline's autono
|
||||
|
||||
This sample assumes you have already:
|
||||
|
||||
- **Cline CLI** installed and authenticated ([Installation Guide](https://docs.cline.bot/cline-cli/installation))
|
||||
- **Cline CLI** installed and authenticated ([Installation Guide](https://docs.cline.bot/getting-started/installing-cline))
|
||||
- **At least one AI model provider** configured (e.g., OpenRouter, Anthropic, OpenAI)
|
||||
- **Basic familiarity** with Cline CLI commands
|
||||
|
||||
@@ -80,24 +80,18 @@ curl -O https://raw.githubusercontent.com/cline/cline/main/src/samples/cli/githu
|
||||
# Analyze a GitHub issue using Cline CLI
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <github-issue-url> [prompt] [address]"
|
||||
echo "Usage: $0 <github-issue-url> [prompt]"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123 'What is the root cause of this issue?'"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123 'What is the root cause of this issue?' 127.0.0.1:46529"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Gather the args
|
||||
ISSUE_URL="$1"
|
||||
PROMPT="${2:-What is the root cause of this issue?}"
|
||||
if [ -n "$3" ]; then
|
||||
ADDRESS="--address $3"
|
||||
fi
|
||||
|
||||
# Ask Cline for its analysis, showing only the summary
|
||||
cline -y "$PROMPT: $ISSUE_URL" --mode act $ADDRESS -F json | \
|
||||
sed -n '/^{/,$p' | \
|
||||
jq -r 'select(.say == "completion_result") | .text' | \
|
||||
cline --auto-approve true --json "$PROMPT: $ISSUE_URL" | \
|
||||
jq -r 'select(.type == "agent_event" and .event.type == "done") | .event.text' | \
|
||||
sed 's/\\n/\n/g'
|
||||
```
|
||||
|
||||
@@ -133,23 +127,6 @@ Ask specific questions about the issue:
|
||||
./analyze-issue.sh https://github.com/owner/repo/issues/456 "What is the security impact?"
|
||||
```
|
||||
|
||||
### Using Specific Cline Instance
|
||||
|
||||
Target a particular Cline instance by address:
|
||||
|
||||
```bash
|
||||
./analyze-issue.sh https://github.com/owner/repo/issues/123 \
|
||||
"What is the root cause of this issue?" \
|
||||
127.0.0.1:46529
|
||||
```
|
||||
|
||||
<Warning>
|
||||
This is useful when:
|
||||
- Running multiple Cline instances
|
||||
- Using a remote Cline server
|
||||
- Testing with specific configurations
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
The script will automatically handle everything: fetching the issue, analyzing it with Cline, and displaying the results. The analysis typically takes 30-60 seconds depending on the issue complexity.
|
||||
</Note>
|
||||
@@ -164,10 +141,9 @@ The script validates input and provides usage instructions:
|
||||
|
||||
```bash
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <github-issue-url> [prompt] [address]"
|
||||
echo "Usage: $0 <github-issue-url> [prompt]"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123 'What is the root cause?'"
|
||||
echo "Example: $0 https://github.com/owner/repo/issues/123 'Analyze security impact' 127.0.0.1:46529"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
@@ -176,7 +152,6 @@ fi
|
||||
- Validates required GitHub issue URL
|
||||
- Shows clear usage examples
|
||||
- Supports optional custom prompt
|
||||
- Supports optional Cline instance address
|
||||
|
||||
### Argument Parsing
|
||||
|
||||
@@ -186,15 +161,12 @@ The script extracts and sets up the arguments:
|
||||
# Gather the args
|
||||
ISSUE_URL="$1"
|
||||
PROMPT="${2:-What is the root cause of this issue?}"
|
||||
if [ -n "$3" ]; then
|
||||
ADDRESS="--address $3"
|
||||
fi
|
||||
```
|
||||
|
||||
**Explanation:**
|
||||
- `ISSUE_URL="$1"` - First argument is always the issue URL
|
||||
- `PROMPT="${2:-...}"` - Second argument is optional, defaults to root cause analysis
|
||||
- `ADDRESS` - Third argument is optional, only set if provided
|
||||
- The SDK CLI runs the task directly, so no address flag is required.
|
||||
|
||||
### The Core Analysis Pipeline
|
||||
|
||||
@@ -202,39 +174,26 @@ This is where the magic happens:
|
||||
|
||||
```bash
|
||||
# Ask Cline for its analysis, showing only the summary
|
||||
cline -y "$PROMPT: $ISSUE_URL" --mode act $ADDRESS -F json | \
|
||||
sed -n '/^{/,$p' | \
|
||||
jq -r 'select(.say == "completion_result") | .text' | \
|
||||
cline --auto-approve true --json "$PROMPT: $ISSUE_URL" | \
|
||||
jq -r 'select(.type == "agent_event" and .event.type == "done") | .event.text' | \
|
||||
sed 's/\\n/\n/g'
|
||||
```
|
||||
|
||||
<Accordion title="Pipeline Breakdown: Understanding Each Component">
|
||||
|
||||
**1. `cline -y "$PROMPT: $ISSUE_URL"`**
|
||||
- `-y` enables yolo mode (no user interaction)
|
||||
**1. `cline --auto-approve true --json "$PROMPT: $ISSUE_URL"`**
|
||||
- `cline` is the Cline CLI binary
|
||||
- Act mode is the default for prompt runs
|
||||
- `--auto-approve true` allows tool use without interactive prompts
|
||||
- `--json` emits newline-delimited JSON for parsing
|
||||
- Constructs prompt with issue URL
|
||||
|
||||
**2. `--mode act`**
|
||||
- Enables act mode for active investigation
|
||||
- Allows Cline to use tools (read files, run commands, etc.)
|
||||
|
||||
**3. `$ADDRESS`**
|
||||
- Optional address flag for specific instance
|
||||
- Expands to `--address <ip:port>` if set
|
||||
|
||||
**4. `-F json`**
|
||||
- Outputs in JSON format for parsing
|
||||
|
||||
**5. `sed -n '/^{/,$p'`**
|
||||
- Extracts JSON from output
|
||||
- Skips any non-JSON prefix lines
|
||||
|
||||
**6. `jq -r 'select(.say == "completion_result") | .text'`**
|
||||
- Filters for completion result messages
|
||||
- Extracts the text field
|
||||
**2. `jq -r 'select(.type == "agent_event" and .event.type == "done") | .event.text'`**
|
||||
- Filters for the final agent `done` event
|
||||
- Extracts the final text field
|
||||
- `-r` outputs raw strings (no JSON quotes)
|
||||
|
||||
**7. `sed 's/\\n/\n/g'`**
|
||||
**3. `sed 's/\\n/\n/g'`**
|
||||
- Converts escaped newlines to actual newlines
|
||||
- Makes output readable
|
||||
|
||||
@@ -376,6 +335,6 @@ This pattern can be adapted for many other automation scenarios, from pull reque
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [CLI Installation Guide](https://docs.cline.bot/cline-cli/installation)
|
||||
- [CLI Reference Documentation](https://docs.cline.bot/cline-cli/cli-reference)
|
||||
- [Headless Mode](https://docs.cline.bot/cline-cli/three-core-flows)
|
||||
- [CLI Installation Guide](https://docs.cline.bot/getting-started/installing-cline)
|
||||
- [CLI Reference Documentation](https://docs.cline.bot/cli/cli-reference)
|
||||
- [Headless Mode](https://docs.cline.bot/usage/cli-overview#headless-mode)
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Cline CLI
|
||||
run: npm install -g cline
|
||||
run: npm install -g @cline/cli
|
||||
|
||||
- name: Configure Cline Authentication
|
||||
# Replace 'anthropic' with your provider of choice (openai, openrouter, etc.)
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
]
|
||||
}
|
||||
run: |
|
||||
cline --yolo 'You are a GitHub PR reviewer for this repository. Your goal is to give the PR author helpful feedback and give maintainers the context they need to review efficiently.
|
||||
cline --auto-approve true 'You are a GitHub PR reviewer for this repository. Your goal is to give the PR author helpful feedback and give maintainers the context they need to review efficiently.
|
||||
|
||||
PR: #'"${PR_NUMBER}"'
|
||||
|
||||
@@ -175,11 +175,11 @@ cline auth --provider anthropic --apikey "..."
|
||||
```
|
||||
The `auth` command configures Cline in the CI environment without interactive prompts. You can switch providers (e.g., `openai`, `openrouter`) by changing the flags.
|
||||
|
||||
### Autonomous Mode (`--yolo`)
|
||||
### Autonomous Mode (`--auto-approve true`)
|
||||
```bash
|
||||
cline --yolo '...'
|
||||
cline --auto-approve true '...'
|
||||
```
|
||||
The `--yolo` flag tells Cline to run autonomously, executing commands without waiting for user approval. This is essential for CI/CD workflows.
|
||||
The `--auto-approve true` flag tells Cline to run autonomously, executing approved tools without waiting for interactive confirmation. Prompt runs start in Act mode by default, so CI/CD workflows can perform the requested work immediately.
|
||||
|
||||
### Command Permissions
|
||||
We explicitly restrict what commands Cline can run using `CLINE_COMMAND_PERMISSIONS`. This ensures Cline can only use `gh` and `git` commands relevant to reviewing, preventing any accidental or malicious system modifications.
|
||||
+27
-27
@@ -43,20 +43,20 @@ Use different models for different phases of work. Route simple tasks to cheap m
|
||||
ISSUE_CONTENT=$(gh issue view $(gh issue list -L 1 | awk '{print $1}'))
|
||||
|
||||
# Phase 1: Quick summary with cheap model
|
||||
SUMMARY=$(echo "$ISSUE_CONTENT" | cline -y --config ~/.cline-haiku \
|
||||
SUMMARY=$(echo "$ISSUE_CONTENT" | cline --auto-approve true --config ~/.cline-haiku \
|
||||
"summarize this issue in 2-3 sentences")
|
||||
|
||||
# Phase 2: Detailed plan with expensive model + thinking
|
||||
PLAN=$(echo "$SUMMARY" | cline -y --thinking --config ~/.cline-opus \
|
||||
PLAN=$(echo "$SUMMARY" | cline --auto-approve true --thinking high --config ~/.cline-opus \
|
||||
"create detailed implementation plan with edge cases")
|
||||
|
||||
# Phase 3: Execute with mid-tier model
|
||||
echo "$PLAN" | cline -y --config ~/.cline-sonnet \
|
||||
echo "$PLAN" | cline --auto-approve true --config ~/.cline-sonnet \
|
||||
"implement the plan from above"
|
||||
```
|
||||
|
||||
<Note>
|
||||
Each cline invocation needs to complete before passing output to the next phase. Use shell variables to store intermediate results rather than piping cline commands directly.
|
||||
Each `cline` invocation needs to complete before passing output to the next phase. Use shell variables to store intermediate results rather than piping `cline` commands directly.
|
||||
</Note>
|
||||
|
||||
**Cost impact:**
|
||||
@@ -102,19 +102,19 @@ Get multiple AI perspectives on the same change, then synthesize their feedback.
|
||||
DIFF=$(git show)
|
||||
|
||||
# Review 1: Gemini's perspective
|
||||
echo "$DIFF" | cline -y --config ~/.cline-gemini \
|
||||
echo "$DIFF" | cline --auto-approve true --config ~/.cline-gemini \
|
||||
"review this diff and write your analysis to gemini-review.md"
|
||||
|
||||
# Review 2: Codex's perspective
|
||||
echo "$DIFF" | cline -y --config ~/.cline-codex \
|
||||
echo "$DIFF" | cline --auto-approve true --config ~/.cline-codex \
|
||||
"review this diff and write your analysis to codex-review.md"
|
||||
|
||||
# Review 3: Opus's perspective
|
||||
echo "$DIFF" | cline -y --config ~/.cline-opus \
|
||||
echo "$DIFF" | cline --auto-approve true --config ~/.cline-opus \
|
||||
"review this diff and write your analysis to opus-review.md"
|
||||
|
||||
# Synthesize all reviews into a consensus
|
||||
cat gemini-review.md codex-review.md opus-review.md | cline -y \
|
||||
cat gemini-review.md codex-review.md opus-review.md | cline --auto-approve true \
|
||||
"summarize these 3 reviews and identify: 1) issues all models agree on, 2) issues only one model caught, 3) your final recommendation"
|
||||
```
|
||||
|
||||
@@ -130,19 +130,19 @@ Run reviews in parallel for faster feedback:
|
||||
|
||||
```bash
|
||||
# Run all reviews simultaneously
|
||||
git show | cline -y --config ~/.cline-gemini "review and save to gemini-review.md" &
|
||||
git show | cline -y --config ~/.cline-codex "review and save to codex-review.md" &
|
||||
git show | cline -y --config ~/.cline-opus "review and save to opus-review.md" &
|
||||
git show | cline --auto-approve true --config ~/.cline-gemini "review and save to gemini-review.md" &
|
||||
git show | cline --auto-approve true --config ~/.cline-codex "review and save to codex-review.md" &
|
||||
git show | cline --auto-approve true --config ~/.cline-opus "review and save to opus-review.md" &
|
||||
|
||||
# Wait for all to complete
|
||||
wait
|
||||
|
||||
# Synthesize
|
||||
cat *-review.md | cline -y "create consensus review"
|
||||
cat *-review.md | cline --auto-approve true "create consensus review"
|
||||
```
|
||||
|
||||
<Note>
|
||||
Parallel execution requires managing multiple Cline instances. See [Multi-instance workflows](/cline-cli/three-core-flows#3-multi-instance-run-parallel-agents) for details.
|
||||
Parallel execution requires managing multiple Cline instances. See [Multi-instance workflows](/usage/cli-overview#automation-patterns) for details.
|
||||
</Note>
|
||||
|
||||
## Extended Thinking for Complex Tasks
|
||||
@@ -151,14 +151,14 @@ Use the `--thinking` flag when Cline needs to analyze multiple approaches:
|
||||
|
||||
```bash
|
||||
# Without thinking: Fast but may miss nuances
|
||||
cline -y "refactor this codebase"
|
||||
cline --auto-approve true "refactor this codebase"
|
||||
|
||||
# With thinking: Slower but more thorough
|
||||
cline -y --thinking \
|
||||
cline --auto-approve true --thinking high \
|
||||
"refactor this codebase - consider: performance, maintainability, backward compatibility"
|
||||
```
|
||||
|
||||
The `--thinking` flag allocates 1024 tokens for internal reasoning before Cline responds. Best for:
|
||||
The `--thinking <level>` flag sets reasoning effort. Use `--thinking high` or `--thinking xhigh` when you want the model to spend more effort on complex tradeoffs. Best for:
|
||||
- Architectural decisions
|
||||
- Security analysis
|
||||
- Complex refactoring
|
||||
@@ -178,12 +178,12 @@ The `--thinking` flag allocates 1024 tokens for internal reasoning before Cline
|
||||
|
||||
```bash
|
||||
# Haiku: Quick summary and issue identification
|
||||
gh pr view $PR | cline -y --config ~/.cline-haiku \
|
||||
gh pr view $PR | cline --auto-approve true --config ~/.cline-haiku \
|
||||
"list all issues to fix, output as JSON"
|
||||
|
||||
# Opus with thinking: Deep analysis only if issues found
|
||||
if [ -s issues.json ]; then
|
||||
cline -y --thinking --config ~/.cline-opus \
|
||||
cline --auto-approve true --thinking high --config ~/.cline-opus \
|
||||
"analyze these issues and recommend fixes"
|
||||
fi
|
||||
```
|
||||
@@ -192,31 +192,31 @@ fi
|
||||
|
||||
```bash
|
||||
# Different models have different security perspectives
|
||||
git diff main | cline -y --config ~/.cline-gemini "security review" > gemini-sec.md &
|
||||
git diff main | cline -y --config ~/.cline-opus "security review" > opus-sec.md &
|
||||
git diff main | cline -y --config ~/.cline-codex "security review" > codex-sec.md &
|
||||
git diff main | cline --auto-approve true --config ~/.cline-gemini "security review" > gemini-sec.md &
|
||||
git diff main | cline --auto-approve true --config ~/.cline-opus "security review" > opus-sec.md &
|
||||
git diff main | cline --auto-approve true --config ~/.cline-codex "security review" > codex-sec.md &
|
||||
wait
|
||||
|
||||
# High-priority: Issues all 3 models found
|
||||
cat *-sec.md | cline -y "find security issues all 3 reviews mentioned"
|
||||
cat *-sec.md | cline --auto-approve true "find security issues all 3 reviews mentioned"
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="CLI Reference" icon="terminal" href="/cline-cli/cli-reference">
|
||||
<Card title="CLI Reference" icon="terminal" href="/cli/cli-reference">
|
||||
Complete documentation for --config and --thinking flags
|
||||
</Card>
|
||||
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
<Card title="Headless Mode" icon="robot" href="/usage/cli-overview#headless-mode">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
|
||||
<Card title="Model Selection Guide" icon="brain" href="/core-features/model-selection-guide">
|
||||
Compare models and choose the right one for your needs
|
||||
<Card title="Cline provider" icon="brain" href="/getting-started/cline-provider">
|
||||
Fastest built-in model access setup and account workflow
|
||||
</Card>
|
||||
|
||||
<Card title="CI/CD Integration" icon="github" href="/cline-cli/samples/github-integration">
|
||||
<Card title="CI/CD Integration" icon="github" href="/cli/samples/github-integration">
|
||||
Automate GitHub workflows with Cline CLI
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -0,0 +1,110 @@
|
||||
---
|
||||
title: "Scheduling"
|
||||
sidebarTitle: "Scheduling"
|
||||
description: "Run agents on cron schedules for recurring automations like daily summaries and code reviews."
|
||||
---
|
||||
<Warning>
|
||||
This feature currently only applies to Cline SDK, CLI, and Kanban. This feature is not applicable on VSCode and JetBrains Extension for now.
|
||||
</Warning>
|
||||
|
||||
The CLI supports running agents on cron schedules through the hub. Scheduled agents persist across process restarts and run independently of any terminal session.
|
||||
|
||||
## Schedule Wizard
|
||||
|
||||
Run `cline schedule` to open an interactive menu for creating and managing schedules, browsing execution history, and viewing performance statistics.
|
||||
|
||||
```bash
|
||||
cline schedule
|
||||
```
|
||||
|
||||
The wizard provides:
|
||||
|
||||
| Action | Description |
|
||||
|--------|-------------|
|
||||
| Create new schedule | Set up a recurring task with cron timing and prompt |
|
||||
| List schedules | View all schedules with status and next run time |
|
||||
| Upcoming runs | Preview the next 10 scheduled executions |
|
||||
| Active executions | Show currently running tasks |
|
||||
| Trigger now | Immediately run a selected schedule |
|
||||
| Pause / Resume | Suspend or restart a schedule |
|
||||
| Execution history | View past runs with status, duration, tokens, and cost |
|
||||
| Statistics | Success rate, average duration, last failure |
|
||||
| Delete | Remove a schedule |
|
||||
|
||||
## Creating Schedules with Flags
|
||||
|
||||
```bash
|
||||
cline schedule create "PR summary" \
|
||||
--cron "0 9 * * MON-FRI" \
|
||||
--prompt "List all open PRs and their review status" \
|
||||
--workspace /path/to/repo \
|
||||
--model anthropic/claude-sonnet-4-6
|
||||
```
|
||||
|
||||
## Managing Schedules
|
||||
|
||||
```bash
|
||||
cline schedule list
|
||||
cline schedule trigger <schedule-id>
|
||||
cline schedule pause <schedule-id>
|
||||
cline schedule resume <schedule-id>
|
||||
cline schedule delete <schedule-id>
|
||||
cline schedule executions <schedule-id>
|
||||
```
|
||||
|
||||
## Cron Expression Reference
|
||||
|
||||
| Expression | Schedule |
|
||||
|-----------|----------|
|
||||
| `*/5 * * * *` | Every 5 minutes |
|
||||
| `*/15 * * * *` | Every 15 minutes |
|
||||
| `0 * * * *` | Every hour |
|
||||
| `0 */6 * * *` | Every 6 hours |
|
||||
| `0 0 * * *` | Daily at midnight |
|
||||
| `0 9 * * *` | Daily at 9am |
|
||||
| `0 9 * * 1-5` | Every weekday at 9am |
|
||||
| `0 9 * * 1` | Every Monday at 9am |
|
||||
| `0 0 1 * *` | First of every month |
|
||||
|
||||
## Examples
|
||||
|
||||
### Daily Standup Summary
|
||||
|
||||
```bash
|
||||
cline schedule create "Standup prep" \
|
||||
--cron "0 8 * * MON-FRI" \
|
||||
--prompt "Summarize: (1) PRs merged yesterday, (2) PRs currently in review, (3) open issues assigned to team members." \
|
||||
--workspace /path/to/repo
|
||||
```
|
||||
|
||||
### Weekly Dependency Check
|
||||
|
||||
```bash
|
||||
cline schedule create "Dependency check" \
|
||||
--cron "0 10 * * MON" \
|
||||
--prompt "Check for outdated npm dependencies. For any with security vulnerabilities, create a branch with the update and open a PR." \
|
||||
--workspace /path/to/project
|
||||
```
|
||||
|
||||
### Codebase Health Report
|
||||
|
||||
```bash
|
||||
cline schedule create "Code health" \
|
||||
--cron "0 6 * * MON" \
|
||||
--prompt "Analyze the codebase for: (1) files with no test coverage, (2) TODO/FIXME comments older than 30 days, (3) functions longer than 100 lines." \
|
||||
--workspace /path/to/project
|
||||
```
|
||||
|
||||
## Routing Results
|
||||
|
||||
Combine schedules with [connectors](/cli/connectors) to send results to messaging platforms:
|
||||
|
||||
```bash
|
||||
cline connect telegram -m my_bot -k $BOT_TOKEN
|
||||
|
||||
cline schedule create "Morning briefing" \
|
||||
--cron "0 8 * * *" \
|
||||
--prompt "Summarize overnight activity in the repo"
|
||||
```
|
||||
|
||||
Scheduling requires the hub. It starts automatically when you create a schedule.
|
||||
@@ -1,428 +0,0 @@
|
||||
---
|
||||
title: "CLI Reference"
|
||||
description: "Complete command reference for Cline CLI including all commands, flags, and configuration options"
|
||||
---
|
||||
|
||||
This page documents all available commands, flags, and configuration options for Cline CLI. For quick help in your terminal, use:
|
||||
|
||||
```bash
|
||||
cline --help # Show all commands
|
||||
cline task --help # Show task command options
|
||||
cline auth --help # Show auth command options
|
||||
man cline # View the full manual page (if installed)
|
||||
```
|
||||
|
||||
## Synopsis
|
||||
|
||||
```bash
|
||||
cline [prompt] [options]
|
||||
cline <command> [options] [arguments]
|
||||
```
|
||||
|
||||
## Global Options
|
||||
|
||||
These options work with any command:
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--config <path>` | Use a custom configuration directory instead of `~/.cline/data/` |
|
||||
| `-c, --cwd <path>` | Set the working directory for the task |
|
||||
| `-v, --verbose` | Show detailed output including model reasoning |
|
||||
| `--help` | Show help for the command |
|
||||
|
||||
## Modes of Operation
|
||||
|
||||
Cline CLI automatically detects the best output mode based on how you invoke it:
|
||||
|
||||
| Mode | When Activated | Description |
|
||||
|------|----------------|-------------|
|
||||
| **Interactive** | `cline` with no args, TTY connected | Rich terminal UI with real-time streaming, keyboard shortcuts, and visual feedback. |
|
||||
| **Task** | `cline "prompt"` with TTY connected | Interactive UI starts immediately with your task. |
|
||||
| **Plain Text** | stdin piped, stdout redirected, or `--yolo`/`--json` flags | Clean text output without UI, suitable for scripting and CI/CD. |
|
||||
|
||||
## Agent Behavior
|
||||
|
||||
Cline operates in two primary modes that control how it approaches tasks:
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| **Act Mode** (default) | Cline actively uses tools to accomplish tasks. It can read files, write code, execute commands, use a headless browser, and more. |
|
||||
| **Plan Mode** | Cline gathers information and creates a detailed plan before implementation. It explores the codebase, asks clarifying questions, and presents a strategy for your approval before switching to Act Mode. |
|
||||
|
||||
Use `-a, --act` or `-p, --plan` flags to explicitly set the mode.
|
||||
|
||||
## Commands
|
||||
|
||||
### cline (default)
|
||||
|
||||
Run Cline without a subcommand to start a task or enter interactive mode.
|
||||
|
||||
```bash
|
||||
# Interactive mode (no arguments)
|
||||
cline
|
||||
|
||||
# Start a task directly
|
||||
cline "your prompt here"
|
||||
|
||||
# Resume the latest task for the current directory
|
||||
cline --continue
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-a, --act` | Start in Act mode (default). Cline executes actions directly. |
|
||||
| `-p, --plan` | Start in Plan mode. Cline analyzes and creates a strategy before acting. |
|
||||
| `-y, --yolo` | YOLO mode: auto-approve all actions, use plain text output, exit when complete. Ideal for CI/CD. |
|
||||
| `-m, --model <id>` | Use a specific model (e.g., `claude-sonnet-4-5-20250929`, `gpt-4o`). |
|
||||
| `-i, --images <paths...>` | Include image files with the prompt. |
|
||||
| `--thinking` | Enable extended thinking with a 1024 token budget. |
|
||||
| `--json` | Output messages as JSON (one object per line). Forces plain text mode. |
|
||||
| `--timeout <seconds>` | Maximum execution time before the task is stopped. |
|
||||
| `--continue` | Resume the most recent task from the current working directory. |
|
||||
|
||||
**Mode Behavior:**
|
||||
|
||||
| Invocation | Output Mode | Why |
|
||||
|------------|-------------|-----|
|
||||
| `cline` | Interactive UI | No arguments, TTY connected |
|
||||
| `cline "prompt"` | Interactive UI | TTY connected |
|
||||
| `cline -y "prompt"` | Plain text | YOLO flag forces plain text |
|
||||
| `cline --json "prompt"` | JSON | JSON flag forces plain text |
|
||||
| `cat file \| cline "prompt"` | Plain text | stdin is piped |
|
||||
| `cline "prompt" > out.txt` | Plain text | stdout is redirected |
|
||||
|
||||
---
|
||||
|
||||
### cline task (alias: t)
|
||||
|
||||
Run a task with a prompt. This is equivalent to `cline "prompt"`.
|
||||
|
||||
```bash
|
||||
cline task "Create a REST API endpoint"
|
||||
cline t "Fix the bug in utils.js"
|
||||
```
|
||||
|
||||
**Options:** Same as the default command above.
|
||||
|
||||
---
|
||||
|
||||
### cline auth
|
||||
|
||||
Configure authentication with an AI provider.
|
||||
|
||||
```bash
|
||||
# Interactive wizard
|
||||
cline auth
|
||||
|
||||
# Quick setup with flags
|
||||
cline auth -p anthropic -k sk-ant-api-xxxxx -m claude-sonnet-4-5-20250929
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-p, --provider <id>` | Provider ID. See [Supported Providers](#supported-providers) below. |
|
||||
| `-k, --apikey <key>` | API key for the provider. |
|
||||
| `-m, --modelid <id>` | Model ID to use (e.g., `claude-sonnet-4-5-20250929`, `gpt-4o`). |
|
||||
| `-b, --baseurl <url>` | Base URL for OpenAI-compatible providers. |
|
||||
|
||||
**Supported Providers:**
|
||||
|
||||
| Provider ID | Description |
|
||||
|-------------|-------------|
|
||||
| `anthropic` | Anthropic Claude (direct API) |
|
||||
| `openai-native` | OpenAI GPT models |
|
||||
| `openai-codex` | ChatGPT subscription via OAuth |
|
||||
| `openrouter` | OpenRouter (access multiple providers) |
|
||||
| `bedrock` | AWS Bedrock |
|
||||
| `gemini` | Google Gemini |
|
||||
| `xai` | X AI (Grok) |
|
||||
| `cerebras` | Cerebras (fast inference) |
|
||||
| `deepseek` | DeepSeek |
|
||||
| `ollama` | Ollama (local models) |
|
||||
| `lmstudio` | LM Studio (local models) |
|
||||
| `openai` | OpenAI-compatible API (custom base URL) |
|
||||
|
||||
---
|
||||
|
||||
### cline history (alias: h)
|
||||
|
||||
Browse task history with pagination.
|
||||
|
||||
```bash
|
||||
# Show recent tasks (default: 10)
|
||||
cline history
|
||||
|
||||
# Show more tasks
|
||||
cline history -n 20
|
||||
|
||||
# Paginate through history
|
||||
cline history -n 10 -p 2
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-n, --limit <number>` | Number of tasks to show (default: 10) |
|
||||
| `-p, --page <number>` | Page number, 1-based (default: 1) |
|
||||
|
||||
---
|
||||
|
||||
### cline config
|
||||
|
||||
View and manage configuration settings.
|
||||
|
||||
```bash
|
||||
cline config
|
||||
```
|
||||
|
||||
Opens an interactive configuration view with tabs for:
|
||||
- **Settings** - Global and workspace-specific settings
|
||||
- **Rules** - `.clinerules` files and imported rules
|
||||
- **Workflows** - Available workflows (appear as slash commands)
|
||||
- **Hooks** - Configured hook scripts
|
||||
- **Skills** - Enabled skills
|
||||
|
||||
---
|
||||
|
||||
### cline update
|
||||
|
||||
Check for updates and install the latest version.
|
||||
|
||||
```bash
|
||||
cline update
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### cline version
|
||||
|
||||
Show the installed CLI version.
|
||||
|
||||
```bash
|
||||
cline version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### cline dev
|
||||
|
||||
Developer tools for debugging.
|
||||
|
||||
```bash
|
||||
# Open the log file
|
||||
cline dev log
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### CLINE_DIR
|
||||
|
||||
Override the default configuration directory:
|
||||
|
||||
```bash
|
||||
export CLINE_DIR=/path/to/custom/config
|
||||
cline "your task"
|
||||
```
|
||||
|
||||
When set, all Cline data (settings, secrets, task history) is stored in this directory instead of `~/.cline/data/`.
|
||||
|
||||
**Use cases:**
|
||||
- Running isolated Cline instances with different settings
|
||||
- CI/CD environments with custom state directories
|
||||
- Testing configuration changes without affecting your main setup
|
||||
|
||||
### CLINE_COMMAND_PERMISSIONS
|
||||
|
||||
Restrict which shell commands Cline can execute:
|
||||
|
||||
```bash
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *"], "deny": ["rm -rf *"]}'
|
||||
```
|
||||
|
||||
**Format:**
|
||||
|
||||
```json
|
||||
{
|
||||
"allow": ["pattern1", "pattern2"],
|
||||
"deny": ["pattern3"],
|
||||
"allowRedirects": true
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `allow` | `string[]` | Glob patterns for allowed commands. If set, **only** matching commands are permitted. |
|
||||
| `deny` | `string[]` | Glob patterns for denied commands. Deny rules **always take precedence** over allow rules. |
|
||||
| `allowRedirects` | `boolean` | Whether to allow shell redirects (`>`, `>>`, `<`). Default: `false`. |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Allow only npm and git commands (deny everything else)
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *"]}'
|
||||
|
||||
# Allow dev commands but explicitly deny dangerous ones
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *", "node *"], "deny": ["rm -rf *", "sudo *"]}'
|
||||
|
||||
# Allow file reading with redirects
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["cat *", "echo *"], "allowRedirects": true}'
|
||||
```
|
||||
|
||||
**How commands are evaluated:**
|
||||
|
||||
1. Check for dangerous characters (backticks outside single quotes, unquoted newlines)
|
||||
2. Parse command into segments split by operators (`&&`, `||`, `|`, `;`)
|
||||
3. If redirects are detected and `allowRedirects` is not true, command is denied
|
||||
4. Each segment is validated against deny rules first, then allow rules
|
||||
5. Subshell contents (`$(...)` and `(...)`) are recursively validated
|
||||
6. All segments must pass for the command to be allowed
|
||||
|
||||
## JSON Output Format
|
||||
|
||||
When using `--json`, each message is output as a JSON object (one per line):
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "say",
|
||||
"text": "I'll create the file now.",
|
||||
"ts": 1760501486669,
|
||||
"say": "text"
|
||||
}
|
||||
```
|
||||
|
||||
**Required fields:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `type` | `"ask"` \| `"say"` | Message category |
|
||||
| `text` | `string` | Human-readable message content |
|
||||
| `ts` | `number` | Unix timestamp in milliseconds |
|
||||
|
||||
**Optional fields:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `say` | `string` | Subtype when `type` is `"say"` (e.g., `"text"`, `"tool"`) |
|
||||
| `ask` | `string` | Subtype when `type` is `"ask"` (e.g., `"tool"`, `"followup"`) |
|
||||
| `reasoning` | `string` | Model reasoning (omitted when empty) |
|
||||
| `partial` | `boolean` | `true` while streaming (omitted when complete) |
|
||||
| `images` | `string[]` | Image URIs (omitted when empty) |
|
||||
| `files` | `string[]` | File paths (omitted when empty) |
|
||||
|
||||
## Configuration Files
|
||||
|
||||
Cline stores all data in `~/.cline/` by default:
|
||||
|
||||
```text
|
||||
~/.cline/
|
||||
├── data/ # Configuration directory
|
||||
│ ├── globalState.json # Global settings
|
||||
│ ├── secrets.json # API keys (stored securely)
|
||||
│ ├── workspace/ # Workspace-specific state
|
||||
│ └── tasks/ # Task history and conversations
|
||||
└── log/ # Debug logs (view with cline dev log)
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Interactive Development
|
||||
|
||||
```bash
|
||||
# Start interactive mode
|
||||
cline
|
||||
|
||||
# Start with a task and use interactive UI
|
||||
cline "Help me refactor this codebase"
|
||||
```
|
||||
|
||||
### Direct Task Execution
|
||||
|
||||
```bash
|
||||
# Run a task directly
|
||||
cline "Add error handling to utils.js"
|
||||
|
||||
# Start in Plan mode to review strategy first
|
||||
cline -p "Design a caching layer for the API"
|
||||
|
||||
# Use a specific model
|
||||
cline -m gpt-4o "Explain this code"
|
||||
```
|
||||
|
||||
### Piped Input
|
||||
|
||||
```bash
|
||||
# Pipe file contents
|
||||
cat README.md | cline "Summarize this document"
|
||||
|
||||
# Review git changes
|
||||
git diff | cline "Review these changes"
|
||||
|
||||
# Analyze test output
|
||||
npm test 2>&1 | cline "Fix any failing tests"
|
||||
```
|
||||
|
||||
### Automation and CI/CD
|
||||
|
||||
```bash
|
||||
# YOLO mode for automated workflows
|
||||
cline -y "Run tests and fix failures"
|
||||
|
||||
# JSON output for scripting
|
||||
cline --json "List all TODO comments" | jq '.text'
|
||||
|
||||
# With timeout
|
||||
cline -y --timeout 600 "Run the full test suite"
|
||||
|
||||
# Chain commands
|
||||
git diff | cline -y "explain" | cline -y "write a commit message"
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
# Interactive wizard
|
||||
cline auth
|
||||
|
||||
# Quick setup: Anthropic
|
||||
cline auth -p anthropic -k sk-ant-api-xxxxx -m claude-sonnet-4-5-20250929
|
||||
|
||||
# Quick setup: OpenAI
|
||||
cline auth -p openai-native -k sk-xxxxx -m gpt-4o
|
||||
|
||||
# Quick setup: OpenRouter
|
||||
cline auth -p openrouter -k sk-or-xxxxx
|
||||
|
||||
# OpenAI-compatible with custom URL
|
||||
cline auth -p openai -k your-key -b https://api.example.com/v1
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
- **Report bugs:** https://github.com/cline/cline/issues
|
||||
- **Discord community:** https://discord.gg/cline
|
||||
- **Documentation:** https://docs.cline.bot
|
||||
|
||||
## See Also
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Installation & Setup" icon="download" href="/cline-cli/installation">
|
||||
Install Cline CLI and configure authentication.
|
||||
</Card>
|
||||
|
||||
<Card title="Interactive Mode" icon="terminal" href="/cline-cli/interactive-mode">
|
||||
Keyboard shortcuts, slash commands, and file mentions.
|
||||
</Card>
|
||||
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
|
||||
<Card title="Configuration" icon="gear" href="/cline-cli/configuration">
|
||||
Environment variables and advanced settings.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -1,330 +0,0 @@
|
||||
---
|
||||
title: "Configuration"
|
||||
description: "Manage Cline CLI settings with cline config, environment variables, and configuration files"
|
||||
---
|
||||
|
||||
Cline CLI provides multiple ways to configure settings, from the interactive `cline config` command to environment variables for automation.
|
||||
|
||||
## The Config Command
|
||||
|
||||
Launch the configuration interface:
|
||||
|
||||
```bash
|
||||
cline config
|
||||
```
|
||||
|
||||
This opens an interactive view with tabs for different configuration categories.
|
||||
|
||||
## Configuration Tabs
|
||||
|
||||
Navigate between tabs using arrow keys.
|
||||
|
||||
### Settings Tab
|
||||
|
||||
View and edit global and workspace-specific settings:
|
||||
|
||||
- **Global State**: Settings that apply across all workspaces
|
||||
- **Workspace State**: Settings specific to the current directory
|
||||
|
||||
### Rules Tab
|
||||
|
||||
Manage Cline rules that guide AI behavior:
|
||||
|
||||
- **`.clinerules` files**: Project-specific rules in your workspace
|
||||
- **Cursor rules**: Import rules from Cursor editor format
|
||||
- **Windsurf rules**: Import rules from Windsurf editor format
|
||||
|
||||
Rules help Cline understand your project's conventions, coding standards, and preferences.
|
||||
|
||||
### Workflows Tab
|
||||
|
||||
View and manage [workflows](/customization/workflows):
|
||||
|
||||
- List available workflows
|
||||
- View workflow definitions
|
||||
- Workflows appear as slash commands in interactive mode
|
||||
|
||||
### Hooks Tab
|
||||
|
||||
Configure [hooks](/customization/hooks) for custom logic integration:
|
||||
|
||||
- Enable/disable hooks globally
|
||||
- View configured hook scripts
|
||||
- Hooks run at key points in Cline's workflow
|
||||
|
||||
<Note>
|
||||
Hooks must be enabled via settings. Use `cline config` to toggle `hooks-enabled`.
|
||||
</Note>
|
||||
|
||||
### Skills Tab
|
||||
|
||||
Manage [skills](/customization/skills) that extend Cline's capabilities:
|
||||
|
||||
- View available skills
|
||||
- Enable/disable specific skills
|
||||
- Skills provide specialized instructions for specific tasks
|
||||
|
||||
## Configuration Directory
|
||||
|
||||
Cline stores configuration in `~/.cline/data/`:
|
||||
|
||||
```text
|
||||
~/.cline/
|
||||
├── data/ # Configuration directory
|
||||
│ ├── globalState.json # Global settings
|
||||
│ ├── secrets.json # API keys (encrypted)
|
||||
│ ├── settings/ # Settings files
|
||||
│ │ └── cline_mcp_settings.json # MCP server configuration
|
||||
│ ├── workspace/ # Workspace-specific state
|
||||
│ └── tasks/ # Task history and data
|
||||
└── log/ # Log files
|
||||
```
|
||||
|
||||
### Viewing Logs
|
||||
|
||||
For debugging, view the log file:
|
||||
|
||||
```bash
|
||||
cline dev log
|
||||
```
|
||||
|
||||
This opens the log file in your default editor.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### CLINE_DIR
|
||||
|
||||
Override the default configuration directory:
|
||||
|
||||
```bash
|
||||
export CLINE_DIR=/custom/path/to/cline
|
||||
cline "your task"
|
||||
```
|
||||
|
||||
When set, all Cline data is stored in this directory instead of `~/.cline/data/`.
|
||||
|
||||
**Use cases:**
|
||||
- Running multiple isolated Cline configurations
|
||||
- Team-shared configurations
|
||||
- CI/CD with custom state directories
|
||||
|
||||
### CLINE_COMMAND_PERMISSIONS
|
||||
|
||||
Restrict which shell commands Cline can execute:
|
||||
|
||||
```bash
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *"], "deny": ["rm -rf *"]}'
|
||||
```
|
||||
|
||||
**Format:**
|
||||
|
||||
```json
|
||||
{
|
||||
"allow": ["pattern1", "pattern2"],
|
||||
"deny": ["pattern3"],
|
||||
"allowRedirects": true
|
||||
}
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `allow` | `string[]` | Glob patterns for allowed commands. If set, only matching commands are permitted. |
|
||||
| `deny` | `string[]` | Glob patterns for denied commands. Deny rules take precedence over allow. |
|
||||
| `allowRedirects` | `boolean` | Whether to allow shell redirects (`>`, `>>`, `<`). Default: `false` |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Allow only npm and git commands
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *"]}'
|
||||
|
||||
# Allow dev commands but deny dangerous ones
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *", "node *"], "deny": ["rm -rf *", "sudo *"]}'
|
||||
|
||||
# Allow file operations with redirects
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["cat *", "echo *"], "allowRedirects": true}'
|
||||
```
|
||||
|
||||
<Warning>
|
||||
When `allow` is set, all commands not matching the allow patterns are denied. Use this for security-sensitive environments.
|
||||
</Warning>
|
||||
|
||||
## Using --config Flag
|
||||
|
||||
Run Cline with a custom configuration directory:
|
||||
|
||||
```bash
|
||||
cline --config /path/to/custom/config "your task"
|
||||
```
|
||||
|
||||
This is useful for:
|
||||
- Running isolated Cline instances
|
||||
- Testing different configurations
|
||||
- Separating work and personal setups
|
||||
|
||||
**Example: Multiple configurations**
|
||||
|
||||
```bash
|
||||
# Work configuration
|
||||
cline --config ~/.cline-work "review this PR"
|
||||
|
||||
# Personal projects
|
||||
cline --config ~/.cline-personal "help me with this side project"
|
||||
```
|
||||
|
||||
## MCP Server Configuration
|
||||
|
||||
Cline CLI supports [MCP (Model Context Protocol)](/mcp/mcp-overview) servers, giving you access to external tools and data sources directly from the terminal. The CLI uses the same MCP configuration format as the VS Code extension.
|
||||
|
||||
### Setting Up MCP Servers
|
||||
|
||||
You can add MCP servers from the CLI:
|
||||
|
||||
```bash
|
||||
# STDIO server
|
||||
cline mcp add kanban -- kanban mcp
|
||||
|
||||
# Remote HTTP server
|
||||
cline mcp add linear https://mcp.linear.app/mcp --type http
|
||||
```
|
||||
|
||||
These commands update:
|
||||
|
||||
```
|
||||
~/.cline/data/settings/cline_mcp_settings.json
|
||||
```
|
||||
|
||||
You can still edit this file directly. It uses the same JSON format as the VS Code extension:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"my-server": {
|
||||
"command": "node",
|
||||
"args": ["/path/to/server.js"],
|
||||
"env": {
|
||||
"API_KEY": "your_api_key"
|
||||
},
|
||||
"alwaysAllow": ["tool1", "tool2"],
|
||||
"disabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For the full configuration reference including STDIO and SSE transport types, see [Adding and Configuring MCP Servers](/mcp/adding-and-configuring-servers).
|
||||
|
||||
<Note>
|
||||
The CLI does not yet have a `/mcp` slash command for interactive management inside the terminal UI. Use `cline mcp add` or edit `cline_mcp_settings.json` directly.
|
||||
</Note>
|
||||
|
||||
### Custom Config Directory
|
||||
|
||||
If you use the `CLINE_DIR` environment variable or `--config` flag, the MCP settings file will be located at `<your-config-dir>/data/settings/cline_mcp_settings.json` instead.
|
||||
|
||||
## Configuration for Local Providers
|
||||
|
||||
### Ollama
|
||||
|
||||
Configure context window size for Ollama:
|
||||
|
||||
```bash
|
||||
# In settings or via config
|
||||
cline config
|
||||
# Navigate to Settings tab, find ollama-api-options-ctx-num
|
||||
```
|
||||
|
||||
Or set via environment:
|
||||
|
||||
```bash
|
||||
# Set context window to 32K tokens
|
||||
cline -m ollama/llama3 "your task"
|
||||
```
|
||||
|
||||
### LM Studio
|
||||
|
||||
Configure max tokens for LM Studio:
|
||||
|
||||
```bash
|
||||
cline config
|
||||
# Navigate to Settings tab, find lm-studio-max-tokens
|
||||
```
|
||||
|
||||
## Importing Configuration
|
||||
|
||||
### From VS Code Extension
|
||||
|
||||
If you use the Cline VS Code extension, the CLI automatically detects and can share some settings. However, the CLI maintains its own configuration for terminal-specific features.
|
||||
|
||||
### From Other CLI Tools
|
||||
|
||||
See [Installation & Setup](/cline-cli/installation#option-3-import-from-existing-tools) for importing configurations from:
|
||||
- Codex CLI
|
||||
- OpenCode
|
||||
|
||||
## Configuration Best Practices
|
||||
|
||||
### For Development
|
||||
|
||||
Use the default configuration with workspace-specific rules:
|
||||
|
||||
```bash
|
||||
# Add project-specific rules
|
||||
echo "Use TypeScript strict mode" > .clinerules/typescript.md
|
||||
```
|
||||
|
||||
### For CI/CD
|
||||
|
||||
Use environment variables and `--yolo` mode:
|
||||
|
||||
```bash
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm test", "npm run build"]}'
|
||||
cline -y "run tests and fix any failures"
|
||||
```
|
||||
|
||||
### For Teams
|
||||
|
||||
Share configuration via version control:
|
||||
|
||||
```bash
|
||||
# Commit .clinerules/ to your repo
|
||||
git add .clinerules/
|
||||
git commit -m "Add Cline rules for team"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Configuration Not Persisting
|
||||
|
||||
1. Check write permissions on `~/.cline/data/`
|
||||
2. Ensure `CLINE_DIR` isn't set to a read-only location
|
||||
3. Verify the config directory exists
|
||||
|
||||
### Environment Variables Not Working
|
||||
|
||||
1. Ensure variables are exported: `export CLINE_DIR=/path`
|
||||
2. Check for typos in variable names
|
||||
3. Verify JSON syntax for `CLINE_COMMAND_PERMISSIONS`
|
||||
|
||||
### Reset Configuration
|
||||
|
||||
To start fresh, remove the configuration directory:
|
||||
|
||||
```bash
|
||||
rm -rf ~/.cline/data/
|
||||
cline auth # Re-authenticate
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
|
||||
<Card title="CLI Reference" icon="terminal" href="/cline-cli/cli-reference">
|
||||
Complete command documentation with all flags and options.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -1,457 +0,0 @@
|
||||
---
|
||||
title: "Getting Started"
|
||||
description: "Run Cline AI coding agents directly in your terminal with an interactive CLI or automated workflows"
|
||||
---
|
||||
|
||||
## What is Cline CLI?
|
||||
|
||||
Cline CLI brings the full power of Cline to your terminal. Whether you prefer an interactive experience or automated workflows for CI/CD pipelines, the CLI adapts to your needs.
|
||||
|
||||
The CLI supports macOS, Linux, and Windows, and works with all the same AI providers as the VS Code extension.
|
||||
|
||||
## Two Ways to Use Cline CLI
|
||||
|
||||
The CLI operates in two distinct modes, automatically selecting the appropriate one based on how you invoke it:
|
||||
|
||||
### Interactive Mode
|
||||
|
||||
Interactive mode is designed for **hands-on development sessions** where you want to collaborate with Cline in real-time. It provides a rich terminal interface that feels like chatting with an AI assistant.
|
||||
|
||||
**When it activates:** Running `cline` without arguments, or when stdin is a TTY (terminal).
|
||||
|
||||
```bash
|
||||
cline
|
||||
```
|
||||
|
||||
Key features:
|
||||
|
||||
- **Real-time conversation** - Type messages, see Cline's responses, and iterate on tasks
|
||||
- **Visual feedback** - Animated welcome screen, syntax-highlighted code, and progress indicators
|
||||
- **File mentions** with `@` - Reference workspace files with fuzzy search autocomplete
|
||||
- **Slash commands** with `/` - Quick access to `/settings`, `/history`, `/models`, and workflows
|
||||
- **Keyboard shortcuts** - `Tab` to toggle Plan/Act, `Shift+Tab` for auto-approve all
|
||||
- **Session summaries** - See tasks completed, files modified, and token usage on exit
|
||||
- **Settings panel** - Configure providers, models, and features without leaving the CLI
|
||||
|
||||
Interactive mode keeps you in control. You review Cline's plan, approve or modify actions, and guide the conversation.
|
||||
|
||||
[Learn more about interactive mode →](/cline-cli/interactive-mode)
|
||||
|
||||
### Headless Mode (Non-Interactive)
|
||||
|
||||
Headless mode is designed for **automation, scripting, and CI/CD pipelines** where human interaction isn't possible or desired.
|
||||
|
||||
**When it activates:** Using the `-y`/`--yolo` flag, `--json` flag, piping input/output, or when stdin is not a TTY.
|
||||
|
||||
```bash
|
||||
# Headless with auto-approval (YOLO mode)
|
||||
cline -y "Run tests and fix any failures"
|
||||
|
||||
# Headless with JSON output for parsing
|
||||
cline --json "List all TODO comments" | jq '.text'
|
||||
|
||||
# Headless via piped input
|
||||
cat README.md | cline "Summarize this document"
|
||||
|
||||
# Chain multiple headless commands
|
||||
git diff | cline -y "explain these changes" | cline -y "write a commit message"
|
||||
```
|
||||
|
||||
Key features:
|
||||
|
||||
- **No visual interface** - Clean text or JSON output suitable for scripting
|
||||
- **Automatic execution** - With `-y`, Cline approves all actions and runs autonomously
|
||||
- **Process control** - Exits automatically when the task completes
|
||||
- **Piped workflows** - Read from stdin, write to stdout, chain with other commands
|
||||
- **Machine-readable output** - Use `--json` to get structured output for parsing
|
||||
|
||||
<Warning>
|
||||
Headless mode with `-y` gives Cline full autonomy. Run on a clean git branch so you can easily revert changes if needed.
|
||||
</Warning>
|
||||
|
||||
### Mode Detection Summary
|
||||
|
||||
Cline automatically detects which mode to use based on your invocation. This table shows how different command patterns trigger each mode, helping you predict behavior in scripts and interactive sessions.
|
||||
|
||||
| Invocation | Mode | Reason |
|
||||
|------------|------|--------|
|
||||
| `cline` | Interactive | No arguments, TTY connected |
|
||||
| `cline "task"` | Interactive | TTY connected |
|
||||
| `cline -y "task"` | Headless | YOLO flag forces headless |
|
||||
| `cline --json "task"` | Headless | JSON flag forces headless |
|
||||
| `cat file \| cline "task"` | Headless | stdin is piped |
|
||||
| `cline "task" > output.txt` | Headless | stdout is redirected |
|
||||
|
||||
[Learn more about headless mode →](/cline-cli/three-core-flows)
|
||||
|
||||
## Supported Model Providers
|
||||
|
||||
Cline CLI supports all providers available in the VS Code extension:
|
||||
|
||||
- **Anthropic** (Claude)
|
||||
- **OpenAI** (GPT-4o, GPT-4)
|
||||
- **OpenAI Codex** (ChatGPT subscription)
|
||||
- **OpenRouter**
|
||||
- **AWS Bedrock**
|
||||
- **Google Gemini**
|
||||
- **X AI (Grok)**
|
||||
- **Cerebras**
|
||||
- **DeepSeek**
|
||||
- **Ollama** (local models)
|
||||
- **LM Studio** (local models)
|
||||
- **OpenAI Compatible** (any compatible API)
|
||||
|
||||
During setup, authenticate with `cline auth` to configure your preferred provider. [See authentication →](#authenticate)
|
||||
|
||||
## What You Can Build
|
||||
|
||||
### Automated Code Maintenance
|
||||
|
||||
Keep your codebase healthy with automated fixes. Cline scans for issues and applies corrections across multiple files.
|
||||
|
||||
```bash
|
||||
cline -y "Fix all ESLint errors in src/"
|
||||
```
|
||||
Finds and fixes linting violations throughout your source directory.
|
||||
|
||||
```bash
|
||||
cline -y "Update all deprecated React lifecycle methods"
|
||||
```
|
||||
Migrates legacy code patterns to modern equivalents (e.g., `componentWillMount` → `useEffect`).
|
||||
|
||||
```bash
|
||||
cline -y "Update dependencies with known vulnerabilities"
|
||||
```
|
||||
Identifies outdated packages with security issues and updates them to safe versions.
|
||||
|
||||
### CI/CD Integration
|
||||
|
||||
Integrate Cline into your continuous integration pipelines for automated code review and documentation.
|
||||
|
||||
```bash
|
||||
git diff origin/main | cline -y "Review these changes for issues"
|
||||
```
|
||||
Pipes your PR diff to Cline for automated code review, catching bugs and style issues before merge.
|
||||
|
||||
```bash
|
||||
git log --oneline v1.0..v1.1 | cline -y "Write release notes"
|
||||
```
|
||||
Generates human-readable release notes from your commit history between two tags.
|
||||
|
||||
```bash
|
||||
cline -y "Run tests and fix failures" --timeout 600
|
||||
```
|
||||
Executes your test suite, analyzes failures, and attempts fixes with a 10-minute timeout.
|
||||
|
||||
### Development Workflows
|
||||
|
||||
From quick edits to complex refactors, Cline adapts to your workflow.
|
||||
|
||||
```bash
|
||||
cline
|
||||
```
|
||||
Launches interactive mode for exploratory development and back-and-forth collaboration.
|
||||
|
||||
```bash
|
||||
cline "Refactor this function to use async/await"
|
||||
```
|
||||
Executes a focused task directly from the command line with approval prompts at key steps.
|
||||
|
||||
```bash
|
||||
cline "Based on @src/api.ts, add error handling to all endpoints"
|
||||
```
|
||||
Uses file mentions (`@`) to give Cline context about specific files in your workspace.
|
||||
|
||||
### Custom Shell Pipelines
|
||||
|
||||
Chain Cline with other CLI tools to build powerful automation workflows.
|
||||
|
||||
```bash
|
||||
gh pr diff 123 | cline -y "Review this PR"
|
||||
```
|
||||
Fetches a GitHub PR diff and pipes it directly to Cline for review.
|
||||
|
||||
```bash
|
||||
cline --json "List all TODO comments" | jq '.text'
|
||||
```
|
||||
Outputs structured JSON that you can process with tools like `jq` for scripting.
|
||||
|
||||
```bash
|
||||
git diff | cline -y "explain" | cline -y "write a haiku about these changes"
|
||||
```
|
||||
Chains multiple Cline invocations together for creative multi-step workflows.
|
||||
|
||||
## Features at a Glance
|
||||
|
||||
| Feature | Interactive Mode | Non-Interactive Mode |
|
||||
|---------|------------------|----------------------|
|
||||
| Interactive chat | ✓ | - |
|
||||
| File mentions (@) | ✓ | ✓ (inline) |
|
||||
| Slash commands (/) | ✓ | - |
|
||||
| Settings panel | ✓ | `cline config` |
|
||||
| Plan/Act toggle | ✓ (Tab) | `-p` / `-a` flags |
|
||||
| Auto-approve | ✓ (Shift+Tab) | `-y` flag |
|
||||
| Session summary | ✓ | - |
|
||||
| JSON output | - | `--json` |
|
||||
| Piped input | - | ✓ |
|
||||
|
||||
---
|
||||
|
||||
## Installation & Setup
|
||||
|
||||
In just a few minutes, you can install the CLI, authenticate with your preferred AI provider, and start running tasks from any directory on your machine.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Cline CLI requires **Node.js version 20 or higher**. We recommend Node.js 22 for the best experience.
|
||||
|
||||
Check your Node.js version:
|
||||
|
||||
```bash
|
||||
node --version
|
||||
```
|
||||
|
||||
If you need to install or update Node.js, visit [nodejs.org](https://nodejs.org) or use a version manager like [nvm](https://github.com/nvm-sh/nvm).
|
||||
|
||||
### Install Cline CLI
|
||||
|
||||
Install globally via npm:
|
||||
|
||||
```bash
|
||||
npm install -g cline
|
||||
```
|
||||
|
||||
Verify the installation:
|
||||
|
||||
```bash
|
||||
cline version
|
||||
```
|
||||
|
||||
<Tip>
|
||||
To install a specific version, use `npm install -g cline@2.0.0`. Check [npm](https://www.npmjs.com/package/cline) for available versions.
|
||||
</Tip>
|
||||
|
||||
### Authenticate
|
||||
|
||||
After installation, run the authentication wizard:
|
||||
|
||||
```bash
|
||||
cline auth
|
||||
```
|
||||
|
||||
This launches an interactive wizard with multiple options. Choose the method that works best for your workflow.
|
||||
|
||||
#### Option 1: Sign in with Cline (Recommended)
|
||||
|
||||
Select **"Sign in with Cline"** to authenticate with your Cline account via OAuth. Your browser opens automatically to complete sign-in.
|
||||
|
||||
#### Option 2: Sign in with ChatGPT Subscription
|
||||
|
||||
If you have a ChatGPT Plus or Pro subscription, select **"Sign in with ChatGPT Subscription"**. This uses OpenAI's Codex OAuth to authenticate with your existing subscription.
|
||||
|
||||
#### Option 3: Import from Existing Tools
|
||||
|
||||
Already using another AI coding CLI? Cline can import your existing configuration:
|
||||
|
||||
- **Import from Codex CLI** - Imports credentials from `~/.codex/auth.json`
|
||||
- **Import from OpenCode** - Imports configuration from `~/.local/share/opencode/auth.json`
|
||||
|
||||
#### Option 4: Bring Your Own API Key
|
||||
|
||||
Select **"Bring your own API key"** to manually configure any supported provider. Or skip the wizard entirely with flags:
|
||||
|
||||
```bash
|
||||
# Anthropic (Claude)
|
||||
cline auth -p anthropic -k sk-ant-api-xxxxx -m claude-sonnet-4-5-20250929
|
||||
|
||||
# OpenAI
|
||||
cline auth -p openai-native -k sk-xxxxx -m gpt-4o
|
||||
|
||||
# OpenRouter
|
||||
cline auth -p openrouter -k sk-or-xxxxx -m anthropic/claude-sonnet-4-5-20250929
|
||||
|
||||
# OpenAI-compatible provider with custom base URL
|
||||
cline auth -p openai -k your-api-key -b https://api.example.com/v1
|
||||
```
|
||||
|
||||
**Quick Setup Flags:**
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-p, --provider <id>` | Provider ID (e.g., `anthropic`, `openai-native`, `openrouter`) |
|
||||
| `-k, --apikey <key>` | Your API key |
|
||||
| `-m, --modelid <id>` | Model ID (e.g., `claude-sonnet-4-5-20250929`, `gpt-4o`) |
|
||||
| `-b, --baseurl <url>` | Base URL for OpenAI-compatible providers |
|
||||
|
||||
<Tip>
|
||||
Flags are especially useful for scripting, CI/CD environments, or setting up multiple machines.
|
||||
</Tip>
|
||||
|
||||
#### Supported Providers
|
||||
|
||||
| Provider | Provider ID | Notes |
|
||||
|----------|-------------|-------|
|
||||
| Anthropic | `anthropic` | Direct Claude API access |
|
||||
| OpenAI | `openai-native` | GPT-4o, GPT-4, etc. |
|
||||
| OpenAI Codex | `openai-codex` | ChatGPT subscription OAuth |
|
||||
| OpenRouter | `openrouter` | Access multiple providers |
|
||||
| AWS Bedrock | `bedrock` | Claude via AWS |
|
||||
| Google Gemini | `gemini` | Gemini Pro, etc. |
|
||||
| X AI (Grok) | `xai` | Grok models |
|
||||
| Cerebras | `cerebras` | Fast inference |
|
||||
| DeepSeek | `deepseek` | DeepSeek models |
|
||||
| Ollama | `ollama` | Local models |
|
||||
| LM Studio | `lmstudio` | Local models |
|
||||
| OpenAI Compatible | `openai` | Any OpenAI-compatible API |
|
||||
|
||||
### Verify Your Setup
|
||||
|
||||
Confirm everything is working with a simple test:
|
||||
|
||||
```bash
|
||||
cline "What is 2 + 2?"
|
||||
```
|
||||
|
||||
If Cline responds with an answer, your installation and authentication are complete.
|
||||
|
||||
Check your current configuration:
|
||||
|
||||
```bash
|
||||
cline config
|
||||
```
|
||||
|
||||
### Quick Start
|
||||
|
||||
Now you're ready to use Cline. Choose how you want to work:
|
||||
|
||||
#### Interactive Mode
|
||||
|
||||
Launch the interactive CLI for development:
|
||||
|
||||
```bash
|
||||
cline
|
||||
```
|
||||
|
||||
You'll see the Cline welcome screen. Type your task and press Enter. Use:
|
||||
- `Tab` to toggle between Plan and Act modes
|
||||
- `Shift+Tab` to enable auto-approve
|
||||
- `/help` for available commands
|
||||
|
||||
[Learn more about interactive mode →](/cline-cli/interactive-mode)
|
||||
|
||||
#### Direct Task Execution
|
||||
|
||||
Run a task directly from your shell:
|
||||
|
||||
```bash
|
||||
cline "Add error handling to utils.js"
|
||||
```
|
||||
|
||||
For non-interactive execution (perfect for scripts and CI/CD):
|
||||
|
||||
```bash
|
||||
cline -y "Run tests and fix any failures"
|
||||
```
|
||||
|
||||
[Learn more about headless mode →](/cline-cli/three-core-flows)
|
||||
|
||||
### Switching Providers
|
||||
|
||||
To change your configured provider at any time:
|
||||
|
||||
```bash
|
||||
cline auth
|
||||
```
|
||||
|
||||
You can also use the settings panel in interactive mode:
|
||||
|
||||
```bash
|
||||
cline
|
||||
# Then type: /settings
|
||||
# Navigate to the API tab
|
||||
```
|
||||
|
||||
### Updating
|
||||
|
||||
Check for updates and install the latest version:
|
||||
|
||||
```bash
|
||||
cline update
|
||||
```
|
||||
|
||||
Or update manually via npm:
|
||||
|
||||
```bash
|
||||
npm update -g cline
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### Command Not Found
|
||||
|
||||
If `cline` is not found after installation:
|
||||
|
||||
1. Ensure npm global bin is in your PATH:
|
||||
```bash
|
||||
npm bin -g
|
||||
```
|
||||
|
||||
2. Add the path to your shell configuration (`.bashrc`, `.zshrc`, etc.):
|
||||
```bash
|
||||
export PATH="$PATH:$(npm bin -g)"
|
||||
```
|
||||
|
||||
3. Restart your terminal or source your shell config.
|
||||
|
||||
#### Permission Errors
|
||||
|
||||
If you get permission errors during installation:
|
||||
|
||||
```bash
|
||||
# Option 1: Use a Node version manager (recommended)
|
||||
# nvm, fnm, or volta handle permissions automatically
|
||||
|
||||
# Option 2: Fix npm permissions
|
||||
# See: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally
|
||||
```
|
||||
|
||||
#### OAuth Flow Issues
|
||||
|
||||
If the browser doesn't open automatically during OAuth:
|
||||
1. Copy the URL from the terminal
|
||||
2. Paste it in your browser manually
|
||||
3. Complete the sign-in flow
|
||||
4. Return to the terminal
|
||||
|
||||
#### API Key Validation
|
||||
|
||||
If your API key is rejected:
|
||||
1. Verify the key is correct and hasn't expired
|
||||
2. Check that you've selected the correct provider
|
||||
3. Ensure your API account has the necessary permissions
|
||||
|
||||
**Provider-specific tips:**
|
||||
- **Anthropic**: Keys start with `sk-ant-`
|
||||
- **OpenAI**: Keys start with `sk-`
|
||||
- **AWS Bedrock**: Requires AWS credentials configured separately. See [AWS Bedrock documentation](/provider-config/aws-bedrock/api-key).
|
||||
|
||||
### Uninstallation
|
||||
|
||||
To remove Cline CLI:
|
||||
|
||||
```bash
|
||||
npm uninstall -g cline
|
||||
```
|
||||
|
||||
To also remove configuration data:
|
||||
|
||||
```bash
|
||||
rm -rf ~/.cline
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **[Interactive Mode](/cline-cli/interactive-mode)** - Master the interactive CLI with shortcuts and slash commands
|
||||
- **[Headless Mode](/cline-cli/three-core-flows)** - Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows
|
||||
- **[Configuration](/cline-cli/configuration)** - Configure settings, rules, workflows, and environment variables
|
||||
- **[CLI Reference](/cline-cli/cli-reference)** - Complete command documentation with all flags and options
|
||||
@@ -1,278 +0,0 @@
|
||||
---
|
||||
title: "Installation & Setup"
|
||||
description: "Install Cline CLI on macOS, Linux, or Windows and configure your AI provider"
|
||||
---
|
||||
|
||||
Cline CLI brings the full power of Cline to your terminal. In just a few minutes, you can install the CLI, authenticate with your preferred AI provider, and start running tasks from any directory on your machine.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Cline CLI requires **Node.js version 20 or higher**. We recommend Node.js 22 for the best experience.
|
||||
|
||||
Check your Node.js version:
|
||||
|
||||
```bash
|
||||
node --version
|
||||
```
|
||||
|
||||
If you need to install or update Node.js, visit [nodejs.org](https://nodejs.org) or use a version manager like [nvm](https://github.com/nvm-sh/nvm).
|
||||
|
||||
## Install Cline CLI
|
||||
|
||||
Install globally via npm:
|
||||
|
||||
```bash
|
||||
npm install -g cline
|
||||
```
|
||||
|
||||
Verify the installation:
|
||||
|
||||
```bash
|
||||
cline version
|
||||
```
|
||||
|
||||
<Tip>
|
||||
To install a specific version, use `npm install -g cline@2.0.0`. Check [npm](https://www.npmjs.com/package/cline) for available versions.
|
||||
</Tip>
|
||||
|
||||
## Authenticate
|
||||
|
||||
After installation, run the authentication wizard:
|
||||
|
||||
```bash
|
||||
cline auth
|
||||
```
|
||||
|
||||
This launches an interactive wizard with multiple options. Choose the method that works best for your workflow.
|
||||
|
||||
### Option 1: Sign in with Cline (Recommended)
|
||||
|
||||
Select **"Sign in with Cline"** to authenticate with your Cline account via OAuth. Your browser opens automatically to complete sign-in.
|
||||
|
||||
### Option 2: Sign in with ChatGPT Subscription
|
||||
|
||||
If you have a ChatGPT Plus or Pro subscription, select **"Sign in with ChatGPT Subscription"**. This uses OpenAI's Codex OAuth to authenticate with your existing subscription.
|
||||
|
||||
### Option 3: Import from Existing Tools
|
||||
|
||||
Already using another AI coding CLI? Cline can import your existing configuration:
|
||||
|
||||
- **Import from Codex CLI** - Imports credentials from `~/.codex/auth.json`
|
||||
- **Import from OpenCode** - Imports configuration from `~/.local/share/opencode/auth.json`
|
||||
|
||||
### Option 4: Bring Your Own API Key
|
||||
|
||||
Select **"Bring your own API key"** to manually configure any supported provider. Or skip the wizard entirely with flags:
|
||||
|
||||
```bash
|
||||
# Anthropic (Claude)
|
||||
cline auth -p anthropic -k sk-ant-api-xxxxx -m claude-sonnet-4-5-20250929
|
||||
|
||||
# OpenAI
|
||||
cline auth -p openai-native -k sk-xxxxx -m gpt-4o
|
||||
|
||||
# OpenRouter
|
||||
cline auth -p openrouter -k sk-or-xxxxx -m anthropic/claude-sonnet-4-5-20250929
|
||||
|
||||
# Moonshot
|
||||
cline auth -p moonshot -k sk-xxxxx -m kimi-k2.5
|
||||
|
||||
# OpenAI-compatible provider with custom base URL
|
||||
cline auth -p openai -k your-api-key -b https://api.example.com/v1
|
||||
```
|
||||
|
||||
**Quick Setup Flags:**
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-p, --provider <id>` | Provider ID (e.g., `anthropic`, `openai-native`, `openrouter`, `moonshot`) |
|
||||
| `-k, --apikey <key>` | Your API key |
|
||||
| `-m, --modelid <id>` | Model ID (e.g., `claude-sonnet-4-5-20250929`, `gpt-4o`) |
|
||||
| `-b, --baseurl <url>` | Base URL for OpenAI-compatible providers |
|
||||
|
||||
<Tip>
|
||||
Flags are especially useful for scripting, CI/CD environments, or setting up multiple machines.
|
||||
</Tip>
|
||||
|
||||
### Supported Providers
|
||||
|
||||
| Provider | Provider ID | Notes |
|
||||
|----------|-------------|-------|
|
||||
| Anthropic | `anthropic` | Direct Claude API access |
|
||||
| OpenAI | `openai-native` | GPT-4o, GPT-4, etc. |
|
||||
| OpenAI Codex | `openai-codex` | ChatGPT subscription OAuth |
|
||||
| OpenRouter | `openrouter` | Access multiple providers |
|
||||
| AWS Bedrock | `bedrock` | Claude via AWS |
|
||||
| Google Gemini | `gemini` | Gemini Pro, etc. |
|
||||
| X AI (Grok) | `xai` | Grok models |
|
||||
| Cerebras | `cerebras` | Fast inference |
|
||||
| DeepSeek | `deepseek` | DeepSeek models |
|
||||
| Moonshot | `moonshot` | Kimi models via Moonshot AI |
|
||||
| Ollama | `ollama` | Local models |
|
||||
| LM Studio | `lmstudio` | Local models |
|
||||
| OpenAI Compatible | `openai` | Any OpenAI-compatible API |
|
||||
|
||||
## Verify Your Setup
|
||||
|
||||
Confirm everything is working with a simple test:
|
||||
|
||||
```bash
|
||||
cline "What is 2 + 2?"
|
||||
```
|
||||
|
||||
If Cline responds with an answer, your installation and authentication are complete.
|
||||
|
||||
Check your current configuration:
|
||||
|
||||
```bash
|
||||
cline config
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
Now you're ready to use Cline. Choose how you want to work:
|
||||
|
||||
### Interactive Mode
|
||||
|
||||
Launch the interactive CLI for development:
|
||||
|
||||
```bash
|
||||
cline
|
||||
```
|
||||
|
||||
You'll see the Cline welcome screen. Type your task and press Enter. Use:
|
||||
- `Tab` to toggle between Plan and Act modes
|
||||
- `Shift+Tab` to enable auto-approve
|
||||
- `/help` for available commands
|
||||
|
||||
[Learn more about interactive mode →](/cline-cli/interactive-mode)
|
||||
|
||||
### Direct Task Execution
|
||||
|
||||
Run a task directly from your shell:
|
||||
|
||||
```bash
|
||||
cline "Add error handling to utils.js"
|
||||
```
|
||||
|
||||
For non-interactive execution (perfect for scripts and CI/CD):
|
||||
|
||||
```bash
|
||||
cline -y "Run tests and fix any failures"
|
||||
```
|
||||
|
||||
[Learn more about headless mode →](/cline-cli/three-core-flows)
|
||||
|
||||
## Switching Providers
|
||||
|
||||
To change your configured provider at any time:
|
||||
|
||||
```bash
|
||||
cline auth
|
||||
```
|
||||
|
||||
You can also use the settings panel in interactive mode:
|
||||
|
||||
```bash
|
||||
cline
|
||||
# Then type: /settings
|
||||
# Navigate to the API tab
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
Check for updates and install the latest version:
|
||||
|
||||
```bash
|
||||
cline update
|
||||
```
|
||||
|
||||
Or update manually via npm:
|
||||
|
||||
```bash
|
||||
npm update -g cline
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Command Not Found
|
||||
|
||||
If `cline` is not found after installation:
|
||||
|
||||
1. Ensure npm global bin is in your PATH:
|
||||
```bash
|
||||
npm bin -g
|
||||
```
|
||||
|
||||
2. Add the path to your shell configuration (`.bashrc`, `.zshrc`, etc.):
|
||||
```bash
|
||||
export PATH="$PATH:$(npm bin -g)"
|
||||
```
|
||||
|
||||
3. Restart your terminal or source your shell config.
|
||||
|
||||
### Permission Errors
|
||||
|
||||
If you get permission errors during installation:
|
||||
|
||||
```bash
|
||||
# Option 1: Use a Node version manager (recommended)
|
||||
# nvm, fnm, or volta handle permissions automatically
|
||||
|
||||
# Option 2: Fix npm permissions
|
||||
# See: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally
|
||||
```
|
||||
|
||||
### OAuth Flow Issues
|
||||
|
||||
If the browser doesn't open automatically during OAuth:
|
||||
1. Copy the URL from the terminal
|
||||
2. Paste it in your browser manually
|
||||
3. Complete the sign-in flow
|
||||
4. Return to the terminal
|
||||
|
||||
### API Key Validation
|
||||
|
||||
If your API key is rejected:
|
||||
1. Verify the key is correct and hasn't expired
|
||||
2. Check that you've selected the correct provider
|
||||
3. Ensure your API account has the necessary permissions
|
||||
|
||||
**Provider-specific tips:**
|
||||
- **Anthropic**: Keys start with `sk-ant-`
|
||||
- **OpenAI**: Keys start with `sk-`
|
||||
- **AWS Bedrock**: Requires AWS credentials configured separately. See [AWS Bedrock documentation](/provider-config/aws-bedrock/api-key).
|
||||
|
||||
## Uninstallation
|
||||
|
||||
To remove Cline CLI:
|
||||
|
||||
```bash
|
||||
npm uninstall -g cline
|
||||
```
|
||||
|
||||
To also remove configuration data:
|
||||
|
||||
```bash
|
||||
rm -rf ~/.cline
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Interactive Mode" icon="terminal" href="/cline-cli/interactive-mode">
|
||||
Master the interactive CLI with shortcuts and slash commands.
|
||||
</Card>
|
||||
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
|
||||
<Card title="Configuration" icon="gear" href="/cline-cli/configuration">
|
||||
Configure settings, rules, workflows, and environment variables.
|
||||
</Card>
|
||||
|
||||
<Card title="CLI Reference" icon="book" href="/cline-cli/cli-reference">
|
||||
Complete command documentation with all flags and options.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -1,252 +0,0 @@
|
||||
---
|
||||
title: "Interactive Mode"
|
||||
description: "Master the interactive CLI with keyboard shortcuts, slash commands, and file mentions"
|
||||
---
|
||||
|
||||
Interactive mode is the primary way to work with Cline CLI when you want a collaborative, conversational experience. Unlike headless mode (which runs a single task and exits), interactive mode keeps a session open where you can have back-and-forth conversations with Cline, refine your requests, and guide the AI as it works.
|
||||
|
||||
## Why Use Interactive Mode?
|
||||
|
||||
Interactive mode is ideal when you:
|
||||
|
||||
- **Don't know exactly what you need yet** - Explore a codebase, ask questions, and let Cline help you understand the architecture before making changes
|
||||
- **Want to review before acting** - Toggle Plan mode to see Cline's strategy, then switch to Act mode when you're ready
|
||||
- **Need iterative refinement** - Build on previous responses, ask follow-up questions, and guide Cline to the right solution
|
||||
- **Prefer human oversight** - Review each action, approve file changes, and maintain control over what Cline does
|
||||
- **Working on complex tasks** - Multi-step refactoring, debugging sessions, or feature development that requires judgment calls
|
||||
|
||||
For automated workflows, scripts, or CI/CD pipelines, see [headless mode](/cline-cli/overview#headless-mode-non-interactive) instead.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before using interactive mode, you need to have Cline CLI installed and authenticated. If you haven't done this yet, follow the [Installation & Setup guide](/cline-cli/installation) first.
|
||||
|
||||
## Launching Interactive Mode
|
||||
|
||||
Start interactive mode by running `cline` without any arguments:
|
||||
|
||||
```bash
|
||||
cline
|
||||
```
|
||||
|
||||
You'll see an animated welcome screen with the Cline robot. Start typing your task in the input field at the bottom of the screen.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
Keyboard shortcuts are the primary way to navigate and control the interactive CLI. Since there's no mouse interaction in the terminal, learning these shortcuts will help you work efficiently and switch between modes, manage input, and control your session without breaking your flow.
|
||||
|
||||
### Mode Controls
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Tab` | Toggle between Plan and Act mode |
|
||||
| `Shift+Tab` | Toggle auto-approve all actions |
|
||||
| `Esc` | Exit or cancel current operation |
|
||||
|
||||
### Input Controls
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Enter` | Submit your message |
|
||||
| `↑` / `↓` | Navigate message history |
|
||||
| `Home` / `End` | Move cursor to start/end of line |
|
||||
| `Ctrl+A` | Move cursor to beginning |
|
||||
| `Ctrl+E` | Move cursor to end |
|
||||
| `Ctrl+W` | Delete word before cursor |
|
||||
| `Ctrl+U` | Delete entire line |
|
||||
|
||||
### Session Controls
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Ctrl+C` | Exit with session summary |
|
||||
|
||||
## File Mentions with @
|
||||
|
||||
Reference files from your workspace by typing `@` followed by the filename:
|
||||
|
||||
```text
|
||||
@src/utils.ts can you add error handling to this file?
|
||||
```
|
||||
|
||||
As you type after `@`, Cline shows a fuzzy search dropdown of matching files. Use arrow keys to navigate and `Enter` to select.
|
||||
|
||||
<Tip>
|
||||
File search uses ripgrep for fast, fuzzy matching. You can type partial paths like `@utils` to find `src/utils/helpers.ts`.
|
||||
</Tip>
|
||||
|
||||
### Multiple File Mentions
|
||||
|
||||
Include multiple files in a single message:
|
||||
|
||||
```text
|
||||
Compare @src/old-api.ts with @src/new-api.ts and list the breaking changes
|
||||
```
|
||||
|
||||
## Slash Commands
|
||||
|
||||
Type `/` to see available commands. Slash commands provide quick access to settings, history, and workflows.
|
||||
|
||||
### Built-in Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/settings` | Open the settings panel |
|
||||
| `/models` | Quick model switching |
|
||||
| `/history` | Browse and resume previous tasks |
|
||||
| `/clear` | Start a fresh task (clears current conversation) |
|
||||
| `/help` | Show help and available commands |
|
||||
| `/exit` | Exit the CLI |
|
||||
|
||||
### Workflow Commands
|
||||
|
||||
If you have [workflows](/customization/workflows) configured, they appear as additional slash commands. For example, if you have a workflow named `code-review`, you can invoke it with:
|
||||
|
||||
```text
|
||||
/code-review
|
||||
```
|
||||
|
||||
## Settings Panel
|
||||
|
||||
Access the settings panel with `/settings`. Navigate between tabs using arrow keys.
|
||||
|
||||
| Tab | Description | Settings |
|
||||
|-----|-------------|----------|
|
||||
| **API** | Configure your AI provider and model | Provider selection, model choice, extended thinking toggle, thinking budget |
|
||||
| **Auto-approve** | Control which actions Cline can perform without prompting | Read files, write files, execute commands, browser actions, MCP tools |
|
||||
| **Features** | Toggle Cline capabilities | Hooks, skills, auto-compact, sound notifications |
|
||||
| **Account** | Manage your Cline account | View account status, sign in/out, manage subscription |
|
||||
| **Other** | Additional preferences | Theme preferences, debug options |
|
||||
|
||||
## Plan and Act Modes
|
||||
|
||||
Cline operates in two modes, toggled with `Tab`. These modes work the same way in the CLI as they do in the VS Code extension. For a deeper explanation of how Plan and Act modes work, see the [Plan and Act documentation](/core-workflows/plan-and-act).
|
||||
|
||||
### Plan Mode
|
||||
|
||||
In Plan mode, Cline analyzes your request and creates a strategy before making changes. Use this when:
|
||||
- Exploring a new codebase
|
||||
- Working on complex refactoring
|
||||
- You want to review the approach first
|
||||
|
||||
### Act Mode
|
||||
|
||||
In Act mode, Cline executes tasks directly. Use this when:
|
||||
- You're confident in the task
|
||||
- Making straightforward changes
|
||||
- Running quick operations
|
||||
|
||||
<Tip>
|
||||
Press `Tab` anytime to switch modes. Starting in Plan mode and switching to Act after reviewing is a common workflow.
|
||||
</Tip>
|
||||
|
||||
## Auto-approve Toggle
|
||||
|
||||
Press `Shift+Tab` to toggle auto-approve for all actions. This removes the approval prompts that appear before each action, letting Cline work continuously without interruption.
|
||||
|
||||
### When to Enable Auto-approve
|
||||
|
||||
Auto-approve is useful when:
|
||||
- **You trust the task** - Well-defined tasks where you're confident in the outcome
|
||||
- **Speed matters** - Long-running tasks where constant approvals slow you down
|
||||
- **You're watching anyway** - You can see Cline's work in real-time and can interrupt if needed
|
||||
- **Iterating quickly** - Rapid prototyping where you want to see results fast
|
||||
|
||||
### What Gets Auto-approved
|
||||
|
||||
When enabled, these actions happen without prompting:
|
||||
- File reads
|
||||
- File writes
|
||||
- Command execution
|
||||
- Browser actions
|
||||
- MCP tool calls
|
||||
|
||||
You can also configure granular auto-approve settings (e.g., auto-approve reads but not writes) via `/settings` → Auto-approve tab, or see the [Auto-approve documentation](/features/auto-approve) for more details.
|
||||
|
||||
<Warning>
|
||||
Auto-approve gives Cline full autonomy. Use on a clean git branch so you can easily revert changes if needed. You can always press `Ctrl+C` to stop Cline immediately.
|
||||
</Warning>
|
||||
|
||||
## Session Summary
|
||||
|
||||
When you exit with `Ctrl+C`, Cline displays a session summary showing:
|
||||
- Tasks completed
|
||||
- Files modified
|
||||
- Commands executed
|
||||
- Token usage
|
||||
|
||||
This helps you track what was accomplished during your session.
|
||||
|
||||
## Running Multiple Instances
|
||||
|
||||
By default, all CLI instances share the same settings and state. However, you may want to run isolated instances with separate configurations for scenarios like:
|
||||
|
||||
- **Different models for different tasks** - Use a fast, cheap model for quick questions in one terminal and a more capable model for complex refactoring in another
|
||||
- **Separate work and personal projects** - Keep API keys, rules, and task history isolated between contexts
|
||||
- **Testing configuration changes** - Experiment with new settings without affecting your main setup
|
||||
- **Team vs. individual settings** - Use shared team configuration for work projects and personal preferences for side projects
|
||||
|
||||
To run isolated instances, use the `--config` flag with different directories:
|
||||
|
||||
```bash
|
||||
# Work instance with team configuration
|
||||
cline --config ~/.cline-work
|
||||
|
||||
# Personal instance with different model/provider
|
||||
cline --config ~/.cline-personal
|
||||
|
||||
# Experimental instance for testing new settings
|
||||
cline --config ~/.cline-test
|
||||
```
|
||||
|
||||
Each config directory maintains its own provider settings, API keys, task history, and preferences.
|
||||
|
||||
<Tip>
|
||||
Use terminal multiplexers like tmux or split terminals to run multiple Cline instances in parallel, each working on different parts of your project with different models or settings.
|
||||
</Tip>
|
||||
|
||||
## Tips for Effective Usage
|
||||
|
||||
### Start with Context
|
||||
|
||||
Give Cline context about what you're working on:
|
||||
|
||||
```text
|
||||
I'm building a REST API with Express. The routes are in @src/routes/ and models in @src/models/. Help me add user authentication.
|
||||
```
|
||||
|
||||
### Use Plan Mode for Exploration
|
||||
|
||||
When you're unsure about the best approach:
|
||||
|
||||
```text
|
||||
[Tab to Plan mode]
|
||||
How should I structure the database schema for a multi-tenant SaaS app?
|
||||
```
|
||||
|
||||
### Iterate with Follow-ups
|
||||
|
||||
The interactive CLI maintains conversation context. Build on previous messages:
|
||||
|
||||
```text
|
||||
> Add a login endpoint
|
||||
[Cline creates the endpoint]
|
||||
|
||||
> Now add rate limiting to it
|
||||
[Cline modifies the same endpoint]
|
||||
|
||||
> Add tests for both features
|
||||
[Cline creates test files]
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
|
||||
<Card title="Configuration" icon="gear" href="/cline-cli/configuration">
|
||||
Explore `cline config` and advanced configuration options.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -1,246 +0,0 @@
|
||||
---
|
||||
title: "Overview"
|
||||
description: "Run Cline AI coding agents directly in your terminal with an interactive CLI or automated workflows"
|
||||
---
|
||||
|
||||
## What is Cline CLI?
|
||||
|
||||
Cline CLI brings the full power of Cline to your terminal. Whether you prefer an interactive experience or automated workflows for CI/CD pipelines, the CLI adapts to your needs.
|
||||
|
||||
The CLI supports macOS, Linux, and Windows, and works with all the same AI providers as the VS Code extension.
|
||||
|
||||
<Tip>
|
||||
Ready to get started? Check out the [installation guide](/cline-cli/installation) to install Cline CLI and run your first task.
|
||||
</Tip>
|
||||
|
||||
## Two Ways to Use Cline CLI
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Interactive Mode" icon="terminal" href="/cline-cli/interactive-mode">
|
||||
**For hands-on development.** Launch `cline` in your terminal and collaborate with Cline in real-time — chat, review plans, approve actions, and iterate on tasks with a rich visual interface.
|
||||
</Card>
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
**For automation & CI/CD.** Run `cline -y "task"` to let Cline work autonomously — no interaction needed. Pipe input/output, get JSON results, and chain commands in scripts and pipelines.
|
||||
</Card>
|
||||
</Columns>
|
||||
|
||||
The CLI operates in two distinct modes, automatically selecting the appropriate one based on how you invoke it:
|
||||
|
||||
### Interactive Mode
|
||||
|
||||
Interactive mode is designed for **hands-on development sessions** where you want to collaborate with Cline in real-time. It provides a rich terminal interface that feels like chatting with an AI assistant.
|
||||
|
||||
**When it activates:** Running `cline` without arguments, or when stdin is a TTY (terminal).
|
||||
|
||||
```bash
|
||||
cline
|
||||
```
|
||||
|
||||
Key features:
|
||||
|
||||
- **Real-time conversation** - Type messages, see Cline's responses, and iterate on tasks
|
||||
- **Visual feedback** - Animated welcome screen, syntax-highlighted code, and progress indicators
|
||||
- **File mentions** with `@` - Reference workspace files with fuzzy search autocomplete
|
||||
- **Slash commands** with `/` - Quick access to `/settings`, `/history`, `/models`, and workflows
|
||||
- **Keyboard shortcuts** - `Tab` to toggle Plan/Act, `Shift+Tab` for auto-approve all
|
||||
- **Session summaries** - See tasks completed, files modified, and token usage on exit
|
||||
- **Settings panel** - Configure providers, models, and features without leaving the CLI
|
||||
|
||||
Interactive mode keeps you in control. You review Cline's plan, approve or modify actions, and guide the conversation.
|
||||
|
||||
[Learn more about interactive mode →](/cline-cli/interactive-mode)
|
||||
|
||||
### Headless Mode (Non-Interactive)
|
||||
|
||||
Headless mode is designed for **automation, scripting, and CI/CD pipelines** where human interaction isn't possible or desired.
|
||||
|
||||
**When it activates:** Using the `-y`/`--yolo` flag, `--json` flag, piping input/output, or when stdin is not a TTY.
|
||||
|
||||
```bash
|
||||
# Headless with auto-approval (YOLO mode)
|
||||
cline -y "Run tests and fix any failures"
|
||||
|
||||
# Headless with JSON output for parsing
|
||||
cline --json "List all TODO comments" | jq '.text'
|
||||
|
||||
# Headless via piped input
|
||||
cat README.md | cline "Summarize this document"
|
||||
|
||||
# Chain multiple headless commands
|
||||
git diff | cline -y "explain these changes" | cline -y "write a commit message"
|
||||
```
|
||||
|
||||
Key features:
|
||||
|
||||
- **No visual interface** - Clean text or JSON output suitable for scripting
|
||||
- **Automatic execution** - With `-y`, Cline approves all actions and runs autonomously
|
||||
- **Process control** - Exits automatically when the task completes
|
||||
- **Piped workflows** - Read from stdin, write to stdout, chain with other commands
|
||||
- **Machine-readable output** - Use `--json` to get structured output for parsing
|
||||
|
||||
<Warning>
|
||||
Headless mode with `-y` gives Cline full autonomy. Run on a clean git branch so you can easily revert changes if needed.
|
||||
</Warning>
|
||||
|
||||
### Mode Detection Summary
|
||||
|
||||
Cline automatically detects which mode to use based on your invocation. This table shows how different command patterns trigger each mode, helping you predict behavior in scripts and interactive sessions.
|
||||
|
||||
| Invocation | Mode | Reason |
|
||||
|------------|------|--------|
|
||||
| `cline` | Interactive | No arguments, TTY connected |
|
||||
| `cline "task"` | Interactive | TTY connected |
|
||||
| `cline -y "task"` | Headless | YOLO flag forces headless |
|
||||
| `cline --json "task"` | Headless | JSON flag forces headless |
|
||||
| `cat file \| cline "task"` | Headless | stdin is piped |
|
||||
| `cline "task" > output.txt` | Headless | stdout is redirected |
|
||||
|
||||
[Learn more about headless mode →](/cline-cli/three-core-flows)
|
||||
|
||||
## Supported Model Providers
|
||||
|
||||
Cline CLI supports all providers available in the VS Code extension:
|
||||
|
||||
- **Anthropic** (Claude)
|
||||
- **OpenAI** (GPT-4o, GPT-4)
|
||||
- **OpenAI Codex** (ChatGPT subscription)
|
||||
- **OpenRouter**
|
||||
- **AWS Bedrock**
|
||||
- **Google Gemini**
|
||||
- **X AI (Grok)**
|
||||
- **Cerebras**
|
||||
- **DeepSeek**
|
||||
- **Ollama** (local models)
|
||||
- **LM Studio** (local models)
|
||||
- **OpenAI Compatible** (any compatible API)
|
||||
|
||||
During setup, authenticate with `cline auth` to configure your preferred provider. [See setup guide →](/cline-cli/installation#authenticate)
|
||||
|
||||
## What You Can Build
|
||||
|
||||
### Automated Code Maintenance
|
||||
|
||||
Keep your codebase healthy with automated fixes. Cline scans for issues and applies corrections across multiple files.
|
||||
|
||||
```bash
|
||||
cline -y "Fix all ESLint errors in src/"
|
||||
```
|
||||
Finds and fixes linting violations throughout your source directory.
|
||||
|
||||
```bash
|
||||
cline -y "Update all deprecated React lifecycle methods"
|
||||
```
|
||||
Migrates legacy code patterns to modern equivalents (e.g., `componentWillMount` → `useEffect`).
|
||||
|
||||
```bash
|
||||
cline -y "Update dependencies with known vulnerabilities"
|
||||
```
|
||||
Identifies outdated packages with security issues and updates them to safe versions.
|
||||
|
||||
### CI/CD Integration
|
||||
|
||||
Integrate Cline into your continuous integration pipelines for automated code review and documentation.
|
||||
|
||||
```bash
|
||||
git diff origin/main | cline -y "Review these changes for issues"
|
||||
```
|
||||
Pipes your PR diff to Cline for automated code review, catching bugs and style issues before merge.
|
||||
|
||||
```bash
|
||||
git log --oneline v1.0..v1.1 | cline -y "Write release notes"
|
||||
```
|
||||
Generates human-readable release notes from your commit history between two tags.
|
||||
|
||||
```bash
|
||||
cline -y "Run tests and fix failures" --timeout 600
|
||||
```
|
||||
Executes your test suite, analyzes failures, and attempts fixes with a 10-minute timeout.
|
||||
|
||||
### Development Workflows
|
||||
|
||||
From quick edits to complex refactors, Cline adapts to your workflow.
|
||||
|
||||
```bash
|
||||
cline
|
||||
```
|
||||
Launches interactive mode for exploratory development and back-and-forth collaboration.
|
||||
|
||||
```bash
|
||||
cline "Refactor this function to use async/await"
|
||||
```
|
||||
Executes a focused task directly from the command line with approval prompts at key steps.
|
||||
|
||||
```bash
|
||||
cline "Based on @src/api.ts, add error handling to all endpoints"
|
||||
```
|
||||
Uses file mentions (`@`) to give Cline context about specific files in your workspace.
|
||||
|
||||
### Custom Shell Pipelines
|
||||
|
||||
Chain Cline with other CLI tools to build powerful automation workflows.
|
||||
|
||||
```bash
|
||||
gh pr diff 123 | cline -y "Review this PR"
|
||||
```
|
||||
Fetches a GitHub PR diff and pipes it directly to Cline for review.
|
||||
|
||||
```bash
|
||||
cline --json "List all TODO comments" | jq '.text'
|
||||
```
|
||||
Outputs structured JSON that you can process with tools like `jq` for scripting.
|
||||
|
||||
```bash
|
||||
git diff | cline -y "explain" | cline -y "write a haiku about these changes"
|
||||
```
|
||||
Chains multiple Cline invocations together for creative multi-step workflows.
|
||||
|
||||
## Features at a Glance
|
||||
|
||||
| Feature | Interactive Mode | Non-Interactive Mode |
|
||||
|---------|------------------|----------------------|
|
||||
| Interactive chat | ✓ | - |
|
||||
| File mentions (@) | ✓ | ✓ (inline) |
|
||||
| Slash commands (/) | ✓ | - |
|
||||
| Settings panel | ✓ | `cline config` |
|
||||
| Plan/Act toggle | ✓ (Tab) | `-p` / `-a` flags |
|
||||
| Auto-approve | ✓ (Shift+Tab) | `-y` flag |
|
||||
| Session summary | ✓ | - |
|
||||
| JSON output | - | `--json` |
|
||||
| Piped input | - | ✓ |
|
||||
| [MCP servers](/cline-cli/configuration#mcp-server-configuration) | ✓ | ✓ |
|
||||
|
||||
## MCP Server Support
|
||||
|
||||
Cline CLI supports [MCP (Model Context Protocol)](/mcp/mcp-overview) servers, the same extensibility system available in the VS Code extension. MCP servers give Cline access to external tools and data sources, from databases and APIs to browser automation and project management.
|
||||
|
||||
To use MCP servers with the CLI, add your server configuration to `~/.cline/data/settings/cline_mcp_settings.json`. The format is identical to the VS Code extension.
|
||||
|
||||
[Configure MCP servers for the CLI →](/cline-cli/configuration#mcp-server-configuration)
|
||||
|
||||
## Learn More
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Installation & Setup" icon="download" href="/cline-cli/installation">
|
||||
Install Cline CLI and authenticate with your preferred provider.
|
||||
</Card>
|
||||
|
||||
<Card title="Interactive Mode" icon="terminal" href="/cline-cli/interactive-mode">
|
||||
Master the interactive CLI with keyboard shortcuts and slash commands.
|
||||
</Card>
|
||||
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
|
||||
<Card title="Configuration" icon="gear" href="/cline-cli/configuration">
|
||||
Configure settings, rules, workflows, and environment variables.
|
||||
</Card>
|
||||
|
||||
<Card title="Use in Other Editors" icon="code" href="/cline-cli/acp-editor-integrations">
|
||||
Run Cline as an ACP agent in JetBrains, Neovim, Zed, and more.
|
||||
</Card>
|
||||
|
||||
<Card title="CLI Samples" icon="flask" href="/cline-cli/samples/overview">
|
||||
Real-world examples of headless workflows and automation patterns.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
title: "Samples Overview"
|
||||
description: Example implementations demonstrating Cline CLI capabilities
|
||||
---
|
||||
|
||||
This section provides sample implementations that demonstrate various Cline CLI features and capabilities. Each sample includes complete code, detailed explanations, and real-world usage examples.
|
||||
|
||||
## Available Samples
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<Card
|
||||
title="Model Orchestration"
|
||||
icon="layer-group"
|
||||
href="/cline-cli/samples/model-orchestration"
|
||||
>
|
||||
Use multiple AI models strategically with --config and --thinking flags. Optimize costs by routing simple tasks to cheap models and complex reasoning to premium models. Includes patterns for CI/CD code review, task phase optimization, and multi-model consensus.
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="Worktree Workflows"
|
||||
icon="code-branch"
|
||||
href="/cline-cli/samples/worktree-workflows"
|
||||
>
|
||||
Use Git worktrees with the --cwd flag to run parallel tasks, test different approaches, and pipe context between isolated environments. Includes patterns for parallel execution, cross-worktree piping, and combining with model orchestration.
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="GitHub Root Cause Analysis"
|
||||
icon="magnifying-glass-chart"
|
||||
href="/cline-cli/samples/github-issue-rca"
|
||||
>
|
||||
A command-line script that uses Cline's autonomous AI capabilities to fetch, analyze, and identify root causes of GitHub issues. Features JSON output parsing and non-interactive execution.
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="GitHub Integration (Actions)"
|
||||
icon="github"
|
||||
href="/cline-cli/samples/github-integration"
|
||||
>
|
||||
Automatically respond to GitHub issues by mentioning @cline in comments. Uses Cline CLI in GitHub Actions to create an AI-powered issue assistant that analyzes and responds autonomously.
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="GitHub PR Review (Actions)"
|
||||
icon="code-pull-request"
|
||||
href="/cline-cli/samples/github-pr-review"
|
||||
>
|
||||
Automatically review Pull Requests with AI. Configures Cline in GitHub Actions to analyze diffs, check for security issues, and post detailed reviews with inline code suggestions.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [CLI Installation Guide](/cline-cli/installation)
|
||||
- [CLI Reference Documentation](/cline-cli/cli-reference)
|
||||
- [Headless Mode](/cline-cli/three-core-flows)
|
||||
@@ -1,273 +0,0 @@
|
||||
---
|
||||
title: "Worktree Workflows"
|
||||
description: "Use Git worktrees with Cline CLI to run parallel tasks, test different approaches, and pipe context between isolated environments"
|
||||
---
|
||||
|
||||
Git worktrees let you have multiple branches checked out simultaneously in different folders. Combined with Cline CLI's `--cwd` flag, this enables powerful parallel development workflows and isolated experimentation.
|
||||
|
||||
<Tip>
|
||||
New to Git worktrees? See our comprehensive [Worktrees guide](/features/worktrees) for the full concept explanation, VS Code integration, and best practices.
|
||||
</Tip>
|
||||
|
||||
## Quick Worktree Setup
|
||||
|
||||
If you haven't used Git worktrees before, here's the essentials:
|
||||
|
||||
```bash
|
||||
# Create a new worktree in ~/worktree-a on branch feature-a
|
||||
git worktree add ~/worktree-a -b feature-a
|
||||
|
||||
# Create another worktree for a different feature
|
||||
git worktree add ~/worktree-b -b feature-b
|
||||
|
||||
# List all worktrees
|
||||
git worktree list
|
||||
|
||||
# Remove a worktree when done
|
||||
git worktree remove ~/worktree-a
|
||||
```
|
||||
|
||||
Each worktree is a separate folder with its own branch checked out. They all share the same Git history and `.git` directory, but have independent working directories.
|
||||
|
||||
## The `--cwd` Flag
|
||||
|
||||
The `-c, --cwd <path>` flag tells Cline to run in a specific directory without changing your current location:
|
||||
|
||||
```bash
|
||||
# Run Cline in a different directory
|
||||
cline --cwd ~/worktree-a -y "refactor the authentication code"
|
||||
|
||||
# Short form
|
||||
cline -c ~/worktree-b -y "add unit tests"
|
||||
```
|
||||
|
||||
This is the key to worktree workflows—you can run multiple Cline instances in different worktrees simultaneously from a single terminal.
|
||||
|
||||
## Pattern 1: Parallel Task Execution
|
||||
|
||||
Run different tasks in parallel across multiple worktrees. Each task works on a separate branch in complete isolation.
|
||||
|
||||
### Example: Parallel Feature Development
|
||||
|
||||
```bash
|
||||
# Terminal 1: Update docs in worktree-a
|
||||
cline --cwd ~/worktree-a -y "read the last 10 changes using git show and update our README with them" &
|
||||
|
||||
# Terminal 2: TypeScript migration in worktree-b
|
||||
cline --cwd ~/worktree-b -y "update the index.js to use typescript" &
|
||||
|
||||
# Terminal 3: Refactoring in worktree-c
|
||||
cline --cwd ~/worktree-c -y "refactor the cli/ folder to be more modular" &
|
||||
|
||||
# Wait for all to complete
|
||||
wait
|
||||
```
|
||||
|
||||
The `&` runs each command in the background, allowing all three to execute simultaneously.
|
||||
|
||||
### When to Use Parallel Execution
|
||||
|
||||
**Perfect for:**
|
||||
- Multiple independent features
|
||||
- Bulk refactoring across different modules
|
||||
- Running tests in one worktree while developing in another
|
||||
- Trying multiple approaches to the same problem
|
||||
|
||||
**Not ideal for:**
|
||||
- Tasks that modify the same files (merge conflicts likely)
|
||||
- Tasks that depend on each other's results
|
||||
- When you need to monitor progress closely
|
||||
|
||||
## Pattern 2: Cross-Worktree Context Piping
|
||||
|
||||
Pipe output from one worktree as input to another. Use when a task in one worktree needs context from attempts in another worktree.
|
||||
|
||||
### Example: Learning from Failures
|
||||
|
||||
```bash
|
||||
# Try approach A in worktree-a, capture only the failure summary
|
||||
cline --cwd ~/worktree-a -y \
|
||||
"edit the index.ts to be better and then npm run. if it fails, output ONLY the failure summary. nothing else but the failure summary" \
|
||||
| cline --cwd ~/worktree-b -y \
|
||||
"i've tried to edit the index.ts in a different worktree but it failed. use a different approach for this work tree"
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
1. First Cline instance runs in `worktree-a`, attempts a change, tests it
|
||||
2. If it fails, outputs just the failure summary
|
||||
3. That summary is piped to a second Cline instance in `worktree-b`
|
||||
4. Second instance sees the failure and tries a different approach
|
||||
|
||||
### When to Use Context Piping
|
||||
|
||||
**Perfect for:**
|
||||
- A/B testing different solutions
|
||||
- Learning from failed attempts
|
||||
- Iterative refinement (try → analyze → try differently)
|
||||
- Comparing outputs across approaches
|
||||
|
||||
**Not ideal for:**
|
||||
- Simple tasks that don't need cross-context
|
||||
- When both worktrees would succeed independently
|
||||
- Real-time collaboration (use parallel execution instead)
|
||||
|
||||
## Combining with Other CLI Features
|
||||
|
||||
### Different Models Per Worktree
|
||||
|
||||
Use `--config` to run different models in different worktrees:
|
||||
|
||||
```bash
|
||||
# Cheap model for simple docs update
|
||||
cline --cwd ~/worktree-docs --config ~/.cline-haiku -y \
|
||||
"update README with latest changes"
|
||||
|
||||
# Expensive model for complex refactoring
|
||||
cline --cwd ~/worktree-refactor --config ~/.cline-opus --thinking -y \
|
||||
"refactor authentication system for better security"
|
||||
```
|
||||
|
||||
This optimizes costs while maintaining quality where it matters.
|
||||
|
||||
### Task Isolation
|
||||
|
||||
Keep long-running worktree sessions isolated by running each task against a different worktree path:
|
||||
|
||||
```bash
|
||||
# Run tasks in dedicated worktrees
|
||||
cline --cwd ~/worktree-a -y "long-running task"
|
||||
cline --cwd ~/worktree-b -y "another task"
|
||||
```
|
||||
|
||||
Each worktree has its own Git branch and working directory, so task history and changes stay separated without needing instance management.
|
||||
|
||||
### With YOLO Mode
|
||||
|
||||
The `-y` (YOLO) flag is essential for worktree workflows:
|
||||
|
||||
```bash
|
||||
# Without -y: Opens interactive chat (blocks other tasks)
|
||||
cline --cwd ~/worktree-a "refactor code"
|
||||
|
||||
# With -y: Runs autonomously (doesn't block)
|
||||
cline --cwd ~/worktree-a -y "refactor code" &
|
||||
```
|
||||
|
||||
For parallel execution, always use `-y` to avoid blocking on user approval.
|
||||
|
||||
## Real-World Workflow Example
|
||||
|
||||
Here's a complete workflow showing how these patterns work together:
|
||||
|
||||
```bash
|
||||
# Setup: Create three worktrees
|
||||
git worktree add ~/cline-worktrees/feature-auth -b feature/authentication
|
||||
git worktree add ~/cline-worktrees/feature-api -b feature/api-endpoints
|
||||
git worktree add ~/cline-worktrees/fix-tests -b fix/failing-tests
|
||||
|
||||
# Pattern 1: Run parallel independent tasks
|
||||
cline -c ~/cline-worktrees/feature-auth -y --config ~/.cline-sonnet \
|
||||
"implement JWT authentication" &
|
||||
|
||||
cline -c ~/cline-worktrees/feature-api -y --config ~/.cline-sonnet \
|
||||
"create REST API endpoints for user management" &
|
||||
|
||||
cline -c ~/cline-worktrees/fix-tests -y --config ~/.cline-haiku \
|
||||
"fix all failing unit tests" &
|
||||
|
||||
wait
|
||||
echo "All parallel tasks complete!"
|
||||
|
||||
# Pattern 2: Use piping for iterative refinement
|
||||
cline -c ~/cline-worktrees/feature-auth -y \
|
||||
"test the authentication with curl. output only errors if any" \
|
||||
| cline -c ~/cline-worktrees/feature-auth -y \
|
||||
"fix the authentication issues described in the input"
|
||||
|
||||
# Merge successful changes back
|
||||
cd ~/cline-worktrees/feature-auth
|
||||
git checkout main
|
||||
git merge feature/authentication
|
||||
|
||||
# Cleanup
|
||||
git worktree remove ~/cline-worktrees/feature-auth
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Worktree Organization">
|
||||
- **Use a dedicated folder**: Create `~/cline-worktrees/` for all worktrees
|
||||
- **Meaningful branch names**: Use `feature/`, `fix/`, `refactor/` prefixes
|
||||
- **Clean up regularly**: Remove worktrees after merging branches
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Isolation">
|
||||
- **Independent features only**: Don't parallelize tasks that touch the same files
|
||||
- **Test in isolation**: Each worktree should have its own test run
|
||||
- **Separate configs**: Use `.worktreeinclude` to copy `node_modules` and build artifacts
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Resource Management">
|
||||
- **Monitor disk space**: Each worktree is a full checkout
|
||||
- **Limit parallel tasks**: Running too many simultaneously can slow your system
|
||||
- **Use background jobs wisely**: Track with `jobs` command, kill with `kill %1`, etc.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Error Handling">
|
||||
- **Check exit codes**: Use `|| echo "Task failed"` to catch errors
|
||||
- **Log outputs**: Redirect to files for debugging: `> worktree-a.log 2>&1`
|
||||
- **Graceful cleanup**: Always remove worktrees after tasks complete
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title=""Branch already checked out" error">
|
||||
Git doesn't allow the same branch in multiple worktrees. Solutions:
|
||||
- Use different branch names for each worktree
|
||||
- Remove the existing worktree first: `git worktree remove <path>`
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Tasks not running in parallel">
|
||||
Make sure you're using:
|
||||
- `&` at the end of each command to background it
|
||||
- `-y` flag so Cline doesn't wait for approval
|
||||
- Different worktrees (not the same path)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Pipe not working as expected">
|
||||
Verify:
|
||||
- First command outputs to stdout (not stderr)
|
||||
- Second command reads from stdin (use `--` separator if needed)
|
||||
- Both commands use correct `--cwd` paths
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Changes not appearing in worktree">
|
||||
Check:
|
||||
- You're in the right worktree: `git worktree list`
|
||||
- Files aren't gitignored
|
||||
- You committed/staged changes if needed
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Related Documentation
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Worktrees Overview" icon="code-branch" href="/features/worktrees">
|
||||
Complete guide to Git worktrees, VS Code integration, and .worktreeinclude
|
||||
</Card>
|
||||
|
||||
<Card title="Model Orchestration" icon="layer-group" href="/cline-cli/samples/model-orchestration">
|
||||
Use different models strategically with --config and --thinking flags
|
||||
</Card>
|
||||
|
||||
<Card title="CLI Reference" icon="terminal" href="/cline-cli/cli-reference">
|
||||
Complete documentation for --cwd and all other CLI flags
|
||||
</Card>
|
||||
|
||||
<Card title="Headless Mode" icon="robot" href="/cline-cli/three-core-flows">
|
||||
Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -1,244 +0,0 @@
|
||||
---
|
||||
title: "Headless Mode"
|
||||
description: "Run Cline autonomously in scripts, CI/CD pipelines, and automated workflows"
|
||||
---
|
||||
|
||||
Headless mode runs Cline without an interactive interface — perfect for automation, scripting, and CI/CD pipelines where human interaction isn't possible or desired. Cline executes tasks, produces clean text or JSON output, and exits when complete.
|
||||
|
||||
For collaborative, conversational development, see [Interactive Mode](/cline-cli/interactive-mode) instead.
|
||||
|
||||
<Note>
|
||||
**Migrating from an older CLI version?** Instance commands (`cline instance new/list/kill`) have been removed in Cline CLI 2.0. The new architecture is simpler — just use `cline -y "task"` for headless execution.
|
||||
</Note>
|
||||
|
||||
## When Headless Mode Activates
|
||||
|
||||
Cline automatically enters headless mode when any of these conditions are met:
|
||||
|
||||
| Invocation | Reason |
|
||||
|------------|--------|
|
||||
| `cline -y "task"` | `-y`/`--yolo` flag forces headless |
|
||||
| `cline --json "task"` | `--json` flag forces headless |
|
||||
| `cat file \| cline "task"` | stdin is piped |
|
||||
| `cline "task" > output.txt` | stdout is redirected |
|
||||
|
||||
If none of these apply (e.g., running `cline` or `cline "task"` in a terminal), Cline launches in [interactive mode](/cline-cli/interactive-mode).
|
||||
|
||||
## YOLO Mode (Fully Autonomous)
|
||||
|
||||
The `-y` or `--yolo` flag enables fully autonomous operation — Cline approves all actions and runs without prompts:
|
||||
|
||||
```bash
|
||||
cline -y "Run the test suite and fix any failures"
|
||||
```
|
||||
|
||||
In YOLO mode:
|
||||
- All actions are auto-approved
|
||||
- Output is plain text (non-interactive)
|
||||
- Process exits automatically when complete
|
||||
- Perfect for CI/CD and scripts
|
||||
|
||||
<Warning>
|
||||
YOLO mode gives Cline full autonomy. Run on a clean git branch so you can easily revert changes if needed.
|
||||
</Warning>
|
||||
|
||||
### Mode Selection
|
||||
|
||||
Control whether Cline plans first or acts immediately:
|
||||
|
||||
```bash
|
||||
# Start in Plan mode (analyze before acting)
|
||||
cline -y -p "Design a REST API for user management"
|
||||
|
||||
# Start in Act mode (default)
|
||||
cline -y -a "Fix the typo in README.md"
|
||||
```
|
||||
|
||||
## Piping Context
|
||||
|
||||
Pipe file contents or command output into Cline to provide context:
|
||||
|
||||
```bash
|
||||
# Explain a file
|
||||
cat README.md | cline "Summarize this document"
|
||||
|
||||
# Review git changes
|
||||
git diff | cline "Review these changes and suggest improvements"
|
||||
|
||||
# Analyze command output
|
||||
npm test 2>&1 | cline "Analyze these test failures and fix them"
|
||||
|
||||
# Pipe a GitHub PR diff
|
||||
gh pr diff 123 | cline -y "Review this PR"
|
||||
```
|
||||
|
||||
When stdin is piped, Cline automatically enters headless mode — the piped content becomes part of the task context.
|
||||
|
||||
## Chaining Commands
|
||||
|
||||
Pipe Cline's output into another Cline instance for multi-step workflows:
|
||||
|
||||
```bash
|
||||
# Explain changes, then write a commit message
|
||||
git diff | cline -y "explain these changes" | cline -y "write a commit message for this"
|
||||
|
||||
# Generate code, then write tests
|
||||
cline -y "create a fibonacci function" | cline -y "write unit tests for this code"
|
||||
|
||||
# Fun: Generate a poem about your code
|
||||
git diff | cline -y "explain" | cline -y "write a haiku about this"
|
||||
```
|
||||
|
||||
## JSON Output
|
||||
|
||||
Use `--json` for machine-readable output that's easy to parse in scripts:
|
||||
|
||||
```bash
|
||||
cline --json "List all TODO comments in the codebase" | jq '.text'
|
||||
```
|
||||
|
||||
JSON output follows the same format as task files in `~/.cline/data/tasks/<id>/ui_messages.json`.
|
||||
|
||||
**JSON Message Schema:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `type` | `"ask"` or `"say"` | Message category |
|
||||
| `text` | `string` | Message content |
|
||||
| `ts` | `number` | Unix timestamp (ms) |
|
||||
| `reasoning` | `string` | (Optional) Model reasoning |
|
||||
| `partial` | `boolean` | (Optional) Streaming flag |
|
||||
|
||||
## Including Images
|
||||
|
||||
Attach images to your headless task:
|
||||
|
||||
```bash
|
||||
cline -y -i screenshot.png "Fix the layout issue shown in this screenshot"
|
||||
|
||||
# Or reference inline
|
||||
cline -y "Fix the UI shown in @./design-mockup.png"
|
||||
```
|
||||
|
||||
## Timeout Control
|
||||
|
||||
Set a maximum execution time to prevent runaway tasks:
|
||||
|
||||
```bash
|
||||
cline -y --timeout 600 "Run full test suite"
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Control Cline behavior via environment variables — useful for CI/CD where you can't use interactive configuration.
|
||||
|
||||
**CLINE_DIR** — Custom configuration directory:
|
||||
```bash
|
||||
export CLINE_DIR=/path/to/config
|
||||
cline -y "your task"
|
||||
```
|
||||
|
||||
**CLINE_COMMAND_PERMISSIONS** — Restrict allowed commands:
|
||||
```bash
|
||||
export CLINE_COMMAND_PERMISSIONS='{"allow": ["npm *", "git *"], "deny": ["rm -rf *"]}'
|
||||
cline -y "your task"
|
||||
```
|
||||
|
||||
See [Configuration](/cline-cli/configuration#environment-variables) for full documentation.
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
### GitHub Actions Example
|
||||
|
||||
Automate PR reviews with Cline:
|
||||
|
||||
```yaml
|
||||
name: AI Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
review:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Install Cline
|
||||
run: npm install -g cline
|
||||
|
||||
- name: Configure Cline
|
||||
run: cline auth -p anthropic -k ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
|
||||
- name: Review PR
|
||||
run: |
|
||||
git diff origin/main...HEAD | cline -y "Review this PR for:
|
||||
- Potential bugs
|
||||
- Security issues
|
||||
- Performance concerns
|
||||
- Code style violations
|
||||
|
||||
Provide a summary of findings."
|
||||
```
|
||||
|
||||
### Shell Script Example
|
||||
|
||||
Create a reusable code review script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# review.sh - AI-powered code review
|
||||
|
||||
set -e
|
||||
|
||||
# Get the diff
|
||||
DIFF=$(git diff HEAD~1)
|
||||
|
||||
if [ -z "$DIFF" ]; then
|
||||
echo "No changes to review"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run Cline review
|
||||
echo "$DIFF" | cline -y --json "Review this code diff for issues" | jq -r '.text'
|
||||
```
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
| Use Case | Example |
|
||||
|----------|---------|
|
||||
| Code review | `git diff \| cline -y "Review these changes"` |
|
||||
| Fix test failures | `cline -y "Run tests and fix any failures"` |
|
||||
| Generate release notes | `git log --oneline v1.0..v1.1 \| cline -y "Write release notes"` |
|
||||
| Fix lint errors | `cline -y "Fix all ESLint errors in src/"` |
|
||||
| Update dependencies | `cline -y "Update dependencies with known vulnerabilities"` |
|
||||
| Migrate code patterns | `cline -y "Update all deprecated React lifecycle methods"` |
|
||||
| PR automation | `gh pr diff 123 \| cline -y "Review this PR"` |
|
||||
| Batch processing | `cline -y --json "List all TODO comments" \| jq '.text'` |
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="Interactive Mode" icon="terminal" href="/cline-cli/interactive-mode">
|
||||
For hands-on development with keyboard shortcuts, slash commands, and file mentions.
|
||||
</Card>
|
||||
|
||||
<Card title="CLI Reference" icon="book" href="/cline-cli/cli-reference">
|
||||
Complete command documentation with all flags and options.
|
||||
</Card>
|
||||
|
||||
<Card title="Configuration" icon="gear" href="/cline-cli/configuration">
|
||||
Environment variables, rules, and advanced settings.
|
||||
</Card>
|
||||
|
||||
<Card title="CLI Samples" icon="flask" href="/cline-cli/samples/overview">
|
||||
Real-world examples of headless workflows and automation patterns.
|
||||
</Card>
|
||||
</Columns>
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: "Cline Overview"
|
||||
sidebarTitle: "Cline Overview"
|
||||
description: "Your AI-powered coding agent for complex work. Read files, write code, run commands, all with your approval."
|
||||
---
|
||||
|
||||
Welcome to the Cline documentation. Whether you're just getting started or looking to unlock advanced capabilities, you'll find everything you need here.
|
||||
|
||||
## What is Cline?
|
||||
|
||||
Cline is an AI coding agent that lives in your editor and your terminal. It can read and write files, run terminal commands, use a browser, and help you build features through natural conversation. Every action requires your explicit approval. You're always in control.
|
||||
### Agent Core (SDK)
|
||||
|
||||
The SDK is Cline's agent core—use it to build your own applications, automations, and integrations. See SDK section for detailed functionality and architectural design of the Cline Agent.
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<Card title="SDK" icon="cube" href="https://docs.cline.bot/sdk/overview">
|
||||
Build AI agents and integrations powered by the same core engine behind the CLI, Kanban, VS Code extension, and JetBrains plugin.
|
||||
|
||||
`npm install @cline/sdk`
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Applications
|
||||
|
||||
These are end-user applications built on top of Cline's agent core:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="CLI" icon="terminal" href="/usage/cli-overview">
|
||||
Run Cline in your terminal with interactive chat or fully headless automation for CI/CD and scripting.
|
||||
|
||||
`npm i -g cline`
|
||||
</Card>
|
||||
<Card title="Kanban" icon="table-columns" href="https://github.com/cline/kanban">
|
||||
Run many agents in parallel from a web-based task board with per-card worktrees, auto-commit, and dependency chains.
|
||||
|
||||
`npx kanban`
|
||||
</Card>
|
||||
<Card title="VS Code Extension" icon="code" href="https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev">
|
||||
AI coding assistant in your editor. Create files, run commands, browse the web, and use tools with human-in-the-loop approval.
|
||||
</Card>
|
||||
<Card title="JetBrains Plugin" icon="brain" href="https://plugins.jetbrains.com/plugin/27189-cline">
|
||||
The same Cline experience in IntelliJ IDEA, PyCharm, WebStorm, GoLand, and the rest of the JetBrains family.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
## Other IDE Supports
|
||||
|
||||
Cline works across all major editors: **VS Code**, **Cursor**, **Windsurf**, **JetBrains** (IntelliJ, PyCharm, WebStorm), **Antigravity**, and **Zed**, **Neovim** via ACP mode.
|
||||
|
||||
|
||||
## Enterprise Solutions
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Security & Governance" icon="shield-halved" href="/enterprise-solutions/overview">
|
||||
SSO, role-based access control, model and tool controls per team, and remote configuration.
|
||||
</Card>
|
||||
<Card title="Observability" icon="chart-line" href="/enterprise-solutions/monitoring/overview">
|
||||
OpenTelemetry, Datadog, Grafana, Splunk integrations with real-time analytics.
|
||||
</Card>
|
||||
<Card title="Team Management" icon="users-gear" href="/enterprise-solutions/team-management/managing-members">
|
||||
Manage members, roles, and permissions across your organization.
|
||||
</Card>
|
||||
<Card title="API Reference" icon="code" href="/enterprise-solutions/api-reference">
|
||||
Programmatic access to Cline's enterprise features.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,675 +0,0 @@
|
||||
---
|
||||
title: "Cline SDK"
|
||||
description: "Embed Cline as a programmable coding agent in your Node.js applications using an ACP-compatible TypeScript API."
|
||||
---
|
||||
|
||||
# Cline SDK
|
||||
|
||||
The Cline SDK lets you embed Cline as a programmable coding agent in your Node.js applications. It exposes the same capabilities as the Cline CLI and VS Code extension — file editing, command execution, browser use, MCP servers — through a TypeScript API that conforms to the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/protocol/schema).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install cline
|
||||
```
|
||||
|
||||
If you want direct ACP type imports as well:
|
||||
|
||||
```bash
|
||||
npm install @agentclientprotocol/sdk
|
||||
```
|
||||
|
||||
Requires Node.js 20+.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { ClineAgent } from "cline";
|
||||
|
||||
const CLINE_DIR = "/Users/username/.cline";
|
||||
const agent = new ClineAgent({ clineDir: CLINE_DIR });
|
||||
|
||||
// 1. Initialize — negotiates capabilities
|
||||
const initializeResponse = await agent.initialize({
|
||||
protocolVersion: 1,
|
||||
// these are the capabilities that the client (you) supports
|
||||
// The cline agent may or may not use them, but it needs to know about them to make informed decisions about what tools to use.
|
||||
clientCapabilities: {
|
||||
fs: { readTextFile: true, writeTextFile: true },
|
||||
terminal: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { agentInfo, authMethods } = initializeResponse;
|
||||
console.log("Agent info:", agentInfo); // contains things like agent name and version
|
||||
console.log("Auth methods:", authMethods); // contains a list of supported authentication methods. More auth methods coming soon
|
||||
|
||||
// 2. Authenticate if needed
|
||||
// If you skip this step, ClineAgent will look in CLINE_DIR for any existing credentials and authenticate with those
|
||||
await agent.authenticate({ methodId: "cline-oauth" });
|
||||
|
||||
// 3. Create a session.
|
||||
// A session represents a conversation or task with the agent. You can have multiple sessions for different tasks or conversations.
|
||||
const { sessionId } = await agent.newSession({
|
||||
cwd: process.cwd(),
|
||||
mcpServers: [], // mcpServers field not supported yet, but exposed here to maintain conformance with acp protocol
|
||||
});
|
||||
|
||||
// 4. Agent updates are sent via events. You can subscribe to these events to get real-time updates on the agent's progress, tool calls, and more.
|
||||
const emitter = agent.emitterForSession(sessionId);
|
||||
|
||||
emitter.on("agent_message_chunk", (payload) => {
|
||||
process.stdout.write(
|
||||
payload.content.type === "text"
|
||||
? payload.content.text
|
||||
: `[${payload.content.type}]`,
|
||||
);
|
||||
});
|
||||
emitter.on("agent_thought_chunk", (payload) => {
|
||||
process.stdout.write(
|
||||
payload.content.type === "text"
|
||||
? payload.content.text
|
||||
: `[${payload.content.type}]`,
|
||||
);
|
||||
});
|
||||
emitter.on("tool_call", (payload) => {
|
||||
console.log(`[tool] ${payload.title}`);
|
||||
});
|
||||
emitter.on("error", (err) => {
|
||||
console.error("[session error]", err);
|
||||
});
|
||||
|
||||
// 5. Send a prompt and wait for completion
|
||||
const { stopReason } = await agent.prompt({
|
||||
sessionId,
|
||||
prompt: [{ type: "text", text: "Create a hello world Express server" }],
|
||||
});
|
||||
|
||||
console.log("Done:", stopReason);
|
||||
|
||||
// 6. Clean up
|
||||
await agent.shutdown();
|
||||
|
||||
```
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Agent Lifecycle
|
||||
|
||||
The SDK follows the ACP lifecycle:
|
||||
|
||||
```
|
||||
initialize() → authenticate() → newSession() → prompt() ⇄ events → shutdown()
|
||||
```
|
||||
|
||||
| Step | Method | Purpose |
|
||||
|------|--------|---------|
|
||||
| Init | `initialize()` | Exchange protocol version and capabilities |
|
||||
| Auth | `authenticate()` | OAuth flow for Cline or OpenAI Codex accounts. Optional step if cline config directory already has credentials |
|
||||
| Session | `newSession()` | Create an isolated conversation context |
|
||||
| Prompt | `prompt()` | Send user messages; blocks until the turn ends |
|
||||
| Cancel | `cancel()` | Abort an in-progress prompt turn |
|
||||
| Mode | `setSessionMode()` | Switch between `"plan"` and `"act"` modes |
|
||||
| Model | `unstable_setSessionModel()` | Change the backing LLM (experimental) |
|
||||
| Shutdown | `shutdown()` | Abort all tasks, flush state, release resources |
|
||||
|
||||
### Sessions
|
||||
|
||||
A session is an independent conversation with its own task history and working directory. You can run multiple sessions concurrently.
|
||||
|
||||
```typescript
|
||||
const { sessionId, modes, models } = await agent.newSession({
|
||||
cwd: "/path/to/project",
|
||||
mcpServers: [], // mcpServers field not supported yet, but exposed here to maintain conformance with acp protocol
|
||||
})
|
||||
```
|
||||
|
||||
The response includes:
|
||||
- `sessionId` — use this in all subsequent calls
|
||||
- `modes` — available modes (`plan`, `act`) and the current mode
|
||||
- `models` — available models and the current model ID
|
||||
|
||||
Access session metadata via the read-only `sessions` map:
|
||||
|
||||
```typescript
|
||||
const session = agent.sessions.get(sessionId)
|
||||
// { sessionId, cwd, mode, mcpServers, createdAt, lastActivityAt, ... }
|
||||
```
|
||||
|
||||
### Prompting
|
||||
|
||||
`prompt()` sends a user message and blocks until the agent finishes its turn. While the prompt is processing, the agent streams output via session events.
|
||||
|
||||
```typescript
|
||||
const response = await agent.prompt({
|
||||
sessionId,
|
||||
prompt: [
|
||||
{ type: "text", text: "Refactor the auth module to use JWT" },
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
The prompt array accepts multiple content blocks:
|
||||
|
||||
```typescript
|
||||
// Text + image + file context
|
||||
await agent.prompt({
|
||||
sessionId,
|
||||
prompt: [
|
||||
{ type: "text", text: "What's in this screenshot?" },
|
||||
{ type: "image", data: base64ImageData, mimeType: "image/png" },
|
||||
{
|
||||
type: "resource",
|
||||
resource: {
|
||||
uri: "file:///path/to/relevant-file.ts",
|
||||
mimeType: "text/plain",
|
||||
text: fileContents,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
#### Content Block Types
|
||||
|
||||
| Type | Fields | Description |
|
||||
|------|--------|-------------|
|
||||
| `TextContent` | `{ type: "text", text: string }` | Plain text message |
|
||||
| `ImageContent` | `{ type: "image", mimeType: string, data: string }` | Base64-encoded image |
|
||||
| `EmbeddedResource` | `{ type: "resource", resource: { uri: string, mimeType?: string, text?: string, blob?: string } }` | File or resource context |
|
||||
|
||||
#### Stop Reasons
|
||||
|
||||
`prompt()` resolves with a `stopReason`:
|
||||
|
||||
| Value | Meaning |
|
||||
|-------|---------|
|
||||
| `"end_turn"` | Agent finished normally (completed task or waiting for user input) |
|
||||
| `"error"` | An error occurred |
|
||||
|
||||
### Streaming Events
|
||||
|
||||
Subscribe to real-time output via `ClineSessionEmitter`. Each session has its own emitter.
|
||||
|
||||
```typescript
|
||||
const emitter = agent.emitterForSession(sessionId)
|
||||
```
|
||||
|
||||
#### Event Types
|
||||
|
||||
All events correspond to [ACP `SessionUpdate` types](https://agentclientprotocol.com/protocol/schema#SessionUpdate):
|
||||
|
||||
| Event | Payload | Description |
|
||||
|-------|---------|-------------|
|
||||
| `agent_message_chunk` | `{ content: ContentBlock }` | Streamed text from the agent |
|
||||
| `agent_thought_chunk` | `{ content: ContentBlock }` | Internal reasoning / chain-of-thought |
|
||||
| `tool_call` | `ToolCall` | New tool invocation (file edit, command, etc.) |
|
||||
| `tool_call_update` | `ToolCallUpdate` | Progress/result update for an existing tool call |
|
||||
| `plan` | `{ entries: PlanEntry[] }` | Agent's execution plan |
|
||||
| `available_commands_update` | `{ availableCommands: AvailableCommand[] }` | Slash commands the agent supports |
|
||||
| `current_mode_update` | `{ currentModeId: string }` | Mode changed (plan/act) |
|
||||
| `user_message_chunk` | `{ content: ContentBlock }` | User message chunks (for multi-turn) |
|
||||
| `config_option_update` | `{ configOptions: SessionConfigOption[] }` | Configuration changed |
|
||||
| `session_info_update` | Session metadata | Session metadata changed |
|
||||
| `error` | `Error` | Session-level error (not an ACP update) |
|
||||
|
||||
```typescript
|
||||
emitter.on("agent_message_chunk", (payload) => {
|
||||
// payload.content is a ContentBlock — usually { type: "text", text: "..." }
|
||||
process.stdout.write(payload.content.text)
|
||||
})
|
||||
|
||||
emitter.on("agent_thought_chunk", (payload) => {
|
||||
console.log("[thinking]", payload.content.text)
|
||||
})
|
||||
|
||||
emitter.on("tool_call", (payload) => {
|
||||
console.log(`[${payload.kind}] ${payload.title} (${payload.status})`)
|
||||
})
|
||||
|
||||
emitter.on("tool_call_update", (payload) => {
|
||||
console.log(` → ${payload.toolCallId}: ${payload.status}`)
|
||||
})
|
||||
|
||||
emitter.on("error", (err) => {
|
||||
console.error("Session error:", err)
|
||||
})
|
||||
```
|
||||
|
||||
The emitter supports `on`, `once`, `off`, and `removeAllListeners`.
|
||||
|
||||
### Permission Handling
|
||||
|
||||
When the agent wants to execute a tool (edit a file, run a command, etc.), it requests permission. You **must** set a permission handler or all tool calls will be auto-rejected.
|
||||
|
||||
```typescript
|
||||
agent.setPermissionHandler(async (request) => {
|
||||
// request.toolCall — details about what the agent wants to do
|
||||
// request.options — available choices (allow_once, reject_once, etc.)
|
||||
|
||||
console.log(`Permission requested: ${request.toolCall.title}`)
|
||||
console.log("Options:", request.options.map(o => `${o.optionId} (${o.kind})`))
|
||||
|
||||
// Auto-approve everything:
|
||||
const allowOption = request.options.find(o => o.kind.includes("allow"))
|
||||
if (allowOption) {
|
||||
return { outcome: { outcome: "selected", optionId: allowOption.optionId } }
|
||||
} else {
|
||||
return { outcome: { outcome: "rejected" } }
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Permission Options
|
||||
|
||||
Each permission request includes an array of `PermissionOption` objects:
|
||||
|
||||
| `kind` | Meaning |
|
||||
|--------|---------|
|
||||
| `allow_once` | Approve this single operation |
|
||||
| `allow_always` | Approve and remember for future operations |
|
||||
| `reject_once` | Deny this single operation |
|
||||
| `reject_always` | Deny and remember for future operations |
|
||||
|
||||
**Important:** If no permission handler is set, all tool calls are rejected for safety.
|
||||
|
||||
### Modes
|
||||
|
||||
Cline supports two modes:
|
||||
|
||||
- **`plan`** — The agent gathers information and creates a plan without executing actions
|
||||
- **`act`** — The agent executes actions (file edits, commands, etc.)
|
||||
|
||||
```typescript
|
||||
// Switch to plan mode
|
||||
await agent.setSessionMode({ sessionId, modeId: "plan" })
|
||||
|
||||
// Switch back to act mode
|
||||
await agent.setSessionMode({ sessionId, modeId: "act" })
|
||||
```
|
||||
|
||||
The current mode is returned in `newSession()`
|
||||
|
||||
### Model Selection
|
||||
|
||||
Change the backing model with `unstable_setSessionModel()`. The model ID format is `"provider/modelId"`.
|
||||
|
||||
```typescript
|
||||
await agent.unstable_setSessionModel({
|
||||
sessionId,
|
||||
modelId: "anthropic/claude-sonnet-4-20250514",
|
||||
})
|
||||
```
|
||||
|
||||
This sets the model for both plan and act modes. Available providers include `anthropic`, `openai-native`, `gemini`, `bedrock`, `deepseek`, `mistral`, `groq`, `xai`, and others. Model Ids can be found in the NewSessionResponse object after calling `agent.newSession(..)`
|
||||
|
||||
> **Note:** This API is experimental and may change.
|
||||
|
||||
### Authentication
|
||||
|
||||
The SDK supports two OAuth flows:
|
||||
|
||||
```typescript
|
||||
// Cline account (uses browser OAuth)
|
||||
await agent.authenticate({ methodId: "cline-oauth" })
|
||||
|
||||
// OpenAI Codex / ChatGPT subscription
|
||||
await agent.authenticate({ methodId: "openai-codex-oauth" })
|
||||
```
|
||||
|
||||
Both methods open a browser window for the OAuth flow and block until authentication completes (5-minute timeout for Cline OAuth).
|
||||
|
||||
For BYO (bring-your-own) API key providers, configure the key through the cline config directory before creating a session. The `authenticate()` call is not needed for BYO providers. We plan to support more auth providers in the near future.
|
||||
|
||||
### Cancellation
|
||||
|
||||
Cancel an in-progress prompt turn:
|
||||
|
||||
```typescript
|
||||
await agent.cancel({ sessionId })
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Constructor
|
||||
|
||||
```typescript
|
||||
new ClineAgent(options: ClineAgentOptions)
|
||||
```
|
||||
|
||||
```typescript
|
||||
interface ClineAgentOptions {
|
||||
/** Enable debug logging (default: false) */
|
||||
debug?: boolean
|
||||
/** Custom Cline config directory (default: ~/.cline) */
|
||||
clineDir?: string
|
||||
}
|
||||
```
|
||||
|
||||
The `clineDir` option lets you isolate configuration and task history per-application:
|
||||
|
||||
```typescript
|
||||
const agent = new ClineAgent({
|
||||
clineDir: "/tmp/my-app-cline",
|
||||
})
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
#### `initialize(params): Promise<InitializeResponse>`
|
||||
|
||||
Initialize the agent and negotiate protocol capabilities.
|
||||
|
||||
```typescript
|
||||
const response = await agent.initialize({
|
||||
clientCapabilities: {},
|
||||
protocolVersion: 1,
|
||||
})
|
||||
|
||||
// Response includes:
|
||||
{
|
||||
protocolVersion: "0.9.0",
|
||||
agentCapabilities: {
|
||||
loadSession: true,
|
||||
promptCapabilities: { image: true, audio: false, embeddedContext: true },
|
||||
mcpCapabilities: { http: true, sse: false }
|
||||
},
|
||||
agentInfo: { name: "cline", version: "2.2.3" },
|
||||
authMethods: [
|
||||
{ id: "cline-oauth", name: "Sign in with Cline", description: "..." },
|
||||
{ id: "openai-codex-oauth", name: "Sign in with ChatGPT", description: "..." }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `newSession(params): Promise<NewSessionResponse>`
|
||||
|
||||
Create a new conversation session.
|
||||
|
||||
```typescript
|
||||
const session = await agent.newSession({
|
||||
cwd: "/path/to/project",
|
||||
mcpServers: [
|
||||
{
|
||||
type: "stdio",
|
||||
name: "filesystem",
|
||||
command: "npx",
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],
|
||||
env: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
// Response includes:
|
||||
{
|
||||
sessionId: "uuid-string",
|
||||
modes: {
|
||||
availableModes: [
|
||||
{ id: "plan", name: "Plan", description: "Gather information and create a detailed plan" },
|
||||
{ id: "act", name: "Act", description: "Execute actions to accomplish the task" }
|
||||
],
|
||||
currentModeId: "act"
|
||||
},
|
||||
models: {
|
||||
currentModelId: "anthropic/claude-sonnet-4-5-20241022",
|
||||
availableModels: [{ modelId: "anthropic/claude-3-5-sonnet-20241022", name: "..." }]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** `newSession()` may throw an auth-required error if credentials are not configured yet.
|
||||
|
||||
#### `prompt(params): Promise<PromptResponse>`
|
||||
|
||||
Send a user prompt to the agent. This is the main method for interacting with Cline. Blocks until the agent finishes its turn.
|
||||
|
||||
```typescript
|
||||
const response = await agent.prompt({
|
||||
sessionId: session.sessionId,
|
||||
prompt: [
|
||||
{ type: "text", text: "Create a function that adds two numbers" },
|
||||
],
|
||||
})
|
||||
|
||||
// Response: { stopReason: "end_turn" | "max_tokens" | "cancelled" | "error" }
|
||||
```
|
||||
|
||||
#### `cancel(params): Promise<void>`
|
||||
|
||||
Cancel an ongoing prompt operation.
|
||||
|
||||
```typescript
|
||||
await agent.cancel({ sessionId: session.sessionId })
|
||||
```
|
||||
|
||||
#### `setSessionMode(params): Promise<SetSessionModeResponse>`
|
||||
|
||||
Switch between plan and act modes.
|
||||
|
||||
```typescript
|
||||
await agent.setSessionMode({ sessionId, modeId: "plan" })
|
||||
```
|
||||
|
||||
#### `unstable_setSessionModel(params): Promise<SetSessionModelResponse>`
|
||||
|
||||
Change the model for the session. Model ID format depends on the inference provider. See NewSessionResponse object to get modelIds.
|
||||
|
||||
```typescript
|
||||
await agent.unstable_setSessionModel({
|
||||
sessionId,
|
||||
modelId: "anthropic/claude-sonnet-4-20250514",
|
||||
})
|
||||
```
|
||||
|
||||
#### `authenticate(params): Promise<AuthenticateResponse>`
|
||||
|
||||
Authenticate with a provider. Opens a browser window for OAuth flow.
|
||||
|
||||
```typescript
|
||||
await agent.authenticate({ methodId: "cline-oauth" })
|
||||
```
|
||||
|
||||
Current methodIds we support:
|
||||
|
||||
| methodId | Description |
|
||||
| -------------------- | ----------------------------- |
|
||||
| `cline-oauth` | use cline inference provider |
|
||||
| `openai-codex-oauth` | use your chatgpt subscription |
|
||||
| more coming soon!... | |
|
||||
|
||||
#### `shutdown(): Promise<void>`
|
||||
|
||||
Clean up all resources. Call this when done.
|
||||
|
||||
```typescript
|
||||
await agent.shutdown()
|
||||
```
|
||||
|
||||
#### `setPermissionHandler(handler)`
|
||||
|
||||
Set a callback to handle tool permission requests.
|
||||
|
||||
```typescript
|
||||
agent.setPermissionHandler((request, resolve) => {
|
||||
resolve({ outcome: { outcome: "selected", optionId: "allow_once" } })
|
||||
})
|
||||
```
|
||||
|
||||
#### `emitterForSession(sessionId): ClineSessionEmitter`
|
||||
|
||||
Get the typed event emitter for a session.
|
||||
|
||||
```typescript
|
||||
const emitter = agent.emitterForSession(session.sessionId)
|
||||
```
|
||||
|
||||
#### `sessions` (read-only Map)
|
||||
|
||||
Access active sessions:
|
||||
|
||||
```typescript
|
||||
for (const [sessionId, session] of agent.sessions) {
|
||||
console.log(sessionId, session.cwd, session.mode)
|
||||
}
|
||||
```
|
||||
|
||||
## Full Example: Auto-Approve Agent
|
||||
|
||||
```typescript
|
||||
import { ClineAgent } from "cline";
|
||||
|
||||
async function runTask(taskPrompt: string, cwd: string) {
|
||||
const agent = new ClineAgent({ clineDir: "/Users/maxpaulus/.cline" });
|
||||
|
||||
await agent.initialize({
|
||||
protocolVersion: 1,
|
||||
clientCapabilities: {},
|
||||
});
|
||||
|
||||
const { sessionId } = await agent.newSession({ cwd, mcpServers: [] });
|
||||
|
||||
// Auto-approve all tool calls
|
||||
agent.setPermissionHandler(async (request) => {
|
||||
const allow = request.options.find((o) => o.kind === "allow_once");
|
||||
return {
|
||||
outcome: allow
|
||||
? { outcome: "selected", optionId: allow.optionId }
|
||||
: { outcome: "cancelled" },
|
||||
};
|
||||
});
|
||||
|
||||
// Collect output
|
||||
const output: string[] = [];
|
||||
const emitter = agent.emitterForSession(sessionId);
|
||||
|
||||
emitter.on("agent_message_chunk", (p) => {
|
||||
if (p.content.type === "text") output.push(p.content.text);
|
||||
});
|
||||
|
||||
emitter.on("tool_call", (p) => {
|
||||
console.log(`[tool] ${p.title}`);
|
||||
});
|
||||
|
||||
const { stopReason } = await agent.prompt({
|
||||
sessionId,
|
||||
prompt: [{ type: "text", text: taskPrompt }],
|
||||
});
|
||||
|
||||
console.log("\n--- Agent Output ---");
|
||||
console.log(output.join(""));
|
||||
console.log(`\nStop reason: ${stopReason}`);
|
||||
|
||||
await agent.shutdown();
|
||||
}
|
||||
|
||||
runTask("Create a README.md for this project", process.cwd());
|
||||
```
|
||||
|
||||
## Full Example: Interactive Permission Flow
|
||||
|
||||
```typescript
|
||||
import { ClineAgent, type PermissionHandler } from "cline";
|
||||
import * as readline from "readline";
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
const ask = (q: string) => new Promise<string>((res) => rl.question(q, res));
|
||||
|
||||
const interactivePermissions: PermissionHandler = async (request) => {
|
||||
console.log(`\n⚠️ Permission: ${request.toolCall.title}`);
|
||||
|
||||
for (const [i, opt] of request.options.entries()) {
|
||||
console.log(` ${i + 1}. [${opt.kind}] ${opt.name}`);
|
||||
}
|
||||
|
||||
const choice = await ask("Choose (number): ");
|
||||
const idx = parseInt(choice, 10) - 1;
|
||||
const selected = request.options[idx];
|
||||
|
||||
if (selected) {
|
||||
return {
|
||||
outcome: { outcome: "selected", optionId: selected.optionId },
|
||||
};
|
||||
} else {
|
||||
return { outcome: { outcome: "cancelled" } };
|
||||
}
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const agent = new ClineAgent({});
|
||||
await agent.initialize({ protocolVersion: 1, clientCapabilities: {} });
|
||||
|
||||
const { sessionId } = await agent.newSession({
|
||||
cwd: process.cwd(),
|
||||
mcpServers: [],
|
||||
});
|
||||
|
||||
agent.setPermissionHandler(interactivePermissions);
|
||||
|
||||
const emitter = agent.emitterForSession(sessionId);
|
||||
emitter.on("agent_message_chunk", (p) => {
|
||||
if (p.content.type === "text") process.stdout.write(p.content.text);
|
||||
});
|
||||
|
||||
// Multi-turn conversation
|
||||
while (true) {
|
||||
const userInput = await ask("\n> ");
|
||||
if (userInput === "exit") break;
|
||||
|
||||
const { stopReason } = await agent.prompt({
|
||||
sessionId,
|
||||
prompt: [{ type: "text", text: userInput }],
|
||||
});
|
||||
|
||||
console.log(`\n[${stopReason}]`);
|
||||
}
|
||||
|
||||
await agent.shutdown();
|
||||
rl.close();
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
```
|
||||
|
||||
## Exported Types
|
||||
|
||||
All types are re-exported from the `cline` package. Key types:
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `ClineAgent` | Main agent class |
|
||||
| `ClineSessionEmitter` | Typed event emitter for session events |
|
||||
| `ClineAgentOptions` | Constructor options |
|
||||
| `ClineAcpSession` | Session metadata (read-only) |
|
||||
| `ClineSessionEvents` | Event name → handler signature map |
|
||||
| `PermissionHandler` | `(request, resolve) => void` callback |
|
||||
| `PermissionResolver` | `(response) => void` callback |
|
||||
| `SessionUpdate` | Union of all session update types |
|
||||
| `SessionUpdateType` | Discriminator values (`"agent_message_chunk"`, `"tool_call"`, etc.) |
|
||||
| `ToolCall` | Tool call details (id, title, kind, status, content) |
|
||||
| `ToolCallUpdate` | Partial update to an existing tool call |
|
||||
| `ToolCallStatus` | `"pending" \| "in_progress" \| "completed" \| "failed"` |
|
||||
| `ToolKind` | `"read" \| "edit" \| "delete" \| "execute" \| "search" \| ...` |
|
||||
| `StopReason` | `"end_turn" \| "cancelled" \| "error" \| "max_tokens" \| ...` |
|
||||
| `ContentBlock` | `TextContent \| ImageContent \| AudioContent \| ...` |
|
||||
| `McpServer` | MCP server configuration (stdio, http) |
|
||||
| `PromptRequest` / `PromptResponse` | Prompt call types |
|
||||
| `NewSessionRequest` / `NewSessionResponse` | Session creation types |
|
||||
| `InitializeRequest` / `InitializeResponse` | Initialization types |
|
||||
|
||||
See the [ACP Schema](https://agentclientprotocol.com/protocol/schema) for the full type definitions.
|
||||
|
||||
## Relationship to ACP
|
||||
|
||||
The Cline SDK implements the [Agent Client Protocol](https://agentclientprotocol.com) `Agent` interface. The key difference from a standard ACP stdio agent is that the SDK uses an **event emitter pattern** instead of a transport connection:
|
||||
|
||||
| ACP Stdio (via `AcpAgent`) | SDK (via `ClineAgent`) |
|
||||
|-----------------------------|------------------------|
|
||||
| Session updates sent over JSON-RPC stdio | Session updates emitted via `ClineSessionEmitter` |
|
||||
| Permissions requested via `connection.requestPermission()` | Permissions requested via `setPermissionHandler()` callback |
|
||||
| Single process, single connection | Embeddable, multiple concurrent sessions |
|
||||
|
||||
If you need stdio-based ACP communication (e.g., for IDE integration), use the `cline` CLI binary directly. The SDK is for embedding Cline in your own Node.js processes.
|
||||
@@ -1,316 +0,0 @@
|
||||
---
|
||||
title: "Documentation Templates"
|
||||
sidebarTitle: "Templates"
|
||||
description: "Templates for different types of Cline documentation"
|
||||
---
|
||||
|
||||
Use these templates as starting points for new documentation. Each template is designed for a specific purpose. Choose the one that best fits what you're documenting.
|
||||
|
||||
## Choosing a Template
|
||||
|
||||
| If you're documenting... | Use this template |
|
||||
|--------------------------|-------------------|
|
||||
| What a feature does and how to use it | Feature Doc |
|
||||
| How to accomplish a specific task | How-To Guide |
|
||||
| Technical specifications or API details | Reference Doc |
|
||||
| A complete project walkthrough | Tutorial |
|
||||
|
||||
## Feature Doc
|
||||
|
||||
Use this template when explaining a Cline feature. Focus on what it does, how to use it, and real examples.
|
||||
|
||||
````text
|
||||
---
|
||||
title: "Feature Name"
|
||||
sidebarTitle: "Feature Name"
|
||||
---
|
||||
|
||||
[One sentence explaining what this feature does.]
|
||||
|
||||
<Frame>
|
||||
<img src="..." alt="Feature in action" />
|
||||
</Frame>
|
||||
|
||||
[1-2 paragraphs explaining the feature in plain terms. What problem does it
|
||||
solve? Why would someone use it?]
|
||||
|
||||
## How It Works
|
||||
|
||||
[Explain the mechanics without jargon. What happens when you use this feature?]
|
||||
|
||||
## Using [Feature Name]
|
||||
|
||||
[Show how to access and use it. Include the exact UI path.]
|
||||
|
||||
### [Option or Variation 1]
|
||||
|
||||
[Details with examples]
|
||||
|
||||
### [Option or Variation 2]
|
||||
|
||||
[Details with examples]
|
||||
|
||||
## Inspiration
|
||||
|
||||
[Share how you personally use this feature. Use "I" voice. Give 2-3 real
|
||||
examples that spark imagination about what's possible.]
|
||||
|
||||
<Note>
|
||||
[Important caveat, limitation, or requirement]
|
||||
</Note>
|
||||
````
|
||||
|
||||
### Example: Checkpoints Feature
|
||||
|
||||
Here's how the [Checkpoints](/core-workflows/checkpoints) doc follows this pattern:
|
||||
|
||||
- Opens with one clear sentence about what checkpoints do
|
||||
- Shows a screenshot of the feature in action
|
||||
- Explains how checkpoints work under the hood
|
||||
- Shows exact steps to create and restore checkpoints
|
||||
- Includes real examples of when checkpoints save the day
|
||||
|
||||
## How-To Guide
|
||||
|
||||
Use this template when showing how to accomplish a specific task. Focus on clear steps and troubleshooting.
|
||||
|
||||
````text
|
||||
---
|
||||
title: "How to [Accomplish Task]"
|
||||
sidebarTitle: "[Short Title]"
|
||||
description: "[One sentence describing what the reader will learn]"
|
||||
---
|
||||
|
||||
[Brief intro explaining what problem this guide solves and what you'll end up
|
||||
with after following it.]
|
||||
|
||||
## Prerequisites
|
||||
|
||||
[What the reader needs before starting. Keep it short. Link to other docs
|
||||
rather than explaining setup here.]
|
||||
|
||||
- Cline installed and configured
|
||||
- [Other requirement]
|
||||
|
||||
## Steps
|
||||
|
||||
<Steps>
|
||||
<Step title="[First Action]">
|
||||
[Clear instructions. Show exactly what to click or type.]
|
||||
|
||||
```bash
|
||||
example command if needed
|
||||
```
|
||||
</Step>
|
||||
<Step title="[Second Action]">
|
||||
[Next step. Include screenshots for complex UI interactions.]
|
||||
|
||||
<Frame>
|
||||
<img src="..." alt="What you should see" />
|
||||
</Frame>
|
||||
</Step>
|
||||
<Step title="[Final Action]">
|
||||
[Complete the task. Show the expected result.]
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Common issues and how to fix them:
|
||||
|
||||
- **Problem description**: Solution in one or two sentences.
|
||||
- **Another problem**: Another solution.
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Card title="Related Feature" icon="arrow-right" href="/path/to/related">
|
||||
Continue learning with this related guide.
|
||||
</Card>
|
||||
````
|
||||
|
||||
### Example: Your First Project
|
||||
|
||||
The [Your First Project](/getting-started/your-first-project) guide follows this pattern:
|
||||
|
||||
- Clear goal stated upfront
|
||||
- Prerequisites listed briefly
|
||||
- Step-by-step instructions with the Steps component
|
||||
- Troubleshooting section for common issues
|
||||
|
||||
## Reference Doc
|
||||
|
||||
Use this template for technical specifications, API documentation, or detailed configuration options.
|
||||
|
||||
````text
|
||||
---
|
||||
title: "[Component/API] Reference"
|
||||
sidebarTitle: "[Short Title]"
|
||||
description: "[What this reference covers]"
|
||||
---
|
||||
|
||||
[Brief description of what this reference documents and when you'd need it.]
|
||||
|
||||
## Overview
|
||||
|
||||
[High-level explanation. What is this component? What role does it play?]
|
||||
|
||||
## [Category 1]
|
||||
|
||||
### [Item Name]
|
||||
|
||||
[What it does in one sentence.]
|
||||
|
||||
| Property | Type | Default | Description |
|
||||
|----------|------|---------|-------------|
|
||||
| `propertyName` | `string` | `"default"` | What this property controls |
|
||||
| `anotherProp` | `boolean` | `false` | What this does |
|
||||
|
||||
**Example:**
|
||||
|
||||
```typescript
|
||||
// Show practical usage
|
||||
const example = {
|
||||
propertyName: "custom value",
|
||||
anotherProp: true
|
||||
}
|
||||
```
|
||||
|
||||
### [Another Item]
|
||||
|
||||
[Continue for each item in this category.]
|
||||
|
||||
## [Category 2]
|
||||
|
||||
[Continue with other categories as needed.]
|
||||
|
||||
## Examples
|
||||
|
||||
[Show 2-3 complete, practical examples that combine multiple concepts.]
|
||||
|
||||
### [Example 1 Title]
|
||||
|
||||
```typescript
|
||||
// Complete working example
|
||||
```
|
||||
|
||||
### [Example 2 Title]
|
||||
|
||||
```typescript
|
||||
// Another complete example
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [Related Doc 1](/path/to/doc) - Brief description
|
||||
- [Related Doc 2](/path/to/doc) - Brief description
|
||||
````
|
||||
|
||||
### Example: Cline Tools Guide
|
||||
|
||||
The [Cline Tools Guide](/tools-reference/all-cline-tools) follows this pattern:
|
||||
|
||||
- Overview of the tool system
|
||||
- Each tool documented with parameters and examples
|
||||
- Practical examples showing tools in context
|
||||
|
||||
## Tutorial
|
||||
|
||||
Use this template for comprehensive project walkthroughs where users build something from start to finish.
|
||||
|
||||
````text
|
||||
---
|
||||
title: "[Build/Create X] Tutorial"
|
||||
sidebarTitle: "[Short Title]"
|
||||
description: "[What the reader will build]"
|
||||
---
|
||||
|
||||
In this tutorial, you'll build [specific outcome]. By the end, you'll have
|
||||
[tangible result you can see/use].
|
||||
|
||||
<Frame>
|
||||
<img src="..." alt="Preview of what you'll build" />
|
||||
</Frame>
|
||||
|
||||
## What You'll Learn
|
||||
|
||||
- [Skill or concept 1]
|
||||
- [Skill or concept 2]
|
||||
- [Skill or concept 3]
|
||||
|
||||
## Prerequisites
|
||||
|
||||
[Required setup. Link to installation guides rather than repeating them.]
|
||||
|
||||
- [Prerequisite 1]
|
||||
- [Prerequisite 2]
|
||||
|
||||
## Part 1: [First Major Section]
|
||||
|
||||
[Introduction to this section. What are we doing and why?]
|
||||
|
||||
### [Subsection]
|
||||
|
||||
[Detailed walkthrough with code blocks and explanations.]
|
||||
|
||||
```typescript
|
||||
// Code that the reader should write or understand
|
||||
```
|
||||
|
||||
[Explain what the code does and why.]
|
||||
|
||||
## Part 2: [Second Major Section]
|
||||
|
||||
[Continue building on Part 1.]
|
||||
|
||||
### [Subsection]
|
||||
|
||||
[More detailed walkthrough.]
|
||||
|
||||
## Part 3: [Final Section]
|
||||
|
||||
[Complete the project.]
|
||||
|
||||
## Summary
|
||||
|
||||
You built [what they built]. Along the way, you learned:
|
||||
|
||||
- [Key takeaway 1]
|
||||
- [Key takeaway 2]
|
||||
- [Key takeaway 3]
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Go Deeper" icon="book" href="/path/to/advanced">
|
||||
Learn more advanced techniques.
|
||||
</Card>
|
||||
<Card title="Related Tutorial" icon="code" href="/path/to/related">
|
||||
Build something else with similar concepts.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
````
|
||||
|
||||
### Example Structure
|
||||
|
||||
A good tutorial:
|
||||
- Shows the end result upfront so readers know what they're building
|
||||
- Breaks the work into logical parts
|
||||
- Explains the "why" alongside the "how"
|
||||
- Ends with clear next steps
|
||||
|
||||
## Quick Tips
|
||||
|
||||
When using these templates:
|
||||
|
||||
1. **Delete sections you don't need.** Templates are starting points, not rigid structures.
|
||||
|
||||
2. **Add sections that make sense.** If your doc needs something not in the template, add it.
|
||||
|
||||
3. **Keep the reader moving forward.** Every section should lead naturally to the next.
|
||||
|
||||
4. **Test your own instructions.** Follow your guide from scratch to catch missing steps.
|
||||
|
||||
<Tip>
|
||||
Use the `/write-docs` workflow to generate documentation from these templates automatically.
|
||||
Cline helps you fill in each section based on your project.
|
||||
</Tip>
|
||||
@@ -1,200 +0,0 @@
|
||||
---
|
||||
title: "Documentation Guide"
|
||||
sidebarTitle: "Documentation Guide"
|
||||
description: "How to write and contribute to Cline documentation"
|
||||
---
|
||||
|
||||
Cline's documentation lives in the `docs/` directory and uses [Mintlify](https://mintlify.com) for rendering. This guide covers how to write docs that match Cline's established style.
|
||||
|
||||
## Using the Documentation Workflow
|
||||
|
||||
The fastest way to create documentation is using the `/write-docs` workflow. Type `/write-docs` in Cline and describe what you want to document. Cline guides you through a 4-step process:
|
||||
|
||||
1. **Research**: Examine existing docs structure and patterns
|
||||
2. **Scope**: Clarify audience, doc type, and key use cases
|
||||
3. **Outline**: Select a template and create structure
|
||||
4. **Write**: Generate documentation following style guidelines
|
||||
|
||||
The workflow file lives at `.clinerules/workflows/write-docs.md` and contains templates, style rules, and examples.
|
||||
|
||||
## Documentation Principles
|
||||
|
||||
### Write for Developers
|
||||
|
||||
Your audience is developers who value their time. Get to the point. Every sentence should either help them understand something or help them do something.
|
||||
|
||||
```markdown
|
||||
# Good
|
||||
Switch to bash in Cline Settings → Terminal → Default Terminal Profile.
|
||||
|
||||
# Bad
|
||||
Users who are experiencing issues may find it helpful to navigate to the
|
||||
Cline settings menu where they can locate the terminal configuration
|
||||
options and subsequently modify the default terminal profile setting.
|
||||
```
|
||||
|
||||
### Show Real Examples
|
||||
|
||||
Abstract descriptions don't help anyone. Show actual code, real file paths, and concrete implementations.
|
||||
|
||||
```markdown
|
||||
# Good
|
||||
I use `/deep-planning` whenever I'm building features that touch multiple
|
||||
parts of the codebase. For example, when adding authentication, Cline
|
||||
mapped every endpoint and created a migration plan that avoided breaking changes.
|
||||
|
||||
# Bad
|
||||
The deep planning feature can be utilized for various complex tasks
|
||||
that may require careful consideration and planning.
|
||||
```
|
||||
|
||||
### Use Active Voice
|
||||
|
||||
Cline does things. Files don't get created by Cline, Cline creates files.
|
||||
|
||||
```markdown
|
||||
# Good
|
||||
Cline reads your project files and builds context automatically.
|
||||
|
||||
# Bad
|
||||
Project files are read and context is built automatically.
|
||||
```
|
||||
|
||||
### Use Neutral Pronouns for Cline
|
||||
|
||||
Refer to Cline as "it" not "he". Cline is software, not a person.
|
||||
|
||||
```markdown
|
||||
# Good
|
||||
When Cline encounters an error, it suggests fixes.
|
||||
|
||||
# Bad
|
||||
When Cline encounters an error, he suggests fixes.
|
||||
```
|
||||
|
||||
## File Format
|
||||
|
||||
All documentation uses MDX format with YAML frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: "Full Page Title"
|
||||
sidebarTitle: "Shorter Nav Title" # optional
|
||||
description: "One sentence for SEO" # optional but recommended
|
||||
---
|
||||
```
|
||||
|
||||
### Adding New Pages
|
||||
|
||||
After creating a new `.mdx` file, add it to `docs/docs.json` in the appropriate navigation group:
|
||||
|
||||
```json
|
||||
{
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"features/existing-page",
|
||||
"features/your-new-page"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Mintlify Components
|
||||
|
||||
Use these components appropriately throughout your docs.
|
||||
|
||||
### Frame
|
||||
|
||||
Wrap all images and videos:
|
||||
|
||||
```jsx
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/filename.png"
|
||||
alt="Descriptive alt text"
|
||||
/>
|
||||
</Frame>
|
||||
```
|
||||
|
||||
### Callouts
|
||||
|
||||
Use sparingly and purposefully:
|
||||
|
||||
```jsx
|
||||
<Tip>Helpful suggestions that improve the experience.</Tip>
|
||||
<Note>Important information the reader needs to know.</Note>
|
||||
<Warning>Something that could cause problems if ignored.</Warning>
|
||||
```
|
||||
|
||||
### Steps
|
||||
|
||||
For sequential procedures:
|
||||
|
||||
```jsx
|
||||
<Steps>
|
||||
<Step title="Install the Extension">
|
||||
Search for "Cline" in the VS Code marketplace.
|
||||
</Step>
|
||||
<Step title="Configure Your Model">
|
||||
Open settings and add your API key.
|
||||
</Step>
|
||||
</Steps>
|
||||
```
|
||||
|
||||
### Cards
|
||||
|
||||
For navigation and feature overviews:
|
||||
|
||||
```jsx
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Getting Started" icon="rocket" href="/getting-started/installing-cline">
|
||||
Install Cline and set up your first project.
|
||||
</Card>
|
||||
<Card title="Features" icon="wand-magic-sparkles" href="/core-workflows/plan-and-act">
|
||||
Explore what Cline can do.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
```
|
||||
|
||||
## Style Rules
|
||||
|
||||
Quick reference for consistent documentation:
|
||||
|
||||
| Do | Don't |
|
||||
|---|---|
|
||||
| Use "use" | Use "utilize" |
|
||||
| Keep sentences under 25 words | Write run-on sentences |
|
||||
| Use bullet points for lists | Write walls of text |
|
||||
| Show where things are in the UI | Assume users can find features |
|
||||
| Cross-link related docs | Leave readers stranded |
|
||||
| Use code blocks with language tags | Use inline code for long snippets |
|
||||
|
||||
### Avoid These Patterns
|
||||
|
||||
- Em dashes and emojis
|
||||
- Starting with "This document explains..."
|
||||
- The **Bold Text**: description pattern
|
||||
- Explaining obvious things
|
||||
- Passive voice
|
||||
|
||||
## Previewing Changes
|
||||
|
||||
Run the docs locally to preview your changes:
|
||||
|
||||
```bash
|
||||
cd docs
|
||||
npm install # first time only
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open `http://localhost:3000` to see your changes in real time.
|
||||
|
||||
## Related Resources
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Documentation Templates" icon="file-lines" href="/contributing/doc-templates">
|
||||
Templates for different documentation types.
|
||||
</Card>
|
||||
<Card title="Workflows" icon="diagram-project" href="/customization/workflows">
|
||||
Learn about Cline's workflow system.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,220 +0,0 @@
|
||||
---
|
||||
title: "Model Selection Guide"
|
||||
description: "Choose the right AI model for your workflow based on reliability, speed, cost, and context window size."
|
||||
---
|
||||
|
||||
New models drop constantly, so this guide focuses on what's working well with Cline right now. We'll keep it updated as the landscape shifts.
|
||||
|
||||
<Callout type="tip">
|
||||
**New to model selection?** Start with [Module 2 of Cline's Learning Path](https://cline.bot/learn) for a comprehensive guide to choosing and configuring models.
|
||||
</Callout>
|
||||
|
||||
## What is an AI Model?
|
||||
|
||||
Think of an AI model as the "brain" that powers Cline. When you ask Cline to write code, fix bugs, or refactor your project, it's the model that actually understands your request and generates the response.
|
||||
|
||||
**Key points:**
|
||||
- **Models are trained AI systems** that understand natural language and code
|
||||
- **Different models have different strengths** some excel at complex reasoning, others prioritize speed or cost
|
||||
- **You choose which model Cline uses** like picking between different experts for different tasks
|
||||
- **Models are accessed via API providers** - companies like Anthropic, OpenAI, and OpenRouter host these models
|
||||
|
||||
**Why it matters:** The model you choose directly impacts Cline's capabilities, response quality, speed, and cost. A premium model might handle complex refactoring beautifully but cost more, while a budget model works great for routine tasks at a fraction of the price.
|
||||
|
||||
## How to Select a Model in Cline
|
||||
|
||||
Follow these 5 simple steps to get Cline up and running with your preferred AI model:
|
||||
|
||||
### Step 1: Open Cline Settings
|
||||
|
||||
First, you need to access Cline's configuration panel.
|
||||
|
||||
**Two ways to open settings:**
|
||||
- **Quick method**: Click the **gear icon (⚙️)** in the top-right corner of Cline's chat interface
|
||||
- **Command palette**: Press **Cmd/Ctrl + Shift + P** → type "Cline: Open Settings"
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/step1-config.png" alt="Cline Settings Panel" />
|
||||
</Frame>
|
||||
|
||||
The settings panel will open, showing configuration options with "API Provider" at the top.
|
||||
|
||||
<Note>
|
||||
The settings panel remembers your last configuration, so you'll only need to set this up once.
|
||||
</Note>
|
||||
|
||||
### Step 2: Select an API Provider
|
||||
|
||||
Choose your preferred AI provider from the dropdown menu.
|
||||
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/step2-provider.png" alt="Cline Settings Panel" />
|
||||
</Frame>
|
||||
|
||||
**Popular providers at a glance:**
|
||||
|
||||
| Provider | Best For | Notes |
|
||||
|----------|----------|-------|
|
||||
| **Cline** | Easiest setup | No API keys needed, access to multiple models including stealth models |
|
||||
| **OpenRouter** | Value seekers | Multiple models, competitive pricing |
|
||||
| **Anthropic** | Reliability | Claude models, most dependable tool usage |
|
||||
| **OpenAI** | Latest tech | GPT-5, o3, o4-mini models |
|
||||
| **OpenAI Codex** | ChatGPT subscribers | Use your ChatGPT subscription — no API key needed |
|
||||
| **Google Gemini** | Large context | Gemini 3/2.5 with up to 2M context |
|
||||
| **DeepSeek** | Budget reasoning | V3.2, R1 models at low cost |
|
||||
| **Alibaba Qwen** | Open source coding | Qwen3 Coder with 1M context |
|
||||
| **Moonshot** | Agentic coding | Kimi K2.5 with 262K context |
|
||||
| **Cerebras** | Speed | Up to 2,600 tokens/sec |
|
||||
| **AWS Bedrock** | Enterprise | Advanced features |
|
||||
| **Ollama** | Privacy | Run models locally |
|
||||
|
||||
See the [full provider list](/getting-started/authorizing-with-cline) for all 30+ supported providers including xAI Grok, Mistral, Groq, Fireworks, Together, Baseten, SambaNova, Nebius, Hugging Face, and more.
|
||||
|
||||
<Info>
|
||||
**Recommended for beginners:** Start with **Cline** as your provider - no API key management needed, instant access to multiple models, and occasional free inferencing through partner providers.
|
||||
</Info>
|
||||
|
||||
### Step 3: Add Your API Key (or Sign In)
|
||||
|
||||
The next step depends on which provider you selected.
|
||||
|
||||
#### If you selected **Cline** as your provider:
|
||||
|
||||
- **No API key needed!** Simply sign in with your Cline account
|
||||
- Click the **Sign In** button when prompted
|
||||
- You'll be redirected to [app.cline.bot](https://app.cline.bot) to authenticate
|
||||
- After signing in, return to your IDE
|
||||
|
||||
<Note>
|
||||
For detailed information about the Cline authentication flow, OAuth tokens, and troubleshooting, see [Authorizing with Cline](/getting-started/authorizing-with-cline).
|
||||
</Note>
|
||||
|
||||
#### If you selected **OpenAI Codex** as your provider:
|
||||
|
||||
- **No API key needed!** If you have a ChatGPT subscription (Plus, Pro, or Team), you can use it directly in Cline
|
||||
- Click **"Sign in with OpenAI"** to authenticate via your browser
|
||||
- Once authorized, all models available on your OpenAI plan will appear automatically
|
||||
- Usage is governed by your ChatGPT subscription — no separate API billing
|
||||
|
||||
See the full [OpenAI Codex setup guide](/provider-config/openai-codex) for details.
|
||||
|
||||
#### If you selected any other provider:
|
||||
|
||||
You'll need to get an API key from your chosen provider:
|
||||
|
||||
1. **Visit your provider's website to get an API key:**
|
||||
- **Anthropic**: [console.anthropic.com](https://console.anthropic.com/)
|
||||
- **OpenRouter**: [openrouter.ai/keys](https://openrouter.ai/keys)
|
||||
- **OpenAI**: [platform.openai.com/api-keys](https://platform.openai.com/api-keys)
|
||||
- **Google**: [aistudio.google.com/apikey](https://aistudio.google.com/apikey)
|
||||
- **Others**: See [Provider Setup Guide](/getting-started/authorizing-with-cline)
|
||||
|
||||
2. **Generate a new API key** on the provider's website
|
||||
|
||||
3. **Copy the API key** to your clipboard
|
||||
|
||||
4. **Paste your key** in the **"API Key"** field in Cline settings
|
||||
|
||||
5. **Save automatically** - Your key is stored securely in your editor's secrets storage
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/step3-API.png" alt="Cline API Selection" />
|
||||
</Frame>
|
||||
|
||||
<Warning>
|
||||
**Payment required for most providers**: Most providers need payment information before generating keys. You only pay for what you use (typically $0.01-$0.10 per coding task).
|
||||
</Warning>
|
||||
|
||||
### Step 4: Choose Your Model
|
||||
|
||||
Once your API key is added (or you've signed in), the **"Model"** dropdown becomes available.
|
||||
|
||||
<Frame>
|
||||
<img src="https://storage.googleapis.com/cline_public_images/step4-model.png" alt="Cline Model Selection" />
|
||||
</Frame>
|
||||
|
||||
**Quick model selection guide:**
|
||||
|
||||
| Your Priority | Choose This Model | Why |
|
||||
|---------------|-------------------|-----|
|
||||
| **Maximum reliability** | Claude Sonnet 4.5 | Most reliable tool usage, excellent at complex tasks |
|
||||
| **Best value** | DeepSeek V3 or Qwen3 Coder | Great performance at budget prices |
|
||||
| **Fastest speed** | Qwen3 Coder on Cerebras | Lightning-fast responses |
|
||||
| **Run locally** | Any Ollama model | Complete privacy, no internet needed |
|
||||
| **Latest features** | GPT-5 | OpenAI's newest capabilities |
|
||||
|
||||
Not sure which to pick? Start with **Claude Sonnet 4.5** for reliability or **DeepSeek V3** for value.
|
||||
|
||||
<Tip>
|
||||
You can switch models at any time without losing your conversation. Try different models to find what works best for your specific tasks.
|
||||
</Tip>
|
||||
|
||||
See the [model comparison tables](#current-top-models) below for detailed specifications and pricing.
|
||||
|
||||
### Step 5: Start Using Cline
|
||||
|
||||
**Congratulations! You're all set up.** Here's how to start coding with Cline:
|
||||
|
||||
1. **Type your request** in the Cline chat box
|
||||
- Example: "Create a React component for a login form"
|
||||
- Example: "Debug this TypeScript error"
|
||||
- Example: "Refactor this function to be more efficient"
|
||||
|
||||
2. **Press Enter** or click the send icon to submit
|
||||
|
||||
## Choosing the Right Model
|
||||
|
||||
Selecting the right model involves balancing several factors. Use this framework to find your ideal match:
|
||||
|
||||
<Note>
|
||||
**Pro tips**: Configure separate models for Plan Mode and Act Mode. Make the most out the each model's strengths. For example, use a budget model for planning discussions and a premium model for implementation.
|
||||
</Note>
|
||||
|
||||
### Key Selection Factors
|
||||
|
||||
| Factor | What to Consider | Recommendation |
|
||||
|--------|------------------|----------------|
|
||||
| **Task Complexity** | Simple fixes vs complex refactoring | Budget models for routine tasks; Premium models for complex work |
|
||||
| **Budget** | Monthly spending capacity | \$10-\$30: Budget, \$30-\$100: Mid-tier, \$100+: Premium |
|
||||
| **Context Window** | Project size and file count | Small: 32K-128K, Medium: 128K-200K, Large: 400K+ |
|
||||
| **Speed** | Response time requirements | Interactive: Fast models, Background: Reasoning models OK |
|
||||
| **Tool Reliability** | Complex operations | Claude excels at tool usage; Test others with your workflow |
|
||||
| **Provider** | Access and pricing needs | OpenRouter: Many options, Direct: Faster/reliable, Local: Privacy |
|
||||
|
||||
|
||||
|
||||
## Model Comparison Resources
|
||||
|
||||
For detailed model comparisons and performance metrics, see:
|
||||
- [**Context Window Guide**](/model-config/context-windows) - Understanding and optimizing context usage
|
||||
|
||||
## Open Source vs Closed Source
|
||||
|
||||
### Open Source Advantages
|
||||
- **Multiple providers** compete to host them
|
||||
- **Cheaper pricing** due to competition
|
||||
- **Provider choice** - switch if one goes down
|
||||
- **Faster innovation** cycles
|
||||
|
||||
### Open Source Models Available
|
||||
- **Qwen3 Coder** (Apache 2.0)
|
||||
- **Z AI GLM 4.5** (MIT)
|
||||
- **Kimi K2** (Open source)
|
||||
- **DeepSeek series** (Various licenses)
|
||||
|
||||
## Quick Decision Matrix
|
||||
|
||||
| If you want... | Use this |
|
||||
|----------------|----------|
|
||||
| Something that just works | Claude Sonnet 4.5 |
|
||||
| To save money | DeepSeek V3 or Qwen3 variants |
|
||||
| Huge context windows | Gemini 2.5 Pro or Claude Sonnet 4.5 |
|
||||
| Open source | Qwen3 Coder, Z AI GLM 4.5, or Kimi K2 |
|
||||
| Latest tech | GPT-5 |
|
||||
| To use your ChatGPT subscription | [OpenAI Codex](/provider-config/openai-codex) — sign in with your OpenAI account, no API key needed |
|
||||
| Speed | Qwen3 Coder on Cerebras (fastest available) |
|
||||
|
||||
## What Others Are Using
|
||||
|
||||
Check [Vercel's leaderboard](https://vercel.com/ai-gateway/leaderboards) to see real usage patterns from the community.
|
||||
@@ -89,7 +89,7 @@ For complex tasks that need thorough analysis, use the `/deep-planning` slash co
|
||||
3. Creates a detailed implementation plan
|
||||
4. Asks clarifying questions before proceeding
|
||||
|
||||
The deep planning prompt is optimized for each model family, so it adapts to the strengths of whatever model you're using. See the [Deep Planning docs](/features/deep-planning) for more details.
|
||||
The deep planning prompt is optimized for each model family, so it adapts to the strengths of whatever model you're using. See [/deep-planning](/core-workflows/using-commands#deep-planning) for more details.
|
||||
|
||||
## Choosing the Right Approach by Task Size
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Using Commands"
|
||||
sidebarTitle: "Using Commands"
|
||||
description: "Built-in slash commands to manage context, plan implementations, and create reusable workflows."
|
||||
description: "Built-in slash commands to manage context, plan implementations, and trigger reusable skills."
|
||||
---
|
||||
|
||||
Cline provides slash commands in chat that help you manage your conversation and plan complex implementations.
|
||||
@@ -37,7 +37,7 @@ Use `/smol` when you're deep into a debugging session or brainstorming and need
|
||||
|
||||
### /newrule
|
||||
|
||||
`/newrule` creates a rule file that teaches Cline your preferences. Cline will guide you through setting up guidelines for communication style, coding standards, project context, and workflows. The rule is saved to your `.clinerules` directory and automatically loaded for future conversations.
|
||||
`/newrule` creates a rule file that teaches Cline your preferences. Cline will guide you through setting up guidelines for communication style, coding standards, project context, and reusable practices. The rule is saved to your `.clinerules` directory and automatically loaded for future conversations.
|
||||
|
||||
Use `/newrule` when you find yourself repeating the same instructions across tasks. For more about rules, see [Cline Rules](/customization/cline-rules).
|
||||
|
||||
@@ -50,7 +50,7 @@ Transform Cline into a meticulous architect who investigates your codebase, asks
|
||||
3. **Plan Creation** - Generates `implementation_plan.md` with detailed specifications
|
||||
4. **Task Creation** - Creates a new task with trackable implementation steps
|
||||
|
||||
Use `/deep-planning` for features touching multiple parts of your codebase, architectural changes, or complex integrations. For detailed documentation, see [Deep Planning](/features/deep-planning).
|
||||
Use `/deep-planning` for features touching multiple parts of your codebase, architectural changes, or complex integrations.
|
||||
|
||||
### /explain-changes
|
||||
|
||||
@@ -68,8 +68,14 @@ Use `/explain-changes` when reviewing code, onboarding to a new codebase, or und
|
||||
|
||||
Use `/reportbug` when you encounter unexpected behavior, crashes, or bugs you want to report.
|
||||
|
||||
## Custom Workflows
|
||||
## Skills via Slash Commands
|
||||
|
||||
Beyond the built-in slash commands, you can create your own workflow files that work the same way. Store Markdown files in `.clinerules/workflows/` and invoke them with `/your-workflow.md`.
|
||||
In addition to built-in commands, you can trigger enabled skills directly from chat using slash commands.
|
||||
|
||||
For a complete guide on creating and managing custom workflows, see [Workflows](/customization/workflows).
|
||||
- Type `/` to open command suggestions.
|
||||
- Select a skill command (for example, `/aws-deploy`).
|
||||
- Cline loads that skill and applies its `SKILL.md` instructions for the task.
|
||||
|
||||
Any enabled skill can be triggered this way, which gives you a fast path to skill-specific guidance without rewriting the same instructions each time.
|
||||
|
||||
For setup and management details, see [Skills](/customization/skills#triggering-skills-with-slash-commands).
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
---
|
||||
title: "Adding Context"
|
||||
sidebarTitle: "Adding Context"
|
||||
description: "Use @ mentions and drag & drop to bring files, terminal output, errors, git changes, and web content into your conversations."
|
||||
description: "Use @ mentions and drag & drop to bring files into your conversations."
|
||||
---
|
||||
|
||||
Cline works best when it has the right context, not just more context. @ mentions let you pull in exactly the files, errors, terminal output, or documentation that matter for your task. No copying, no pasting, no context switching.
|
||||
Cline works best when it has the right context, not just more context. `@` mentions let you pull in the files and folders that matter for your task — no copying, no pasting, no context switching.
|
||||
|
||||
You can add context two ways:
|
||||
- Type `@` in the chat input and select what you want
|
||||
- Click the **+** button in the bottom left to browse files, images, or mentions
|
||||
|
||||
<Tip>
|
||||
**Want to learn more about managing context?** Watch [Adding Context with @ Mentions](https://youtu.be/7j6R75Dvj1Y) to see it in action.
|
||||
</Tip>
|
||||
- Type `@` in the chat input and select a file or folder
|
||||
- Click the **+** button in the bottom left to browse files or images
|
||||
|
||||
## Quick Reference
|
||||
|
||||
@@ -20,11 +16,8 @@ You can add context two ways:
|
||||
|---------------|--------|---------|
|
||||
| File content | `@/path/to/file` | `@/src/index.ts` |
|
||||
| Folder contents | `@/path/to/folder/` | `@/src/components/` |
|
||||
| Workspace errors | `@problems` | `@problems` |
|
||||
| Terminal output | `@terminal` | `@terminal` |
|
||||
| Uncommitted changes | `@git-changes` | `@git-changes` |
|
||||
| Specific commit | `@<commit-hash>` | `@a1b2c3d` |
|
||||
| Web page | `@<url>` | `@https://react.dev/learn` |
|
||||
|
||||
For other context — git history, web pages, terminal errors — just describe it. Cline will run `git log`, fetch the URL, or read the output itself.
|
||||
|
||||
## File Mentions
|
||||
|
||||
@@ -46,59 +39,6 @@ Explain how the components in @/src/components/auth/ work together.
|
||||
In multi-root workspaces, prefix paths with the workspace name: `@workspace-name:/path/to/file`
|
||||
</Note>
|
||||
|
||||
## Problem Mentions
|
||||
|
||||
Use `@problems` to share all errors and warnings from your workspace's Problems panel.
|
||||
|
||||
```text
|
||||
@problems Can you fix these TypeScript errors?
|
||||
```
|
||||
|
||||
## Terminal Mentions
|
||||
|
||||
Use `@terminal` to share recent terminal output. Perfect for debugging build errors or test failures.
|
||||
|
||||
```text
|
||||
@terminal The build is failing. What's wrong?
|
||||
```
|
||||
|
||||
## Git Mentions
|
||||
|
||||
Reference uncommitted changes with `@git-changes`:
|
||||
|
||||
```text
|
||||
@git-changes Review my changes before I commit.
|
||||
```
|
||||
|
||||
Reference specific commits with `@<commit-hash>` (7-40 character hex):
|
||||
|
||||
```text
|
||||
What did @a1b2c3d change?
|
||||
```
|
||||
|
||||
## URL Mentions
|
||||
|
||||
Reference web content with `@https://example.com`. Cline fetches the page content.
|
||||
|
||||
```text
|
||||
Implement the pattern described in @https://react.dev/learn/scaling-up-with-reducer-and-context
|
||||
```
|
||||
|
||||
## Combining Mentions
|
||||
|
||||
Combine multiple @ mentions for comprehensive context:
|
||||
|
||||
```text
|
||||
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
|
||||
```
|
||||
|
||||
## Drag & Drop
|
||||
|
||||
Drag files directly into the chat input to add them to your conversation.
|
||||
|
||||
@@ -51,7 +51,7 @@ your-project/
|
||||
|
||||
Cline processes all `.md` and `.txt` files inside `.clinerules/`, combining them into a unified set of rules. Numeric prefixes (like `01-coding.md`) help organize files but are optional.
|
||||
|
||||
When both workspace and global rules exist, Cline combines them. Workspace rules take precedence when they conflict with global rules. See [Storage Locations](/customization/overview#storage-locations) for more guidance.
|
||||
When both workspace and global rules exist, Cline combines them. Workspace rules take precedence when they conflict with global rules. See [Storage Locations](/getting-started/config#storage-locations) for more guidance.
|
||||
|
||||
### Global Rules Directory
|
||||
|
||||
|
||||
@@ -107,4 +107,3 @@ You can still reference ignored files explicitly using [@ mentions](/core-workfl
|
||||
- [Cline Rules](/customization/cline-rules) - Define persistent instructions for Cline
|
||||
- [Task Management](/core-workflows/task-management#context-window) - Understand how context windows work
|
||||
- [Auto-Compact](/features/auto-compact) - Automatic context compression during long tasks
|
||||
- [Memory Bank](/features/memory-bank) - Structured documentation for cross-session context
|
||||
|
||||
@@ -1,509 +1,7 @@
|
||||
---
|
||||
title: "Hooks"
|
||||
sidebarTitle: "Hooks"
|
||||
description: "Inject custom logic into Cline's workflow to validate operations and shape Cline's decisions."
|
||||
description: "See details under SDK Hooks page."
|
||||
---
|
||||
|
||||
Hooks are scripts that run at key moments in Cline's workflow. Because they execute at known points with consistent inputs and outputs, hooks bring determinism to the non-deterministic nature of AI models by enforcing guardrails, validations, and context injection. You can validate operations before they execute, monitor tool usage, and shape how Cline makes decisions.
|
||||
|
||||
## What You Can Build
|
||||
|
||||
- Stop operations before they cause problems (like creating `.js` files in a TypeScript project)
|
||||
- Run linters or custom validators before files get saved
|
||||
- Prevent operations that violate security policies
|
||||
- Track everything for analytics or compliance
|
||||
- Trigger external tools or services at the right moments
|
||||
- Add context to the conversation based on what Cline is doing
|
||||
|
||||
## Hook Types
|
||||
|
||||
Cline supports 8 hook types that run at different points in the task lifecycle:
|
||||
|
||||
| Hook Type | When It Runs |
|
||||
|-----------|--------------|
|
||||
| TaskStart | When you start a new task |
|
||||
| TaskResume | When you resume an interrupted task |
|
||||
| TaskCancel | When you cancel a running task |
|
||||
| TaskComplete | When a task finishes successfully |
|
||||
| PreToolUse | Before Cline executes a tool (read_file, write_to_file, etc.) |
|
||||
| PostToolUse | After a tool execution completes |
|
||||
| UserPromptSubmit | When you submit a message to Cline |
|
||||
| PreCompact | Before Cline truncates conversation history to free up context |
|
||||
|
||||
## Hook Lifecycle
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
%% Styling
|
||||
classDef hook fill:#FFB74D,stroke:#E65100,stroke-width:2px,color:black,rx:5,ry:5;
|
||||
classDef state fill:#E1F5FE,stroke:#0277BD,stroke-width:2px,color:black;
|
||||
classDef action fill:#FFFFFF,stroke:#333,stroke-width:1px,color:black,stroke-dasharray: 5 5;
|
||||
|
||||
%% Entry Points
|
||||
Start((Start)) --> CheckType{New or<br/>Resume?}
|
||||
|
||||
%% Initialization Hooks
|
||||
CheckType -- New Task --> H_Start[TaskStart]:::hook
|
||||
CheckType -- Resume --> H_Resume[TaskResume]:::hook
|
||||
|
||||
%% Main Loop
|
||||
H_Start --> Loop(Task Active Loop):::state
|
||||
H_Resume --> Loop
|
||||
|
||||
subgraph Conversation Cycle
|
||||
direction TB
|
||||
Loop -- User sends message --> H_Submit[UserPromptSubmit]:::hook
|
||||
H_Submit --> Thinking[Cline Processes Context]:::state
|
||||
|
||||
%% Context Compaction Path
|
||||
Thinking -. Context Limit Reached .-> H_Compact[PreCompact]:::hook
|
||||
H_Compact -.-> Thinking
|
||||
|
||||
%% Tool Execution Path
|
||||
Thinking -- Decides to use tool --> H_PreTool[PreToolUse]:::hook
|
||||
H_PreTool -- Allowed --> ToolExec[Tool Executes]:::action
|
||||
H_PreTool -- Cancelled --> Thinking
|
||||
ToolExec --> H_PostTool[PostToolUse]:::hook
|
||||
H_PostTool --> Thinking
|
||||
end
|
||||
|
||||
%% Termination Paths
|
||||
Thinking -- Task Successfully Finished --> H_Complete[TaskComplete]:::hook
|
||||
Loop -- User Cancels Task --> H_Cancel[TaskCancel]:::hook
|
||||
|
||||
%% End
|
||||
H_Complete --> End((End))
|
||||
H_Cancel --> End
|
||||
```
|
||||
|
||||
The diagram shows the complete hook lifecycle:
|
||||
|
||||
1. **Entry**: When you start a task, either **TaskStart** (new task) or **TaskResume** (interrupted task) runs first
|
||||
2. **Conversation Cycle**: Each time you send a message, **UserPromptSubmit** runs, then Cline processes your request
|
||||
3. **Tool Execution**: When Cline decides to use a tool, **PreToolUse** runs first-if allowed, the tool executes, then **PostToolUse** runs
|
||||
4. **Context Management**: If the conversation approaches context limits, **PreCompact** runs before truncation
|
||||
5. **Exit**: The task ends with either **TaskComplete** (success) or **TaskCancel** (user cancellation)
|
||||
|
||||
Orange nodes represent hooks where you can inject custom logic. The cycle repeats as you continue the conversation.
|
||||
|
||||
## Hook Locations
|
||||
|
||||
Hooks can be stored globally or in a project workspace. See [Storage Locations](/customization/overview#storage-locations) for guidance on when to use each.
|
||||
|
||||
- **Global hooks**: `~/Documents/Cline/Hooks/`
|
||||
- **Project hooks**: `.clinerules/hooks/` in your repo (can be committed to version control)
|
||||
|
||||
When both global and workspace hooks exist for the same hook type, both run. Global hooks execute first, then workspace hooks. If either returns `cancel: true`, the operation stops.
|
||||
|
||||
## Creating a Hook
|
||||
|
||||
<Steps>
|
||||
<Step title="Open the Hooks tab">
|
||||
Click the scale icon at the bottom of the Cline panel, to the left of the model selector. Switch to the Hooks tab.
|
||||
</Step>
|
||||
<Step title="Create a new hook">
|
||||
Click **"New hook..."** dropdown and select a hook type (e.g., PreToolUse, TaskStart).
|
||||
</Step>
|
||||
<Step title="Review the hook's code">
|
||||
Click the pencil icon to open and edit the hook script. Cline generates a template with examples.
|
||||
</Step>
|
||||
<Step title="Enable the hook">
|
||||
Toggle the switch to activate the hook once you understand what it does.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
Always review a hook's code before enabling it. Hooks execute automatically during your workflow and can block operations or run shell commands.
|
||||
</Warning>
|
||||
|
||||
## Quick Start: Your First Hook
|
||||
|
||||
Let's create a simple hook that logs every file Cline reads or writes. You'll see results in seconds.
|
||||
|
||||
### The Hook
|
||||
|
||||
Create a file called `file-logger` in your hooks directory with this content:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Logs all file operations to ~/cline-activity.log
|
||||
|
||||
INPUT=$(cat)
|
||||
TOOL=$(echo "$INPUT" | jq -r '.preToolUse.tool')
|
||||
FILE_PATH=$(echo "$INPUT" | jq -r '.preToolUse.parameters.path // "N/A"')
|
||||
|
||||
# Log to file
|
||||
echo "$(date '+%H:%M:%S') - $TOOL: $FILE_PATH" >> ~/cline-activity.log
|
||||
|
||||
# Always allow the operation
|
||||
echo '{"cancel":false}'
|
||||
```
|
||||
|
||||
### Setup
|
||||
|
||||
<Steps>
|
||||
<Step title="Create the hook file">
|
||||
Save the script above as `~/Documents/Cline/Hooks/file-logger` or create it through the Hooks UI.
|
||||
</Step>
|
||||
<Step title="Make it executable">
|
||||
On macOS/Linux, run `chmod +x ~/Documents/Cline/Hooks/file-logger`.
|
||||
</Step>
|
||||
<Step title="Enable it (macOS/Linux only)">
|
||||
In Cline's Hooks tab, find "file-logger" under PreToolUse hooks and toggle it on.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
On Windows, hooks are executed with PowerShell and run whenever the hook file exists. In this
|
||||
foundation PR, hook enable/disable toggling is not yet supported on Windows.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Coming next: JSON-backed hook enabled/disabled state across platforms, so toggle behavior is
|
||||
consistent on Windows, macOS, and Linux.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Hook filenames are platform-specific:
|
||||
|
||||
- **Windows**: only `HookName.ps1` is supported (PowerShell script files)
|
||||
- **macOS/Linux**: only extensionless `HookName` is supported (executable files like bash scripts or binaries)
|
||||
|
||||
Wrong-platform naming is ignored by hook discovery.
|
||||
</Note>
|
||||
|
||||
### Test It
|
||||
|
||||
Ask Cline to read any file in your project: "What's in package.json?"
|
||||
|
||||
Then check the log:
|
||||
|
||||
```bash
|
||||
cat ~/cline-activity.log
|
||||
```
|
||||
|
||||
You'll see entries like:
|
||||
```text
|
||||
14:23:45 - read_file: /path/to/package.json
|
||||
14:23:47 - search_files: /path/to/src
|
||||
```
|
||||
|
||||
### Customize It
|
||||
|
||||
Try modifying the hook to:
|
||||
- Filter specific file types (only log `.ts` files)
|
||||
- Add the task ID to each log entry
|
||||
- Send notifications for write operations
|
||||
- Block operations on certain paths
|
||||
|
||||
The sections below explain how hooks receive input and return output, plus more examples.
|
||||
|
||||
## How Hooks Work
|
||||
|
||||
Hooks are executable scripts that receive JSON input via stdin and return JSON output via stdout.
|
||||
|
||||
### Input Structure
|
||||
|
||||
Every hook receives a JSON object with common fields plus hook-specific data:
|
||||
|
||||
```json
|
||||
{
|
||||
"taskId": "abc123",
|
||||
"hookName": "PreToolUse",
|
||||
"clineVersion": "3.17.0",
|
||||
"timestamp": "1736654400000",
|
||||
"workspaceRoots": ["/path/to/project"],
|
||||
"userId": "user_123",
|
||||
"model": {
|
||||
"provider": "openrouter",
|
||||
"slug": "anthropic/claude-sonnet-4.5"
|
||||
},
|
||||
|
||||
// Hook-specific field (name matches hook type in camelCase)
|
||||
"taskStart": {
|
||||
"task": "Add authentication to the API"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`model.provider` and `model.slug` are machine-stable identifiers for the active provider/model at hook execution time. If unavailable, Cline sends deterministic fallback values: `"unknown"`.
|
||||
|
||||
<Note>
|
||||
Migration note for existing hook scripts:
|
||||
|
||||
- `timestamp` is a string (milliseconds since epoch), not a number
|
||||
- `workspaceRoots` is an array of workspace root paths and replaces the old singular `workspacePath`
|
||||
|
||||
If your scripts previously read `.workspacePath`, switch to `.workspaceRoots[0]` (or iterate all roots).
|
||||
</Note>
|
||||
|
||||
The hook-specific field name matches the hook type:
|
||||
- `taskStart`, `taskResume`, `taskCancel`, `taskComplete` contain `{ task: string }`
|
||||
- `preToolUse` contains `{ tool: string, parameters: object }`
|
||||
- `postToolUse` contains `{ tool: string, parameters: object, result: string, success: boolean, durationMs: number }`
|
||||
- `userPromptSubmit` contains `{ prompt: string }`
|
||||
- `preCompact` contains `{ conversationLength: number, estimatedTokens: number }`
|
||||
|
||||
### Output Structure
|
||||
|
||||
Hooks return a JSON object to stdout:
|
||||
|
||||
```json
|
||||
{
|
||||
"cancel": false,
|
||||
"contextModification": "Optional text to add to the conversation",
|
||||
"errorMessage": ""
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `cancel` | boolean | If `true`, stops the operation (blocks the tool, cancels the task start, etc.) |
|
||||
| `contextModification` | string | Optional text that gets injected into the conversation as context for Cline |
|
||||
| `errorMessage` | string | Shown to the user if `cancel` is `true` |
|
||||
|
||||
### Context Modification
|
||||
|
||||
The `contextModification` field lets hooks inject information into the conversation. This is useful for:
|
||||
|
||||
- Adding project-specific context when a task starts
|
||||
- Providing validation results that Cline should consider
|
||||
- Injecting environment information before tool execution
|
||||
|
||||
For example, a PreToolUse hook could add: `"Note: This file is auto-generated. Edits may be overwritten."`
|
||||
|
||||
## Hook Reference
|
||||
|
||||
### Task Lifecycle Hooks
|
||||
|
||||
#### TaskStart
|
||||
|
||||
Runs when you start a new task. Use it to:
|
||||
- Log task start time for analytics
|
||||
- Add project context to the conversation
|
||||
- Check prerequisites before work begins
|
||||
- Notify external systems (Slack, issue trackers)
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
INPUT=$(cat)
|
||||
TASK=$(echo "$INPUT" | jq -r '.taskStart.task')
|
||||
echo "[TaskStart] Starting: $TASK" >&2
|
||||
echo '{"cancel":false,"contextModification":"","errorMessage":""}'
|
||||
```
|
||||
|
||||
#### TaskResume
|
||||
|
||||
Runs when you resume an interrupted task (instead of TaskStart). Use it to:
|
||||
- Check for changes since the task was paused
|
||||
- Refresh context with latest project state
|
||||
- Notify that work is resuming
|
||||
|
||||
#### TaskCancel
|
||||
|
||||
Runs when you cancel a running task. Use it to:
|
||||
- Clean up temporary files or resources
|
||||
- Notify external systems about cancellation
|
||||
- Log cancellation for analytics
|
||||
|
||||
#### TaskComplete
|
||||
|
||||
Runs when a task completes successfully. Use it to:
|
||||
- Run tests or validation after changes
|
||||
- Generate reports or summaries
|
||||
- Notify stakeholders
|
||||
- Trigger CI/CD pipelines
|
||||
|
||||
### Tool Hooks
|
||||
|
||||
#### PreToolUse
|
||||
|
||||
Runs before any tool executes. This is the most powerful hook for validation and safety. Use it to:
|
||||
- Block dangerous operations
|
||||
- Validate parameters before execution
|
||||
- Add context about the file or resource being accessed
|
||||
- Log tool usage
|
||||
|
||||
The input includes the tool name and its parameters:
|
||||
|
||||
```json
|
||||
{
|
||||
"preToolUse": {
|
||||
"tool": "write_to_file",
|
||||
"parameters": {
|
||||
"path": "src/config.ts",
|
||||
"content": "..."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example that blocks `.js` files in a TypeScript project:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
INPUT=$(cat)
|
||||
TOOL=$(echo "$INPUT" | jq -r '.preToolUse.tool')
|
||||
FILE_PATH=$(echo "$INPUT" | jq -r '.preToolUse.parameters.path // empty')
|
||||
|
||||
if [[ "$TOOL" == "write_to_file" && "$FILE_PATH" == *.js ]]; then
|
||||
echo '{"cancel":true,"errorMessage":"Use .ts files instead of .js in this TypeScript project"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo '{"cancel":false}'
|
||||
```
|
||||
|
||||
#### PostToolUse
|
||||
|
||||
Runs after a tool completes (success or failure). Use it to:
|
||||
- Audit tool usage
|
||||
- Validate results
|
||||
- Trigger follow-up actions
|
||||
- Monitor performance
|
||||
|
||||
The input includes execution results:
|
||||
|
||||
```json
|
||||
{
|
||||
"postToolUse": {
|
||||
"tool": "execute_command",
|
||||
"parameters": { "command": "npm test" },
|
||||
"result": "All tests passed",
|
||||
"success": true,
|
||||
"durationMs": 3450
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
PostToolUse hooks can return `cancel: true` to stop the task, but they cannot undo the tool execution that already happened.
|
||||
</Note>
|
||||
|
||||
### Other Hooks
|
||||
|
||||
#### UserPromptSubmit
|
||||
|
||||
Runs when you send a message to Cline. Use it to:
|
||||
- Log prompts for analytics
|
||||
- Add context based on prompt content
|
||||
- Validate or sanitize prompts
|
||||
|
||||
#### PreCompact
|
||||
|
||||
Runs before Cline truncates conversation history to stay within context limits. Use it to:
|
||||
- Archive important conversation parts before they're removed
|
||||
- Log compaction events
|
||||
- Add a summary of what's being removed
|
||||
|
||||
The input includes context metrics:
|
||||
|
||||
```json
|
||||
{
|
||||
"preCompact": {
|
||||
"conversationLength": 45,
|
||||
"estimatedTokens": 125000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### TypeScript Enforcement
|
||||
|
||||
Block creation of `.js` files in a TypeScript project:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# PreToolUse hook
|
||||
|
||||
INPUT=$(cat)
|
||||
TOOL=$(echo "$INPUT" | jq -r '.preToolUse.tool')
|
||||
FILE_PATH=$(echo "$INPUT" | jq -r '.preToolUse.parameters.path // empty')
|
||||
|
||||
if [[ "$TOOL" == "write_to_file" && "$FILE_PATH" == *.js ]]; then
|
||||
echo '{"cancel":true,"errorMessage":"Use .ts files instead of .js in this TypeScript project"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo '{"cancel":false}'
|
||||
```
|
||||
|
||||
### Tool Usage Logging
|
||||
|
||||
Log all tool executions to a file:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# PostToolUse hook
|
||||
|
||||
INPUT=$(cat)
|
||||
TOOL=$(echo "$INPUT" | jq -r '.postToolUse.tool')
|
||||
SUCCESS=$(echo "$INPUT" | jq -r '.postToolUse.success')
|
||||
DURATION=$(echo "$INPUT" | jq -r '.postToolUse.durationMs')
|
||||
|
||||
echo "$(date -Iseconds) | $TOOL | success=$SUCCESS | ${DURATION}ms" >> ~/.cline-tool-log.txt
|
||||
|
||||
echo '{"cancel":false}'
|
||||
```
|
||||
|
||||
### Add Project Context on Task Start
|
||||
|
||||
Inject project-specific information when a task begins:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# TaskStart hook
|
||||
|
||||
INPUT=$(cat)
|
||||
WORKSPACE=$(echo "$INPUT" | jq -r '.workspaceRoots[0] // empty')
|
||||
|
||||
# Read project info if available
|
||||
if [[ -f "$WORKSPACE/.project-context" ]]; then
|
||||
CONTEXT=$(cat "$WORKSPACE/.project-context")
|
||||
echo "{\"cancel\":false,\"contextModification\":\"Project context: $CONTEXT\"}"
|
||||
else
|
||||
echo '{"cancel":false}'
|
||||
fi
|
||||
```
|
||||
|
||||
## CLI Support
|
||||
|
||||
Hooks are available in the [Cline CLI](/cline-cli/getting-started):
|
||||
|
||||
```bash
|
||||
# Enable hooks for a task
|
||||
cline "What does this repo do?" -s hooks_enabled=true
|
||||
|
||||
# Configure hooks globally
|
||||
cline config set hooks-enabled=true
|
||||
```
|
||||
|
||||
<Note>
|
||||
Windows hooks require PowerShell (`powershell.exe`) available on your PATH.
|
||||
</Note>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Hook not running?**
|
||||
- On macOS/Linux, check that the file is executable (`chmod +x hookname`)
|
||||
- On Windows, ensure PowerShell is available (`powershell -NoProfile -Command "$PSVersionTable.PSVersion"`)
|
||||
- On Windows, ensure the hook file is named `<HookName>.ps1` (for example `PreToolUse.ps1`)
|
||||
- On macOS/Linux, ensure the hook file uses extensionless `<HookName>` naming (for example `PreToolUse`)
|
||||
- On macOS/Linux, verify the hook is enabled (toggle is on in the Hooks tab)
|
||||
- Check that Hooks are enabled globally in Settings
|
||||
|
||||
**Hook output not parsed?**
|
||||
- Ensure output is valid JSON on a single line to stdout
|
||||
- Use stderr (`>&2`) for debug logging, not stdout
|
||||
- Check for trailing characters or newlines before the JSON
|
||||
|
||||
**Hook blocking unexpectedly?**
|
||||
- Review the hook's logic and test with sample input
|
||||
- Check both global and workspace hooks (both run if they exist)
|
||||
|
||||
## Related Features
|
||||
|
||||
- [Rules](/customization/cline-rules) define high-level guidance that hooks can enforce programmatically
|
||||
- [Checkpoints](/core-workflows/checkpoints) let you roll back if a hook didn't catch an issue
|
||||
- [Auto-Approve](/features/auto-approve) works well with hooks as safety nets
|
||||
See details under [SDK Plugins](/sdk/plugins).
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
title: "Overview"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Understand how Rules, Skills, Workflows, Hooks, and .clineignore work together to customize Cline."
|
||||
---
|
||||
|
||||
Out of the box, Cline is a general-purpose AI assistant. Customizations transform it into an expert on your codebase, your team's conventions, and your workflows. Instead of repeating the same instructions every task, you define them once and Cline follows them automatically.
|
||||
|
||||
Cline offers five systems for this: Rules, Skills, Workflows, Hooks, and .clineignore. Each serves a different purpose and activates at different times.
|
||||
|
||||
## Quick Comparison
|
||||
|
||||
| Feature | Purpose | When Active | Best For |
|
||||
|---------|---------|-------------|----------|
|
||||
| **[Rules](/customization/cline-rules)** | Define how Cline behaves | Always (or contextually) | Coding standards, project constraints, team conventions |
|
||||
| **[Skills](/customization/skills)** | Domain expertise loaded on-demand | Triggered by matching requests | Specialized knowledge, complex procedures, institutional expertise |
|
||||
| **[Workflows](/customization/workflows)** | Step-by-step task automation | Invoked with `/workflow.md` | Repetitive processes, release procedures, setup scripts |
|
||||
| **[Hooks](/customization/hooks)** | Inject custom logic at key moments | Automatically on specific events | Validation, enforcement, monitoring, automation triggers |
|
||||
| **[.clineignore](/customization/clineignore)** | Control file access | Always | Excluding dependencies, build artifacts, large data files |
|
||||
|
||||
## Understanding Each Tool
|
||||
|
||||
**[Rules](/customization/cline-rules)** are always-on guidance. Use them when you want Cline to consistently follow certain patterns: coding standards, naming conventions, architectural constraints, or project-specific context. Rules shape *how* Cline works across all tasks. For example, a rule might say "always use TypeScript" or "follow the repository pattern for data access."
|
||||
|
||||
**[Skills](/customization/skills)** are domain expertise that loads only when relevant. Use them when you have extensive knowledge that would waste context if always active. Cline sees skill descriptions at startup and activates the full instructions only when your request matches. A data analysis skill might include pandas patterns, visualization preferences, and output formats that Cline only loads when you're working with data files.
|
||||
|
||||
**[Workflows](/customization/workflows)** are explicit task scripts you invoke on demand. Use them when you have a repeatable multi-step process that should run the same way every time. Type `/release.md` and Cline executes your release sequence: bump version, run tests, update changelog, commit, tag, push. Workflows define *what* to do, step by step.
|
||||
|
||||
**[Hooks](/customization/hooks)** are programmatic guardrails that run automatically at key moments. Use them when you need to validate, enforce, or extend Cline's behavior with custom code. A hook might block `.js` file creation in a TypeScript project, run linters before saves, or notify external services after deployments.
|
||||
|
||||
**[.clineignore](/customization/clineignore)** controls which files and directories Cline can access. Use it to exclude dependencies, build artifacts, generated files, and large data files from Cline's context. This reduces token usage, lowers costs, and keeps Cline focused on the code that matters. It works like `.gitignore`: add patterns to a `.clineignore` file in your project root and matching files are automatically excluded.
|
||||
|
||||
### Example: A Release Process
|
||||
|
||||
Consider how all five work together for releasing a new version:
|
||||
|
||||
1. **Rules** ensure Cline follows your team's commit message format and versioning policy
|
||||
2. **Skills** offer deep knowledge about your CI/CD system that Cline loads when deployment questions arise
|
||||
3. **Workflows** provide the explicit `/release.md` sequence: bump version, update changelog, tag, push
|
||||
4. **Hooks** validate that tests pass before allowing any commit or that the changelog was actually updated
|
||||
5. **.clineignore** keeps build artifacts, `node_modules/`, and generated files out of Cline's context so it stays focused
|
||||
|
||||
## Storage Locations
|
||||
|
||||
All five systems support both global and project-specific configurations:
|
||||
|
||||
| System | Global Location | Project Location |
|
||||
|--------|-----------------|------------------|
|
||||
| Rules | `~/Documents/Cline/Rules/` | `.clinerules/` |
|
||||
| Skills | `~/.cline/skills/` | `.cline/skills/` |
|
||||
| Workflows | `~/Documents/Cline/Workflows/` | `.clinerules/workflows/` |
|
||||
| Hooks | `~/Documents/Cline/Hooks/` | `.clinerules/hooks/` |
|
||||
| .clineignore | N/A | `.clineignore` |
|
||||
|
||||
### When to Use Each
|
||||
|
||||
**Start with project storage.** Most customizations belong in your project's directory because they're tied to that specific codebase. Team coding standards, deployment workflows, and architectural constraints all live with the code they describe. This also means your customizations travel with the repository, so collaborators get them automatically and changes can be reviewed in pull requests.
|
||||
|
||||
**Use global storage for personal preferences.** If you find yourself adding the same customization to every project, move it to global storage. Your preferred communication style, personal productivity workflows, and tools you use everywhere belong here. Global customizations apply to all projects but stay out of version control, so they won't affect your teammates.
|
||||
|
||||
When names conflict, project-specific configurations take precedence (except for Skills, where global takes precedence). This lets you override global defaults for specific projects when needed.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
<Warning>
|
||||
Always review customizations before adding them to your projects. Only use customizations from sources you trust.
|
||||
</Warning>
|
||||
|
||||
Customizations are powerful. They shape how Cline writes code, execute commands automatically, and influence every interaction. Treat customization files with the same scrutiny you'd give any code running in your environment.
|
||||
|
||||
### Best Practices
|
||||
|
||||
Review any customization file before adding it to your project or global configuration. Understand what it does and why.
|
||||
|
||||
When downloading customizations from GitHub repositories, community shares, or other external sources, verify the source:
|
||||
- Is the author reputable?
|
||||
- Has the community reviewed it?
|
||||
- Does the code do what it claims?
|
||||
|
||||
Look for dangerous commands:
|
||||
- Shell commands that delete files (`rm`, `del`)
|
||||
- Commands that transmit data (`curl`, `wget` with POST)
|
||||
- File operations outside your project directory
|
||||
- Commands that modify system configuration
|
||||
|
||||
Keep your customizations in version control so you can track changes, review diffs, and roll back if something goes wrong. When creating hooks, use the most restrictive event triggers necessary. Don't run hooks on every file save if you only need them before commits.
|
||||
@@ -0,0 +1,138 @@
|
||||
---
|
||||
title: "Plugins"
|
||||
sidebarTitle: "Plugins"
|
||||
description: "Install and manage plugins that extend Cline with custom tools, hooks, and capabilities."
|
||||
---
|
||||
<Warning>
|
||||
This feature currently only applies to Cline SDK, CLI, and Kanban. This feature is not applicable on VSCode and JetBrains Extension for now.
|
||||
</Warning>
|
||||
|
||||
Plugins extend Cline with custom tools, lifecycle hooks, slash commands, and more. They can be installed globally (available in all sessions) or per-project.
|
||||
|
||||
## Installing Plugins via CLI
|
||||
|
||||
The `cline plugin install` command installs plugins from three source types:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Git Repository">
|
||||
```bash
|
||||
cline plugin install https://github.com/owner/repo.git
|
||||
cline plugin install git@github.com:owner/repo.git
|
||||
```
|
||||
|
||||
The installer clones the repository, installs production dependencies, and registers the plugin entry files.
|
||||
|
||||
To install a specific branch or tag, append `@ref`:
|
||||
|
||||
```bash
|
||||
cline plugin install https://github.com/owner/repo.git@v1.2.0
|
||||
cline plugin install https://github.com/owner/repo.git@main
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="npm Package">
|
||||
```bash
|
||||
cline plugin install npm:@scope/my-plugin
|
||||
cline plugin install --npm my-plugin
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Local Path">
|
||||
```bash
|
||||
cline plugin install ./my-plugin
|
||||
cline plugin install ~/plugins/my-tool
|
||||
cline plugin install /absolute/path/to/plugin.ts
|
||||
```
|
||||
|
||||
Local installs copy the file or directory into the plugin store. Both single `.ts`/`.js` files and directories with a `package.json` are supported.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Additional flags:
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--force` | Replace an existing install for the same source |
|
||||
| `--json` | Output the result as JSON (useful for scripting) |
|
||||
| `--cwd <path>` | Install to `<path>/.cline/plugins` instead of the global directory |
|
||||
|
||||
After installation, confirm the plugin is loaded by running `cline config` and checking the plugin tab.
|
||||
|
||||
### Example: TypeScript Navigation Plugin
|
||||
|
||||
The [typescript-lsp-plugin](https://github.com/cline/typescript-lsp-plugin) is a good reference for how plugins work. It adds a `goto_definition` tool that uses the TypeScript Language Service API to resolve symbol definitions through imports, re-exports, and type aliases.
|
||||
|
||||
Install it with:
|
||||
|
||||
```bash
|
||||
cline plugin install https://github.com/cline/typescript-lsp-plugin.git
|
||||
```
|
||||
|
||||
Once installed, Cline can call `goto_definition` with a file path and line number to find where symbols are defined, which is much more precise than text search.
|
||||
|
||||
## Plugin Manifest Format
|
||||
|
||||
For a repository or npm package to be installable as a Cline plugin, its `package.json` should include a `cline` field that declares plugin entry points:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-cline-plugin",
|
||||
"version": "1.0.0",
|
||||
"cline": {
|
||||
"plugins": [
|
||||
{
|
||||
"paths": ["./index.ts"],
|
||||
"capabilities": ["tools", "hooks"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `cline.plugins` array accepts:
|
||||
|
||||
| Format | Example |
|
||||
|--------|---------|
|
||||
| Object with `paths` array | `{ "paths": ["./src/plugin.ts"], "capabilities": ["tools"] }` |
|
||||
| Plain string | `"./index.ts"` |
|
||||
|
||||
Each path should point to a `.ts` or `.js` file that exports an `AgentExtension` (either as the default export or a named export).
|
||||
|
||||
If no `cline.plugins` field is present, the installer falls back to auto-discovery: it looks for standard entry points, then recursively scans for `.ts` and `.js` files (skipping `node_modules` and `.git`).
|
||||
|
||||
### Host-Provided Dependencies
|
||||
|
||||
Dependencies under the `@cline/` scope (like `@cline/core`, `@cline/shared`) are provided by the host runtime. The installer automatically strips these from the plugin's dependency list before running `npm install`, so you should declare them as `peerDependencies`:
|
||||
|
||||
```json
|
||||
{
|
||||
"peerDependencies": {
|
||||
"@cline/core": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@cline/core": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin Directory Structure
|
||||
|
||||
Plugins are stored in the `plugins` directory at two levels:
|
||||
|
||||
```
|
||||
~/.cline/
|
||||
plugins/ # Global plugins
|
||||
_installed/ # Managed by `cline plugin install`
|
||||
npm/ # npm-sourced plugins
|
||||
git/ # git-sourced plugins
|
||||
local/ # local-sourced plugins
|
||||
|
||||
.cline/ # Project root
|
||||
plugins/ # Project-scoped plugins
|
||||
```
|
||||
|
||||
Global plugins (`~/.cline/plugins/`) are available across all sessions. Project plugins (`.cline/plugins/` in your repo) are available only when working in that project.
|
||||
|
||||
## Writing Plugins
|
||||
|
||||
For a guide on building plugins with the SDK, see [Writing Plugins](/sdk/guides/writing-plugins). For the plugin API reference, see [SDK Plugins](/sdk/plugins).
|
||||
@@ -4,7 +4,7 @@ sidebarTitle: "Skills"
|
||||
description: "Modular instruction sets that extend Cline's capabilities for specific tasks."
|
||||
---
|
||||
|
||||
Skills are modular instruction sets that extend Cline's capabilities for specific tasks. Each skill packages detailed guidance, workflows, and optional resources that Cline loads only when relevant to your request.
|
||||
Skills are modular instruction sets that extend Cline's capabilities for specific tasks. Each skill packages detailed guidance, processes, and optional resources that Cline loads only when relevant to your request.
|
||||
|
||||
Install multiple skills and Cline only loads what it needs. A deployment skill stays dormant until you ask about deploying. Unlike [rules](/customization/cline-rules) (which are always active), skills load on-demand so they don't consume context when you're working on something unrelated.
|
||||
|
||||
@@ -24,6 +24,16 @@ Skills use progressive loading to maximize efficiency:
|
||||
|
||||
When you send a message, Cline sees a list of available skills with their descriptions. If your request matches a skill's description, Cline activates it using the `use_skill` tool, which loads the full instructions from SKILL.md.
|
||||
|
||||
## Triggering Skills with Slash Commands
|
||||
|
||||
You can also invoke enabled skills explicitly from the chat input using slash commands.
|
||||
|
||||
1. Type `/` in chat to open command suggestions.
|
||||
2. Select the skill command you want to run (for example, `/aws-deploy`).
|
||||
3. Cline triggers that skill and loads its `SKILL.md` instructions.
|
||||
|
||||
This is useful when you want to force a specific skill immediately instead of waiting for auto-matching based on description.
|
||||
|
||||
## Skill Structure
|
||||
|
||||
Every skill is a directory containing a `SKILL.md` file with YAML frontmatter.
|
||||
@@ -138,7 +148,7 @@ Include real examples. Show what commands to run, what output to expect, and wha
|
||||
|
||||
## Where Skills Live
|
||||
|
||||
Skills can be stored globally or in a project workspace. See [Storage Locations](/customization/overview#storage-locations) for guidance on when to use each.
|
||||
Skills can be stored globally or in a project workspace. See [Storage Locations](/getting-started/config#storage-locations) for guidance on when to use each.
|
||||
|
||||
Project skills:
|
||||
- `.cline/skills/` (recommended)
|
||||
@@ -215,7 +225,7 @@ Cline reads documentation files using `read_file` when the instructions referenc
|
||||
| Use Scripts For | Use Instructions For |
|
||||
|-----------------|---------------------|
|
||||
| Deterministic operations (validation, formatting) | Flexible guidance that adapts to context |
|
||||
| Complex computations | Decision-making workflows |
|
||||
| Complex computations | Decision-making processes |
|
||||
| Operations that need reliability | Steps that might vary by situation |
|
||||
| Anything you'd rather not consume tokens explaining | Best practices and patterns |
|
||||
|
||||
@@ -231,7 +241,7 @@ description: Analyze data files and generate insights. Use when working with CSV
|
||||
|
||||
# Data Analysis
|
||||
|
||||
When analyzing data files, follow this workflow:
|
||||
When analyzing data files, follow this process:
|
||||
|
||||
## 1. Understand the Data
|
||||
- Read a sample of the file to understand its structure
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
---
|
||||
title: "Workflows"
|
||||
sidebarTitle: "Workflows"
|
||||
description: "Automate repetitive tasks with Markdown-based workflow files."
|
||||
---
|
||||
|
||||
Workflows are Markdown files that define a series of steps to guide Cline through repetitive or complex tasks. Type `/` followed by the workflow's filename to invoke it (e.g., `/deploy.md`).
|
||||
|
||||
Deploying, setting up a new project, running through a release checklist: these tasks often require remembering a dozen steps, running commands in the right order, and updating files manually. Mess up one step and you're debugging for an hour. Workflows turn those multi-step processes into one command. Type `/release.md` and Cline handles the version bump, runs tests, updates the changelog, commits, tags, and pushes. You just review and approve.
|
||||
|
||||
## Workflow Structure
|
||||
|
||||
A workflow is a markdown file with a title and steps. The filename becomes the command: `demo-workflow.md` is invoked with `/demo-workflow.md`.
|
||||
|
||||
````markdown title="demo-workflow.md"
|
||||
# Demo Workflow
|
||||
|
||||
Brief description of what this workflow accomplishes.
|
||||
|
||||
## Step 1: Check prerequisites
|
||||
Verify the environment is ready. Look for required tools and dependencies.
|
||||
|
||||
## Step 2: Run the build
|
||||
Execute the build command:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Step 3: Verify results
|
||||
Check that the build completed successfully and report any issues.
|
||||
````
|
||||
|
||||
Steps can be written at different levels of detail:
|
||||
|
||||
- **High-level**: "Run the test suite and fix any failures" lets Cline decide how to accomplish the goal
|
||||
- **Specific**: Use XML tool syntax or exact commands when you need precise control
|
||||
|
||||
## Creating Workflows
|
||||
|
||||
<Steps>
|
||||
<Step title="Open the Workflows menu">
|
||||
Click the scale icon at the bottom of the Cline panel, to the left of the model selector. Switch to the Workflows tab.
|
||||
</Step>
|
||||
<Step title="Create a new workflow file">
|
||||
Click "New workflow file..." and enter a filename (e.g., `deploy`). The file will be created with a `.md` extension.
|
||||
</Step>
|
||||
<Step title="Write your workflow">
|
||||
Add a title and numbered steps in markdown format. Describe what each step should accomplish.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Tip>
|
||||
**Create workflows from completed tasks.** After finishing something you'll need to repeat, tell Cline: "Create a workflow for the process I just completed." Cline analyzes the conversation, identifies the steps, and generates the workflow file. Your accumulated context becomes reusable automation.
|
||||
</Tip>
|
||||
|
||||
### Invoking Workflows
|
||||
|
||||
Type `/` in the chat input to see available workflows. Cline shows autocomplete suggestions as you type, so `/rel` would match `release-prep.md`. Select a workflow and press Enter to start it.
|
||||
|
||||
Cline executes each step in sequence, pausing for your approval when needed. You can stop a workflow at any point by rejecting a step.
|
||||
|
||||
### Toggling Workflows
|
||||
|
||||
Every workflow has a toggle to enable or disable it. This lets you control which workflows appear in the `/` menu without deleting the file.
|
||||
|
||||
## Where Workflows Live
|
||||
|
||||
Workflows can be stored in two locations: your project workspace or globally on your system.
|
||||
|
||||
**Workspace workflows** go in `.clinerules/workflows/` at your project root. Use these for project-specific automation like deployment scripts, release processes, or setup procedures that your team shares.
|
||||
|
||||
**Global workflows** go in your system's Cline Workflows directory. Use these for personal productivity workflows you use across all projects.
|
||||
|
||||
### Global Workflows Directory
|
||||
|
||||
| Operating System | Default Location |
|
||||
|------------------|------------------|
|
||||
| Windows | `Documents\Cline\Workflows` |
|
||||
| macOS | `~/Documents/Cline/Workflows` |
|
||||
| Linux/WSL | `~/Documents/Cline/Workflows` |
|
||||
|
||||
Workspace workflows take precedence when names match global workflows. See [Storage Locations](/customization/overview#storage-locations) for more guidance.
|
||||
|
||||
## What Workflows Can Use
|
||||
|
||||
Workflows can combine natural language instructions with specific tool calls. This flexibility lets you write workflows that are as simple or as precise as your task requires.
|
||||
|
||||
### Natural Language
|
||||
|
||||
Write steps as plain instructions. Cline interprets them and figures out which tools to use:
|
||||
|
||||
```markdown
|
||||
## Step 1: Check for uncommitted changes
|
||||
Look at the git status. If there are uncommitted changes, ask whether to continue or abort.
|
||||
|
||||
## Step 2: Run the test suite
|
||||
Execute all tests. If any fail, show the failures and stop.
|
||||
```
|
||||
|
||||
This approach works well when you want Cline to adapt to the situation rather than follow rigid steps.
|
||||
|
||||
### Cline Tools
|
||||
|
||||
For precise control, use Cline's built-in tools with XML syntax. This guarantees specific actions:
|
||||
|
||||
```xml
|
||||
<execute_command>
|
||||
<command>npm run test</command>
|
||||
<requires_approval>false</requires_approval>
|
||||
</execute_command>
|
||||
```
|
||||
|
||||
```xml
|
||||
<read_file>
|
||||
<path>src/config.json</path>
|
||||
</read_file>
|
||||
```
|
||||
|
||||
```xml
|
||||
<ask_followup_question>
|
||||
<question>Deploy to production or staging?</question>
|
||||
<options>["Production", "Staging", "Cancel"]</options>
|
||||
</ask_followup_question>
|
||||
```
|
||||
|
||||
See the full list in the [Cline Tools Reference](/tools-reference/all-cline-tools).
|
||||
|
||||
### CLI Tools
|
||||
|
||||
Reference any command-line tool installed on your machine. Git, npm, docker, gh, make, curl: whatever you have available.
|
||||
|
||||
```bash
|
||||
git log --author="$(git config user.name)" --since="yesterday" --oneline
|
||||
```
|
||||
|
||||
### MCP Tools
|
||||
|
||||
If you have [MCP servers](/mcp/mcp-overview) connected, use them in your workflows with the `use_mcp_tool` syntax. This lets you integrate with external services like GitHub, Slack, databases, or custom internal tools.
|
||||
|
||||
```xml
|
||||
<use_mcp_tool>
|
||||
<server_name>github-server</server_name>
|
||||
<tool_name>create_release</tool_name>
|
||||
<arguments>{"tag": "v1.2.0", "name": "Release v1.2.0", "body": "Changelog content here"}</arguments>
|
||||
</use_mcp_tool>
|
||||
```
|
||||
|
||||
Or describe the intent in natural language and let Cline figure out the tool call:
|
||||
|
||||
```markdown
|
||||
## Step 3: Create GitHub release
|
||||
Use the GitHub MCP server to create a release tagged with the version from package.json.
|
||||
Include the changelog as the release body.
|
||||
```
|
||||
|
||||
## Writing Effective Workflows
|
||||
|
||||
**Start simple.** Write natural language steps first. Only add XML tool calls when you need guaranteed behavior.
|
||||
|
||||
**Be specific about decisions.** If a step requires user input, make that explicit: "Ask whether to deploy to production or staging."
|
||||
|
||||
**Include failure handling.** Tell Cline what to do when something goes wrong: "If tests fail, show the failures and stop the workflow."
|
||||
|
||||
**Keep workflows focused.** A `deploy.md` should deploy. A `setup-db.md` should set up the database. Split complex processes into multiple workflows that can be run independently.
|
||||
|
||||
**Version control your workflows.** Store workflows in `.clinerules/workflows/` and commit them. Your team can share, review, and improve them together.
|
||||
|
||||
<Warning>
|
||||
Workflows execute with your permissions. Review workflows before running them, especially those from external sources.
|
||||
</Warning>
|
||||
|
||||
## Example: Release Preparation
|
||||
|
||||
This workflow automates the tedious pre-release checklist. It verifies your working directory is clean, runs tests and builds, prompts you for the version bump, and generates a changelog from recent commits.
|
||||
|
||||
The workflow demonstrates both approaches: XML tool syntax (`<execute_command>`, `<ask_followup_question>`) for steps that need precise control, and natural language for steps where Cline should adapt to the situation.
|
||||
|
||||
````markdown title="release-prep.md"
|
||||
# Release Preparation
|
||||
|
||||
Prepare a new release by running tests, building, and updating version info.
|
||||
|
||||
## Step 1: Check for clean working directory
|
||||
<execute_command>
|
||||
<command>git status --porcelain</command>
|
||||
</execute_command>
|
||||
|
||||
If there are uncommitted changes, ask whether to continue or stash them first.
|
||||
|
||||
## Step 2: Run the test suite
|
||||
<execute_command>
|
||||
<command>npm run test</command>
|
||||
</execute_command>
|
||||
|
||||
If any tests fail, stop the workflow and report the failures.
|
||||
|
||||
## Step 3: Build the project
|
||||
<execute_command>
|
||||
<command>npm run build</command>
|
||||
</execute_command>
|
||||
|
||||
Verify the build completes without errors.
|
||||
|
||||
## Step 4: Ask for new version
|
||||
<ask_followup_question>
|
||||
<question>What should the new version be?</question>
|
||||
<options>["Patch (x.x.X)", "Minor (x.X.0)", "Major (X.0.0)", "Custom"]</options>
|
||||
</ask_followup_question>
|
||||
|
||||
## Step 5: Update version
|
||||
Update the version in `package.json` to the new version specified by the user.
|
||||
|
||||
## Step 6: Generate changelog entry
|
||||
<execute_command>
|
||||
<command>git log --oneline $(git describe --tags --abbrev=0)..HEAD</command>
|
||||
</execute_command>
|
||||
|
||||
Use these commits to write a changelog entry for the new version.
|
||||
````
|
||||
|
||||
Invoke it with `/release-prep.md` and Cline walks through each step.
|
||||
+502
-200
@@ -56,192 +56,182 @@
|
||||
"navigation": {
|
||||
"tabs": [
|
||||
{
|
||||
"tab": "Docs",
|
||||
"icon": "square-terminal",
|
||||
"tab": "Cline",
|
||||
"icon": "robot",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Home",
|
||||
"pages": [
|
||||
"home",
|
||||
"getting-started/quick-start"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Getting Started",
|
||||
"pages": [
|
||||
"getting-started/what-is-cline",
|
||||
"cline-overview",
|
||||
"getting-started/installing-cline",
|
||||
"getting-started/authorizing-with-cline",
|
||||
"getting-started/your-first-project"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Core Workflows",
|
||||
"pages": [
|
||||
"core-workflows/task-management",
|
||||
"core-workflows/plan-and-act",
|
||||
"core-workflows/working-with-files",
|
||||
"core-workflows/using-commands",
|
||||
"core-workflows/checkpoints"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Customization",
|
||||
"pages": [
|
||||
"customization/overview",
|
||||
"customization/cline-rules",
|
||||
"customization/skills",
|
||||
"customization/workflows",
|
||||
"customization/hooks",
|
||||
"customization/clineignore"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Cline CLI",
|
||||
"pages": [
|
||||
"cline-cli/overview",
|
||||
"cline-cli/installation",
|
||||
"cline-cli/interactive-mode",
|
||||
{
|
||||
"group": "Headless Mode",
|
||||
"pages": [
|
||||
"cline-cli/three-core-flows",
|
||||
"cline-cli/samples/overview",
|
||||
"cline-cli/samples/github-issue-rca",
|
||||
"cline-cli/samples/github-integration",
|
||||
"cline-cli/samples/github-pr-review",
|
||||
"cline-cli/samples/model-orchestration",
|
||||
"cline-cli/samples/worktree-workflows"
|
||||
]
|
||||
},
|
||||
"cline-cli/configuration",
|
||||
"cline-cli/acp-editor-integrations",
|
||||
"cline-sdk/overview",
|
||||
"cline-cli/cli-reference"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"features/memory-bank",
|
||||
"features/focus-chain",
|
||||
"features/auto-approve",
|
||||
"features/auto-compact",
|
||||
"features/multiroot-workspace",
|
||||
"features/subagents",
|
||||
"features/background-edit",
|
||||
"features/jupyter-notebooks",
|
||||
"features/deep-planning",
|
||||
"features/web-tools",
|
||||
"features/worktrees"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Models & Providers",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Choosing & Configuring Models",
|
||||
"pages": [
|
||||
"core-features/model-selection-guide",
|
||||
"model-config/context-windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Running Models Locally",
|
||||
"group": "Models & Providers",
|
||||
"pages": [
|
||||
"getting-started/authorizing-with-cline",
|
||||
"getting-started/cline-provider",
|
||||
"running-models-locally/overview",
|
||||
"running-models-locally/ollama",
|
||||
"running-models-locally/lm-studio"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Cloud Providers",
|
||||
"pages": [
|
||||
"provider-config/qwen",
|
||||
"provider-config/anthropic",
|
||||
"provider-config/asksage",
|
||||
"provider-config/baseten",
|
||||
"provider-config/cerebras",
|
||||
"provider-config/claude-code",
|
||||
"provider-config/deepseek",
|
||||
"provider-config/doubao",
|
||||
"provider-config/fireworks",
|
||||
"provider-config/gcp-vertex-ai",
|
||||
"provider-config/google-gemini",
|
||||
"provider-config/groq",
|
||||
"provider-config/huawei-cloud-maas",
|
||||
"provider-config/huggingface",
|
||||
"provider-config/minimax",
|
||||
"provider-config/mistral-ai",
|
||||
"provider-config/moonshot",
|
||||
"provider-config/nebius",
|
||||
"provider-config/nousresearch",
|
||||
"provider-config/openai",
|
||||
"provider-config/openai-codex",
|
||||
"provider-config/openrouter",
|
||||
"provider-config/oracle-code-assist",
|
||||
"provider-config/qwen-code",
|
||||
"provider-config/sambanova",
|
||||
"provider-config/together",
|
||||
"provider-config/xai-grok",
|
||||
"provider-config/zai",
|
||||
{
|
||||
"group": "AWS Bedrock",
|
||||
"group": "Cloud Providers",
|
||||
"pages": [
|
||||
"provider-config/aws-bedrock/api-key",
|
||||
"provider-config/aws-bedrock/iam-credentials",
|
||||
"provider-config/aws-bedrock/cli-profile"
|
||||
"provider-config/qwen",
|
||||
"provider-config/anthropic",
|
||||
{
|
||||
"group": "AWS Bedrock",
|
||||
"pages": [
|
||||
"provider-config/aws-bedrock/api-key",
|
||||
"provider-config/aws-bedrock/iam-credentials",
|
||||
"provider-config/aws-bedrock/cli-profile"
|
||||
]
|
||||
},
|
||||
"provider-config/deepseek",
|
||||
"provider-config/google-gemini",
|
||||
"provider-config/minimax",
|
||||
"provider-config/openai",
|
||||
"provider-config/openai-compatible",
|
||||
"provider-config/openrouter",
|
||||
"provider-config/zai",
|
||||
"provider-config/other-30-plus-providers"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"getting-started/config"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Usage",
|
||||
"pages": [
|
||||
"usage/ide",
|
||||
"usage/tui",
|
||||
{
|
||||
"group": "Advanced Configuration",
|
||||
"group": "CLI",
|
||||
"pages": [
|
||||
"provider-config/aihubmix",
|
||||
"provider-config/dify",
|
||||
"provider-config/hicap",
|
||||
"provider-config/litellm-and-cline-using-codestral",
|
||||
"provider-config/openai-compatible",
|
||||
"provider-config/requesty",
|
||||
"provider-config/sap-aicore",
|
||||
"provider-config/vercel-ai-gateway",
|
||||
"provider-config/vscode-language-model-api"
|
||||
"usage/cli-overview",
|
||||
"cli/cli-reference",
|
||||
{
|
||||
"group": "Examples",
|
||||
"pages": [
|
||||
"cli/samples/github-issue-rca",
|
||||
"cli/samples/github-integration",
|
||||
"cli/samples/github-pr-review",
|
||||
"cli/samples/model-orchestration"
|
||||
]
|
||||
},
|
||||
"cli/acp-editor-integrations"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Kanban",
|
||||
"pages": [
|
||||
"usage/kanban",
|
||||
"kanban/core-workflow",
|
||||
"kanban/remote-access"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "MCP (Extending Cline)",
|
||||
"group": "Configurations",
|
||||
"pages": [
|
||||
"tools-reference/all-cline-tools",
|
||||
"customization/cline-rules",
|
||||
"customization/skills",
|
||||
"customization/plugins",
|
||||
"mcp/mcp-overview",
|
||||
"mcp/mcp-marketplace",
|
||||
"mcp/adding-and-configuring-servers",
|
||||
"mcp/mcp-server-development-protocol",
|
||||
"mcp/connecting-to-a-remote-server",
|
||||
"mcp/mcp-transport-mechanisms"
|
||||
"customization/hooks",
|
||||
"cli/scheduling",
|
||||
"cli/connectors",
|
||||
"customization/clineignore"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Tools Reference",
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"tools-reference/all-cline-tools",
|
||||
"tools-reference/browser-automation"
|
||||
"core-workflows/plan-and-act",
|
||||
"core-workflows/working-with-files",
|
||||
"core-workflows/using-commands",
|
||||
"core-workflows/checkpoints",
|
||||
"cli/agent-teams",
|
||||
"features/subagents"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "IDE Specific Features",
|
||||
"pages": [
|
||||
"features/auto-approve",
|
||||
"features/jupyter-notebooks",
|
||||
"features/multiroot-workspace"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Troubleshooting",
|
||||
"pages": [
|
||||
"troubleshooting/terminal-quick-fixes",
|
||||
"troubleshooting/networking-and-proxies",
|
||||
"troubleshooting/task-history-recovery"
|
||||
"troubleshooting/networking-and-proxies"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "SDK",
|
||||
"icon": "cube",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Start",
|
||||
"pages": [
|
||||
"sdk/overview",
|
||||
"sdk/examples"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Contributing",
|
||||
"group": "Concepts",
|
||||
"pages": [
|
||||
"contributing/documentation-guide",
|
||||
"contributing/doc-templates"
|
||||
"sdk/runtime",
|
||||
"sdk/model-providers",
|
||||
{
|
||||
"group": "Tools",
|
||||
"pages": [
|
||||
"sdk/tools",
|
||||
"sdk/guides/creating-custom-tools"
|
||||
]
|
||||
},
|
||||
"sdk/events",
|
||||
{
|
||||
"group": "Plugins",
|
||||
"pages": [
|
||||
"sdk/plugins",
|
||||
"sdk/plugin-install",
|
||||
"sdk/guides/writing-plugins",
|
||||
"sdk/plugin-examples"
|
||||
]
|
||||
},
|
||||
"sdk/guides/scheduled-agents"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Architecture",
|
||||
"pages": [
|
||||
"sdk/architecture/overview",
|
||||
"sdk/architecture/hub-spoke"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Guides",
|
||||
"pages": [
|
||||
"sdk/guides/building-an-agent",
|
||||
"sdk/guides/permission-handling",
|
||||
"sdk/guides/multi-agent-teams",
|
||||
"sdk/guides/going-to-production"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "API Reference",
|
||||
"pages": [
|
||||
"sdk/reference/cline-core",
|
||||
"sdk/reference/agent",
|
||||
"sdk/reference/gateway",
|
||||
"sdk/reference/tools-api",
|
||||
"sdk/reference/events",
|
||||
"sdk/reference/types"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -258,7 +248,7 @@
|
||||
"enterprise-solutions/sso-setup",
|
||||
"enterprise-solutions/team-management/managing-members",
|
||||
{
|
||||
"group": "SaaS Provider Configuration",
|
||||
"group": "Remote Provider Configuration",
|
||||
"pages": [
|
||||
"enterprise-solutions/configuration/remote-configuration/overview",
|
||||
{
|
||||
@@ -268,19 +258,33 @@
|
||||
"enterprise-solutions/configuration/remote-configuration/aws-bedrock/member-configuration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "LiteLLM",
|
||||
"pages": [
|
||||
"enterprise-solutions/configuration/remote-configuration/litellm/admin-configuration",
|
||||
"enterprise-solutions/configuration/remote-configuration/litellm/member-configuration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Google Vertex AI",
|
||||
"pages": [
|
||||
"enterprise-solutions/configuration/remote-configuration/google-vertex/admin-configuration",
|
||||
"enterprise-solutions/configuration/remote-configuration/google-vertex/member-configuration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "OpenAI Compatible",
|
||||
"pages": [
|
||||
"enterprise-solutions/configuration/remote-configuration/openai-compatible/admin-configuration",
|
||||
"enterprise-solutions/configuration/remote-configuration/openai-compatible/member-configuration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Anthropic",
|
||||
"pages": [
|
||||
"enterprise-solutions/configuration/remote-configuration/anthropic/admin-configuration",
|
||||
"enterprise-solutions/configuration/remote-configuration/anthropic/member-configuration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "LiteLLM",
|
||||
"pages": [
|
||||
"enterprise-solutions/configuration/remote-configuration/litellm/admin-configuration",
|
||||
"enterprise-solutions/configuration/remote-configuration/litellm/member-configuration"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -296,7 +300,10 @@
|
||||
"pages": [
|
||||
"enterprise-solutions/monitoring/overview",
|
||||
"enterprise-solutions/monitoring/telemetry",
|
||||
"enterprise-solutions/monitoring/opentelemetry"
|
||||
"enterprise-solutions/monitoring/prompt-storage",
|
||||
"enterprise-solutions/monitoring/opentelemetry",
|
||||
"enterprise-solutions/monitoring/opentelemetry-events",
|
||||
"enterprise-solutions/monitoring/opentelemetry_override"
|
||||
]
|
||||
},
|
||||
"enterprise-solutions/api-reference"
|
||||
@@ -331,11 +338,6 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "Learn",
|
||||
"icon": "graduation-cap",
|
||||
"href": "https://cline.bot/learn"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -350,53 +352,77 @@
|
||||
{
|
||||
"name": "Overview",
|
||||
"icon": "house",
|
||||
"url": "getting-started/what-is-cline"
|
||||
"url": "cline-overview"
|
||||
}
|
||||
],
|
||||
"redirects": [
|
||||
{
|
||||
"source": "/usage/cli",
|
||||
"destination": "/usage/cli-overview"
|
||||
},
|
||||
{
|
||||
"source": "/getting-started/installing-cline-jetbrains",
|
||||
"destination": "/getting-started/installing-cline"
|
||||
},
|
||||
{
|
||||
"source": "/getting-started/overview",
|
||||
"destination": "/getting-started/what-is-cline"
|
||||
"destination": "/cline-overview"
|
||||
},
|
||||
{
|
||||
"source": "/getting-started/your-first-project",
|
||||
"destination": "/usage/ide"
|
||||
},
|
||||
{
|
||||
"source": "/introduction",
|
||||
"destination": "/getting-started/what-is-cline"
|
||||
"destination": "/cline-overview"
|
||||
},
|
||||
{
|
||||
"source": "/introduction/welcome",
|
||||
"destination": "/getting-started/what-is-cline"
|
||||
"destination": "/cline-overview"
|
||||
},
|
||||
{
|
||||
"source": "/introduction/overview",
|
||||
"destination": "/getting-started/what-is-cline"
|
||||
"destination": "/cline-overview"
|
||||
},
|
||||
{
|
||||
"source": "/getting-started/model-selection-guide",
|
||||
"destination": "/core-features/model-selection-guide"
|
||||
"destination": "/getting-started/cline-provider"
|
||||
},
|
||||
{
|
||||
"source": "/provider-config/ollama",
|
||||
"destination": "/running-models-locally/ollama"
|
||||
"destination": "/running-models-locally/overview#runtime-options"
|
||||
},
|
||||
{
|
||||
"source": "/running-models-locally/read-me-first",
|
||||
"destination": "/running-models-locally/overview"
|
||||
},
|
||||
{
|
||||
"source": "/running-models-locally/ollama",
|
||||
"destination": "/running-models-locally/overview#runtime-options"
|
||||
},
|
||||
{
|
||||
"source": "/running-models-locally/lm-studio",
|
||||
"destination": "/running-models-locally/overview#runtime-options"
|
||||
},
|
||||
{
|
||||
"source": "/getting-started/understanding-context-management",
|
||||
"destination": "/model-config/context-windows"
|
||||
"destination": "/getting-started/cline-provider"
|
||||
},
|
||||
{
|
||||
"source": "/best-practices/understanding-context-management",
|
||||
"destination": "/model-config/context-windows"
|
||||
"destination": "/getting-started/cline-provider"
|
||||
},
|
||||
{
|
||||
"source": "/prompting/understanding-context-management",
|
||||
"destination": "/model-config/context-windows"
|
||||
"destination": "/getting-started/cline-provider"
|
||||
},
|
||||
{
|
||||
"source": "/model-config/context-windows",
|
||||
"destination": "/getting-started/cline-provider"
|
||||
},
|
||||
{
|
||||
"source": "/core-features/model-selection-guide",
|
||||
"destination": "/getting-started/cline-provider"
|
||||
},
|
||||
{
|
||||
"source": "/prompting/prompt-engineering-guide",
|
||||
@@ -404,15 +430,23 @@
|
||||
},
|
||||
{
|
||||
"source": "/prompting/cline-memory-bank",
|
||||
"destination": "/features/memory-bank"
|
||||
"destination": "/core-workflows/task-management"
|
||||
},
|
||||
{
|
||||
"source": "/customization/memory-bank",
|
||||
"destination": "/features/memory-bank"
|
||||
"destination": "/core-workflows/task-management"
|
||||
},
|
||||
{
|
||||
"source": "/customization/overview",
|
||||
"destination": "/getting-started/config"
|
||||
},
|
||||
{
|
||||
"source": "/customization/focus-chain",
|
||||
"destination": "/features/focus-chain"
|
||||
"destination": "/core-workflows/using-commands#deep-planning"
|
||||
},
|
||||
{
|
||||
"source": "/features/deep-planning",
|
||||
"destination": "/core-workflows/using-commands#deep-planning"
|
||||
},
|
||||
{
|
||||
"source": "/customization/auto-approve",
|
||||
@@ -426,14 +460,6 @@
|
||||
"source": "/getting-started/your-first-task",
|
||||
"destination": "/getting-started/your-first-project"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/samples",
|
||||
"destination": "/cline-cli/samples/overview"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/overview",
|
||||
"destination": "/cline-cli/getting-started"
|
||||
},
|
||||
{
|
||||
"source": "/features/hooks/real-world-examples",
|
||||
"destination": "/customization/hooks"
|
||||
@@ -538,18 +564,6 @@
|
||||
"source": "/features/slash-commands/new-task",
|
||||
"destination": "/core-workflows/using-commands"
|
||||
},
|
||||
{
|
||||
"source": "/features/slash-commands/workflows/index",
|
||||
"destination": "/customization/workflows"
|
||||
},
|
||||
{
|
||||
"source": "/features/slash-commands/workflows/quickstart",
|
||||
"destination": "/customization/workflows"
|
||||
},
|
||||
{
|
||||
"source": "/features/slash-commands/workflows/best-practices",
|
||||
"destination": "/customization/workflows"
|
||||
},
|
||||
{
|
||||
"source": "/exploring-clines-tools/cline-tools-guide",
|
||||
"destination": "/tools-reference/all-cline-tools"
|
||||
@@ -560,15 +574,15 @@
|
||||
},
|
||||
{
|
||||
"source": "/exploring-clines-tools/remote-browser-support",
|
||||
"destination": "/tools-reference/browser-automation"
|
||||
"destination": "/tools-reference/all-cline-tools"
|
||||
},
|
||||
{
|
||||
"source": "/mcp/adding-mcp-servers-from-github",
|
||||
"destination": "/mcp/adding-and-configuring-servers"
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/mcp/configuring-mcp-servers",
|
||||
"destination": "/mcp/adding-and-configuring-servers"
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/more-info/telemetry",
|
||||
@@ -634,6 +648,14 @@
|
||||
"source": "/features/slash-commands/new-rule",
|
||||
"destination": "/core-workflows/using-commands#newrule"
|
||||
},
|
||||
{
|
||||
"source": "/features/memory-bank",
|
||||
"destination": "/core-workflows/task-management"
|
||||
},
|
||||
{
|
||||
"source": "/features/focus-chain",
|
||||
"destination": "/features/deep-planning"
|
||||
},
|
||||
{
|
||||
"source": "/features/skills",
|
||||
"destination": "/customization/skills"
|
||||
@@ -641,6 +663,286 @@
|
||||
{
|
||||
"source": "/api/reference",
|
||||
"destination": "/api/overview"
|
||||
},
|
||||
{
|
||||
"source": "/cli/overview",
|
||||
"destination": "/usage/cli-overview"
|
||||
},
|
||||
{
|
||||
"source": "/kanban/overview",
|
||||
"destination": "/usage/kanban"
|
||||
},
|
||||
{
|
||||
"source": "/kanban/getting-started",
|
||||
"destination": "/usage/kanban"
|
||||
},
|
||||
{
|
||||
"source": "/kanban/features",
|
||||
"destination": "/usage/kanban"
|
||||
},
|
||||
{
|
||||
"source": "/features/background-edit",
|
||||
"destination": "/features/auto-approve"
|
||||
},
|
||||
{
|
||||
"source": "/features/worktrees",
|
||||
"destination": "/usage/ide"
|
||||
},
|
||||
{
|
||||
"source": "/cli/getting-started",
|
||||
"destination": "/usage/cli-overview"
|
||||
},
|
||||
{
|
||||
"source": "/cli/installation",
|
||||
"destination": "/getting-started/installing-cline"
|
||||
},
|
||||
{
|
||||
"source": "/cli/three-core-flows",
|
||||
"destination": "/usage/cli-overview#headless-mode"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/getting-started",
|
||||
"destination": "/usage/cli-overview"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/installation",
|
||||
"destination": "/getting-started/installing-cline"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/three-core-flows",
|
||||
"destination": "/usage/cli-overview#headless-mode"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/connectors",
|
||||
"destination": "/cli/connectors"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/scheduling",
|
||||
"destination": "/cli/scheduling"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/mcp-servers",
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/cli/mcp-servers",
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/agent-teams",
|
||||
"destination": "/cli/agent-teams"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/cli-reference",
|
||||
"destination": "/cli/cli-reference"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/configuration",
|
||||
"destination": "/getting-started/config"
|
||||
},
|
||||
{
|
||||
"source": "/provider-config/claude-code",
|
||||
"destination": "/provider-config/anthropic"
|
||||
},
|
||||
{
|
||||
"source": "/provider-config/openai-codex",
|
||||
"destination": "/provider-config/openai"
|
||||
},
|
||||
{
|
||||
"source": "/cli/configuration",
|
||||
"destination": "/getting-started/config"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/acp-editor-integrations",
|
||||
"destination": "/cli/acp-editor-integrations"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/samples/github-issue-rca",
|
||||
"destination": "/cli/samples/github-issue-rca"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/samples/github-integration",
|
||||
"destination": "/cli/samples/github-integration"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/samples/github-pr-review",
|
||||
"destination": "/cli/samples/github-pr-review"
|
||||
},
|
||||
{
|
||||
"source": "/cline-cli/samples/model-orchestration",
|
||||
"destination": "/cli/samples/model-orchestration"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/overview",
|
||||
"destination": "/sdk/overview"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/quickstart",
|
||||
"destination": "/sdk/examples"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/quickstart",
|
||||
"destination": "/sdk/examples"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/examples",
|
||||
"destination": "/sdk/guides/building-an-agent"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/agents",
|
||||
"destination": "/sdk/runtime"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/sessions",
|
||||
"destination": "/sdk/runtime"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/tools",
|
||||
"destination": "/sdk/tools"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/streaming-and-events",
|
||||
"destination": "/sdk/events"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/plugins",
|
||||
"destination": "/sdk/plugins"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/hooks",
|
||||
"destination": "/sdk/plugins"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/model-providers",
|
||||
"destination": "/sdk/model-providers"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/building-an-agent",
|
||||
"destination": "/sdk/guides/building-an-agent"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/creating-custom-tools",
|
||||
"destination": "/sdk/guides/creating-custom-tools"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/writing-plugins",
|
||||
"destination": "/sdk/guides/writing-plugins"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/permission-handling",
|
||||
"destination": "/sdk/guides/permission-handling"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/scheduled-agents",
|
||||
"destination": "/sdk/guides/scheduled-agents"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/multi-agent-teams",
|
||||
"destination": "/sdk/guides/multi-agent-teams"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/connectors",
|
||||
"destination": "/cli/connectors"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/guides/connectors",
|
||||
"destination": "/cli/connectors"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/going-to-production",
|
||||
"destination": "/sdk/guides/going-to-production"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/architecture/overview",
|
||||
"destination": "/sdk/architecture/overview"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/architecture/hub-spoke",
|
||||
"destination": "/sdk/architecture/hub-spoke"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/architecture/packages",
|
||||
"destination": "/sdk/architecture/overview"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/reference/cline-core",
|
||||
"destination": "/sdk/reference/cline-core"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/reference/agent",
|
||||
"destination": "/sdk/reference/agent"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/reference/gateway",
|
||||
"destination": "/sdk/reference/gateway"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/reference/tools-api",
|
||||
"destination": "/sdk/reference/tools-api"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/reference/events",
|
||||
"destination": "/sdk/reference/events"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/reference/types",
|
||||
"destination": "/sdk/reference/types"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/extensions",
|
||||
"destination": "/sdk/plugins"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/guides/writing-extensions",
|
||||
"destination": "/sdk/guides/writing-plugins"
|
||||
},
|
||||
{
|
||||
"source": "/cline-sdk/guides/writing-extensions",
|
||||
"destination": "/sdk/guides/writing-plugins"
|
||||
},
|
||||
{
|
||||
"source": "/mcp/mcp-marketplace",
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/mcp/adding-and-configuring-servers",
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/mcp/mcp-server-development-protocol",
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/mcp/connecting-to-a-remote-server",
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/mcp/mcp-transport-mechanisms",
|
||||
"destination": "/mcp/mcp-overview"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/agents",
|
||||
"destination": "/sdk/runtime"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/sessions",
|
||||
"destination": "/sdk/runtime"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/streaming-and-events",
|
||||
"destination": "/sdk/events"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/hooks",
|
||||
"destination": "/sdk/plugins"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/extensions",
|
||||
"destination": "/sdk/plugins"
|
||||
},
|
||||
{
|
||||
"source": "/sdk/examples",
|
||||
"destination": "/sdk/guides/building-an-agent"
|
||||
}
|
||||
],
|
||||
"search": {
|
||||
|
||||
@@ -4,7 +4,7 @@ sidebarTitle: "API Reference"
|
||||
description: "REST API endpoints for managing users, organizations, billing, plans, and API keys."
|
||||
---
|
||||
|
||||
The Enterprise API provides REST endpoints for account management, organization administration, billing, and API key management. These are separate from the [Chat Completions API](/api/reference), which handles model inference.
|
||||
The Enterprise API provides REST endpoints for account management, organization administration, billing, and API key management. These are separate from the [Chat Completions API](/api/overview), which handles model inference.
|
||||
|
||||
## Base URL
|
||||
|
||||
@@ -20,7 +20,7 @@ All endpoints require a Bearer token in the `Authorization` header:
|
||||
Authorization: Bearer YOUR_AUTH_TOKEN
|
||||
```
|
||||
|
||||
Use the same API key or account auth token described in the [public API reference](/api/reference#authentication).
|
||||
Use the same API key or account auth token described in the [public API reference](/api/overview#authentication).
|
||||
|
||||
## Quick Example
|
||||
|
||||
@@ -180,7 +180,7 @@ Track token consumption and costs across your organization.
|
||||
|
||||
## API Keys
|
||||
|
||||
Create and manage API keys for programmatic access. Keys created here work with both the [Chat Completions API](/api/reference) and the endpoints on this page.
|
||||
Create and manage API keys for programmatic access. Keys created here work with both the [Chat Completions API](/api/overview) and the endpoints on this page.
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
@@ -193,7 +193,7 @@ Create and manage API keys for programmatic access. Keys created here work with
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Chat Completions API" icon="code" href="/api/reference">
|
||||
<Card title="Chat Completions API" icon="code" href="/api/overview">
|
||||
The public inference API for sending prompts and receiving completions.
|
||||
</Card>
|
||||
<Card title="SSO Setup" icon="key" href="/enterprise-solutions/sso-setup">
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "Configure Anthropic Provider (Admin)"
|
||||
sidebarTitle: "Configure Anthropic (Admin)"
|
||||
description: "This guide explains how administrators configure Anthropic as the organization-wide LLM provider for Cline."
|
||||
---
|
||||
|
||||
|
||||
As an administrator, you can add Anthropic as the organization-wide LLM provider for all Cline users through the hosted admin console. This centralized approach provides direct access to Anthropic's Claude models, with an optional custom base URL for organizations that route traffic through a proxy.
|
||||
|
||||
## Before You Begin
|
||||
|
||||
To get started with setting up Anthropic as your organization's LLM provider, you'll need a few items in place.
|
||||
|
||||
**Administrator access to the Cline Admin console**
|
||||
You need admin privileges to enforce provider settings across your organization. If you can navigate to **Settings → Cline Settings** in the admin console at [app.cline.bot](https://app.cline.bot), you have the right access level.
|
||||
|
||||
**Anthropic API access**
|
||||
Your organization needs an Anthropic account with API access to Claude models. Members will need individual API keys to authenticate.
|
||||
|
||||
<Note>
|
||||
If your organization requires routing API traffic through a proxy or custom endpoint, have the proxy URL ready before configuring.
|
||||
</Note>
|
||||
|
||||
## Configuration Steps
|
||||
|
||||
<Steps>
|
||||
<Step title="Access Cline Settings">
|
||||
Navigate to [app.cline.bot](https://app.cline.bot) and sign in with your administrator account. Go to **Settings → Cline Settings**.
|
||||
|
||||
<Info>
|
||||
You should see the provider configuration options if you have the correct admin access level.
|
||||
</Info>
|
||||
</Step>
|
||||
|
||||
<Step title="Enable Remote Provider Configuration">
|
||||
Toggle on **Enable settings** to reveal the remote provider configuration options. This allows you to enforce provider settings across your organization.
|
||||
</Step>
|
||||
|
||||
<Step title="Select Anthropic as the API Provider">
|
||||
Open the **API Provider** dropdown menu and select **Anthropic**. This will open the Anthropic configuration panel where you'll configure all your organization-wide settings.
|
||||
</Step>
|
||||
|
||||
<Step title="Configure Anthropic Settings">
|
||||
The configuration panel includes settings that control how Anthropic works for your organization:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Base URL (optional)">
|
||||
By default, Cline connects directly to the Anthropic API (`https://api.anthropic.com`). If your organization routes API traffic through a proxy or custom endpoint, enter the base URL here.
|
||||
|
||||
Use cases for a custom base URL:
|
||||
- Corporate proxy that logs or filters API traffic
|
||||
- Self-hosted API gateway for rate limiting or access control
|
||||
- Regional routing requirements
|
||||
|
||||
Leave this empty to use the default Anthropic API endpoint.
|
||||
|
||||
<Tip>
|
||||
If using a proxy, ensure it correctly forwards requests to the Anthropic API and preserves all required headers.
|
||||
</Tip>
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Save Configuration">
|
||||
After configuring your settings, close the provider configuration panel and click **Save** on the settings page to persist your changes.
|
||||
|
||||
Once saved, all organization members signed into the Cline extension will automatically use Anthropic with your configured settings. They won't be able to select other providers or switch to their personal Cline accounts.
|
||||
|
||||
<Warning>
|
||||
Members can't switch to personal Cline accounts or join other organizations once remote configuration is enabled. This ensures consistent provider usage across your team.
|
||||
</Warning>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Verification
|
||||
|
||||
To verify the configuration:
|
||||
|
||||
1. Check that the provider shows as "Anthropic" in the Enabled provider field
|
||||
2. Confirm the settings persist after refreshing the page
|
||||
3. Test with a member account to ensure they see only Anthropic as a provider
|
||||
4. Verify that Claude models are available in the model dropdown
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Members don't see the configured provider**
|
||||
Ensure you clicked Save after closing the configuration panel. Verify the member account belongs to the correct organization.
|
||||
|
||||
**Connection errors when using a custom base URL**
|
||||
Verify the proxy URL is correct and accessible from your team's development environments. Ensure the proxy correctly forwards requests to the Anthropic API.
|
||||
|
||||
**Configuration changes don't persist**
|
||||
Make sure to click the Save button on the main settings page, not just close the configuration panel.
|
||||
|
||||
**Need to change settings later**
|
||||
You can update the base URL or other settings at any time. Changes take effect immediately for all organization members.
|
||||
|
||||
For further details, consult the [Anthropic API documentation](https://docs.anthropic.com/) and coordinate with your infrastructure team.
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
---
|
||||
title: "Configure Anthropic in VS Code (Members)"
|
||||
sidebarTitle: "Configure Anthropic (Member)"
|
||||
description: "Guide for engineers connecting to their organization's Anthropic provider through VS Code after admin setup"
|
||||
---
|
||||
|
||||
As a team member, you can connect your local development environment to your organization's Anthropic provider setup. This guide walks you through configuring your API key in VS Code so you can start using Claude models through your organization's configuration. Your administrator has already configured the provider settings — you just need to add your API key to get started.
|
||||
|
||||
## Before You Begin
|
||||
|
||||
To successfully connect to your organization's Anthropic provider, you'll need a few things ready.
|
||||
|
||||
**Cline extension installed and configured**
|
||||
The Cline extension must be installed in VS Code and you need to be signed into your organization account. If you haven't installed Cline yet, follow our [installation guide](/getting-started/installing-cline).
|
||||
|
||||
<Info>
|
||||
**Quick Check**: Open the Cline panel in VS Code. If you see your organization name in the bottom left, you're signed in correctly.
|
||||
</Info>
|
||||
|
||||
**Anthropic API key**
|
||||
You need an API key from Anthropic to authenticate requests. Your organization may provide keys centrally or require you to create one through the [Anthropic Console](https://console.anthropic.com/).
|
||||
|
||||
<Note>
|
||||
If you're unsure how to obtain an API key, check with your administrator about your organization's key provisioning process.
|
||||
</Note>
|
||||
|
||||
## Configuration Steps
|
||||
|
||||
<Steps>
|
||||
<Step title="Open Cline Settings">
|
||||
Open VS Code and access the Cline settings panel using either of these methods:
|
||||
|
||||
- Click the settings icon (⚙️) in the Cline panel
|
||||
- Click on the API Provider dropdown located directly below the chat area
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Enter Your API Key">
|
||||
|
||||
1. Select or confirm the **Anthropic** provider is selected
|
||||
2. Enter your Anthropic API key in the **API Key** field
|
||||
3. If your administrator configured a custom base URL, it will already be set and locked
|
||||
4. Click **Save** to store your credentials
|
||||
|
||||
<Tip>
|
||||
API keys are stored locally and are only used by the Cline extension.
|
||||
</Tip>
|
||||
|
||||
<Note>
|
||||
The base URL setting is controlled by your administrator. If a custom proxy URL is configured, your API requests will be routed through it automatically.
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Verify Configuration">
|
||||
After entering your API key, administrator-controlled settings (such as base URL) will be locked (shown with a lock icon 🔒) as they're managed by your organization.
|
||||
</Step>
|
||||
|
||||
<Step title="Test the Connection">
|
||||
Send a test message in Cline to verify your API key works correctly with the configured Anthropic endpoint.
|
||||
|
||||
<Tip>
|
||||
**Testing Recommendation**
|
||||
|
||||
Try a simple test like "Hello" first to verify basic connectivity before starting development tasks.
|
||||
</Tip>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Anthropic not available as provider option**
|
||||
Confirm you're signed into the correct Cline organization. Verify your administrator has saved the Anthropic configuration and that you have the latest version of the Cline extension.
|
||||
|
||||
**Authentication errors ("Invalid API Key" or "Unauthorized")**
|
||||
Verify your API key is correct and active. Check the [Anthropic Console](https://console.anthropic.com/) to confirm your key status and that it has sufficient permissions.
|
||||
|
||||
**Connection errors or timeouts**
|
||||
If your administrator configured a custom base URL (proxy), check with your IT team about network requirements. If using the default Anthropic endpoint, ensure you have internet access to `api.anthropic.com`.
|
||||
|
||||
**Models not available**
|
||||
The available models depend on your Anthropic API plan and your organization's configuration. Contact your administrator if expected models are not available.
|
||||
|
||||
**Rate limit errors**
|
||||
Your API key may have rate limits configured by Anthropic. If you encounter rate limit errors during normal use, contact your administrator about adjusting limits or managing key usage across the team.
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
When working with your Anthropic API key:
|
||||
|
||||
- Keep your API key secure and do not share it
|
||||
- Never store your API key in code or version control
|
||||
- Report any suspected key compromise to your administrator immediately
|
||||
- Regularly check the [Anthropic Console](https://console.anthropic.com/) for unusual usage patterns
|
||||
|
||||
For further details, consult the [Anthropic API documentation](https://docs.anthropic.com/) and coordinate with your organization's administrator.
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
---
|
||||
title: "Configure OpenAI Compatible Provider (Admin)"
|
||||
sidebarTitle: "Configure OpenAI Compatible (Admin)"
|
||||
description: "This guide explains how administrators configure an OpenAI-compatible endpoint as the organization-wide LLM provider for Cline."
|
||||
---
|
||||
|
||||
|
||||
As an administrator, you can add an OpenAI-compatible endpoint as the organization-wide LLM provider for all Cline users through the hosted admin console. This covers any provider that exposes an OpenAI-compatible API, including Azure Foundry (Azure OpenAI), self-hosted inference engines (vLLM, TGI), and other compatible services.
|
||||
|
||||
## Before You Begin
|
||||
|
||||
To get started with setting up an OpenAI-compatible provider for your organization, you'll need a few items in place.
|
||||
|
||||
**Administrator access to the Cline Admin console**
|
||||
You need admin privileges to enforce provider settings across your organization. If you can navigate to **Settings → Cline Settings** in the admin console at [app.cline.bot](https://app.cline.bot), you have the right access level.
|
||||
|
||||
**An OpenAI-compatible API endpoint**
|
||||
You need a running endpoint that implements the OpenAI chat completions API. This could be:
|
||||
- Azure Foundry (Azure OpenAI Service)
|
||||
- A self-hosted inference engine (vLLM, text-generation-inference, etc.)
|
||||
- Any third-party service with an OpenAI-compatible API
|
||||
|
||||
<Note>
|
||||
If you're using Azure Foundry, you'll need your Azure OpenAI endpoint URL and optionally the API version. Work with your Azure administrator to ensure the endpoint is provisioned and accessible.
|
||||
</Note>
|
||||
|
||||
**Endpoint URL and authentication details**
|
||||
You'll need the base URL of your endpoint and any required authentication headers.
|
||||
|
||||
## Configuration Steps
|
||||
|
||||
<Steps>
|
||||
<Step title="Access Cline Settings">
|
||||
Navigate to [app.cline.bot](https://app.cline.bot) and sign in with your administrator account. Go to **Settings → Cline Settings**.
|
||||
|
||||
<Info>
|
||||
You should see the provider configuration options if you have the correct admin access level.
|
||||
</Info>
|
||||
</Step>
|
||||
|
||||
<Step title="Enable Remote Provider Configuration">
|
||||
Toggle on **Enable settings** to reveal the remote provider configuration options. This allows you to enforce provider settings across your organization.
|
||||
</Step>
|
||||
|
||||
<Step title="Select OpenAI Compatible as the API Provider">
|
||||
Open the **API Provider** dropdown menu and select **OpenAI Compatible**. This will open the configuration panel where you'll configure all your organization-wide settings.
|
||||
</Step>
|
||||
|
||||
<Step title="Configure OpenAI Compatible Settings">
|
||||
The configuration panel includes settings that control how the provider works for your organization:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Base URL (required)">
|
||||
Enter the base URL of your OpenAI-compatible endpoint. Examples:
|
||||
|
||||
- **Azure Foundry**: `https://your-resource.openai.azure.com`
|
||||
- **Self-hosted vLLM**: `https://inference.yourcompany.com/v1`
|
||||
- **Other compatible services**: The provider's API base URL
|
||||
|
||||
<Tip>
|
||||
Use HTTPS endpoints in production for security. Ensure the URL is accessible from your team's development environments.
|
||||
</Tip>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Custom Headers (optional)">
|
||||
Add custom HTTP headers that will be included with every API request. This is useful for:
|
||||
|
||||
- Custom authentication schemes beyond API keys
|
||||
- Routing headers for internal load balancers
|
||||
- Organization or tenant identifiers required by your endpoint
|
||||
|
||||
Headers are configured as key-value pairs.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Azure API Version (optional — Azure Foundry only)">
|
||||
If you're using Azure Foundry (Azure OpenAI), specify the API version string. For example: `2024-02-15-preview` or `2024-06-01`.
|
||||
|
||||
This field is only needed for Azure OpenAI deployments. Leave it empty for non-Azure endpoints.
|
||||
|
||||
<Note>
|
||||
Check the [Azure OpenAI API version documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference) for available versions.
|
||||
</Note>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Azure Identity Authentication (optional — Azure Foundry only)">
|
||||
Enable this to use Azure Active Directory (Entra ID) token-based authentication instead of API keys. When enabled, members authenticate using their Azure AD credentials rather than a static API key.
|
||||
|
||||
This field is only relevant for Azure Foundry deployments.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Save Configuration">
|
||||
After configuring your settings, close the provider configuration panel and click **Save** on the settings page to persist your changes.
|
||||
|
||||
Once saved, all organization members signed into the Cline extension will automatically use the OpenAI Compatible provider with your configured settings. They won't be able to select other providers or switch to their personal Cline accounts.
|
||||
|
||||
<Warning>
|
||||
Members can't switch to personal Cline accounts or join other organizations once remote configuration is enabled. This ensures consistent provider usage across your team.
|
||||
</Warning>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Azure Foundry Configuration
|
||||
|
||||
For organizations using Azure Foundry (Azure OpenAI Service), use the following configuration:
|
||||
|
||||
1. **Base URL**: Your Azure OpenAI endpoint (e.g., `https://your-resource.openai.azure.com`)
|
||||
2. **Azure API Version**: The API version to use (e.g., `2024-06-01`)
|
||||
3. **Azure Identity Authentication**: Enable if your organization uses Azure AD for authentication instead of API keys
|
||||
|
||||
## Verification
|
||||
|
||||
To verify the configuration:
|
||||
|
||||
1. Check that the provider shows as "OpenAI Compatible" in the Enabled provider field
|
||||
2. Confirm the settings persist after refreshing the page
|
||||
3. Test with a member account to ensure they see only the OpenAI Compatible provider
|
||||
4. Verify that configured models are available in the model dropdown
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Members don't see the configured provider**
|
||||
Ensure you clicked Save after closing the configuration panel. Verify the member account belongs to the correct organization.
|
||||
|
||||
**Connection errors to the endpoint**
|
||||
Verify the Base URL is correct and accessible from your team's development environments. Check that any firewalls or security groups allow access from developer IP addresses.
|
||||
|
||||
**Azure authentication failures**
|
||||
If using Azure Identity Authentication, verify that members' Azure AD accounts have the appropriate role assignments on the Azure OpenAI resource. If using API keys, verify the key is correctly entered by the member.
|
||||
|
||||
**Configuration changes don't persist**
|
||||
Make sure to click the Save button on the main settings page, not just close the configuration panel.
|
||||
|
||||
**Need to change endpoint or settings later**
|
||||
You can update these settings at any time. Changes take effect immediately for all organization members.
|
||||
|
||||
For Azure Foundry, consult the [Azure OpenAI Service documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/). For other OpenAI-compatible endpoints, refer to your provider's documentation.
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: "Configure OpenAI Compatible in VS Code (Members)"
|
||||
sidebarTitle: "Configure OpenAI Compatible (Member)"
|
||||
description: "Guide for engineers connecting to their organization's OpenAI-compatible endpoint through VS Code after admin setup"
|
||||
---
|
||||
|
||||
As a team member, you can connect your local development environment to your organization's OpenAI-compatible endpoint. This guide walks you through configuring your credentials in VS Code so you can start using models through your organization's configured endpoint. Your administrator has already configured the provider settings — you just need to add your API key to get started.
|
||||
|
||||
## Before You Begin
|
||||
|
||||
To successfully connect to your organization's OpenAI-compatible endpoint, you'll need a few things ready.
|
||||
|
||||
**Cline extension installed and configured**
|
||||
The Cline extension must be installed in VS Code and you need to be signed into your organization account. If you haven't installed Cline yet, follow our [installation guide](/getting-started/installing-cline).
|
||||
|
||||
<Info>
|
||||
**Quick Check**: Open the Cline panel in VS Code. If you see your organization name in the bottom left, you're signed in correctly.
|
||||
</Info>
|
||||
|
||||
**API key or credentials for your endpoint**
|
||||
You need an API key or credentials to authenticate with your organization's configured endpoint. For Azure Foundry deployments using Azure Identity Authentication, your Azure AD credentials may be used instead.
|
||||
|
||||
<Note>
|
||||
If you're unsure what credentials to use, check with your administrator or IT team about how your organization has configured access.
|
||||
</Note>
|
||||
|
||||
## Configuration Steps
|
||||
|
||||
<Steps>
|
||||
<Step title="Open Cline Settings">
|
||||
Open VS Code and access the Cline settings panel using either of these methods:
|
||||
|
||||
- Click the settings icon (⚙️) in the Cline panel
|
||||
- Click on the API Provider dropdown located directly below the chat area
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Configure Your Credentials">
|
||||
The authentication method depends on how your administrator configured the endpoint:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="API Key Authentication">
|
||||
For most OpenAI-compatible endpoints:
|
||||
|
||||
1. Select or confirm the **OpenAI Compatible** provider is selected
|
||||
2. Enter your API key in the **API Key** field
|
||||
3. The base URL, custom headers, and other settings are preconfigured by your administrator
|
||||
4. Click **Save** to store your credentials
|
||||
|
||||
<Tip>
|
||||
API keys are stored locally and are only used by the Cline extension.
|
||||
</Tip>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Azure Identity Authentication (Azure Foundry)">
|
||||
If your organization uses Azure AD authentication:
|
||||
|
||||
1. Select or confirm the **OpenAI Compatible** provider is selected
|
||||
2. Ensure you are signed into Azure in your development environment
|
||||
3. The extension will use your Azure AD credentials automatically
|
||||
4. No API key is needed when Azure Identity Authentication is enabled
|
||||
|
||||
<Note>
|
||||
You may need the Azure Account extension or Azure CLI installed for credential resolution.
|
||||
</Note>
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Note>
|
||||
The Base URL, custom headers, Azure API version, and Azure Identity settings are preconfigured by your administrator and do not need to be set in the extension.
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Verify Configuration">
|
||||
After configuring your credentials, administrator-controlled settings will be locked (shown with a lock icon 🔒) as they're managed by your organization.
|
||||
</Step>
|
||||
|
||||
<Step title="Test the Connection">
|
||||
Send a test message in Cline to verify your credentials work correctly with the configured endpoint.
|
||||
|
||||
<Tip>
|
||||
**Testing Recommendation**
|
||||
|
||||
Try a simple test like "Hello" first to verify basic connectivity before starting development tasks.
|
||||
</Tip>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**OpenAI Compatible not available as provider option**
|
||||
Confirm you're signed into the correct Cline organization. Verify your administrator has saved the configuration and that you have the latest version of the Cline extension.
|
||||
|
||||
**Authentication errors ("Access Denied" or "Invalid API Key")**
|
||||
Verify your API key is correct and active. For Azure Foundry with Azure Identity Authentication, ensure you are signed into Azure in your development environment and that your account has the appropriate role assignments on the Azure OpenAI resource.
|
||||
|
||||
**Connection errors or timeouts**
|
||||
The endpoint URL is configured by your administrator. If you experience connection issues, check with your IT team about network requirements (VPN, firewall rules, etc.).
|
||||
|
||||
**Models not available**
|
||||
The available models depend on your organization's endpoint configuration. Contact your administrator if expected models are not available in the model dropdown.
|
||||
|
||||
**Configuration changes don't persist**
|
||||
Make sure to save your credentials. The base URL and other admin-controlled settings cannot be changed locally.
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
When working with your API credentials:
|
||||
|
||||
- Keep your API key secure and do not share it
|
||||
- Never store credentials in code or version control
|
||||
- Report any suspected key compromise to your administrator immediately
|
||||
- Follow your organization's usage guidelines for the configured endpoint
|
||||
|
||||
Your organization administrator controls which endpoint, models, and settings are available. The extension will automatically apply the configured settings based on your organization's remote configuration.
|
||||
|
||||
For Azure Foundry, refer to the [Azure OpenAI Service documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/). For other endpoints, consult your organization's internal documentation or contact your administrator.
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "SaaS Provider Configuration"
|
||||
title: "Enterprise Provider Configuration"
|
||||
sidebarTitle: "Overview"
|
||||
description: "Configure inference providers through the Cline hosted admin console for centralized organization management"
|
||||
---
|
||||
|
||||
|
||||
SaaS Provider Configuration allows administrators to centrally configure inference providers for their entire organization through the Cline hosted admin console. This approach ensures consistent provider access, security policies, and cost management across all team members without requiring individual developer setup or infrastructure deployment.
|
||||
Remote Provider Configuration allows administrators to centrally configure inference providers for their entire organization through the Cline hosted admin console. This approach ensures consistent provider access, security policies, and cost management across all team members without requiring individual developer setup or infrastructure deployment.
|
||||
|
||||
## How Remote Configuration Works
|
||||
|
||||
@@ -35,11 +35,17 @@ Cline supports remote configuration for the following inference providers:
|
||||
|
||||
| Provider | Use Case | Configuration | Member Setup |
|
||||
|----------|----------|---------------|--------------|
|
||||
| **Cline** | Organizations using Cline's native provider with centralized API key management | API provider selection, model access | No individual API keys needed - fully managed by organization |
|
||||
| **Amazon Bedrock** | Organizations using AWS infrastructure | Region selection, VPC endpoints, cross-region inference, prompt caching | AWS credential configuration in VS Code |
|
||||
| **LiteLLM** | Organizations requiring multi-model access through a unified proxy | Proxy endpoint, authentication, model routing | API key or endpoint configuration in VS Code (or centralized with Master Key) |
|
||||
| **Google Vertex AI** | Organizations using Google Cloud Platform | Project ID, region selection, model access | Service account or credential configuration in VS Code |
|
||||
| **Cline** | Organizations using Cline's native provider with centralized API key management | API provider selection, model access | No individual API keys needed — fully managed by organization |
|
||||
| **Amazon Bedrock** | Organizations using AWS infrastructure | Region selection, VPC endpoints, cross-region inference, global inference, prompt caching | AWS credential configuration (API key, CLI profile, or credential chain) |
|
||||
| **Google Vertex AI** | Organizations using Google Cloud Platform | Project ID, region selection, model access | Google Cloud credential configuration (service account, SDK, or ADC) |
|
||||
| **Azure Foundry** | Organizations using Azure OpenAI or Azure AI services | Base URL, Azure API version, Azure identity authentication, custom headers | API key configuration in the extension |
|
||||
| **Anthropic** | Organizations using the Anthropic API directly | Optional custom base URL for proxy deployments, model access | API key configuration in the extension |
|
||||
| **OpenAI Compatible** | Organizations using any OpenAI-compatible endpoint (self-hosted, vLLM, custom proxies) | Base URL, custom headers, model access | API key configuration in the extension |
|
||||
| **LiteLLM** | Organizations requiring multi-model access through a unified proxy | Proxy endpoint, authentication, model routing | API key or endpoint configuration (or centralized with Master Key) |
|
||||
|
||||
<Note>
|
||||
**Azure Foundry** uses the OpenAI Compatible provider configuration with Azure-specific settings (API version, Azure identity authentication). See the [OpenAI Compatible admin configuration](/enterprise-solutions/configuration/remote-configuration/openai-compatible/admin-configuration) for setup instructions.
|
||||
</Note>
|
||||
|
||||
## Configuration Process
|
||||
|
||||
@@ -55,7 +61,7 @@ Provider configuration is automatically distributed to all organization members
|
||||
</Step>
|
||||
|
||||
<Step title="Member Credential Setup">
|
||||
Team members add their individual credentials (API keys, AWS profiles, etc.) to connect to the configured provider.
|
||||
Team members add their individual credentials (API keys, AWS profiles, etc.) to connect to the configured provider. For some providers like Cline and LiteLLM (with Master Key), no individual credentials are needed.
|
||||
</Step>
|
||||
|
||||
<Step title="Immediate Access">
|
||||
@@ -92,11 +98,19 @@ Select your provider below to begin the configuration process:
|
||||
AWS-based AI models with enterprise security and compliance features.
|
||||
</Card>
|
||||
|
||||
<Card title="Google Vertex AI" icon="google" href="/enterprise-solutions/configuration/remote-configuration/google-vertex/admin-configuration">
|
||||
Google Cloud's AI platform with Gemini models and regional control.
|
||||
</Card>
|
||||
|
||||
<Card title="OpenAI Compatible" icon="plug" href="/enterprise-solutions/configuration/remote-configuration/openai-compatible/admin-configuration">
|
||||
Any OpenAI-compatible endpoint, including Azure Foundry.
|
||||
</Card>
|
||||
|
||||
<Card title="Anthropic" icon="robot" href="/enterprise-solutions/configuration/remote-configuration/anthropic/admin-configuration">
|
||||
Direct Anthropic API access with optional custom base URL configuration.
|
||||
</Card>
|
||||
|
||||
<Card title="LiteLLM" icon="layer-group" href="/enterprise-solutions/configuration/remote-configuration/litellm/admin-configuration">
|
||||
Unified proxy for accessing 100+ AI models through a single interface.
|
||||
</Card>
|
||||
|
||||
<Card title="Google Vertex AI" icon="google" href="/enterprise-solutions/configuration/remote-configuration/google-vertex/admin-configuration">
|
||||
Google Cloud's AI platform with advanced ML capabilities and global infrastructure.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -0,0 +1,630 @@
|
||||
---
|
||||
title: "OpenTelemetry Events Reference"
|
||||
sidebarTitle: "OTel Events"
|
||||
description: "Complete reference of OpenTelemetry log events emitted by Cline"
|
||||
---
|
||||
|
||||
This page documents all OpenTelemetry log events currently instrumented in Cline. These events are emitted when OpenTelemetry integration is enabled and provide detailed insights into user behavior, task execution, and system operations.
|
||||
|
||||
<Info>
|
||||
Events are only emitted when OpenTelemetry is enabled. See [OpenTelemetry](/enterprise-solutions/monitoring/opentelemetry) for configuration instructions.
|
||||
</Info>
|
||||
|
||||
## Event Categories
|
||||
|
||||
Cline emits events across several categories, each prefixed with a namespace:
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="user.*" icon="user">
|
||||
Authentication, telemetry controls, extension lifecycle
|
||||
</Card>
|
||||
|
||||
<Card title="task.*" icon="list-check">
|
||||
Task execution, conversation turns, tool usage, tokens
|
||||
</Card>
|
||||
|
||||
<Card title="workspace.*" icon="folder-tree">
|
||||
Workspace initialization, VCS detection, path resolution
|
||||
</Card>
|
||||
|
||||
<Card title="ui.*" icon="window">
|
||||
User interface interactions and model selection
|
||||
</Card>
|
||||
|
||||
<Card title="hooks.*" icon="webhook">
|
||||
Hook discovery, execution, and context modification
|
||||
</Card>
|
||||
|
||||
<Card title="worktree.*" icon="code-branch">
|
||||
Git worktree operations and merge handling
|
||||
</Card>
|
||||
|
||||
<Card title="host.*" icon="computer">
|
||||
Host environment detection
|
||||
</Card>
|
||||
|
||||
<Card title="test.*" icon="flask">
|
||||
Diagnostic and connection testing
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## User Events
|
||||
|
||||
Events related to user authentication, telemetry preferences, and extension lifecycle.
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `user.opt_out` | User explicitly opts out of telemetry | user_id, timestamp |
|
||||
| `user.opt_in` | User explicitly opts into telemetry | user_id, timestamp |
|
||||
| `user.telemetry_enabled` | Telemetry service enabled/initialization signal | enabled, timestamp |
|
||||
| `user.extension_activated` | Extension activation event | extension_version, host_type |
|
||||
| `user.extension_storage_error` | Error while reading/writing extension storage state | error_type, error_message |
|
||||
| `user.auth_started` | Authentication flow started | provider, timestamp |
|
||||
| `user.auth_succeeded` | Authentication flow succeeded | provider, user_id |
|
||||
| `user.auth_failed` | Authentication flow failed | provider, error_reason |
|
||||
| `user.auth_logged_out` | User logged out | reason, provider |
|
||||
| `user.onboarding_progress` | Onboarding step/action progress | step, action, completed |
|
||||
|
||||
### Example: user.auth_succeeded
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "user.auth_succeeded",
|
||||
"timestamp": "2026-03-05T10:30:00Z",
|
||||
"attributes": {
|
||||
"provider": "github",
|
||||
"user_id": "user_abc123",
|
||||
"session_id": "sess_xyz789"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Workspace Events
|
||||
|
||||
Events related to workspace initialization, version control detection, and multi-root operations.
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `workspace.initialized` | Workspace initialization completed | roots_count, vcs_type, duration_ms |
|
||||
| `workspace.init_error` | Workspace initialization failed | error_type, fallback_used |
|
||||
| `workspace.vcs_detected` | Version control system detection event | vcs_type, root_path_hash |
|
||||
| `workspace.multi_root_checkpoint` | Multi-root checkpoint operation telemetry | operation, roots_count, duration_ms |
|
||||
| `workspace.path_resolved` | Workspace path resolution | hint, fallback_used, cross_workspace |
|
||||
|
||||
### Example: workspace.initialized
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "workspace.initialized",
|
||||
"timestamp": "2026-03-05T10:32:15Z",
|
||||
"attributes": {
|
||||
"roots_count": 2,
|
||||
"vcs_type": "git",
|
||||
"duration_ms": 145,
|
||||
"multi_root_enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Task Events
|
||||
|
||||
Core events tracking task lifecycle, conversation turns, tool usage, and execution details.
|
||||
|
||||
### Task Lifecycle
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.created` | New task/conversation started | task_id, mode, model, provider |
|
||||
| `task.restarted` | Existing task restarted/reopened | task_id, time_since_last_message |
|
||||
| `task.completed` | Task completed | task_id, duration_ms, model, provider, tokens_total |
|
||||
| `task.feedback` | User feedback on task | task_id, feedback_type (thumbs_up/thumbs_down) |
|
||||
| `task.historical_loaded` | Historical task loaded from storage | task_id, age_days |
|
||||
| `task.retry_clicked` | User clicked retry on a failed action/request | task_id, action_type |
|
||||
|
||||
### Conversation & Tokens
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.conversation_turn` | Conversation turn event | role (user/assistant), provider, model, tokens_in, tokens_out |
|
||||
| `task.tokens` | Token usage event | tokens_in, tokens_out, cached_tokens, cost |
|
||||
| `task.mode` | Plan/Act mode switch event | previous_mode, new_mode, task_id |
|
||||
|
||||
### Tool Usage
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.tool_used` | Tool invocation and outcome telemetry | tool_name, success, duration_ms, auto_approved |
|
||||
| `task.mcp_tool_called` | MCP tool call lifecycle event | status (started/success/error), tool_name, server_name |
|
||||
| `task.browser_tool_start` | Browser tool/session started | url, action |
|
||||
| `task.browser_tool_end` | Browser tool/session ended with stats | duration_ms, actions_count, success |
|
||||
| `task.browser_error` | Browser tool error event | error_type, url |
|
||||
| `task.terminal_execution` | Terminal execution capture success/failure event | success, command_hash, duration_ms |
|
||||
| `task.terminal_output_failure` | Terminal output capture failed | reason |
|
||||
| `task.terminal_user_intervention` | User intervention during terminal execution | intervention_type |
|
||||
| `task.terminal_hang` | Terminal hang/stuck detection event | duration_ms, command_hash |
|
||||
|
||||
### Features & Options
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.checkpoint_used` | Checkpoint action used | action (create/restore/compare), task_id |
|
||||
| `task.option_selected` | User selected one of AI-provided options | option_index, total_options |
|
||||
| `task.options_ignored` | User ignored AI options and entered custom input | options_count |
|
||||
| `task.slash_command_used` | Slash command or MCP prompt command used | command_name |
|
||||
| `task.mention_used` | Mention resolution succeeded | mention_type (file/url/folder/terminal/problems/git) |
|
||||
| `task.mention_failed` | Mention resolution failed | mention_type, error_reason |
|
||||
| `task.mention_search_results` | Mention search query result telemetry | query, results_count |
|
||||
| `task.workspace_search_pattern` | Workspace search strategy/pattern telemetry | pattern_type, files_scanned |
|
||||
|
||||
### Advanced Features
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.focus_chain_enabled` | Focus chain feature enabled | task_id |
|
||||
| `task.focus_chain_disabled` | Focus chain feature disabled | task_id |
|
||||
| `task.focus_chain_progress_first` | First focus-chain checklist/progress emitted | items_count |
|
||||
| `task.focus_chain_progress_update` | Subsequent focus-chain checklist/progress updates | items_total, items_completed |
|
||||
| `task.focus_chain_incomplete_on_completion` | Task completed while focus-chain checklist still incomplete | items_remaining |
|
||||
| `task.focus_chain_list_opened` | Focus-chain markdown/list opened by user | task_id |
|
||||
| `task.focus_chain_list_written` | Focus-chain markdown/list written/saved | task_id |
|
||||
| `task.subagent_enabled` | Subagents feature enabled | task_id |
|
||||
| `task.subagent_disabled` | Subagents feature disabled | task_id |
|
||||
| `task.subagent_started` | Subagent execution started | subagent_id, prompt_length |
|
||||
| `task.subagent_completed` | Subagent execution completed | subagent_id, duration_ms, success |
|
||||
| `task.skill_used` | Skill invocation event | skill_name, task_id |
|
||||
|
||||
### Auto-Compact & Context
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.summarize_task` | Auto-compaction/summarize triggered for context pressure | conversation_length, estimated_tokens |
|
||||
| `task.auto_condense_toggled` | Auto-condense setting toggled | enabled |
|
||||
|
||||
### Settings & Features
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.feature_toggled` | Generic feature toggle changed | feature_name, enabled |
|
||||
| `task.rule_toggled` | Cline rule toggled on/off | rule_name, enabled, is_global |
|
||||
| `task.yolo_mode_toggled` | YOLO mode toggled | enabled |
|
||||
| `task.cline_web_tools_toggled` | Cline web tools setting toggled | enabled |
|
||||
|
||||
### API & Performance
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.gemini_api_performance` | Gemini-specific API performance telemetry | duration_ms, tokens, cache_hit |
|
||||
| `task.provider_api_error` | API provider error event | provider, model, error_code, error_message |
|
||||
| `task.diff_edit_failed` | Diff/replace edit failed | file_path_hash, error_type |
|
||||
| `task.initialization` | Task initialization timing/metadata event | duration_ms, mode |
|
||||
|
||||
### AI Output Feedback
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `task.ai_output.accepted` | AI-generated file edit accepted | lines_added, lines_removed, file_count |
|
||||
| `task.ai_output.rejected` | AI-generated file edit rejected | lines_added, lines_removed, file_count |
|
||||
|
||||
### Example: task.tool_used
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "task.tool_used",
|
||||
"timestamp": "2026-03-05T10:35:22Z",
|
||||
"attributes": {
|
||||
"task_id": "task_1234567890",
|
||||
"tool_name": "write_to_file",
|
||||
"success": true,
|
||||
"duration_ms": 125,
|
||||
"auto_approved": false,
|
||||
"model": "claude-sonnet-4",
|
||||
"provider": "anthropic"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## UI Events
|
||||
|
||||
Events tracking user interface interactions.
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `ui.model_selected` | Model selected in UI | model, provider, previous_model |
|
||||
| `ui.model_favorite_toggled` | Model favorite toggled | model_id, is_favorited |
|
||||
| `ui.button_clicked` | UI button click event | button_id, context |
|
||||
| `ui.rules_menu_opened` | Rules/skills menu/modal opened | menu_type |
|
||||
|
||||
### Example: ui.model_selected
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "ui.model_selected",
|
||||
"timestamp": "2026-03-05T11:20:00Z",
|
||||
"attributes": {
|
||||
"model": "claude-sonnet-4",
|
||||
"provider": "anthropic",
|
||||
"previous_model": "gpt-4o",
|
||||
"mode": "act"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Hooks Events
|
||||
|
||||
Events related to hook discovery, execution lifecycle, and context modifications.
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `hooks.enabled` | Hooks feature enabled | user_id |
|
||||
| `hooks.disabled` | Hooks feature disabled | user_id |
|
||||
| `hooks.cancel_requested` | Hook requested cancellation | hook_name, task_id |
|
||||
| `hooks.context_modified` | Hook modified context | hook_name, modification_type |
|
||||
| `hooks.discovery_completed` | Hook discovery completed | hooks_count, global_count, workspace_count |
|
||||
| `hooks.execution` | Unified hook execution lifecycle | hook_name, status (started/completed/failed/cancelled), duration_ms |
|
||||
|
||||
### Hook Execution Lifecycle
|
||||
|
||||
The `hooks.execution` event tracks the complete lifecycle with a `status` attribute:
|
||||
|
||||
- **started**: Hook execution began
|
||||
- **completed**: Hook finished successfully
|
||||
- **failed**: Hook encountered an error
|
||||
- **cancelled**: Hook was cancelled by user or system
|
||||
|
||||
### Example: hooks.execution
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "hooks.execution",
|
||||
"timestamp": "2026-03-05T10:40:15Z",
|
||||
"attributes": {
|
||||
"hook_name": "preToolUse",
|
||||
"status": "completed",
|
||||
"duration_ms": 234,
|
||||
"task_id": "task_1234567890",
|
||||
"context_modified": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Worktree Events
|
||||
|
||||
Events related to Git worktree operations.
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `worktree.view_opened` | Worktree view opened | user_id |
|
||||
| `worktree.created` | Worktree create event | success, branch_name, duration_ms |
|
||||
| `worktree.merge_attempted` | Worktree merge attempt event | has_conflicts, delete_option_chosen |
|
||||
|
||||
### Example: worktree.created
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "worktree.created",
|
||||
"timestamp": "2026-03-05T14:22:00Z",
|
||||
"attributes": {
|
||||
"success": true,
|
||||
"branch_name_hash": "abc123",
|
||||
"duration_ms": 1250,
|
||||
"parent_branch": "main"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Host Events
|
||||
|
||||
Events related to host environment detection.
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `host.detected` | Host environment detection event | host_type (vscode/jetbrains/cli), version |
|
||||
|
||||
### Example: host.detected
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "host.detected",
|
||||
"timestamp": "2026-03-05T09:00:00Z",
|
||||
"attributes": {
|
||||
"host_type": "vscode",
|
||||
"version": "1.95.0",
|
||||
"platform": "darwin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Test Events
|
||||
|
||||
Diagnostic and connection testing events.
|
||||
|
||||
| Event | Description | Key Attributes |
|
||||
|-------|-------------|----------------|
|
||||
| `cline.test.connection` | OTEL connection test event from "Test OTEL Connection" flow | success, exporter_type, endpoint |
|
||||
|
||||
### Example: cline.test.connection
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "cline.test.connection",
|
||||
"timestamp": "2026-03-05T15:30:00Z",
|
||||
"attributes": {
|
||||
"success": true,
|
||||
"exporter_type": "otlp",
|
||||
"endpoint": "https://api.datadoghq.com:4317",
|
||||
"protocol": "grpc"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Event Attribute Guidelines
|
||||
|
||||
### Common Attributes
|
||||
|
||||
Most events include these standard attributes:
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `timestamp` | ISO 8601 | Event occurrence time |
|
||||
| `user_id` | string | Anonymized user identifier (when authenticated) |
|
||||
| `session_id` | string | Current session identifier |
|
||||
| `extension_version` | string | Cline extension version |
|
||||
| `host_type` | string | vscode, jetbrains, or cli |
|
||||
|
||||
### Privacy & Hashing
|
||||
|
||||
Sensitive information is hashed or anonymized:
|
||||
|
||||
- **File paths**: Hashed to preserve privacy
|
||||
- **Command content**: Hashed, not logged verbatim
|
||||
- **User identifiers**: Anonymized tokens
|
||||
- **Branch names**: Hashed in worktree events
|
||||
|
||||
<Warning>
|
||||
File paths, command arguments, and code content are **never** included in raw form. Only hashes or anonymized identifiers are used.
|
||||
</Warning>
|
||||
|
||||
## Task Event Deep Dive
|
||||
|
||||
Task events are the most detailed category. Here's a typical task execution flow:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant Cline
|
||||
participant OTel
|
||||
|
||||
User->>Cline: Start Task
|
||||
Cline->>OTel: task.created
|
||||
|
||||
User->>Cline: Submit Message
|
||||
Cline->>OTel: task.conversation_turn (user)
|
||||
|
||||
Cline->>Cline: Process with AI
|
||||
Cline->>OTel: task.tokens
|
||||
Cline->>OTel: task.conversation_turn (assistant)
|
||||
|
||||
Cline->>Cline: Use Tool
|
||||
Cline->>OTel: task.tool_used
|
||||
|
||||
User->>Cline: Provide Feedback
|
||||
Cline->>OTel: task.option_selected
|
||||
|
||||
User->>Cline: Complete Task
|
||||
Cline->>OTel: task.completed
|
||||
```
|
||||
|
||||
### Task Token Tracking
|
||||
|
||||
Token events provide detailed cost and usage information:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "task.tokens",
|
||||
"timestamp": "2026-03-05T10:35:30Z",
|
||||
"attributes": {
|
||||
"task_id": "task_1234567890",
|
||||
"tokens_in": 2500,
|
||||
"tokens_out": 850,
|
||||
"cached_tokens": 1200,
|
||||
"cost": 0.0043,
|
||||
"model": "claude-sonnet-4",
|
||||
"provider": "anthropic"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Using Events for Analytics
|
||||
|
||||
<Warning>
|
||||
**SQL syntax is illustrative only.** Attribute access varies by observability platform — for example, `JSON_EXTRACT(attributes, '$.model')` in BigQuery, `attributes['model']` in ClickHouse, or `@attributes.model` in Datadog. Adapt all queries below to your platform's query language before use.
|
||||
</Warning>
|
||||
|
||||
### Query Patterns
|
||||
|
||||
**Most used tools:**
|
||||
```sql
|
||||
SELECT attributes.tool_name, COUNT(*) as count
|
||||
FROM otel_logs
|
||||
WHERE event = 'task.tool_used'
|
||||
AND attributes.success = true
|
||||
GROUP BY attributes.tool_name
|
||||
ORDER BY count DESC
|
||||
LIMIT 10
|
||||
```
|
||||
|
||||
**Average task duration by model:**
|
||||
```sql
|
||||
SELECT
|
||||
attributes.model,
|
||||
AVG(attributes.duration_ms) as avg_duration_ms,
|
||||
COUNT(*) as task_count
|
||||
FROM otel_logs
|
||||
WHERE event = 'task.completed'
|
||||
GROUP BY attributes.model
|
||||
```
|
||||
|
||||
**Token usage by provider:**
|
||||
```sql
|
||||
SELECT
|
||||
attributes.provider,
|
||||
SUM(attributes.tokens_in) as total_tokens_in,
|
||||
SUM(attributes.tokens_out) as total_tokens_out,
|
||||
SUM(attributes.cost) as total_cost
|
||||
FROM otel_logs
|
||||
WHERE event = 'task.tokens'
|
||||
AND timestamp >= NOW() - INTERVAL '30 days'
|
||||
GROUP BY attributes.provider
|
||||
```
|
||||
|
||||
**Tool approval rates:**
|
||||
```sql
|
||||
SELECT
|
||||
attributes.tool_name,
|
||||
SUM(CASE WHEN attributes.auto_approved THEN 1 ELSE 0 END)::float / COUNT(*) as auto_approval_rate,
|
||||
COUNT(*) as total_uses
|
||||
FROM otel_logs
|
||||
WHERE event = 'task.tool_used'
|
||||
GROUP BY attributes.tool_name
|
||||
ORDER BY total_uses DESC
|
||||
```
|
||||
|
||||
## Integration Examples
|
||||
|
||||
<Note>
|
||||
Query syntax below is illustrative. Attribute access varies by platform — for example, `JSON_EXTRACT(attributes, '$.model')` in BigQuery, `attributes['model']` in ClickHouse, or dot notation in Datadog. Adapt to your platform's query language.
|
||||
</Note>
|
||||
|
||||
### Datadog Dashboard
|
||||
|
||||
Create custom Datadog dashboards using these events:
|
||||
|
||||
```json
|
||||
{
|
||||
"widgets": [
|
||||
{
|
||||
"definition": {
|
||||
"type": "timeseries",
|
||||
"requests": [
|
||||
{
|
||||
"q": "sum:cline.task.completed{*}.as_count()",
|
||||
"display_type": "bars"
|
||||
}
|
||||
],
|
||||
"title": "Tasks Completed Over Time"
|
||||
}
|
||||
},
|
||||
{
|
||||
"definition": {
|
||||
"type": "query_value",
|
||||
"requests": [
|
||||
{
|
||||
"q": "sum:cline.task.tokens{*}",
|
||||
"aggregator": "sum"
|
||||
}
|
||||
],
|
||||
"title": "Total Tokens Used"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Grafana Queries
|
||||
|
||||
Example Loki query for tool usage:
|
||||
|
||||
```logql
|
||||
{event="task.tool_used"}
|
||||
| json
|
||||
| line_format "{{.attributes_tool_name}}: {{.attributes_success}}"
|
||||
```
|
||||
|
||||
### New Relic NRQL
|
||||
|
||||
Query task completion rates:
|
||||
|
||||
```sql
|
||||
SELECT count(*)
|
||||
FROM Log
|
||||
WHERE event = 'task.completed'
|
||||
FACET attributes.model
|
||||
SINCE 1 day ago
|
||||
```
|
||||
|
||||
## Event Schema Reference
|
||||
|
||||
All events follow this structure:
|
||||
|
||||
```typescript
|
||||
interface OtelLogEvent {
|
||||
event: string // Event name (e.g., "task.created")
|
||||
timestamp: string // ISO 8601 timestamp
|
||||
attributes: {
|
||||
// Event-specific attributes
|
||||
[key: string]: string | number | boolean
|
||||
}
|
||||
resource: {
|
||||
service_name: "cline"
|
||||
service_version: string // Extension version
|
||||
host_type: string // vscode | jetbrains | cli
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Filter Noise" icon="filter">
|
||||
Focus on events relevant to your use case. Not all events need dashboards.
|
||||
</Card>
|
||||
|
||||
<Card title="Set Alerts" icon="bell">
|
||||
Alert on error events and usage anomalies for proactive monitoring.
|
||||
</Card>
|
||||
|
||||
<Card title="Aggregate Metrics" icon="chart-bar">
|
||||
Roll up events into metrics for long-term trend analysis.
|
||||
</Card>
|
||||
|
||||
<Card title="Respect Privacy" icon="shield">
|
||||
Remember events are already anonymized. Don't attempt to de-anonymize.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Events Not Appearing
|
||||
|
||||
If events aren't showing up in your observability platform:
|
||||
|
||||
1. **Verify OTel is enabled** in remote configuration or environment variables
|
||||
2. **Check endpoint configuration** - ensure URL and protocol are correct
|
||||
3. **Validate credentials** - test with the "Test OTEL Connection" button
|
||||
4. **Check exporter settings** - ensure logs exporter includes `otlp`
|
||||
5. **Review platform-specific requirements** - some platforms need specific headers
|
||||
|
||||
### Event Volume Concerns
|
||||
|
||||
If you're seeing excessive event volume:
|
||||
|
||||
1. **Sample events** - Configure sampling in your OTel collector
|
||||
2. **Filter events** - Use your platform's filtering to drop noisy events
|
||||
3. **Aggregate on collection** - Pre-aggregate metrics before export
|
||||
4. **Adjust export intervals** - Increase `openTelemetryMetricExportInterval` and batch settings
|
||||
|
||||
## See Also
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="OpenTelemetry Setup" icon="chart-line" href="/enterprise-solutions/monitoring/opentelemetry">
|
||||
Configure OTel integration
|
||||
</Card>
|
||||
|
||||
<Card title="Prompt Storage" icon="database" href="/enterprise-solutions/monitoring/prompt-storage">
|
||||
Backup conversation history
|
||||
</Card>
|
||||
|
||||
<Card title="Telemetry" icon="chart-simple" href="/enterprise-solutions/monitoring/telemetry">
|
||||
Basic telemetry overview
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -194,7 +194,11 @@ Current OpenTelemetry support in Cline:
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Event Reference" icon="list" href="/enterprise-solutions/monitoring/opentelemetry-events">
|
||||
Complete catalog of all emitted OTel events
|
||||
</Card>
|
||||
|
||||
<Card title="Cline Telemetry" icon="chart-simple" href="/enterprise-solutions/monitoring/telemetry">
|
||||
Configure simple built-in telemetry
|
||||
</Card>
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
---
|
||||
title: "OpenTelemetry Environment Variables"
|
||||
sidebarTitle: "OpenTelemetry Override"
|
||||
description: "Configure OpenTelemetry using environment variables for advanced scenarios"
|
||||
---
|
||||
|
||||
<Note>
|
||||
This is an **advanced configuration method**. Most users should use [Remote Configuration](/enterprise-solutions/monitoring/opentelemetry) via the dashboard instead.
|
||||
</Note>
|
||||
|
||||
Environment variables provide an alternative way to configure OpenTelemetry, useful for self-hosted deployments, local development, CI/CD pipelines, or when you need to override organization settings.
|
||||
|
||||
## When to Use
|
||||
|
||||
- **Self-hosted deployments** without dashboard access
|
||||
- **Local development and testing** with your own collectors
|
||||
- **CI/CD pipelines** that need observability
|
||||
- **Override organization settings** with user-specific configuration
|
||||
|
||||
<Warning>
|
||||
Environment variable configuration bypasses user telemetry settings and will export data regardless of individual preferences.
|
||||
</Warning>
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### Core Configuration
|
||||
|
||||
| Variable | Description | Values |
|
||||
|----------|-------------|--------|
|
||||
| `CLINE_OTEL_TELEMETRY_ENABLED` | Enable OpenTelemetry export | `"true"` or `"false"` |
|
||||
| `CLINE_OTEL_METRICS_EXPORTER` | Metrics exporters (comma-separated) | `"console"`, `"otlp"` |
|
||||
| `CLINE_OTEL_LOGS_EXPORTER` | Logs exporters (comma-separated) | `"console"`, `"otlp"` |
|
||||
|
||||
### OTLP Configuration
|
||||
|
||||
| Variable | Description | Values |
|
||||
|----------|-------------|--------|
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_PROTOCOL` | OTLP protocol | `"grpc"`, `"http/json"`, or `"http/protobuf"` |
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint (applies to both metrics and logs) | URL with optional port |
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_HEADERS` | Authentication headers (comma-separated `key=value` pairs) | `"key=value,key2=value2"` |
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_INSECURE` | Disable TLS for gRPC (local development only) | `"true"` |
|
||||
|
||||
### Advanced OTLP Configuration
|
||||
|
||||
For separate metrics and logs endpoints:
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Metrics-specific protocol override |
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | Metrics-specific endpoint |
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` | Logs-specific protocol override |
|
||||
| `CLINE_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Logs-specific endpoint |
|
||||
|
||||
### Export Tuning
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `CLINE_OTEL_METRIC_EXPORT_INTERVAL` | Milliseconds between metric exports | 60000 |
|
||||
| `CLINE_OTEL_LOG_BATCH_SIZE` | Maximum batch size for log records | 512 |
|
||||
| `CLINE_OTEL_LOG_BATCH_TIMEOUT` | Maximum time before exporting logs (ms) | 5000 |
|
||||
| `CLINE_OTEL_LOG_MAX_QUEUE_SIZE` | Maximum queue size for log records | 2048 |
|
||||
|
||||
## Quick Start Examples
|
||||
|
||||
### Datadog with gRPC
|
||||
|
||||
```bash
|
||||
export CLINE_OTEL_TELEMETRY_ENABLED=true
|
||||
export CLINE_OTEL_METRICS_EXPORTER=otlp
|
||||
export CLINE_OTEL_LOGS_EXPORTER=otlp
|
||||
export CLINE_OTEL_EXPORTER_OTLP_PROTOCOL=grpc
|
||||
export CLINE_OTEL_EXPORTER_OTLP_ENDPOINT=https://api.datadoghq.com:4317
|
||||
export CLINE_OTEL_EXPORTER_OTLP_HEADERS="dd-api-key=YOUR_API_KEY"
|
||||
|
||||
code .
|
||||
```
|
||||
|
||||
<Note>
|
||||
The endpoint shown above is for Datadog's **US1 region**. If you're in a different region (EU, US3, US5, AP1, etc.), replace `api.datadoghq.com` with your region-specific hostname (e.g., `api.datadoghq.eu` for EU). See [Datadog's OTLP documentation](https://docs.datadoghq.com/opentelemetry/) for your region's endpoint.
|
||||
</Note>
|
||||
|
||||
### New Relic with HTTP
|
||||
|
||||
```bash
|
||||
export CLINE_OTEL_TELEMETRY_ENABLED=true
|
||||
export CLINE_OTEL_METRICS_EXPORTER=otlp
|
||||
export CLINE_OTEL_LOGS_EXPORTER=otlp
|
||||
export CLINE_OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
|
||||
export CLINE_OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.nr-data.net:4318
|
||||
export CLINE_OTEL_EXPORTER_OTLP_HEADERS="api-key=YOUR_LICENSE_KEY"
|
||||
|
||||
code .
|
||||
```
|
||||
|
||||
### Local Development (Insecure)
|
||||
|
||||
```bash
|
||||
export CLINE_OTEL_TELEMETRY_ENABLED=true
|
||||
export CLINE_OTEL_METRICS_EXPORTER=otlp
|
||||
export CLINE_OTEL_LOGS_EXPORTER=otlp
|
||||
export CLINE_OTEL_EXPORTER_OTLP_PROTOCOL=grpc
|
||||
export CLINE_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
|
||||
export CLINE_OTEL_EXPORTER_OTLP_INSECURE=true
|
||||
|
||||
code .
|
||||
```
|
||||
|
||||
### Console Output (Testing)
|
||||
|
||||
```bash
|
||||
export CLINE_OTEL_TELEMETRY_ENABLED=true
|
||||
export CLINE_OTEL_METRICS_EXPORTER=console
|
||||
export CLINE_OTEL_LOGS_EXPORTER=console
|
||||
|
||||
code .
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
Enable detailed OpenTelemetry diagnostic logging:
|
||||
|
||||
```bash
|
||||
export TEL_DEBUG_DIAGNOSTICS=true
|
||||
code .
|
||||
```
|
||||
|
||||
This outputs:
|
||||
- Configuration being used
|
||||
- Exporters being created
|
||||
- Connection attempts
|
||||
- Export successes/failures
|
||||
|
||||
Check the VS Code Developer Tools Console (Help > Toggle Developer Tools) for diagnostic output.
|
||||
|
||||
## Configuration Priority
|
||||
|
||||
When multiple configuration methods are present, Cline uses this priority order:
|
||||
|
||||
1. **Environment variables** (highest priority) - This method
|
||||
2. **Remote Configuration** - Dashboard settings
|
||||
3. **Default settings** - Built-in defaults
|
||||
|
||||
Environment variable configuration will override dashboard settings.
|
||||
|
||||
## See Also
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Dashboard Configuration" icon="globe" href="/enterprise-solutions/monitoring/opentelemetry">
|
||||
Configure OpenTelemetry via the web dashboard
|
||||
</Card>
|
||||
|
||||
<Card title="Remote Configuration" icon="server" href="/enterprise-solutions/configuration/remote-configuration/overview">
|
||||
Learn about Remote Configuration system
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -9,6 +9,14 @@ Cline includes optional monitoring capabilities for organizations that want to t
|
||||
## Monitoring Options
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Cline Telemetry" icon="chart-simple" href="/enterprise-solutions/monitoring/telemetry">
|
||||
Built-in anonymous usage tracking that helps improve Cline (opt-in)
|
||||
</Card>
|
||||
|
||||
<Card title="Prompt Storage" icon="database" href="/enterprise-solutions/monitoring/prompt-storage">
|
||||
Backup conversation history to S3/R2 for compliance and analysis
|
||||
</Card>
|
||||
|
||||
<Card title="OpenTelemetry" icon="chart-line" href="/enterprise-solutions/monitoring/opentelemetry">
|
||||
Export metrics and logs to your own observability backends
|
||||
</Card>
|
||||
@@ -18,12 +26,6 @@ Cline includes optional monitoring capabilities for organizations that want to t
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<Card title="Cline Telemetry" icon="chart-simple" href="/enterprise-solutions/monitoring/telemetry">
|
||||
Built-in anonymous usage tracking that helps improve Cline (opt-in)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Cline Telemetry
|
||||
|
||||
Cline includes opt-in telemetry for anonymous usage tracking:
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
---
|
||||
title: "Prompt Storage"
|
||||
description: "Backup conversation history to S3 or Cloudflare R2 for compliance, audit, and analysis"
|
||||
---
|
||||
|
||||
Prompt Storage allows enterprises to automatically back up Cline conversation history to cloud storage (AWS S3 or Cloudflare R2). This provides a centralized repository for compliance, audit trails, and usage analysis while maintaining local storage as the primary source of truth.
|
||||
|
||||
## Overview
|
||||
|
||||
Every Cline task conversation is stored locally in `~/.cline/data/tasks/<taskId>/api_conversation_history.json`. When prompt storage is enabled, a background sync worker automatically uploads these conversation files to your configured S3 or R2 bucket.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Compliance Ready" icon="shield-check">
|
||||
Maintain conversation records for regulatory requirements and internal policies.
|
||||
</Card>
|
||||
|
||||
<Card title="Audit Trail" icon="scroll">
|
||||
Track AI interactions across your organization with timestamped conversation logs.
|
||||
</Card>
|
||||
|
||||
<Card title="Usage Analysis" icon="chart-line">
|
||||
Analyze conversation patterns, token usage, and model performance at scale.
|
||||
</Card>
|
||||
|
||||
<Card title="Disaster Recovery" icon="cloud-arrow-up">
|
||||
Backup conversation history independent of local storage for business continuity.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## How It Works
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[User] --> B[Cline Extension]
|
||||
B --> C[Local Storage<br/>~/.cline/data/tasks/]
|
||||
C --> D[Background Sync Worker]
|
||||
D --> E[S3/R2 Bucket]
|
||||
E --> F[Compliance/Analytics]
|
||||
```
|
||||
|
||||
1. **Local Storage First**: All conversations are written to local disk immediately
|
||||
2. **Background Sync**: A worker process queues conversation files for upload
|
||||
3. **Reliable Upload**: Automatic retry logic with configurable batch sizes
|
||||
4. **Cloud Backup**: Files are stored in your S3/R2 bucket with the same path structure
|
||||
|
||||
## Storage Architecture
|
||||
|
||||
### What Gets Stored
|
||||
|
||||
Prompt storage uploads the following files from each task:
|
||||
|
||||
| File | Content | Purpose |
|
||||
|------|---------|---------|
|
||||
| `api_conversation_history.json` | Full conversation in Anthropic MessageParam format | Core conversation data for analysis |
|
||||
| Task metadata | Task ID, timestamps, model info | Correlation and indexing |
|
||||
|
||||
### What's NOT Stored
|
||||
|
||||
Prompt storage **does not** include:
|
||||
|
||||
- ❌ Workspace files not accessed by Cline
|
||||
- ❌ API keys or secrets
|
||||
- ❌ User credentials or authentication tokens
|
||||
|
||||
<Warning>
|
||||
Conversation history includes **all tool inputs and outputs**. This means code written via `write_to_file`, file contents read via `read_file`, and command outputs are included in the uploaded data. Review your compliance and data classification requirements before enabling.
|
||||
</Warning>
|
||||
|
||||
### Storage Path Pattern
|
||||
|
||||
Files are uploaded to your bucket following this structure:
|
||||
|
||||
```
|
||||
s3://your-bucket/tasks/{taskId}/api_conversation_history.json
|
||||
```
|
||||
|
||||
This mirrors the local storage structure, making it easy to correlate local and cloud data.
|
||||
|
||||
## Configuration
|
||||
|
||||
Prompt storage is configured through Remote Configuration in the `enterpriseTelemetry.promptUploading` section.
|
||||
|
||||
### Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"enterpriseTelemetry": {
|
||||
"promptUploading": {
|
||||
"enabled": true,
|
||||
"type": "s3_access_keys",
|
||||
"s3AccessSettings": {
|
||||
"bucket": "your-cline-prompts",
|
||||
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
|
||||
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
||||
"region": "us-east-1",
|
||||
"intervalMs": 30000,
|
||||
"maxRetries": 5,
|
||||
"batchSize": 10,
|
||||
"maxQueueSize": 1000,
|
||||
"maxFailedAgeMs": 604800000,
|
||||
"backfillEnabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Fields
|
||||
|
||||
#### Core Settings
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `enabled` | boolean | Yes | Enable/disable prompt storage |
|
||||
| `type` | string | Yes | Storage type: `"s3_access_keys"` or `"r2_access_keys"` |
|
||||
|
||||
#### Access Settings (S3/R2)
|
||||
|
||||
| Field | Type | Required | Description | Default |
|
||||
|-------|------|----------|-------------|---------|
|
||||
| `bucket` | string | Yes | S3/R2 bucket name | - |
|
||||
| `accessKeyId` | string | Yes | AWS/Cloudflare access key ID | - |
|
||||
| `secretAccessKey` | string | Yes | AWS/Cloudflare secret access key | - |
|
||||
| `region` | string | S3 only | AWS region (e.g., `us-east-1`) | - |
|
||||
| `endpoint` | string | R2 only | Cloudflare R2 endpoint URL | - |
|
||||
| `accountId` | string | R2 only | Cloudflare account ID | - |
|
||||
|
||||
#### Sync Worker Settings
|
||||
|
||||
| Field | Type | Description | Default |
|
||||
|-------|------|-------------|---------|
|
||||
| `intervalMs` | number | Milliseconds between sync attempts | 30000 (30s) |
|
||||
| `maxRetries` | number | Maximum retries before giving up | 5 |
|
||||
| `batchSize` | number | Items to process per interval | 10 |
|
||||
| `maxQueueSize` | number | Maximum queue size before eviction | 1000 |
|
||||
| `maxFailedAgeMs` | number | Time before discarding failed items | 604800000 (7 days) |
|
||||
| `backfillEnabled` | boolean | Sync existing tasks on startup | false |
|
||||
|
||||
## Setup Guides
|
||||
|
||||
<Tabs>
|
||||
<Tab title="AWS S3">
|
||||
### AWS S3 Configuration
|
||||
|
||||
<Steps>
|
||||
<Step title="Create S3 Bucket">
|
||||
Create a dedicated S3 bucket for Cline conversation storage:
|
||||
|
||||
```bash
|
||||
aws s3 mb s3://your-cline-prompts --region us-east-1
|
||||
```
|
||||
|
||||
Enable versioning and encryption:
|
||||
|
||||
```bash
|
||||
aws s3api put-bucket-versioning \
|
||||
--bucket your-cline-prompts \
|
||||
--versioning-configuration Status=Enabled
|
||||
|
||||
aws s3api put-bucket-encryption \
|
||||
--bucket your-cline-prompts \
|
||||
--server-side-encryption-configuration '{
|
||||
"Rules": [{
|
||||
"ApplyServerSideEncryptionByDefault": {
|
||||
"SSEAlgorithm": "AES256"
|
||||
}
|
||||
}]
|
||||
}'
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create IAM Policy">
|
||||
Create an IAM policy with minimal required permissions:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:PutObject",
|
||||
"s3:PutObjectAcl",
|
||||
"s3:GetObject",
|
||||
"s3:DeleteObject"
|
||||
],
|
||||
"Resource": "arn:aws:s3:::your-cline-prompts/*"
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Resource": "arn:aws:s3:::your-cline-prompts"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Save this as `cline-prompt-storage-policy.json` and create the policy:
|
||||
|
||||
```bash
|
||||
aws iam create-policy \
|
||||
--policy-name ClinePromptStorage \
|
||||
--policy-document file://cline-prompt-storage-policy.json
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create IAM User">
|
||||
Create a dedicated IAM user and attach the policy:
|
||||
|
||||
```bash
|
||||
aws iam create-user --user-name cline-prompt-uploader
|
||||
|
||||
aws iam attach-user-policy \
|
||||
--user-name cline-prompt-uploader \
|
||||
--policy-arn arn:aws:iam::YOUR_ACCOUNT_ID:policy/ClinePromptStorage
|
||||
|
||||
aws iam create-access-key --user-name cline-prompt-uploader
|
||||
```
|
||||
|
||||
Save the `AccessKeyId` and `SecretAccessKey` from the output.
|
||||
</Step>
|
||||
|
||||
<Step title="Configure in Cline Dashboard">
|
||||
In the Cline admin console at [app.cline.bot](https://app.cline.bot):
|
||||
|
||||
1. Navigate to **Settings** → **Enterprise Telemetry**
|
||||
2. Enable **Prompt Uploading**
|
||||
3. Select **S3** as the storage type
|
||||
4. Enter your bucket name, access key ID, secret key, and region
|
||||
5. Configure sync worker settings (or use defaults)
|
||||
6. Save configuration
|
||||
</Step>
|
||||
|
||||
<Step title="Test Connection">
|
||||
Use the "Test Connection" button in the admin console to verify:
|
||||
- Bucket access
|
||||
- Write permissions
|
||||
- Credential validity
|
||||
|
||||
A test file will be uploaded and deleted from your bucket.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Optional: Lifecycle Policies
|
||||
|
||||
Configure retention policies for cost management:
|
||||
|
||||
```json
|
||||
{
|
||||
"Rules": [
|
||||
{
|
||||
"Id": "ArchiveOldPrompts",
|
||||
"Status": "Enabled",
|
||||
"Transitions": [
|
||||
{
|
||||
"Days": 90,
|
||||
"StorageClass": "GLACIER"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "DeleteOldPrompts",
|
||||
"Status": "Enabled",
|
||||
"Expiration": {
|
||||
"Days": 2555
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Cloudflare R2">
|
||||
### Cloudflare R2 Configuration
|
||||
|
||||
<Steps>
|
||||
<Step title="Create R2 Bucket">
|
||||
1. Log in to the [Cloudflare Dashboard](https://dash.cloudflare.com)
|
||||
2. Navigate to **R2** in the sidebar
|
||||
3. Click **Create bucket**
|
||||
4. Name your bucket (e.g., `cline-prompts`)
|
||||
5. Select a location close to your users
|
||||
6. Click **Create bucket**
|
||||
</Step>
|
||||
|
||||
<Step title="Generate API Token">
|
||||
1. In the R2 dashboard, click **Manage R2 API Tokens**
|
||||
2. Click **Create API token**
|
||||
3. Configure permissions:
|
||||
- **Token name**: Cline Prompt Storage
|
||||
- **Permissions**: Object Read & Write
|
||||
- **Bucket**: Select your bucket or use All buckets
|
||||
4. Click **Create API Token**
|
||||
5. Save the **Access Key ID** and **Secret Access Key**
|
||||
6. Note your **Account ID** (shown in the R2 overview)
|
||||
</Step>
|
||||
|
||||
<Step title="Get R2 Endpoint">
|
||||
Your R2 endpoint follows this format:
|
||||
|
||||
```
|
||||
https://<ACCOUNT_ID>.r2.cloudflarestorage.com
|
||||
```
|
||||
|
||||
Find your account ID in the Cloudflare dashboard under R2 overview.
|
||||
</Step>
|
||||
|
||||
<Step title="Configure in Cline Dashboard">
|
||||
In the Cline admin console at [app.cline.bot](https://app.cline.bot):
|
||||
|
||||
1. Navigate to **Settings** → **Enterprise Telemetry**
|
||||
2. Enable **Prompt Uploading**
|
||||
3. Select **R2** as the storage type
|
||||
4. Enter:
|
||||
- Bucket name
|
||||
- Access key ID
|
||||
- Secret access key
|
||||
- Account ID
|
||||
- Endpoint URL
|
||||
5. Configure sync worker settings (or use defaults)
|
||||
6. Save configuration
|
||||
</Step>
|
||||
|
||||
<Step title="Test Connection">
|
||||
Use the "Test Connection" button to verify:
|
||||
- Bucket access with provided credentials
|
||||
- Write permissions
|
||||
- Endpoint connectivity
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Cost Advantages
|
||||
|
||||
R2 offers significant cost advantages over S3:
|
||||
- **No egress fees**: Download data at no cost
|
||||
- **Lower storage costs**: ~$0.015/GB vs S3's ~$0.023/GB
|
||||
- **Global edge access**: Fast access from anywhere
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Sync Worker Behavior
|
||||
|
||||
The background sync worker manages the upload queue with these characteristics:
|
||||
|
||||
### Queue Management
|
||||
|
||||
- **FIFO ordering**: Files are uploaded in the order they were created
|
||||
- **Automatic batching**: Processes up to `batchSize` items per interval
|
||||
- **Queue size limits**: Evicts oldest items when `maxQueueSize` is exceeded
|
||||
- **Retry logic**: Failed uploads are retried up to `maxRetries` times
|
||||
|
||||
### Failure Handling
|
||||
|
||||
When an upload fails:
|
||||
|
||||
1. **Immediate retry**: Item stays in queue for next sync interval
|
||||
2. **Exponential backoff**: Retry attempts are spaced out
|
||||
3. **Maximum retries**: After `maxRetries` attempts, item is marked as permanently failed
|
||||
4. **Age-based cleanup**: Failed items older than `maxFailedAgeMs` are discarded
|
||||
5. **No data loss**: Local files remain intact regardless of sync status
|
||||
|
||||
### Backfill Mode
|
||||
|
||||
When `backfillEnabled` is set to `true`:
|
||||
|
||||
- On first startup, scans all existing tasks in `~/.cline/data/tasks/`
|
||||
- Queues conversation files that haven't been uploaded
|
||||
- Useful for enabling prompt storage on an existing Cline deployment
|
||||
- Can generate significant upload volume — monitor queue size
|
||||
|
||||
<Warning>
|
||||
Enable backfill carefully on large deployments. Consider starting with `backfillEnabled: false` and monitoring the steady-state queue before enabling backfill.
|
||||
</Warning>
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
### Integration with OpenTelemetry
|
||||
|
||||
While prompt storage operates independently, it integrates with Cline's observability system:
|
||||
|
||||
- **Task lifecycle events**: `task.created`, `task.completed` track when conversations are generated
|
||||
- **Conversation events**: `task.conversation_turn`, `task.tokens` provide usage metrics
|
||||
- **Local monitoring**: Sync worker status is logged but not yet exported as OTel events
|
||||
|
||||
See [OpenTelemetry](/enterprise-solutions/monitoring/opentelemetry) for configuring metrics export.
|
||||
|
||||
### CloudWatch Monitoring (S3)
|
||||
|
||||
Monitor S3 upload activity with CloudWatch:
|
||||
|
||||
```bash
|
||||
# View PutObject requests (uploads)
|
||||
aws cloudwatch get-metric-statistics \
|
||||
--namespace AWS/S3 \
|
||||
--metric-name NumberOfObjects \
|
||||
--dimensions Name=BucketName,Value=your-cline-prompts \
|
||||
--start-time 2026-03-01T00:00:00Z \
|
||||
--end-time 2026-03-08T00:00:00Z \
|
||||
--period 3600 \
|
||||
--statistics Sum
|
||||
```
|
||||
|
||||
### R2 Analytics
|
||||
|
||||
Cloudflare R2 provides built-in analytics in the dashboard:
|
||||
|
||||
- Request counts and rates
|
||||
- Storage usage over time
|
||||
- Bandwidth utilization
|
||||
- Error rates
|
||||
|
||||
## Security & Compliance
|
||||
|
||||
### Encryption
|
||||
|
||||
**At Rest:**
|
||||
- S3: Enable server-side encryption (SSE-S3 or SSE-KMS)
|
||||
- R2: Encryption enabled by default
|
||||
|
||||
**In Transit:**
|
||||
- All uploads use HTTPS/TLS
|
||||
- Credentials are never logged or exposed
|
||||
|
||||
### Access Control
|
||||
|
||||
**Recommended IAM policies:**
|
||||
|
||||
- Use dedicated IAM users/roles
|
||||
- Limit permissions to write-only if read access isn't needed
|
||||
- Enable MFA for credential generation
|
||||
- Rotate access keys regularly
|
||||
|
||||
**Bucket policies:**
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Deny",
|
||||
"Principal": "*",
|
||||
"Action": "s3:*",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::your-cline-prompts/*",
|
||||
"arn:aws:s3:::your-cline-prompts"
|
||||
],
|
||||
"Condition": {
|
||||
"Bool": {
|
||||
"aws:SecureTransport": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Audit Logging
|
||||
|
||||
**S3 Server Access Logging:**
|
||||
|
||||
```bash
|
||||
aws s3api put-bucket-logging \
|
||||
--bucket your-cline-prompts \
|
||||
--bucket-logging-status '{
|
||||
"LoggingEnabled": {
|
||||
"TargetBucket": "your-log-bucket",
|
||||
"TargetPrefix": "cline-prompts-access/"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**CloudTrail for API Calls:**
|
||||
|
||||
Enable CloudTrail to track all S3 API operations on your bucket.
|
||||
|
||||
### Data Retention
|
||||
|
||||
Implement retention policies based on your compliance requirements:
|
||||
|
||||
- **GDPR**: Consider right to erasure
|
||||
- **SOC 2**: Maintain audit trails for required period
|
||||
- **HIPAA**: Ensure appropriate retention and disposal
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Queue size growing continuously">
|
||||
**Symptoms**: `maxQueueSize` limit reached, oldest items being evicted
|
||||
|
||||
**Causes**:
|
||||
- Upload rate slower than conversation creation rate
|
||||
- Network connectivity issues
|
||||
- Insufficient batch size or interval
|
||||
|
||||
**Solutions**:
|
||||
1. Increase `batchSize` to process more items per interval
|
||||
2. Decrease `intervalMs` to sync more frequently
|
||||
3. Check network connectivity and credentials
|
||||
4. Temporarily increase `maxQueueSize` while investigating
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Uploads failing with 403 Forbidden">
|
||||
**Symptoms**: Repeated upload failures, items reaching `maxRetries`
|
||||
|
||||
**Causes**:
|
||||
- Invalid or expired credentials
|
||||
- Insufficient IAM permissions
|
||||
- Bucket policy denying access
|
||||
|
||||
**Solutions**:
|
||||
1. Verify credentials are correct in remote config
|
||||
2. Check IAM policy includes `s3:PutObject` permission
|
||||
3. Review bucket policies for deny rules
|
||||
4. Test with AWS CLI: `aws s3 cp test.txt s3://your-bucket/`
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="R2 endpoint connection timeout">
|
||||
**Symptoms**: Connection timeouts, failed uploads
|
||||
|
||||
**Causes**:
|
||||
- Incorrect endpoint URL
|
||||
- Firewall blocking Cloudflare IPs
|
||||
- Invalid account ID
|
||||
|
||||
**Solutions**:
|
||||
1. Verify endpoint format: `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`
|
||||
2. Check firewall rules allow HTTPS to Cloudflare IPs
|
||||
3. Confirm account ID in Cloudflare dashboard
|
||||
4. Test with curl: `curl -I https://<ACCOUNT_ID>.r2.cloudflarestorage.com`
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Backfill overwhelming upload queue">
|
||||
**Symptoms**: Queue at max size immediately after enabling backfill
|
||||
|
||||
**Causes**:
|
||||
- Large number of existing tasks
|
||||
- Backfill queuing faster than upload processing
|
||||
|
||||
**Solutions**:
|
||||
1. Disable backfill temporarily: `"backfillEnabled": false`
|
||||
2. Let steady-state queue drain first
|
||||
3. Increase `batchSize` and decrease `intervalMs`
|
||||
4. Consider `maxQueueSize` increase during backfill period
|
||||
5. Re-enable backfill once queue is stable
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Debug Logging
|
||||
|
||||
Enable debug logging to diagnose sync issues:
|
||||
|
||||
1. Check extension developer console (Help → Toggle Developer Tools)
|
||||
2. Look for `[ClineBlobStorage]` and `[SyncWorker]` log entries
|
||||
3. Failed uploads log error messages with details
|
||||
|
||||
### Testing Configuration
|
||||
|
||||
Use the built-in test connection feature:
|
||||
|
||||
```typescript
|
||||
// Programmatic test (for custom integrations)
|
||||
import { testPromptUploading } from '@/core/controller/state/testPromptUploading'
|
||||
|
||||
await testPromptUploading(controller)
|
||||
// Returns: { success: boolean, message: string }
|
||||
```
|
||||
|
||||
## Data Format Reference
|
||||
|
||||
### Conversation File Schema
|
||||
|
||||
Uploaded `api_conversation_history.json` files contain an array of messages:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Create a React component for a todo list"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "I'll create a todo list component..."
|
||||
},
|
||||
{
|
||||
"type": "tool_use",
|
||||
"id": "toolu_123",
|
||||
"name": "write_to_file",
|
||||
"input": {
|
||||
"path": "TodoList.tsx",
|
||||
"content": "..."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
This follows the [Anthropic Messages API format](https://docs.anthropic.com/claude/reference/messages_post).
|
||||
|
||||
### Metadata Schema
|
||||
|
||||
Task metadata includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"taskId": "1234567890",
|
||||
"createdAt": "2026-03-05T10:30:00Z",
|
||||
"lastModified": "2026-03-05T11:45:00Z",
|
||||
"modelInfo": {
|
||||
"id": "claude-sonnet-4",
|
||||
"provider": "anthropic"
|
||||
},
|
||||
"tokensUsed": {
|
||||
"input": 1250,
|
||||
"output": 3400
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Start Small" icon="seedling">
|
||||
Test with a single team or project before rolling out organization-wide.
|
||||
</Card>
|
||||
|
||||
<Card title="Monitor Costs" icon="dollar-sign">
|
||||
Set up billing alerts and review storage usage monthly.
|
||||
</Card>
|
||||
|
||||
<Card title="Secure Credentials" icon="lock">
|
||||
Use dedicated IAM users with minimal permissions and rotate keys regularly.
|
||||
</Card>
|
||||
|
||||
<Card title="Plan Retention" icon="calendar">
|
||||
Define and implement data retention policies based on compliance needs.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## See Also
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="OpenTelemetry" icon="chart-line" href="/enterprise-solutions/monitoring/opentelemetry">
|
||||
Configure metrics and logs export for comprehensive observability
|
||||
</Card>
|
||||
|
||||
<Card title="Telemetry" icon="chart-simple" href="/enterprise-solutions/monitoring/telemetry">
|
||||
Learn about Cline's built-in anonymous usage tracking
|
||||
</Card>
|
||||
|
||||
<Card title="Remote Configuration" icon="gear" href="/enterprise-solutions/configuration/remote-configuration/overview">
|
||||
Understand the remote configuration system
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user