Files
ironclaw/README.ko.md
Illia Polosukhin 8b6298513d feat(i18n): add Korean translation, fix zh-CN drift, and prevent future drift via pre-commit hook (#2065)
* feat(i18n): add Korean translation, fix zh-CN drift, cover hardcoded strings

Adds Korean (ko) as the third web UI language, brings zh-CN back into
parity with en, converts ~80 hardcoded English strings in app.js into
i18n keys, and installs a pre-commit hook that prevents future drift.

## Korean web UI

- New `src/channels/web/static/i18n/ko.js` — full translation of all
  663 keys, mirroring the structure of `en.js`/`zh-CN.js`
- New `src/channels/web/server.rs` route `/i18n/ko.js` + handler
- New language menu button in `index.html`
- Browser auto-detect now special-cases `ko-*` (in addition to `zh-*`)
  so Korean visitors land on Korean by default
- Toast label map in `i18n-app.js` becomes a small lookup table so the
  next language is a single-line addition

## zh-CN drift fix

`zh-CN.js` was missing 9 keys that had been added to `en.js` after the
Chinese pack was last touched (`config.telegramOpenBot`,
`settings.tools`, and 7 keys under the `tools.*` namespace for the new
Tool Permissions tab). Backfilled with Chinese translations so users on
the Tools settings panel see proper labels instead of raw key strings.

## Hardcoded strings in app.js

`app.js` had ~80 user-facing English string literals that bypassed
`I18n.t()` entirely — toasts, confirms, alerts, button labels, meta-item
labels for jobs/routines/missions detail panels, the theme dynamic
label, dynamic auth states ("Connecting...", "Authenticated"), etc.
These were invisible to the language switcher and would always render
in English regardless of the user's choice.

Replaced every literal with `I18n.t('key', { ...placeholders })` and
added the corresponding ~95 new keys to `en.js`, `zh-CN.js`, AND `ko.js`
in lockstep so all three packs stay at 663 keys with identical key sets
and matching `{name}`-style placeholder tokens.

Existing keys were reused where possible (`message.copy`,
`approval.approved`, `connection.reconnected`, etc.).

## Pre-commit parity hook

New `scripts/check-i18n-parity.sh` (pure POSIX bash, no Node) verifies:

1. No duplicate keys within any single language file
2. Every language has the same key set as `en.js` (the source of truth)
3. Placeholder tokens like `{name}`, `{count}` match across all
   languages — catches the silent bug where a translator drops an
   interpolation token

Wired into both pre-commit hook install paths:
- `scripts/pre-commit-safety.sh` (installed by `dev-setup.sh` as a
  symlink at `.git/hooks/pre-commit`; symlink is followed via
  `readlink` so the script location resolves correctly)
- `.githooks/pre-commit` (used when devs set
  `git config core.hooksPath .githooks`)

Both block the commit on failure with a clear error message and the
`git commit --no-verify` escape hatch. Tested by deliberately removing
a key from `ko.js` (caught) and stripping a `{path}` placeholder
(caught).

## Korean README

New `README.ko.md` — full Korean translation of `README.md`. Follows
the layout of `README.ja.md` (6-item single-word ToC to keep anchors
clean for non-Latin headings). All code blocks, image paths, and badge
URLs preserved verbatim.

`한국어` link added to the language switcher in all 5 READMEs
(`README.md`, `.zh-CN.md`, `.ru.md`, `.ja.md`, and the new `.ko.md`).

## Verification

- `./scripts/check-i18n-parity.sh` — `OK (663 keys × 3 languages)`
- `node --check` clean on every modified JS file
- Three-way parity: identical sorted key sets across en/zh-CN/ko, zero
  placeholder mismatches
- Hook tested by removing/mutating keys and confirming the commit is
  blocked

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(i18n): address PR review feedback [skip-regression-check]

Addresses 6 review comments on #2065. All changes are in
src/channels/web/static/ (per .claude/rules/review-discipline.md
exemption) plus a bash helper script — no Rust code is touched.

## scripts/check-i18n-parity.sh

- **Portable mktemp** (Copilot): bare `mktemp` works on GNU but BSD/macOS
  `mktemp` requires an explicit template with at least 6 trailing X's.
  Wrap in a small `mktemp_file()` helper that always passes a template
  (`${TMPDIR:-/tmp}/check-i18n-parity.XXXXXX`) so the script runs on
  every platform.

- **Symlink-attack-prone /tmp path** (gemini-code-assist): the
  placeholder-mismatch buffer was using `/tmp/i18n-ph-mismatch.$$`,
  which is predictable and vulnerable to symlink races in shared
  /tmp. Replace with `mktemp_file()` for consistency with the rest
  of the script.

## src/channels/web/static/app.js

- **Hardcoded `'Mode'` label** (gemini): jobs detail meta-grid had
  `metaItem('Mode', job.job_mode)` — convert to
  `I18n.t('jobs.mode')` and add the new key to all 3 language packs.

- **Hardcoded `'Yes'`/`'No'`** (Copilot): routine detail showed
  `routine.enabled ? 'Yes' : 'No'` even though the surrounding labels
  were translated. Reuse the existing `settings.on`/`settings.off`
  keys ("On"/"Off") which already render in all languages.

- **Hardcoded `'N/A'`** (Copilot): mission detail showed
  `m.next_fire_at ? formatDate(...) : 'N/A'`. Reuse the existing
  `common.noData` key. Also fixed the same pattern in the TEE popover
  (`renderTeePopover`) where `'N/A'` was used as a fallback for
  three different attestation fields, since fixing the pattern
  across the file is the principled response per the repo's
  review-discipline rule.

## src/channels/web/static/i18n-app.js

- **Hardcoded `LANG_LABELS` map** (gemini): the language-switch toast
  was reading from a per-call `{ 'en': 'English', 'zh-CN': '简体中文',
  'ko': '한국어' }` literal that would grow with every new language
  and drift from the actual supported set. Move each language's own
  native name into its own pack under a new `language.name` key:

      en.js    → 'language.name': 'English'
      zh-CN.js → 'language.name': '简体中文'
      ko.js    → 'language.name': '한국어'

  Then the toast becomes `I18n.t('language.switch') + ': ' +
  I18n.t('language.name')` — both halves are read from the language
  pack that was just switched in, so the entire toast appears in the
  newly selected language. Adding a future language is now a single
  key addition with NO changes to i18n-app.js.

## Verification

  $ ./scripts/check-i18n-parity.sh
  i18n parity: OK (665 keys × 3 languages)

  $ cargo test --lib
  test result: ok. 4241 passed; 0 failed; 3 ignored

Three-way parity preserved with the 2 new keys (`jobs.mode` and
`language.name`) added to all three language packs in lockstep.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 09:22:19 -07:00

15 KiB

IronClaw

IronClaw

언제나 당신 편인 안전한 개인 AI 어시스턴트

License: MIT OR Apache-2.0 Telegram: @ironclawAI Reddit: r/ironclawAI gitcgr

English | 简体中文 | Русский | 日本語 | 한국어

철학기능설치설정보안아키텍처


철학

IronClaw는 단순한 원칙 위에 만들어졌습니다: AI 어시스턴트는 당신을 위해 일해야 하며, 당신을 거슬러서는 안 됩니다.

AI 시스템이 데이터 처리에 대해 점점 더 불투명해지고 기업의 이익에 맞춰지는 세상에서, IronClaw는 다른 접근 방식을 취합니다:

  • 데이터는 당신의 것 - 모든 정보는 로컬에 저장되고 암호화되며, 절대 당신의 통제를 벗어나지 않습니다
  • 설계에 의한 투명성 - 오픈 소스, 감사 가능, 숨겨진 텔레메트리나 데이터 수집 없음
  • 자가 확장 기능 - 공급업체의 업데이트를 기다리지 않고 즉석에서 새로운 도구를 만들 수 있습니다
  • 심층 방어 - 프롬프트 인젝션 및 데이터 유출로부터 보호하는 다중 보안 계층

IronClaw는 개인적, 직업적 삶에서 실제로 신뢰할 수 있는 AI 어시스턴트입니다.

기능

보안 우선

  • WASM 샌드박스 - 신뢰할 수 없는 도구는 권한 기반의 격리된 WebAssembly 컨테이너에서 실행됩니다
  • 자격 증명 보호 - 비밀은 도구에 노출되지 않고, 누출 감지와 함께 호스트 경계에서 주입됩니다
  • 프롬프트 인젝션 방어 - 패턴 감지, 콘텐츠 정화, 정책 시행
  • 엔드포인트 화이트리스트 - HTTP 요청은 명시적으로 승인된 호스트와 경로로만 전송됩니다

항상 사용 가능

  • 다중 채널 - REPL, HTTP 웹훅, WASM 채널 (Telegram, Slack), 웹 게이트웨이
  • Docker 샌드박스 - 작업별 토큰과 오케스트레이터/워커 패턴을 사용한 격리된 컨테이너 실행
  • 웹 게이트웨이 - 실시간 SSE/WebSocket 스트리밍이 있는 브라우저 UI
  • 루틴 - 백그라운드 자동화를 위한 cron 일정, 이벤트 트리거, 웹훅 핸들러
  • 하트비트 시스템 - 모니터링 및 유지 보수 작업을 위한 사전 백그라운드 실행
  • 병렬 작업 - 격리된 컨텍스트로 여러 요청을 동시에 처리합니다
  • 자가 복구 - 중단된 작업의 자동 감지 및 복구

자가 확장

  • 동적 도구 빌드 - 필요한 것을 설명하면 IronClaw가 WASM 도구로 만들어 줍니다
  • MCP 프로토콜 - 추가 기능을 위해 Model Context Protocol 서버에 연결합니다
  • 플러그인 아키텍처 - 재시작 없이 새로운 WASM 도구와 채널을 추가할 수 있습니다

영구 메모리

  • 하이브리드 검색 - Reciprocal Rank Fusion을 사용한 전체 텍스트 + 벡터 검색
  • 워크스페이스 파일시스템 - 노트, 로그, 컨텍스트를 위한 유연한 경로 기반 저장소
  • 아이덴티티 파일 - 세션 간 일관된 성격과 선호도를 유지합니다

설치

사전 요구 사항

  • Rust 1.85+
  • pgvector 확장이 있는 PostgreSQL 15+
  • NEAR AI 계정 (인증은 설정 마법사를 통해 처리됨)

다운로드 또는 빌드

릴리스 페이지를 방문하여 최신 업데이트를 확인하세요.

Windows 인스톨러로 설치 (Windows)

Windows 인스톨러를 다운로드하여 실행하세요.

PowerShell 스크립트로 설치 (Windows)
irm https://github.com/nearai/ironclaw/releases/latest/download/ironclaw-installer.ps1 | iex
셸 스크립트로 설치 (macOS, Linux, Windows/WSL)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nearai/ironclaw/releases/latest/download/ironclaw-installer.sh | sh
Homebrew로 설치 (macOS/Linux)
brew install ironclaw
소스 코드 컴파일 (Windows, Linux, macOS의 Cargo)

cargo로 설치하세요. 컴퓨터에 Rust가 설치되어 있는지 확인하세요.

# 저장소 복제
git clone https://github.com/nearai/ironclaw.git
cd ironclaw

# 빌드
cargo build --release

# 테스트 실행
cargo test

전체 릴리스의 경우 (채널 소스를 수정한 후), ./scripts/build-all.sh를 실행하여 채널을 먼저 다시 빌드하세요.

데이터베이스 설정

# 데이터베이스 생성
createdb ironclaw

# pgvector 활성화
psql ironclaw -c "CREATE EXTENSION IF NOT EXISTS vector;"

설정

설정 마법사를 실행하여 IronClaw를 구성하세요:

ironclaw onboard

마법사는 데이터베이스 연결, NEAR AI 인증 (브라우저 OAuth를 통해), 그리고 비밀 암호화 (시스템 키체인 사용)를 처리합니다. 설정은 연결된 데이터베이스에 저장됩니다. 부트스트랩 변수 (예: DATABASE_URL, LLM_BACKEND)는 데이터베이스가 연결되기 전에 사용할 수 있도록 ~/.ironclaw/.env에 기록됩니다.

대체 LLM 공급자

IronClaw는 기본적으로 NEAR AI를 사용하지만 많은 LLM 공급자를 기본 지원합니다. 내장 공급자에는 Anthropic, OpenAI, GitHub Copilot, Google Gemini, MiniMax, Mistral, Ollama (로컬)이 포함됩니다. OpenRouter (300+ 모델), Together AI, Fireworks AI, 자체 호스팅 서버 (vLLM, LiteLLM) 같은 OpenAI 호환 서비스도 지원됩니다.

마법사에서 공급자를 선택하거나 환경 변수를 직접 설정하세요:

# 예: MiniMax (내장, 204K 컨텍스트)
LLM_BACKEND=minimax
MINIMAX_API_KEY=...

# 예: OpenAI 호환 엔드포인트
LLM_BACKEND=openai_compatible
LLM_BASE_URL=https://openrouter.ai/api/v1
LLM_API_KEY=sk-or-...
LLM_MODEL=anthropic/claude-sonnet-4

전체 공급자 가이드는 docs/LLM_PROVIDERS.md를 참조하세요.

보안

IronClaw는 데이터를 보호하고 오용을 방지하기 위해 심층 방어를 구현합니다.

WASM 샌드박스

신뢰할 수 없는 모든 도구는 격리된 WebAssembly 컨테이너에서 실행됩니다:

  • 권한 기반 권한 - HTTP, 비밀, 도구 호출에 대한 명시적 옵트인
  • 엔드포인트 화이트리스트 - HTTP 요청은 승인된 호스트/경로로만 전송됩니다
  • 자격 증명 주입 - 비밀은 호스트 경계에서 주입되며, WASM 코드에 절대 노출되지 않습니다
  • 누출 감지 - 비밀 유출 시도에 대해 요청과 응답을 스캔합니다
  • 속도 제한 - 남용을 방지하기 위한 도구별 요청 제한
  • 리소스 제한 - 메모리, CPU, 실행 시간 제약
WASM ──► 화이트리스트 ──► 누출 스캔 ──► 자격 증명 ──► 실행 ──► 누출 스캔 ──► WASM
         검증기            (요청)         주입기         요청       (응답)

프롬프트 인젝션 방어

외부 콘텐츠는 여러 보안 계층을 통과합니다:

  • 인젝션 시도의 패턴 기반 감지
  • 콘텐츠 정화 및 이스케이핑
  • 심각도 수준이 있는 정책 규칙 (차단/경고/검토/정화)
  • 안전한 LLM 컨텍스트 주입을 위한 도구 출력 래핑

데이터 보호

  • 모든 데이터는 로컬 PostgreSQL 데이터베이스에 저장됩니다
  • 비밀은 AES-256-GCM으로 암호화됩니다
  • 텔레메트리, 분석, 데이터 공유 없음
  • 모든 도구 실행에 대한 전체 감사 로그

아키텍처

┌────────────────────────────────────────────────────────────────┐
│                          채널                                  │
│  ┌──────┐  ┌──────┐   ┌─────────────┐  ┌─────────────┐         │
│  │ REPL │  │ HTTP │   │ WASM 채널   │  │ 웹 게이트웨이│         │
│  └──┬───┘  └──┬───┘   └──────┬──────┘  │ (SSE + WS)  │         │
│     │         │              │         └──────┬──────┘         │
│     └─────────┴──────────────┴────────────────┘                │
│                              │                                 │
│                    ┌─────────▼─────────┐                       │
│                    │   에이전트 루프   │  의도 라우팅         │
│                    └────┬──────────┬───┘                       │
│                         │          │                           │
│              ┌──────────▼────┐  ┌──▼───────────────┐           │
│              │  스케줄러     │  │  루틴 엔진       │           │
│              │ (병렬 작업)   │  │ (cron, 이벤트, wh)│          │
│              └──────┬────────┘  └────────┬─────────┘           │
│                     │                    │                     │
│       ┌─────────────┼────────────────────┘                     │
│       │             │                                          │
│   ┌───▼─────┐  ┌────▼────────────────┐                         │
│   │ 로컬    │  │   오케스트레이터    │                         │
│   │ 워커    │  │  ┌───────────────┐  │                         │
│   │(인프로세스)│ │ │Docker 샌드박스│ │                         │
│   └───┬─────┘  │  │   컨테이너    │  │                         │
│       │        │  │ ┌───────────┐ │  │                         │
│       │        │  │ │Worker / CC│ │  │                         │
│       │        │  │ └───────────┘ │  │                         │
│       │        │  └───────────────┘  │                         │
│       │        └─────────┬───────────┘                         │
│       └──────────────────┤                                     │
│                          │                                     │
│              ┌───────────▼──────────┐                          │
│              │   도구 레지스트리    │                          │
│              │  내장, MCP, WASM     │                          │
│              └──────────────────────┘                          │
└────────────────────────────────────────────────────────────────┘

핵심 구성 요소

구성 요소 목적
에이전트 루프 주요 메시지 처리 및 작업 조정
라우터 사용자 의도 분류 (명령, 쿼리, 작업)
스케줄러 우선순위가 있는 병렬 작업 실행 관리
워커 LLM 추론과 도구 호출로 작업 실행
오케스트레이터 컨테이너 라이프사이클, LLM 프록시, 작업별 인증
웹 게이트웨이 채팅, 메모리, 작업, 로그, 확장, 루틴이 있는 브라우저 UI
루틴 엔진 예약된 (cron) 및 반응형 (이벤트, 웹훅) 백그라운드 작업
워크스페이스 하이브리드 검색이 있는 영구 메모리
안전 계층 프롬프트 인젝션 방어 및 콘텐츠 정화

사용법

# 첫 설정 (데이터베이스, 인증 등 구성)
ironclaw onboard

# 대화형 REPL 시작
cargo run

# 디버그 로깅 사용
RUST_LOG=ironclaw=debug cargo run

개발

# 코드 포맷
cargo fmt

# 린트
cargo clippy --all --benches --tests --examples --all-features

# 테스트 실행
createdb ironclaw_test
cargo test

# 특정 테스트 실행
cargo test test_name
  • Telegram 채널: 설정 및 DM 페어링에 대해 docs/TELEGRAM_SETUP.md를 참조하세요.
  • 채널 소스 변경: 업데이트된 WASM이 번들되도록 cargo build 전에 ./channels-src/telegram/build.sh를 실행하세요.

OpenClaw 역사

IronClaw는 OpenClaw에서 영감을 받은 Rust 재구현입니다. 전체 추적 매트릭스는 FEATURE_PARITY.md를 참조하세요.

주요 차이점:

  • Rust vs TypeScript - 네이티브 성능, 메모리 안전, 단일 바이너리
  • WASM 샌드박스 vs Docker - 가벼운 권한 기반 보안
  • PostgreSQL vs SQLite - 프로덕션 준비된 영속성
  • 보안 우선 설계 - 다중 방어 계층, 자격 증명 보호

라이선스

다음 중 하나를 선택하여 라이선스가 부여됩니다:

원하는 대로 선택할 수 있습니다.