Skip to content

Commit 1e5b3bc

Browse files
committed
feat: Add CI/CD, autocompletion, troubleshooting docs, and update README
1 parent dae31e7 commit 1e5b3bc

File tree

7 files changed

+290
-20
lines changed

7 files changed

+290
-20
lines changed

.github/workflows/ci.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "master" ]
6+
pull_request:
7+
branches: [ "master" ]
8+
9+
jobs:
10+
test-python:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Set up Python
16+
uses: actions/setup-python@v5
17+
with:
18+
python-version: '3.11'
19+
cache: 'pip'
20+
21+
- name: Install dependencies
22+
run: |
23+
cd pipeline
24+
python -m pip install --upgrade pip
25+
pip install -r requirements-dev.txt
26+
pip install -e .
27+
28+
- name: Test with pytest
29+
run: |
30+
cd pipeline
31+
pytest tests/ -v -p no:anchorpy --cov=cloding --cov-report=xml

.github/workflows/docs.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Deploy VitePress site to Pages
2+
3+
on:
4+
push:
5+
branches: ["master"]
6+
7+
# Allows you to run this workflow manually from the Actions tab
8+
workflow_dispatch:
9+
10+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
11+
permissions:
12+
contents: read
13+
pages: write
14+
id-token: write
15+
16+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
17+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
18+
concurrency:
19+
group: pages
20+
cancel-in-progress: false
21+
22+
jobs:
23+
# Build job
24+
build:
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
with:
30+
fetch-depth: 0 # Not needed if lastUpdated is not configured
31+
- name: Setup Node
32+
uses: actions/setup-node@v4
33+
with:
34+
node-version: 20
35+
cache: npm
36+
- name: Setup Pages
37+
uses: actions/configure-pages@v4
38+
- name: Install dependencies
39+
run: npm install
40+
- name: Build with VitePress
41+
run: npm run docs:build
42+
- name: Upload artifact
43+
uses: actions/upload-pages-artifact@v3
44+
with:
45+
path: docs/.vitepress/dist
46+
47+
# Deployment job
48+
deploy:
49+
environment:
50+
name: github-pages
51+
url: ${{ steps.deployment.outputs.page_url }}
52+
needs: build
53+
runs-on: ubuntu-latest
54+
name: Deploy
55+
steps:
56+
- name: Deploy to GitHub Pages
57+
id: deployment
58+
uses: actions/deploy-pages@v4

.github/workflows/pypi.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Publish Python Package to PyPI
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
8+
jobs:
9+
pypi-publish:
10+
name: Build and publish Python distribution to PyPI
11+
runs-on: ubuntu-latest
12+
13+
# Required for PyPI trusted publishing
14+
permissions:
15+
id-token: write
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.11"
24+
25+
- name: Install pypa/build
26+
run: python -m pip install build --user
27+
28+
- name: Build a binary wheel and a source tarball
29+
run: |
30+
cd pipeline
31+
python -m build
32+
33+
- name: Publish package
34+
uses: pypa/gh-action-pypi-publish@release/v1
35+
with:
36+
packages-dir: pipeline/dist/

README.md

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,55 @@ Cloding is a universal wrapper that lets you run Claude Code, Gemini CLI, Codex
1111
╚█████╔╝███████╗╚█████╔╝██████╔╝██║██║░╚████║╚██████╔╝
1212
░╚════╝░╚══════╝░╚════╝░╚═════╝░╚═╝╚═╝░░╚═══╝░╚═════╝
1313

14+
---
15+
1416
**Code with any LLM in a Docker sandbox. Configurable multi-stage code orchestration**
1517

16-
Claude Opus 4.6 costs $5/$25 per Mtok.
17-
Qwen 3 Coder Next costs $0.12/$0.75 per Mtok.
18-
That's 42x cheaper on input, 33x cheaper on output.
18+
Claude Opus 4.6 costs $5/$25 per Mtok.
19+
Qwen 3 Coder Next costs $0.12/$0.75 per Mtok.
20+
*That's 42x cheaper on input, 33x cheaper on output.*
1921

2022
Run multiple coding CLIs from one command, with model shortcuts and optional pipeline orchestration.
2123

22-
Supported tools:
24+
**Supported tools:**
2325
- Claude Code (`claude`)
2426
- Gemini CLI (`gemini`)
2527
- Codex CLI (`codex`)
2628
- GitHub Copilot CLI (`copilot`)
2729
- OpenCode (`opencode`, via custom model entries)
2830

31+
---
32+
33+
## Capabilities
34+
35+
Cloding enhances your development workflow through:
36+
37+
### Universal Access
38+
Seamlessly switch between leading AI coding assistants using a single, unified interface.
39+
40+
### Cost Control
41+
Leverage deeply discounted models via OpenRouter while maintaining high performance. Avoid expensive subscription lock-ins.
42+
43+
### Container Security
44+
Run AI-generated code safely. The built-in Docker mode executes tools in an isolated sandbox with configurable CPU/memory limits, preventing untrusted code from accessing your host system.
45+
46+
### Advanced Automation
47+
The Python-based orchestrator enables multi-stage workflows:
48+
- **Plan:** Analyze requirements and design solutions.
49+
- **Explore:** Gather context from large codebases.
50+
- **Code:** Implement the planned changes.
51+
- **Review:** Automatically verify and refine the code.
52+
53+
### Extensive Documentation
54+
Read our comprehensive [documentation site](https://claudlos.github.io/cloding/) for in-depth walkthroughs and a dedicated [Troubleshooting guide](https://claudlos.github.io/cloding/troubleshooting).
55+
56+
---
57+
2958
## Installation
3059

31-
### Standalone Binary (recommended)
60+
### Standalone Binary (Recommended)
3261

33-
No Node.js required — download a single binary:
62+
No Node.js required — download a single standalone binary:
3463

3564
**macOS / Linux:**
3665

@@ -46,33 +75,50 @@ irm https://raw.githubusercontent.com/claudlos/cloding/master/install.ps1 | iex
4675

4776
### npm
4877

49-
If you already have Node.js 18+:
78+
If you already have Node.js 18+ installed:
5079

5180
```bash
5281
npm install -g cloding
5382
```
5483

84+
**Installing Node.js 18+**
85+
If you don't have Node.js installed, you can quickly install the latest version using the following commands:
86+
87+
**macOS / Linux (via nvm):**
88+
```bash
89+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
90+
nvm install node
91+
```
92+
93+
**Windows (PowerShell via winget):**
94+
```powershell
95+
winget install OpenJS.NodeJS
96+
```
97+
*(Alternatively, you can download the official installer directly from [nodejs.org](https://nodejs.org/))*
98+
99+
---
100+
55101
## Quick Start
56102

57103
```bash
58-
# Set your OpenRouter API key
104+
# 1. Set your OpenRouter API key
59105
export OPENROUTER_API_KEY=sk-or-v1-your-key-here
60106

61-
# Install all CLI tools (Claude Code, Gemini, Codex, Copilot, OpenCode)
107+
# 2. Install all CLI tools (Claude Code, Gemini, Codex, Copilot, OpenCode)
62108
cloding setup
63109

64-
# Start coding
110+
# 3. Start coding!
65111
cloding
66112
```
67113

68-
Basic usage:
114+
### Basic usage:
69115

70116
```bash
71117
cloding # interactive (default: qwen)
72-
cloding -m sonnet # choose shortcut
118+
cloding -m sonnet # choose a specific shortcut
73119
cloding -p "fix failing tests" # one-shot prompt
74120
cloding --list-models # list shortcuts and prices
75-
cloding -h # help
121+
cloding -h # view help
76122
```
77123

78124
## Setup Command

bin/cloding.js

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,20 @@ function forwardSignals(child) {
6262
// .env loader (no dependencies)
6363
// ──────────────────────────────────────────────
6464
function loadEnvFile() {
65-
// Search for .env in: cwd, then user home, then cloding package root
65+
// Search for .env files in decreasing order of priority. We load them in
66+
// reverse so that highest priority (cwd/.env) overwrites global configs.
6667
const candidates = [
67-
path.join(process.cwd(), ".env"),
68-
path.join(os.homedir(), ".env"),
6968
path.join(__dirname, "..", ".env"),
69+
path.join(os.homedir(), ".clodingrc"),
70+
path.join(os.homedir(), ".env"),
71+
path.join(process.cwd(), ".env"),
7072
];
7173

74+
let loadedPaths = [];
75+
7276
for (const envPath of candidates) {
7377
if (fs.existsSync(envPath)) {
78+
loadedPaths.push(envPath);
7479
const lines = fs.readFileSync(envPath, "utf8").split("\n");
7580
for (const line of lines) {
7681
const trimmed = line.trim();
@@ -86,16 +91,15 @@ function loadEnvFile() {
8691
) {
8792
val = val.slice(1, -1);
8893
}
89-
// Don't override existing env vars (check existence, not truthiness —
90-
// empty string values like ANTHROPIC_API_KEY="" must be preserved)
94+
// Overwrite existing parsed env vars from earlier (lower-priority) files,
95+
// but don't overwrite true environment variables passed to the process.
9196
if (!(key in process.env)) {
9297
process.env[key] = val;
9398
}
9499
}
95-
return envPath;
96100
}
97101
}
98-
return null;
102+
return loadedPaths.length > 0 ? loadedPaths : null;
99103
}
100104

101105
// ──────────────────────────────────────────────
@@ -152,6 +156,8 @@ function parseArgs(argv) {
152156
docker: false,
153157
dockerSubcommand: null,
154158
dockerArgs: [],
159+
completion: false,
160+
listModelsRaw: false,
155161
claudeArgs: [], // passthrough args for claude CLI
156162
};
157163

@@ -178,6 +184,11 @@ function parseArgs(argv) {
178184
break;
179185
}
180186

187+
if (arg === "completion") {
188+
args.completion = true;
189+
break;
190+
}
191+
181192
switch (arg) {
182193
case "-m":
183194
case "--model":
@@ -198,6 +209,9 @@ function parseArgs(argv) {
198209
case "--list-models":
199210
args.listModels = true;
200211
break;
212+
case "--list-models-raw":
213+
args.listModelsRaw = true;
214+
break;
201215
case "-v":
202216
case "--version":
203217
args.version = true;
@@ -236,6 +250,23 @@ function printVersion() {
236250
}
237251
}
238252

253+
function printCompletionScript() {
254+
console.log(`_cloding_completion() {
255+
local cur prev
256+
cur="\${COMP_WORDS[COMP_CWORD]}"
257+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
258+
259+
if [[ "$prev" == "-m" || "$prev" == "--model" ]]; then
260+
COMPREPLY=( $(compgen -W "$(cloding --list-models-raw 2>/dev/null)" -- "$cur") )
261+
return 0
262+
fi
263+
264+
COMPREPLY=( $(compgen -W "docker pipeline setup completion --list-models -h -v -m -p" -- "$cur") )
265+
}
266+
complete -F _cloding_completion cloding
267+
`);
268+
}
269+
239270
function printHelp() {
240271
console.log(`
241272
cloding — Claude Code with any model via OpenRouter
@@ -248,6 +279,7 @@ USAGE:
248279
cloding setup Detect and install all CLI tools
249280
cloding pipeline "Add auth" Run the full pipeline (requires Python)
250281
cloding docker <command> Docker container management
282+
cloding completion Print bash/zsh completion script
251283
252284
OPTIONS:
253285
-m, --model <name|id> Model shortcut or full OpenRouter model ID
@@ -1392,6 +1424,16 @@ function main() {
13921424
process.exit(0);
13931425
}
13941426

1427+
if (args.listModelsRaw) {
1428+
console.log(Object.keys(models).join(" "));
1429+
process.exit(0);
1430+
}
1431+
1432+
if (args.completion) {
1433+
printCompletionScript();
1434+
process.exit(0);
1435+
}
1436+
13951437
// ── Setup mode ──
13961438
if (args.setup) {
13971439
handleSetup(args);

docs/.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export default defineConfig({
4747
items: [
4848
{ text: 'CLI Reference', link: '/cli' },
4949
{ text: 'Custom Models', link: '/custom-models' },
50+
{ text: 'Troubleshooting', link: '/troubleshooting' },
5051
]
5152
}
5253
],

0 commit comments

Comments
 (0)