WhipWhip

챗으로 만들기

아래 글 전체를 복사해 평소 쓰는 챗(ChatGPT·Claude·Gemini 등)에 붙여넣어 보내세요. 아래 칸에 원하는 기능을 적어 두면 복사본 맨 끝(내 요청)에 같이 들어갑니다. 챗이 휩셋 JSON을 돌려주면 그대로 복사해 확장 패널 휩셋 선택 드롭다운의 📥 가져오기에 붙여넣으면 됩니다. 글에 적힌 <<var.key>>는 패널 빌더에선 {{var.key}}로 보입니다. 고칠 곳이 있으면 패널이 목록을 주고, 그 목록을 챗에 다시 붙여넣으면 됩니다.

JSON 스키마 · llms-full.txt

지금부터 휩휩(WhipWhip)의 휩셋을 설계해서 JSON 객체 하나로 써 주세요. 이 안내를 끝까지 먼저 읽으세요. 맨 끝 "내 요청" 아래에 제가 원하는 것을 적습니다. 꼭 필요한 정보가 빠졌을 때만 짧은 질문 하나를 하고, 그렇지 않으면 바로 JSON으로 답해 주세요.

휩휩이 무엇인가

휩휩은 브라우저 확장입니다. 제가 쓰는 웹챗(ChatGPT·Claude·Gemini·Grok·Perplexity) 위에 패널을 띄우고, 저장해 둔 절차를 그 챗 안에서 대신 실행합니다. 입력창에 글을 쓰고, 보내고, 답을 기다리고, 답을 읽어 일부를 저장하고, 결과를 보여 줍니다.

휩휩은 API를 부르지 않습니다. 모든 일이 실제 챗 페이지에서, 제가 직접 입력한 것과 똑같이 일어납니다. 그래서 휩은 사람이 그 페이지에서 할 수 있는 일을 카드 하나씩 할 수 있을 뿐입니다.

카드가 어떻게 이어지나

챗과 대화하기. prompt_write는 입력창에 글을 넣습니다(보내지는 않습니다). submit은 그 글을 보내고 답이 다 나올 때까지 기다립니다. submit 뒤에는 답을 쓸 수 있습니다.

답 남기기. var_save에 "valueSource": "var.last.assistant"를 주면 가장 최근 답 전체를 변수에 저장합니다. 결과를 남기는 기본 방법입니다. ask_and_extract는 답에서 짧은 이름 붙은 값(제목, 점수, 분류)을 뽑을 때 씁니다 — 프롬프트 끝에 값을 태그로 덧붙이라는 지시를 더하고 그 값을 읽습니다. 긴 답 전체를 담는 데 쓰지 마세요. extract_response는 이 대화의 마지막 답을 별도 탭에서 정해 둔 JSON 모양으로 정리해 옵니다. 드물게만 쓰세요. validate는 최근 답이 형식(JSON, 정규식, 비어 있지 않음)을 지켰는지 보고, 아니면 챗에게 다시 요청합니다.

저에게 묻기. 두 가지입니다.

  1. user_input 변수를 프롬프트에 토큰으로 넣습니다. 휩이 실행되기 전에 휩휩이 그 휩에 필요한 user_input 변수마다 작은 입력 폼을 보여 줍니다. 기본이고 보통 가장 좋습니다.
  2. input_prompt는 실행 도중, 그 카드가 있는 자리에서 묻습니다. 그 순간에만 의미가 있는 질문 (예: 답을 읽은 뒤 "이 스크랩 이름은?")이거나, "alwaysAsk": true로 이미 채워진 값을 확인받을 때 씁니다.

choice_prompt는 선택지에서 고르게 합니다. 고정 목록(options에 한 줄에 하나)이나 목록 변수의 항목에서 고를 수 있습니다.

결과 보여 주기. show_result_modal은 변수로 만든 글을 창으로 띄웁니다. 제가 복사할 것 같으면 "copyButton": "copy_body"를 주세요.

대화 옮겨 다니기. new_chat은 같은 서비스에서 새 대화를 엽니다. open_service는 다른 서비스로 갑니다. open_url은 주소를 엽니다. tag_current_chat은 실행이 서 있는 대화에 역할을 붙입니다. go_to_role은 그 역할을 가진 대화로 실행을 옮기고, "closeCurrent": "true"면 떠나는 탭을 닫습니다. 역할은 어떤 휩이 go_to_role로 가기 전에 먼저 tag_current_chat으로 붙어 있어야 합니다.

역할 대화는 휩이 엽니다. 탭마다 역할을 미리 앉히는 "시작" 휩을 두지 마세요. 역할이 필요한 휩이 그 자리에서 대화를 엽니다: 지금 대화에 역할을 붙이고(tag_current_chat) → new_chat("openMode": "new_tab") → 그 대화에서 할 일을 역할 설명과 함께 한 메시지로 보내고(prompt_write → submit) → 새 대화에 역할을 붙입니다(tag_current_chat).

휩이 어느 목록에 서나. scopeTags가 없는 휩은 메인 목록(태그 없는 대화)에 뜹니다 — 셋의 입구와 대화를 여는 휩이 여기 섭니다. scopeTags: ["critic"]인 휩은 그 역할 대화에서만 뜹니다 — 그 대화의 답을 읽어 무언가 하는 휩이 여기 섭니다.

셋의 모양은 넷 중 하나입니다.

목록. "valueType": "array" 변수는 레코드 목록을 담습니다. append_item은 레코드를 더하고 (fields는 이름/값 쌍 목록, autoId는 레코드마다 id를 붙입니다), upsert_item은 id로 더하거나 바꾸고, patch_item은 레코드 하나의 일부 필드를 바꾸고, remove_item은 하나를 지웁니다. derive_index는 목록을 글로 바꿔(항목마다 한 줄, <<item.field>> 토큰이 든 템플릿으로) 다른 변수에 저장합니다. 그래야 프롬프트나 결과 창이 그 목록을 보여 줄 수 있습니다. 여러 번 실행에 걸쳐 무언가를 기억하는 셋(노트, 라이브러리, 기록)은 목록으로 만듭니다.

변수.

토큰

카드 글 안에서 변수는 **<<var.key>>**로 씁니다 — 양쪽에 꺾쇠 두 개씩입니다. 목록 템플릿 안에서는 <<item.field>>입니다. <<now>>는 오늘 날짜입니다. 중괄호로 토큰을 쓰지 마세요. <<…>>는 휩휩이 알아서 바꿉니다.

JSON 모양

{
  "format": "whipwhip.authoring/1",
  "name": "…",                       셋 이름, 제 언어로
  "description": "…",                선택, 셋이 하는 일과 쓰는 법
  "tags": [ { "name": "writer" } ],  역할. A–Z a–z 0–9 _ - 로 3–10자
  "variables": [ { "key": "…", "label": "…", "source": "…", "required": true } ],
  "whips": [
    {
      "label": "…",                  버튼 글, 짧게
      "description": "…",            선택
      "preflightStyle": "form",      선택: "form"(기본) 또는 "none"
      "scopeTags": [ "writer" ],     선택: 이 휩이 속한 역할 대화
      "actions": [ { "card": "prompt_write", "config": { "text": "…" } } ]
    }
  ]
}

id, usedVars, requiresVars, producesVars, askInline, 키, 서명, 버전은 쓰지 마세요. 휩휩이 채웁니다.

카드 레퍼런스

prompt_write

채팅창에 내용을 입력하거나 수정합니다.

submit

작성된 내용을 전송하고, 대기를 끄지 않았다면 AI의 응답을 기다립니다.

input_prompt

사용자에게 필요한 정보를 입력받습니다.

ask_and_extract

AI에게 묻고, 답에서 필요한 값을 골라 변수에 담습니다.

extract_response

이 대화의 마지막 AI 답을 정해 둔 JSON 모양으로 정리해 변수에 담습니다. 임시 탭에서 정리하며, ChatGPT 밖에선 그 대화가 기록에 남습니다.

validate

응답이 형식을 지켰는지 보고 아니면 다시 요구합니다. 형식만 봅니다 — 내용이 맞는지는 판정할 수 없습니다.

send_to_services

같은 글을 고른 AI들에 보냅니다(나머지는 뒤쪽 새 탭). 답은 기다려 모으거나, 태그만 붙이거나, 태그된 대화에서 읽습니다.

var_save

입력창 글, AI 답 같은 내용을 변수에 담아 둡니다.

var_flush

이 휩셋의 모든 변수 값을 비웁니다(변수 목록은 그대로). 모아 둔 목록도 비워지니 주의하세요.

설정 없음 — "config": {}.

append_item

목록 변수에 항목을 하나 더합니다 (예: 모은 메모 목록에 새 메모).

upsert_item

"id" 필드로 매칭해 배열 변수의 항목을 삽입하거나 갱신합니다.

patch_item

id로 매칭한 항목의 지정 필드만 수정하고 나머지 필드는 유지합니다 (예: 상태만 전환).

remove_item

"id"로 배열 변수의 항목을 제거합니다.

derive_index

배열 변수에서 항목당 한 줄씩 요약/인덱스 문자열을 만듭니다.

go_to_role

태그가 붙은 대화로 이동합니다.

go_to_start

휩을 누른 탭으로 돌아옵니다. 지금 탭을 닫을 수도 있어요 — 곁가지에서 묻고 돌아올 때 씁니다.

new_chat

현재 서비스에서 새 대화를 엽니다.

open_service

다른 AI 서비스로 전환합니다 (ChatGPT, Gemini, Claude…).

open_url

https:// 주소로 이동합니다.

tag_current_chat

현재 대화에 태그를 붙여 관리합니다.

choice_prompt

사용자에게 옵션 목록을 보여주고, 고른 값을 변수에 담습니다.

show_result_modal

변수에 저장된 값을 활용해 결과창을 띄웁니다.

import_whipset

변수에 든, 챗이 쓴 휩셋 JSON을 가져옵니다. 저장 전에 미리보기로 확인받습니다.

값 출처(var_save.valueSource)

builtin.date_today · builtin.date_iso · builtin.time_now · builtin.timestamp · builtin.day_of_week · builtin.page_url · builtin.page_title · builtin.page_domain · builtin.language · builtin.random_uuid · builtin.selection · composer · var.last.user · var.last.assistant

흔한 실수

예시

대화 하나: 초안을 다듬어 보여 주기

{
  "format": "whipwhip.authoring/1",
  "name": "초안 다듬기",
  "description": "거친 초안을 또렷하게 고쳐 쓰고 결과를 보여 줍니다.",
  "tags": [],
  "variables": [
    { "key": "draft", "label": "초안", "source": "user_input", "required": true },
    { "key": "polished", "label": "다듬은 글", "source": "set_by_action", "required": false }
  ],
  "whips": [
    {
      "label": "다듬기",
      "actions": [
        { "card": "prompt_write", "config": { "text": "아래 초안을 또렷하고 간결하게 고쳐 써 줘. 내 뜻과 말투는 지켜 줘. 고친 글만 답해.\n\n<<var.draft>>", "mode": "replace" } },
        { "card": "submit", "config": {} },
        { "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "polished" } },
        { "card": "show_result_modal", "config": { "title": "다듬은 글", "body": "<<var.polished>>", "copyButton": "copy_body" } }
      ]
    }
  ]
}

역할 둘: 내 대화의 답을 곁가지에서 검토받기

{
  "format": "whipwhip.authoring/1",
  "name": "검토받고 고치기",
  "description": "쓰던 대화에서 '이 답 검토받기'를 누르면 새 탭에서 검토자가 답합니다. 검토 대화에서 '검토 반영'을 누르면 원래 대화로 돌아와 고칩니다.",
  "tags": [ { "name": "author" }, { "name": "reviewer" } ],
  "variables": [
    { "key": "draft", "label": "원고", "source": "set_by_action", "required": false },
    { "key": "review", "label": "검토", "source": "set_by_action", "required": false }
  ],
  "whips": [
    {
      "label": "이 답 검토받기",
      "actions": [
        { "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "draft", "refuseIfEmpty": true } },
        { "card": "tag_current_chat", "config": { "tagName": "author" } },
        { "card": "new_chat", "config": { "isTemp": "false", "openMode": "new_tab" } },
        { "card": "prompt_write", "config": { "text": "이 대화에서 너는 까다로운 검토자야. 아래 원고의 약한 지점을 가장 약한 것부터 한 줄에 하나씩 짚어 줘. 고쳐 쓰지는 마.\n\n[원고]\n<<var.draft>>", "mode": "replace" } },
        { "card": "submit", "config": {} },
        { "card": "tag_current_chat", "config": { "tagName": "reviewer" } }
      ]
    },
    {
      "label": "검토 반영",
      "scopeTags": [ "reviewer" ],
      "actions": [
        { "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "review" } },
        { "card": "input_prompt", "config": { "title": "검토", "selectedVars": [ { "key": "review", "question": "이 검토로 고칠까요? 뺄 줄은 먼저 지우세요." } ], "alwaysAsk": true } },
        { "card": "go_to_role", "config": { "tagName": "author", "closeCurrent": "true" } },
        { "card": "prompt_write", "config": { "text": "이 검토를 반영해 방금 답을 고쳐 줘. 고친 전문만 답해.\n\n<<var.review>>", "mode": "replace" } },
        { "card": "submit", "config": {} }
      ]
    }
  ]
}

쌓이는 목록: 답 스크랩 노트

{
  "format": "whipwhip.authoring/1",
  "name": "답 스크랩 노트",
  "tags": [],
  "variables": [
    { "key": "clip", "label": "스크랩한 답", "source": "set_by_action", "required": false },
    { "key": "clip_title", "label": "제목", "source": "set_by_action", "required": false },
    { "key": "notes", "label": "노트", "source": "set_by_action", "valueType": "array", "required": false },
    { "key": "notes_index", "label": "노트 목록", "source": "set_by_action", "required": false },
    { "key": "notes_full", "label": "노트 전문", "source": "set_by_action", "required": false },
    { "key": "summary", "label": "요약", "source": "set_by_action", "required": false }
  ],
  "whips": [
    {
      "label": "이 답 저장",
      "actions": [
        { "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "clip" } },
        { "card": "input_prompt", "config": { "title": "이 답 저장", "selectedVars": [ { "key": "clip_title", "question": "짧은 제목을 붙여 주세요" } ], "inputStyle": "inline", "alwaysAsk": true } },
        { "card": "append_item", "config": { "key": "notes", "autoId": true, "idPrefix": "note-", "fields": [ { "name": "title", "value": "<<var.clip_title>>" }, { "name": "text", "value": "<<var.clip>>" }, { "name": "date", "value": "<<now>>" } ] } },
        { "card": "derive_index", "config": { "sourceKey": "notes", "key": "notes_index", "itemTemplate": "<<item.id>> — <<item.title>> (<<item.date>>)" } },
        { "card": "show_result_modal", "config": { "title": "노트", "body": "<<var.notes_index>>" } }
      ]
    },
    {
      "label": "노트 요약",
      "actions": [
        { "card": "derive_index", "config": { "sourceKey": "notes", "key": "notes_full", "itemTemplate": "### <<item.title>>\n<<item.text>>" } },
        { "card": "new_chat", "config": { "openMode": "current" } },
        { "card": "prompt_write", "config": { "text": "이 노트들에 공통으로 흐르는 것과 합치면 무엇이 되는지 정리해 줘.\n\n<<var.notes_full>>", "mode": "replace" } },
        { "card": "submit", "config": {} },
        { "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "summary" } },
        { "card": "show_result_modal", "config": { "title": "요약", "body": "<<var.summary>>", "copyButton": "copy_body" } }
      ]
    }
  ]
}

가벼운 휩셋: 어느 대화에서든 같은 문체

{
  "format": "whipwhip.authoring/1",
  "name": "글쓰기 도우미",
  "description": "문체를 한 번 정해 두면, 어느 대화에서든 버튼 하나로 다듬고 길이를 바꿉니다.",
  "tags": [],
  "variables": [
    { "key": "style", "label": "문체", "source": "user_input", "required": false, "scope": "set" },
    { "key": "length", "label": "길이", "source": "set_by_action", "required": false }
  ],
  "whips": [
    {
      "label": "문체 정하기",
      "preflightStyle": "none",
      "actions": [
        { "card": "input_prompt", "config": { "title": "문체", "selectedVars": [ { "key": "style", "question": "어떤 문체로 쓸까요? (예: 담백한 존댓말, 짧은 문장)" } ], "inputStyle": "inline", "alwaysAsk": true } },
        { "card": "prompt_write", "config": { "text": "이 대화에서 앞으로 쓰는 글은 이 문체로 써줘: <<var.style>>\n알겠으면 «확인»이라고만 답해줘.", "mode": "replace" } },
        { "card": "submit", "config": {} }
      ]
    },
    {
      "label": "다듬기",
      "preflightStyle": "none",
      "actions": [
        { "card": "input_prompt", "config": { "title": "문체", "selectedVars": [ { "key": "style", "question": "어떤 문체로 쓸까요? (예: 담백한 존댓말, 짧은 문장)" } ], "inputStyle": "inline" } },
        { "card": "prompt_write", "config": { "text": "방금 쓴 글을 다듬어줘. 뜻과 내용은 그대로 두고 어색한 문장·맞춤법·반복만 고쳐. 문체: <<var.style>>\n다듬은 글만 보여줘.", "mode": "replace" } },
        { "card": "submit", "config": {} }
      ]
    },
    {
      "label": "길이 조정",
      "preflightStyle": "none",
      "actions": [
        { "card": "input_prompt", "config": { "title": "문체", "selectedVars": [ { "key": "style", "question": "어떤 문체로 쓸까요? (예: 담백한 존댓말, 짧은 문장)" } ], "inputStyle": "inline" } },
        { "card": "choice_prompt", "config": { "label": "어느 쪽으로 바꿀까요?", "optionsSource": "static", "options": "더 짧게\n더 길게", "key": "length" } },
        { "card": "prompt_write", "config": { "text": "방금 쓴 글을 <<var.length>> 고쳐줘. 핵심 내용은 지키고, 문체: <<var.style>>\n고친 글만 보여줘.", "mode": "replace" } },
        { "card": "submit", "config": {} }
      ]
    }
  ]
}

출력 규칙

  1. 제가 어떤 휩을 어떤 순서로 누를지 먼저 생각하고, 동작하는 가장 작은 셋을 설계하세요.
  2. 이름·라벨·질문·프롬프트·결과 제목은 제가 요청을 쓴 언어로 쓰세요. 카드 이름, 필드 이름, 변수 키, 태그 이름은 이 안내에 적힌 그대로 둡니다.
  3. 휩셋 전체를 담은 JSON 코드블록 하나로 답하세요. 블록 뒤에 어떤 버튼부터 누르면 되는지 짧은 문장 두 개까지만 덧붙여도 됩니다.
  4. 제가 휩휩이 알려 준 고칠 곳 목록을 붙여넣으면, 전부 고쳐서 완전한 JSON을 다시 보내 주세요. 고친 부분만 보내지 마세요.

내 요청