Claude Code 설치(클로드코드 설치)부터 첫 자동화까지: 리눅스에서 매일 도는 작업 만들기
새벽 1시에 혼자 도는 Claude
제 리눅스 노트북에서는 매일 새벽 1시에 Claude Code가 한 번 돕니다. Claude Code 본체와 플러그인, 같이 쓰는 코딩 도구에 새 버전이 나왔는지 확인하고, 바꿀 만한 게 있으면 제안만 남기는 작업입니다. 직접 고치지는 않습니다. 이 노트북에 걸어 둔 systemd 타이머가 지금(2026-09-30) 25개인데, 그중 하나입니다.
지난 글은 역할별 스킬을 만드는 이야기였습니다. 이번에는 Claude Code를 사람이 없을 때도 돌게 만드는 과정을 순서대로 적습니다. 설치하고, 대화창 없이 부르고, 타이머에 겁니다.
1. Claude Code 설치 방법: 리눅스 설치 명령어 (2026-09-30 공식 문서 기준)
공식 문서가 권하는 방법은 설치 스크립트 한 줄입니다.
curl -fsSL https://claude.ai/install.sh | bash
새 터미널을 열고 확인합니다.
claude --version # 예: 2.1.285 (Claude Code)
claude doctor # 설치 상태와 설정 파일 오류를 읽기 전용으로 점검
그다음 claude 를 한 번 실행하면 브라우저가 열립니다. 거기서 로그인하면 됩니다. 무료 요금제에는 Claude Code가 들어 있지 않고, Pro · Max · Team · Enterprise 또는 Console(API) 계정이 필요합니다.
리눅스 기준 요구 사항은 Ubuntu 20.04 이상 또는 Debian 10 이상, 메모리 4GB 이상입니다. apt · dnf 저장소나 npm으로 설치할 수도 있습니다. 다만 공식 설치 스크립트로 깔아야 백그라운드 자동 업데이트가 됩니다. 스크립트는 실행 파일을 ~/.local/bin/claude 에 둡니다. 이 경로는 3단계에서 다시 나옵니다.
2. 대화 없이 부르기: claude -p
-p(--print)를 붙이면 대화창을 열지 않고 답만 출력한 뒤 끝납니다. 입력은 파이프로 넘길 수 있습니다.
git log --since=yesterday --oneline \
| claude -p "어제 커밋 목록이다. 무엇을 했는지 세 줄로 요약해 줘." \
--model sonnet --tools "" --output-format json --max-budget-usd 1
새벽 1시 작업에도 아래 옵션이 모두 들어 있습니다.
| 옵션 | 하는 일 | 넣은 이유 |
|---|---|---|
--tools "" |
내장 도구(파일 읽기·수정, 셸 실행)를 전부 끔 | 답만 받으면 되는 작업입니다. 사람 없이 도는 동안 파일을 건드릴 일 자체를 없앴습니다 |
--output-format json |
결과를 JSON으로 받음 | 스크립트가 성공 여부(is_error)와 사용량을 읽어야 합니다 |
--max-budget-usd |
쓴 금액이 이 값에 닿으면 멈춤 | 폭주 방지. 새벽 1시 작업은 5달러로 잡았습니다 |
--model |
모델 지정 | 요약 정도는 작은 모델로 충분합니다 |
하나 조심할 점. --tools "" 는 내장 도구만 끕니다. 연결해 둔 MCP 도구는 그대로 남습니다.
직접 재 본 것: 같은 요약, 27만 토큰과 4천 토큰
이 글을 쓰면서 위 명령을 조건만 바꿔 가며 돌려 봤습니다. 넣은 것도 매번 같은 어제 커밋 목록입니다.
| 조건 | 입력 토큰 | 결과 |
|---|---|---|
| 프로젝트 폴더에서 실행, 모델 지정 안 함(제 기본 설정은 Opus) | 272,792 | 상한 1달러에 걸려 실패 |
같은 폴더, --model sonnet |
272,571 | 역시 상한에 걸려 실패 |
| 빈 폴더에서 실행 | 139,777 | 성공 |
+ --strict-mcp-config (MCP 서버를 안 불러옴) |
13,574 | 성공 |
+ --disable-slash-commands --setting-sources project |
4,331 | 성공 |
세 줄 요약에 27만 토큰. 그 대부분은 질문과 함께 딸려 들어간 설정이었습니다. -p 로 불러도 Claude Code는 평소처럼 CLAUDE.md, 전역 규칙, 스킬 목록, 연결해 둔 MCP 서버의 도구 설명까지 전부 읽고 시작합니다. 저처럼 규칙과 MCP 연결을 많이 쌓아 둘수록 딸려 가는 양도 커집니다. 모델을 작은 걸로 바꿔도 입력 토큰은 거의 그대로였습니다.
그래서 자동 작업에는 세 가지를 지킵니다.
- 작업 전용 빈 폴더에서 실행합니다. 프로젝트 폴더의 CLAUDE.md가 따라오지 않습니다.
- 필요 없는 MCP 서버를 안 부릅니다(
--strict-mcp-config). - 스킬과 사용자 전역 설정을 끕니다(
--disable-slash-commands --setting-sources project).
--bare 라는 최소 모드도 있습니다. 써 보니 「Not logged in」 으로 끝났습니다. claude --help 를 보면 --bare 는 구독 로그인 정보를 읽지 않고 API 키로만 인증하거든요. 구독 계정이라면 위 세 가지로 줄이는 편이 낫습니다.
상한은 이번에 제값을 했습니다. 첫 실행이 1달러에서 멈췄으니까요. 설정을 줄이지 않고 그대로 타이머에 걸었다면 매일 아침 이만한 호출이 한 번씩 나갔을 겁니다. 구독 요금제에서는 이 금액이 실제 청구액이 아니라 사용량을 달러로 환산한 값입니다. 그래도 그만큼 한도는 줄어듭니다.
3. systemd 사용자 타이머로 매일 돌리기
cron도 되지만 저는 systemd 사용자 타이머를 씁니다. 실행 기록이 journalctl 에 남고, 컴퓨터가 꺼져 있어 놓친 실행을 나중에 따라잡게 할 수 있어서입니다.
스크립트 ~/bin/daily-note.sh:
#!/usr/bin/env bash
set -euo pipefail
cd "$HOME/daily-note" # 설정이 따라오지 않는 작업 전용 폴더
git -C "$HOME/my-project" log --since=yesterday --oneline \
| claude -p "어제 커밋 목록이다. 무엇을 했는지 세 줄로 요약해 줘." \
--model sonnet --tools "" --output-format json --max-budget-usd 1 \
--strict-mcp-config --disable-slash-commands --setting-sources project \
> "$HOME/daily-note/$(date +%F).json"
서비스 ~/.config/systemd/user/daily-note.service:
[Unit]
Description=Daily commit summary by Claude Code
[Service]
Type=oneshot
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=%h/bin/daily-note.sh
타이머 ~/.config/systemd/user/daily-note.timer:
[Unit]
Description=Run daily-note every morning at 07:00
[Timer]
OnCalendar=*-*-* 07:00:00
Persistent=true
[Install]
WantedBy=timers.target
켜는 명령입니다.
systemctl --user daemon-reload
systemctl --user enable --now daily-note.timer
loginctl enable-linger "$USER" # 로그인하지 않은 상태에서도 사용자 타이머가 돌게
Persistent=true 가 앞에서 말한 그 따라잡기 설정입니다. enable-linger 를 빼먹으면 로그아웃해 있는 동안 타이머가 돌지 않습니다.
조용히 죽는 함정: status=127
서비스 파일에 Environment=PATH=… 줄을 넣은 이유가 있습니다. systemd 사용자 서비스는 제 터미널의 PATH를 물려받지 않거든요. 이 줄이 없으면 ~/.local/bin 에 있는 claude 를 못 찾습니다. 이 글을 쓰면서 PATH를 /usr/bin:/bin 으로만 두고 위 스크립트를 돌려 보니 바로 이렇게 끝났습니다.
line 5: claude: command not found
exit=127
실제 운영에서 이미 겪은 일입니다. 매일 아침 저장소 상태를 보는 자체 점검 서비스가 이틀 연속(8월 31일, 9월 1일) status=127 로 죽어 있었습니다. 원인은 같았습니다. nvm으로 깐 node를 /usr/bin/env node 로 불렀는데, systemd의 PATH에는 node가 없었습니다. 알림도 없었습니다. 당시 이 서비스는 텔레그램으로 알림을 보내지 않는 설정이었고, 실패는 journalctl 에만 남았습니다. 그걸 매일 읽는 사람은 없었습니다.
그 뒤로 지키는 규칙은 두 가지입니다.
- 서비스 파일에서는 실행 파일을 절대 경로로 쓰거나,
Environment=PATH=로 경로를 직접 적습니다. enable한 뒤에도 한 번은 직접 돌려서 종료 상태를 봅니다.
systemctl --user start daily-note.service
systemctl --user status daily-note.service # Main PID 줄의 status=0/SUCCESS 확인
journalctl --user -u daily-note.service -n 20
처음 만든다면
매일 손으로 하던 확인 작업 하나로 시작하세요. 어제 커밋 요약, 에러 로그 훑기, 의존성 업데이트 확인 정도면 됩니다. 도구는 끄고(--tools ""), 상한을 걸고(--max-budget-usd), 빈 폴더에서 돌리고, 첫 실행은 직접 해서 결과 파일과 종료 상태를 확인하세요.
다음 글에서는 매일 돌리다 보면 부딪히는 요금제 한도 이야기를 합니다. 한도에 실제로 걸려 작업이 멈춘 날의 기록입니다.
이 블로그에 쓴 글들을 바탕으로 전자책과 템플릿 묶음을 만들어 볼까 고민하고 있어요. 낼지, 낸다면 언제일지는 아직 미정.
나오면 알림을 받고 싶은 분은 제목을 [출시 알림]으로 해서 codenara.contact@gmail.com 으로 메일 주세요.
개인정보 안내: 받은 메일 주소는 출시 알림 한 번 보내는 데만 쓰고, 보내고 나면 지워요. 내지 않기로 하면 그때 지우고, 요청하시면 그 전에라도 바로 지웁니다.
이런 자동화를 직접 세팅하고 싶거나 팀 환경에 맞게 설계해 보고 싶다면 codenara.contact@gmail.com 으로 연락 주세요. 교육·세팅 문의는 따로 받고 있습니다.