SpyBara
Go Premium

plugins/mods/gallery.md 2026-10-01 23:59 UTC to 2026-10-02 03:59 UTC

This page contains 435 additions and 0 deletions.

2026
Fri 2 04:57

모드용 인터페이스 갤러리

텍스트, 버튼, 필드, Markdown, 코드, diff 등 Claude Code 모드가 그릴 수 있는 인터페이스 요소를 샘플 코드 및 터미널 스크린샷과 함께 살펴봅니다.

모드는 요소를 사용해 인터페이스를 그립니다. 요소에는 텍스트, 박스, 버튼, 필드, 그리고 콘텐츠 서식을 대신 지정해 주는 몇 가지 요소가 있습니다. 이 페이지의 샘플은 요소를 그리는 코드를 보여 주며, 대부분은 터미널 창에 그려진 결과 스크린샷을 함께 제공하므로 모양을 보고 요소를 고를 수 있습니다.

그리기가 작동하는 방식을 알아보려면 인터페이스에 그리기부터 시작하십시오. 주요 props와 각 요소를 그리는 앱은 요소 레퍼런스를 참조하십시오. 타입 선언에는 모든 prop이 나열되어 있습니다.

샘플 사용해 보기

이 페이지의 샘플은 완전한 모드가 아니라 코드 조각입니다. 각 샘플은 하나의 요소와 그 안에 중첩된 모든 항목에 대한 코드입니다.

샘플을 직접 터미널에서 확인하려면 다음 단계에 따라 작은 모드를 만들고 샘플을 붙여 넣으십시오. 이 모드는 창을 열고 그 안에 샘플을 그리는 /gallery 명령을 추가합니다. 창은 넓은 전체 화면 터미널에서는 트랜스크립트 옆의 사이드바이고, 그 외의 경우에는 프롬프트 위의 테두리가 있는 영역입니다.

1

모드 만들기

gallery라는 디렉터리를 만들고 그 안에 .claude-plugin 및 hooks 디렉터리를 만드십시오. 파일에 대한 설명은 모드 만들기를 참조하십시오.

매니페스트를 gallery/.claude-plugin/plugin.json으로 저장합니다.

{
"name": "gallery",
"version": "0.1.0",
"description": "Opens a pane that draws one sample",
"author": { "name": "Your Name" }
}

gallery/hooks/hooks.json에 진입점을 지정합니다.

{
"modules": ["./register.js"]
}

코드를 gallery/hooks/register.js로 저장합니다. 이 코드는 창을 여는 /gallery 명령을 추가하고 그 창에 Plain text를 그립니다.

// Stands in for your own callback in the samples that take one
const noop = () => {}
// The Select sample keeps its choice here
let picked = 'md'

// The Raster sample packs its cells with this function
const DEFAULT_COLOR = 0x01000000
function cellsOf(rows) {
const numbers = rows.flat().flatMap(([char, color]) => [char.codePointAt(0), color, DEFAULT_COLOR])
return new Uint8Array(Uint32Array.from(numbers).buffer).toBase64()
}

export function register(on) {
on('session.start', async ($, e, next) => {
await $.command.register({ name: 'gallery', description: 'Open the sample pane' })
return next(e)
})

on('command.run', { command: 'gallery' }, async ($) => {
await $.ui.open({ id: 'gallery', focus: true, closeOnEscape: true })
return {}
})

on('ui.render', { component: 'Pane' }, async ($, e, next) => {
if (e.requestId !== 'gallery') return next(e)
const { Box, Text, Button, Input, Select, Link, Markdown, Code, Raster, Svg } = $.ui.resolve(e)
// Replace the element after return with a sample
return Text({ children: ['Plain text'] })
})
}
2

모드 실행하기

셸에서 gallery가 있는 디렉터리에서 Claude Code를 시작합니다.

claude --plugin-dir ./gallery

Claude Code 프롬프트에서 /gallery를 실행합니다. Plain text가 표시된 창이 열립니다.

3

샘플로 교체하기

이 페이지에서 샘플을 복사합니다. register.js에서 Text({ children: ['Plain text'] }) 위치에 샘플을 붙여 넣어 return 뒤에 오도록 한 다음 파일을 저장합니다. Claude Code는 저장할 때마다 모듈을 다시 로드하므로, /gallery를 다시 실행하면 새 샘플을 볼 수 있습니다.

요소 선택하기

샘플은 화면에 표시하려는 내용에 따라 분류되어 있습니다.

텍스트 표시하기

화면에 글자를 표시하는 요소는 세 가지입니다. 직접 스타일을 지정할 때는 Text, 이미 서식이 지정된 콘텐츠에는 Markdown, URL에는 Link를 사용합니다.

`Text`

Text는 지정한 스타일로 문자열을 그립니다. 이 샘플은 각 스타일마다 한 줄씩 보여 줍니다.

Box({
  flexDirection: 'column',
  children: [
    Text({ children: ['Plain text'] }),
    Text({ bold: true, children: ['bold'] }),
    Text({ italic: true, children: ['italic'] }),
    Text({ underline: true, children: ['underline'] }),
    Text({ strikethrough: true, children: ['strikethrough'] }),
    Text({ dimColor: true, children: ['dimColor'] }),
    Text({ inverse: true, children: ['inverse'] }),
    Text({ color: 'red', children: ["color: 'red'"] }),
    Text({ backgroundColor: 'blue', children: ["backgroundColor: 'blue'"] }),
  ],
})
각 줄이 해당 스타일 이름으로 된 아홉 줄의 텍스트가 있는 창: plain, bold, italic, underline, strikethrough, 회색의 dimColor, inverse, color red, backgroundColor blue. 각 줄이 해당 스타일 이름으로 된 아홉 줄의 텍스트가 있는 창: plain, bold, italic, underline, strikethrough, 회색의 dimColor, inverse, color red, backgroundColor blue.

dimColor는 텍스트를 회색으로 그립니다. backgroundColor는 텍스트 너비만큼만 채웁니다.

`Markdown`

Markdown은 Claude의 응답과 같은 방식으로 텍스트 서식을 지정합니다. 콘텐츠는 children이 아닌 text로 전달하십시오.

Markdown({
  text: '## Release notes\n\nThis build has **two** fixes and one `flag`:\n\n- Faster start\n- Fewer prompts\n\n> Quoted text',
})
굵은 제목 Release notes, 굵은 단어 하나와 색이 입혀진 코드 단어 하나가 있는 문장, 두 항목으로 된 목록, 왼쪽에 막대가 있는 기울임꼴 인용문이 있는 창. 굵은 제목 Release notes, 굵은 단어 하나와 색이 입혀진 코드 단어 하나가 있는 문장, 두 항목으로 된 목록, 왼쪽에 막대가 있는 기울임꼴 인용문이 있는 창.

제목은 # 기호 없이 굵게 그려집니다. 인라인 코드는 백틱 없이 색으로 그려집니다. 인용문은 왼쪽에 막대가 있는 기울임꼴로 그려집니다.

Link는 레이블과 그 뒤에 URL을 그립니다.

Link({ href: 'https://code.claude.com/docs', label: 'Claude Code docs' })
한 줄이 있는 창: 레이블 Claude Code docs와 그 뒤에 회색으로 표시된 URL. 한 줄이 있는 창: 레이블 Claude Code docs와 그 뒤에 회색으로 표시된 URL.

터미널은 레이블 뒤에 URL을 텍스트로 그립니다. 클릭으로 URL이 열리는지 여부는 사용자의 터미널에 따라 다릅니다.

코드 및 변경 사항 표시하기

Code는 Claude Code 자체의 구문 색상으로 소스 텍스트를 그리거나 diff를 그립니다.

`Code`

language를 지정하거나, Claude Code가 언어를 추론할 수 있도록 path를 전달하십시오. startLine을 지정하면 해당 번호부터 줄 번호가 매겨집니다.

Code({
  language: 'javascript',
  startLine: 1,
  source: "const name = 'mods'\nconsole.log('hello ' + name)",
})
구문 색상이 적용된 두 줄의 번호 매겨진 JavaScript가 있는 창. 구문 색상이 적용된 두 줄의 번호 매겨진 JavaScript가 있는 창.

색상은 사용자의 테마를 따릅니다.

diff로 표시하는 `Code`

format: 'diff'를 지정하면 source는 하나 이상의 unified diff 헝크가 됩니다.

Code({
  format: 'diff',
  source: '@@ -1,3 +1,3 @@\n # Mods\n-A mod is a plugin.\n+A mod is a plugin that runs code.\n Read on.',
})
네 줄짜리 diff가 있는 창. 삭제된 줄은 빨간색, 추가된 줄은 초록색 음영으로 표시되며 각각 줄 번호가 있습니다. 추가된 줄에서 that runs code라는 단어는 더 진한 음영으로 표시됩니다. 네 줄짜리 diff가 있는 창. 삭제된 줄은 빨간색, 추가된 줄은 초록색 음영으로 표시되며 각각 줄 번호가 있습니다. 추가된 줄에서 that runs code라는 단어는 더 진한 음영으로 표시됩니다.

Claude Code는 @@ 줄 대신 줄 번호를 그립니다. 삭제된 줄과 추가된 줄이 비슷한 경우, 변경된 단어는 더 진한 음영으로 표시됩니다.

요소 배치하기

`Box`

Box는 내부 요소를 행 또는 열로 배치하며 테두리를 그릴 수 있습니다. 이 샘플은 단어 한 행을 테두리가 있는 박스 위에 배치합니다.

Box({
  flexDirection: 'column',
  gap: 1,
  children: [
    Box({
      flexDirection: 'row',
      columnGap: 4,
      children: [Text({ children: ['a row'] }), Text({ children: ['of three'] }), Text({ children: ['items'] })],
    }),
    Box({
      borderStyle: 'round',
      paddingX: 1,
      children: [Text({ children: ["borderStyle: 'round'"] })],
    }),
  ],
})
네 열 간격으로 한 행에 놓인 세 단어, 빈 행, 그리고 한 줄의 텍스트를 둘러싼 둥근 테두리가 있는 창. 테두리는 창의 전체 너비에 걸쳐 있습니다. 네 열 간격으로 한 행에 놓인 세 단어, 빈 행, 그리고 한 줄의 텍스트를 둘러싼 둥근 테두리가 있는 창. 테두리는 창의 전체 너비에 걸쳐 있습니다.

테두리는 창의 너비만큼 늘어납니다.

입력 받기

Button, Input, Select는 컨트롤입니다. 사용자는 Tab으로 컨트롤 사이를 이동하고 포커스가 있는 컨트롤을 사용합니다. 어떤 키가 컨트롤에 전달되는지는 키보드 포커스 및 단축키에서 설명합니다.

focus: true로 창을 열면 창에 키보드 포커스가 주어집니다. 입력한 글자는 Input에 포커스가 있을 때 전달되므로, 창이 열리자마자 입력을 받아야 하는 필드에는 autoFocus: true를 추가하십시오.

`Button`

버튼은 onPress를 실행합니다. 이 샘플은 기본 형태, 단축키가 있는 plain 버튼, 흐리게 표시된 버튼을 보여 줍니다.

Box({
  flexDirection: 'column',
  children: [
    Button({ key: 'save', label: 'Save', onPress: noop }),
    Button({ key: 'next', label: 'Next', hotkey: 'n', plain: true, onPress: noop }),
    Button({ key: 'skip', label: 'Skip', dimColor: true, onPress: noop }),
  ],
})
한 줄에 하나씩 세 개의 버튼이 있는 창: 대괄호로 묶인 Save, 대괄호 없이 n이 색으로 표시된 n: Next, 대괄호로 묶인 회색 Skip. 한 줄에 하나씩 세 개의 버튼이 있는 창: 대괄호로 묶인 Save, 대괄호 없이 n이 색으로 표시된 n: Next, 대괄호로 묶인 회색 Skip.

포커스가 있는 버튼은 반전 표시로 그려집니다. 다음은 사용자가 Tab을 두 번 누른 상태입니다.

같은 세 개의 버튼 중 두 번째 버튼 n: Next가 반전 표시로 그려진 모습. 같은 세 개의 버튼 중 두 번째 버튼 n: Next가 반전 표시로 그려진 모습.

`Input`

Input은 사용자가 Enter를 누르면 onSubmit을 실행하는 한 줄 텍스트 필드입니다.

Input({
  key: 'title',
  label: 'Title',
  placeholder: 'Type a title and press Enter',
  value: '',
  submitLabel: 'save',
  onSubmit: noop,
})

포커스가 없으면 필드에 레이블과 플레이스홀더가 표시됩니다.

한 줄이 있는 창: 레이블 Title과 그 뒤에 회색으로 표시된 플레이스홀더 Type a title and press Enter. 한 줄이 있는 창: 레이블 Title과 그 뒤에 회색으로 표시된 플레이스홀더 Type a title and press Enter.

포커스가 있으면 레이블이 굵게 바뀌고 커서가 나타나며, ⏎ 뒤에 submitLabel이 표시됩니다.

레이블이 굵게 표시되고, 플레이스홀더의 첫 글자에 블록 커서가 있으며, 리턴 기호 뒤에 save라는 단어가 있는 같은 필드. 레이블이 굵게 표시되고, 플레이스홀더의 첫 글자에 블록 커서가 있으며, 리턴 기호 뒤에 save라는 단어가 있는 같은 필드.

입력을 시작하면 플레이스홀더가 대체됩니다.

입력된 글자 Rel과 그 뒤에 리턴 기호 및 save라는 단어가 있는 같은 필드. 입력된 글자 Rel과 그 뒤에 리턴 기호 및 save라는 단어가 있는 같은 필드.

`Select`

Select를 사용하면 사용자가 여러 옵션 중 하나를 선택할 수 있으며, 선택한 옵션의 value로 onSelect를 실행합니다.

Select({
  key: 'format',
  label: 'Format',
  value: picked,
  options: [
    { value: 'md', label: 'Markdown' },
    { value: 'html', label: 'HTML' },
    { value: 'txt', label: 'Plain text' },
  ],
  onSelect: (value) => {
    picked = value
  },
})

닫힌 상태에서는 레이블과 현재 옵션이 표시됩니다.

한 줄이 있는 창: 레이블 Format, 현재 옵션 Markdown, 작은 아래쪽 화살표. 한 줄이 있는 창: 레이블 Format, 현재 옵션 Markdown, 작은 아래쪽 화살표.

열린 상태에서는 옵션 목록이 표시되고 그중 하나가 강조됩니다.

레이블 아래에 세 개의 옵션이 나열된 열린 선택기. 두 번째 옵션 HTML이 반전 표시로 그려져 있습니다. 레이블 아래에 세 개의 옵션이 나열된 열린 선택기. 두 번째 옵션 HTML이 반전 표시로 그려져 있습니다.

사용자가 옵션을 선택하면 목록이 닫힙니다.

다시 닫힌 선택기로, 이제 현재 옵션으로 HTML이 표시됩니다. 다시 닫힌 선택기로, 이제 현재 옵션으로 HTML이 표시됩니다.

그림 그리기

`Raster`

Raster는 색이 입혀진 문자 셀의 격자로, 히트맵, 스파크라인, 게임 보드 등에 사용합니다. 터미널이 이를 그립니다. 이 샘플은 시작 모듈의 cellsOf 함수를 사용하며, 이 함수는 셀을 Raster가 받는 문자열로 압축합니다. 자세한 설명은 색이 입혀진 셀 격자 그리기를 참조하십시오.

Raster({
  key: 'grid',
  columns: 3,
  rows: 2,
  cells: cellsOf([
    [['█', 0x2e7d32], ['█', 0xf9a825], ['█', 0xc62828]],
    [['█', 0x2e7d32], ['█', 0x2e7d32], ['█', 0xf9a825]],
  ]),
})
세 개씩 두 행으로 된 작은 색 블록 격자가 있는 창: 초록, 황색, 빨강, 그다음 초록, 초록, 황색. 세 개씩 두 행으로 된 작은 색 블록 격자가 있는 창: 초록, 황색, 빨강, 그다음 초록, 초록, 황색.

Raster는 각 색상을 더 작은 팔레트로 반올림하므로 0x2e7d32는 #337733으로 그려집니다.

`Svg`

Svg는 Desktop 앱에서 SVG 문서를 그립니다.

Svg({
  alt: 'Three bars of rising height',
  width: 120,
  height: 60,
  source:
    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 60"><rect x="10" y="40" width="20" height="20" fill="#2e7d32"/><rect x="50" y="25" width="20" height="35" fill="#f9a825"/><rect x="90" y="5" width="20" height="55" fill="#c62828"/></svg>',
})

터미널에서는 Svg만 반환하는 창이 빈 상태로 열립니다. 터미널에서 다른 것을 그리려면 e.surface를 확인하고 다른 트리를 반환하십시오.

`Image` 및 `Client`

두 요소는 여기에 샘플이 없습니다. Image는 터미널에서 PNG 또는 원시 픽셀을 그립니다. Client는 애니메이션과 포인터 입력을 위해 사용자가 작성한 두 번째 파일이 그리는 영역입니다. 해당 props는 요소 레퍼런스에 나열되어 있습니다.

모드가 그릴 수 있는 위치 확인하기

모든 샘플은 창에 그립니다. 모드는 다른 위치에도 그릴 수 있으며, Claude Code를 호출해 무언가를 대신 표시하게 할 수도 있습니다.

다음 단계