jeo-code 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +342 -0
- package/package.json +57 -0
- package/scripts/install.sh +322 -0
- package/scripts/uninstall.sh +30 -0
- package/src/agent/compaction.ts +75 -0
- package/src/agent/config-schema.ts +87 -0
- package/src/agent/context-files.ts +51 -0
- package/src/agent/engine.ts +208 -0
- package/src/agent/json.ts +87 -0
- package/src/agent/loop.ts +22 -0
- package/src/agent/session.ts +198 -0
- package/src/agent/state.ts +199 -0
- package/src/agent/subagents.ts +149 -0
- package/src/agent/tools.ts +355 -0
- package/src/ai/index.ts +11 -0
- package/src/ai/model-catalog-compat.ts +119 -0
- package/src/ai/model-catalog.ts +97 -0
- package/src/ai/model-discovery.ts +148 -0
- package/src/ai/model-enrich.ts +75 -0
- package/src/ai/model-manager.ts +178 -0
- package/src/ai/model-picker.ts +73 -0
- package/src/ai/model-registry.ts +83 -0
- package/src/ai/provider-status.ts +77 -0
- package/src/ai/providers/anthropic.ts +87 -0
- package/src/ai/providers/errors.ts +47 -0
- package/src/ai/providers/gemini.ts +77 -0
- package/src/ai/providers/ollama.ts +54 -0
- package/src/ai/providers/openai.ts +67 -0
- package/src/ai/sse.ts +46 -0
- package/src/ai/types.ts +37 -0
- package/src/auth/callback-server.ts +195 -0
- package/src/auth/flows/anthropic.ts +114 -0
- package/src/auth/flows/google.ts +120 -0
- package/src/auth/flows/index.ts +50 -0
- package/src/auth/flows/openai.ts +130 -0
- package/src/auth/index.ts +23 -0
- package/src/auth/oauth.ts +80 -0
- package/src/auth/pkce.ts +24 -0
- package/src/auth/refresh.ts +60 -0
- package/src/auth/storage.ts +113 -0
- package/src/auth/types.ts +26 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/runner.ts +245 -0
- package/src/cli.ts +17 -0
- package/src/commands/approve.ts +63 -0
- package/src/commands/auth.ts +144 -0
- package/src/commands/chat.ts +37 -0
- package/src/commands/deep-interview.ts +239 -0
- package/src/commands/doctor.ts +250 -0
- package/src/commands/evolve.ts +191 -0
- package/src/commands/launch.ts +745 -0
- package/src/commands/mcp.ts +18 -0
- package/src/commands/models.ts +104 -0
- package/src/commands/ralplan.ts +86 -0
- package/src/commands/resume.ts +6 -0
- package/src/commands/setup-helpers.ts +93 -0
- package/src/commands/setup.ts +190 -0
- package/src/commands/skills.ts +38 -0
- package/src/commands/team.ts +337 -0
- package/src/commands/ultragoal.ts +102 -0
- package/src/index.ts +31 -0
- package/src/mcp/index.ts +3 -0
- package/src/mcp/protocol.ts +45 -0
- package/src/mcp/server.ts +97 -0
- package/src/mcp/tools.ts +156 -0
- package/src/skills/catalog.ts +61 -0
- package/src/tui/app.ts +297 -0
- package/src/tui/components/ascii-art.ts +340 -0
- package/src/tui/components/autocomplete.ts +165 -0
- package/src/tui/components/capability.ts +29 -0
- package/src/tui/components/code-view.ts +146 -0
- package/src/tui/components/color.ts +172 -0
- package/src/tui/components/config-panel.ts +193 -0
- package/src/tui/components/evolution.ts +305 -0
- package/src/tui/components/footer.ts +95 -0
- package/src/tui/components/forge.ts +167 -0
- package/src/tui/components/index.ts +7 -0
- package/src/tui/components/layout.ts +105 -0
- package/src/tui/components/meter.ts +61 -0
- package/src/tui/components/model-picker.ts +82 -0
- package/src/tui/components/provider-picker.ts +42 -0
- package/src/tui/components/select-list.ts +199 -0
- package/src/tui/components/slash.ts +34 -0
- package/src/tui/components/spinner.ts +49 -0
- package/src/tui/components/status.ts +45 -0
- package/src/tui/components/stream.ts +36 -0
- package/src/tui/components/themes.ts +86 -0
- package/src/tui/components/tool-list.ts +67 -0
- package/src/tui/index.ts +2 -0
- package/src/tui/renderer.ts +70 -0
- package/src/tui/terminal.ts +78 -0
- package/src/util/retry.ts +108 -0
- package/tsconfig.json +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# jeo-code (`joc`)
|
|
2
|
+
|
|
3
|
+
[](https://bun.sh)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[]()
|
|
6
|
+
[]()
|
|
7
|
+
|
|
8
|
+
> An interactive AI coding agent **and** a disciplined spec-first pipeline — one
|
|
9
|
+
> lean, pure-TypeScript CLI on Bun.
|
|
10
|
+
`jeo-code` is a single-package coding agent (binary `joc`) that you can use two ways:
|
|
11
|
+
|
|
12
|
+
- **Interactive agent** — run bare `joc` to chat with an agent that reads, writes,
|
|
13
|
+
edits, and runs commands in a loop until your request is done (with a live TUI).
|
|
14
|
+
- **Spec-first pipeline** — `deep-interview → ralplan → team → ultragoal`: crystallize
|
|
15
|
+
requirements before any code changes, plan, execute, then verify against acceptance criteria.
|
|
16
|
+
|
|
17
|
+
It re-implements the [`gajae-code`](https://github.com/Yeachan-Heo/gajae-code) (`gjc`)
|
|
18
|
+
workflow contract and adopts [`pi-mono`](https://github.com/badlogic/pi-mono) runtime
|
|
19
|
+
ergonomics (minimal tool loop, persistent sessions, compaction, project context) — with
|
|
20
|
+
**no native deps**: just Bun + TypeScript.
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
joc → interactive coding agent (TUI: live tools + status footer)
|
|
24
|
+
|
|
25
|
+
joc deep-interview → joc ralplan → joc approve → joc team → joc ultragoal
|
|
26
|
+
(Socratic clarify) (blueprint) (gate) (execute) (verify)
|
|
27
|
+
│
|
|
28
|
+
[Mutation Lock] — file edits blocked until ambiguity ≤ 20%
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
Install `joc` the same way you install `gjc` — a single Bun global install — then
|
|
36
|
+
launch it from whatever repository you want it to operate on:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. Install (gjc parity: one bun global install)
|
|
40
|
+
bun install -g jeo-code # npm registry (once published)
|
|
41
|
+
bun install -g github:akillness/jeo-code # GitHub shorthand
|
|
42
|
+
bun install -g git+https://github.com/akillness/jeo-code.git # explicit Git URL
|
|
43
|
+
# …or bootstrap Bun + install from the Git URL in one shot:
|
|
44
|
+
curl -fsSL https://raw.githubusercontent.com/akillness/jeo-code/main/scripts/install.sh | sh
|
|
45
|
+
|
|
46
|
+
# 2. Configure a provider + default model (interactive)
|
|
47
|
+
joc setup
|
|
48
|
+
# …or go fully local with Ollama, no key:
|
|
49
|
+
ollama pull qwen2.5:0.5b
|
|
50
|
+
export JOC_DEFAULT_MODEL=ollama/qwen2.5:0.5b
|
|
51
|
+
|
|
52
|
+
# 3. Verify the setup is reachable
|
|
53
|
+
joc doctor
|
|
54
|
+
|
|
55
|
+
# 4. Launch from the target repo (gjc-style entrypoints)
|
|
56
|
+
joc # interactive agent in the current checkout
|
|
57
|
+
joc --tmux # create/attach a joc-managed tmux session
|
|
58
|
+
joc --tmux --worktree ../joc-feature # isolate work in a dedicated git worktree
|
|
59
|
+
joc "add a /health route to server.ts and run the tests" # one-shot request
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Requirements:** Bun `v1.3.14+` (the installer auto-installs it if missing; the CLI re-checks at startup).
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
`joc` installs exactly like `gjc`: a single Bun global install that registers the
|
|
69
|
+
`joc` binary in `~/.bun/bin`. The installer also drops a compatibility symlink at
|
|
70
|
+
`~/.local/bin/joc` and auto-installs Bun (enforcing the `1.3.14` floor) when it is missing.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
bun install -g jeo-code # npm registry (gjc parity, once published)
|
|
74
|
+
bun install -g github:akillness/jeo-code # GitHub shorthand
|
|
75
|
+
bun install -g git+https://github.com/akillness/jeo-code.git # explicit Git URL
|
|
76
|
+
sh scripts/install.sh --repo https://github.com/akillness/jeo-code.git
|
|
77
|
+
sh scripts/install.sh --ref v0.1.0 # global install of a specific tag
|
|
78
|
+
sh scripts/install.sh --binary # compile a standalone binary (no bun at runtime)
|
|
79
|
+
sh scripts/uninstall.sh [--purge] # remove the bin + bun registry entry (--purge also wipes ~/.joc/)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Registry-aware installs
|
|
83
|
+
|
|
84
|
+
`joc` does **not** mutate your npm registry by default. Use `--registry` for a one-shot
|
|
85
|
+
Bun install, and add `--persist-registry` only when you intentionally want the installer
|
|
86
|
+
to run `npm config set ...`.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# One-shot registry for this install only
|
|
90
|
+
sh scripts/install.sh --npm --registry https://registry.npmjs.org/
|
|
91
|
+
sh scripts/install.sh --npm --registry https://npmjs.co.kr
|
|
92
|
+
sh scripts/install.sh --npm --registry https://your-company-registry.com
|
|
93
|
+
|
|
94
|
+
# Persist globally via npm config (official registry restore / mirror / private)
|
|
95
|
+
sh scripts/install.sh --npm --registry https://registry.npmjs.org/ --persist-registry
|
|
96
|
+
sh scripts/install.sh --npm --registry https://npmjs.co.kr --persist-registry
|
|
97
|
+
sh scripts/install.sh --npm --registry https://your-company-registry.com --persist-registry
|
|
98
|
+
|
|
99
|
+
# Scope-only registry (writes @my-org:registry, not the global registry)
|
|
100
|
+
sh scripts/install.sh --npm --scope @my-org --registry https://your-company-registry.com --persist-registry
|
|
101
|
+
|
|
102
|
+
# Project-pinned .npmrc instead of global npm config
|
|
103
|
+
sh scripts/install.sh --npm --registry https://registry.npmjs.org/ --project-npmrc
|
|
104
|
+
|
|
105
|
+
# Inspect / reset npm registry config
|
|
106
|
+
sh scripts/install.sh --print-registry
|
|
107
|
+
sh scripts/install.sh --delete-registry
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Publishing `jeo-code` to npm
|
|
111
|
+
|
|
112
|
+
`bun install -g jeo-code` resolves through the npm registry, so the package must be
|
|
113
|
+
published there. The package is configured for public npm publication
|
|
114
|
+
(`publishConfig.registry=https://registry.npmjs.org/`, `publishConfig.access=public`)
|
|
115
|
+
and keeps the executable bin as `joc -> src/cli.ts` with a Bun shebang.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npm login --registry https://registry.npmjs.org/
|
|
119
|
+
bun run publish:npm
|
|
120
|
+
npm view jeo-code version bin --registry https://registry.npmjs.org/
|
|
121
|
+
bun install -g jeo-code
|
|
122
|
+
joc --version
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
For CI/release publishing, add an npm token as the repository secret `NPM_TOKEN`,
|
|
126
|
+
then run the `Publish npm package` GitHub Action (dry-run or publish) or publish a
|
|
127
|
+
GitHub release. The workflow runs `bun install --frozen-lockfile`, `bun run typecheck`,
|
|
128
|
+
`bun test`, `npm pack --dry-run`, then `npm publish --provenance`.
|
|
129
|
+
|
|
130
|
+
Required npm token permissions:
|
|
131
|
+
|
|
132
|
+
1. npmjs.com → account settings → **Access Tokens** → create an **Automation** token, or
|
|
133
|
+
a **Granular Access Token** with package publish/read-write permission.
|
|
134
|
+
2. If the npm account has 2FA enabled, the token must be allowed to **bypass 2FA for
|
|
135
|
+
publishing**. A read-only token or granular token without 2FA bypass fails with:
|
|
136
|
+
`Two-factor authentication or granular access token with bypass 2fa enabled is required`.
|
|
137
|
+
3. GitHub repo → Settings → Secrets and variables → Actions → set `NPM_TOKEN` to that token.
|
|
138
|
+
4. Re-run the `Publish npm package` workflow. After it succeeds, verify:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm view jeo-code version bin --registry https://registry.npmjs.org/
|
|
142
|
+
bun install -g jeo-code
|
|
143
|
+
joc --version
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
From a clone, `./install.sh` performs the dev install (`bun link`) so source edits
|
|
147
|
+
take effect immediately; `scripts/install.sh --help` lists every mode.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
./install.sh # dev install from this clone (= scripts/install.sh --local)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Local dev without installing (from the repo root):
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
bun run start --help # = bun src/cli.ts --help
|
|
157
|
+
bun run typecheck # tsc -p tsconfig.json --noEmit
|
|
158
|
+
bun test # unit tests (61 files, 372 tests)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Commands
|
|
164
|
+
|
|
165
|
+
| Command | What it does |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| `joc` / `joc launch ["request"]` | Interactive coding agent (TUI REPL, one-shot, or piped). `--tmux` (create/attach a joc tmux session), `--worktree <path>` (run in a dedicated git worktree), `--resume [id]`, `--list`, `--no-tui`, `--no-session`. |
|
|
168
|
+
| `joc setup` | Interactive provider/model picker (API key / browser OAuth / local), with live model probing. |
|
|
169
|
+
| `joc auth [login\|logout\|refresh\|status] [provider] [--token <bearer>]` | Real OAuth (PKCE) login + token storage with auto-refresh. |
|
|
170
|
+
| `joc doctor [--strict] [--json]` | Probe provider connectivity, credentials, and OAuth expiry; report if the default model is reachable. Colorized status on a TTY. `--strict` exits non-zero when it isn't; `--json` emits a machine-readable report for CI. |
|
|
171
|
+
| `joc deep-interview "<idea>" [--auto]` | Socratic requirements interview; freezes a spec when ambiguity ≤ 20%. `--auto` runs non-interactively (CI/pipes). |
|
|
172
|
+
| `joc ralplan` | Planner/Architect/Critic blueprint from the frozen seed. |
|
|
173
|
+
| `joc approve <plan-path>` | Approve the active plan blueprint; gates execution (`team` refuses to run until approved). Idempotent. |
|
|
174
|
+
| `joc team` | Per-task executor loop (shared tool engine) against the plan. |
|
|
175
|
+
| `joc ultragoal` | Verify acceptance criteria and write a report. |
|
|
176
|
+
| `joc models [name] [--catalog] [--caps] [--check]` | Live model list from logged-in (OAuth/API) accounts + aliases & provider credentials. `--catalog` shows the capability catalog (context/out/thinking/images), `--caps` merges live models with capabilities (`--thinking=<lvl>`/`--images`/`--long` filters), `--check` is a per-provider auth/reachability probe. |
|
|
177
|
+
| `joc skills [name]` | List bundled workflow skills; `joc skills <name>` prints details. |
|
|
178
|
+
| `joc resume [id]` | Resume the latest interactive session (or a specific id). |
|
|
179
|
+
| `joc chat "<msg>"` | Single-shot streaming chat (no tools) — renders the reply token-by-token. |
|
|
180
|
+
| `joc mcp [serve\|tools]` | Run `joc` as an MCP stdio server (set `JOC_MCP_PIPELINE=1` to also expose the pipeline tools). |
|
|
181
|
+
| `joc evolve [--step N] [--max M] [--animate] [--loop N] [--theme cosmic\|matrix\|solar\|mono] [--gradient] [--ascii] [--fit] [--width W] [--list] [--list-themes] [--json] [--no-color]` | Preview the **evolution TUI** identity — five ASCII-art stages with track + stage meter. `--gradient` truecolor (256/16/plain downgrade), `--theme` palettes, `--ascii` legacy-terminal fallback, `--fit`/`--width` terminal sizing, `--list`/`--list-themes`/`--json` for tooling. |
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Interactive agent
|
|
186
|
+
|
|
187
|
+
Run bare `joc` (or `joc launch`) for a conversational coding agent built on a shared,
|
|
188
|
+
hardened tool-call engine (`src/agent/engine.ts`). It calls `read` / `write` / `edit` /
|
|
189
|
+
`bash` / `find` / `search` in a loop until it signals done.
|
|
190
|
+
|
|
191
|
+
- **TUI** — on a TTY it renders a differential UI (live tool-call list, `joc thinking`
|
|
192
|
+
progress status, `joc forge` tool stats, and boxed previews for `bash` / `write` /
|
|
193
|
+
`read` / `edit` calls); `--no-tui`, piped input, and non-TTY fall back to a
|
|
194
|
+
plain `stream:complete` / `stream:error` event stream.
|
|
195
|
+
- **Evolution TUI** — the live view evolves with the agent's progress through five stages
|
|
196
|
+
(**Primordial Cell → Double Helix → Tool User → AI Coding Agent → Singularity**). The ASCII
|
|
197
|
+
art, spinner, progress meter, and footer track all advance in lockstep from one canonical
|
|
198
|
+
stage model (`src/tui/components/evolution.ts`); `finish()` records `Evolved to: <stage>`.
|
|
199
|
+
Preview it any time with `joc evolve` (try `--theme matrix --gradient --fit`). On a TTY the
|
|
200
|
+
live frame **fills the terminal** — art centered to the width, footer pinned to the bottom row —
|
|
201
|
+
and downgrades gracefully (truecolor→256→16→plain, unicode→ASCII) per terminal capability.
|
|
202
|
+
- **Model & provider control (live)** — `<Tab>` autocompletes slash commands and their
|
|
203
|
+
arguments: model ids, providers, and subagent roles. `/model` and `/models` pull the
|
|
204
|
+
**real model list from your logged-in (OAuth / API-key) accounts** via live discovery —
|
|
205
|
+
pick by id or `#N`, set the session model or save it as default. `/provider` switches
|
|
206
|
+
providers (and lists that provider's live models), and `/agents <role> [model]` pins a per-role
|
|
207
|
+
model for the `executor` / `planner` / `architect` / `critic` subagents. `/roles [tier model]`
|
|
208
|
+
sets the `smol`/`slow`/`plan` model tiers; `/thinking` spans `minimal`→`xhigh`; `/view` / `/diff`
|
|
209
|
+
/ `/find` / `/search` give an in-TUI code view.
|
|
210
|
+
- **Sessions** — every turn is appended to `.joc/sessions/<id>.jsonl`; `joc launch --list`
|
|
211
|
+
and `joc launch --resume [id]` resume past conversations.
|
|
212
|
+
- **tmux orchestration (gjc parity)** — `joc --tmux` creates/attaches a leader session named
|
|
213
|
+
`joc-<branch>`; add `--worktree <path>` to run inside a dedicated git worktree (auto-created
|
|
214
|
+
on a branch named after the path) so edits and evidence stay isolated from your main checkout.
|
|
215
|
+
- **Project context** — the prompt auto-loads the first of `JEO.md` / `AGENTS.md` /
|
|
216
|
+
`.joc/context.md` / `CLAUDE.md`.
|
|
217
|
+
- **Compaction** — long conversations are summarized automatically to stay within the context window.
|
|
218
|
+
- **Progress guards** — if a (weak/local) model repeats the same tool call 3× or racks up 5
|
|
219
|
+
consecutive tool failures without signalling done, the loop stops with a clear message instead of burning steps.
|
|
220
|
+
- **Token usage** — each turn prints a `(N in / M out tokens)` footer; all four provider
|
|
221
|
+
adapters report usage in both blocking `call` and streaming modes.
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
joc # REPL — slash: /model /models /provider /agents /roles /thinking /config /view /diff /find /search (Tab to autocomplete)
|
|
225
|
+
joc launch "fix the failing test" # one-shot
|
|
226
|
+
echo "summarize src/agent" | joc # piped / non-TTY (plain output)
|
|
227
|
+
joc launch --resume # resume the latest session (or --resume <uuid>)
|
|
228
|
+
joc --tmux # create/attach a joc-managed tmux session (named joc-<branch>)
|
|
229
|
+
joc --tmux --worktree ../joc-feature # isolate edits/evidence in a dedicated git worktree
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Spec-first pipeline
|
|
235
|
+
|
|
236
|
+
Crystallize requirements before touching code. While a `deep-interview` is active, the
|
|
237
|
+
**MutationGuard** blocks code-mutating tools — `write`/`edit` outside `.joc/`, and `bash`
|
|
238
|
+
entirely — releasing once ambiguity ≤ 20%.
|
|
239
|
+
|
|
240
|
+
1. **`joc deep-interview "<idea>"`** — Socratic loop scoring ambiguity across Goal clarity,
|
|
241
|
+
Constraint completeness, and Success/Acceptance criteria. Freezes a seed to
|
|
242
|
+
`.joc/seeds/seed-<slug>.yaml`.
|
|
243
|
+
2. **`joc ralplan`** — multi-role (Planner/Architect/Critic) blueprint → `.joc/plans/plan-<slug>.yaml`.
|
|
244
|
+
3. **`joc approve <plan-path>`** — approval gate: marks the plan approved so `team` will execute it.
|
|
245
|
+
4. **`joc team`** — executes plan tasks via the shared tool engine; checkpoints to `.joc/state/team-state.json`.
|
|
246
|
+
5. **`joc ultragoal`** — runs acceptance checks and writes `.joc/state/ultragoal-report.md`.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Providers, OAuth & local models
|
|
251
|
+
|
|
252
|
+
Routing is inferred from the model id; credentials resolve from `~/.joc/config.json` (or env).
|
|
253
|
+
|
|
254
|
+
| Provider | Model id example | Credential |
|
|
255
|
+
| --- | --- | --- |
|
|
256
|
+
| Anthropic | `claude-3-5-sonnet` | `ANTHROPIC_API_KEY` or OAuth (`ANTHROPIC_OAUTH_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN`) |
|
|
257
|
+
| OpenAI | `gpt-4o` / `openai/<model>` | `OPENAI_API_KEY` or `OPENAI_OAUTH_TOKEN` |
|
|
258
|
+
| Gemini | `gemini-2.5-flash` | `GEMINI_API_KEY` or `GEMINI_OAUTH_TOKEN` |
|
|
259
|
+
| Ollama (local) | `ollama/qwen2.5:0.5b` | none — offline via `OLLAMA_HOST` (default `http://localhost:11434`) |
|
|
260
|
+
| OpenAI-compatible (LM Studio / vLLM / llama.cpp) | `openai/<model>` | optional key; set `openaiBaseUrl` / `OPENAI_BASE_URL` |
|
|
261
|
+
|
|
262
|
+
- **Real OAuth (PKCE):** `joc auth login <anthropic|openai|gemini>` opens the provider's
|
|
263
|
+
authorize URL, runs a local callback server (Anthropic `:54545`, OpenAI `:1455`,
|
|
264
|
+
Google `:8085`), exchanges the code, and stores `access` + `refresh` + `expires`. Tokens
|
|
265
|
+
**auto-refresh** on expiry (single-flight); `joc auth refresh <provider>` forces it. On
|
|
266
|
+
headless boxes, paste the redirect URL/code when prompted, or use
|
|
267
|
+
`joc auth login <provider> --token <bearer>` for a manual (non-refreshing) token.
|
|
268
|
+
- **Compatibility:** OAuth beats API keys for the same provider, **except** the bundled
|
|
269
|
+
adapters fall back to the API key when the OAuth flow isn't end-to-end compatible.
|
|
270
|
+
Anthropic OAuth is verified e2e with the Messages adapter; OpenAI/Google OAuth tokens
|
|
271
|
+
target the Codex / Cloud-Code-Assist backends, so the bundled chat / generativelanguage
|
|
272
|
+
adapters prefer an API key (the CLI warns you up front).
|
|
273
|
+
- **Local/offline:** set `JOC_DEFAULT_MODEL=ollama/<model>` after `ollama pull <model>` — no
|
|
274
|
+
key required. Any OpenAI-compatible endpoint works via `openaiBaseUrl`.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Configuration
|
|
279
|
+
|
|
280
|
+
| What | Where |
|
|
281
|
+
| --- | --- |
|
|
282
|
+
| Global config | `~/.joc/config.json` (dir `0700`, file `0600`); override dir with `JOC_CONFIG_DIR` |
|
|
283
|
+
| Per-project runtime | `<cwd>/.joc/` → `seeds/`, `plans/`, `state/`, `sessions/` |
|
|
284
|
+
|
|
285
|
+
`config.json` fields: `providers`, `oauth`, `defaultModel`, `ollamaBaseUrl`, `openaiBaseUrl`,
|
|
286
|
+
`thinkingLevel` (`minimal`/`low`/`medium`/`high`/`xhigh`), `modelAliases`, `roles` (`smol`/`slow`/`plan`
|
|
287
|
+
model tiers), `subagents` (per-role model/maxSteps), `retry`. Env vars (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`,
|
|
288
|
+
`GEMINI_API_KEY`, the `*_OAUTH_TOKEN` bearers, `OLLAMA_HOST`, `OPENAI_BASE_URL`,
|
|
289
|
+
`JOC_DEFAULT_MODEL`) fill gaps but never override on-disk values. Verify everything with `joc doctor`.
|
|
290
|
+
|
|
291
|
+
**Provider retry budgets (gjc parity).** `retry.requestMaxRetries` sets how many times a failed
|
|
292
|
+
provider request is retried (the initial request is not counted); `retry.maxDelayMs` caps the
|
|
293
|
+
exponential backoff. `retry.streamMaxRetries` / `retry.maxRetries` are accepted for gjc-config
|
|
294
|
+
compatibility. Retries apply only to transient failures (network errors, `408/425/429/5xx/529`),
|
|
295
|
+
honoring a server `Retry-After`; auth, bad-model, and malformed-request errors stay fail-fast.
|
|
296
|
+
|
|
297
|
+
```json
|
|
298
|
+
{ "defaultModel": "claude-3-5-sonnet", "retry": { "requestMaxRetries": 4, "maxDelayMs": 300000 } }
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Project structure
|
|
304
|
+
|
|
305
|
+
```text
|
|
306
|
+
jeo-code/
|
|
307
|
+
├── package.json # name: jeo-code, bin: { joc: src/cli.ts }, bun scripts
|
|
308
|
+
├── tsconfig.json # strict typecheck config
|
|
309
|
+
├── install.sh # top-level shim → scripts/install.sh --local
|
|
310
|
+
├── src/
|
|
311
|
+
│ ├── cli.ts # entry: Bun version guard + dispatch
|
|
312
|
+
│ ├── cli/runner.ts # lazy command registry (bare joc → launch)
|
|
313
|
+
│ ├── commands/ # launch, setup, auth, deep-interview, ralplan, approve, team, ultragoal, doctor, mcp, models, skills, resume, chat
|
|
314
|
+
│ ├── agent/ # engine (tool loop), loop, json, tools (+MutationGuard), session, compaction, context-files, state
|
|
315
|
+
│ ├── ai/ # provider adapters (anthropic/openai/gemini/ollama) + model-manager
|
|
316
|
+
│ ├── auth/ # storage (+auto-refresh), pkce, callback-server, refresh, flows/{anthropic,openai,google}
|
|
317
|
+
│ ├── mcp/ # MCP protocol + tools + stdio server
|
|
318
|
+
│ └── tui/ # differential renderer + components + LaunchTui
|
|
319
|
+
├── scripts/ # install.sh / uninstall.sh (bun install + bun link)
|
|
320
|
+
├── test/ # 61 suites (372 tests): oauth, engine, tools-fs, retry, config-schema, cli-runner, mutation-guard, approve, team-schema, session, compaction, streaming, evolution, ascii-art, footer, evolve, meter, install, model-discovery/picker/catalog/enrich/roles, provider-status, config-panel, code-view, tui-*
|
|
321
|
+
├── docs/improvements.md # architectural analysis & changelog (ralph passes)
|
|
322
|
+
├── plan/ # long-horizon work plans (TUI, features, install, model, provider)
|
|
323
|
+
└── README.md
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Development
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
bun install # deps: zod (config validation), chalk (doctor colors)
|
|
332
|
+
bun run typecheck # tsc -p tsconfig.json --noEmit
|
|
333
|
+
bun test # full suite
|
|
334
|
+
GEMINI_OAUTH_CLIENT_SECRET=<x> bun test # Google OAuth flow tests need this env var
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Design lineage and the milestone roadmap (TUI, features, install, model config, provider)
|
|
338
|
+
live in [`plan/`](./plan/README.md); the running changelog is [`docs/improvements.md`](./docs/improvements.md).
|
|
339
|
+
|
|
340
|
+
## License
|
|
341
|
+
|
|
342
|
+
MIT.
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jeo-code",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Clean, highly optimized AI coding agent using spec-first loop",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/cli.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"joc": "src/cli.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"scripts/install.sh",
|
|
13
|
+
"scripts/uninstall.sh",
|
|
14
|
+
"tsconfig.json",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"bun": ">=1.3.14"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/akillness/jeo-code.git"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/akillness/jeo-code#readme",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/akillness/jeo-code/issues"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"ai",
|
|
30
|
+
"coding-agent",
|
|
31
|
+
"bun",
|
|
32
|
+
"cli",
|
|
33
|
+
"spec-first",
|
|
34
|
+
"gjc"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"registry": "https://registry.npmjs.org/"
|
|
39
|
+
},
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"scripts": {
|
|
42
|
+
"start": "bun src/cli.ts",
|
|
43
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
44
|
+
"build": "bun build src/cli.ts --compile --outfile dist/joc",
|
|
45
|
+
"pack:check": "npm pack --dry-run",
|
|
46
|
+
"publish:npm": "npm publish --access public --registry https://registry.npmjs.org/",
|
|
47
|
+
"test": "bun test"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"zod": "^3.24.1",
|
|
51
|
+
"chalk": "^5.3.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/bun": "^1.1.14",
|
|
55
|
+
"typescript": "^5.6.3"
|
|
56
|
+
}
|
|
57
|
+
}
|