code.oscarkilo.com/okg

Hash:
4168cab2728a278987afcef9e5f7253c88d63707
Author:
Igor Naverniouk <[email protected]>
Date:
Thu Jun 4 18:21:39 2026 -0400
Message:
okg: expand to Oscar Kilo Goodness; add embed; man-page-style help Rename the tagline to "Oscar Kilo Goodness" as okg grows past klee-only git ops to absorb LLM utilities from klex-git. First absorbed subcommand: `okg embed` — reads stdin, calls klex-git's api.Client.Embed, writes vectors one per line. New klex.go centralizes Klex client construction (KlexDefaultUrl, KLEX_URL env override for dev/tests, ApiKey from existing loadConfig). --help reorganized into man-page sections (SETUP, GIT REPOS, PULL REQUESTS, ARTIFICIAL INTELLIGENCE, GLOBAL FLAGS, EXAMPLES) with flags listed per subcommand and an Examples section at the bottom. Repo commands moved out of SETUP since they aren't prerequisites. Transitional dep on oscarkilo.com/klex-git for the api package. Once one and exemplary land and the klex-git binaries are deprecated, we move api+config into //okg directly.
diff --git a/README.md b/README.md
index 7b3ac78..d05ef29 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,10 @@
-# okg — Oscar Kilo Git CLI
+# okg — Oscar Kilo Goodness

-A `gh`-style command-line tool for interacting with
-[klee](https://code.oscarkilo.com), the Oscar Kilo git server.
+A command-line tool that bundles Oscar Kilo's externally usable
+services into one binary. Today: git ops against
+[klee](https://code.oscarkilo.com), and LLM embeddings against
+[klex](https://oscarkilo.com/klex). More LLM utilities (`one`,
+`exemplary`) coming as the legacy `klex-git` binaries fold in.

Designed for both humans and AI agents (Claude, OpenClaw) to
use directly from the command line.
@@ -51,8 +54,21 @@ okg pr close NUMBER
okg pr reopen NUMBER

okg auth login [--host HOST] [--user USERNAME]
+
+okg embed [--model NAME] [--dims N] [--full-path]
+ (reads stdin → vectors on stdout)
```

+### Coming next
+
+- `okg one` — one LLM inference on one input (from
+ `klex-git/one`).
+- `okg exemplary` — few-shot batch runner (from
+ `klex-git/exemplary`).
+
+Once those land, the standalone `klex-git` binaries are
+deprecated.
+
### Flags

- `--repo REPO` overrides auto-detected repo name
@@ -73,4 +89,6 @@ git remote get-url origin

## Dependencies

-None beyond the Go standard library.
+- `oscarkilo.com/klex-git` for the LLM API client (transitional;
+ to be folded in once all `klex-git` binaries have moved here).
+- Otherwise Go standard library only.
diff --git a/embed.go b/embed.go
new file mode 100644
index 0000000..347708e
--- /dev/null
+++ b/embed.go
@@ -0,0 +1,62 @@
+package main
+
+import "flag"
+import "fmt"
+import "io"
+import "os"
+
+import "oscarkilo.com/klex-git/api"
+
+// runEmbed converts stdin text into embedding vectors, written to
+// stdout one vector per line, space-separated floats. Mirrors the
+// (now-deprecated) `klex-git/embed` binary.
+func runEmbed(args []string) error {
+ fs := flag.NewFlagSet("embed", flag.ContinueOnError)
+ model := fs.String("model",
+ "openai:text-embedding-3-small",
+ "embedding model name")
+ dims := fs.Int("dims", 1536,
+ "number of vector dimensions to return")
+ fullPath := fs.Bool("full-path", false,
+ "return one vector per prefix of input "+
+ "(otherwise just the final vector)")
+ if err := fs.Parse(args); err != nil {
+ return err
+ }
+
+ cfg, err := loadConfig()
+ if err != nil {
+ return err
+ }
+ if cfg.ApiKey == "" {
+ return fmt.Errorf(
+ "no API key — run `okg auth login`")
+ }
+ client := newKlexClient(cfg)
+
+ text, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ return fmt.Errorf("read stdin: %v", err)
+ }
+
+ vectors, err := client.Embed(api.EmbedRequest{
+ Text: string(text),
+ Model: *model,
+ Dims: *dims,
+ FullPath: *fullPath,
+ })
+ if err != nil {
+ return fmt.Errorf("embed: %v", err)
+ }
+
+ for _, vector := range vectors {
+ for i, w := range vector {
+ if i > 0 {
+ fmt.Print(" ")
+ }
+ fmt.Printf("%g", w)
+ }
+ fmt.Println()
+ }
+ return nil
+}
diff --git a/go.mod b/go.mod
index 6d06c4c..d50f747 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,5 @@
module oscarkilo.com/okg

go 1.23
+
+require oscarkilo.com/klex-git v0.0.0-20260602231643-098e5bd263e9 // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..ebbe14d
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+oscarkilo.com/klex-git v0.0.0-20260602231643-098e5bd263e9 h1:QvENdX6T54dU1GdjYawBQQWAtVGQyvTOR0yCUHwDb/k=
+oscarkilo.com/klex-git v0.0.0-20260602231643-098e5bd263e9/go.mod h1:147EoC+UxFadHm6fgxyR2lmvex3FE9Z5wkfiKyi40kg=
diff --git a/klex.go b/klex.go
new file mode 100644
index 0000000..e3c79f5
--- /dev/null
+++ b/klex.go
@@ -0,0 +1,17 @@
+package main
+
+import "os"
+
+import "oscarkilo.com/klex-git/api"
+
+// KlexDefaultUrl is the production Klex LLM endpoint. Override
+// via the KLEX_URL env var for dev/tests.
+const KlexDefaultUrl = "https://oscarkilo.com/klex"
+
+func newKlexClient(cfg *Config) *api.Client {
+ url := KlexDefaultUrl
+ if v := os.Getenv("KLEX_URL"); v != "" {
+ url = v
+ }
+ return api.NewClient(url, cfg.ApiKey)
+}
diff --git a/main.go b/main.go
index f22ec75..f4b325f 100644
--- a/main.go
+++ b/main.go
@@ -18,6 +18,8 @@ func main() {
err = runRepo(args[1:])
case "auth":
err = runAuth(args[1:])
+ case "embed":
+ err = runEmbed(args[1:])
case "help", "--help", "-h":
printUsage()
return
@@ -34,25 +36,78 @@ func main() {
}

func printUsage() {
- fmt.Fprintf(os.Stderr, `okg — Oscar Kilo Git CLI
-
-Usage:
- okg pr list [--state open|closed] [--json]
- okg pr create --head BRANCH [--base master] \
- --title TITLE [--body BODY] [--json]
- okg pr view NUMBER [--json]
- okg pr diff NUMBER
- okg pr comment NUMBER --body BODY \
- [--approve | --request-changes]
- okg pr merge NUMBER [--json]
- okg pr close NUMBER [--json]
- okg pr reopen NUMBER [--json]
- okg repo create NAME [--reader USER]
- okg repo list [--json]
- okg auth login [--host HOST] [--user USERNAME]
-
-Flags:
- --repo REPO Override auto-detected repo name
- --json Output raw JSON
+ fmt.Fprintf(os.Stderr, `NAME
+ okg — Oscar Kilo Goodness
+
+SETUP
+ okg auth login
+ --host HOST klee host (default: production)
+ --user USERNAME login as USERNAME
+
+GIT REPOS
+ okg repo list
+ --json output raw JSON
+
+ okg repo create NAME
+ --reader USER grant read to USER (default: anyone)
+
+PULL REQUESTS
+ okg pr list
+ --state STATE open or closed (default: open)
+ --json output raw JSON
+
+ okg pr create
+ --head BRANCH source branch
+ --base BRANCH target branch (default: master)
+ --title TITLE PR title
+ --body BODY PR body (optional)
+ --json output raw JSON
+
+ okg pr view NUMBER
+ --json output raw JSON
+
+ okg pr diff NUMBER
+
+ okg pr comment NUMBER
+ --body BODY comment body
+ --approve also approve the PR
+ --request-changes also request changes
+
+ okg pr merge NUMBER
+ --json output raw JSON
+
+ okg pr close NUMBER
+ --json output raw JSON
+
+ okg pr reopen NUMBER
+ --json output raw JSON
+
+ARTIFICIAL INTELLIGENCE
+ okg embed
+ --model NAME embedding model
+ (default: openai:text-embedding-3-small)
+ --dims N number of dimensions (default: 1536)
+ --full-path one vector per prefix of input
+ (reads stdin; writes vectors to stdout, one per line)
+
+GLOBAL FLAGS
+ --repo REPO override auto-detected repo name
+ --json output raw JSON (where applicable)
+
+EXAMPLES
+ Setup
+ okg auth login
+
+ Git repos
+ okg repo list
+ okg repo create my-new-repo
+
+ Pull requests
+ okg pr list --state open
+ okg pr view 42
+ okg pr comment 42 --body 'LGTM' --approve
+
+ Artificial intelligence
+ echo 'hello world' | okg embed --dims 384
`)
}
a/README.md
b/README.md
1
# okg — Oscar Kilo Git CLI
1
# okg — Oscar Kilo Goodness
2
2
3
A `gh`-style command-line tool for interacting with
3
A command-line tool that bundles Oscar Kilo's externally usable
4
[klee](https://code.oscarkilo.com), the Oscar Kilo git server.
4
services into one binary. Today: git ops against
5
[klee](https://code.oscarkilo.com), and LLM embeddings against
6
[klex](https://oscarkilo.com/klex). More LLM utilities (`one`,
7
`exemplary`) coming as the legacy `klex-git` binaries fold in.
5
8
6
Designed for both humans and AI agents (Claude, OpenClaw) to
9
Designed for both humans and AI agents (Claude, OpenClaw) to
7
use directly from the command line.
10
use directly from the command line.
8
11
9
## Install
12
## Install
10
13
11
```bash
14
```bash
12
go install oscarkilo.com/okg@latest
15
go install oscarkilo.com/okg@latest
13
```
16
```
14
17
15
Or build from source:
18
Or build from source:
16
19
17
```bash
20
```bash
18
git clone https://code.oscarkilo.com/okg
21
git clone https://code.oscarkilo.com/okg
19
cd okg && go build .
22
cd okg && go build .
20
```
23
```
21
24
22
## Setup
25
## Setup
23
26
24
By default okg talks to the production klee host
27
By default okg talks to the production klee host
25
(`https://code.oscarkilo.com`); the only setup you need is to give it
28
(`https://code.oscarkilo.com`); the only setup you need is to give it
26
your API key. Either:
29
your API key. Either:
27
30
28
```bash
31
```bash
29
# Interactive login — saves host + key to ~/.config/okg/config.json.
32
# Interactive login — saves host + key to ~/.config/okg/config.json.
30
okg auth login
33
okg auth login
31
34
32
# Or non-interactive: just set the API key.
35
# Or non-interactive: just set the API key.
33
export KLEX_API_KEY=your-api-key
36
export KLEX_API_KEY=your-api-key
34
```
37
```
35
38
36
Override the host for dev/local work with `--host` on `auth login`,
39
Override the host for dev/local work with `--host` on `auth login`,
37
or with the `OKG_HOST` env var.
40
or with the `OKG_HOST` env var.
38
41
39
## Commands
42
## Commands
40
43
41
```
44
```
42
okg repo list
45
okg repo list
43
46
44
okg pr list [--state open|closed]
47
okg pr list [--state open|closed]
45
okg pr create --head BRANCH [--base master] --title TITLE [--body BODY]
48
okg pr create --head BRANCH [--base master] --title TITLE [--body BODY]
46
okg pr view NUMBER
49
okg pr view NUMBER
47
okg pr diff NUMBER
50
okg pr diff NUMBER
48
okg pr comment NUMBER --body BODY [--approve | --request-changes]
51
okg pr comment NUMBER --body BODY [--approve | --request-changes]
49
okg pr merge NUMBER
52
okg pr merge NUMBER
50
okg pr close NUMBER
53
okg pr close NUMBER
51
okg pr reopen NUMBER
54
okg pr reopen NUMBER
52
55
53
okg auth login [--host HOST] [--user USERNAME]
56
okg auth login [--host HOST] [--user USERNAME]
57
58
okg embed [--model NAME] [--dims N] [--full-path]
59
(reads stdin → vectors on stdout)
54
```
60
```
55
61
62
### Coming next
63
64
- `okg one` — one LLM inference on one input (from
65
`klex-git/one`).
66
- `okg exemplary` — few-shot batch runner (from
67
`klex-git/exemplary`).
68
69
Once those land, the standalone `klex-git` binaries are
70
deprecated.
71
56
### Flags
72
### Flags
57
73
58
- `--repo REPO` overrides auto-detected repo name
74
- `--repo REPO` overrides auto-detected repo name
59
(normally parsed from `git remote get-url origin`)
75
(normally parsed from `git remote get-url origin`)
60
- `--json` outputs raw JSON for any command
76
- `--json` outputs raw JSON for any command
61
- `OKG_REPO` env var also overrides repo detection
77
- `OKG_REPO` env var also overrides repo detection
62
78
63
## Repo Detection
79
## Repo Detection
64
80
65
Like `gh`, okg detects the repo from the current directory's
81
Like `gh`, okg detects the repo from the current directory's
66
git remote:
82
git remote:
67
83
68
```
84
```
69
git remote get-url origin
85
git remote get-url origin
70
→ https://code.oscarkilo.com/widget.git
86
→ https://code.oscarkilo.com/widget.git
71
→ repo = "widget"
87
→ repo = "widget"
72
```
88
```
73
89
74
## Dependencies
90
## Dependencies
75
91
76
None beyond the Go standard library.
92
- `oscarkilo.com/klex-git` for the LLM API client (transitional;
93
to be folded in once all `klex-git` binaries have moved here).
94
- Otherwise Go standard library only.
/dev/null
b/embed.go
1
package main
2
3
import "flag"
4
import "fmt"
5
import "io"
6
import "os"
7
8
import "oscarkilo.com/klex-git/api"
9
10
// runEmbed converts stdin text into embedding vectors, written to
11
// stdout one vector per line, space-separated floats. Mirrors the
12
// (now-deprecated) `klex-git/embed` binary.
13
func runEmbed(args []string) error {
14
fs := flag.NewFlagSet("embed", flag.ContinueOnError)
15
model := fs.String("model",
16
"openai:text-embedding-3-small",
17
"embedding model name")
18
dims := fs.Int("dims", 1536,
19
"number of vector dimensions to return")
20
fullPath := fs.Bool("full-path", false,
21
"return one vector per prefix of input "+
22
"(otherwise just the final vector)")
23
if err := fs.Parse(args); err != nil {
24
return err
25
}
26
27
cfg, err := loadConfig()
28
if err != nil {
29
return err
30
}
31
if cfg.ApiKey == "" {
32
return fmt.Errorf(
33
"no API key — run `okg auth login`")
34
}
35
client := newKlexClient(cfg)
36
37
text, err := io.ReadAll(os.Stdin)
38
if err != nil {
39
return fmt.Errorf("read stdin: %v", err)
40
}
41
42
vectors, err := client.Embed(api.EmbedRequest{
43
Text: string(text),
44
Model: *model,
45
Dims: *dims,
46
FullPath: *fullPath,
47
})
48
if err != nil {
49
return fmt.Errorf("embed: %v", err)
50
}
51
52
for _, vector := range vectors {
53
for i, w := range vector {
54
if i > 0 {
55
fmt.Print(" ")
56
}
57
fmt.Printf("%g", w)
58
}
59
fmt.Println()
60
}
61
return nil
62
}
a/go.mod
b/go.mod
1
module oscarkilo.com/okg
1
module oscarkilo.com/okg
2
2
3
go 1.23
3
go 1.23
4
5
require oscarkilo.com/klex-git v0.0.0-20260602231643-098e5bd263e9 // indirect
/dev/null
b/go.sum
1
oscarkilo.com/klex-git v0.0.0-20260602231643-098e5bd263e9 h1:QvENdX6T54dU1GdjYawBQQWAtVGQyvTOR0yCUHwDb/k=
2
oscarkilo.com/klex-git v0.0.0-20260602231643-098e5bd263e9/go.mod h1:147EoC+UxFadHm6fgxyR2lmvex3FE9Z5wkfiKyi40kg=
/dev/null
b/klex.go
1
package main
2
3
import "os"
4
5
import "oscarkilo.com/klex-git/api"
6
7
// KlexDefaultUrl is the production Klex LLM endpoint. Override
8
// via the KLEX_URL env var for dev/tests.
9
const KlexDefaultUrl = "https://oscarkilo.com/klex"
10
11
func newKlexClient(cfg *Config) *api.Client {
12
url := KlexDefaultUrl
13
if v := os.Getenv("KLEX_URL"); v != "" {
14
url = v
15
}
16
return api.NewClient(url, cfg.ApiKey)
17
}
a/main.go
b/main.go
1
package main
1
package main
2
2
3
import "fmt"
3
import "fmt"
4
import "os"
4
import "os"
5
5
6
func main() {
6
func main() {
7
args := os.Args[1:]
7
args := os.Args[1:]
8
if len(args) == 0 {
8
if len(args) == 0 {
9
printUsage()
9
printUsage()
10
os.Exit(1)
10
os.Exit(1)
11
}
11
}
12
12
13
var err error
13
var err error
14
switch args[0] {
14
switch args[0] {
15
case "pr":
15
case "pr":
16
err = runPR(args[1:])
16
err = runPR(args[1:])
17
case "repo":
17
case "repo":
18
err = runRepo(args[1:])
18
err = runRepo(args[1:])
19
case "auth":
19
case "auth":
20
err = runAuth(args[1:])
20
err = runAuth(args[1:])
21
case "embed":
22
err = runEmbed(args[1:])
21
case "help", "--help", "-h":
23
case "help", "--help", "-h":
22
printUsage()
24
printUsage()
23
return
25
return
24
default:
26
default:
25
fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
27
fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
26
printUsage()
28
printUsage()
27
os.Exit(1)
29
os.Exit(1)
28
}
30
}
29
31
30
if err != nil {
32
if err != nil {
31
fmt.Fprintf(os.Stderr, "error: %v\n", err)
33
fmt.Fprintf(os.Stderr, "error: %v\n", err)
32
os.Exit(1)
34
os.Exit(1)
33
}
35
}
34
}
36
}
35
37
36
func printUsage() {
38
func printUsage() {
37
fmt.Fprintf(os.Stderr, `okg — Oscar Kilo Git CLI
39
fmt.Fprintf(os.Stderr, `NAME
38
40
okg — Oscar Kilo Goodness
39
Usage:
41
40
okg pr list [--state open|closed] [--json]
42
SETUP
41
okg pr create --head BRANCH [--base master] \
43
okg auth login
42
--title TITLE [--body BODY] [--json]
44
--host HOST klee host (default: production)
43
okg pr view NUMBER [--json]
45
--user USERNAME login as USERNAME
44
okg pr diff NUMBER
46
45
okg pr comment NUMBER --body BODY \
47
GIT REPOS
46
[--approve | --request-changes]
48
okg repo list
47
okg pr merge NUMBER [--json]
49
--json output raw JSON
48
okg pr close NUMBER [--json]
50
49
okg pr reopen NUMBER [--json]
51
okg repo create NAME
50
okg repo create NAME [--reader USER]
52
--reader USER grant read to USER (default: anyone)
51
okg repo list [--json]
53
52
okg auth login [--host HOST] [--user USERNAME]
54
PULL REQUESTS
53
55
okg pr list
54
Flags:
56
--state STATE open or closed (default: open)
55
--repo REPO Override auto-detected repo name
57
--json output raw JSON
56
--json Output raw JSON
58
59
okg pr create
60
--head BRANCH source branch
61
--base BRANCH target branch (default: master)
62
--title TITLE PR title
63
--body BODY PR body (optional)
64
--json output raw JSON
65
66
okg pr view NUMBER
67
--json output raw JSON
68
69
okg pr diff NUMBER
70
71
okg pr comment NUMBER
72
--body BODY comment body
73
--approve also approve the PR
74
--request-changes also request changes
75
76
okg pr merge NUMBER
77
--json output raw JSON
78
79
okg pr close NUMBER
80
--json output raw JSON
81
82
okg pr reopen NUMBER
83
--json output raw JSON
84
85
ARTIFICIAL INTELLIGENCE
86
okg embed
87
--model NAME embedding model
88
(default: openai:text-embedding-3-small)
89
--dims N number of dimensions (default: 1536)
90
--full-path one vector per prefix of input
91
(reads stdin; writes vectors to stdout, one per line)
92
93
GLOBAL FLAGS
94
--repo REPO override auto-detected repo name
95
--json output raw JSON (where applicable)
96
97
EXAMPLES
98
Setup
99
okg auth login
100
101
Git repos
102
okg repo list
103
okg repo create my-new-repo
104
105
Pull requests
106
okg pr list --state open
107
okg pr view 42
108
okg pr comment 42 --body 'LGTM' --approve
109
110
Artificial intelligence
111
echo 'hello world' | okg embed --dims 384
57
`)
112
`)
58
}
113
}