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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 44 additions & 7 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
},
"dependencies": {
"commander": "^13.1.0",
"minimatch": "^10.0.3",
"update-notifier": "^7.3.1"
},
"devDependencies": {
Expand Down
30 changes: 18 additions & 12 deletions src/commands/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import * as fs from 'fs';
import * as path from 'path';
import { spawnSync } from 'child_process';
import { minimatch } from 'minimatch';

// Define environment variable configurations and their corresponding CoDevelopedBy values
// Format: ["key=value", "co-developed-by-string"]
// Use glob patterns for value matching with ** to match any characters including /
const envConfigs: [string, string][] = [
// We can run CLI in IDE (such as Cursor and Qoder), so check CLI env variables first
['CLAUDECODE=1', 'Claude <noreply@anthropic.com>'],
Expand All @@ -19,6 +21,14 @@ const envConfigs: [string, string][] = [
['__CFBundleIdentifier=dev.kiro.desktop', 'Kiro <noreply@kiro.dev>'],
['VSCODE_BRAND=Qoder', 'Qoder <noreply@qoder.com>'],
['__CFBundleIdentifier=com.qoder.ide', 'Qoder <noreply@qoder.com>'], // Use this unstable variable until Qoder has a better one
// Check env variables for IDEs in remove development environments
[
'VSCODE_GIT_ASKPASS_MAIN=**/.cursor-server/**',
'Cursor <noreply@cursor.com>',
],
['BROWSER=**/.cursor-server/**', 'Cursor <noreply@cursor.com>'],
['VSCODE_GIT_ASKPASS_MAIN=**/.qoder-server/**', 'Qoder <noreply@qoder.com>'],
['BROWSER=**/.qoder-server/**', 'Qoder <noreply@qoder.com>'],
];

/**
Expand Down Expand Up @@ -278,30 +288,26 @@ function getCoDevelopedBy(): string {
continue;
}

// First check for exact match
if (
expectedValue !== null &&
expectedValue !== '*' &&
actualValue === expectedValue
) {
return coDevelopedBy;
}

// For wildcard cases (*) or null for expectedValue, only return CoDevelopedBy
// if the value is actually meaningful
if (expectedValue === '*' || expectedValue === null) {
// For null expectedValue (just check key existence)
if (expectedValue === null) {
// Only return CoDevelopedBy if the actual value is truthy (not empty, not '0', not 'false', etc.)
if (
actualValue &&
actualValue !== '0' &&
actualValue !== 'false' &&
actualValue !== 'off' &&
actualValue !== 'no'
) {
return coDevelopedBy;
}
// Continue to next configuration if value is falsy
continue;
}

// Use minimatch for glob pattern matching
if (minimatch(actualValue, expectedValue, { dot: true })) {
return coDevelopedBy;
}
}

// Return empty string if none of the environment configurations match
Expand Down
27 changes: 27 additions & 0 deletions test/commands/exec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,33 @@ describe('exec command utilities', () => {
process.env.CLAUDECODE = '';
expect(getCoDevelopedBy()).toBe('');
});

// Enhanced tests for Cursor and Qoder detection
it('should return Cursor CoDevelopedBy when VSCODE_GIT_ASKPASS_MAIN contains .cursor-server', () => {
clearCoDevelopedByEnvVars();
process.env.VSCODE_GIT_ASKPASS_MAIN =
'/home/user/.cursor-server/bin/askpass-main.js';
expect(getCoDevelopedBy()).toBe('Cursor <noreply@cursor.com>');
});

it('should return Cursor CoDevelopedBy when BROWSER contains .cursor-server', () => {
clearCoDevelopedByEnvVars();
process.env.BROWSER = '/home/user/.cursor-server/bin/helpers/browser.sh';
expect(getCoDevelopedBy()).toBe('Cursor <noreply@cursor.com>');
});

it('should return Qoder CoDevelopedBy when VSCODE_GIT_ASKPASS_MAIN contains .qoder-server', () => {
clearCoDevelopedByEnvVars();
process.env.VSCODE_GIT_ASKPASS_MAIN =
'/home/user/.qoder-server/bin/askpass-main.js';
expect(getCoDevelopedBy()).toBe('Qoder <noreply@qoder.com>');
});

it('should return Qoder CoDevelopedBy when BROWSER contains .qoder-server', () => {
clearCoDevelopedByEnvVars();
process.env.BROWSER = '/home/user/.qoder-server/bin/helpers/browser.sh';
expect(getCoDevelopedBy()).toBe('Qoder <noreply@qoder.com>');
});
});

describe('hasCoDevelopedBy', () => {
Expand Down
Loading