Claude Code를 오래 쓰다 보면 실행 명령이 점점 길어집니다. 기본 실행만 해도 괜찮지만, 여기에 --resume, --worktree, --chrome, --teammate-mode auto, --dangerously-skip-permissions 같은 옵션이 붙기 시작하면 “이번에는 어떤 조합으로 띄워야 하지?“를 계속 다시 생각하게 됩니다.

이럴 때 가장 단순하면서 효과가 큰 방법이 실행 래퍼 함수 하나를 두는 것입니다. 이번 글에서는 실제 cc() bash 함수를 기준으로, Claude 모드와 GLM 모드를 전환하고, resume/worktree/skip-permissions 조합을 짧게 호출하는 패턴을 정리합니다.

Sources

왜 이런 래퍼가 필요한가

문제는 기능이 부족해서가 아니라, 기능이 많아질수록 실행 진입 비용이 커진다는 데 있습니다.

  • 기본 세션을 띄울 때와 이어서 작업할 때의 옵션이 다릅니다.
  • Claude 기본 모드와 GLM 프록시 모드는 필요한 환경 변수가 다릅니다.
  • worktree를 같이 쓰는 날도 있고, 그냥 현재 디렉터리에서 들어가는 날도 있습니다.
  • 빠른 실험용 세션과 안전한 기본 세션을 머릿속으로 계속 구분해야 합니다.

즉, 문제는 “명령어를 기억하기 어렵다"보다 “상황별 실행 규칙이 분산된다"에 가깝습니다. cc() 함수는 그 규칙을 쉘 레벨에서 묶어둔 작은 런처라고 보면 됩니다.

flowchart TD
    A["사용자 입력
cc -grw feature-x"] --> B["옵션 문자열 해석"] B --> C["service_type 결정
c 또는 g"] C --> D["resume/worktree/y 조합 반영"] D --> E["필요한 환경 변수 설정"] E --> F["claude 인자 배열 생성"] F --> G["env ... claude 실행"] classDef input fill:#c5dcef,stroke:#333,color:#333; classDef parse fill:#c0ecd3,stroke:#333,color:#333; classDef mode fill:#fde8c0,stroke:#333,color:#333; classDef output fill:#e0c8ef,stroke:#333,color:#333; class A input; class B,C,D,E,F parse; class G output;

cc() 함수 전체 코드

먼저 원본 함수는 아래와 같습니다.

function cc() {
  local env_vars=(
    "ENABLE_BACKGROUND_TASKS=true"
    "FORCE_AUTO_BACKGROUND_TASKS=true"
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=true"
    "CLAUDE_CODE_ENABLE_UNIFIED_READ_TOOL=true"
  )

  local claude_args=()
  local opt="${1:-}"
  local service_type="c"
  local worktree_name=""
  local use_worktree=false

  if [[ "$opt" == -* ]]; then
    [[ "$opt" == *g* ]] && service_type="g"
    [[ "$opt" == *r* ]] && claude_args+=("--resume")
    [[ "$opt" == *w* ]] && use_worktree=true
    [[ "$opt" == *y* ]] && claude_args+=("--chrome" "--teammate-mode" "auto" "--dangerously-skip-permissions")

    if [[ "$use_worktree" == true ]]; then
      worktree_name="${2:-}"
    fi
  fi

  if [[ -n "$worktree_name" ]]; then
    claude_args+=("--worktree" "$worktree_name")
  elif [[ "$use_worktree" == true ]]; then
    claude_args+=("--worktree")
  fi

  case "$service_type" in
    "g")
      export ANTHROPIC_AUTH_TOKEN="$GLM_API_KEY"
      export ANTHROPIC_BASE_URL="https://api.z.ai/api/anthropic"
      export API_TIMEOUT_MS="3000000"
      export ANTHROPIC_DEFAULT_HAIKU_MODEL="glm-4.5-air"
      export ANTHROPIC_DEFAULT_SONNET_MODEL="glm-4.7"
      export ANTHROPIC_DEFAULT_OPUS_MODEL="glm-5"
      ;;
    "c")
      unset ANTHROPIC_AUTH_TOKEN
      unset ANTHROPIC_BASE_URL
      unset API_TIMEOUT_MS
      unset ANTHROPIC_DEFAULT_HAIKU_MODEL
      unset ANTHROPIC_DEFAULT_SONNET_MODEL
      unset ANTHROPIC_DEFAULT_OPUS_MODEL
      ;;
  esac

  env "${env_vars[@]}" claude "${claude_args[@]}"
}

겉으로 보면 짧은 함수지만, 실제로는 세 가지 책임을 동시에 처리합니다.

  1. 짧은 옵션 문자열을 해석한다.
  2. 실행 모드에 따라 환경 변수를 바꾼다.
  3. 마지막에 claude 실행 인자를 일관된 방식으로 조립한다.

대신 범위는 명확합니다. 이 함수는 어디까지나 세션 시작용 런처에 가깝고, 임의의 추가 claude 인자나 프롬프트를 일반적으로 뒤에 계속 전달하는 형태는 아닙니다. 실제로는 $1을 옵션 문자열로 보고, 필요할 때만 $2를 worktree 이름으로 사용합니다.

1) 옵션 문자열 하나로 여러 실행 패턴을 압축한다

이 함수의 첫 번째 장점은 -grw, -gryw 같은 문자열을 조합형 모드 스위치처럼 쓴다는 점입니다.

공식 CLI 기준으로 보면 --resume은 특정 세션을 이어 붙이거나 선택기로 재개하는 옵션이고, --worktree는 Git 저장소 아래 격리된 worktree 세션을 시작하는 옵션입니다. 이 함수는 그 공식 플래그를 더 짧은 묶음으로 재배치한 셈입니다.

예를 들어 cc -grw my-task는 대략 이렇게 읽으면 됩니다.

  • g: GLM 모드
  • r: 이전 세션 이어서 시작
  • w: worktree 사용

즉, 긴 명령어를 외우는 대신 “오늘 필요한 성격"만 짧게 적는 방식입니다.

flowchart TD
    A["옵션 입력
-gryw"] --> B["g 포함?
GLM 모드"] A --> C["r 포함?
resume 추가"] A --> D["w 포함?
worktree 사용"] A --> E["y 포함?
빠른 자동화 세트 추가"] B --> F["service_type='g'"] C --> G["--resume"] D --> H["--worktree [name]"] E --> I["--chrome
--teammate-mode auto
--dangerously-skip-permissions"] classDef source fill:#c5dcef,stroke:#333,color:#333; classDef branch fill:#c0ecd3,stroke:#333,color:#333; classDef result fill:#fde8c0,stroke:#333,color:#333; class A source; class B,C,D,E branch; class F,G,H,I result;

이 패턴의 핵심은 플래그를 나열하는 CLI의도 중심 단축어로 다시 감싼다는 데 있습니다. CLI는 원래 세밀할수록 좋지만, 사용자는 매번 세밀하게 입력하기보다 자주 쓰는 조합을 빠르게 부르는 편이 생산성에 더 유리합니다.

2) -w는 “지금 이 세션을 격리할지"를 즉시 결정하게 해 준다

개인적으로 이 함수에서 가장 실용적인 부분은 worktree 처리입니다.

cc -w my-feature
cc -gw fix-bug
cc -grw continue-work

여기서 좋은 점은 두 가지입니다. 그리고 공식 문서 기준으로도 --worktree는 이름을 생략하면 자동 이름을 만들 수 있기 때문에, 이 함수의 분기 구조는 실제 CLI 동작과 잘 맞습니다.

첫째, worktree 이름이 있으면 --worktree <name>으로 넘기고, 이름이 없으면 --worktree만 넘깁니다. 즉, “명시적 이름이 있는 격리 세션"과 “자동 이름 기반 격리 세션"을 둘 다 수용합니다.

둘째, 사용자가 직접 긴 claude --worktree ... 명령을 치는 대신, 처음부터 cc -w ...라는 더 짧은 습관으로 worktree 사용을 기본 선택지에 올려둡니다. 이런 래퍼의 진짜 가치는 기능 추가보다 좋은 기본 행동을 더 싸게 만드는 것에 있습니다.

sequenceDiagram
    participant U as 사용자
    participant C as "cc()"
    participant P as 옵션 파서
    participant CLI as "claude"

    U->>C: "cc -gw fix-bug"
    C->>P: "g, w 플래그 해석"
    P-->>C: "GLM 모드 + worktree 이름 반환"
    C->>CLI: "claude --worktree fix-bug"
    Note over C,CLI: GLM 관련 환경 변수는 env/export로 주입

3) -g는 단순 별칭이 아니라 실행 환경 전환이다

이 함수에서 g는 단순히 다른 모델 이름을 넘기는 정도가 아닙니다. 실제로는 Claude 기본 연결 대신, GLM 호환 엔드포인트로 향하도록 관련 환경 변수를 한 번에 바꿉니다.

export ANTHROPIC_AUTH_TOKEN="$GLM_API_KEY"
export ANTHROPIC_BASE_URL="https://api.z.ai/api/anthropic"
export API_TIMEOUT_MS="3000000"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="glm-4.5-air"
export ANTHROPIC_DEFAULT_SONNET_MODEL="glm-4.7"
export ANTHROPIC_DEFAULT_OPUS_MODEL="glm-5"

여기서 하나 짚고 가야 할 점이 있습니다. 위 코드는 GLM 값을 env ... claude에 인라인으로만 넣는 것이 아니라, 현재 셸에 export합니다. 즉, cc -g를 한 번 실행하면 그 환경 변수는 해당 claude 프로세스에서만 쓰이고 끝나는 것이 아니라, 같은 셸 세션에 그대로 남습니다. 이후 cc를 다시 Claude 기본 모드로 실행할 때 unset이 호출되기 전까지는 셸 상태가 GLM 쪽으로 기울어져 있는 셈입니다.

반대로 Claude 기본 모드에서는 이 값들을 unset해서 이전 세션의 환경이 남지 않게 처리합니다. 이 부분이 중요합니다. 래퍼를 쓰지 않고 셸에서 환경 변수를 수동으로 바꿔가며 실행하면, “어제 켜둔 값"이 오늘 세션에 섞이는 문제가 자주 생깁니다.

즉, cc()는 단순 런처가 아니라 실행 전 상태 정리기 역할도 합니다.

flowchart TD
    A["service_type 확인"] --> B{"g 인가?"}
    B -->|"yes"| C["GLM 엔드포인트/모델 env export"]
    B -->|"no"| D["Anthropic 관련 env unset"]
    C --> E["일관된 GLM 세션 시작"]
    D --> F["기본 Claude 세션 시작"]

    classDef start fill:#c5dcef,stroke:#333,color:#333;
    classDef branch fill:#fde8c0,stroke:#333,color:#333;
    classDef action fill:#c0ecd3,stroke:#333,color:#333;
    classDef done fill:#e0c8ef,stroke:#333,color:#333;

    class A start;
    class B branch;
    class C,D action;
    class E,F done;

4) -y는 “빠른 실험 모드"를 한 번에 묶는다

y 플래그는 다음 세 가지를 한 번에 추가합니다.

--chrome
--teammate-mode auto
--dangerously-skip-permissions

공식 문서 관점에서 보면 이 세 개는 성격이 조금 다릅니다.

  • --chrome: 브라우저 자동화/테스트를 켜는 옵션입니다. 현재 문서상 beta 기능입니다.
  • --teammate-mode auto: teammate 표시 방식을 정하는 옵션입니다. auto는 기본값이라서, 이 조합에서 실질적인 행동 변화라기보다 “이 세션은 자동 teammate 표시 흐름을 전제로 한다"는 의도 표시에 가깝습니다.
  • --dangerously-skip-permissions: 권한 확인 프롬프트를 건너뛰는 옵션입니다. 이름 그대로 신중하게 써야 합니다.

즉, 이 조합은 이름 그대로 조심해서 써야 하지만, 반복 실험이나 개인 로컬 자동화에서는 매우 강력합니다. 포인트는 위험한 플래그를 숨기는 것이 아니라, 의도를 명확한 별칭으로 분리하는 것입니다.

예를 들어 평소에는 cc 또는 cc -r로 안전한 기본 흐름을 타고, 정말 빠른 실험이 필요할 때만 cc -ycc -gryw처럼 “나는 지금 빠른 자동화 모드로 들어간다"를 의식적으로 선택하게 됩니다.

이 구조는 실수 방지에도 도움이 됩니다. 긴 명령에서 위험한 플래그 하나를 빼먹거나 반대로 무심코 복붙하는 것보다, -y를 쓸지 말지를 먼저 결정하는 편이 인지적으로 더 안전합니다.

5) 실행 시 항상 붙는 공통 환경 변수도 눈여겨볼 만하다

함수 상단의 env_vars 배열은 실행할 때마다 공통으로 주입됩니다.

"ENABLE_BACKGROUND_TASKS=true"
"FORCE_AUTO_BACKGROUND_TASKS=true"
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=true"
"CLAUDE_CODE_ENABLE_UNIFIED_READ_TOOL=true"

이 값들은 사용자의 로컬 운영 철학을 반영한 기본 프로필이라고 볼 수 있습니다. 즉, 이 함수는 단순한 alias보다 더 강합니다. alias는 짧은 이름만 주지만, 이 패턴은 기본 동작 정책까지 함께 캡슐화합니다.

특히 팀이나 개인이 Claude Code를 반복적으로 같은 방식으로 운영한다면, 이런 공통 환경 변수를 런처에 고정해 두는 편이 세션별 편차를 줄이는 데 좋습니다.

실전에서 어떻게 쓰면 좋은가

아래 정도만 외워도 대부분 커버됩니다.

cc
  • 기본 Claude 세션 시작
cc -r
  • 직전 흐름을 이어서 시작
cc -w feature-auth
  • worktree를 분리해서 새 작업 시작
cc -gw experiment-ui
  • GLM 모드로 worktree 세션 시작
cc -gryw fast-prototype
  • GLM + resume + 빠른 자동화 + worktree까지 한 번에 시작

여기서 중요한 건 모든 옵션을 다 쓰는 것이 아니라, 내가 자주 반복하는 조합을 몇 개의 습관으로 고정하는 것입니다.

이 패턴에서 배울 수 있는 설계 포인트

이 함수는 길지 않지만, CLI 래퍼를 설계할 때 참고할 포인트가 꽤 많습니다.

  1. 옵션을 기능 단위가 아니라 사용 시나리오 단위로 묶는다. -g, -r, -w, -y는 각각 “기술적 세부 옵션"보다 “작업 성격"에 가깝습니다.
  2. 상태 전환은 반드시 되돌리는 코드까지 같이 둔다. GLM 모드에서 export만 하고 끝내지 않고, Claude 모드에서 unset하는 부분이 그래서 중요합니다.
  3. 반복되는 공통 정책은 실행 지점에서 강제한다. 배경 작업, unified read tool 같은 설정을 실행 함수에 넣으면 세션 편차가 줄어듭니다.
  4. 위험한 모드는 숨기지 말고 분리한다. -y처럼 이름 있는 실험 모드가 오히려 안전합니다.

Practical Takeaways

  • cc() 같은 래퍼는 긴 CLI 옵션을 줄이는 도구이기도 하지만, 더 본질적으로는 실행 정책을 고정하는 도구입니다.
  • -w를 짧게 만들면 worktree를 더 자주 쓰게 되고, 결국 작업 격리가 습관이 됩니다.
  • -g는 모델 이름 변경이 아니라 환경 전환이므로 unset까지 함께 설계해야 안전합니다.
  • -y처럼 빠른 자동화 세트는 생산성을 높이지만, 별도의 의식적인 모드로 분리할 때 더 안전합니다.
  • 좋은 런처는 명령을 줄이는 것보다, 매번 같은 품질의 세션을 열게 만드는 데 가치가 있습니다.

Conclusion

Claude Code를 깊게 쓰는 사람일수록 “프롬프트"보다 먼저 “어떤 세션으로 들어가느냐"가 중요해집니다. cc() 같은 작은 함수는 거창한 프레임워크가 아니어도, 매일 반복되는 실행 결정을 정리하고, GLM/Claude 전환과 worktree 습관, 빠른 실험 모드를 한 줄로 묶어주는 꽤 강력한 DX 레이어가 됩니다.

결국 좋은 래퍼의 기준은 복잡한 기능이 아니라, 자주 하는 선택을 더 짧고 더 일관되게 만드는가입니다. 그런 의미에서 이 cc() 함수는 Claude Code를 “실행하는 명령어"가 아니라, 내 작업 방식을 호출하는 진입점에 가깝습니다.