# Lua scripts in Skink: init.lua commands and events

> Extend Skink with Lua 5.4 in init.lua: add commands, react to open, save and key events, edit text, show status items and pickers. Project scripts run only once trusted.

Source: https://skink.cc/customize/scripting/

Write Lua in `~/.config/skink/init.lua` (`%APPDATA%\skink\init.lua` on Windows). It runs when Skink starts.

```lua
skink.add_command("reviewed", function()
  skink.insert("// reviewed\n")
end)

skink.on("save", function(path)
  skink.message("saved " .. path)
end)
```

Restart Skink, then run `:reviewed`.

## The API

| Call | Does |
|---|---|
| `skink.add_command(name, fn)` | `:name ARGS` calls `fn(ARGS...)` |
| `skink.on(event, fn)` | `"open"`, `"save"` and `"change"` (after a typing pause) get the path. `"key"` gets an unbound key like `"Ctrl-Alt-J"`; return `true` to take it |
| `skink.text()` `skink.path()` `skink.lang()` `skink.selection()` | Read the file |
| `skink.cursor()` / `skink.set_cursor(line [, col])` | Cursor position, 1-based |
| `skink.insert(text)` / `skink.set_text(text)` | Type at the cursors / replace the whole text |
| `skink.action("Save")` / `skink.command("goto 10")` | Run any action or command |
| `skink.message(text)` | Show a message. `print()` shows a toast |
| `skink.set_status(name, text)` | An item on the right of the status line (`nil` removes it) |
| `skink.pick(title, items, fn)` | A list; `fn(label, index)` runs on Enter |

All the edits of one call undo as one step.

Three complete examples are in [docs/scripts](https://github.com/xuckless/skink/tree/main/docs/scripts): a word count in the status line, trim trailing spaces on save, and a TODO picker.

## Limits

- Lua 5.4 with `table`, `string`, `math` and `utf8`. No `io` or `os`: files and processes go through editor commands. No coroutines.
- Each call may run for 250 ms, string patterns included, then it is stopped. All scripts share 32 MB.
- Errors show as a toast; the editor keeps running.

## Project scripts

A project can ship `.skink/init.lua`. Skink asks before running it:

```text
This project has a script (.skink/init.lua) that can edit files and run commands. Run it? (t)rust / (n)o
```

It asks again whenever the file changes. Scripts that come with [packages](https://skink.cc/customize/packages/) are asked about the same way, once per version.

**Tip:**
Without a script, Skink starts no Lua at all and pays nothing for it.
