Skip to content

셸에서 에이전트 다루기 ​

이 가이드를 마치면 셸 스크립트로 여러 세션을 다룰 수 있어요. 세션을 시작하고, 입력하고, 각각이 끝날 때까지 기다리고, 조건에 맞는 세션을 찾아요. 명령마다 프로세스를 띄우지 않고 소켓에 바로 말하는 빠른 경로로 스크립트를 바꾸는 방법도 다뤄요.

시작하기 전에 ​

  • PATH에 zeropty가 있는 Mac이 필요해요. 자세한 내용은 설치와 지원 플랫폼을 보세요.
  • bash builtin을 쓰려면 소스에서 빌드해야 해요(./build.sh가 dist/zeropty_bash.dylib를 만들어요). 릴리스 아카이브에는 들어 있지 않아요.
  • 아래 단계는 각 세션에서 sh를 실행하므로 claude가 없어도 돼요. 실제 스크립트에서는 대신 에이전트를 실행해요. 예를 들어 dist/claude-zeropty예요(claude와 다른 터미널 프로그램 실행하기 참고).

1. 세션 시작하기 ​

세션은 서버가 계속 실행해 주는 프로그램 하나예요. 서버가 없으면 첫 new-session이 서버를 띄워요.

sh
zeropty new-session -d -s build -x 80 -y 6 sh

-d는 내 터미널을 그대로 두고, -s build는 세션 이름을 정하고, -x/-y는 화면 크기를 정해요. 자세한 내용은 세션과 서버를 보세요.

2. 키 보내기 ​

모든 명령은 타깃(-t)으로 세션을 가리켜요. 스크립트에서는 '=build:'처럼 따옴표로 감싸서 써요.

sh
zeropty send-keys -t '=build:' -l 'ls / | head -3; echo "exit: $?"'
zeropty send-keys -t '=build:' Enter

send-keys의 인자는 하나하나가 키 이름이거나 글자 그대로의 텍스트예요.

이렇게 쓰면이렇게 보내요
Enter, C-c, Up, F5그 키의 바이트(키 이름)
-l 'Enter'Enter라는 다섯 글자. 키가 아니에요
-H 41 42 0a16진수 바이트 그대로(AB와 줄바꿈)
-N 3 Down인자 전체를 세 번

프롬프트나 변수에서 온 텍스트에는 항상 -l을 쓰세요. 그러면 그 안의 Enter나 Space 같은 단어가 키로 해석되지 않아요. Enter는 -l 없이 별도 명령으로 보내요.

zsh에서는 타깃에 따옴표를 쓰세요

zsh는 =word를 명령의 경로로 바꿔요(= 확장). =build:가 아니라 '=build:'로 쓰세요. tmux 타깃도 같은 문제가 있어요.

3. 결과 기다리기 ​

wait-pane은 글자가 나타나거나(-m), 출력이 멈추거나(-q), 둘 다 만족할 때 답해요. -T는 타임아웃이에요.

sh
zeropty wait-pane -t '=build:' -m 'exit: 0' -T 10000

서버는 출력이 올 때만 확인하므로 폴링이 없어요. 친 키는 화면에 에코되므로, 결과에서만 출력되는 글자를 기다리세요. 위에서 친 줄에는 0이 아니라 $?가 들어 있어서, exit: 0은 출력에만 일치해요.

마지막에 어떤 글자가 나올지 알 수 없는 에이전트라면 대신 조용해질 때까지 기다려요.

sh
zeropty wait-pane -t '=fix-1:' -q 5000 -T 600000   # until output pauses for 5 s, at most 10 minutes

wait-pane은 시간이 초과되거나(wait-pane: timed out) 세션이 끝나면 종료 코드 1로 끝나요. 자세한 내용은 화면, 키, 기다리기를 보세요.

4. 화면 읽기 ​

capture-pane -p는 화면을 출력해요. 밀린 출력을 먼저 처리하므로 화면은 늘 최신이에요.

sh
zeropty capture-pane -p -t '=build:'                 # the visible screen
zeropty capture-pane -p -e -S -200 -t '=build:'      # plus 200 lines of scrollback, with colors
zeropty capture-pane -p -J -S - -E - -t '=build:'    # everything, wrapped lines joined
옵션효과
-p표준 출력으로 내보내요(없으면 화면이 버퍼에 들어가요)
-e색·글꼴 이스케이프를 남겨요
-J줄바꿈으로 나뉜 줄을 이어 붙여요
-N줄 끝 공백을 남겨요
-S, -E첫 줄과 마지막 줄. 0이 화면 첫 줄, 음수가 스크롤백, -는 끝까지예요

모든 옵션은 화면 읽기를 보세요.

5. 여러 세션 다루기 ​

작업마다 세션을 하나씩 시작한 다음, 각각을 기다리고 grep-panes로 한꺼번에 찾아요. 아래 내용을 jobs.sh로 저장하세요.

sh
#!/bin/sh
set -e
for n in 1 2 3; do
  zeropty new-session -d -s "job-$n" -x 80 -y 10 sh
  zeropty send-keys -t "=job-$n:" -l "sleep $n; echo \"finished: \$?\""
  zeropty send-keys -t "=job-$n:" Enter
done
for n in 1 2 3; do
  zeropty wait-pane -t "=job-$n:" -m 'finished: 0' -T 30000
done
zeropty grep-panes 'finished: 0'

grep-panes는 일치한 줄을 세션: 줄 형태로 세션 이름순으로 출력하고, 일치하는 게 없으면 종료 코드 1로 끝나요. -S -100을 더하면 스크롤백까지 찾아요. 세션 1000개에서 16~32ms 걸렸어요. 화면을 하나씩 읽지 않고도 입력을 기다리는 에이전트를 찾을 때 써요.

6. 빠른 경로 쓰기 ​

zeropty 프로그램을 실행하면 명령마다 프로세스가 떠요(3.59~4.23ms). zsh 함수와 bash builtin은 대신 셸 안에서 소켓으로 명령을 바로 보내요.

sh
source /path/to/zeropty/shell/zeropty.zsh
sh
enable -f /path/to/zeropty/dist/zeropty_bash.dylib zeropty

/path/to/zeropty는 clone한 폴더로 바꾸세요. 스크립트는 그대로 두면 돼요. 이제 zeropty가 함수 또는 builtin이 될 뿐이에요.

경로측정값
zsh 함수send-keys -l p50 0.12ms(tmux CLI보다 50.9~52.7배 빨라요), has-session 0.11~0.17ms, 2000줄 capture-pane 0.50~0.55ms
bash builtin명령당 0.041~0.138ms(tmux CLI보다 48.7~157배 빨라요), macOS의 /bin/bash 3.2에서 확인했어요

둘 다 attach, serve, restart-server, -V, --help, 인자 없는 실행, 서버가 없을 때의 모든 명령은 여전히 프로그램을 실행해요. ZEROPTY_BIN을 지정하면 다른 프로그램을 가리킬 수 있어요.

확인하기 ​

스크립트를 실행한 뒤 화면 하나를 읽어 보세요.

sh
sh jobs.sh
zeropty capture-pane -p -t '=job-2:'

grep-panes가 세션마다 한 줄씩 보여 줘야 해요.

text
job-1: finished: 0
job-2: finished: 0
job-3: finished: 0

job-2의 화면에는 친 줄이 먼저 나오고, 그다음에 finished: 0이 나와요.

text
sleep 2; echo "finished: $?"
finished: 0

zeropty kill-server로 정리하세요.

문제가 생기면 ​

증상해결
wait-pane -m이 바로 끝나요글자가 내가 친 줄에 들어 있어요. 결과에서만 출력되는 글자를 기다리세요.
글자가 나왔는데도 wait-pane: session ended가 나와요프로그램이 출력 직후에 끝났어요. 살아 있게 하세요. 예: sh -c 'make; echo build done; exec cat'
보이는 세션인데 can't find session: NAME 또는 can't find pane: NAME이 나와요타깃은 정확히 일치해야 해요. 앞부분 일치는 없어요. zeropty ls로 확인하세요.
no server running on ...그 소켓에서 듣는 서버가 없어요. new-session으로 서버를 띄우거나 ZEROPTY_SOCK을 지정하세요.
send-keys: unknown flag -X모르는 옵션은 오류예요. 키 보내기를 보세요.
C-d 뒤로 입력이 안 들어가요빈 줄의 C-d는 세션의 입력을 영영 닫아요. 대신 C-c나 프로그램의 종료 명령을 보내세요.

다음 단계 ​

MIT 또는 Apache-2.0 라이선스로 배포해요.