Lifecycle hooks
Bob Shell 세션의 주요 시점에서 셸 명령을 자동으로 실행하여 활동을 기록하고, 컨텍스트를 주입하거나, 직접 작성한 로직으로 작업을 차단합니다.
Lifecycle hooks를 사용하면 Bob Shell 세션의 특정 시점에 셸 명령을 실행할 수 있습니다. 활동 로깅, 모델에 컨텍스트 주입, 작업 허용 또는 차단, 후속 자동화 시작 등을 Bob Shell을 수정하지 않고 구현할 수 있습니다.
지원되는 hooks
| Hook | 실행 시점 | 차단 여부 | stdout 동작 |
|---|---|---|---|
SessionStart | 세션 시작 시 1회 | 아니요 | 컨텍스트로 주입 |
UserPromptSubmit | 프롬프트를 제출할 때마다 | 예 (exit 2) | 컨텍스트로 주입 |
PreToolUse | 일치하는 도구 실행 전 | 예 (exit 2) | 무시됨 |
PostToolUse | 일치하는 도구 완료 후 | 아니요 | 무시됨 |
Stop | 에이전트가 중지될 때 | 아니요 | 무시됨 |
설정
Hooks는 settings.json의 hooks 키 아래에 정의됩니다. Bob Shell은 두 위치에서 hooks를 병합합니다:
| 범위 | 파일 |
|---|---|
| 전역 (모든 workspace) | ~/.bob/settings/settings.json |
| Workspace (현재 프로젝트) | .bob/settings.json |
전역 hooks는 항상 실행됩니다. Workspace hooks는 전역 hooks 위에 병합되어 현재 프로젝트에만 적용됩니다.
Workspace hooks는 신뢰할 수 있는 폴더에서만 실행됩니다. 현재 폴더가 신뢰되지 않으면 .bob/settings.json 파일이 로드되지 않고 workspace hooks는 자동으로 건너뜁니다. ~/.bob/settings/settings.json의 전역 hooks는 폴더 신뢰 설정의 영향을 받지 않습니다.
설정 파일의 위치 및 로드 방법에 대한 자세한 내용은 Bob Shell 구성하기를 참조하세요.
Hook 스키마
{
"hooks": {
"PreToolUse": [
{
"matcher": "^write_file$",
"hooks": [
{
"type": "command",
"command": "sh .bob/hooks/check.sh",
"timeout": 5
}
]
}
]
}
}설정 필드
| 필드 | 타입 | 기본값 | 설명 |
|---|---|---|---|
type | "command" | (없음) | 필수. command만 지원됩니다. |
command | string | (없음) | 필수. 실행할 셸 명령. macOS/Linux에서는 sh -c로 실행됩니다. |
matcher | string | (없음) | 선택. 도구 이름과 매칭할 regex (PreToolUse, PostToolUse에만 해당). 생략하면 모든 도구에 매칭됩니다. |
timeout | number | 10 | Hook을 중지하기 전 초. 0으로 설정하면 타임아웃을 비활성화합니다. |
Hook 참조
새 세션이 시작될 때 첫 번째 턴 전에 1회 실행됩니다.
stdin 스키마
{
"event": "string",
"session_id": "string"
}페이로드 예시
{
"event": "SessionStart",
"session_id": "ses_01abc123"
}Stdout: 추가 세션 정보로 모델의 컨텍스트에 기록됩니다.
차단: Exit 코드 2는 지원되지 않습니다. 세션은 항상 시작됩니다. 기타 비-제로 종료는 로그에 기록되고 무시됩니다.
프롬프트를 제출할 때마다 모델로 전송되기 전에 실행됩니다.
stdin 스키마
{
"event": "string",
"session_id": "string",
"prompt": "string"
}페이로드 예시
{
"event": "UserPromptSubmit",
"session_id": "ses_01abc123",
"prompt": "Refactor the auth module"
}Stdout: 프롬프트와 함께 모델의 컨텍스트에 기록됩니다.
차단: Exit 코드 2는 프롬프트 전송을 차단합니다. Bob Shell은 오류를 표시하고 프롬프트가 제출되지 않습니다.
일치하는 도구가 실행되기 전에 실행되어 작업을 검사하거나 차단할 기회를 줍니다.
stdin 스키마
{
"event": "string",
"session_id": "string",
"tool": "string",
"input": "object"
}페이로드 예시
{
"event": "PreToolUse",
"session_id": "ses_01abc123",
"tool": "write_file",
"input": {
"path": "src/index.ts",
"content": "..."
}
}Stdout: 무시됩니다.
차단: Exit 코드 2는 도구 실행을 방지합니다. Bob Shell은 도구가 차단되었다고 보고하고 세션을 계속합니다.
일치하는 도구가 완료된 후 성공 여부와 관계없이 실행됩니다.
stdin 스키마
{
"event": "string",
"session_id": "string",
"tool": "string",
"input": "object",
"output": "string"
}페이로드 예시
{
"event": "PostToolUse",
"session_id": "ses_01abc123",
"tool": "write_file",
"input": {
"path": "src/index.ts",
"content": "..."
},
"output": "File written successfully"
}Stdout: 무시됩니다.
차단: Exit 코드 2는 효과가 없습니다. 도구는 이미 실행되었습니다.
에이전트가 중지될 때 마지막 턴 완료 후 실행됩니다.
stdin 스키마
{
"event": "string",
"session_id": "string"
}페이로드 예시
{
"event": "Stop",
"session_id": "ses_01abc123"
}Stdout: 무시됩니다.
차단: Exit 코드 2는 효과가 없습니다. 세션은 이미 종료되었습니다.
Exit 코드와 차단
| Exit 코드 | 동작 | 적용 대상 |
|---|---|---|
0 | 성공: hook이 문제 없이 실행됨 | 모든 hooks |
2 | 차단: 현재 작업 중지 | UserPromptSubmit, PreToolUse |
| 기타 비-제로 | 비-차단 실패: 로그에 기록되고 무시됨 | 모든 hooks |
차단을 지원하는 것은 UserPromptSubmit과 PreToolUse뿐입니다. SessionStart, PostToolUse, Stop에서의 Exit 코드 2는 비-차단 실패로 처리됩니다.
명령 세부 정보
- 작업 디렉터리: 명령은 태스크 작업 디렉터리 (Bob이 작업 중인 폴더)에서 실행됩니다.
- 기본 타임아웃: 10초.
timeout필드로 hook별로 재정의할 수 있습니다.timeout을0으로 설정하면 타임아웃을 완전히 비활성화합니다. - Stderr: Bob Shell의 로그에 기록되지만 hook 결과에는 영향을 주지 않습니다.
- Shell: macOS와 Linux에서는
sh -c로 명령이 실행됩니다.
시작하기
~/.bob/settings/settings.json에 있는 전역 설정 파일을 열거나 생성합니다.
사용할 hook의 hooks 키를 추가합니다. 아래 예시는 모든 write_file 호출 전에 스크립트를 실행합니다:
{
"hooks": {
"PreToolUse": [
{
"matcher": "^write_file$",
"hooks": [
{
"type": "command",
"command": "sh ~/.bob/hooks/log-write.sh"
}
]
}
]
}
}스크립트 파일을 생성합니다. 이 최소 스크립트는 들어오는 JSON 페이로드를 기록합니다:
#!/bin/sh
# ~/.bob/hooks/log-write.sh
cat >> ~/.bob/hooks/write-log.txtBob Shell 세션을 시작하고 일치하는 도구를 사용합니다. ~/.bob/hooks/write-log.txt를 확인하여 hook이 실행되고 페이로드가 기록되었는지 확인합니다.
예시
모든 hook 입력 로깅
디버깅을 위해 각 hook의 stdin을 파일에 기록합니다:
#!/bin/sh
# 타임스탬프와 함께 들어오는 JSON 페이로드 추가
echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> ~/.bob/hooks/debug.log
cat >> ~/.bob/hooks/debug.log
echo "" >> ~/.bob/hooks/debug.log임의의 hook 아래에 설정합니다:
{
"hooks": {
"SessionStart": [
{
"hooks": [{ "type": "command", "command": "sh ~/.bob/hooks/debug.sh" }]
}
]
}
}세션 컨텍스트 주입
SessionStart hook에서 텍스트를 반환하여 모델의 컨텍스트에 추가합니다:
#!/bin/sh
# 모델이 사용할 프로젝트 메타데이터 출력
echo "Project: $(basename $PWD)"
echo "Git branch: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
echo "Node version: $(node --version 2>/dev/null || echo 'not installed')"프롬프트 차단
UserPromptSubmit hook에서 Exit 코드 2로 종료하여 프롬프트 전송을 방지합니다:
#!/bin/sh
# "delete" 단어가 포함된 프롬프트 차단
PROMPT=$(cat | python3 -c "import sys,json; print(json.load(sys.stdin)['prompt'])")
case "$PROMPT" in
*delete*|*DELETE*)
echo "Prompt blocked: contains 'delete'" >&2
exit 2
;;
esac일치하는 도구 차단
PreToolUse hook에서 Exit 코드 2로 종료하여 특정 도구의 실행을 방지합니다:
#!/bin/sh
# src/ 디렉터리 외부 파일에 대한 write_file 작업 차단
PATH_VAL=$(cat | python3 -c "import sys,json; print(json.load(sys.stdin)['input'].get('path',''))")
case "$PATH_VAL" in
src/*) ;;
*)
echo "Blocked: writes outside src/ are not allowed" >&2
exit 2
;;
esacStop에서 후속 자동화 실행
Stop을 사용하여 세션 종료 후 정리 또는 보고를 시작합니다:
#!/bin/sh
# 에이전트 완료 후 스테이징된 변경사항 커밋
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob Shell session"현재 제한 사항
이번 릴리스에서는 command hooks와 위에 나열된 5가지 hook 타입만 지원됩니다. 다음은 아직 사용할 수 없습니다:
command이외의 hook 타입: function hooks, 인라인 스크립트 hooks 등은 지원되지 않습니다.- 예약 hooks: hooks를 타이머 또는 외부 이벤트에 응답하여 실행되도록 설정할 수 없습니다.
- 입력 재작성: hooks는 프롬프트나 도구 입력이 모델에 도달하기 전에 수정할 수 없습니다.
- 샌드박스 실행: hooks는 사용자의 전체 권한으로 실행됩니다. 격리가 적용되지 않습니다.
- 전용 hook 텔레메트리: hook 활동은 세션 분석에서 별도로 추적되지 않습니다.
PostToolUse또는Stop에서의 차단: 이러한 hooks에서 Exit 코드2는 효과가 없습니다.