Skip to content

fix(cli): Ink TUI 스트리밍 플리커 제거#46

Merged
4entrepreneur merged 2 commits into
mainfrom
hy/cli-flicker-fix
May 5, 2026
Merged

fix(cli): Ink TUI 스트리밍 플리커 제거#46
4entrepreneur merged 2 commits into
mainfrom
hy/cli-flicker-fix

Conversation

@4entrepreneur

Copy link
Copy Markdown
Collaborator

변경 요약

openclone chat Ink TUI 모드에서 응답을 받는 동안 화면이 깜빡이던 문제를 해결한다. 근본 원인은 두 층에 걸쳐 있었다 — (1) AI SDK가 토큰을 초당 수십~수백 회 yield 할 때마다 setStreaming이 React 리렌더를 트리거했고, (2) Ink 7의 standard 렌더 모드가 매 프레임마다 dynamic 영역(streaming 박스 + InputBox + 두 ink-spinner) 전체를 erase 후 재출력해 응답이 길어질수록 클리어되는 줄 수가 선형 증가했다. 이를 (a) setStreaming을 ref + 33ms throttle(약 30fps)로 묶고, (b) streaming 박스 내부 spinner를 제거해 frame-tick 트리거를 절반으로 줄이고, (c) Ink의 incrementalRendering: true를 켜서 변경되지 않은 줄을 redraw에서 제외하는 세 변경으로 함께 해결했다.

변경 유형

  • 기타: CLI(src/ui/) 렌더링 최적화

테스트 방법

  • `npm install && npm run build && npm test` — 87개 테스트 전부 통과 확인.
  • TTY에서 `node dist/cli/index.js chat ` 진입 후 긴 응답을 유도하는 프롬프트(예: "1000자 분량의 자기소개")로 streaming 받으면서 (1) 토큰이 깜빡임 없이 누적되는지, (2) 종료 시 마지막 글자 누락이 없는지, (3) 한글/마크다운이 정상 표시되는지 확인.
  • non-TTY 경로(`< input.txt`로 stdin 리디렉션)는 readline로 분기되어 영향 없음.

체크리스트

  • 빌드/테스트 통과
  • 이모지 미포함
  • 내장 클론(clones/) 미변경
  • CHANGELOG [Unreleased] 갱신은 별도 결정 필요

4entrepreneur and others added 2 commits May 6, 2026 04:28
매 토큰마다 setStreaming을 호출해 React/Ink가 동적 영역(streaming
박스 + InputBox + 두 개의 ink-spinner)을 통째로 redraw하던 것이
주원인. ref에 토큰을 누적하고 33ms(약 30fps) 간격으로만 setState 하도록
throttle 했고, streaming 박스 내부 spinner도 제거해 동적 영역의
frame-tick 트리거를 둘에서 하나(InputBox의 thinking spinner)로
줄였다. 종료/에러/언마운트 경로 모두에서 pending timer를 clear해
setStreaming(null) 후 박스가 다시 등장하는 회귀를 막는다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ink 7의 incrementalRendering 옵션은 변경되지 않은 줄을 다시 그리지
않는다. 기본 standard 모드는 매 렌더마다 dynamic 영역 전체를 erase 후
재출력하므로, streaming 응답이 길어질수록 클리어/재출력 라인 수가
선형적으로 증가해 플리커의 근본 원인이 된다. 이 플래그 한 줄로
InputBox/HeaderBar/이미 그려진 streaming 줄은 redraw에서 제외되어
앞 커밋의 throttle/spinner 제거 효과가 곱셈으로 커진다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vkehfdl1

vkehfdl1 commented May 5, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the contribution! 🙏

This repository's automation only reviews pull requests that target the dev branch (this PR currently targets main). Please change the base branch to dev so dani can pick it up for automated review.

GitHub UI → click "Edit" next to the PR title → change the base branch to dev, then push (or reopen) the PR.

@4entrepreneur
4entrepreneur merged commit 6dad573 into main May 5, 2026
1 check passed
4entrepreneur added a commit that referenced this pull request May 5, 2026
방금 머지한 origin/main의 PR #46·#48이 추가한 두 파일이 src 트리에 빠져 있어 보강. format-error.ts는 provider/SDK 에러를 ErrorBanner가 렌더할 구조로 정규화하고, ErrorBanner.tsx는 Ink TUI에서 그 에러 박스를 그림.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4entrepreneur added a commit that referenced this pull request May 5, 2026
* docs: AGENTS.md를 SSOT로 도입, CLAUDE.md는 @AGENTS.md 임포트 스텁

Codex/Cursor 등 비-Claude 에이전트가 같은 컨트리뷰팅 가이드를 읽도록
루트 CLAUDE.md를 AGENTS.md로 이동(`git mv`로 히스토리 보존). 루트
CLAUDE.md는 한 줄짜리 `@AGENTS.md` 네이티브 임포트 스텁으로 유지해
Claude Code가 같은 본문을 그대로 로드하도록 함. 본문 톤은 에이전트
중립으로 일반화하고, docs/architecture.md 두 곳의 링크와 CHANGELOG
Unreleased 항목을 함께 갱신.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): Gotchas 중복 7글머리 정리

L224-L230의 7개 글머리는 L216-L223의 정확한 중복이라 삭제. sparse-checkout 패턴 3곳 갱신 규칙은 위쪽 글머리 한 곳에서만 유지.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): update 서브명령 + update-workflow.md 반영

SKILL.md의 dispatch는 이미 update를 라우팅하고 references/update-workflow.md도 실재하지만 본문에 빠져 있어 신규 컨트리뷰터가 update를 인지하지 못함. dispatch 표·references 트리에 추가하고, new·ingest·update가 모두 Chrome MCP 사용을 hard preflight gate로 강제한다는 사실을 한 단락 명시.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): npm 배포 경로 + publish-npm.yml 반영

L7의 'no build step / no package manager / no node_modules' 절대표현이 같은 저장소의 package.json·dist/·publish-npm 워크플로를 가리고 있었음. 'What this repo is'를 두 배포 경로(Claude Code skill + npm CLI `@openclone/openclone`)로 명시적으로 분리하고, 릴리스 태그 기반 자동 npm publish 워크플로(prerelease→next dist-tag, validate+build+audit+shellcheck+markdownlint 후 --provenance --access public) 동작을 한 단락으로 요약. workflows 트리에 publish-npm.yml 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): src 트리 전면 갱신 + AI SDK tools / Ink TUI 반영

자기모순 해소: history-store.ts와 conversation.ts는 본문이 이름으로 직접 참조하면서도 src 트리에 빠져 있었음. 12개 lib 파일 + Ink TUI 디렉터리(9개 컴포넌트/훅/타입)를 모두 트리에 명시. Standalone Node CLI 단락에도 AI SDK 도구 4종(list_knowledge_files / read_knowledge_file / web_fetch / web_search), 기본 모델 gpt-5.5, OPENCLONE_* 환경변수 6종, Codex OAuth knobs, Ink TUI vs single-shot 경로 분기를 짧게 명시.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): 자동 컴팩션 + /compact + history --quiet 반영

CLI conversation persistence 섹션이 schemaVersion·resume·orphan만 다루고 사용자 가시 표면이 큰 변경(자동 컴팩션 35만자 임계, 8턴 보존 기본값, /compact 수동, OPENCLONE_COMPACT_* 환경변수 3종)을 누락하고 있었음. 새 'Auto-compaction and /compact' 하위 섹션 추가하고, history 출력에서 --quiet 플래그(컬럼 헤더와 per-session resume hint 모두 억제)도 한 줄 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): openclone-cli nested skill 반영

skills/openclone-cli/는 별도의 Claude Code skill로 npm 설치·provider 선택·--resume·troubleshooting 등 CLI 사용 도움말을 노출하는데, 본문 트리·Editing conventions 모두 미언급. Project structure 트리에 nested skill 디렉터리(SKILL.md + 6개 references)를 추가하고, validate-skill.ts가 nested skills도 같이 검증한다는 사실을 Editing conventions 단락에 한 줄 명시.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): validate-readme-i18n + 3-language README + sparse 5곳

CI에서 매번 도는 validate-readme-i18n.ts(README ko/en/zh 번역 세트 동기 검증)와 README_en.md / README_zh.md가 본문 어디에도 없었음. Project structure 트리에 두 번역 파일 + i18n validator 추가하고, Editing conventions의 CI 단락을 'two TypeScript validators'에서 'three'로 수정해 i18n validator 동작(언어 picker/sync-comment SHA/clone slug parity/install fragment/REVIEW NEEDED)을 한 줄 명시. Gotchas의 'sparse-checkout pattern lives in three places' 표현은 실제로는 README가 3언어이므로 5곳임을 정확화.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): test/ + 설정 파일 + 미세 정확성 수정

Project structure 트리에 package.json/tsconfig.json/package-lock.json/.markdownlint-cli2.jsonc/test/ 디렉터리 추가. Commands 블록의 npm 명령을 'install && build && test'에서 'install && validate(=typecheck+build+test+smoke-hook)' + 'test'로 분리해 CI가 실제로 부르는 진입점을 노출. shellcheck 명령에 setup/uninstall을 명시(action 자체는 shebang 감지로 잡지만 본문 일관성 확보). 'No emojis' invariants 단락은 panel-workflow.md만 가리키던 표현을 5개 reference 동시 갱신 규칙으로 정확화하고, references 트리의 panel-workflow.md 주석에서 canonical 표현 제거.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(agents): src 트리에 format-error.ts / ErrorBanner.tsx 추가

방금 머지한 origin/main의 PR #46·#48이 추가한 두 파일이 src 트리에 빠져 있어 보강. format-error.ts는 provider/SDK 에러를 ErrorBanner가 렌더할 구조로 정규화하고, ErrorBanner.tsx는 Ink TUI에서 그 에러 박스를 그림.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants