https://github.com/milliorn/chatgpt-cli
Chat with OpenAI GPT-3 using Golang, NodeJs, or Python
https://github.com/milliorn/chatgpt-cli
ai artificial-intelligence chatbot chatbots chatgpt chatgpt3 cli command-line-interface command-line-tool conversational-ai developer-tool gpt-3 interactive language-model natural-language-processing nlp openai openai-gpt3 terminal text-generation
Last synced: 3 months ago
JSON representation
Chat with OpenAI GPT-3 using Golang, NodeJs, or Python
- Host: GitHub
- URL: https://github.com/milliorn/chatgpt-cli
- Owner: milliorn
- Created: 2023-05-12T21:57:25.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2025-09-01T09:40:29.000Z (10 months ago)
- Last Synced: 2025-09-01T10:54:50.861Z (10 months ago)
- Topics: ai, artificial-intelligence, chatbot, chatbots, chatgpt, chatgpt3, cli, command-line-interface, command-line-tool, conversational-ai, developer-tool, gpt-3, interactive, language-model, natural-language-processing, nlp, openai, openai-gpt3, terminal, text-generation
- Language: Go
- Homepage:
- Size: 146 KB
- Stars: 1
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# ChatGPT CLI
[](https://github.com/milliorn/chatgpt-cli/actions/workflows/github-code-scanning/codeql)




A command-line interface for having interactive, real-time conversations with OpenAI's ChatGPT models — implemented in three programming languages: **Node.js**, **Go**, and **Python**. Each implementation is functionally equivalent and demonstrates idiomatic patterns for its respective language. This repository is ideal for developers who want to quickly spin up a local ChatGPT CLI, compare multi-language API integration approaches, or use it as a learning reference.
---
## Table of Contents
1. [Overview](#overview)
2. [Features](#features)
3. [Repository Structure](#repository-structure)
4. [Prerequisites](#prerequisites)
- [Obtaining an OpenAI API Key](#obtaining-an-openai-api-key)
- [Node.js Prerequisites](#nodejs-prerequisites)
- [Go Prerequisites](#go-prerequisites)
- [Python Prerequisites](#python-prerequisites)
5. [Configuration](#configuration)
6. [Installation & Usage](#installation--usage)
- [Node.js](#nodejs)
- [Go](#go)
- [Python](#python)
7. [How It Works](#how-it-works)
- [Architecture Overview](#architecture-overview)
- [Node.js Implementation Details](#nodejs-implementation-details)
- [Go Implementation Details](#go-implementation-details)
- [Python Implementation Details](#python-implementation-details)
8. [Error Handling & Resilience](#error-handling--resilience)
9. [Implementation Comparison](#implementation-comparison)
10. [Troubleshooting](#troubleshooting)
11. [Contributing](#contributing)
12. [Security](#security)
13. [License](#license)
14. [Acknowledgements](#acknowledgements)
---
## Overview
**ChatGPT CLI** provides a lightweight, interactive terminal interface to the [OpenAI Chat Completions API](https://platform.openai.com/docs/api-reference/chat). You type a prompt, the application sends it to OpenAI, and the model's response is printed directly in your terminal. The loop repeats until you type `exit`.
The project contains three complete, independent implementations that all share the same high-level design:
- **Node.js** — Uses the official `openai` npm package with async/await and exponential backoff retry logic.
- **Go** — Uses Go's standard library `net/http` directly, with structured JSON types and a 10-second request timeout.
- **Python** — Uses the `requests` library with Python dataclasses for type-safe request construction.
You only need to set up one implementation — choose whichever language you are most comfortable with.
---
## Features
- **Interactive conversation loop** — Type prompts and receive responses in real time without leaving the terminal.
- **Clean exit** — Type `exit` at any prompt to gracefully shut down the application.
- **Empty input guard** — If you press Enter without typing anything, the application prompts you again rather than sending a blank request.
- **Environment-based configuration** — API credentials are loaded from a `.env` file and are never hardcoded.
- **Exponential backoff with retry (Node.js)** — Automatically retries failed requests up to three times, with delays of 2 s, 4 s, and 8 s. Respects the `Retry-After` response header when rate-limited.
- **Request timeout (Go & Python)** — HTTP requests are bounded by a hard 10-second timeout to prevent indefinite hangs.
- **Structured error reporting** — All implementations clearly report configuration errors and API failures to the terminal.
- **Automated dependency updates** — Dependabot monitors all three package ecosystems and automatically merges patch and minor updates.
---
## Repository Structure
```
chatgpt-cli/
├── .github/
│ ├── dependabot.yml # Monitors npm, Go modules, and pip for updates
│ └── workflows/
│ └── automerge.yml # Auto-approves patch/minor Dependabot PRs
├── golang/
│ ├── main.go # Entry point: input loop, request dispatch, response display
│ ├── types.go # Go structs: Request, Message, Response, Choice, Content
│ ├── go.mod # Module definition: requires Go 1.22, godotenv v1.5.1
│ ├── go.sum # Dependency checksums (do not edit manually)
│ ├── .env # Your credentials (not committed to version control)
│ ├── .gitignore
│ └── readme.md
├── nodejs/
│ ├── chatgpt.js # Complete CLI application (ES module)
│ ├── package.json # npm scripts, dependencies (dotenv, openai)
│ ├── package-lock.json # Locked dependency tree
│ ├── .env # Your credentials (not committed to version control)
│ ├── .gitignore
│ └── README.md
├── python/
│ ├── chat_cli.py # Entry point: input loop and output display
│ ├── send_request.py # Handles HTTP request construction and execution
│ ├── models.py # Dataclasses: Message, RequestBody
│ ├── requirements.txt # Pinned dependencies
│ ├── .env # Your credentials (not committed to version control)
│ └── readme.md
├── SECURITY.md # Vulnerability reporting policy
└── readme.md # This file
```
> **Note:** The `.env` files listed above are for your local credentials only. They are excluded from version control via `.gitignore`. Never commit API keys to a repository.
---
## Prerequisites
### Obtaining an OpenAI API Key
All three implementations require a valid OpenAI API key. Follow these steps to obtain one:
1. Visit [https://platform.openai.com/signup](https://platform.openai.com/signup) and create an account, or sign in if you already have one.
2. Navigate to **API Keys** in the left sidebar (or go to [https://platform.openai.com/api-keys](https://platform.openai.com/api-keys)).
3. Click **Create new secret key**, give it a descriptive name, and copy the key immediately — it will not be shown again.
4. If your account belongs to an organization, note your **Organization ID** from [https://platform.openai.com/account/org-settings](https://platform.openai.com/account/org-settings). The Node.js implementation requires this; Go and Python do not.
> **Billing:** OpenAI API usage is billed per token. New accounts may receive free credits. Review your [usage limits](https://platform.openai.com/account/limits) before running the application extensively.
---
### Node.js Prerequisites
| Requirement | Minimum Version | How to Check |
|---|---|---|
| Node.js | 18.x LTS or later | `node --version` |
| npm | 8.x or later | `npm --version` |
Download Node.js from [https://nodejs.org](https://nodejs.org). npm is bundled with Node.js.
---
### Go Prerequisites
| Requirement | Minimum Version | How to Check |
|---|---|---|
| Go | 1.22 or later | `go version` |
Download Go from [https://go.dev/dl](https://go.dev/dl). Follow the official installation instructions for your operating system. After installation, ensure `go` is on your `PATH`.
---
### Python Prerequisites
| Requirement | Minimum Version | How to Check |
|---|---|---|
| Python | 3.7 or later | `python --version` or `python3 --version` |
| pip | Any recent version | `pip --version` |
Download Python from [https://www.python.org/downloads](https://www.python.org/downloads). pip is included with Python 3.4+. Using a virtual environment is strongly recommended (see [Python setup](#python) below).
---
## Configuration
Each implementation reads credentials from a `.env` file located in its own subdirectory. You must create this file before running the application. The `.env` file is excluded from version control.
### Node.js — `nodejs/.env`
```ini
OPENAI_API_KEY=sk-...your-key-here...
OPENAI_ORGANIZATION=org-...your-org-id-here...
```
Both variables are required. The application exits with a clear error message if either is missing.
### Go — `golang/.env`
```ini
OPENAI_API_KEY=sk-...your-key-here...
```
Only the API key is required. The Go implementation does not use an organization ID.
### Python — `python/.env`
```ini
OPENAI_API_KEY=sk-...your-key-here...
```
Only the API key is required. The Python implementation does not use an organization ID.
> **Security reminder:** Treat your API key like a password. Do not share it, commit it, or embed it in code. If a key is ever exposed, rotate it immediately from the OpenAI dashboard.
---
## Installation & Usage
### Node.js
**1. Navigate to the Node.js directory:**
```bash
cd nodejs
```
**2. Install dependencies:**
```bash
npm install
```
This installs `dotenv` (environment variable loading) and `openai` (official OpenAI API client) as declared in `package.json`.
**3. Create your `.env` file** (see [Configuration](#configuration) above).
**4. Start the application:**
```bash
npm start
```
Alternatively, you can run it directly with Node.js:
```bash
node chatgpt.js
```
**5. Interact with the chatbot:**
```
Please enter a prompt (type "exit" to quit): What is the capital of France?
ChatGPT: The capital of France is Paris.
Please enter a prompt (type "exit" to quit): exit
Goodbye!
```
---
### Go
**1. Navigate to the Go directory:**
```bash
cd golang
```
**2. Download dependencies:**
```bash
go mod download
```
This fetches `github.com/joho/godotenv`, the only external dependency.
**3. Create your `.env` file** (see [Configuration](#configuration) above).
**4. Run the application:**
You can run without building (useful for development):
```bash
go run .
```
Or run with explicit file names:
```bash
go run main.go types.go
```
To compile a binary and then run it:
```bash
go build -o chatgpt-cli
./chatgpt-cli
```
On Windows the binary will be named `chatgpt-cli.exe` and is executed with:
```bash
.\chatgpt-cli.exe
```
**5. Interact with the chatbot:**
```
Enter your prompt (or 'exit' to quit): Explain recursion in simple terms.
ChatGPT: Recursion is when a function calls itself...
Enter your prompt (or 'exit' to quit): exit
Goodbye!
```
---
### Python
**1. Navigate to the Python directory:**
```bash
cd python
```
**2. (Recommended) Create and activate a virtual environment:**
On macOS/Linux:
```bash
python3 -m venv venv
source venv/bin/activate
```
On Windows (Command Prompt):
```cmd
python -m venv venv
venv\Scripts\activate.bat
```
On Windows (PowerShell):
```powershell
python -m venv venv
venv\Scripts\Activate.ps1
```
Using a virtual environment isolates this project's dependencies from your system Python installation.
**3. Install dependencies:**
```bash
pip install -r requirements.txt
```
This installs the following pinned packages:
| Package | Version | Purpose |
|---|---|---|
| `requests` | 2.32.3 | HTTP client for OpenAI API calls |
| `python-dotenv` | 1.0.1 | Loads `.env` files into environment variables |
| `certifi` | 2025.1.31 | Up-to-date CA certificates for HTTPS |
| `charset-normalizer` | 3.4.1 | Character encoding detection (requests dependency) |
| `idna` | 3.10 | Internationalized domain names (requests dependency) |
| `urllib3` | 2.3.0 | Low-level HTTP client (requests dependency) |
**4. Create your `.env` file** (see [Configuration](#configuration) above).
**5. Start the application:**
```bash
python chat_cli.py
```
**6. Interact with the chatbot:**
```
Welcome to the Python Chat CLI!
Enter your prompt (or 'exit' to quit): Write a haiku about programming.
ChatGPT: Code flows like water,
Logic blooms in silent loops,
Bugs fade into light.
Enter your prompt (or 'exit' to quit): exit
Goodbye!
```
**7. When finished, deactivate the virtual environment:**
```bash
deactivate
```
---
## How It Works
### Architecture Overview
All three implementations follow the same request/response pattern:
```
User types prompt
|
v
Validate input (non-empty, not "exit")
|
v
Build request payload:
{
"model": "",
"messages": [
{ "role": "user", "content": "" }
]
}
|
v
POST https://api.openai.com/v1/chat/completions
Headers:
Authorization: Bearer
Content-Type: application/json
|
v
Parse JSON response:
choices[0].message.content
|
v
Print response to terminal
|
v
Repeat loop
```
The conversation is **stateless** — each message is sent as a fresh single-turn request. There is no conversation history accumulation across turns; each prompt is treated independently.
---
### Node.js Implementation Details
**File:** `nodejs/chatgpt.js`
The Node.js implementation is written as an ES module (`"type": "module"` in `package.json`) and uses `async`/`await` throughout.
**Startup sequence:**
1. `dotenv.config()` loads `nodejs/.env` into `process.env`.
2. Both `OPENAI_API_KEY` and `OPENAI_ORGANIZATION` are validated. If either is absent, the process exits with code `1` and a descriptive error message.
3. An `OpenAI` client instance is created using the official SDK.
4. A `readline.Interface` is created, binding to `stdin`/`stdout`.
**Request handling — `handleRequest(input, retries = 0)`:**
This async function wraps `openai.chat.completions.create()` in a `try/catch` block. On success, it prints the content from `res.choices[0].message.content`. On failure:
- If the error is an HTTP 429 (rate limit), it reads the `Retry-After` response header (defaulting to exponential backoff if the header is absent) and schedules a retry via `setTimeout`.
- For other errors, it applies exponential backoff: delay = `initialDelay * 2^retries` (2 s → 4 s → 8 s).
- After `maxRetries` (3) attempts, it logs a final error and stops retrying.
**Input loop — `askQuestion()`:**
Uses `userInterface.question()` to prompt the user. After `handleRequest` resolves, it chains `.then(() => askQuestion())` to present the next prompt. Typing `exit` (case-insensitive) closes the readline interface and terminates the process.
**Model used:** `gpt-3.5-turbo`
---
### Go Implementation Details
**Files:** `golang/main.go`, `golang/types.go`
The Go implementation uses only the standard library for HTTP and JSON, with a single third-party dependency for `.env` loading.
**Type definitions (`types.go`):**
```go
type Request struct { Model string; Messages []Message }
type Message struct { Role string; Content string }
type Response struct { Choices []Choice }
type Choice struct { Message Content }
type Content struct { Content string }
```
All fields use `json:"...,omitempty"` tags for clean JSON serialization.
**Startup sequence (`main.go`):**
1. `godotenv.Load()` reads `golang/.env` — a fatal error if the file is missing or unreadable.
2. `os.Getenv("OPENAI_API_KEY")` is retrieved and validated — fatal if empty.
3. An `http.Client` and a `bufio.Reader` on `os.Stdin` are created.
**Request function — `sendOpenAIRequest`:**
1. Marshals the `Request` struct to JSON using `encoding/json`.
2. Creates a `context.WithTimeout` of **10 seconds** — any request that does not complete within this window is cancelled automatically.
3. Constructs an `http.NewRequestWithContext` POST to `https://api.openai.com/v1/chat/completions` with `Authorization` and `Content-Type` headers.
4. Executes the request and checks the HTTP status code. Any non-200 response reads the body and returns it as an error string.
5. Decodes the JSON response into a `Response` struct and returns it.
**Input loop:** A standard `for` loop with `reader.ReadString('\n')` reads one line at a time. The prompt is trimmed of whitespace, checked for `exit` or empty string, then dispatched to `sendOpenAIRequest`.
**Model used:** `gpt-3.5-turbo`
---
### Python Implementation Details
**Files:** `python/chat_cli.py`, `python/send_request.py`, `python/models.py`
The Python implementation is split across three files following a separation-of-concerns approach.
**Data models (`models.py`):**
```python
@dataclass
class Message:
role: str
content: str
@dataclass
class RequestBody:
model: str
messages: List[Message]
```
Python 3.7+ dataclasses provide lightweight, type-annotated data containers. `dataclasses.asdict()` converts them to plain dictionaries for JSON serialization.
**API layer (`send_request.py`):**
`send_openai_request(api_key, user_prompt)` builds a `RequestBody` with `model="gpt-4"`, serializes it with `json.dumps(asdict(body))`, and sends a POST request using `requests.post()` with a **10-second timeout**. If the status code is not 200, it prints the status and body before calling `raise_for_status()`. On success it extracts and returns `choices[0]["message"]["content"]`. Exceptions of type `requests.RequestException` or `KeyError` are caught and logged, returning `None`.
**Entry point (`chat_cli.py`):**
1. `load_dotenv()` reads `python/.env`.
2. `OPENAI_API_KEY` is retrieved and validated.
3. A `while True` loop reads input from `stdin` using Python's built-in `input()`, strips whitespace, checks for `exit` or empty strings, and calls `send_openai_request`.
**Model used:** `gpt-4`
---
## Error Handling & Resilience
| Scenario | Node.js | Go | Python |
|---|---|---|---|
| Missing `OPENAI_API_KEY` | `process.exit(1)` with message | `log.Fatal` | Prints error, returns from `main()` |
| Missing `OPENAI_ORGANIZATION` | `process.exit(1)` with message | N/A | N/A |
| Empty user input | Re-prompts | Re-prompts | Re-prompts |
| HTTP 429 Rate Limit | Reads `Retry-After` header, retries | Returns error, continues loop | Prints status + body, returns `None` |
| Other HTTP error | Retries up to 3x with backoff | Returns formatted error string | Prints status + body, returns `None` |
| Request timeout | No hard timeout (relies on retry) | 10-second context cancellation | 10-second timeout on `requests.post()` |
| JSON decode failure | SDK handles internally | Returns wrapped error | Caught as `KeyError`, returns `None` |
| Max retries exceeded | Logs error, continues loop | N/A (no retry) | N/A (no retry) |
---
## Implementation Comparison
| Property | Node.js | Go | Python |
|---|---|---|---|
| **Model** | `gpt-3.5-turbo` | `gpt-3.5-turbo` | `gpt-4` |
| **OpenAI SDK** | Official `openai` npm package | None (direct `net/http`) | None (direct `requests`) |
| **Retry logic** | Yes — 3 retries, exponential backoff | No | No |
| **Rate limit awareness** | Yes — reads `Retry-After` header | No | No |
| **Request timeout** | None (retry-based) | 10 s (context) | 10 s (requests param) |
| **Env loading** | `dotenv` npm package | `godotenv` | `python-dotenv` |
| **Org ID required** | Yes | No | No |
| **Type safety** | Runtime checks | Compile-time structs | Dataclasses (runtime) |
| **Concurrency model** | Async/await (event loop) | Synchronous (goroutine-ready) | Synchronous |
| **External dependencies** | 2 (`dotenv`, `openai`) | 1 (`godotenv`) | 6 (including transitive) |
| **File count** | 1 source file | 2 source files | 3 source files |
---
## Troubleshooting
**`Error: Missing required environment variables (OPENAI_API_KEY)`**
You have not created a `.env` file or the variable name is misspelled. Check that the file exists in the correct subdirectory (`nodejs/`, `golang/`, or `python/`) and that it contains the correct variable name with no extra spaces around the `=` sign.
**`Could not load .env file` (Go)**
The Go binary must be run from within the `golang/` directory, or the `.env` file must exist in the same directory as the working directory when the binary is executed. Ensure you `cd golang` before running `go run .`.
**HTTP 401 Unauthorized**
Your API key is invalid, has been revoked, or was copied incorrectly. Verify it in the OpenAI dashboard and update your `.env` file.
**HTTP 429 Too Many Requests**
You have exceeded your rate limit or used up your free-tier credits. Check your [usage dashboard](https://platform.openai.com/usage). The Node.js implementation will automatically retry; the Go and Python implementations will log the error and continue the loop, allowing you to try again manually.
**HTTP 404 Not Found (Python, gpt-4)**
Your OpenAI account or tier may not have access to the `gpt-4` model. Verify model access at [https://platform.openai.com/account/limits](https://platform.openai.com/account/limits). If needed, change `model="gpt-4"` to `model="gpt-3.5-turbo"` in `python/send_request.py`.
**`go: command not found`**
Go is not installed or not in your `PATH`. Follow the [official installation guide](https://go.dev/doc/install) and ensure the Go install directory is in your `PATH`.
**`ModuleNotFoundError` (Python)**
Dependencies have not been installed. Run `pip install -r requirements.txt` from within the `python/` directory, preferably inside a virtual environment.
**`node: command not found` or `npm: command not found`**
Node.js is not installed. Download it from [https://nodejs.org](https://nodejs.org).
**Responses are slow or time out (Go/Python)**
OpenAI API response times vary with model load. The 10-second timeout is intentionally conservative. If you consistently experience timeouts, check [https://status.openai.com](https://status.openai.com) for any ongoing incidents.
---
## Contributing
Contributions are welcome. Please follow these guidelines:
1. **Fork** the repository and create your branch from `main`.
2. **Keep changes focused** — one logical change per pull request.
3. **Consistency** — if you change behavior in one language implementation, consider whether the same change applies to the others.
4. **Do not commit `.env` files or API keys.** The `.gitignore` files prevent this, but double-check before pushing.
5. **Open an issue first** for significant changes to discuss the approach before investing time in implementation.
6. **Submit a pull request** with a clear description of what was changed and why.
For bug reports or feature requests, open an issue at [https://github.com/milliorn/chatgpt-cli/issues](https://github.com/milliorn/chatgpt-cli/issues).
---
## Security
If you discover a security vulnerability in this project, **do not open a public GitHub issue**, as this may expose the vulnerability to others before a fix is available.
Instead, email the project maintainer directly at **** with:
- A description of the vulnerability
- Steps to reproduce the issue
- Any relevant logs or screenshots
The maintainer will acknowledge receipt, keep you informed of progress, and credit you in the release notes if desired. See [SECURITY.md](SECURITY.md) for the full disclosure policy.
This repository is also scanned automatically by [GitHub CodeQL](https://github.com/milliorn/chatgpt-cli/actions/workflows/github-code-scanning/codeql) for common vulnerability patterns on every push and pull request.
---
## License
This project is licensed under the **ISC License**.
The ISC License is a permissive open-source license functionally equivalent to the MIT License. You are free to use, copy, modify, and distribute this software for any purpose, with or without modification, provided that the copyright notice and license text are retained. See the [LICENSE](LICENSE) file for the full license text.
---
## Acknowledgements
- [OpenAI](https://openai.com/) — For the GPT-3.5 and GPT-4 models and the Chat Completions API.
- [openai-node](https://github.com/openai/openai-node) — The official OpenAI Node.js SDK used in the Node.js implementation.
- [dotenv](https://www.npmjs.com/package/dotenv) — Environment variable loading for Node.js.
- [godotenv](https://github.com/joho/godotenv) — `.env` file loading for the Go implementation.
- [python-dotenv](https://pypi.org/project/python-dotenv/) — `.env` file loading for the Python implementation.
- [Requests](https://docs.python-requests.org/) — Elegant HTTP library for Python.
- [Dependabot](https://docs.github.com/en/code-security/dependabot) — Automated dependency update management across all three ecosystems.