
Claude Code의 Hook을 사용하여 프로젝트 전환 자동화하기 (UserPromptSubmit + additionalContext)
요약
Claude Code의 UserPromptSubmit Hook과 additionalContext를 활용하여 프로젝트 전환 과정을 자동화하는 방법을 설명합니다. 프롬프트에 프로젝트 이름만 입력해도 자동으로 해당 리포지토리 경로를 주입하여 작업 효율을 높일 수 있습니다.
핵심 포인트
- UserPromptSubmit Hook을 통한 프롬프트 자동 처리
- additionalContext를 활용한 시스템 프롬프트 주입
- 키워드 매칭을 통한 리포지토리 경로 자동 인식
- 반복적인 경로 입력 및 디렉토리 이동 작업 제거
귀찮은 것을 싫어하는 저로서는, "다음은 저 프로젝트를 수정해야지"라고 생각했을 때 Claude Code에 매번 리포지토리(Repository)를 알려주는 것이 은근히 스트레스였습니다.
/exit
하고 cd
를 한 뒤
claude
명령어를 입력하거나, 대화 속에서 리포지토리 경로를 직접 타이핑하거나. 뭐, 그렇게 하면 된다고 변명할 수도 있겠지만, 근본적인 귀찮음이 머릿속에서 고개를 듭니다. 프로젝트가 늘어날수록 이 마찰은 쌓여가고, 무엇보다 매번 반복하는 것이 성미에 맞지 않았습니다.
이 기사에서는 UserPromptSubmit Hook과 additionalContext를 사용하여, 프롬프트에 프로젝트 이름만 적어도 리포지토리 경로를 자동으로 전달하는 메커니즘을 만드는 방법을 소개합니다.
사용자: 수발주 시스템의 그 버그를 확인해줘
↓ Hook이 자동으로 additionalContext를 주입
Claude: [수발주 시스템의 경로 /path/to/order-system을 인식한 상태로 답변]
대화 속에서 프로젝트 이름을 자연스럽게 언급하는 것만으로, Claude가 해당 리포지토리를 의식한 답변을 해줍니다. cd나 명시적인 경로 지정도 필요 없습니다.
Claude Code에는 "Hook(후크)"이라는 메커니즘이 있습니다. 특정 이벤트가 발생했을 때 자동으로 스크립트를 실행하여, 그 결과를 Claude의 동작에 반영할 수 있습니다.
Hook의 종류는 여러 가지가 있지만, 이번에 사용할 것은 UserPromptSubmit입니다. 이름 그대로 사용자가 메시지를 전송한 직후에 실행됩니다.
~/.claude/settings.json에 등록합니다.
{
"hooks": {
"UserPromptSubmit": [
...
matcher가 빈 문자열인 경우, 모든 프롬프트에 대해 Hook이 실행됩니다.
Hook 스크립트는 표준 입력(stdin)으로부터 JSON을 받고, 표준 출력(stdout)으로 JSON을 반환합니다.
입력 (stdin):
{
"prompt": "사용자가 전송한 텍스트",
"cwd": "/current/working/directory",
...
출력 (stdout)에서 additionalContext를 반환:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
...
additionalContext에 문자열을 넣으면, Claude의 처리 전에 시스템 프롬프트(System Prompt)와 같은 형태로 삽입됩니다. 여기에 리포지토리 경로를 넣음으로써, Claude가 해당 리포지토리를 전제로 답변하도록 만들 수 있습니다.
#!/usr/bin/env python3
"""
UserPromptSubmit Hook: 프롬프트 내용으로부터 리포지토리를 추정하고,
...
"""
순서대로 포인트를 설명하겠습니다.
REPOS = {
"수발주 시스템": "/path/to/order-system",
"order-system": "/path/to/order-system",
...
동일한 경로를 여러 키워드로 등록할 수 있습니다. 이를 통해 정식 리포지토리 이름이든 일본어 통칭이든 매칭되도록 할 수 있습니다. "수발주 시스템"과 "order-system"이 동일한 경로를 가리키고 있어도 문제없습니다.
UNIQUE_REPOS는 중복 경로를 제외한 표시용 딕셔너리로, 목록을 표시할 때 동일한 프로젝트가 두 번 나오지 않게 하기 위한 것입니다.
def find_repo(prompt: str) -> tuple[str, str] | None:
for keyword in sorted(REPOS.keys(), key=len, reverse=True):
...
키워드를 긴 순서대로 시도하는 것이 중요합니다. 예를 들어 "portal-admin"과 "portal"이 모두 등록되어 있는 경우, 짧은 쪽부터 시도하면 "portal"이 먼저 걸려 잘못된 경로를 반환하게 됩니다. 긴 쪽부터 시도함으로써 더 구체적인 키워드가 우선순위를 갖게 됩니다.
LIST_TRIGGERS = [
"리포지토리 목록", "repo 목록", "어느 리포지토리",
"프로젝트 목록", ...
...
"리포지토리 목록을 보여줘"와 같은 질문을 감지했을 때, 등록된 프로젝트 목록을 additionalContext
로 Claude에게 전달하고, AskUserQuestion 툴을 사용하여 선택 메뉴를 표시합니다. 프로젝트 이름을 잊어버렸을 때나, 다른 사람에게 "어떤 프로젝트들이 있는지" 보여주고 싶을 때 유용합니다.
result = find_repo(prompt)
if result:
...
...
프로젝트 이름이 포함되지 않은 프롬프트일 때는 아무것도 출력하지 않습니다. 이는 Claude에게 불필요한 컨텍스트 (Context) 주입을 피하기 위함입니다. 매번 무언가를 보내면, 관련 없는 대화에서도 리포지토리 정보가 섞여 들어가 노이즈가 됩니다.
cp repo_switcher.py ~/.claude/repo_switcher.py
chmod +x ~/.claude/repo_switcher.py
~/.claude/settings.json을 편집합니다. hooks 섹션이 없다면 추가합니다.
{
"hooks": {
"UserPromptSubmit": [
...
경로는 절대 경로로 작성해야 합니다. ~는 확장되지 않을 수 있습니다.
Claude Code를 실행하여, 등록한 프로젝트 이름이 포함된 메시지를 보내봅니다. 응답의 서두에 시스템 정보로서 [repo-switcher]로 시작하는 행이 보인다면 정상적으로 작동하고 있는 것입니다.
디버깅하고 싶을 때는 스크립트를 직접 실행하여 확인할 수 있습니다.
echo '{"prompt": "受発注システムのバグを確認して"}' | python3 ~/.claude/repo_switcher.py
기대하는 출력:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
...
Claude Code에는 "스킬 (Skill)"이라는 메커니즘도 있습니다. 스킬은 /my-skill과 같이 명시적으로 호출하는 것입니다. 후크 (Hook)는 "전송할 때마다 자동으로 동작하는" 것입니다.
이 스크립트의 가치는 "매번 의식하지 않아도 동작한다"는 점에 있습니다. 매번 /repo-switch라고 입력하는 것은 경로를 직접 타이핑하는 것과 번거로움이 다르지 않습니다. 프롬프트에 자연스럽게 등장하는 프로젝트 이름을 포착하여 동작하기 때문에 마찰이 없습니다. "무언가를 자동화하고 싶다"가 아니라 "무언가를 의식하고 싶지 않다"면 후크가 적합합니다.
이것은 중요한 점인데, repo_switcher.py는 프롬프트마다 매번 경로를 주입하므로 Claude는 새로운 리포지토리를 인식합니다. 하지만 이전 대화에서 읽어들인 파일의 내용이나 코드는 컨텍스트 (Context)에 그대로 남아 있습니다.
그대로 본격적인 작업을 시작하면, Claude가 "아까 그 파일"을 참조하거나 다른 프로젝트의 코드와 혼동된 답변을 내놓는 등 컨텍스트가 혼란스러워질 수 있습니다.
운영 가이드는 다음과 같습니다.
| 작업의 무게 | 대응 |
|---|---|
| 간단히 확인하고 싶은 정도 | 그대로 진행해도 OK |
| 본격적으로 다른 프로젝트 작업에 들어감 | /clear를 실행한 후 프롬프트 전송 |
/clear는 후크나 settings.json 설정에는 영향을 주지 않으므로, 실행 후에도 repo_switcher.py는 계속해서 작동합니다.
| 요소 | 역할 |
|---|---|
UserPromptSubmit 후크 | 프롬프트 전송 시마다 자동 실행 |
additionalContext | Claude에게 추가 정보를 삽입 |
| 키워드 긴 순서 매칭 | 짧은 키워드로 인한 오탐지 방지 |
| 일본어·영어 다중 키 | 통칭이든 정식 명칭이든 매칭 |
| 매칭되지 않을 때 무출력 | 관련 없는 대화에 노이즈 주입 방지 |
설정은 REPOS 딕셔너리에 키워드와 경로를 추가하기만 하면 되므로, 프로젝트가 늘어나도 관리하기 쉬운 구조입니다. Claude Code를 여러 프로젝트에서 사용하고 계신 분들은 꼭 시도해 보세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기