Go whose errors the compiler checks, with an exit to plain Go.
loGos is one toolchain for Go and loGo/s. loGo/s adds ? error propagation and errdefer to Go. You write .lgo files. The logos command checks them, lowers them to plain Go, and compiles them with the Go 1.27 backend. Plain go keeps Go semantics and its upstream command text (see README.go.md). Go packages and loGo/s packages import each other, per import. logos eject turns a loGo/s module back into plain Go with its comments.
- Plain Go underneath (
TestEjectMatchesLoweringchecks the lowered output against whatlogos ejectwrites). - Go keeps its meaning (
run.bashpasses with plaingo). - Go and loGo/s import each other, one kind per module (
logos_interop.txtcovers the per-import rule in both directions).
Contents:
package main
import (
"fmt"
"os"
"strconv"
)
func double(s string) (int, error) {
n := strconv.Atoi(s)?
return 2 * n, nil
}
func main() { fmt.Println(double(os.Args[1])) } // logos run . 21 -> 42 <nil>Run it with logos run . 21. It prints 42 <nil>. The full language is defined in logos-docs/SPEC.md.
You need Go 1.24.6 or newer to bootstrap. src/make.bash sets this requirement (bootgo=1.24.6).
-
Clone the tree:
git clone https://github.com/gosuda/loGos
-
Build the toolchain:
cd loGos/src./make.bash
-
Put
logoson your PATH:export PATH="$PWD/../bin:$PATH"
-
Check the toolchain:
logos version
mkdir hello && cd hello
logos mod init example.com/hello
cat > main.lgo <<'EOF'
package main
import (
"fmt"
"os"
"strconv"
)
func double(s string) (int, error) {
n := strconv.Atoi(s)?
return 2 * n, nil
}
func main() { fmt.Println(double(os.Args[1])) }
EOF
logos run . 21logos eject -o ../hello-go
cd ../hello-go && go run . 21Both print 42 <nil>. The ejected module is plain Go.
| Form | Meaning |
|---|---|
x := f()? |
Bind the call results except the error, and return the error from the caller when it is non-nil. |
f()? |
Discard the value results, and return the error from the caller when it is non-nil. |
defer f()? |
At function exit, join a non-nil deferred error into the caller's error result. |
errdefer f() |
Run f only when the frame exits with a non-nil error, a panic, or Goexit. |
errdefer f()? |
Run f only on failure, joining its error into the primary error. |
? applies to a call whose last result is error. The enclosing function must also return error last. errdefer is allowed only in such functions. A module holds either .go or .lgo packages, never both. Imports cross the boundary per import.
The plugins/logos/ plugin ships three skills:
- logos: write, build, test, and eject loGo/s code.
- logos-review: review
.lgocode against the compiler rules. - logos-from-go: migrate a Go module to loGo/s by hand.
Claude (clones the whole Go fork):
claude plugin marketplace add gosuda/loGos
claude plugin install logos@logosCodex:
codex plugin marketplace add gosuda/loGos --sparse plugins/logos
codex plugin add logos@logosAgy, from a clone of this repository:
agy plugin install ./plugins/logosCopy plugins/logos/templates/AGENTS.md into a loGo/s repository so agents follow the module rules there.
cd src && ./make.bash
go test cmd/go -run 'Script/^logos_'
go test cmd/internal/testdir -run 'Test/logos/'
./run.bash --no-rebuildBSD-style, see LICENSE (The Go Authors). loGo/s changes are under the same license.