Lifecycle hooks

Bob 세션의 주요 시점에서 셸 명령을 자동으로 실행하여 활동을 기록하고, 컨텍스트를 주입하거나, 직접 작성한 로직으로 작업을 차단합니다.

Lifecycle hooks를 사용하면 Bob 세션의 특정 시점에 셸 명령을 실행할 수 있습니다. 활동 로깅, 모델에 컨텍스트 주입, 작업 허용 또는 차단, 후속 자동화 시작 등을 Bob을 수정하지 않고 구현할 수 있습니다.

지원되는 hooks

Hook실행 시점차단 여부stdout 동작
SessionStart세션 시작 시 1회아니요컨텍스트로 주입
UserPromptSubmit프롬프트를 제출할 때마다예 (exit 2)컨텍스트로 주입
PreToolUse일치하는 도구 실행 전예 (exit 2)무시됨
PostToolUse일치하는 도구 완료 후아니요무시됨
Stop에이전트가 중지될 때아니요무시됨

설정

Hooks는 settings.jsonhooks 키 아래에 정의됩니다. Bob은 두 위치에서 hooks를 병합합니다:

범위파일
전역 (모든 workspace)~/.bob/settings/settings.json
Workspace (현재 프로젝트).bob/settings.json

전역 hooks는 항상 실행됩니다. Workspace hooks는 전역 hooks 위에 병합되어 현재 프로젝트에만 적용됩니다.

Hook 스키마

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^write_file$",
        "hooks": [
          {
            "type": "command",
            "command": "sh .bob/hooks/check.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

설정 필드

필드타입기본값설명
type"command"(없음)필수. command만 지원됩니다.
commandstring(없음)필수. 실행할 셸 명령. macOS/Linux에서는 sh -c, Windows에서는 cmd /c로 실행됩니다.
matcherstring(없음)선택. 도구 이름과 매칭할 regex (PreToolUse, PostToolUse에만 해당). 생략하면 모든 도구에 매칭됩니다.
timeoutnumber10Hook을 중지하기 전 초. 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은 오류를 표시하고 프롬프트가 제출되지 않습니다.

일치하는 도구가 실행되기 전에 실행되어 작업을 검사하거나 차단할 기회를 줍니다.

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은 도구가 차단되었다고 보고하고 세션을 계속합니다.

일치하는 도구가 완료된 후 성공 여부와 관계없이 실행됩니다.

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
참고:

차단을 지원하는 것은 UserPromptSubmitPreToolUse뿐입니다. SessionStart, PostToolUse, Stop에서의 Exit 코드 2는 비-차단 실패로 처리됩니다.

명령 세부 정보

  • 작업 디렉터리: 명령은 태스크 작업 디렉터리 (Bob이 작업 중인 폴더)에서 실행됩니다.
  • 기본 타임아웃: 10초. timeout 필드로 hook별로 재정의할 수 있습니다. timeout0으로 설정하면 타임아웃을 완전히 비활성화합니다.
  • Stderr: Bob의 로그에 기록되지만 hook 결과에는 영향을 주지 않습니다.
  • Shell: macOS와 Linux에서는 sh -c, Windows에서는 cmd /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.txt

Bob 세션을 시작하고 일치하는 도구를 사용합니다. ~/.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
    ;;
esac

Stop에서 후속 자동화 실행

Stop을 사용하여 세션 종료 후 정리 또는 보고를 시작합니다:

#!/bin/sh
# 에이전트 완료 후 스테이징된 변경사항 커밋
cd "$PWD"
git diff --cached --quiet || git commit -m "chore: auto-commit from Bob session"

현재 제한 사항

이번 릴리스에서는 command hooks와 위에 나열된 5가지 hook 타입만 지원됩니다. 다음은 아직 사용할 수 없습니다:

  • command 이외의 hook 타입: function hooks, 인라인 스크립트 hooks 등은 지원되지 않습니다.
  • 예약 hooks: hooks를 타이머 또는 외부 이벤트에 응답하여 실행되도록 설정할 수 없습니다.
  • 입력 재작성: hooks는 프롬프트나 도구 입력이 모델에 도달하기 전에 수정할 수 없습니다.
  • 샌드박스 실행: hooks는 사용자의 전체 권한으로 실행됩니다. 격리가 적용되지 않습니다.
  • 전용 hook 텔레메트리: hook 활동은 세션 분석에서 별도로 추적되지 않습니다.
  • PostToolUse 또는 Stop에서의 차단: 이러한 hooks에서 Exit 코드 2는 효과가 없습니다.
이 주제는 어떤가요?