Codex 教程

Codex中文乱码

2026-03-11
434 views
Codex中文乱码

Codex 修改文件导致中文乱码的解决办法

问题结论

编辑器编码 和 终端编码 必须保持一致。
在使用 Codex 修改文件时,有时会出现 中文乱码 的情况

image-20251019165022152

image-20251019165122901

打开 VS Code 设置(Ctrl + ,),在 settings.json 里增加以下配置:

json
"files.encoding": "utf8",
"files.autoGuessEncoding": true
  • files.encoding: 默认使用 UTF-8 保存文件

  • files.autoGuessEncoding: 打开文件时自动检测是否存在 BOM/其他编码

    这样 VS Code 打开和保存文件时,都能尽量保持编码一致。

将以下脚本复制创建.ps1文件并在管理员模型下执行

text
powershell -ExecutionPolicy Bypass -File .\utf8-script.ps1
text
# setup-ai-cli-utf8.ps1
# Windows AI CLI 乱码修复一键脚本
# 支持 Codex CLI / Claude Code / OpenCode
# 用法: powershell -ExecutionPolicy Bypass -File .\setup-ai-cli-utf8.ps1

param(
    [switch]$Codex,      # 只配置 Codex CLI
    [switch]$Claude,     # 只配置 Claude Code
    [switch]$OpenCode,   # 只配置 OpenCode
    [switch]$All         # 配置所有已安装的工具(默认)
)

$ErrorActionPreference = "Stop"

# 如果没有指定,默认处理所有已安装的工具
if (-not ($Codex -or $Claude -or $OpenCode)) {
    $All = $true
}

Write-Host "========================================" -ForegroundColor Cyan
Write-Host " Windows AI CLI UTF-8 修复脚本" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan

# === 诊断当前状态 ===
Write-Host "`n=== 诊断当前编码状态 ===" -ForegroundColor Yellow

$CurrentCodePage = cmd /c chcp 2>&1
Write-Host "当前 Code Page: $CurrentCodePage"

$ConsoleOutEnc = [Console]::OutputEncoding.WebName
$OutputEnc = $OutputEncoding.WebName
Write-Host "Console OutputEncoding: $ConsoleOutEnc"
Write-Host "OutputEncoding: $OutputEnc"

if ($ConsoleOutEnc -eq "utf-8" -and $OutputEnc -eq "utf-8") {
    Write-Host "编码已为 UTF-8,无需修复。" -ForegroundColor Green
    Write-Host "如果仍有乱码,可能是字体问题,跳转到字体检查部分。"
    $NeedsFix = $false
} else {
    Write-Host "编码不是 UTF-8,需要修复。" -ForegroundColor Red
    $NeedsFix = $true
}

# === [1/6] 安装 PowerShell 7 ===
Write-Host "`n=== [1/6] 检查并安装 PowerShell 7 ===" -ForegroundColor Yellow

$HasPwsh = Get-Command pwsh -ErrorAction SilentlyContinue
if ($HasPwsh) {
    Write-Host "PowerShell 7 已安装: $(pwsh -Version)" -ForegroundColor Green
} else {
    Write-Host "正在通过 winget 安装 PowerShell 7..." -ForegroundColor Yellow
    try {
        winget install --id Microsoft.PowerShell --source winget --accept-source-agreements --accept-package-agreements
        Write-Host "PowerShell 7 安装完成" -ForegroundColor Green
    } catch {
        Write-Host "winget 安装失败,请手动安装: https://github.com/PowerShell/PowerShell" -ForegroundColor Red
    }
}

# === [2/6] 创建 UTF-8 Core 脚本 ===
Write-Host "`n=== [2/6] 创建 UTF-8 引导脚本 ===" -ForegroundColor Yellow

$BinDir = Join-Path $env:USERPROFILE "bin"
New-Item -ItemType Directory -Path $BinDir -Force | Out-Null

$CoreScript = Join-Path $BinDir "ai-cli-utf8-core.ps1"

$CoreContent = @'
# ai-cli-utf8-core.ps1
# 所有 AI CLI wrapper 共用的 UTF-8 引导脚本

try {
    chcp 65001 | Out-Null
} catch {
    # chcp 不可用时忽略
}

$Utf8NoBom = [System.Text.UTF8Encoding]::new($false)

try { [Console]::InputEncoding  = $Utf8NoBom } catch {}
try { [Console]::OutputEncoding = $Utf8NoBom } catch {}

$global:OutputEncoding = $Utf8NoBom

# 语言运行时编码
$env:PYTHONUTF8       = "1"
$env:PYTHONIOENCODING = "utf-8"
$env:LESSCHARSET      = "utf-8"

# Git Bash / MSYS 兼容
if (-not $env:LANG) {
    $env:LANG = "C.UTF-8"
}
'@

Set-Content -Path $CoreScript -Value $CoreContent -Encoding UTF8
Write-Host "核心引导脚本已创建: $CoreScript" -ForegroundColor Green

# === [3/6] 创建 Wrapper 脚本 ===
Write-Host "`n=== [3/6] 创建 UTF-8 Wrapper ===" -ForegroundColor Yellow

function New-Wrapper {
    param([string]$ToolName)
    
    $Ps1Path = Join-Path $BinDir "$($ToolName)u.ps1"
    $CmdPath = Join-Path $BinDir "$($ToolName)u.cmd"
    
    # .ps1 wrapper
    $Ps1Content = @"
param(
  [Parameter(ValueFromRemainingArguments = `$true)]
  [string[]]`$RemainingArgs
)

. "`$PSScriptRoot\ai-cli-utf8-core.ps1"

`$cmd = Get-Command "$ToolName" -ErrorAction SilentlyContinue
if (-not `$cmd) {
  Write-Error "Command '$ToolName' was not found in PATH. Install it first, then retry."
  exit 127
}

& "$ToolName" @RemainingArgs
exit `$LASTEXITCODE
"@
    
    Set-Content -Path $Ps1Path -Value $Ps1Content -Encoding UTF8
    
    # .cmd wrapper (兼容直接在 cmd 中调用)
    $CmdContent = @"
@echo off
chcp 65001 >nul
where pwsh >nul 2>nul
if errorlevel 1 (
  powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%~dp0$($ToolName)u.ps1" %*
) else (
  pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%~dp0$($ToolName)u.ps1" %*
)
"@
    
    Set-Content -Path $CmdPath -Value $CmdContent -Encoding ASCII
    
    Write-Host "  $($ToolName)u.ps1 / $($ToolName)u.cmd 已创建" -ForegroundColor Green
}

# 检查哪些工具已安装
$HasCodex = Get-Command codex -ErrorAction SilentlyContinue
$HasClaude = Get-Command claude -ErrorAction SilentlyContinue
$HasOpenCode = Get-Command opencode -ErrorAction SilentlyContinue

if ($Codex -or $All) {
    if ($HasCodex) {
        New-Wrapper "codex"
    } else {
        Write-Host "  Codex CLI 未安装,跳过" -ForegroundColor DarkYellow
    }
}

if ($Claude -or $All) {
    if ($HasClaude) {
        New-Wrapper "claude"
    } else {
        Write-Host "  Claude Code 未安装,跳过" -ForegroundColor DarkYellow
    }
}

if ($OpenCode -or $All) {
    if ($HasOpenCode) {
        New-Wrapper "opencode"
    } else {
        Write-Host "  OpenCode 未安装,跳过" -ForegroundColor DarkYellow
    }
}

# === [4/6] 配置 PATH ===
Write-Host "`n=== [4/6] 配置系统 PATH ===" -ForegroundColor Yellow

$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($UserPath -notlike "*$BinDir*") {
    $NewPath = if ($UserPath) { "$UserPath;$BinDir" } else { $BinDir }
    [Environment]::SetEnvironmentVariable("Path", $NewPath, "User")
    $env:Path = "$env:Path;$BinDir"
    Write-Host "已将 $BinDir 添加到用户 PATH" -ForegroundColor Green
} else {
    Write-Host "$BinDir 已在 PATH 中" -ForegroundColor DarkYellow
}

# === [5/6] 配置 PowerShell Profile ===
Write-Host "`n=== [5/6] 配置 PowerShell Profile ===" -ForegroundColor Yellow

$ProfileDir = Split-Path $PROFILE -Parent
New-Item -ItemType Directory -Path $ProfileDir -Force | Out-Null

$Marker = "# >>> AI CLI UTF-8 bootstrap >>>"
$ProfileNeedsPatch = $true
if (Test-Path $PROFILE) {
    $ProfileNeedsPatch = -not (Select-String -Path $PROFILE -SimpleMatch $Marker -Quiet)
}

if ($ProfileNeedsPatch) {
    $Snippet = @"

# >>> AI CLI UTF-8 bootstrap >>>
`$AiCliUtf8Core = Join-Path `$env:USERPROFILE 'bin\ai-cli-utf8-core.ps1'
if (Test-Path `$AiCliUtf8Core) {
  . `$AiCliUtf8Core
}
# <<< AI CLI UTF-8 bootstrap <<<
"@
    Add-Content -Path $PROFILE -Value $Snippet -Encoding UTF8
    Write-Host "PowerShell Profile 已添加 UTF-8 引导" -ForegroundColor Green
} else {
    Write-Host "Profile 中已存在 UTF-8 引导" -ForegroundColor DarkYellow
}

# 同样为 PowerShell 7 配置 profile
$PwshProfile = Join-Path ([Environment]::GetFolderPath('MyDocuments')) "PowerShell\Microsoft.PowerShell_profile.ps1"
$PwshProfileDir = Split-Path $PwshProfile -Parent
New-Item -ItemType Directory -Path $PwshProfileDir -Force | Out-Null

$PwshNeedsPatch = $true
if (Test-Path $PwshProfile) {
    $PwshNeedsPatch = -not (Select-String -Path $PwshProfile -SimpleMatch $Marker -Quiet)
}

if ($PwshNeedsPatch) {
    Add-Content -Path $PwshProfile -Value $Snippet -Encoding UTF8
    Write-Host "PowerShell 7 Profile 已添加 UTF-8 引导" -ForegroundColor Green
}

# === [6/6] 配置 Git & 工具规则 ===
Write-Host "`n=== [6/6] 配置 Git UTF-8 和工具编码规则 ===" -ForegroundColor Yellow

# Git
try {
    git config --global core.quotepath false
    git config --global i18n.logOutputEncoding utf-8
    git config --global i18n.commitEncoding utf-8
    Write-Host "Git UTF-8 配置完成" -ForegroundColor Green
} catch {
    Write-Host "Git 配置失败(可能未安装),跳过" -ForegroundColor DarkYellow
}

# 编码规则内容
$EncodingRules = @"

# Windows encoding rules

- When running PowerShell on Windows, set UTF-8 first:
  `chcp 65001; [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new(`$false); `$OutputEncoding = [System.Text.UTF8Encoding]::new(`$false)`.
- Do not judge source file corruption from terminal-rendered mojibake alone.
- Before rewriting files that contain non-ASCII text, validate bytes using strict UTF-8 decoding.
- Preserve existing file encoding where possible.
- Prefer UTF-8 without BOM for cross-platform source files.
- For `.ps1` scripts intended for Windows PowerShell 5.1 with non-ASCII characters, UTF-8 with BOM may be safer.
"@

# Codex CLI: 写入 AGENTS.md
if ($Codex -or $All) {
    if ($HasCodex) {
        $CodexDir = Join-Path $env:USERPROFILE ".codex"
        if (Test-Path $CodexDir) {
            $CodexAgents = Join-Path $CodexDir "AGENTS.md"
            $Existing = if (Test-Path $CodexAgents) { Get-Content $CodexAgents -Raw } else { "" }
            if ($Existing -notmatch "Windows encoding rules") {
                Set-Content -Path $CodexAgents -Value "$Existing$EncodingRules" -Encoding UTF8
                Write-Host "Codex CLI AGENTS.md 已添加编码规则" -ForegroundColor Green
            } else {
                Write-Host "Codex CLI AGENTS.md 已包含编码规则" -ForegroundColor DarkYellow
            }
        }
    }
}

# Claude Code: 写入 CLAUDE.md
if ($Claude -or $All) {
    if ($HasClaude) {
        $ClaudeDir = Join-Path $env:USERPROFILE ".claude"
        if (Test-Path $ClaudeDir) {
            $ClaudeMd = Join-Path $ClaudeDir "CLAUDE.md"
            $Existing = if (Test-Path $ClaudeMd) { Get-Content $ClaudeMd -Raw } else { "" }
            if ($Existing -notmatch "Windows encoding rules") {
                Set-Content -Path $ClaudeMd -Value "$Existing$EncodingRules" -Encoding UTF8
                Write-Host "Claude Code CLAUDE.md 已添加编码规则" -ForegroundColor Green
            } else {
                Write-Host "Claude Code CLAUDE.md 已包含编码规则" -ForegroundColor DarkYellow
            }
        }
    }
}

# OpenCode: 写入 AGENTS.md
if ($OpenCode -or $All) {
    if ($HasOpenCode) {
        $OpenCodeDir = Join-Path $env:USERPROFILE ".opencode"
        if (-not (Test-Path $OpenCodeDir)) {
            New-Item -ItemType Directory -Path $OpenCodeDir -Force | Out-Null
        }
        $OpenCodeAgents = Join-Path $OpenCodeDir "AGENTS.md"
        $Existing = if (Test-Path $OpenCodeAgents) { Get-Content $OpenCodeAgents -Raw } else { "" }
        if ($Existing -notmatch "Windows encoding rules") {
            Set-Content -Path $OpenCodeAgents -Value "$Existing$EncodingRules" -Encoding UTF8
            Write-Host "OpenCode AGENTS.md 已添加编码规则" -ForegroundColor Green
        } else {
            Write-Host "OpenCode AGENTS.md 已包含编码规则" -ForegroundColor DarkYellow
        }
    }
}

# === 完成 ===
Write-Host "`n========================================" -ForegroundColor Green
Write-Host " UTF-8 修复完成!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Write-Host "已创建的 Wrapper 命令:" -ForegroundColor Cyan

if ($HasCodex) { Write-Host "  codexu     -> 启动 Codex CLI (UTF-8)" -ForegroundColor White }
if ($HasClaude) { Write-Host "  claudeu    -> 启动 Claude Code (UTF-8)" -ForegroundColor White }
if ($HasOpenCode) { Write-Host "  opencodeu  -> 启动 OpenCode (UTF-8)" -ForegroundColor White }

Write-Host ""
Write-Host "使用方式:" -ForegroundColor Cyan
Write-Host "  # 新开一个 PowerShell 窗口,运行:"
Write-Host ""
if ($HasCodex) { Write-Host "  codexu" -ForegroundColor White }
if ($HasClaude) { Write-Host "  claudeu" -ForegroundColor White }
if ($HasOpenCode) { Write-Host "  opencodeu" -ForegroundColor White }

Write-Host ""
Write-Host "验证 UTF-8 是否生效:" -ForegroundColor Cyan
Write-Host "  pwsh -Command `"chcp; Write-Host '中文测试 😀'`""

Write-Host ""
Write-Host "如果仍然乱码,检查:" -ForegroundColor Yellow
Write-Host "检查:是否有使用这个命令执行 powershell -ExecutionPolicy Bypass -File .\utf8-script.ps1"
Write-Host "终端字体是否支持 CJK(推荐 Windows Terminal + Sarasa Gothic / Cascadia Code)"

Write-Host "# 查看当前编码状态
cmd /c chcp

# 查看 PowerShell 编码设置
[Console]::InputEncoding.WebName
[Console]::OutputEncoding.WebName
$OutputEncoding.WebName

# Unicode 烟雾测试
"中文测试 😀 äöü Привет こんにちは 한국어""

Write-Host "# 期望看到:
 Active code page: 65001      # ← 必须是 65001
ConsoleInputEncoding  = utf-8
ConsoleOutputEncoding = utf-8
OutputEncoding        = utf-8
中文测试 😀 äöü Привет こんにちは 한국어   # ← 完整显示
"