Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kiwifs.com/llms.txt

Use this file to discover all available pages before exploring further.

You can embed KiwiFS directly in any Go application using the pkg/kiwi package. This gives you a fully functional knowledge server without running a separate process.

Installation

go get github.com/kiwifs/kiwifs/pkg/kiwi

Quick start

Create a KiwiFS server, configure it with options, and start serving.
package main

import (
    "log"

    "github.com/kiwifs/kiwifs/pkg/kiwi"
)

func main() {
    srv, err := kiwi.New("/data/knowledge",
        kiwi.WithSearch("sqlite"),
        kiwi.WithVersioning("git"),
        kiwi.WithAuth("apikey", "my-secret"),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer srv.Close()

    log.Println("KiwiFS listening on :3333")
    log.Fatal(srv.ListenAndServe(":3333"))
}

Options

Configure KiwiFS behavior by passing option functions to kiwi.New.
OptionDescription
kiwi.WithSearch(engine)Search engine. "sqlite" for full-text search or "grep" for simple string matching.
kiwi.WithVersioning(strategy)Version control strategy. "git" for git history, "cow" for copy-on-write snapshots, or "none" to disable.
kiwi.WithAuth(authType, key)Authentication. Set authType to "apikey" and provide the key, or "none" to disable.
kiwi.WithCORSOrigins(origins...)Allowed CORS origins. Pass one or more origin URLs.
srv, err := kiwi.New("/data/knowledge",
    kiwi.WithSearch("sqlite"),
    kiwi.WithVersioning("git"),
    kiwi.WithAuth("apikey", "my-secret"),
    kiwi.WithCORSOrigins("https://app.example.com", "http://localhost:3000"),
)

Methods

The kiwi.Server type provides these methods.
MethodSignatureDescription
HandlerHandler() http.HandlerReturns the HTTP handler. Use this to mount KiwiFS alongside other routes.
PipelinePipeline() *pipeline.PipelineReturns the pipeline for programmatic file operations.
ListenAndServeListenAndServe(addr string) errorStart the HTTP server on the given address.
ShutdownShutdown(ctx context.Context) errorGracefully shut down the server. In-flight requests complete before the method returns.
CloseClose() errorRelease all resources (search indexes, file watchers, git locks).

Mount alongside an existing server

Use srv.Handler() to mount KiwiFS as a route within your existing HTTP application.
package main

import (
    "log"
    "net/http"

    "github.com/kiwifs/kiwifs/pkg/kiwi"
)

func main() {
    // Create the KiwiFS server
    kiwifsSrv, err := kiwi.New("/data/knowledge",
        kiwi.WithSearch("sqlite"),
        kiwi.WithVersioning("git"),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer kiwifsSrv.Close()

    // Set up your application router
    mux := http.NewServeMux()

    // Mount KiwiFS under /knowledge/
    mux.Handle("/knowledge/", http.StripPrefix("/knowledge", kiwifsSrv.Handler()))

    // Your own routes
    mux.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("ok"))
    })

    log.Println("App listening on :8080")
    log.Fatal(http.ListenAndServe(":8080", mux))
}
When mounting under a subpath, use http.StripPrefix so KiwiFS receives paths relative to its root.

Programmatic file operations

Use srv.Pipeline() to read and write files without going through HTTP.
pipe := srv.Pipeline()

// Write a file
err := pipe.Write("concepts/auth.md", []byte(`---
title: Authentication
status: draft
---

# Authentication

Overview of auth mechanisms.
`))

// Read a file
content, err := pipe.Read("concepts/auth.md")

// List files
files, err := pipe.List("concepts/")
The pipeline respects the same versioning and indexing rules as the HTTP API. Writes trigger git commits (if versioning is enabled) and update the search index automatically.

Graceful shutdown

Handle OS signals to shut down KiwiFS cleanly. This flushes pending async commits and releases file locks.
package main

import (
    "context"
    "log"
    "os"
    "os/signal"
    "syscall"
    "time"

    "github.com/kiwifs/kiwifs/pkg/kiwi"
)

func main() {
    srv, err := kiwi.New("/data/knowledge",
        kiwi.WithSearch("sqlite"),
        kiwi.WithVersioning("git"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Start server in a goroutine
    go func() {
        if err := srv.ListenAndServe(":3333"); err != nil {
            log.Printf("server stopped: %v", err)
        }
    }()

    // Wait for interrupt signal
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit

    // Graceful shutdown with timeout
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    if err := srv.Shutdown(ctx); err != nil {
        log.Printf("shutdown error: %v", err)
    }
    srv.Close()
    log.Println("server stopped")
}
Always call srv.Close() or srv.Shutdown(ctx) before your program exits. Skipping this can leave stale git lock files or incomplete search indexes.
Last modified on May 4, 2026