# sjcode ein terminal coding agent, der die ollama API nutzt ## Setup ```bash cp config.toml.example config.toml # then edit port / model / limits python3 server/server.py # starts the daemon + admin CLI ``` `config.toml` is machine-local and git-ignored; `config.toml.example` is the template. On first start the daemon creates the SQLite database (`sjcode.db`). ## Daemon (server.py) On startup it prints its settings and drops into a minimal admin CLI (accounts are stored in SQLite): | command | effect | |--------------------------|-------------------------------------------------| | `create [role]` | create account (asks for password, default role `user`) | | `list` | show all accounts | | `delete ` | remove account | | `role ` | change role | | `passwd ` | set a new password | | `usage [name]` | used minutes today vs. limit | | `reset [name]` | reset the daily usage counter | | `status` | show daemon settings | | `quit` | stop the daemon | While the CLI runs, an HTTP API is served in the background: - `POST /login` — `{"username", "password"}` → `{"token", ...}` - `POST /chat` — `{"token", "message", "model"?}` → `{"response", ...}` - `GET /models?token=...` — list ollama models Every user row stores: `username`, `password_hash`, `last_logged_in`, `role`, `used_today` (minutes of AI usage; resets on a new day). ## Roles and limits In `config.toml` each role gets a daily limit in minutes: ```toml [limits] user = 120 # default role for new accounts admin = -1 # negative = unlimited ``` Login and every chat request are blocked once `used_today` reaches the limit. ## Client (client.py) ```bash ./coder # or: python3 client.py python3 client.py 10.0.0.5:8420 # explicit daemon address python3 client.py --model qwen3-coder # skip the model picker python3 client.py --no-probe # skip the reachability check (use behind # HTTP proxies that answer on every port) ``` On start the client asks which server to connect to: pick one of the saved ones, or add a new one (`n`). Every server you use is saved in `~/.config/sjcode/client.json` together with the username and the last model, so the next start is just Enter-Enter. Addresses without a port use 8420; `host:port`, `http(s)://...` URLs and IPv6 literals are accepted. After login and model choice you get the agent banner and a chat REPL. Commands: | command | effect | |---------------|-----------------------------------------| | `/help` | list commands | | `/server` | show the connected server | | `/models` | list models on the server | | `/model ` | switch model (saved for this server) | | `/limit` | remaining minutes today (last known) | | `/clear` | forget the conversation history | | `/quit` | exit | Anything else is sent to the model. The client keeps the last few turns as context (the daemon API itself is stateless) and renders the reply in the agent style (`✓` lines for actions the model reports). ## Requirements - Python 3.11+ (stdlib only; `tomllib` is included) - ollama listening on the address from `config.toml`