Browse Source

Merge pull request #9 from dacrab/master

Improvements
pull/20/head
煎饼果子卷鲨鱼辣椒 6 months ago
committed by GitHub
parent
commit
394e144a2e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 28
      .gitignore
  2. 400
      README.md
  3. BIN
      app.exe
  4. 11
      app.manifest
  5. BIN
      cursor-id-modifier-linux
  6. BIN
      cursor-id-modifier-macos
  7. 4
      go.mod
  8. 2
      go.sum
  9. 76
      install.sh
  10. 638
      main.go
  11. BIN
      releases/linux/cursor-id-modifier
  12. BIN
      releases/macos/cursor-id-modifier-amd64
  13. BIN
      releases/macos/cursor-id-modifier-arm64
  14. BIN
      releases/v1.0.1/releases/v1.0.1/cursor-id-modifier
  15. BIN
      releases/v1.0.1/releases/v1.0.1/cursor-id-modifier-amd64
  16. BIN
      releases/v1.0.1/releases/v1.0.1/cursor-id-modifier-arm64
  17. BIN
      releases/v1.0.1/releases/v1.0.1/cursor-id-modifier.exe

28
.gitignore

@ -0,0 +1,28 @@
# Binary files
app.exe
cursor-id-modifier-linux
cursor-id-modifier-macos
cursor-id-modifier-*
*.exe
*.dll
*.so
*.dylib
# Build directories
bin/
releases/
scripts/
# IDE
.vscode/
# Go specific
go.sum
# Temporary files
*.tmp
*~
# System files
.DS_Store
Thumbs.db

400
README.md

@ -1,169 +1,285 @@
# Cursor Free Trial Reset Tool
# 🚀 Cursor Free Trial Reset Tool
<div align="center">
[![Release](https://img.shields.io/github/v/release/yuaotian/go-cursor-help?style=for-the-badge&logo=github&color=blue)](https://github.com/yuaotian/go-cursor-help/releases/latest)
[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge&logo=bookstack)](https://github.com/yuaotian/go-cursor-help/blob/main/LICENSE)
[![Stars](https://img.shields.io/github/stars/yuaotian/go-cursor-help?style=for-the-badge&logo=github)](https://github.com/yuaotian/go-cursor-help/stargazers)
[English](#english) | [中文](#chinese)
### Important Notice | 重要声明
---
<img src="https://ai-cursor.com/wp-content/uploads/2024/09/logo-cursor-ai-png.webp" alt="Cursor Logo" width="150"/>
</div>
## ⚠️ Important Notice | 重要声明
<table>
<tr>
<td>
This tool is only intended for the following specific scenarios:
1. During Cursor's official free trial period
2. When system mistakenly flags as duplicate trial due to technical issues
3. As a temporary solution when official support is not readily available
Please note:
- This tool is not meant for bypassing paid features or cracking software
- If your trial period has expired, please purchase a license or seek alternatives
- It's recommended to contact official support first
- Please ensure you are within valid trial period before using this tool
本工具仅用于解决以下特定场景:
1. 在Cursor官方承诺的免费试用期内
2. 由于技术原因导致系统误判为重复试用
3. 无法通过正常渠道及时获得官方支持时的临时解决方案
请注意:
- 本工具不是用于规避付费或破解软件
- 如果您已超出试用期,请购买正版授权或寻找其他替代方案
- 建议优先通过官方支持渠道解决问题
- 使用本工具前请确认您处于有效的试用期内
- 🕒 During Cursor's official free trial period
- 🔄 When system mistakenly flags as duplicate trial
- 🆘 As a temporary solution when official support is unavailable
**Please note:**
- 🚫 Not for bypassing paid features
- 💳 Purchase a license if trial expired
- 📞 Contact official support first
- ✅ Ensure valid trial period before use
</td>
</tr>
</table>
<a name="english"></a>
## English
## 🌟 English
### Description
### 📝 Description
A tool to resolve the following prompt issue during Cursor's free trial period:
<table>
<tr>
<td>
<pre>
Too many free trial accounts used on this machine.
Please upgrade to pro. We have this limit in place
to prevent abuse. Please let us know if you believe
this is a mistake.
</pre>
</td>
</tr>
</table>
### ✨ Features
- 🔄 Reset Cursor free trial limitations
- 🔍 Automatic detection and closing of running instances
- 🌐 Cross-platform support with architecture detection
- 📦 Automated installation scripts
- 🖥️ Both GUI and command-line interfaces
### 💻 System Support
| Platform | Status |
|----------|---------|
| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=flat&logo=windows&logoColor=white) | ✅ x64 |
| ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white) | ✅ Intel/Apple Silicon |
| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat&logo=linux&logoColor=black) | ✅ x64/ARM64 |
### 📥 Installation Methods
<details open>
<summary><b>1️⃣ Automated Installation (Recommended)</b></summary>
#### Linux/macOS
```bash
curl -fsSL https://raw.githubusercontent.com/yuaotian/go-cursor-help/main/install.sh | sudo bash
```
Too many free trial accounts used on this machine. Please upgrade to pro. We have this limit in place to prevent abuse. Please let us know if you believe this is a mistake.
#### Windows PowerShell
```powershell
# Download and run with admin privileges
$url = "https://github.com/yuaotian/go-cursor-help/releases/latest/download/cursor-id-modifier.exe"
$output = "$env:TEMP\cursor-id-modifier.exe"
Invoke-WebRequest -Uri $url -OutFile $output
Start-Process -FilePath $output -Verb RunAs
```
</details>
### Features
- Reset Cursor free trial limitations
- Provides both automatic and manual reset methods
- Support multiple platforms
### System Support
- ✅ Windows (Tested)
- ✅ MacOS (Tested)
- ✅ Linux (Tested)
### Automatic Reset
#### Prerequisites
- Requires administrator/root privileges
- Ensure Cursor is completely closed before use
#### Usage
1. Download the appropriate executable for your system:
- Windows: `cursor_id_modifier.exe`
- MacOS: `cursor_id_modifier_mac` or `cursor_id_modifier_mac_arm64`
- Linux: `cursor_id_modifier_linux`
2. Run the program as administrator
3. Follow the prompts
4. Restart Cursor to apply changes
### Manual Reset
1. Close Cursor completely
2. Locate the storage.json file:
- Windows: `%APPDATA%\Roaming\Cursor\User\globalStorage\storage.json`
- MacOS: `~/Library/Application Support/Cursor/User/globalStorage/storage.json`
- Linux: `~/.config/Cursor/User/globalStorage/storage.json`
3. Make the file writable (if needed):
- Windows: Right click -> Properties -> Uncheck "Read-only"
- MacOS/Linux: `chmod 666 storage.json`
4. Edit the file and replace these fields with new random values:
```json
{
"telemetry.macMachineId": "generate-64-char-hex",
"telemetry.machineId": "generate-64-char-hex",
"telemetry.devDeviceId": "generate-uuid-format"
}
```
- For hex values: Use 64 characters (0-9, a-f)
- For UUID: Use format like "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
5. Make the file read-only:
- Windows: Right click -> Properties -> Check "Read-only"
- MacOS/Linux: `chmod 444 storage.json`
6. Restart Cursor
<details>
<summary><b>2️⃣ Manual Download</b></summary>
### ⚠️ Cautions
1. Use this tool at your own risk
2. Backup important data before use
3. For educational and research purposes only
Download from [Releases](https://github.com/yuaotian/go-cursor-help/releases/latest):
| Platform | Architecture | File |
|----------|-------------|------|
| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=flat&logo=windows&logoColor=white) | x64 | `cursor-id-modifier.exe` |
| ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white) | Intel (x64) | `cursor-id-modifier-amd64` |
| ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white) | Apple Silicon | `cursor-id-modifier-arm64` |
| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat&logo=linux&logoColor=black) | x64 | `cursor-id-modifier` |
| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat&logo=linux&logoColor=black) | ARM64 | `cursor-id-modifier-arm64` |
</details>
### 📚 Usage Instructions
<details>
<summary>Prerequisites</summary>
- 👑 Administrator/root privileges required
- 🚫 Cursor should be completely closed
- 🌐 Internet connection for installation
</details>
<details>
<summary>Running the Tool</summary>
The tool will automatically:
1. 🔑 Check for and request admin privileges
2. 🔍 Detect and close Cursor instances
3. 💾 Backup existing configuration
4. 🔄 Generate new identifiers
5. ✅ Apply changes
Restart Cursor after completion.
</details>
### 🔧 Troubleshooting
<details>
<summary>Common Issues</summary>
#### 🚫 Permission Denied
- Windows: Right-click → "Run as Administrator"
- Linux/macOS: Use \`sudo\` when running
### Disclaimer
This tool is for educational purposes only. Users bear all risks and responsibilities associated with its use.
#### ⚠️ Cursor Still Running
- Tool will attempt auto-close
- Manual close via Task Manager if needed
### Contributing
Issues and Pull Requests are welcome to help improve this project.
#### 🔒 macOS Security
If you see "unidentified developer" warning:
1. Right-click → Open
2. Click "Open" in dialog
</details>
### ⚠️ Cautions
- 🛡️ Use at your own risk
- 💾 Backup important data
- 📚 Educational purposes only
### 🤝 Contributing
We welcome contributions! Please ensure:
- ✅ Cross-platform compatibility
- 🚫 No breaking changes
- 🔍 Proper error handling
- 📝 Documentation updates
---
<a name="chinese"></a>
## 中文
## 🌏 中文
### 问题描述
### 📝 问题描述
解决Cursor在免费订阅期间出现以下提示的问题:
<table>
<tr>
<td>
<pre>
Too many free trial accounts used on this machine.
Please upgrade to pro. We have this limit in place
to prevent abuse. Please let us know if you believe
this is a mistake.
</pre>
</td>
</tr>
</table>
### ✨ 功能特性
- 🔄 重置Cursor免费试用限制
- 🔍 自动检测和关闭运行中的实例
- 🌐 跨平台支持,自动检测系统架构
- 📦 自动化安装脚本
- 🖥️ 支持图形界面和命令行
### 💻 系统支持
| 平台 | 状态 |
|----------|---------|
| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=flat&logo=windows&logoColor=white) | ✅ x64 |
| ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white) | ✅ Intel/Apple Silicon |
| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat&logo=linux&logoColor=black) | ✅ x64/ARM64 |
### 📥 安装方法
<details open>
<summary><b>1️⃣ 自动安装(推荐)</b></summary>
#### Linux/macOS
```bash
curl -fsSL https://raw.githubusercontent.com/yuaotian/go-cursor-help/main/install.sh | sudo bash
```
Too many free trial accounts used on this machine. Please upgrade to pro. We have this limit in place to prevent abuse. Please let us know if you believe this is a mistake.
#### Windows PowerShell
```powershell
# 下载并以管理员权限运行
$url = "https://github.com/yuaotian/go-cursor-help/releases/latest/download/cursor-id-modifier.exe"
$output = "$env:TEMP\cursor-id-modifier.exe"
Invoke-WebRequest -Uri $url -OutFile $output
Start-Process -FilePath $output -Verb RunAs
```
</details>
### 功能特性
- 重置Cursor免费试用限制
- 提供自动和手动重置方法
- 支持多个操作系统平台
### 系统支持
- ✅ Windows (已测试)
- ✅ MacOS (已测试)
- ✅ Linux (已测试)
### 自动重置
#### 使用前提
- 需要管理员/root权限执行
- 请确保已完全退出Cursor程序
#### 使用方法
1. 下载对应系统的可执行文件:
- Windows系统:`cursor_id_modifier.exe`
- MacOS系统:`cursor_id_modifier_mac` 或 `cursor_id_modifier_mac_arm64`
- Linux系统:`cursor_id_modifier_linux`
2. 以管理员身份运行程序
3. 按照提示进行操作
4. 重启Cursor即可
### 手动重置
1. 完全关闭Cursor
2. 找到storage.json文件:
- Windows: `%APPDATA%\Roaming\Cursor\User\globalStorage\storage.json`
- MacOS: `~/Library/Application Support/Cursor/User/globalStorage/storage.json`
- Linux: `~/.config/Cursor/User/globalStorage/storage.json`
3. 修改文件为可写(如果需要):
- Windows: 右键 -> 属性 -> 取消勾选"只读"
- MacOS/Linux: `chmod 666 storage.json`
4. 编辑文件,替换以下字段为新的随机值:
```json
{
"telemetry.macMachineId": "生成64位十六进制",
"telemetry.machineId": "生成64位十六进制",
"telemetry.devDeviceId": "生成UUID格式"
}
```
- 十六进制值:使用64个字符(0-9, a-f)
- UUID格式:类似 "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
5. 将文件设为只读:
- Windows: 右键 -> 属性 -> 勾选"只读"
- MacOS/Linux: `chmod 444 storage.json`
6. 重启Cursor
<details>
<summary><b>2️⃣ 手动下载</b></summary>
### ⚠️ 注意事项
1. 使用本工具需要您自行承担风险
2. 建议在重要数据做好备份后使用
3. 本工具仅用于学习研究,请勿用于商业用途
从[发布页面](https://github.com/yuaotian/go-cursor-help/releases/latest)下载:
| 平台 | 架构 | 文件 |
|----------|-------------|------|
| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=flat&logo=windows&logoColor=white) | x64 | `cursor-id-modifier.exe` |
| ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white) | Intel (x64) | `cursor-id-modifier-amd64` |
| ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white) | Apple Silicon | `cursor-id-modifier-arm64` |
| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat&logo=linux&logoColor=black) | x64 | `cursor-id-modifier` |
| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat&logo=linux&logoColor=black) | ARM64 | `cursor-id-modifier-arm64` |
</details>
### 📚 使用说明
<details>
<summary>使用前提</summary>
- 👑 需要管理员/root权限
- 🚫 确保Cursor完全关闭
- 🌐 需要网络连接进行安装
</details>
<details>
<summary>运行工具</summary>
工具将自动执行:
1. 🔑 检查并请求管理员权限
2. 🔍 检测并关闭Cursor进程
3. 💾 备份现有配置
4. 🔄 生成新的标识符
5. ✅ 应用更改
### 免责声明
本工具仅供学习交流使用,使用本工具所造成的任何问题由使用者自行承担。
完成后重启Cursor即可。
</details>
### 贡献
欢迎提交Issue和Pull Request来帮助改进这个项目。
### 🔧 故障排除
## License
<details>
<summary>常见问题</summary>
#### 🚫 权限被拒绝
- Windows:右键 → "以管理员身份运行"
- Linux/macOS:使用 \`sudo\` 运行
#### ⚠️ Cursor仍在运行
- 工具会尝试自动关闭
- 如需要请通过任务管理器手动关闭
#### 🔒 macOS安全性问题
如果看到"未识别的开发者"提示:
1. 右键点击 → 打开
2. 点击确认对话框中的"打开"
</details>
### ⚠️ 注意事项
- 🛡️ 使用本工具需自行承担风险
- 💾 使用前请备份重要数据
- 📚 仅用于学习研究目的
### 🤝 贡献
欢迎提交问题和改进建议!请确保:
- ✅ 保持跨平台兼容性
- 🚫 避免破坏性更改
- 🔍 完善的错误处理
- 📝 更新相关文档
## 📄 License
MIT License
Copyright (c) 2024
@ -177,9 +293,3 @@ furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

BIN
app.exe

11
app.manifest

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="app" type="win32"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

BIN
cursor-id-modifier-linux

BIN
cursor-id-modifier-macos

4
go.mod

@ -1,4 +1,4 @@
module go-cursor-help
module github.com/yuaotian/go-cursor-help
go 1.22.0
@ -7,5 +7,5 @@ require github.com/fatih/color v1.18.0
require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/sys v0.28.0
)

2
go.sum

@ -9,3 +9,5 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

76
install.sh

@ -0,0 +1,76 @@
#!/bin/bash
# Error handling function / 错误处理函数
error() {
echo "Error/错误: $1" >&2
exit 1
}
# Detect OS and architecture / 检测操作系统和架构
detect_platform() {
# Get lowercase OS name and architecture / 获取小写操作系统名称和架构
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
# Set binary name based on platform / 根据平台设置二进制文件名
case "$OS" in
linux*)
case "$ARCH" in
x86_64) BINARY_NAME="cursor-id-modifier" ;;
aarch64) BINARY_NAME="cursor-id-modifier-arm64" ;;
*) error "Unsupported Linux architecture/不支持的Linux架构: $ARCH" ;;
esac
;;
darwin*)
case "$ARCH" in
x86_64) BINARY_NAME="cursor-id-modifier-amd64" ;;
arm64) BINARY_NAME="cursor-id-modifier-arm64" ;;
*) error "Unsupported macOS architecture/不支持的macOS架构: $ARCH" ;;
esac
;;
*)
error "Unsupported operating system/不支持的操作系统: $OS"
;;
esac
}
# Check root privileges / 检查root权限
if [ "$(id -u)" -ne 0 ]; then
error "This script must be run with sudo or as root/此脚本必须使用sudo或root权限运行"
fi
# Initialize installation / 初始化安装
detect_platform
INSTALL_DIR="/usr/local/bin"
[ -d "$INSTALL_DIR" ] || mkdir -p "$INSTALL_DIR"
# Download binary / 下载二进制文件
echo "Downloading cursor-id-modifier for/正在下载 $OS ($ARCH)..."
TEMP_DIR=$(mktemp -d)
DOWNLOAD_URL="https://github.com/yuaotian/go-cursor-help/releases/latest/download/$BINARY_NAME"
if ! curl -fsSL "$DOWNLOAD_URL" -o "$TEMP_DIR/$BINARY_NAME"; then
error "Failed to download binary/下载二进制文件失败"
fi
# Set permissions / 设置权限
if ! chmod +x "$TEMP_DIR/$BINARY_NAME"; then
error "Failed to make binary executable/无法设置可执行权限"
fi
# Handle macOS security / 处理macOS安全设置
if [ "$OS" = "darwin" ]; then
echo "Removing macOS quarantine attribute/移除macOS隔离属性..."
xattr -d com.apple.quarantine "$TEMP_DIR/$BINARY_NAME" 2>/dev/null || true
fi
# Install binary / 安装二进制文件
if ! mv "$TEMP_DIR/$BINARY_NAME" "$INSTALL_DIR/cursor-id-modifier"; then
error "Failed to install binary/安装二进制文件失败"
fi
# Cleanup / 清理
rm -rf "$TEMP_DIR"
echo "✅ Installation successful! You can now run 'cursor-id-modifier' from anywhere."
echo "✅ 安装成功!现在可以在任何位置运行 'cursor-id-modifier'。"

638
main.go

@ -1,5 +1,7 @@
// 主程序包 / Main package
package main
// 导入所需的包 / Import required packages
import (
"bufio"
"crypto/rand"
@ -13,12 +15,39 @@ import (
"path/filepath"
"runtime"
"strings"
"syscall"
"time"
"github.com/fatih/color"
"golang.org/x/sys/windows"
)
// StorageConfig 存储配置结构体优化
// 语言类型和常量 / Language type and constants
type Language string
const (
CN Language = "cn"
EN Language = "en"
// Version constant
Version = "1.0.1"
)
// TextResource 存储多语言文本 / TextResource stores multilingual text
type TextResource struct {
SuccessMessage string
RestartMessage string
ReadingConfig string
GeneratingIds string
PressEnterToExit string
ErrorPrefix string
PrivilegeError string
RunAsAdmin string
RunWithSudo string
SudoExample string
}
// StorageConfig 优化的存储配置结构 / StorageConfig optimized storage configuration struct
type StorageConfig struct {
TelemetryMacMachineId string `json:"telemetry.macMachineId"`
TelemetryMachineId string `json:"telemetry.machineId"`
@ -27,47 +56,91 @@ type StorageConfig struct {
Version string `json:"version"`
}
// NewStorageConfig 创建新的配置实例
// AppError 定义错误类型 / AppError defines error types
type AppError struct {
Op string
Path string
Err error
}
// ProgressSpinner 用于显示进度动画 / ProgressSpinner for showing progress animation
type ProgressSpinner struct {
frames []string
current int
message string
}
// 全局变量 / Global variables
var (
currentLanguage = CN // 默认为中文 / Default to Chinese
texts = map[Language]TextResource{
CN: {
SuccessMessage: "[√] 配置文件已成功更新!",
RestartMessage: "[!] 请手动重启 Cursor 以使更新生效",
ReadingConfig: "正在读取配置文件...",
GeneratingIds: "正在生成新的标识符...",
PressEnterToExit: "按回车键退出程序...",
ErrorPrefix: "程序发生严重错误: %v",
PrivilegeError: "\n[!] 错误:需要管理员权限",
RunAsAdmin: "请右键点击程序,选择「以管理员身份运行」",
RunWithSudo: "请使用 sudo 命令运行此程序",
SudoExample: "示例: sudo %s",
},
EN: {
SuccessMessage: "[√] Configuration file updated successfully!",
RestartMessage: "[!] Please restart Cursor manually for changes to take effect",
ReadingConfig: "Reading configuration file...",
GeneratingIds: "Generating new identifiers...",
PressEnterToExit: "Press Enter to exit...",
ErrorPrefix: "Program encountered a serious error: %v",
PrivilegeError: "\n[!] Error: Administrator privileges required",
RunAsAdmin: "Please right-click and select 'Run as Administrator'",
RunWithSudo: "Please run this program with sudo",
SudoExample: "Example: sudo %s",
},
}
)
// Error implementation for AppError
func (e *AppError) Error() string {
if e.Path != "" {
return fmt.Sprintf("%s: %v [Path: %s]", e.Op, e.Err, e.Path)
}
return fmt.Sprintf("%s: %v", e.Op, e.Err)
}
// NewStorageConfig 创建新的配置实例 / Creates a new configuration instance
func NewStorageConfig() *StorageConfig {
return &StorageConfig{
TelemetryMacMachineId: generateMacMachineId(),
TelemetryMacMachineId: generateMachineId(),
TelemetryMachineId: generateMachineId(),
TelemetryDevDeviceId: generateDevDeviceId(),
LastModified: time.Now(),
Version: "1.0.1",
Version: Version,
}
}
// 生成类似原始machineId的字符串 (64位小写hex)
// 生成类似原始machineId的字符串(64位小写十六进制) / Generate a string similar to the original machineId (64-bit lowercase hex)
func generateMachineId() string {
// 生成一些随机数据
data := make([]byte, 32)
rand.Read(data)
// 使用SHA256生成hash
hash := sha256.New()
hash.Write(data)
// 转换为小写的hex字符串
return hex.EncodeToString(hash.Sum(nil))
}
// 生成类似原始macMachineId的字符串 (64位小写hex)
func generateMacMachineId() string {
return generateMachineId() // 使用相同的格式
if _, err := rand.Read(data); err != nil {
panic(fmt.Errorf("failed to generate random data: %v", err))
}
hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:])
}
// 生成类似原始devDeviceId的字符 (标准UUID格式)
// 生成类似原始devDeviceId的字符串(标准UUID格式) / Generate a string similar to the original devDeviceId (standard UUID format)
func generateDevDeviceId() string {
// 生成 UUID v4
uuid := make([]byte, 16)
rand.Read(uuid)
if _, err := rand.Read(uuid); err != nil {
panic(fmt.Errorf("failed to generate UUID: %v", err))
}
// 设置版本 (4) 和变体位
uuid[6] = (uuid[6] & 0x0f) | 0x40 // 版本 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 变体
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
// 格式化为标准 UUID 字符串
return fmt.Sprintf("%x-%x-%x-%x-%x",
uuid[0:4],
uuid[4:6],
@ -76,19 +149,39 @@ func generateDevDeviceId() string {
uuid[10:16])
}
// 获取配置文件路径
// NewProgressSpinner creates a new progress spinner
func NewProgressSpinner(message string) *ProgressSpinner {
return &ProgressSpinner{
frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
message: message,
}
}
// Spin advances the spinner animation
func (s *ProgressSpinner) Spin() {
frame := s.frames[s.current%len(s.frames)]
s.current++
fmt.Printf("\r%s %s", color.CyanString(frame), s.message)
}
// Stop ends the spinner animation
func (s *ProgressSpinner) Stop() {
fmt.Println()
}
// File and system operations
func getConfigPath() (string, error) {
var configDir string
switch runtime.GOOS {
case "windows":
configDir = filepath.Join(os.Getenv("APPDATA"), "Cursor", "User", "globalStorage")
case "darwin":
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
configDir = filepath.Join(homeDir, "Library", "Application Support", "Cursor", "User", "globalStorage")
case "windows":
appData := os.Getenv("APPDATA")
configDir = filepath.Join(appData, "Cursor", "User", "globalStorage")
case "linux":
homeDir, err := os.UserHomeDir()
if err != nil {
@ -96,22 +189,87 @@ func getConfigPath() (string, error) {
}
configDir = filepath.Join(homeDir, ".config", "Cursor", "User", "globalStorage")
default:
return "", fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
return "", fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
return filepath.Join(configDir, "storage.json"), nil
}
// 修改件权限
func safeWriteFile(path string, data []byte, perm os.FileMode) error {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0755); err != nil {
return &AppError{"create directory", dir, err}
}
tmpPath := path + ".tmp"
if err := os.WriteFile(tmpPath, data, perm); err != nil {
return &AppError{"write temporary file", tmpPath, err}
}
if err := os.Rename(tmpPath, path); err != nil {
os.Remove(tmpPath)
return &AppError{"rename file", path, err}
}
return nil
}
func setFilePermissions(filePath string) error {
if runtime.GOOS == "windows" {
// Windows 使用 ACL 权限系统,这里仅设置为只读
return os.Chmod(filePath, 0444)
}
// Process management functions
func killCursorProcesses() error {
if runtime.GOOS == "windows" {
// First try graceful shutdown
exec.Command("taskkill", "/IM", "Cursor.exe").Run()
exec.Command("taskkill", "/IM", "cursor.exe").Run()
time.Sleep(time.Second)
// Force kill any remaining instances
exec.Command("taskkill", "/F", "/IM", "Cursor.exe").Run()
exec.Command("taskkill", "/F", "/IM", "cursor.exe").Run()
} else {
// Linux 和 macOS
return os.Chmod(filePath, 0444)
exec.Command("pkill", "-f", "Cursor").Run()
exec.Command("pkill", "-f", "cursor").Run()
}
return nil
}
func checkCursorRunning() bool {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("tasklist", "/FI", "IMAGENAME eq Cursor.exe", "/NH")
} else {
cmd = exec.Command("pgrep", "-f", "Cursor")
}
output, _ := cmd.Output()
return strings.Contains(string(output), "Cursor") || strings.Contains(string(output), "cursor")
}
// UI and display functions
func clearScreen() {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("cmd", "/c", "cls")
} else {
cmd = exec.Command("clear")
}
cmd.Stdout = os.Stdout
cmd.Run()
}
func showProgress(message string) {
spinner := NewProgressSpinner(message)
for i := 0; i < 15; i++ {
spinner.Spin()
time.Sleep(100 * time.Millisecond)
}
spinner.Stop()
}
func printCyberpunkBanner() {
cyan := color.New(color.FgCyan, color.Bold)
@ -123,7 +281,7 @@ func printCyberpunkBanner() {
`
@ -131,7 +289,6 @@ func printCyberpunkBanner() {
yellow.Println("\t\t>> Cursor ID Modifier v1.0 <<")
magenta.Println("\t\t [ By Pancake Fruit Rolled Shark Chili ]")
// 添加语言标识
langText := "当前语言/Language: "
if currentLanguage == CN {
langText += "简体中文"
@ -141,352 +298,265 @@ func printCyberpunkBanner() {
green.Printf("\n\t\t %s\n\n", langText)
}
type ProgressSpinner struct {
frames []string
current int
message string
}
func NewProgressSpinner(message string) *ProgressSpinner {
return &ProgressSpinner{
frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
message: message,
}
}
func (s *ProgressSpinner) Spin() {
frame := s.frames[s.current%len(s.frames)]
s.current++
fmt.Printf("\r%s %s", color.CyanString(frame), s.message)
}
func (s *ProgressSpinner) Stop() {
fmt.Println()
}
// 定义错误类型
type AppError struct {
Op string
Path string
Err error
}
func showSuccess() {
text := texts[currentLanguage]
successColor := color.New(color.FgGreen, color.Bold)
warningColor := color.New(color.FgYellow, color.Bold)
func (e *AppError) Error() string {
if e.Path != "" {
return fmt.Sprintf("%s: %v [路径: %s]", e.Op, e.Err, e.Path)
}
return fmt.Sprintf("%s: %v", e.Op, e.Err)
successColor.Printf("\n%s\n", text.SuccessMessage)
warningColor.Printf("%s\n", text.RestartMessage)
}
// 文件操作包装函数
func safeWriteFile(path string, data []byte, perm os.FileMode) error {
// 创建临时文件
tmpPath := path + ".tmp"
if err := os.WriteFile(tmpPath, data, perm); err != nil {
return &AppError{"写入临时文件", tmpPath, err}
}
func showPrivilegeError() {
text := texts[currentLanguage]
red := color.New(color.FgRed, color.Bold)
yellow := color.New(color.FgYellow)
// 重命名临时文件
if err := os.Rename(tmpPath, path); err != nil {
os.Remove(tmpPath) // 清理临时文件
return &AppError{"重命名文件", path, err}
red.Println(text.PrivilegeError)
if runtime.GOOS == "windows" {
yellow.Println(text.RunAsAdmin)
} else {
yellow.Println(text.RunWithSudo)
yellow.Printf(text.SudoExample, os.Args[0])
}
return nil
}
func showIdComparison(oldConfig *StorageConfig, newConfig *StorageConfig) {
cyan := color.New(color.FgCyan)
yellow := color.New(color.FgYellow)
fmt.Println("\n=== ID Modification Comparison / ID 修改对比 ===")
// clearScreen 清除终端屏幕
func clearScreen() {
if runtime.GOOS == "windows" {
cmd := exec.Command("cmd", "/c", "cls")
cmd.Stdout = os.Stdout
cmd.Run()
} else {
cmd := exec.Command("clear")
cmd.Stdout = os.Stdout
cmd.Run()
if oldConfig != nil {
cyan.Println("\n[Original IDs / 原始 ID]")
yellow.Printf("Machine ID: %s\n", oldConfig.TelemetryMachineId)
yellow.Printf("Mac Machine ID: %s\n", oldConfig.TelemetryMacMachineId)
yellow.Printf("Dev Device ID: %s\n", oldConfig.TelemetryDevDeviceId)
}
}
// showProgress 显示进度
func showProgress(message string) {
spinner := NewProgressSpinner(message)
for i := 0; i < 15; i++ {
spinner.Spin()
time.Sleep(100 * time.Millisecond)
}
spinner.Stop()
cyan.Println("\n[Newly Generated IDs / 新生成 ID]")
yellow.Printf("Machine ID: %s\n", newConfig.TelemetryMachineId)
yellow.Printf("Mac Machine ID: %s\n", newConfig.TelemetryMacMachineId)
yellow.Printf("Dev Device ID: %s\n", newConfig.TelemetryDevDeviceId)
fmt.Println()
}
// saveConfig 保存配置到文件
// Configuration operations
func saveConfig(config *StorageConfig) error {
configPath, err := getConfigPath()
if err != nil {
return err
}
// 转换为JSON
content, err := json.MarshalIndent(config, "", " ")
if err != nil {
return &AppError{"生成JSON", "", err}
return &AppError{"generate JSON", "", err}
}
// 确保文件可写
err = os.Chmod(configPath, 0666)
if err != nil {
return &AppError{"修改文件权限", configPath, err}
if err := os.Chmod(configPath, 0666); err != nil && !os.IsNotExist(err) {
return &AppError{"modify file permissions", configPath, err}
}
// 安全写入文件
if err := safeWriteFile(configPath, content, 0666); err != nil {
return err
}
// 设置为只读
return setFilePermissions(configPath)
}
// showSuccess 显示成功信息
func showSuccess() {
text := texts[currentLanguage]
successColor := color.New(color.FgGreen, color.Bold)
warningColor := color.New(color.FgYellow, color.Bold)
successColor.Printf("\n%s\n", text.SuccessMessage)
warningColor.Printf("%s\n", text.RestartMessage)
}
// 修改 loadAndUpdateConfig 函数使用 configPath
func loadAndUpdateConfig() (*StorageConfig, error) {
func readExistingConfig() (*StorageConfig, error) {
configPath, err := getConfigPath()
if err != nil {
return nil, err
}
text := texts[currentLanguage]
showProgress(text.ReadingConfig)
// 读取原始文件内容
_, err = os.ReadFile(configPath)
if err != nil && !os.IsNotExist(err) {
return nil, &AppError{"读取配置文件", configPath, err}
}
showProgress(text.GeneratingIds)
config := NewStorageConfig()
return config, nil
}
// 修改 waitExit 函数,正确初始化 reader
func waitExit() {
reader := bufio.NewReader(os.Stdin)
color.Cyan("\n" + texts[currentLanguage].PressEnterToExit)
reader.ReadString('\n')
}
func main() {
currentLanguage = detectLanguage()
defer func() {
if err := recover(); err != nil {
color.Red(texts[currentLanguage].ErrorPrefix, err)
waitExit()
}
}()
// 添加权限检查
isAdmin, err := checkAdminPrivileges()
data, err := os.ReadFile(configPath)
if err != nil {
handleError("权限检查失败", err)
waitExit()
return
if os.IsNotExist(err) {
return nil, nil
}
if !isAdmin {
showPrivilegeError()
waitExit()
return
return nil, err
}
setupProgram()
oldConfig, err := readExistingConfig()
if err != nil {
oldConfig = nil
var config StorageConfig
if err := json.Unmarshal(data, &config); err != nil {
return nil, err
}
config, err := loadAndUpdateConfig()
return &config, nil
}
func loadAndUpdateConfig() (*StorageConfig, error) {
configPath, err := getConfigPath()
if err != nil {
handleError("配置更新失败", err)
return
return nil, err
}
showIdComparison(oldConfig, config)
text := texts[currentLanguage]
showProgress(text.ReadingConfig)
if err := saveConfig(config); err != nil {
handleError("保存配置失败", err)
return
_, err = os.ReadFile(configPath)
if err != nil && !os.IsNotExist(err) {
return nil, &AppError{"read config file", configPath, err}
}
showSuccess()
waitExit()
}
func setupProgram() {
clearScreen()
printCyberpunkBanner()
showProgress(text.GeneratingIds)
return NewStorageConfig(), nil
}
func handleError(msg string, err error) {
if appErr, ok := err.(*AppError); ok {
color.Red("%s: %v", msg, appErr)
} else {
color.Red("%s: %v", msg, err)
}
}
// System privilege functions
func checkAdminPrivileges() (bool, error) {
switch runtime.GOOS {
case "windows":
// Windows 管理员权限检查
cmd := exec.Command("net", "session")
err := cmd.Run()
return err == nil, nil
case "darwin", "linux":
// Unix 系统检查 root 权限
currentUser, err := user.Current()
if err != nil {
return false, fmt.Errorf("获取当前用户失败: %v", err)
return false, fmt.Errorf("failed to get current user: %v", err)
}
return currentUser.Uid == "0", nil
default:
return false, fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
return false, fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
}
func showPrivilegeError() {
text := texts[currentLanguage]
red := color.New(color.FgRed, color.Bold)
yellow := color.New(color.FgYellow)
func selfElevate() error {
verb := "runas"
exe, err := os.Executable()
if err != nil {
return err
}
red.Println(text.PrivilegeError)
if runtime.GOOS == "windows" {
yellow.Println(text.RunAsAdmin)
} else {
yellow.Println(text.RunWithSudo)
yellow.Printf(text.SudoExample, os.Args[0])
cwd, err := os.Getwd()
if err != nil {
return err
}
}
// 在文件开头添加新的类型和变量定义
type Language string
verbPtr, _ := syscall.UTF16PtrFromString(verb)
exePtr, _ := syscall.UTF16PtrFromString(exe)
cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
argPtr, _ := syscall.UTF16PtrFromString("")
const (
CN Language = "cn"
EN Language = "en"
)
var showCmd int32 = 1 //SW_NORMAL
// TextResource 存储多语言文本
type TextResource struct {
SuccessMessage string
RestartMessage string
ReadingConfig string
GeneratingIds string
PressEnterToExit string
ErrorPrefix string
PrivilegeError string
RunAsAdmin string
RunWithSudo string
SudoExample string
err = windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd)
if err != nil {
return err
}
os.Exit(0)
return nil
}
var (
currentLanguage = CN // 默认使用中文
// Utility functions
texts = map[Language]TextResource{
CN: {
SuccessMessage: "[√] 配置文件已成功更新!",
RestartMessage: "[!] 请手动重启 Cursor 以使更改生效",
ReadingConfig: "正在读取配置文件...",
GeneratingIds: "正在生成新的标识符...",
PressEnterToExit: "按回车键退出程序...",
ErrorPrefix: "程序发生严重错误: %v",
PrivilegeError: "\n[!] 错误:需要管理员权限",
RunAsAdmin: "请右键点击程序,选择「以管理员身份运行」",
RunWithSudo: "请使用 sudo 命令运行此程序",
SudoExample: "示例: sudo %s",
},
EN: {
SuccessMessage: "[√] Configuration file updated successfully!",
RestartMessage: "[!] Please restart Cursor manually for changes to take effect",
ReadingConfig: "Reading configuration file...",
GeneratingIds: "Generating new identifiers...",
PressEnterToExit: "Press Enter to exit...",
ErrorPrefix: "Program encountered a serious error: %v",
PrivilegeError: "\n[!] Error: Administrator privileges required",
RunAsAdmin: "Please right-click and select 'Run as Administrator'",
RunWithSudo: "Please run this program with sudo",
SudoExample: "Example: sudo %s",
},
}
)
// 添加语言检测函数
func detectLanguage() Language {
// 获取系统语言环境
lang := os.Getenv("LANG")
if lang == "" {
lang = os.Getenv("LANGUAGE")
}
// 如果包含 zh 则使用中文,否则使用英文
if strings.Contains(strings.ToLower(lang), "zh") {
return CN
}
return EN
}
// 添加新函数用于显示ID对比
func showIdComparison(oldConfig *StorageConfig, newConfig *StorageConfig) {
cyan := color.New(color.FgCyan)
yellow := color.New(color.FgYellow)
func waitExit() {
fmt.Println("\nPress Enter to exit... / 按回车键退出程序...")
os.Stdout.Sync()
bufio.NewReader(os.Stdin).ReadString('\n')
}
fmt.Println("\n=== ID 修改对比 ===")
func handleError(msg string, err error) {
if appErr, ok := err.(*AppError); ok {
color.Red("%s: %v", msg, appErr)
} else {
color.Red("%s: %v", msg, err)
}
}
if oldConfig != nil {
cyan.Println("\n[原始 ID]")
yellow.Printf("Machine ID: %s\n", oldConfig.TelemetryMachineId)
yellow.Printf("Mac Machine ID: %s\n", oldConfig.TelemetryMacMachineId)
yellow.Printf("Dev Device ID: %s\n", oldConfig.TelemetryDevDeviceId)
// Main program entry
func main() {
defer func() {
if r := recover(); r != nil {
color.Red(texts[currentLanguage].ErrorPrefix, r)
fmt.Println("\nAn error occurred! / 发生错误!")
waitExit()
}
}()
cyan.Println("\n[新生成 ID]")
yellow.Printf("Machine ID: %s\n", newConfig.TelemetryMachineId)
yellow.Printf("Mac Machine ID: %s\n", newConfig.TelemetryMacMachineId)
yellow.Printf("Dev Device ID: %s\n", newConfig.TelemetryDevDeviceId)
fmt.Println()
}
os.Stdout.Sync()
currentLanguage = detectLanguage()
// 新增函数用于读取现有配置
func readExistingConfig() (*StorageConfig, error) {
configPath, err := getConfigPath()
isAdmin, err := checkAdminPrivileges()
if err != nil {
return nil, err
handleError("permission check failed", err)
waitExit()
return
}
data, err := os.ReadFile(configPath)
if !isAdmin && runtime.GOOS == "windows" {
fmt.Println("Requesting administrator privileges... / 请求管理员权限...")
if err := selfElevate(); err != nil {
handleError("failed to elevate privileges", err)
showPrivilegeError()
waitExit()
return
}
return
} else if !isAdmin {
showPrivilegeError()
waitExit()
return
}
if checkCursorRunning() {
fmt.Println("\nDetected running Cursor instance(s). Closing... / 检测到正在运行的 Cursor 实例,正在关闭...")
if err := killCursorProcesses(); err != nil {
fmt.Println("Warning: Could not close all Cursor instances. Please close them manually. / 警告:无法关闭所有 Cursor 实例,请手动关闭。")
waitExit()
return
}
time.Sleep(2 * time.Second)
if checkCursorRunning() {
fmt.Println("\nWarning: Cursor is still running. Please close it manually. / 警告:Cursor 仍在运行,请手动关闭。")
waitExit()
return
}
}
clearScreen()
printCyberpunkBanner()
oldConfig, err := readExistingConfig()
if err != nil {
return nil, err
oldConfig = nil
}
var config StorageConfig
if err := json.Unmarshal(data, &config); err != nil {
return nil, err
config, err := loadAndUpdateConfig()
if err != nil {
handleError("configuration update failed", err)
waitExit()
return
}
return &config, nil
showIdComparison(oldConfig, config)
if err := saveConfig(config); err != nil {
handleError("failed to save configuration", err)
waitExit()
return
}
showSuccess()
fmt.Println("\nOperation completed! / 操作完成!")
waitExit()
}

BIN
releases/linux/cursor-id-modifier

BIN
releases/macos/cursor-id-modifier-amd64

BIN
releases/macos/cursor-id-modifier-arm64

BIN
releases/v1.0.1/releases/v1.0.1/cursor-id-modifier

BIN
releases/v1.0.1/releases/v1.0.1/cursor-id-modifier-amd64

BIN
releases/v1.0.1/releases/v1.0.1/cursor-id-modifier-arm64

BIN
releases/v1.0.1/releases/v1.0.1/cursor-id-modifier.exe

Loading…
Cancel
Save