Brett Owers
← All Projects

Njinn

Archived

May 1, 2024

A single Python script that turned ChatGPT into a CLI — all it needed was $OPENAI_API_KEY. Stored conversation logs in the filesystem as a simple state management system. Actually super useful when it was made. The precursor to Claude Code and every terminal-based AI tool that followed.

Purpose

Built a Python CLI that connected directly to OpenAI's API, turning the terminal into a ChatGPT interface. One script, one environment variable, and you had AI in your workflow without opening a browser. Conversation logs were stored as files in the filesystem — a dead-simple state management system that let you resume conversations and search past interactions.

Stack

PythonOpenAI APICLIFilesystemState Management

What I Learned

  • The entire implementation was a single Python script: read $OPENAI_API_KEY from the environment, open a REPL loop (input → API call → print response → repeat), and append each exchange to a log file. No framework, no database, no dependencies beyond the openai Python package. The simplicity was the feature.
  • Using the filesystem as state management is underrated for single-user tools. A conversation log as a .jsonl file (one JSON object per line) gives you: persistence (survives restarts), searchability (grep), history (cat the file), and portability (copy the file to another machine). No database setup, no migration scripts, no connection strings. For personal tools, flat files are often the right answer.
  • Having AI in the terminal changes your workflow. Instead of context-switching to a browser, you stay in the terminal where the code lives. Ask a question about the error you just saw. Generate a shell command. Explain a stack trace. The proximity of the AI to the work removes the friction that kills most AI usage: the tab switch.
  • This was actually super useful when I made it — before Claude Code, before GitHub Copilot Chat, before terminal-integrated AI was standard. Building your own tool and using it daily teaches you exactly what you want from AI tooling. Every preference I have about Claude Code was shaped by what Njinn got right and what it lacked.

Key Insights

  • Njinn was Claude Code before Claude Code existed — a terminal AI that understood the developer's context. The difference: Njinn was stateless beyond log files (no codebase awareness, no file editing, no tool use). Claude Code has full codebase access, can read and write files, run commands, and maintain context across complex tasks. The evolution from Njinn to Claude Code is the evolution from "AI in the terminal" to "AI as a development partner."
  • The best tools are the ones you build for yourself and then discover that everyone else wants too. Njinn was built for personal use. The same concept — AI in the terminal with conversation persistence — became a multi-billion-dollar product category within a year. The pattern recognition ability to see a personal tool and recognize a market is the entrepreneurial instinct. I had the tool but not the instinct to productize it.
  • The $OPENAI_API_KEY as the only configuration is a design principle worth preserving: one secret, one capability. No account creation, no OAuth flow, no permissions matrix. Just: do you have the key? Then you have the tool. This minimal-auth pattern is what makes developer tools feel lightweight. Every additional configuration step is a dropout point.
#Python#CLI#OpenAI#ChatGPT#terminal#developer-tools#state-management#filesystem#Claude-Code#precursor

This post was composed through a conversation between Brett Owers and Claude Code (Anthropic). The content reflects Brett's recollection of each project and the lessons drawn from it. Some details may be approximate or omitted — the purpose is to paint an honest picture of a software engineer's development over time, not to serve as a precise historical record.