| name | tako-sdk-go |
| description | tako.sh Go SDK: ListenAndServe for http.Handler, Listener for custom servers, typed secrets via tako generate, metadata helpers. |
| type | framework |
| library | tako.sh |
| library_version | 0.0.1 |
| sources | ["tako-sh/tako:tako.go","tako-sh/tako:internal"] |
Tako SDK (tako.sh Go module)
Runtime SDK for Go apps deployed with Tako.
CRITICAL: The Go SDK is required — your app must call tako.ListenAndServe() or use tako.Listener() to speak the Tako protocol (health checks, graceful shutdown). Secrets are loaded from the Tako bootstrap envelope at init time: fd 3 first for native processes, then TAKO_BOOTSTRAP_DATA for containers.
CRITICAL: Any framework that implements http.Handler works directly with ListenAndServe. Only Fiber (fasthttp) needs the Listener path.
Core Concept: http.Handler
Tako wraps any standard http.Handler:
package main
import (
"net/http"
"tako.sh"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello from Tako!"))
})
tako.ListenAndServe(mux)
}
This is a complete Tako app. ListenAndServe handles:
- Binding to the correct address (from Tako environment or
0.0.0.0:3000)
- Intercepting
Host: <app>.tako requests for health checks and channel auth
- Graceful shutdown on SIGTERM/SIGINT (10-second grace period)
API
tako.ListenAndServe(handler http.Handler) error
Wraps the handler with Tako protocol and starts serving. Blocks until shutdown.
Works with any http.Handler:
mux := http.NewServeMux()
tako.ListenAndServe(mux)
r := gin.Default()
tako.ListenAndServe(r)
e := echo.New()
tako.ListenAndServe(e)
r := chi.NewRouter()
tako.ListenAndServe(r)
tako.Listener() (net.Listener, error)
Returns a net.Listener for frameworks that manage their own server:
ln, err := tako.Listener()
if err != nil {
log.Fatal(err)
}
app := fiber.New()
app.Listener(ln)
Important: When using Listener() directly, your app must handle the Tako protocol itself (health checks on Host: <app>.tako, secrets endpoint). Most apps should use ListenAndServe instead.
tako.InstanceID() string
Returns the 8-char instance identifier assigned by tako-server. Empty in dev mode.
slog.Info("request handled", "instance", tako.InstanceID())
tako.Version() string
Returns the deploy version string. Empty in dev mode.
tako.Uptime() time.Duration
Returns time since process start.
tako.GetSecret(name string) string
Returns a secret value by name. Prefer the generated Secrets struct instead of calling this directly.
Secrets
Secrets are accessed via a generated struct — type-safe with autocompletion:
db := Secrets.DatabaseUrl()
key := Secrets.ApiKey()
Generate (or update) the typed secrets file:
tako generate
This reads secret names from .tako/secrets.json and generates tako_secrets.go:
package main
import "tako.sh"
var Secrets = struct {
ApiKey func() string
DatabaseUrl func() string
}{
ApiKey: func() string { return tako.GetSecret("API_KEY") },
DatabaseUrl: func() string { return tako.GetSecret("DATABASE_URL") },
}
Run tako generate after adding or removing secrets. tako gen and tako g are aliases.
Internal Protocol
The SDK transparently handles these — you don't interact with them directly:
GET /status on Host: <app>.tako — health check (returns JSON with status, instance_id, version, pid, uptime_seconds)
POST /channels/authorize on Host: <app>.tako — channel auth callback for tako-server
- Token authentication via
x-tako-internal-token header (required in production, skipped in dev)
- Secrets are read from the Tako bootstrap envelope at process startup, not via HTTP. Native processes use fd 3; containers use
TAKO_BOOTSTRAP_DATA.
Common Mistakes
1. CRITICAL: Not using the SDK
http.ListenAndServe(":3000", mux)
tako.ListenAndServe(mux)
2. HIGH: Hardcoding the listen address
ln, _ := net.Listen("tcp", ":8080")
tako.ListenAndServe(mux)
ln, _ := tako.Listener()
4. MEDIUM: Using Listener without protocol handling
ln, _ := tako.Listener()
http.Serve(ln, mux)
tako.ListenAndServe(mux)