mirror of
https://github.com/cline/cline.git
synced 2026-08-29 03:52:41 +08:00
Rename desktop app from "Cline Code" to "Cline" (#13401)
* Rename desktop app from Cline Code to Cline Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Format touched Rust test assertions Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> --------- Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
---
|
||||
name: publish-desktop
|
||||
description: Use when preparing, tagging, and publishing a Cline Code desktop app (apps/examples/desktop-app) release — stable (desktop-vX.Y.Z from main) or beta (desktop-vX.Y.Z-beta.N from desktop-experimental, shipped as the side-by-side "Cline Code Beta" app). Guides changelog drafting, version bumps in package.json + tauri.conf.json, tagging, and the desktop-publish GitHub workflow that builds, signs, notarizes, and updates the per-channel auto-update feed.
|
||||
description: Use when preparing, tagging, and publishing a Cline desktop app (apps/examples/desktop-app) release — stable (desktop-vX.Y.Z from main) or beta (desktop-vX.Y.Z-beta.N from desktop-experimental, shipped as the side-by-side "Cline Beta" app). Guides changelog drafting, version bumps in package.json + tauri.conf.json, tagging, and the desktop-publish GitHub workflow that builds, signs, notarizes, and updates the per-channel auto-update feed.
|
||||
---
|
||||
|
||||
# Desktop App Release
|
||||
|
||||
Use this skill when the user asks to release the desktop app, publish Cline Code, cut a desktop beta, bump the desktop version, create a `desktop-vX.Y.Z` (or `desktop-vX.Y.Z-beta.N`) tag, or trigger the desktop publish workflow.
|
||||
Use this skill when the user asks to release the desktop app, publish the Cline desktop app, cut a desktop beta, bump the desktop version, create a `desktop-vX.Y.Z` (or `desktop-vX.Y.Z-beta.N`) tag, or trigger the desktop publish workflow.
|
||||
|
||||
> Working directory: run every command below from the repository root.
|
||||
|
||||
@@ -14,8 +14,8 @@ Desktop releases are macOS-only today (a single signed + notarized universal DMG
|
||||
## Release contract
|
||||
|
||||
- Two channels, one workflow (`channel` input on `desktop-publish.yml`):
|
||||
- **stable** — tag `desktop-vX.Y.Z` (no suffix; the workflow rejects prerelease suffixes on this channel), cut from `main`, feeds the rolling `desktop-latest` release, ships as "Cline Code".
|
||||
- **beta** — tag `desktop-vX.Y.Z-beta.N`, cut from `desktop-experimental`, feeds the rolling `desktop-beta` release, ships as "Cline Code Beta" (separate bundle identifier `bot.cline.app.beta`; installs side by side with stable). Built with the extra `src-tauri/tauri.beta.conf.json` overlay. Process background: `apps/examples/desktop-app/EXPERIMENTAL.md`.
|
||||
- **stable** — tag `desktop-vX.Y.Z` (no suffix; the workflow rejects prerelease suffixes on this channel), cut from `main`, feeds the rolling `desktop-latest` release, ships as "Cline".
|
||||
- **beta** — tag `desktop-vX.Y.Z-beta.N`, cut from `desktop-experimental`, feeds the rolling `desktop-beta` release, ships as "Cline Beta" (separate bundle identifier `bot.cline.app.beta`; installs side by side with stable). Built with the extra `src-tauri/tauri.beta.conf.json` overlay. Process background: `apps/examples/desktop-app/EXPERIMENTAL.md`.
|
||||
- Version sources (must match each other and the tag): `apps/examples/desktop-app/package.json` and `apps/examples/desktop-app/src-tauri/tauri.conf.json`. (`src-tauri/Cargo.toml` has its own version but `tauri.conf.json` overrides it; no need to touch it.)
|
||||
- Beta versions are prereleases of the **next** stable: stable `0.0.13` → betas `0.0.14-beta.1`, `-beta.2`, … Once a stable ≥ the beta base ships, the next beta bumps its base (`0.0.15-beta.1`).
|
||||
- Release prep includes approved release notes, the version bumps, and an `apps/examples/desktop-app/CHANGELOG.md` update — committed on `main` for stable, on `desktop-experimental` for beta.
|
||||
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
fi
|
||||
ANCESTOR_REF=main
|
||||
FEED=desktop-latest
|
||||
PRODUCT="Cline Code"
|
||||
PRODUCT="Cline"
|
||||
;;
|
||||
beta)
|
||||
if ! printf "%s\n" "$TAG" | grep -Eq '^desktop-v[0-9]+\.[0-9]+\.[0-9]+-beta\.[0-9]+$'; then
|
||||
@@ -120,7 +120,7 @@ jobs:
|
||||
fi
|
||||
ANCESTOR_REF=desktop-experimental
|
||||
FEED=desktop-beta
|
||||
PRODUCT="Cline Code Beta"
|
||||
PRODUCT="Cline Beta"
|
||||
;;
|
||||
*)
|
||||
echo "unknown channel: ${CHANNEL}"
|
||||
@@ -435,7 +435,7 @@ jobs:
|
||||
OUT="dist/publish"
|
||||
mkdir -p "$OUT"
|
||||
|
||||
# "Cline Code" -> Cline-Code, "Cline Code Beta" -> Cline-Code-Beta
|
||||
# "Cline" -> Cline, "Cline Beta" -> Cline-Beta
|
||||
PREFIX="${PRODUCT// /-}"
|
||||
|
||||
DMG=$(find "$BUNDLE_DIR/dmg" -name '*.dmg' -print -quit)
|
||||
@@ -607,14 +607,14 @@ jobs:
|
||||
if ! gh release view "$FEED" >/dev/null 2>&1; then
|
||||
if [ "$CHANNEL" = "beta" ]; then
|
||||
gh release create "$FEED" \
|
||||
--title "Cline Code desktop beta (auto-update feed)" \
|
||||
--title "Cline desktop beta (auto-update feed)" \
|
||||
--notes "Rolling release backing the beta desktop app auto-updater. The latest.json asset points at the newest desktop-vX.Y.Z-beta.N release. Only beta installs poll this feed; stable installs use desktop-latest. Do not delete." \
|
||||
--latest=false \
|
||||
--prerelease \
|
||||
--target "$(git rev-parse HEAD)"
|
||||
else
|
||||
gh release create "$FEED" \
|
||||
--title "Cline Code desktop (auto-update feed)" \
|
||||
--title "Cline desktop (auto-update feed)" \
|
||||
--notes "Rolling release backing the desktop app auto-updater. The latest.json asset points at the newest desktop-vX.Y.Z release. Do not delete." \
|
||||
--latest=false \
|
||||
--target "$(git rev-parse HEAD)"
|
||||
@@ -628,7 +628,7 @@ jobs:
|
||||
TAG: ${{ needs.validate.outputs.tag }}
|
||||
FEED: ${{ needs.validate.outputs.feed }}
|
||||
run: |
|
||||
echo "Published Cline Code desktop v${VERSION}"
|
||||
echo "Published Cline desktop v${VERSION}"
|
||||
echo "Release: https://github.com/${GITHUB_REPOSITORY}/releases/tag/${TAG}"
|
||||
echo "Auto-update feed refreshed: https://github.com/${GITHUB_REPOSITORY}/releases/download/${FEED}/latest.json"
|
||||
|
||||
@@ -639,12 +639,12 @@ jobs:
|
||||
token: ${{ secrets.SLACK_RELEASE_BOT_TOKEN }}
|
||||
payload: |
|
||||
channel: "C0APVKGGZFC"
|
||||
text: "Cline Code desktop v${{ needs.validate.outputs.version }}${{ needs.validate.outputs.channel == 'beta' && ' (beta)' || '' }}"
|
||||
text: "Cline desktop v${{ needs.validate.outputs.version }}${{ needs.validate.outputs.channel == 'beta' && ' (beta)' || '' }}"
|
||||
blocks:
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: "Cline Code desktop v${{ needs.validate.outputs.version }}${{ needs.validate.outputs.channel == 'beta' && ' (beta)' || '' }}"
|
||||
text: "Cline desktop v${{ needs.validate.outputs.version }}${{ needs.validate.outputs.channel == 'beta' && ' (beta)' || '' }}"
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
|
||||
@@ -88,7 +88,7 @@ function summarizeClient(client: TrackedClient): {
|
||||
normalizedType === "code-sidecar-observer" ||
|
||||
normalizedType === "code-sidecar-list"
|
||||
) {
|
||||
return { key: "code-app", label: "Code App", name: "Code App" };
|
||||
return { key: "code-app", label: "Cline Desktop", name: "Cline Desktop" };
|
||||
}
|
||||
return {
|
||||
key: client.clientId,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Cline Code Desktop Changelog
|
||||
# Cline Desktop Changelog
|
||||
|
||||
## 0.0.14
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Desktop Experimental Branch & Beta Channel
|
||||
|
||||
How experimental desktop features are developed on the `desktop-experimental`
|
||||
branch, shipped to users as **Cline Code Beta**, and graduated into `main`.
|
||||
branch, shipped to users as **Cline Beta**, and graduated into `main`.
|
||||
The release mechanics (workflow internals, secrets) live in
|
||||
[`.github/workflows/desktop-publish.yml`](../../../.github/workflows/desktop-publish.yml)
|
||||
and the `publish-desktop` skill
|
||||
@@ -12,8 +12,8 @@ this doc is the process.
|
||||
|
||||
The beta is a **separate app**, not a mode of the stable app:
|
||||
|
||||
- Product name `Cline Code Beta`, bundle identifier `bot.cline.app.beta`
|
||||
(stable is `Cline Code` / `bot.cline.app`) — set by
|
||||
- Product name `Cline Beta`, bundle identifier `bot.cline.app.beta`
|
||||
(stable is `Cline` / `bot.cline.app`) — set by
|
||||
[`src-tauri/tauri.beta.conf.json`](./src-tauri/tauri.beta.conf.json), which
|
||||
is layered over `tauri.release.conf.json` at build time.
|
||||
- Both apps install and run **side by side**, so people can compare beta
|
||||
|
||||
@@ -55,7 +55,7 @@ lost: the `desktop-latest` release/tag (its feed URL is baked into shipped
|
||||
apps) and the updater private key (`TAURI_SIGNING_PRIVATE_KEY` — without it,
|
||||
shipped apps can't verify new updates).
|
||||
|
||||
There is also a beta channel ("Cline Code Beta", a separate app that installs
|
||||
There is also a beta channel ("Cline Beta", a separate app that installs
|
||||
side by side with stable) cut from the `desktop-experimental` branch and
|
||||
served by the rolling `desktop-beta` release — the same never-delete rule
|
||||
applies to it. The experimental-branch process and beta release flow live in
|
||||
|
||||
@@ -121,7 +121,7 @@ const main = () => {
|
||||
|
||||
const notes = notesFile
|
||||
? readFileSync(notesFile, "utf8").trim()
|
||||
: `Cline Code v${version}`;
|
||||
: `Cline v${version}`;
|
||||
|
||||
const manifest = buildUpdateManifest({
|
||||
version,
|
||||
|
||||
@@ -15,7 +15,7 @@ const BOOLEAN_FLAGS = new Set(["--allow-unsigned-mac", "--skip-build"]);
|
||||
const VALUE_FLAGS = new Set(["--platform", "--target"]);
|
||||
const VALID_FLAGS = [...BOOLEAN_FLAGS, ...VALUE_FLAGS];
|
||||
|
||||
const APP_NAME = "Cline Code";
|
||||
const APP_NAME = "Cline";
|
||||
const APP_ROOT = path.resolve(import.meta.dir, "..");
|
||||
const BUNDLE_ROOT = path.join(
|
||||
APP_ROOT,
|
||||
|
||||
@@ -49,7 +49,7 @@ const sessionManager = await ClineCore.create({
|
||||
workspaceRoot,
|
||||
cwd: workspaceRoot,
|
||||
clientType: "code-sidecar",
|
||||
displayName: "Code App sidecar",
|
||||
displayName: "Cline Desktop sidecar",
|
||||
},
|
||||
capabilities: {
|
||||
requestToolApproval: async (request) => {
|
||||
|
||||
@@ -80,7 +80,7 @@ describe("Code sidecar runtime capabilities", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("registers Code App capability factory with core", async () => {
|
||||
it("registers the desktop capability factory with core", async () => {
|
||||
const { createSidecarContext, initializeSessionManager } = await import(
|
||||
"./context"
|
||||
);
|
||||
@@ -102,7 +102,7 @@ describe("Code sidecar runtime capabilities", () => {
|
||||
workspaceRoot: "/workspace/project",
|
||||
cwd: "/workspace/project",
|
||||
clientType: "code-sidecar",
|
||||
displayName: "Code App sidecar",
|
||||
displayName: "Cline Desktop sidecar",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
@@ -113,7 +113,7 @@ describe("Code sidecar runtime capabilities", () => {
|
||||
expect.objectContaining({
|
||||
url: "ws://127.0.0.1:25463/hub",
|
||||
clientType: "code-sidecar-observer",
|
||||
displayName: "Code App observer",
|
||||
displayName: "Cline Desktop observer",
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -578,7 +578,7 @@ describe("Code sidecar runtime capabilities", () => {
|
||||
hub: expect.objectContaining({
|
||||
strategy: "require-hub",
|
||||
clientType: "code-sidecar",
|
||||
displayName: "Code App sidecar",
|
||||
displayName: "Cline Desktop sidecar",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -851,7 +851,7 @@ export async function initializeSessionManager(
|
||||
workspaceRoot: ctx.workspaceRoot,
|
||||
cwd: ctx.workspaceRoot,
|
||||
clientType: "code-sidecar",
|
||||
displayName: "Code App sidecar",
|
||||
displayName: "Cline Desktop sidecar",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -899,7 +899,7 @@ export async function ensureSharedHubClient(
|
||||
const client = new NodeHubClient({
|
||||
url,
|
||||
clientType: "code-sidecar-observer",
|
||||
displayName: "Code App observer",
|
||||
displayName: "Cline Desktop observer",
|
||||
workspaceRoot: ctx.workspaceRoot,
|
||||
cwd: ctx.workspaceRoot,
|
||||
});
|
||||
|
||||
@@ -58,7 +58,7 @@ describe("desktop observability", () => {
|
||||
expect(mocks.createClineTelemetryServiceConfig).toHaveBeenCalledWith({
|
||||
metadata: expect.objectContaining({
|
||||
cline_type: "desktop",
|
||||
platform: "Cline Code",
|
||||
platform: "Cline",
|
||||
}),
|
||||
});
|
||||
expect(mocks.createConfiguredTelemetryHandle).toHaveBeenCalledWith(
|
||||
|
||||
@@ -30,7 +30,7 @@ export function createDesktopObservability(): DesktopObservability {
|
||||
metadata: {
|
||||
extension_version: version,
|
||||
cline_type: "desktop",
|
||||
platform: "Cline Code",
|
||||
platform: "Cline",
|
||||
platform_version: process.version,
|
||||
os_type: os.platform(),
|
||||
os_version: os.version(),
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Cline Code uses the microphone to transcribe speech into chat input.</string>
|
||||
<string>Cline uses the microphone to transcribe speech into chat input.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::sync::OnceLock;
|
||||
use tauri::AppHandle;
|
||||
|
||||
const DEV_APP_DIRECTORY: &str = "notification-identity";
|
||||
const DEV_BUNDLE_NAME: &str = "Cline Code.app";
|
||||
const DEV_BUNDLE_NAME: &str = "Cline.app";
|
||||
const LAUNCH_SERVICES_REGISTER: &str = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";
|
||||
|
||||
static CONFIGURATION: OnceLock<Result<(), String>> = OnceLock::new();
|
||||
@@ -200,17 +200,13 @@ mod tests {
|
||||
fs::write(&executable, b"test executable").unwrap();
|
||||
fs::write(&icon, b"test icon").unwrap();
|
||||
|
||||
let bundle = create_dev_application_bundle(
|
||||
&executable,
|
||||
&icon,
|
||||
"bot.cline.app.dev",
|
||||
"Cline Code Dev",
|
||||
)
|
||||
.unwrap();
|
||||
let bundle =
|
||||
create_dev_application_bundle(&executable, &icon, "bot.cline.app.dev", "Cline Dev")
|
||||
.unwrap();
|
||||
let plist = fs::read_to_string(bundle.join("Contents/Info.plist")).unwrap();
|
||||
|
||||
assert!(plist.contains("<string>bot.cline.app.dev</string>"));
|
||||
assert!(plist.contains("<string>Cline Code Dev</string>"));
|
||||
assert!(plist.contains("<string>Cline Dev</string>"));
|
||||
assert_eq!(
|
||||
fs::read_link(bundle.join("Contents/MacOS/cline-app")).unwrap(),
|
||||
executable
|
||||
|
||||
@@ -162,7 +162,7 @@ fn running_sessions_text(running_sessions: u32) -> String {
|
||||
}
|
||||
|
||||
// app_name is package_info().name (the configured productName), so beta
|
||||
// builds ("Cline Code Beta") identify themselves in the tooltip too.
|
||||
// builds ("Cline Beta") identify themselves in the tooltip too.
|
||||
fn tray_tooltip_text(app_name: &str, running_sessions: u32) -> String {
|
||||
if running_sessions == 0 {
|
||||
app_name.to_string()
|
||||
@@ -1036,7 +1036,7 @@ fn setup_tray_icon(app: &tauri::App) -> tauri::Result<()> {
|
||||
.text(
|
||||
TRAY_OPEN_MENU_ID,
|
||||
// package_info().name is the configured productName, so beta
|
||||
// builds ("Cline Code Beta") identify themselves in the tray too.
|
||||
// builds ("Cline Beta") identify themselves in the tray too.
|
||||
format!(
|
||||
"{} v{}",
|
||||
app.package_info().name,
|
||||
@@ -1326,14 +1326,11 @@ mod tests {
|
||||
assert_eq!(running_sessions_text(0), "0 sessions running");
|
||||
assert_eq!(running_sessions_text(1), "1 session running");
|
||||
assert_eq!(running_sessions_text(3), "3 sessions running");
|
||||
assert_eq!(tray_tooltip_text("Cline Code", 0), "Cline Code");
|
||||
assert_eq!(tray_tooltip_text("Cline", 0), "Cline");
|
||||
assert_eq!(tray_tooltip_text("Cline", 3), "Cline — 3 sessions running");
|
||||
assert_eq!(
|
||||
tray_tooltip_text("Cline Code", 3),
|
||||
"Cline Code — 3 sessions running"
|
||||
);
|
||||
assert_eq!(
|
||||
tray_tooltip_text("Cline Code Beta", 2),
|
||||
"Cline Code Beta — 2 sessions running"
|
||||
tray_tooltip_text("Cline Beta", 2),
|
||||
"Cline Beta — 2 sessions running"
|
||||
);
|
||||
assert_eq!(tray_badge_text(0), None);
|
||||
assert_eq!(tray_badge_text(3), Some("3".to_string()));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Cline Code Beta",
|
||||
"productName": "Cline Beta",
|
||||
"identifier": "bot.cline.app.beta",
|
||||
"plugins": {
|
||||
"updater": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Cline Code",
|
||||
"productName": "Cline",
|
||||
"version": "0.0.14",
|
||||
"identifier": "bot.cline.app",
|
||||
"build": {
|
||||
@@ -21,7 +21,7 @@
|
||||
"windows": [
|
||||
{
|
||||
"label": "main",
|
||||
"title": "Cline Code",
|
||||
"title": "Cline",
|
||||
"width": 1500,
|
||||
"height": 980,
|
||||
"resizable": true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Cline Code Dev",
|
||||
"productName": "Cline Dev",
|
||||
"identifier": "bot.cline.app.dev"
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ describe("AgentSidebar session organization", () => {
|
||||
|
||||
const titleBar = container.querySelector("[data-tauri-drag-region]");
|
||||
expect(titleBar).not.toBeNull();
|
||||
expect(titleBar?.textContent).not.toContain("Cline Code");
|
||||
expect(titleBar?.textContent).not.toContain("Cline");
|
||||
|
||||
await click(
|
||||
container.querySelector('[aria-label="Previous page"]') as Element,
|
||||
|
||||
@@ -104,8 +104,8 @@ export function HubUpdateRequiredDialog() {
|
||||
{mismatch?.hubCoreVersion
|
||||
? ` (core ${mismatch.hubCoreVersion})`
|
||||
: ""}
|
||||
, and it no longer matches this app. Update and restart Cline Code
|
||||
to stay in sync with the running Hub.
|
||||
, and it no longer matches this app. Update and restart Cline to
|
||||
stay in sync with the running Hub.
|
||||
</AlertDialogDescription>
|
||||
{updateHint ? (
|
||||
<AlertDialogDescription>{updateHint}</AlertDialogDescription>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
* See apps/examples/desktop-app/EXPERIMENTAL.md for the channel model.
|
||||
*/
|
||||
|
||||
export const STABLE_PRODUCT_NAME = "Cline Code";
|
||||
export const BETA_PRODUCT_NAME = "Cline Code Beta";
|
||||
export const STABLE_PRODUCT_NAME = "Cline";
|
||||
export const BETA_PRODUCT_NAME = "Cline Beta";
|
||||
|
||||
export function isBetaVersion(version: string | null | undefined): boolean {
|
||||
return typeof version === "string" && version.includes("-beta");
|
||||
|
||||
@@ -49,7 +49,7 @@ describe("desktop window title", () => {
|
||||
it("titles beta builds with the beta product name", async () => {
|
||||
const { buildDesktopWindowTitle } = await importFresh();
|
||||
expect(buildDesktopWindowTitle("0.0.14-beta.1")).toBe(
|
||||
"Cline Code Beta v0.0.14-beta.1",
|
||||
"Cline Beta v0.0.14-beta.1",
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -268,8 +268,8 @@ function summarizeClient(client: TrackedClient): {
|
||||
) {
|
||||
return {
|
||||
key: "code-app",
|
||||
label: "Code App",
|
||||
name: "Code App",
|
||||
label: "Cline Desktop",
|
||||
name: "Cline Desktop",
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ flowchart TD
|
||||
shared["@cline/shared"] --> llms["@cline/llms"] & agents["@cline/agents"] & core["@cline/core"]
|
||||
llms --> agents & core
|
||||
agents --> core
|
||||
core --> apps["CLI / VS Code / Code App"]
|
||||
core --> apps["CLI / VS Code / Desktop App"]
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
Reference in New Issue
Block a user