On August 31, 2026, I released Kinmokusei v0.1.0, the first public preview of a programming language for writing web backends and Go libraries with TypeScript-inspired syntax and compiling them to readable Go source.
The compiler command is named keika, source files use the .km extension, and the generated program remains part of the ordinary Go ecosystem: it uses Go modules, the Go toolchain, the Go ABI, the Go runtime, and existing Go packages directly. Go—not TypeScript—is the compatibility target.
Repository: https://github.com/puffball1567/kinmokusei
What Kinmokusei is
Kinmokusei is a source language for the Go ecosystem. It resembles TypeScript, but it is not TypeScript. It is intended for developers who like TypeScript-shaped syntax but want to build and publish ordinary Go programs and libraries. Its syntax is the approachable frontend; Go is the platform underneath and the main compatibility boundary.
It is not a TypeScript-to-Go converter, transpiler, or TypeScript implementation. It does not accept .ts files or existing TypeScript projects and turn them into Go. It is also not Go source with alternate punctuation. Kinmokusei is a separate language with its own .km source, type system, and explicit constructs for behavior that must lower predictably to Go, including Go named types, pointers, multiple return values, interfaces, generics, channels, errors, and nil.
The central design choice is that generated Go is not a hidden temporary representation. It is deterministic, formatted with gofmt, readable by a Go developer, and suitable for inspection or publication.
.km source
↓ keika check / build / emit-go
readable Go source
↓ standard Go toolchain
native executable or Go library
Authors can distribute the .km source, the generated Go module, or both.
Go compatibility instead of npm compatibility
Kinmokusei deliberately does not target npm, Node.js, browser JavaScript, or the TypeScript package ecosystem. An npm package cannot be imported merely because the source looks similar to TypeScript, and JavaScript runtime behavior is not reproduced behind the generated program.
That is an intentional tradeoff rather than a missing transpiler feature. By giving up npm compatibility, the language can concentrate on Go compatibility: existing Go module graphs, exported package data, named types, pointers, structs, interfaces and method sets, multiple results, generics, channels, error, goroutines, the Go ABI, and the standard Go build toolchain.
The practical ecosystem escape hatch is therefore import go, not an npm compatibility layer. Higher-level Kinmokusei libraries can be built on that boundary, while the low-level types and behavior remain recognizable to Go developers.
A first program
The smallest program can import the real Go standard library through an explicit namespace:
import go fmt from "fmt";
function main(): void {
fmt.Println("Hello from Kinmokusei");
}
Save this as hello.km, then check and run it:
keika check hello.km
keika run hello.km
keika emit-go hello.km prints the generated source:
// Code generated by Kinmokusei. DO NOT EDIT.
package main
import fmt "fmt"
func main() {
fmt.Println("Hello from Kinmokusei")
}
There is no separate JavaScript runtime or compatibility layer in this path. The result is Go code that the normal Go toolchain can build.
TypeScript-inspired classes with Go underneath
Kinmokusei provides reference-type classes, interfaces, visibility, constructors, and explicit single inheritance. These features lower to Go structs, methods, embedding, and interfaces instead of introducing a second object runtime.
import { CounterValue } from "./counter-contract";
class Counter implements CounterValue {
constructor(private value: int) {}
public function increment(): void {
this.value = this.value + 1;
}
public function current(): int {
return this.value;
}
}
Classes are reference types, while native struct declarations provide nominal Go-style value types with copy semantics. The language also includes interfaces, generic functions and types, fixed arrays and slices, maps, enums, defined types, nullable references, explicit Result<T> propagation, exceptions isolated from ordinary Go panics, channels, select, goroutines, and structured Task<T> values.
The aim is not to imitate every TypeScript or JavaScript behavior. The syntax should make the source approachable while preserving the distinctions that matter to generated Go, such as value versus reference semantics, copying versus aliasing, and a checked language null versus raw Go nil.
Use Go packages directly
The import go form is the low-level bridge to the Go ecosystem. It works with both the standard library and external modules:
import go gin from "github.com/gin-gonic/gin";
import go http from "net/http";
function NewRouter(): *gin.Engine {
const router = gin.New();
router.GET("/api/health", (ctx: *gin.Context): void => {
ctx.JSON(http.StatusOK, {
status: "ok",
language: "Kinmokusei",
});
});
return router;
}
The compiler reads exported Go package data and preserves Go types rather than flattening everything into a smaller foreign-function interface. Functions, constants, variables, structs, fields, methods, interfaces, pointers, multiple results, generics, callbacks, and explicit conversions are checked at the .km source location.
Kinmokusei can use an existing go.mod, or it can manage a locked module graph through its project manifest and lockfile. Normal checking and building validate that graph without silently updating dependencies.
Web backends are the first application target
The initial release focuses on web backends, Go library production, and goroutine-based workloads. The repository contains a JSON API built directly on net/http, an embedded HTTP package, and a full-stack example with one React and TypeScript frontend connected to interchangeable Gin and Fiber backends written in Kinmokusei.
Both framework examples call the real upstream Go packages. They compile into ordinary Go services and are tested against independently handwritten Go implementations of the same HTTP contract.
Kinmokusei also provides checked C boundaries for cases where Go is not the final consumer. Explicitly exported functions can produce a versioned C ABI, while incoming C FFI generation supports checked scalar, string, byte, array, struct, tagged-union, callback, error, handle, and ownership contracts.
The generated program must remain trustworthy
A source-to-source language can look convincing while small semantic differences accumulate underneath. Kinmokusei therefore keeps a registry of Go-equivalent runtime contracts. In v0.1.0, all 75 registered contracts have isolated differential tests against independently handwritten Go programs.
Generated programs are also compiled and tested across supported Go toolchains and target platforms. The release supports Go 1.23 through Go 1.27, and the published compiler is built with Go 1.27 so it can read export data produced by each supported toolchain.
This does not mean that Kinmokusei already covers the entire Go language or ecosystem. It means that accepted behavior is expected to be explicit, testable, and predictable instead of being passed through silently.
Compiler and editor support ship together
The keika distribution includes the compiler and keika lsp --stdio. The official Visual Studio Code extension is a thin client for that same language server, so diagnostics and semantic behavior stay aligned with the compiler version.
The current LSP provides diagnostics, hover, definition, references, rename, document symbols, completion, and signature help for Kinmokusei declarations and supported Go APIs. Matching VSIX files are attached to each release.
Try the public preview
Go 1.23 through Go 1.27 are supported. If Go is already installed, the tagged compiler can be installed with:
go install github.com/puffball1567/kinmokusei/cmd/keika@v0.1.0
keika version
Prebuilt archives for Linux, macOS, and Windows, checksums, and the matching Visual Studio Code extension are available on the v0.1.0 release page.
This is a pre-1.0 public preview. Source syntax and generated APIs may change between minor releases, and several areas remain intentionally incomplete. The current goal is to make the implemented boundary solid enough for real experiments, feedback, and incremental expansion.
If TypeScript-inspired source that produces readable Go sounds useful for a backend or library project, I would be glad to hear what you try, where the generated interface feels natural, and where it does not.
Top comments (0)