Setting Up AI Coding CLI Tools and Connecting Custom LLM APIs: A Practical Guide
A practical guide to installing command-line AI coding tools behind restricted networks, wiring them to OpenAI-compatible model endpoints, managing API keys securely, switching between providers with profiles, controlling costs, and troubleshooting common installation and connection failures.
Separating Two Critical Paths
Many AI coding tools bundle the client and model access into a single overseas service. When the network is unreachable, both installation and inference fail. If the subscription channel doesn’t support your payment method, onboarding gets stuck too. A more robust approach is to split these two paths: the CLI client handles terminal interaction, sessions, and context management, while inference is delegated to a swappable LLM API.
Most model providers now offer OpenAI-compatible APIs. Such an API typically involves three elements: the base_url (the API root, usually ending in /v1), the model name, and the Authorization: Bearer
Runtime Setup and Version Checks
CLI coding tools typically depend on Node.js. Check the tool’s official documentation for the minimum version. If the docs don’t specify, assume Node.js 18 and prefer the LTS release.
Windows: Download the LTS .msi installer from a Node.js mirror directory (such as the npmmirror mirror), run the wizard, and verify the file’s integrity against the SHASUMS256.txt checksums in the same directory.
macOS: Download the .pkg installer matching your chip architecture (Apple Silicon or Intel). If you already use nvm, set a mirror first and then install:
export NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node/nvm install --lts
Linux: Install via nvm as above, or use your distribution’s package repositories. Either way, confirm the version meets the requirement.
After installation, open a new terminal and run:
node -vnpm -v
node -v should print v18 or higher, e.g. v20.x.x. npm ships with Node.js; just confirm it prints a version. If node -v reports a version below 18, upgrade Node.js before continuing. If multiple Node.js versions exist on the machine, run which node (where node on Windows) to see which one is being called.
Installing via a Fast Mirror
The default npm registry may be slow or time out depending on your network. Switch npm to a mirror:
npm config set registry https://registry.npmmirror.comnpm config get registry
The second command should output https://registry.npmmirror.com/.
Install the tool globally. Use the package name from the tool’s official documentation, and pin the version to avoid accidental upgrades:
npm install -g <package>@<version>
Then verify:
<command> --version
If it prints a version number, the installation succeeded.
Two caveats. First, the registry setting is global and affects all npm operations. If a scoped package (e.g. @company/package) lives on a private registry, configure it separately, e.g. npm config set @company:registry <private-registry-url>. Second, mirrors sync with a delay, so the latest version may not be available yet. If a version can’t be found, verify the version number first, then decide whether to wait for sync.
Avoid sudo npm install -g. It makes global files root-owned and complicates future upgrades. If you hit an EACCES permission error, move the global install directory to your home directory:
npm config set prefix ~/.npm-globalexport PATH="$HOME/.npm-global/bin:$PATH"
Then rerun the install command.
Creating an API Key and Setting Environment Variables
Create an API Key in your provider’s console and choose pay-as-you-go billing. Use each key for only one project or machine so it can be revoked independently. If the console supports spending limits or alerts, enable them.
Never hard-code keys in source code, config files, or Git repositories. Store them in environment variables that the client reads. The variable names below are examples—use whatever your tool requires.
On macOS or Linux, write the variables to a dedicated file with restricted permissions:
touch ~/.config/llm.envchmod 600 ~/.config/llm.env
Open the file in an editor and add two lines (don’t use echo, so the key stays out of your shell history):
export LLM_API_KEY="your-key"export LLM_BASE_URL="https://your-provider-endpoint/v1"
Then add source ~/.config/llm.env to ~/.zshrc or ~/.bashrc.
On Windows, set user-level environment variables in PowerShell:
[Environment]::SetEnvironmentVariable("LLM_API_KEY", "your-key", "User")[Environment]::SetEnvironmentVariable("LLM_BASE_URL", "https://your-provider-endpoint/v1", "User")
Reopen the terminal for the changes to take effect.
When checking whether variables loaded, print only the length, never the key itself: echo ${#LLM_API_KEY} in bash/zsh, or $env:LLM_API_KEY.Length in PowerShell.
Next, verify API connectivity:
curl -s "$LLM_BASE_URL/models" -H "Authorization: Bearer $LLM_API_KEY"
Normally the response lists available models in JSON. Some providers don’t support the /models endpoint—if you get a 404, fall back to a minimal chat request:
curl -s "$LLM_BASE_URL/chat/completions" \-H "Authorization: Bearer $LLM_API_KEY" \-H "Content-Type: application/json" \-d '{"model":"<model-name>","messages":[{"role":"user","content":"ping"}],"max_tokens":8}'
If the response JSON contains a choices field, your key, base URL, and model name are all working. A 401 usually indicates a key problem. On Windows, use curl.exe to avoid PowerShell treating curl as an alias.
Managing Multiple Providers with Profiles
Different tasks suit different models: fast completions favor small models, complex refactors favor large ones. Saving these combinations as profiles is more reliable than editing environment variables each time. Example (paths and field names depend on your tool’s documentation):
{"profiles": {"fast": {"provider": "openai-compatible","base_url": "https://your-provider-endpoint/v1","model": "<small-model-name>","api_key_env": "LLM_API_KEY"},"strong": {"provider": "openai-compatible","base_url": "https://another-provider-endpoint/v1","model": "<large-model-name>","api_key_env": "LLM_API_KEY_2"}}}
Store only the environment variable name (api_key_env) in profiles, never the key itself. This way the config file can be committed to version control while keys remain on the local machine. Each provider needs its own key variable.
Switch with the parameter your tool supports, e.g.:
<command> --profile fast
Cost Boundaries
Pay-as-you-go billing charges per actual usage, usually measured in tokens, with separate prices for input and output. A rough estimate: cost per call ≈ (input tokens × input price) + (output tokens × output price). See each provider’s public pricing page for exact rates.
Subscriptions have a fixed monthly cost and suit teams with steady, heavy usage. Pay-as-you-go suits irregular usage or switching between multiple models, but requires actively monitoring consumption. Neither model is inherently better—comparisons must hold the model, context length, and call count constant. Even with the same model, usage rises sharply if the tool sends large context every call.
To control usage:
- Review usage details in the provider console regularly.
- Set budget caps or alerts if the provider supports them.
- Limit per-request context length; don’t send an entire repository at once.
- Check for looping or duplicate requests.
Troubleshooting Guide
Order of diagnosis: version first, then network, then key and base URL, then model name.
| Symptom | Likely Cause | How to Check |
|---|---|---|
| npm install times out or ETIMEDOUT | Mirror not applied | Run npm config get registry and confirm it points to the mirror |
| Command not found after install | Global bin directory not in PATH | Run npm config get prefix, add its bin directory to PATH, reopen terminal |
| Tool exits immediately with syntax errors | Node.js below 18 | Run node -v, upgrade, and retry |
| EACCES: permission denied | No write access to global directory | Change prefix to a user directory; don’t use sudo |
| 401 Unauthorized | Wrong/expired key, or env var not loaded | Run echo ${#LLM_API_KEY} to check length, open a new terminal, regenerate key if needed |
| 403 Forbidden | Model not enabled, region restriction, or insufficient balance | Check model permissions and balance in the console |
| 404 or model not found | Typo in model name, or model not offered by the provider | Query /models to verify the model name |
| Mirror works but model calls time out | System proxy conflicts with the API endpoint | Run echo $HTTPS_PROXY; set NO_PROXY for the API domain if needed |
| HTML page returned or path errors | base_url missing /v1 or wrong path | Fix base_url against the provider’s API documentation |
| Calls succeed but costs are unusually high | Context too long or duplicate requests | Check per-call token counts in usage details and narrow the context |
Security and Risk Notes
- Keep keys out of repositories. Add key files and local config files to .gitignore. Before committing, run
git statusandgit diff --cachedto confirm no keys are staged. - Never paste keys into chats, screenshots, or logs. If a key leaks, revoke it in the console immediately and generate a new one.
- Use trustworthy mirrors only—stick to well-known public mirrors such as npmmirror. Pin versions during installation and verify them against official release notes.
- Mirrors speed up downloads but don’t replace verification. After installing, run
npm ls -g --depth=0to review global packages and remove anything unfamiliar. - In teams, manage profile files and keys centrally rather than letting each member store keys independently.
Conclusion
- Verify Node.js is version 18 or higher.
- Point npm at a fast mirror and install the tool with a pinned version.
- Store the API Key in environment variables and verify connectivity with curl.
- Save provider/model combinations as profiles and switch as needed.
- When something breaks, work through the troubleshooting table step by step.
Above all: never commit API keys to a Git repository.
