1
# okg — Oscar Kilo G
1
# okg — Oscar Kilo G
2
2
3
A command-line tool neci t
3
A command-line tool neci t
4
ecesio e ar git s
4
ecesio e ar git s
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
oe the i
92
oe the i
93
to be folded in once all `klex-git` binaries have moved here).
94
- Otherwise Go standard library only.
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
}
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
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=
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
}
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, `
39
fmt.Fprintf(os.Stderr, `
38
40
39
41
40
42
41
okg th
43
okg th
42
e on
44
e on
43
r
45
r
44
46
45
EO
47
EO
46
o rest
48
o rest
47
49
48
50
49
okg p ree NME
51
okg p ree NME
50
rte E ea
52
rte E ea
51
53
52
STS
54
STS
53
55
54
as:
56
as:
55
-- ott r
57
-- ott r
56
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
}