rss2.pub

PyTorchKR - 최신 글

@discuss_pytorch_kr_lat_4uf2xvk@beta.rss2.pub

Fast Jev Compaction: 컨텍스트 정리 시, 불필요한 도구 호출 결과를 제외하는 Claude Code 플러그인

Fast Jev Compaction 소개

코딩 에이전트와 한 세션을 오래 이어 가면 주고받은 대화가 컨텍스트 창을 채웁니다. 이때 대부분의 도구는 오래된 대화를 언어 모델에 넘겨 요약문으로 바꿔 놓는데, 요약은 본질적으로 정보가 줄어드는 처리입니다. 나중에 다시 필요해지는 파일 경로, 정확한 오류 문구, 사용자가 걸어 둔 제약, 실행했던 명령어가 요약 과정에서 빠질 수 있습니다. 한 번 빠지고 나면 그런 내용이 원래 대화에 있었다는 사실조차 남지 않아서, 에이전트가 같은 파일을 다시 읽거나 이미 손대지 말라고 했던 경로를 건드리는 일이 생깁니다. 이번에 소개하는 fast-jev-compaction은 그 요약 단계를 생략하고, 오래된 도구 호출 가운데 더 이상 필요 없는 것만 골라 지우는 Claude Code 플러그인입니다.

fast-jev-compaction은 대화 내용을 다시 쓰지 않고 삭제만 합니다. 무엇을 지울지는 TypeSafe AI의 Jev ( Jev, 토큰 대신 확률적 결정을 내놓는 새로운 형태의 System One 모델 (feat. TypeSafe AI))에 맡기는데, Jev는 문장을 생성하는 대신 질문마다 확률을 돌려주는 System One 모델입니다. 플러그인은 도구 호출 하나마다 두 가지를 묻습니다. 이 호출이 기록에 남아야 하는지, 그리고 그 결과가 원문 그대로 남아야 하는지입니다. 질문을 던질 때는 대화 전체를 함께 보여주기 때문에, 오래된 호출 하나를 지울지 판단하는 근거에 그 뒤에 일어난 일까지 모두 들어갑니다. 사용자와 어시스턴트가 주고받은 텍스트는 이 과정에서 손대지 않고 원문 그대로, 순서 그대로 남습니다.

fast-jev-compaction의 저장소는 두 가지를 겸합니다. src/는 TypeScript로 작성한 npm 라이브러리이고, hooks/와 .claude-plugin/은 그 라이브러리를 호출해 Claude Code의 기본 압축 요약을 대체하는 플러그인입니다. 공개한 사람은 TypeSafe AI가 아니라 개인 개발자 tamara tran이며, 같은 저자가 Bash 출력이 모델에 닿기 전에 Jev로 줄이는 jev-pruner도 함께 내놓았습니다.

fast-jev-compaction과 Claude Code 기본 압축 요약의 차이

Claude Code의 기본 압축은 압축이 끝난 시점에 대화 요약문을 만들어 두고, 훅에 compact_summary 필드로 그 요약문을 넘깁니다(Claude Code 훅 레퍼런스). fast-jev-compaction은 같은 자리에서 요약문 대신 원래 메시지를 돌려주며, 두 방식이 다른 점은 다음과 같습니다:

구분 Claude Code 기본 압축 fast-jev-compaction 오래된 대화를 처리하는 방식 언어 모델이 요약문으로 다시 씀 원문을 그대로 두고 일부만 삭제 줄이기의 대상 오래된 대화 전체 도구 호출과 도구 결과만 사용자와 어시스턴트 텍스트 요약문에 흡수됨 손대지 않고 유지 남길지 정하는 주체 요약문을 만드는 언어 모델 Jev가 호출마다 돌려주는 두 확률 외부 API 키 필요 없음 TypeSafe API 키 필요 실패했을 때 해당 없음 Claude Code 기본 요약으로 되돌아감

표의 마지막 행이 이 플러그인의 안전장치입니다. Jev 요청이 실패하거나, 응답 형식이 깨지거나, 키를 찾지 못하거나, 대화 기록이 상태 예산에 들어가지 않거나, 줄어든 양이 minReductionRatio 기본값인 25%에 못 미치면 훅은 폴백을 기록하고 Claude Code의 기본 압축에 처리를 넘깁니다. 결과는 세션에 토스트로 뜨는데, 원래 기록이 기본 요약을 대신했을 때는 fast-jev-compaction: kept N/M messages, no summary (…)가, 되돌아갔을 때는 fallback to built-in summary (…)가 표시됩니다.

fast-jev-compaction을 사용하면 좋을 사용자

도구 호출이 많고 그 결과가 긴 세션을 오래 이어 가는 사람에게 fast-jev-compaction이 맞습니다. 큰 저장소를 훑거나 테스트와 빌드 로그를 반복해서 읽는 작업은 대화의 대부분이 도구 결과이고, 그중 상당수는 몇 턴만 지나면 다시 쓰이지 않습니다. 이런 세션에서는 지울 대상이 분명하고, 지우고 남은 부분이 요약문이 아니라 원문이라는 점이 곧 이득이 됩니다.

반대로 대화가 주로 텍스트로 이루어져 지울 도구 호출이 적은 세션에서는 fast-jev-compaction을 켜 둘 이유가 크지 않습니다. 텍스트 메시지는 애초에 삭제 후보가 아니어서, 줄어드는 양이 minReductionRatio에 못 미치면 결국 기본 요약으로 되돌아갑니다.

대화 전체가 외부로 전송되는 것이 문제가 되는 환경이라면 fast-jev-compaction은 선택지가 아닙니다. 압축할 때마다 도구 결과를 한 줄 메모로 바꾼 대화 전문이 TypeSafe의 System One 엔드포인트로 실려 나가고, 도구 입력과 사용자 프롬프트는 내용이 그대로 포함됩니다. TypeSafe API 키를 발급받을 수 없는 경우에도 마찬가지로 쓸 수 없습니다.

fast-jev-compaction의 동작 원리

첫 단계는 짝짓기와 고정입니다. fast-jev-compaction은 모든 tool_use 블록을 tool_use_id로 해당 tool_result와 짝지어 하나의 호출 단위로 묶고, 결과가 아직 없는 호출은 후보에서 뺍니다. 여기에 더해 첫 번째 메시지와 가장 최근 preserveRecentMessages개(기본값 6) 메시지에 속한 호출은 고정되어 어떤 경우에도 건드리지 않습니다. preserveRecentMessages를 0으로 낮추더라도 첫 번째 메시지는 언제나 남습니다.

두 번째 단계에서 Jev에 보낼 상태를 만듭니다. 상태는 지금까지의 대화 전체를 오래된 것부터 담되, 모든 도구 결과를 ok, 4213 chars (omitted) 같은 짧은 메모로 바꾼 형태입니다. 도구 입력과 텍스트는 그대로 들어가고 요약되는 것은 없습니다. 함께 보내는 goal 필드에는 진행 중인 작업 설명이 들어가며, 값을 주지 않으면 최근 사용자 프롬프트 세 개가 쓰입니다.

세 번째 단계가 질문입니다. 고정되지 않은 호출마다 Noul 질문 두 개가 만들어집니다. Noul은 Jev가 제공하는 세 가지 질문 유형 중 하나로, 진술 하나가 참인지를 0에서 1 사이 값으로 돌려줍니다. 첫 번째 질문은 그 호출이 이루어졌다는 사실과 입력값이 앞으로의 작업에 여전히 중요한지를 묻고, 두 번째 질문은 그 결과의 내용이 여전히 필요하며 도구를 다시 실행하는 것으로는 대신할 수 없는지를 묻습니다. 질문은 상태와 합쳐 maxRequestTokens(기본값 30000) 안에 들어가도록 여러 요청으로 쪼개지고, 같은 상태가 매 요청에 함께 실려 나가며, 요청들은 동시에 실행된 뒤 답이 합쳐집니다.

마지막 단계에서 두 확률을 keepThreshold(기본값 0.5)와 견주어 호출마다 처리 방향을 정합니다:

조건 처리 keepResult ≥ 임계값 호출과 결과를 모두 유지 keepCall ≥ 임계값 호출은 유지하고, 결과는 앞 truncateHeadChars 글자(기본값 300)와 한 줄 안내만 남기고 잘라냄 둘 다 임계값 미만 호출과 결과를 함께 삭제

잘라낸 결과 자리에는 [fast-jev-compaction truncated N chars of this tool result; re-run the tool if needed]라는 안내가 붙어, 몇 글자가 잘렸는지와 필요하면 도구를 다시 실행하라는 지시가 함께 남습니다. 결정을 반영해 대화를 다시 조립할 때는 내용이 전부 없어진 메시지를 통째로 제거하고, 손대지 않은 메시지는 원래 객체를 그대로 돌려주며, 호출이 사라진 자리에 결과만 남는 상태는 만들지 않습니다.

fast-jev-compaction이 대화 상태를 줄이는 단계

Jev에 보내는 상태에는 maxStateTokens(기본값 25000)라는 상한이 있습니다. 대화가 이 상한을 넘으면 fast-jev-compaction은 다음 단계를 순서대로 적용하며, 각 단계는 직전 단계로도 부족했을 때만 실행됩니다:

  1. 도구 입력을 200자로, 그래도 부족하면 60자로 더 자릅니다. 기본 상태에서 입력은 이미 1000자로 잘려 있습니다.
  2. 긴 텍스트를 앞 400자와 뒤 150자만 남기고 줄입니다. 고정되지 않은 오래된 메시지부터 처리합니다.
  3. 오래된 비고정 메시지를 [… N chars omitted …] 메모 한 줄로 접습니다.
  4. 오래된 도구 호출을 t12 Read file_path=src/a.ts → ok 480ch 형태의 한 줄로 바꿉니다.
  5. 호출이 없는 오래된 메시지를 상태에서 제외합니다.
  6. 호출만 있는 오래된 메시지가 연달아 있으면 하나로 합칩니다.

여섯 단계를 다 거치고도 상한에 들어가지 않으면 압축은 예외를 던지고, 그 뒤 처리는 호출자가 결정합니다. 플러그인으로 쓸 때는 이 예외도 기본 요약으로 되돌아가는 경로로 이어집니다.

fast-jev-compaction은 토큰을 셀 때 토크나이저를 쓰지 않고 문자 구성으로 추정하는데, 알파벳 낱말은 6자당 1토큰, 숫자는 한 글자당 0.5토큰, 나머지 기호는 하나당 0.9토큰으로 계산합니다. 저자는 실제 Jev가 보고한 사용량보다 2%에서 18% 높게 나오도록 이 계수를 맞췄다고 src/state.ts의 주석에 적어 두었습니다. 단순히 글자 수를 일정 비율로 나누는 방식은 JSON이 많은 상태에서 실제보다 최대 40% 적게 세기 때문에, 일부러 넉넉하게 잡는 쪽을 골랐다는 설명입니다.

fast-jev-compaction이 밝힌 한계

저자는 한계를 네 가지로 정리해 두었습니다. 첫째, 후보가 되는 것은 도구 호출과 결과뿐이고 텍스트 메시지는 출력에서 제거되거나 짧아지지 않습니다. 텍스트가 줄어드는 것은 Jev가 보는 상태 안에서일 뿐입니다. 둘째, 토큰 크기는 토크나이저가 아니라 문자 수에서 나온 추정치입니다. 셋째, 보정은 요청 단위로 이루어지므로 확률값 하나가 그 결과를 지워도 안전하다는 증명은 되지 못하며, 대신 어시스턴트가 언제든 도구를 다시 실행할 수 있다는 점이 안전장치가 됩니다. 넷째, 전체 상태가 매 요청에 반복되기 때문에 상태 상한에 가까운 대화 기록은 질문 몇 개마다 요청 하나씩을 쓰게 됩니다.

여기에 저장소 밖에서 확인되는 한계가 하나 더 있습니다. 이 플러그인이 활용하는 함수 훅(function hook)은 Claude Code 2.1.274 이상에서 쓸 수 있는 얼리 액세스 기능이고, 공개된 훅 레퍼런스와 플러그인 레퍼런스에는 아직 함수 훅도, 이 플러그인이 쓰는 session.compact와 turn.complete 이벤트도 실려 있지 않습니다. 공개 문서에 적힌 hooks/hooks.json도 이벤트 매처와 동작을 담은 JSON 설정인데, 이 저장소의 같은 파일은 {"modules": ["./fast-jev.ts"]} 한 줄로 TypeScript 모듈을 가리킵니다. 저자도 함수 훅이 릴리스 사이에 바뀔 수 있다고 적으면서, types/claude-code.d.ts의 타입 선언을 Claude Code 업그레이드 후에 다시 생성해 검토하라고 안내합니다.

fast-jev-compaction 설치와 사용

함수 훅은 기본적으로 꺼져 있으므로, Claude Code가 실행되는 곳의 설정에 옵트인 플래그를 먼저 넣어야 합니다. ~/.claude/settings.json에 넣는다면 다음과 같습니다:

{ "env": { "CLAUDE_CODE_ENABLE_FUNCTION_HOOKS": "1", "TYPESAFE_API_KEY": "<your key>" } }

그 다음 저장소를 플러그인 마켓플레이스로 추가하고 플러그인을 설치합니다. 셸에서 실행해도 되고 세션 안에서 슬래시 명령으로 실행해도 됩니다:

claude plugin marketplace add tamaratran/fast-jev-compaction
claude plugin install fast-jev-compaction@fast-jev-compaction

설치 과정에서 API 키와 임계값 같은 플러그인 옵션을 묻는데, 기본값으로 두면 환경 변수의 TYPESAFE_API_KEY를 씁니다. 설치 후 Claude Code를 다시 시작하거나 /reload-plugins를 실행하면 그때부터 /compact와 자동 압축이 Jev를 거칩니다. 훅은 줄어든 비율과 사유별 개수, 상태 크기, 요청 수를 로그에 남기고 호출마다 두 확률을 담은 decisions: 줄도 함께 기록하므로, keepThreshold를 조정할 때 그 값을 근거로 삼을 수 있습니다. 저장소를 내려받아 바로 시험해 보려면 저장소 루트에서 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude --plugin-dir .을 실행하면 되고, 마켓플레이스가 저장소의 .claude-plugin/marketplace.json 자체라 따로 배포하는 단계는 없습니다. TypeSafe 키 없이 동작만 먼저 보고 싶다면 demo/JevDemo를 demo/JevDemo/build.sh로 빌드해 실행할 수 있는데, 이 macOS 앱은 미리 준비한 대화 기록을 각색해 보여줄 뿐 실제로 API를 호출하지는 않습니다.

플러그인이 받는 설정값은 .claude-plugin/plugin.json에 선언되어 있습니다:

옵션 기본값 설명 apiKey (없음) TypeSafe API 키, 비워 두면 TYPESAFE_API_KEY 사용 keepThreshold 0.5 호출이나 결과가 남기 위한 최소 확률 preserveRecentMessages 6 압축에서 고정하는 최신 메시지 개수 compactAtPercent 60 이 컨텍스트 비율에 닿으면 압축을 요청 minReductionRatio 0.25 이만큼 줄지 않으면 기본 요약으로 넘김 maxStateTokens 25000 상태의 추정 토큰 예산 maxRequestTokens 30000 상태와 질문 한 묶음의 추정 토큰 예산 truncateHeadChars 300 버려지는 결과에서 남길 앞부분 글자 수 model jev-latest Jev 모델 이름

이 가운데 compactAtPercent는 플러그인에만 있는 값입니다. turn.complete 훅이 매 턴 끝에서 컨텍스트 사용률을 보고 이 비율에 닿으면 압축을 스스로 요청하므로, 컨텍스트가 가득 차기를 기다리지 않고 60% 지점에서 미리 정리하는 동작이 기본값이 됩니다.

라이브러리로 쓸 때는 compactMessages 하나로 시작할 수 있습니다. 저장소가 제시하는 최소 예시는 다음과 같습니다:

import { compactMessages, reductionRatio, type Message } from 'fast-jev-compaction';

Fast Jev Compaction: 컨텍스트 정리 시, 불필요한 도구 호출 결과를 제외하는 Claude Code 플러그인

Fast Jev Compaction 소개

코딩 에이전트와 한 세션을 오래 이어 가면 주고받은 대화가 컨텍스트 창을 채웁니다. 이때 대부분의 도구는 오래된 대화를 언어 모델에 넘겨 요약문으로 바꿔 놓는데, 요약은 본질적으로 정보가 줄어드는 처리입니다. 나중에 다시 필요해지는 파일 경로, 정확한 오류 문구, 사용자가 걸어 둔 제약, 실행했던 명령어가 요약 과정에서 빠질 수 있습니다. 한 번 빠지고 나면 그런 내용이 원래 대화에 있었다는 사실조차 남지 않아서, 에이전트가 같은 파일을 다시 읽거나 이미 손대지 말라고 했던 경로를 건드리는 일이 생깁니다. 이번에 소개하는 fast-jev-compaction은 그 요약 단계를 생략하고, 오래된 도구 호출 가운데 더 이상 필요 없는 것만 골라 지우는 Claude Code 플러그인입니다.

fast-jev-compaction은 대화 내용을 다시 쓰지 않고 삭제만 합니다. 무엇을 지울지는 TypeSafe AI의 Jev ( Jev, 토큰 대신 확률적 결정을 내놓는 새로운 형태의 System One 모델 (feat. TypeSafe AI))에 맡기는데, Jev는 문장을 생성하는 대신 질문마다 확률을 돌려주는 System One 모델입니다. 플러그인은 도구 호출 하나마다 두 가지를 묻습니다. 이 호출이 기록에 남아야 하는지, 그리고 그 결과가 원문 그대로 남아야 하는지입니다. 질문을 던질 때는 대화 전체를 함께 보여주기 때문에, 오래된 호출 하나를 지울지 판단하는 근거에 그 뒤에 일어난 일까지 모두 들어갑니다. 사용자와 어시스턴트가 주고받은 텍스트는 이 과정에서 손대지 않고 원문 그대로, 순서 그대로 남습니다.

fast-jev-compaction의 저장소는 두 가지를 겸합니다. src/는 TypeScript로 작성한 npm 라이브러리이고, hooks/와 .claude-plugin/은 그 라이브러리를 호출해 Claude Code의 기본 압축 요약을 대체하는 플러그인입니다. 공개한 사람은 TypeSafe AI가 아니라 개인 개발자 tamara tran이며, 같은 저자가 Bash 출력이 모델에 닿기 전에 Jev로 줄이는 jev-pruner도 함께 내놓았습니다.

fast-jev-compaction과 Claude Code 기본 압축 요약의 차이

Claude Code의 기본 압축은 압축이 끝난 시점에 대화 요약문을 만들어 두고, 훅에 compact_summary 필드로 그 요약문을 넘깁니다(Claude Code 훅 레퍼런스). fast-jev-compaction은 같은 자리에서 요약문 대신 원래 메시지를 돌려주며, 두 방식이 다른 점은 다음과 같습니다:

구분 Claude Code 기본 압축 fast-jev-compaction 오래된 대화를 처리하는 방식 언어 모델이 요약문으로 다시 씀 원문을 그대로 두고 일부만 삭제 줄이기의 대상 오래된 대화 전체 도구 호출과 도구 결과만 사용자와 어시스턴트 텍스트 요약문에 흡수됨 손대지 않고 유지 남길지 정하는 주체 요약문을 만드는 언어 모델 Jev가 호출마다 돌려주는 두 확률 외부 API 키 필요 없음 TypeSafe API 키 필요 실패했을 때 해당 없음 Claude Code 기본 요약으로 되돌아감

표의 마지막 행이 이 플러그인의 안전장치입니다. Jev 요청이 실패하거나, 응답 형식이 깨지거나, 키를 찾지 못하거나, 대화 기록이 상태 예산에 들어가지 않거나, 줄어든 양이 minReductionRatio 기본값인 25%에 못 미치면 훅은 폴백을 기록하고 Claude Code의 기본 압축에 처리를 넘깁니다. 결과는 세션에 토스트로 뜨는데, 원래 기록이 기본 요약을 대신했을 때는 fast-jev-compaction: kept N/M messages, no summary (…)가, 되돌아갔을 때는 fallback to built-in summary (…)가 표시됩니다.

fast-jev-compaction을 사용하면 좋을 사용자

도구 호출이 많고 그 결과가 긴 세션을 오래 이어 가는 사람에게 fast-jev-compaction이 맞습니다. 큰 저장소를 훑거나 테스트와 빌드 로그를 반복해서 읽는 작업은 대화의 대부분이 도구 결과이고, 그중 상당수는 몇 턴만 지나면 다시 쓰이지 않습니다. 이런 세션에서는 지울 대상이 분명하고, 지우고 남은 부분이 요약문이 아니라 원문이라는 점이 곧 이득이 됩니다.

반대로 대화가 주로 텍스트로 이루어져 지울 도구 호출이 적은 세션에서는 fast-jev-compaction을 켜 둘 이유가 크지 않습니다. 텍스트 메시지는 애초에 삭제 후보가 아니어서, 줄어드는 양이 minReductionRatio에 못 미치면 결국 기본 요약으로 되돌아갑니다.

대화 전체가 외부로 전송되는 것이 문제가 되는 환경이라면 fast-jev-compaction은 선택지가 아닙니다. 압축할 때마다 도구 결과를 한 줄 메모로 바꾼 대화 전문이 TypeSafe의 System One 엔드포인트로 실려 나가고, 도구 입력과 사용자 프롬프트는 내용이 그대로 포함됩니다. TypeSafe API 키를 발급받을 수 없는 경우에도 마찬가지로 쓸 수 없습니다.

fast-jev-compaction의 동작 원리

첫 단계는 짝짓기와 고정입니다. fast-jev-compaction은 모든 tool_use 블록을 tool_use_id로 해당 tool_result와 짝지어 하나의 호출 단위로 묶고, 결과가 아직 없는 호출은 후보에서 뺍니다. 여기에 더해 첫 번째 메시지와 가장 최근 preserveRecentMessages개(기본값 6) 메시지에 속한 호출은 고정되어 어떤 경우에도 건드리지 않습니다. preserveRecentMessages를 0으로 낮추더라도 첫 번째 메시지는 언제나 남습니다.

두 번째 단계에서 Jev에 보낼 상태를 만듭니다. 상태는 지금까지의 대화 전체를 오래된 것부터 담되, 모든 도구 결과를 ok, 4213 chars (omitted) 같은 짧은 메모로 바꾼 형태입니다. 도구 입력과 텍스트는 그대로 들어가고 요약되는 것은 없습니다. 함께 보내는 goal 필드에는 진행 중인 작업 설명이 들어가며, 값을 주지 않으면 최근 사용자 프롬프트 세 개가 쓰입니다.

세 번째 단계가 질문입니다. 고정되지 않은 호출마다 Noul 질문 두 개가 만들어집니다. Noul은 Jev가 제공하는 세 가지 질문 유형 중 하나로, 진술 하나가 참인지를 0에서 1 사이 값으로 돌려줍니다. 첫 번째 질문은 그 호출이 이루어졌다는 사실과 입력값이 앞으로의 작업에 여전히 중요한지를 묻고, 두 번째 질문은 그 결과의 내용이 여전히 필요하며 도구를 다시 실행하는 것으로는 대신할 수 없는지를 묻습니다. 질문은 상태와 합쳐 maxRequestTokens(기본값 30000) 안에 들어가도록 여러 요청으로 쪼개지고, 같은 상태가 매 요청에 함께 실려 나가며, 요청들은 동시에 실행된 뒤 답이 합쳐집니다.

마지막 단계에서 두 확률을 keepThreshold(기본값 0.5)와 견주어 호출마다 처리 방향을 정합니다:

조건 처리 keepResult ≥ 임계값 호출과 결과를 모두 유지 keepCall ≥ 임계값 호출은 유지하고, 결과는 앞 truncateHeadChars 글자(기본값 300)와 한 줄 안내만 남기고 잘라냄 둘 다 임계값 미만 호출과 결과를 함께 삭제

잘라낸 결과 자리에는 [fast-jev-compaction truncated N chars of this tool result; re-run the tool if needed]라는 안내가 붙어, 몇 글자가 잘렸는지와 필요하면 도구를 다시 실행하라는 지시가 함께 남습니다. 결정을 반영해 대화를 다시 조립할 때는 내용이 전부 없어진 메시지를 통째로 제거하고, 손대지 않은 메시지는 원래 객체를 그대로 돌려주며, 호출이 사라진 자리에 결과만 남는 상태는 만들지 않습니다.

fast-jev-compaction이 대화 상태를 줄이는 단계

Jev에 보내는 상태에는 maxStateTokens(기본값 25000)라는 상한이 있습니다. 대화가 이 상한을 넘으면 fast-jev-compaction은 다음 단계를 순서대로 적용하며, 각 단계는 직전 단계로도 부족했을 때만 실행됩니다:

  1. 도구 입력을 200자로, 그래도 부족하면 60자로 더 자릅니다. 기본 상태에서 입력은 이미 1000자로 잘려 있습니다.
  2. 긴 텍스트를 앞 400자와 뒤 150자만 남기고 줄입니다. 고정되지 않은 오래된 메시지부터 처리합니다.
  3. 오래된 비고정 메시지를 [… N chars omitted …] 메모 한 줄로 접습니다.
  4. 오래된 도구 호출을 t12 Read file_path=src/a.ts → ok 480ch 형태의 한 줄로 바꿉니다.
  5. 호출이 없는 오래된 메시지를 상태에서 제외합니다.
  6. 호출만 있는 오래된 메시지가 연달아 있으면 하나로 합칩니다.

여섯 단계를 다 거치고도 상한에 들어가지 않으면 압축은 예외를 던지고, 그 뒤 처리는 호출자가 결정합니다. 플러그인으로 쓸 때는 이 예외도 기본 요약으로 되돌아가는 경로로 이어집니다.

fast-jev-compaction은 토큰을 셀 때 토크나이저를 쓰지 않고 문자 구성으로 추정하는데, 알파벳 낱말은 6자당 1토큰, 숫자는 한 글자당 0.5토큰, 나머지 기호는 하나당 0.9토큰으로 계산합니다. 저자는 실제 Jev가 보고한 사용량보다 2%에서 18% 높게 나오도록 이 계수를 맞췄다고 src/state.ts의 주석에 적어 두었습니다. 단순히 글자 수를 일정 비율로 나누는 방식은 JSON이 많은 상태에서 실제보다 최대 40% 적게 세기 때문에, 일부러 넉넉하게 잡는 쪽을 골랐다는 설명입니다.

fast-jev-compaction이 밝힌 한계

저자는 한계를 네 가지로 정리해 두었습니다. 첫째, 후보가 되는 것은 도구 호출과 결과뿐이고 텍스트 메시지는 출력에서 제거되거나 짧아지지 않습니다. 텍스트가 줄어드는 것은 Jev가 보는 상태 안에서일 뿐입니다. 둘째, 토큰 크기는 토크나이저가 아니라 문자 수에서 나온 추정치입니다. 셋째, 보정은 요청 단위로 이루어지므로 확률값 하나가 그 결과를 지워도 안전하다는 증명은 되지 못하며, 대신 어시스턴트가 언제든 도구를 다시 실행할 수 있다는 점이 안전장치가 됩니다. 넷째, 전체 상태가 매 요청에 반복되기 때문에 상태 상한에 가까운 대화 기록은 질문 몇 개마다 요청 하나씩을 쓰게 됩니다.

여기에 저장소 밖에서 확인되는 한계가 하나 더 있습니다. 이 플러그인이 활용하는 함수 훅(function hook)은 Claude Code 2.1.274 이상에서 쓸 수 있는 얼리 액세스 기능이고, 공개된 훅 레퍼런스와 플러그인 레퍼런스에는 아직 함수 훅도, 이 플러그인이 쓰는 session.compact와 turn.complete 이벤트도 실려 있지 않습니다. 공개 문서에 적힌 hooks/hooks.json도 이벤트 매처와 동작을 담은 JSON 설정인데, 이 저장소의 같은 파일은 {"modules": ["./fast-jev.ts"]} 한 줄로 TypeScript 모듈을 가리킵니다. 저자도 함수 훅이 릴리스 사이에 바뀔 수 있다고 적으면서, types/claude-code.d.ts의 타입 선언을 Claude Code 업그레이드 후에 다시 생성해 검토하라고 안내합니다.

fast-jev-compaction 설치와 사용

함수 훅은 기본적으로 꺼져 있으므로, Claude Code가 실행되는 곳의 설정에 옵트인 플래그를 먼저 넣어야 합니다. ~/.claude/settings.json에 넣는다면 다음과 같습니다:

{ "env": { "CLAUDE_CODE_ENABLE_FUNCTION_HOOKS": "1", "TYPESAFE_API_KEY": "<your key>" } }

그 다음 저장소를 플러그인 마켓플레이스로 추가하고 플러그인을 설치합니다. 셸에서 실행해도 되고 세션 안에서 슬래시 명령으로 실행해도 됩니다:

claude plugin marketplace add tamaratran/fast-jev-compaction
claude plugin install fast-jev-compaction@fast-jev-compaction

설치 과정에서 API 키와 임계값 같은 플러그인 옵션을 묻는데, 기본값으로 두면 환경 변수의 TYPESAFE_API_KEY를 씁니다. 설치 후 Claude Code를 다시 시작하거나 /reload-plugins를 실행하면 그때부터 /compact와 자동 압축이 Jev를 거칩니다. 훅은 줄어든 비율과 사유별 개수, 상태 크기, 요청 수를 로그에 남기고 호출마다 두 확률을 담은 decisions: 줄도 함께 기록하므로, keepThreshold를 조정할 때 그 값을 근거로 삼을 수 있습니다. 저장소를 내려받아 바로 시험해 보려면 저장소 루트에서 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude --plugin-dir .을 실행하면 되고, 마켓플레이스가 저장소의 .claude-plugin/marketplace.json 자체라 따로 배포하는 단계는 없습니다. TypeSafe 키 없이 동작만 먼저 보고 싶다면 demo/JevDemo를 demo/JevDemo/build.sh로 빌드해 실행할 수 있는데, 이 macOS 앱은 미리 준비한 대화 기록을 각색해 보여줄 뿐 실제로 API를 호출하지는 않습니다.

플러그인이 받는 설정값은 .claude-plugin/plugin.json에 선언되어 있습니다:

옵션 기본값 설명 apiKey (없음) TypeSafe API 키, 비워 두면 TYPESAFE_API_KEY 사용 keepThreshold 0.5 호출이나 결과가 남기 위한 최소 확률 preserveRecentMessages 6 압축에서 고정하는 최신 메시지 개수 compactAtPercent 60 이 컨텍스트 비율에 닿으면 압축을 요청 minReductionRatio 0.25 이만큼 줄지 않으면 기본 요약으로 넘김 maxStateTokens 25000 상태의 추정 토큰 예산 maxRequestTokens 30000 상태와 질문 한 묶음의 추정 토큰 예산 truncateHeadChars 300 버려지는 결과에서 남길 앞부분 글자 수 model jev-latest Jev 모델 이름

이 가운데 compactAtPercent는 플러그인에만 있는 값입니다. turn.complete 훅이 매 턴 끝에서 컨텍스트 사용률을 보고 이 비율에 닿으면 압축을 스스로 요청하므로, 컨텍스트가 가득 차기를 기다리지 않고 60% 지점에서 미리 정리하는 동작이 기본값이 됩니다.

라이브러리로 쓸 때는 compactMessages 하나로 시작할 수 있습니다. 저장소가 제시하는 최소 예시는 다음과 같습니다:

import { compactMessages, reductionRatio, type Message } from 'fast-jev-compaction';

const transcript: Message[] = [
  { role: 'user', text: 'Fix the failing test. Never edit src/generated.', toolUses: [] },
  {
    role: 'assistant',
    text: '',
    toolUses: [{ tool_use_id: 'toolu_1', tool: 'Read', input: { file_path: 'src/a.ts' } }],
  },
  { role: 'user', text: '', toolUses: [], toolResults: [{ tool_use_id: 'toolu_1', text: '…file…' }] },
  // …
];

const result = await compactMessages(transcript, { preserveRecentMessages: 4 });
console.log(result.messages, result.decisions, result.stats);

Message 타입이 Claude Code SessionMessage의 부분집합이라 세션 기록을 그대로 넘길 수 있고, 전송 계층을 직접 구현하고 싶으면 ask(state, questions) 메서드 하나를 가진 JevAsker를 만들어 compact(messages, asker, options)에 넘기면 됩니다. 다만 npm install fast-jev-compaction은 README에 적혀 있는 것과 달리 아직 동작하지 않습니다. npm 레지스트리에 이 이름의 패키지가 없어서, 라이브러리로 쓰려면 저장소를 직접 가져와 빌드해야 합니다.

fast-jev-compaction의 라이선스

fast-jev-compaction은 MIT 라이선스로 공개되어 있어 개인 및 상업적 목적으로 자유롭게 사용할 수 있습니다.

fast-jev-compaction이 사용하는 Jev 모델의 TypeSafe AI 문서

TypeSafe AI

Introduction - TypeSafe AI

Jev is TypeSafe's flagship model and the first System One model. Send state and typed questions; get structured answers your code can use directly.

fast-jev-compaction 프로젝트 GitHub 저장소

github.com

GitHub - tamaratran/fast-jev-compaction: Claude Code plugin that replaces the compaction...

Claude Code plugin that replaces the compaction summary with Jev decisions: every tool call and result is scored in one fast request, stale ones are dropped or truncated, everything kept stays verbatim.

더 읽어보기



이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다.

파이토치 한국 사용자 모임은 이런 글들을 한국어로 정리해 나누고 있습니다. 회원으로 가입하시면 주요 글들을 이메일로 보내드리고, 텔레그램(Telegram)과 Slack/Discord/Teams/Dooray/GoogleChat 등으로도 새 글 알림을 받으실 수 있습니다.

아래쪽에 좋아요를 눌러주시면 다음 글을 정리하는 데 힘이 됩니다~

2개의 게시물 - 1명의 참여자

전체 주제 읽기

https://discuss.pytorch.kr/t/fast-jev-compaction-claude-code/11970

元の投稿を見る