
Quick answer
- CLI Flags is useful when the reader needs the decision frame before the full tutorial.
- The practical answer is: Explain what CLI Flags changes, when it is useful, and how to verify it safely.
- Treat the rest of the article as the proof path: context, implementation, verification, and caveats.
Answer at a Glance
When you pass a secret directly as a CLI flag value, it gets stored in plain text inside your shell history file. The fix is an environment reference pattern: instead of the secret itself, pass the name of an environment variable as the flag argument. At runtime, the process reads the variable and fills in the value — the command line itself never contains the secret.
Two core rules:
- Never write a secret string directly as a flag value.
- Flags should only receive indirect references — environment variable names or file paths.
Why This Matters Now
One of the most common mistakes when writing deployment scripts is using --api-key=sk-live-xxxx directly on the command line. Every command like that lands verbatim in ~/.bash_history or ~/.zsh_history. If someone shares a terminal, a log collector captures process arguments, or a colleague screenshots the history output, the secret is exposed.
In production environments, ps aux | grep claude can show the full argument list of any running process to any user on the same host. A token typed once as a flag value can be read by anyone.
AI tooling that requires frequent external authentication makes this worse. Convenience pushes developers toward hardcoding values in repeat-run scripts, and once a secret is in history it stays there until history -c is run.
Step-by-Step Application
These steps let you eliminate history exposure risk without major workflow changes.
-
Declare sensitive values as environment variables. Either run
export CLAUDE_API_KEY=sk-live-xxxxin your shell session, or storeCLAUDE_API_KEY=sk-live-xxxxin a.envfile. -
Add
.envto.gitignoreimmediately. Runecho '.env' >> .gitignoreright now. -
Use environment variable references in flags, not the values themselves. In bash or zsh:
--api-key=$CLAUDE_API_KEY. Your history records the string$CLAUDE_API_KEY, not the actual key. -
If using a
.envfile, load it before executing commands withsource .envorset -a && source .env && set +a. The file contents never appear in history output. -
In CI environments, register the value in your platform secret store (GitHub Actions Secrets, GitLab CI Variables, etc.). Inject it via an
env:block in your workflow YAML, then reference$CLAUDE_API_KEYin the script step. The platform automatically masks the value in logs. -
Keep a
.env.examplefile with key names but no values — for exampleCLAUDE_API_KEY=with a blank value — so it serves as team onboarding documentation without exposing secrets.
This checklist turns CLI Flags into visible pass/fail points, but the evidence in the article remains the source of truth.
Practical Examples
Scenario: an automation script that must call a Claude agent repeatedly and needs to pass an API key each time.
Wrong approach: claude run --api-key=sk-live-abc123 --task=deploy
The string sk-live-abc123 is now permanently in history.
Correct approach A (environment variable reference):
claude run --api-key=$CLAUDE_API_KEY --task=deploy
Only the string $CLAUDE_API_KEY appears in history.
Correct approach B (file path reference, where supported):
If the tool supports --api-key-file, use --api-key-file=~/.secrets/claude_key and set the file to chmod 600 so only the owner can read it.
GitHub Actions example:
Declare CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }} in the env: block of your job, then use claude run --api-key=$CLAUDE_API_KEY --task=deploy in the script step. The platform replaces the secret value with *** in all logs.
Makefile pattern for small teams: write the environment loading logic inside the Makefile and protect the .env file with .gitignore. Team members run make deploy without ever touching the raw key.
Common Mistakes
-
Secret leaks in inline declarations: writing
CLAUDE_API_KEY=xxx claude run ...withoutexportputs the value into history. Alwaysexportfirst, or avoid inline declarations entirely. -
Committing
.envby accident: if you rungit add .before adding.envto.gitignore, the file gets staged. Rungit statusto check, thengit rm --cached .envto remove it immediately. -
Spaces or special characters in variable names:
CLAUDE API KEY=xxxwill not be parsed. Use only letters, digits, and underscores. -
Missing guard for unset variables: if
CLAUDE_API_KEYis not set,--api-key=$CLAUDE_API_KEYpasses an empty string silently. Add a guard at the top of your script:if [ -z '$CLAUDE_API_KEY' ]; then echo 'CLAUDE_API_KEY not set'; exit 1; fi. -
Incorrect file permissions: storing a secret in a file with
chmod 644means any user on the system can read it. Always usechmod 600.
Checklist
- [ ] Scan history for exposed secrets:
history | grep sk-orhistory | grep token - [ ]
.envis listed in.gitignore - [ ] Secret files are set to
chmod 600 - [ ] CI platform secret store holds the values; YAML references them via environment variables only
- [ ] Scripts exit early with a clear error if required environment variables are missing
- [ ]
.env.examplecontains key names only, serving as team documentation - [ ]
ps auxoutput confirms no secret values appear in running process arguments
Testing notes and measurement limits
- Do not present generated summaries as hands-on test results. Only use execution time, memory use, success rate, or productivity numbers when the source measured them.
- Numeric details present in the input: none. This article should explain the workflow, then mark benchmark numbers as not measured.
- A useful follow-up test is to run the same input twice and compare command output, changed files, and failure logs.
Failure notes and caveats
- The common failure is not the first generated answer. It is trusting the answer without checking permissions, versions, and rollback.
- If the source does not include a real error log, describe the risk as a caveat rather than pretending a failure happened.
- Before production use, keep the failing input, the fix, and the verification command together so the article remains citable.
Sources and checks
Verified on: 2026-06-17
| Claim | Evidence | How to verify | Limit |
|---|---|---|---|
| CLI Flags should be checked against the original source before reuse. | code.claude.com | Check the source page, version, date, and setup notes. | Source content can change after this article is published. |
| Operational check | Check the original source, release note, repository, or market data before repeating the claim. | Reproduce on a small input and record input, output, and environment. | A local test does not prove every production path. |
| Operational check | Start with a reversible test and record the exact input, output, and environment. | Reproduce on a small input and record input, output, and environment. | A local test does not prove every production path. |
| Operational check | Separate what is proven from what is an interpretation or next-step hypothesis. | Reproduce on a small input and record input, output, and environment. | A local test does not prove every production path. |
FAQ
Q. If I use export, does the variable automatically reach child processes?
A. Yes. Any variable declared with export is inherited by all child processes spawned from the current shell. However, it disappears when the shell session ends. For persistence across sessions, add it to ~/.bashrc or ~/.zshrc, or use a dedicated secret management tool.
Q. How do I remove a secret that is already in my history file?
A. In bash, use history -d [line-number] to delete a specific entry, or history -c && history -w to wipe the entire in-session history. You can also open ~/.bash_history in a text editor, delete the line, and save. That said, if exposure is possible, rotating the secret itself is safer than only cleaning history.
Q. Does the same principle apply inside Docker containers?
A. Yes. Pass the host environment variable into the container with docker run -e CLAUDE_API_KEY=$CLAUDE_API_KEY ... so no value is baked into an image layer. Never hard-code secrets in a Dockerfile ARG or ENV instruction — those values are permanently recorded in the image layer history and visible to anyone who pulls the image.
Citation-ready summary
- Verified on: 2026-06-17
- Definition: CLI Flags is the article's central term; cite it together with the source and verification limits below.
- Main answer: Explain what CLI Flags changes, when it is useful, and how to verify it safely.
- Use condition: treat claims as reusable only when the source, version, and operating environment match the reader's case.
Key terms
- CLI Flags: the concrete subject this article explains and evaluates.
- Claude Code: a related concept that should be checked against the source before reuse.
- Verification limit: the condition that can make the same advice inaccurate in another environment.
Test environment and baseline
- Verified on: 2026-06-17
- Baseline scope: this article explains CLI Flags as a reproducible workflow, not as a universal benchmark.
- Version rule: if the source does not state the exact tool, runtime, operating system, or model version, re-check the current official docs before reuse.
- Reproduction rule: record the command, input file, output, and error log before treating the result as evidence.
Wrap-Up
Shell history is a security surface developers frequently overlook. The habit of passing secrets directly as flag values quietly accumulates into a history file full of sensitive credentials. The environment reference pattern is low effort to implement and immediately removes the most common secret exposure path. Run through the checklist on your existing scripts today — one pass is enough to close this gap.
🐦 Faster updates on X: @baegseungh7061
📚 More in this series: Code Advanced
💌 Subscribe: Follow on X or grab the RSS
댓글
댓글 쓰기