Installation

OwlKnit lives in ReplicatedStorage.OwlKnit, same as any Wally package. Once it's in your project, starting the framework only takes two calls per side: load your modules, then Owl.Start().

Server

Load every Service from a folder, then start the framework. Owl.Start() returns a promise that resolves once every OwlInit/OwlStart phase across all Services has completed.

ServerScriptService/Init.server.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Owl = require(ReplicatedStorage.OwlKnit.Owl)
 
-- > // 1. Load every Service from a folder
Owl.AddServices(script.Parent.Services)
 
-- > // 2. Start (with optional config)
Owl.Start({
    Verbose = true,
    GlobalMiddleware = {
        Inbound = {
            Owl.Util.RateLimiter.perPlayer(30, 1, "Global"),
        },
    },
}):andThen(function()
    print("Owl Server started!")
end):catch(warn)

Client

Same shape with Controllers instead of Services. There's no GlobalMiddleware on the client, middleware is a server-side security concern, covered in Middleware.

StarterPlayerScripts/Init.client.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Owl = require(ReplicatedStorage.OwlKnit.Owl)
 
-- > // 1. Load every Controller from a folder
Owl.AddControllers(script.Parent.Controllers)
 
-- > // 2. Start
Owl.Start():andThen(function()
    print("Owl Client started!")
end):catch(warn)

Configuration

Owl.Config can be edited before Owl.Start(). Once the framework has started, the config table is frozen (table.freeze), any attempt to modify it afterwards throws an error.

Key Type Default Description
Verbose boolean false Enables [Owl][INFO] debug logs
InitTimeout number 30 Timeout in seconds for the OwlInit phase
StartTimeout number 30 Timeout in seconds for the OwlStart phase
GlobalMiddleware table {} Global middleware applied to every remote
Backend string ProfileStore/DataStore2 Type of data used (ProfileStore recommended)
AutoSave boolean true Allow autosave for datas
SaveInterval number 60 How many times before autosave

For the three last (Backend, AutoSave and SaveInterval), check (see OwlData)

You can set these either directly on Owl.Config or inline as the first argument to Owl.Start(), both are equivalent but passing everything to Owl.Start() is the recommended style since it keeps your whole config in one place.

Init.server.lua
Owl.Start({
    Verbose = true,
    InitTimeout = 60,
    StartTimeout = 60,
    GlobalMiddleware = {
        Inbound = { Owl.Util.RateLimiter.perPlayer(30, 1, "Global") },
    },
    Data = {
		Backend = "ProfileStore",
		AutoSave = true,
		SaveInterval = 60,
	},
}):catch(warn)

Owl.Start() rejects if any Service or Controller throws during OwlInit or if a phase exceeds its timeout. Always attach a :catch(warn), a silent failure at startup is much harder to debug than a loud one.

Where to go next

  • Want to see it end-to-end? First Project walks through creating one real Service and Controller together.
  • Coming from Knit? Check Owl vs Knit - the startup sequence above is one of the few things that stayed identical on purpose.