> ## Documentation Index
> Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 차이점

`diffs`는 짧은 내장 시스템 지침과 변경 내용을 에이전트용 읽기 전용 diff 아티팩트로 변환하는 동반 skill이 있는 선택적 Plugin 도구입니다.

다음 중 하나를 받을 수 있습니다.

* `before` 및 `after` 텍스트
* 통합 `patch`

다음을 반환할 수 있습니다.

* 캔버스 표시용 Gateway 뷰어 URL
* 메시지 전달용 렌더링된 파일 경로(PNG 또는 PDF)
* 한 번의 호출에서 두 출력 모두

활성화하면 Plugin은 간결한 사용 지침을 시스템 프롬프트 공간 앞에 추가하고, 에이전트에 더 자세한 지침이 필요한 경우를 위해 상세 skill도 노출합니다.

## 빠른 시작

<Steps>
  <Step title="Plugin 설치">
    ```bash theme={"theme":{"light":"min-light","dark":"min-dark"}}
    openclaw plugins install diffs
    ```
  </Step>

  <Step title="Plugin 활성화">
    ```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
    {
      plugins: {
        entries: {
          diffs: {
            enabled: true,
          },
        },
      },
    }
    ```
  </Step>

  <Step title="모드 선택">
    <Tabs>
      <Tab title="view">
        캔버스 우선 흐름: 에이전트는 `mode: "view"`로 `diffs`를 호출하고 `canvas present`로 `details.viewerUrl`을 엽니다.
      </Tab>

      <Tab title="file">
        채팅 파일 전달: 에이전트는 `mode: "file"`로 `diffs`를 호출하고 `path` 또는 `filePath`를 사용해 `message`로 `details.filePath`를 보냅니다.
      </Tab>

      <Tab title="both">
        결합: 에이전트는 `mode: "both"`로 `diffs`를 호출해 한 번의 호출에서 두 아티팩트를 모두 가져옵니다.
      </Tab>
    </Tabs>
  </Step>
</Steps>

## 내장 시스템 지침 비활성화

`diffs` 도구는 활성화한 상태로 유지하되 내장 시스템 프롬프트 지침을 비활성화하려면 `plugins.entries.diffs.hooks.allowPromptInjection`을 `false`로 설정하세요.

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        hooks: {
          allowPromptInjection: false,
        },
      },
    },
  },
}
```

이렇게 하면 Plugin, 도구, 동반 skill은 계속 사용할 수 있는 상태로 두면서 diffs Plugin의 `before_prompt_build` 훅을 차단합니다.

지침과 도구를 모두 비활성화하려면 대신 Plugin을 비활성화하세요.

## 일반적인 에이전트 워크플로

<Steps>
  <Step title="diffs 호출">
    에이전트가 입력과 함께 `diffs` 도구를 호출합니다.
  </Step>

  <Step title="details 읽기">
    에이전트가 응답에서 `details` 필드를 읽습니다.
  </Step>

  <Step title="표시">
    에이전트는 `canvas present`로 `details.viewerUrl`을 열거나, `path` 또는 `filePath`를 사용해 `message`로 `details.filePath`를 보내거나, 둘 다 수행합니다.
  </Step>
</Steps>

## 입력 예시

<Tabs>
  <Tab title="Before 및 after">
    ```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
    {
      "before": "# Hello\n\nOne",
      "after": "# Hello\n\nTwo",
      "path": "docs/example.md",
      "mode": "view"
    }
    ```
  </Tab>

  <Tab title="Patch">
    ```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
    {
      "patch": "diff --git a/src/example.ts b/src/example.ts\n--- a/src/example.ts\n+++ b/src/example.ts\n@@ -1 +1 @@\n-const x = 1;\n+const x = 2;\n",
      "mode": "both"
    }
    ```
  </Tab>
</Tabs>

## 도구 입력 참조

명시된 경우를 제외하고 모든 필드는 선택 사항입니다.

<ParamField path="before" type="string">
  원본 텍스트입니다. `patch`가 생략된 경우 `after`와 함께 필요합니다.
</ParamField>

<ParamField path="after" type="string">
  업데이트된 텍스트입니다. `patch`가 생략된 경우 `before`와 함께 필요합니다.
</ParamField>

<ParamField path="patch" type="string">
  통합 diff 텍스트입니다. `before` 및 `after`와 상호 배타적입니다.
</ParamField>

<ParamField path="path" type="string">
  before 및 after 모드의 표시 파일 이름입니다.
</ParamField>

<ParamField path="lang" type="string">
  before 및 after 모드의 언어 재정의 힌트입니다. Diff Viewer Language Pack Plugin이 설치되어 있지 않으면 알 수 없는 값과 기본 뷰어 집합 외부의 언어는 일반 텍스트로 대체됩니다.
</ParamField>

<ParamField path="title" type="string">
  뷰어 제목 재정의입니다.
</ParamField>

<ParamField path="mode" type="&#x22;view&#x22; | &#x22;file&#x22; | &#x22;both&#x22;">
  출력 모드입니다. 기본값은 Plugin 기본값 `defaults.mode`입니다. 더 이상 권장되지 않는 별칭: `"image"`는 `"file"`처럼 동작하며 이전 버전과의 호환성을 위해 여전히 허용됩니다.
</ParamField>

<ParamField path="theme" type="&#x22;light&#x22; | &#x22;dark&#x22;">
  뷰어 테마입니다. 기본값은 Plugin 기본값 `defaults.theme`입니다.
</ParamField>

<ParamField path="layout" type="&#x22;unified&#x22; | &#x22;split&#x22;">
  Diff 레이아웃입니다. 기본값은 Plugin 기본값 `defaults.layout`입니다.
</ParamField>

<ParamField path="expandUnchanged" type="boolean">
  전체 컨텍스트를 사용할 수 있을 때 변경되지 않은 섹션을 확장합니다. 호출별 옵션만 해당합니다(Plugin 기본 키가 아님).
</ParamField>

<ParamField path="fileFormat" type="&#x22;png&#x22; | &#x22;pdf&#x22;">
  렌더링된 파일 형식입니다. 기본값은 Plugin 기본값 `defaults.fileFormat`입니다.
</ParamField>

<ParamField path="fileQuality" type="&#x22;standard&#x22; | &#x22;hq&#x22; | &#x22;print&#x22;">
  PNG 또는 PDF 렌더링의 품질 프리셋입니다.
</ParamField>

<ParamField path="fileScale" type="number">
  기기 배율 재정의(`1`-`4`)입니다.
</ParamField>

<ParamField path="fileMaxWidth" type="number">
  CSS 픽셀 단위의 최대 렌더링 너비(`640`-`2400`)입니다.
</ParamField>

<ParamField path="ttlSeconds" type="number" default="1800">
  뷰어 및 독립 실행형 파일 출력의 아티팩트 TTL(초)입니다. 최대 21600입니다.
</ParamField>

<ParamField path="baseUrl" type="string">
  뷰어 URL 원본 재정의입니다. Plugin `viewerBaseUrl`을 재정의합니다. `http` 또는 `https`여야 하며 쿼리/해시는 없어야 합니다.
</ParamField>

<AccordionGroup>
  <Accordion title="레거시 입력 별칭">
    이전 버전과의 호환성을 위해 여전히 허용됩니다.

    * `format` -> `fileFormat`
    * `imageFormat` -> `fileFormat`
    * `imageQuality` -> `fileQuality`
    * `imageScale` -> `fileScale`
    * `imageMaxWidth` -> `fileMaxWidth`
  </Accordion>

  <Accordion title="검증 및 제한">
    * `before` 및 `after`는 각각 최대 512 KiB입니다.
    * `patch`는 최대 2 MiB입니다.
    * `path`는 최대 2048바이트입니다.
    * `lang`은 최대 128바이트입니다.
    * `title`은 최대 1024바이트입니다.
    * Patch 복잡도 상한: 최대 파일 128개 및 총 120000줄입니다.
    * `patch`와 `before` 또는 `after`를 함께 사용하면 거부됩니다.
    * 렌더링된 파일 안전 제한(PNG 및 PDF에 적용):
      * `fileQuality: "standard"`: 최대 8 MP(렌더링된 픽셀 8,000,000개).
      * `fileQuality: "hq"`: 최대 14 MP(렌더링된 픽셀 14,000,000개).
      * `fileQuality: "print"`: 최대 24 MP(렌더링된 픽셀 24,000,000개).
      * PDF는 최대 50페이지 제한도 있습니다.
  </Accordion>
</AccordionGroup>

## 구문 강조

OpenClaw에는 일반적인 소스, 구성, 문서 언어에 대한 구문 강조가 포함되어 있습니다.

`javascript`, `typescript`, `tsx`, `jsx`, `json`, `markdown`, `yaml`, `css`, `html`, `sh`, `python`, `go`, `rust`, `java`, `c`, `cpp`, `csharp`, `php`, `sql`, `docker`, `ruby`, `swift`, `kotlin`, `r`, `dart`, `lua`, `powershell`, `xml`, `toml`.

`js`, `ts`, `bash`, `md`, `yml`, `c++`, `dockerfile`, `rb`, `kt`, `ps1` 같은 일반적인 별칭은 해당 기본 언어로 정규화됩니다.

Diff Viewer Language Pack Plugin을 설치하여 다른 언어를 강조 표시하세요.

```bash theme={"theme":{"light":"min-light","dark":"min-dark"}}
openclaw plugins install clawhub:@openclaw/diffs-language-pack
```

언어 팩을 사용할 수 있으면 OpenClaw는 훨씬 더 많은 언어를 강조 표시할 수 있습니다. 팩이 설치되어 있지 않아도 기본 목록 밖의 파일은 읽기 쉬운 일반 텍스트로 계속 렌더링됩니다. 예로는 Astro, Vue, Svelte, MDX, GraphQL, Terraform/HCL, Nix, Clojure, Elixir, Haskell, OCaml, Scala, Zig, Solidity, Verilog/VHDL, Fortran, MATLAB, LaTeX, Mermaid, Sass/Less/SCSS, Nginx, Apache, CSV, dotenv, INI, diff 파일이 있습니다.

자세한 내용은 [Diffs Language Pack Plugin](/ko/plugins/reference/diffs-language-pack)을, Shiki의 업스트림 언어 및 별칭 카탈로그는 [Shiki languages](https://shiki.style/languages)를 참고하세요.

## 출력 세부 정보 계약

이 도구는 `details` 아래에 구조화된 메타데이터를 반환합니다.

<AccordionGroup>
  <Accordion title="뷰어 필드">
    뷰어를 생성하는 모드의 공유 필드:

    * `artifactId`
    * `viewerUrl`
    * `viewerPath`
    * `title`
    * `expiresAt`
    * `inputKind`
    * `fileCount`
    * `mode`
    * `context` (사용 가능한 경우 `agentId`, `sessionId`, `messageChannel`, `agentAccountId`)
  </Accordion>

  <Accordion title="파일 필드">
    PNG 또는 PDF가 렌더링될 때의 파일 필드:

    * `artifactId`
    * `expiresAt`
    * `filePath`
    * `path` (메시지 도구 호환성을 위해 `filePath`와 같은 값)
    * `fileBytes`
    * `fileFormat`
    * `fileQuality`
    * `fileScale`
    * `fileMaxWidth`
  </Accordion>

  <Accordion title="호환성 별칭">
    기존 호출자에게도 반환됩니다:

    * `format` (`fileFormat`과 같은 값)
    * `imagePath` (`filePath`와 같은 값)
    * `imageBytes` (`fileBytes`와 같은 값)
    * `imageQuality` (`fileQuality`와 같은 값)
    * `imageScale` (`fileScale`와 같은 값)
    * `imageMaxWidth` (`fileMaxWidth`와 같은 값)
  </Accordion>
</AccordionGroup>

모드 동작 요약:

| 모드       | 반환되는 내용                                                                    |
| -------- | -------------------------------------------------------------------------- |
| `"view"` | 뷰어 필드만.                                                                    |
| `"file"` | 파일 필드만, 뷰어 아티팩트 없음.                                                        |
| `"both"` | 뷰어 필드와 파일 필드. 파일 렌더링이 실패하면 뷰어는 `fileError` 및 `imageError` 별칭과 함께 계속 반환됩니다. |

## 접힌 변경 없는 섹션

* 뷰어는 `N unmodified lines` 같은 행을 표시할 수 있습니다.
* 해당 행의 펼치기 컨트롤은 조건부이며 모든 입력 종류에서 보장되지는 않습니다.
* 펼치기 컨트롤은 렌더링된 diff에 펼칠 수 있는 컨텍스트 데이터가 있을 때 표시되며, 이는 before 및 after 입력에서 일반적입니다.
* 많은 unified patch 입력의 경우 생략된 컨텍스트 본문은 파싱된 패치 hunk에서 사용할 수 없으므로, 행이 펼치기 컨트롤 없이 나타날 수 있습니다. 이는 예상된 동작입니다.
* `expandUnchanged`는 펼칠 수 있는 컨텍스트가 있을 때만 적용됩니다.

## Plugin 기본값

Plugin 전체 기본값을 `~/.openclaw/openclaw.json`에 설정하세요.

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          defaults: {
            fontFamily: "Fira Code",
            fontSize: 15,
            lineSpacing: 1.6,
            layout: "unified",
            showLineNumbers: true,
            diffIndicators: "bars",
            wordWrap: true,
            background: true,
            theme: "dark",
            fileFormat: "png",
            fileQuality: "standard",
            fileScale: 2,
            fileMaxWidth: 960,
            mode: "both",
            ttlSeconds: 21600,
          },
        },
      },
    },
  },
}
```

지원되는 기본값:

* `fontFamily`
* `fontSize`
* `lineSpacing`
* `layout`
* `showLineNumbers`
* `diffIndicators`
* `wordWrap`
* `background`
* `theme`
* `fileFormat`
* `fileQuality`
* `fileScale`
* `fileMaxWidth`
* `mode`
* `ttlSeconds`

명시적인 도구 매개변수는 이러한 기본값을 재정의합니다.

### 영구 뷰어 URL 구성

<ParamField path="viewerBaseUrl" type="string">
  도구 호출이 `baseUrl`을 전달하지 않을 때 반환되는 뷰어 링크에 대한 Plugin 소유 fallback입니다. `http` 또는 `https`여야 하며, 쿼리/해시는 없어야 합니다.
</ParamField>

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          viewerBaseUrl: "https://gateway.example.com/openclaw",
        },
      },
    },
  },
}
```

## 보안 구성

<ParamField path="security.allowRemoteViewer" type="boolean" default="false">
  `false`: 뷰어 라우트에 대한 non-loopback 요청이 거부됩니다. `true`: 토큰화된 경로가 유효하면 원격 뷰어가 허용됩니다.
</ParamField>

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  plugins: {
    entries: {
      diffs: {
        enabled: true,
        config: {
          security: {
            allowRemoteViewer: false,
          },
        },
      },
    },
  },
}
```

## 아티팩트 수명 주기 및 스토리지

* 아티팩트는 임시 하위 폴더 `$TMPDIR/openclaw-diffs` 아래에 저장됩니다.
* 뷰어 아티팩트 메타데이터에는 다음이 포함됩니다.
  * 무작위 아티팩트 ID(16진수 20자)
  * 무작위 토큰(16진수 48자)
  * `createdAt` 및 `expiresAt`
  * 저장된 `viewer.html` 경로
* 지정하지 않으면 기본 아티팩트 TTL은 30분입니다.
* 허용되는 최대 뷰어 TTL은 6시간입니다.
* 정리는 아티팩트 생성 후 기회가 있을 때 실행됩니다.
* 만료된 아티팩트는 삭제됩니다.
* 메타데이터가 없으면 대체 정리가 24시간보다 오래된 오래된 폴더를 제거합니다.

## 뷰어 URL 및 네트워크 동작

뷰어 라우트:

* `/plugins/diffs/view/{artifactId}/{token}`

뷰어 애셋:

* `/plugins/diffs/assets/viewer.js`
* `/plugins/diffs/assets/viewer-runtime.js`
* diff가 Diff Viewer Language Pack의 언어를 사용할 때 `/plugins/diffs-language-pack/assets/viewer.js`

뷰어 문서는 해당 애셋을 뷰어 URL 기준 상대 경로로 확인하므로, 선택적 `baseUrl` 경로 접두사는 두 애셋 요청 모두에도 보존됩니다.

URL 구성 동작:

* 도구 호출 `baseUrl`이 제공되면 엄격한 검증 후 사용됩니다.
* 그렇지 않고 Plugin `viewerBaseUrl`이 구성되어 있으면 사용됩니다.
* 두 재정의가 모두 없으면 뷰어 URL은 기본적으로 loopback `127.0.0.1`을 사용합니다.
* Gateway 바인드 모드가 `custom`이고 `gateway.customBindHost`가 설정되어 있으면 해당 호스트가 사용됩니다.

`baseUrl` 규칙:

* `http://` 또는 `https://`여야 합니다.
* 쿼리와 해시는 거부됩니다.
* Origin과 선택적 기본 경로가 허용됩니다.

## 보안 모델

<AccordionGroup>
  <Accordion title="뷰어 강화">
    * 기본적으로 loopback 전용입니다.
    * 엄격한 ID 및 토큰 검증이 적용된 토큰화된 뷰어 경로.
    * 뷰어 응답 CSP:
      * `default-src 'none'`
      * 스크립트와 애셋은 자체 출처에서만
      * 아웃바운드 `connect-src` 없음
    * 원격 액세스가 활성화된 경우 원격 실패 제한:
      * 60초당 40회 실패
      * 60초 잠금(`429 Too Many Requests`)
  </Accordion>

  <Accordion title="파일 렌더링 강화">
    * 스크린샷 브라우저 요청 라우팅은 기본적으로 거부됩니다.
    * `http://127.0.0.1/plugins/diffs/assets/*`의 로컬 뷰어 애셋만 허용됩니다.
    * 외부 네트워크 요청은 차단됩니다.
  </Accordion>
</AccordionGroup>

## 파일 모드의 브라우저 요구 사항

`mode: "file"` 및 `mode: "both"`에는 Chromium 호환 브라우저가 필요합니다.

확인 순서:

<Steps>
  <Step title="구성">
    OpenClaw 구성의 `browser.executablePath`.
  </Step>

  <Step title="환경 변수">
    * `OPENCLAW_BROWSER_EXECUTABLE_PATH`
    * `BROWSER_EXECUTABLE_PATH`
    * `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH`
  </Step>

  <Step title="플랫폼 대체">
    플랫폼 명령/경로 탐색 대체.
  </Step>
</Steps>

일반적인 실패 문구:

* `Diff PNG/PDF rendering requires a Chromium-compatible browser...`

Chrome, Chromium, Edge 또는 Brave를 설치하거나 위의 실행 파일 경로 옵션 중 하나를 설정하여 해결하세요.

## 문제 해결

<AccordionGroup>
  <Accordion title="입력 검증 오류">
    * `Provide patch or both before and after text.` — `before`와 `after`를 모두 포함하거나 `patch`를 제공하세요.
    * `Provide either patch or before/after input, not both.` — 입력 모드를 혼합하지 마세요.
    * `Invalid baseUrl: ...` — 선택적 경로가 있는 `http(s)` Origin을 사용하고 쿼리/해시는 사용하지 마세요.
    * `{field} exceeds maximum size (...)` — 페이로드 크기를 줄이세요.
    * 큰 패치 거부 — 패치 파일 수 또는 전체 줄 수를 줄이세요.
  </Accordion>

  <Accordion title="뷰어 접근성">
    * 뷰어 URL은 기본적으로 `127.0.0.1`로 확인됩니다.
    * 원격 액세스 시나리오에서는 다음 중 하나를 사용하세요.
      * Plugin `viewerBaseUrl`을 설정하거나,
      * 도구 호출마다 `baseUrl`을 전달하거나,
      * `gateway.bind=custom` 및 `gateway.customBindHost`를 사용
    * `gateway.trustedProxies`가 동일 호스트 프록시(예: Tailscale Serve)를 위해 loopback을 포함하는 경우, 전달된 클라이언트 IP 헤더가 없는 원시 loopback 뷰어 요청은 설계상 실패하도록 닫힙니다.
    * 해당 프록시 토폴로지에서는 다음을 따르세요.
      * 첨부 파일만 필요할 때는 `mode: "file"` 또는 `mode: "both"`를 선호하거나,
      * 공유 가능한 뷰어 URL이 필요할 때는 의도적으로 `security.allowRemoteViewer`를 활성화하고 Plugin `viewerBaseUrl`을 설정하거나 프록시/공개 `baseUrl`을 전달하세요.
    * 외부 뷰어 액세스를 의도할 때만 `security.allowRemoteViewer`를 활성화하세요.
  </Accordion>

  <Accordion title="수정되지 않은 줄 행에 확장 버튼이 없음">
    패치 입력에서 패치가 확장 가능한 컨텍스트를 포함하지 않는 경우 발생할 수 있습니다. 이는 예상된 동작이며 뷰어 실패를 의미하지 않습니다.
  </Accordion>

  <Accordion title="아티팩트를 찾을 수 없음">
    * TTL로 인해 아티팩트가 만료되었습니다.
    * 토큰 또는 경로가 변경되었습니다.
    * 정리가 오래된 데이터를 제거했습니다.
  </Accordion>
</AccordionGroup>

## 운영 지침

* 캔버스의 로컬 대화형 리뷰에는 `mode: "view"`를 선호하세요.
* 첨부 파일이 필요한 아웃바운드 채팅 채널에는 `mode: "file"`을 선호하세요.
* 배포에 원격 뷰어 URL이 필요하지 않으면 `allowRemoteViewer`를 비활성화 상태로 유지하세요.
* 민감한 diff에는 명시적으로 짧은 `ttlSeconds`를 설정하세요.
* 필요하지 않을 때는 diff 입력에 비밀 정보를 보내지 마세요.
* 채널이 이미지를 강하게 압축하는 경우(예: Telegram 또는 WhatsApp), PDF 출력(`fileFormat: "pdf"`)을 선호하세요.

<Note>
  Diff 렌더링 엔진은 [Diffs](https://diffs.com)에서 제공합니다.
</Note>

## 관련 항목

* [브라우저](/ko/tools/browser)
* [Plugins](/ko/tools/plugin)
* [도구 개요](/ko/tools)
