Start
Ovid builds wherever Go does; the programs it compiles run on Linux x86-64. Other targets are not there yet.
Install
git clone https://github.com/ovid-sh/ovid
cd ovid
go build -o bin/ovid ./cmd/ovid
The toolchain needs nothing beyond Go. Elsewhere it still checks, edits, and builds Linux binaries; run and test need Linux x86-64 to run what it built.
A module
$ ovid init hello
{"files":["hello/ovid.mod","hello/hello/main.ov","hello/hello/main_test.ov"],"next":"cd hello && ovid run && ovid test; ovid help language","ok":true,"root":"hello"}
A module is a directory with ovid.mod. Each directory of .ov files in it is one package, named by its path. init writes a main and a test:
package hello
import ovid/io
func Greeting() i64 {
return strptr("hello, world\n")
}
func main(io *ovid/io.Cap) i64 {
ovid/io.Print(Greeting())
return 0
}
package hello
import ovid/io
import ovid/mem
func TestGreeting(io *ovid/io.Cap) i64 {
if ovid/mem.EqC(Greeting(), strptr("hello, world\n"), strlen("hello, world\n")) {
return 0
}
return 1
}
Run and test
$ ovid run
hello, world
$ ovid build
{"bytes":745,"ok":true,"output":"hello/bin/hello","syscalls":[1,9,60]}
$ ovid test
{"fact":"test","file":"hello/main_test.ov","id":"fn:hello.TestGreeting","line":6,"ms":0,"ok":true}
{"fact":"summary","failed":0,"ok":true,"passed":1}
Each test runs in its own process and passes by returning 0. A failure names the return that produced it; a crash, its signal, statement, and call stack.
Give it to an agent
ovid help is written for an agent to read first, and each topic it names is the reference for that part. This site has them all in one file, llms-full.txt.
ovid: a small compiled language and its toolchain, built for agents.
Source is plain .ov text. A module is a directory with ovid.mod; each
subdirectory holding .ov files is one package, and its path is the package
name. Every command prints JSON lines; the last line always has "ok".
Exit codes: 0 ok, 1 errors, 2 stale edit, 64 usage, 124 run: timeout,
125 run: could not build or start the program.
Paths in records are relative to the working directory; with
OVID_PATHS=module in the environment, to the module root.
Start here:
ovid init <dir> new module with a hello-world entry and a test
ovid check errors with file:line:col, expected/got, hint
ovid run [-- args] build to a temp file and run it
ovid run --json [--timeout 5s]
the same, with exit, signal, and output as JSON
ovid test [--run Name] run Test* funcs, one process each
Read without opening whole files:
ovid outline [--pkg P] packages, or one package's decls with hashes
(outline, refs, grep print 200 records a page)
ovid show <id|name>... [--plain] [--json] [--exprs]
source of a decl or node, lines tagged with ids
ovid refs <id|name> every use of a func/type/field/const/param/var
ovid grep <regexp> text matches, each with its decl and stmt id
Change code (or edit the .ov files directly; both are fine):
ovid replace <id> --expect H <<'EOF'
one edit, code from stdin (no JSON escaping);
also insert --after/--before <id>, append <id>,
delete <id>
ovid edit <file|-> id-addressed batch edit, all or nothing
ovid rename <id|name> <new> rename a decl and all its uses
ovid move <id|name>... <pkg> move funcs/types/consts to another package
Also: ovid build [-o out], ovid dump (program as JSON), ovid version
(commit and binary hash: which ovid is this?), ovid help <topic>.
All commands take -C <dir> (default: the module containing the cwd).
The language at a glance (all of it: ovid help language):
i64, bool, *T; var x i64 = 0; if/else if/else; while; no for/break/continue
var p *T = ovid/io.Alloc(io, sizeof(T)) as *T structs live on the heap
ovid/io.Print(strptr("hi\n")); ovid/io.PrintInt(io, n) output
var sp bool = c == 32 || c == 9 && || ! work anywhere
Topics: ovid help language | commands | edit | std | ids