Claude Code's --help lists more than 50 flags. After using it daily for two weeks, I built a 60-line zsh wrapper called cco that bakes in the flags I actually want. The interesting part isn't the code itself, but the architectural decisions behind those 60 lines—most of which I had to backtrack on at least once.
This is the decision log. If you are using Claude Code seriously, some of these will save you from the same backtracks.
Decision 1: Function, not alias, not shell script
The lazy instinct is to use an alias like alias cc="claude --permission-mode acceptEdits ...". This works fine until you want subcommands. Aliases cannot branch on arguments, making subcommands like cco plan or cco review impossible.
A standalone shell script in ~/.local/bin/cc was my next thought. It works for most cases but spawns a subshell. That is fine for stateless commands, but not when wrapping an interactive process like Claude Code, which requires the parent terminal's tty for tmux attachment and interactive prompt rendering. It behaved weirdly in edge cases during testing.
A Zsh function, however, runs in the current shell, inherits the tty cleanly, dispatches on subcommands, and can be tab-completed via compdef. The only cost is that it must live in your .zshrc, making it non-portable to Bash users without a rewrite. For personal use, that is a perfectly acceptable trade-off.
Decision 2: cc vs cco
I picked cc first. It is short and stands for "Claude Code." But on macOS, cc is a symlink to the C compiler at /usr/bin/cc. Since Zsh functions take precedence over $PATH lookups in interactive shells, my function would shadow the system compiler.
While programmatic build tools (like Cargo or CMake) invoke compilers via execvp (which bypasses shell functions), some dependencies and build scripts (such as Rust's cc crate) occasionally invoke cc through shell wrappers. The probability of hitting a collision is low, but the debugging cost of a failed build due to a shadowed compiler is extremely high. I renamed the command to cco. Three keystrokes instead of two is well worth the peace of mind.
Decision 3: Keep the system prompt in a separate file
Claude Code accepts --append-system-prompt "string". While tempting to inline it inside the Zsh function, you should avoid it. System prompts grow over time. Mine started as three lines and quickly expanded to thirty, covering anti-sycophancy and confidence marking rules. Editing multiline strings and handling escape characters inside a shell function is incredibly painful. Decoupling the prompt into an external file is a much cleaner approach.
[AgentUpdate Depth Analysis] The launch of Claude Code signals a major shift of AI Agents from sandboxed web environments to native developer workflows. The author’s refinement of the `cco` wrapper highlights the growing necessity of smooth Agent-OS integration. Compared to heavyweight, orchestrator-driven Agent frameworks, lightweight CLI-native Agents exhibit superior practicality and performance. Moving forward, the boundary of AI Agents will blur as they seamlessly integrate into existing Unix toolchains through shell functions, keybindings, and pipes. Engineering details—such as maintaining TTY integrity, avoiding binary namespace collisions, and decoupling prompt configurations—are not just trivial shell scripting concerns; they represent the foundational challenges of building robust, on-device AI Agent environments.