Настройка DeepSeek Harness
DeepSeek Harness (команда dsh) это агент для работы с кодом от DeepSeek с веб-интерфейсом в браузере. Одна команда ниже ставит его, подключает к Claudexia и запускает. После этого в Harness доступны модели DeepSeek, GPT, Claude и другие из каталога Claudexia.
Что понадобится
- Node.js 24.9 или новее. Node.js это среда, в которой работает Harness. Скачайте версию LTS с nodejs.org и установите, затем откройте новое окно терминала и проверьте версию:
- Ключ Claudexia. Создайте его в кабинете, раздел «API-ключи». Ключ начинается с
sk_cdx_. Если аккаунта ещё нет, зарегистрируйтесь. - Деньги на балансе. Пополнить можно рублями: картой российского банка или по СБП, от 1 доллара. Способы оплаты перечислены на странице Тарифы.
node --versionОтвет должен начинаться с v24.9 или с большего числа, например v24.11.0 или v26.1.0.
Шаги
- Скопируйте ключ в разделе «API-ключи».
- Откройте терминал. На macOS это программа «Терминал», на Windows это PowerShell из меню «Пуск».
- Скопируйте команду для своей системы кнопкой «Копировать» и вставьте в терминал. Замените
sk_cdx_YOUR_KEYв начале команды на свой ключ. - Нажмите Enter. Команда поставит Harness, запишет настройки и запустит его. Через минуту-две откроется браузер.
bash <<'CLAUDEXIA_SETUP'
set -e
CLAUDEXIA_API_KEY="sk_cdx_YOUR_KEY"
if [ "${CLAUDEXIA_API_KEY#sk_cdx_}" = "YOUR_KEY" ]; then
echo "Replace sk_cdx_YOUR_KEY with your Claudexia key" >&2
exit 1
fi
if ! node -e 'const [a, b] = process.versions.node.split(".").map(Number); process.exit(a > 24 || (a === 24 && b >= 9) ? 0 : 1)'; then
echo "DeepSeek Harness needs Node.js 24.9 or newer: https://nodejs.org" >&2
exit 1
fi
npm install -g @deepseek-ai/dsh
export CLAUDEXIA_API_KEY
NODE_PATH="$(npm root -g)/@deepseek-ai/dsh/node_modules" node <<'NODE'
const fs = require('fs')
const os = require('os')
const path = require('path')
const yaml = require('js-yaml')
const home = process.env.DSH_HOME || path.join(os.homedir(), '.dsh')
const dir = path.join(home, 'profiles', 'web')
const file = path.join(dir, 'cordis.patch.yml')
fs.mkdirSync(dir, { recursive: true })
let rows = []
if (fs.existsSync(file)) {
try {
rows = yaml.load(fs.readFileSync(file, 'utf8')) || []
} catch (error) {
console.error('Cannot read ' + file + ': ' + error.message)
process.exit(1)
}
if (!Array.isArray(rows)) {
console.error(file + ' is not a list, nothing was changed')
process.exit(1)
}
fs.copyFileSync(file, file + '.bak-' + Date.now())
}
const claudexia = {
displayName: 'Claudexia',
apiKeyEnv: 'CLAUDEXIA_API_KEY',
api: 'openai-completions',
baseURL: 'https://api.claudexia.tech/v1',
models: [
{ id: 'deepseek-v4.1-flash', name: 'DeepSeek V4.1 Flash' },
{ id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro' },
{ id: 'gpt-6-sol', name: 'GPT-6 Sol' },
{ id: 'gpt-6-luna', name: 'GPT-6 Luna' },
{ id: 'claude-sonnet-5', name: 'Claude Sonnet 5' },
{ id: 'glm-5.3', name: 'GLM-5.3' },
{ id: 'qwen3.8-max', name: 'Qwen3.8 Max' },
],
}
const piAi = rows.find((row) => row && row.id === 'llm-pi-ai')
const piAiConfig = (piAi && piAi.config) || {}
const kept = rows.filter((row) => row && row.id !== 'llm-pi-ai' && row.id !== 'agent-default-model')
kept.push({ id: 'llm-pi-ai', config: { ...piAiConfig, providers: { ...(piAiConfig.providers || {}), claudexia } } })
kept.push({ id: 'agent-default-model', config: { provider: 'claudexia', model: 'deepseek-v4.1-flash' } })
fs.writeFileSync(file, yaml.dump(kept, { lineWidth: -1, noRefs: true }))
const envFile = path.join(home, '.env')
const lines = fs.existsSync(envFile) ? fs.readFileSync(envFile, 'utf8').split(/\r?\n/) : []
const rest = lines.filter((line) => line && !line.startsWith('CLAUDEXIA_API_KEY='))
rest.push('CLAUDEXIA_API_KEY=' + process.env.CLAUDEXIA_API_KEY)
fs.writeFileSync(envFile, rest.join('\n') + '\n', { mode: 0o600 })
fs.chmodSync(envFile, 0o600)
console.log('Claudexia is ready. Default model: deepseek-v4.1-flash')
NODE
dsh web
CLAUDEXIA_SETUP& {
$env:CLAUDEXIA_API_KEY = 'sk_cdx_YOUR_KEY'
if ($env:CLAUDEXIA_API_KEY.EndsWith('_YOUR_KEY')) {
Write-Host 'Replace sk_cdx_YOUR_KEY with your Claudexia key'
return
}
$nodeOk = $false
try { $nodeOk = [version](node -p 'process.versions.node') -ge [version]'24.9.0' } catch {}
if (-not $nodeOk) {
Write-Host 'DeepSeek Harness needs Node.js 24.9 or newer: https://nodejs.org'
return
}
npm.cmd install -g @deepseek-ai/dsh
if ($LASTEXITCODE -ne 0) { return }
$env:NODE_PATH = Join-Path (npm.cmd root -g) '@deepseek-ai\dsh\node_modules'
$setup = @'
const fs = require('fs')
const os = require('os')
const path = require('path')
const yaml = require('js-yaml')
const home = process.env.DSH_HOME || path.join(os.homedir(), '.dsh')
const dir = path.join(home, 'profiles', 'web')
const file = path.join(dir, 'cordis.patch.yml')
fs.mkdirSync(dir, { recursive: true })
let rows = []
if (fs.existsSync(file)) {
try {
rows = yaml.load(fs.readFileSync(file, 'utf8')) || []
} catch (error) {
console.error('Cannot read ' + file + ': ' + error.message)
process.exit(1)
}
if (!Array.isArray(rows)) {
console.error(file + ' is not a list, nothing was changed')
process.exit(1)
}
fs.copyFileSync(file, file + '.bak-' + Date.now())
}
const claudexia = {
displayName: 'Claudexia',
apiKeyEnv: 'CLAUDEXIA_API_KEY',
api: 'openai-completions',
baseURL: 'https://api.claudexia.tech/v1',
models: [
{ id: 'deepseek-v4.1-flash', name: 'DeepSeek V4.1 Flash' },
{ id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro' },
{ id: 'gpt-6-sol', name: 'GPT-6 Sol' },
{ id: 'gpt-6-luna', name: 'GPT-6 Luna' },
{ id: 'claude-sonnet-5', name: 'Claude Sonnet 5' },
{ id: 'glm-5.3', name: 'GLM-5.3' },
{ id: 'qwen3.8-max', name: 'Qwen3.8 Max' },
],
}
const piAi = rows.find((row) => row && row.id === 'llm-pi-ai')
const piAiConfig = (piAi && piAi.config) || {}
const kept = rows.filter((row) => row && row.id !== 'llm-pi-ai' && row.id !== 'agent-default-model')
kept.push({ id: 'llm-pi-ai', config: { ...piAiConfig, providers: { ...(piAiConfig.providers || {}), claudexia } } })
kept.push({ id: 'agent-default-model', config: { provider: 'claudexia', model: 'deepseek-v4.1-flash' } })
fs.writeFileSync(file, yaml.dump(kept, { lineWidth: -1, noRefs: true }))
const envFile = path.join(home, '.env')
const lines = fs.existsSync(envFile) ? fs.readFileSync(envFile, 'utf8').split(/\r?\n/) : []
const rest = lines.filter((line) => line && !line.startsWith('CLAUDEXIA_API_KEY='))
rest.push('CLAUDEXIA_API_KEY=' + process.env.CLAUDEXIA_API_KEY)
fs.writeFileSync(envFile, rest.join('\n') + '\n', { mode: 0o600 })
fs.chmodSync(envFile, 0o600)
console.log('Claudexia is ready. Default model: deepseek-v4.1-flash')
'@
$setup | node
if ($LASTEXITCODE -eq 0) { dsh.cmd web }
}Что делает команда: ставит пакет @deepseek-ai/dsh через npm, добавляет провайдера Claudexia в файл ~/.dsh/profiles/web/cordis.patch.yml и сохраняет ключ в ~/.dsh/.env. Файл с ключом доступен только вашему пользователю. Если файл настроек уже был, команда сохраняет копию рядом с ним (cordis.patch.yml.bak-…) и не трогает других провайдеров. Команду можно запускать повторно, например чтобы сменить ключ.
В следующий раз запускайте Harness из папки своего проекта одной командой:
dsh webПроверьте, что работает
- Если браузер не открылся сам, скопируйте из терминала адрес вида
http://127.0.0.1:3080/?token=…и откройте его. Без частиtokenстраница ответит ошибкой 401. - Выберите папку проекта (workspace). Без неё поле ввода не работает.
- В списке моделей выберите Claudexia и модель
deepseek-v4.1-flash, напишите «Ответь одним словом: OK». Пришёл ответ: всё работает.
Настройка без команды
Провайдера можно добавить и в самом Harness: Settings → Models → Add model provider → Custom model API. Provider ID: claudexia, Base URL: https://api.claudexia.tech/v1, API protocol: OpenAI Chat Completions, в поле ключа вставьте свой ключ. Кнопка Fetch available models подтянет список моделей.
Или впишите провайдера в файл настроек сами. Это тот же файл, который пишет команда:
- id: llm-pi-ai
config:
providers:
claudexia:
displayName: Claudexia
apiKeyEnv: CLAUDEXIA_API_KEY
api: openai-completions
baseURL: https://api.claudexia.tech/v1
models:
- id: deepseek-v4.1-flash
name: DeepSeek V4.1 Flash
- id: deepseek-v4-pro
name: DeepSeek V4 Pro
- id: gpt-6-sol
name: GPT-6 Sol
- id: gpt-6-luna
name: GPT-6 Luna
- id: claude-sonnet-5
name: Claude Sonnet 5
- id: glm-5.3
name: GLM-5.3
- id: qwen3.8-max
name: Qwen3.8 Max
- id: agent-default-model
config:
provider: claudexia
model: deepseek-v4.1-flashКлюч положите в файл ~/.dsh/.env строкой CLAUDEXIA_API_KEY=sk_cdx_… и перезапустите dsh web.
Какую модель выбрать
- Для повседневной работы:
claude-sonnet-5в канале Premium. В Cheap беритеclaude-opus-5-5. - Для сложных задач:
claude-opus-5-5илиgpt-6-astra. - Чтобы тратить меньше:
deepseek-v4.1-flashилиgpt-6-luna. Обе в разы дешевле Sonnet 5.
Чтобы добавить модель, допишите её ID в список models в файле настроек или в Settings → Models. Модель по умолчанию для новых сессий задаёт строка model в блоке agent-default-model.
Цены и полный список моделей в каталоге. Модели GPT, DeepSeek, Gemini и другие не из семейства Claude доступны только ключам канала Premium: см. Каналы.
Частые ошибки
Нажмите на ошибку, чтобы увидеть, что делать.
Needs Node.js 24.9 or newer
Стоит старая версия Node.js или её нет. Скачайте LTS с nodejs.org, установите, откройте новое окно терминала и запустите команду снова.
npm: EACCES или permission denied
npm не может писать в системную папку. Так бывает на Linux, когда Node.js поставлен из пакетов системы. Поставьте Node.js через установщик с nodejs.org или через nvm и повторите. Строки npm warn allow-scripts во время установки не мешают запуску.
Harness отвечает ошибкой на каждый запрос
Документация Harness советует для сторонних шлюзов добавить провайдеру блок compat с параметрами supportsDeveloperRole: false и maxTokensField: max_tokens. Добавьте его рядом с baseURL в файле настроек, сохраните файл и повторите запрос.
401: Invalid or missing API key
Программа отправила неверный ключ или не отправила его вовсе. Скопируйте ключ из раздела «API-ключи» целиком: он начинается с sk_cdx_, в нём нет пробелов и переносов строк. Если ключ удалили или отозвали, создайте новый. После замены ключа перезапустите программу.
402: баланс пуст
На балансе закончились деньги. В формате OpenAI ошибка приходит с кодом insufficient_quota, в формате Anthropic это HTTP-статус 402. Пополните баланс в разделе «Оплата»: рублями с карты или по СБП, от 1 доллара. Настройки менять не нужно, просто повторите запрос. Если баланс почти пуст, запросы идут по одному и может прийти 429 с кодом low_balance. Код account_frozen значит, что аккаунт приостановлен: напишите в поддержку.
404: Not found или неверный адрес
Программа обращается не по тому адресу. Для этой программы адрес такой: https://api.claudexia.tech/v1, с /v1 на конце и без косой черты после него. Если программа сама дописывает /v1, получится /v1/v1 и ошибка 404: тогда уберите /v1 из поля. Таблица адресов для разных программ есть на странице Адреса и форматы.
Программа не видит ключ
Программы читают настройки при запуске. Закройте программу полностью и откройте снова, а терминал откройте новый. Переменная окружения, заданная в одном окне терминала, не видна в другом. Приложения, запущенные из Dock, меню «Пуск» или ярлыка, не читают ~/.zshrc и ~/.bashrc: для них ключ вписывают в настройки самой программы.
Model not found или модель не найдена
Имя модели должно совпадать с ID в каталоге до символа: claude-sonnet-5, а не «Claude Sonnet 5». Суффикс [1m] понимает только Claude Code, в других программах его не пишите.
403: model_not_in_channel
Модели нет в канале вашего ключа. В канале Cheap работают только модели Claude, в канале Premium весь каталог. Смените модель или канал ключа: подробнее в разделе Каналы Premium и Cheap.
Проверьте ключ отдельно от программы
Команда ниже отправляет один короткий запрос напрямую в Claudexia, без программы. Так видно, в чём дело: в ключе и балансе или в настройках программы. Замените sk_cdx_YOUR_KEY на свой ключ. Запрос стоит доли цента.
curl https://api.claudexia.tech/v1/chat/completions \
-H "Authorization: Bearer sk_cdx_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "claude-sonnet-5", "max_tokens": 16, "messages": [{"role": "user", "content": "Reply with OK"}]}'Invoke-RestMethod https://api.claudexia.tech/v1/chat/completions -Method Post `
-Headers @{ Authorization = 'Bearer sk_cdx_YOUR_KEY' } -ContentType 'application/json' `
-Body '{"model": "claude-sonnet-5", "max_tokens": 16, "messages": [{"role": "user", "content": "Reply with OK"}]}'Пришёл ответ с полем choices: ключ и баланс в порядке, ищите ошибку в настройках программы. Пришла ошибка: код и текст подскажут причину, они разобраны выше и в справочнике ошибок.
Harness пока в предварительной версии, и формат его настроек может меняться. Мы проверили, что команда ставит Harness 0.2.2-rc.1, пишет корректный файл настроек и запускает веб-интерфейс. Если после обновления Harness настройки перестали читаться, сверьтесь с документацией Harness или напишите в поддержку.