<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="repartee — A modern terminal IRC client built with Ratatui, Tokio, and Rust. Scripting, theming, encrypted logging, and more.">
<meta name="keywords" content="irc, terminal, tui, client, chat, repartee, ratatui, tokio, rust">
<meta name="author" content="outragedevs">
<meta property="og:title" content="Examples — repartee">
<meta property="og:description" content="A modern terminal IRC client built with Ratatui, Tokio, and Rust. Inspired by irssi, designed for the future.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://outragedevs.github.io/repartee/">
<meta property="og:image" content="https://outragedevs.github.io/repartee/images/chat.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{title}} — repartee">
<meta name="twitter:description" content="A modern terminal IRC client built with Ratatui, Tokio, and Rust.">
<meta name="twitter:image" content="https://outragedevs.github.io/repartee/images/chat.png">
<title>{{title}} — repartee</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<button class="hamburger" aria-label="Toggle navigation">
<span></span>
<span></span>
<span></span>
</button>
<div class="page-wrapper">
<aside class="sidebar">
<div class="sidebar-header">
<a href="index.html" class="brand">repartee</a>
<span class="brand-tagline">Documentation</span>
</div>
<nav class="sidebar-nav">
<ul>
<li><a href="index.html">Home</a></li>
</ul>
<div class="nav-section">
<span class="nav-section-title">Getting Started</span>
<ul>
<li><a href="installation.html">Installation</a></li>
<li><a href="first-connection.html">First Connection</a></li>
<li><a href="configuration.html">Configuration</a></li>
</ul>
</div>
<div class="nav-section">
<span class="nav-section-title">Reference</span>
<ul>
<li><a href="commands.html">Commands</a></li>
</ul>
</div>
<div class="nav-section">
<span class="nav-section-title">Scripting</span>
<ul>
<li><a href="scripting-getting-started.html">Getting Started</a></li>
<li><a href="scripting-api.html">API Reference</a></li>
<li><a href="scripting-examples.html" class="active">Examples</a></li>
</ul>
</div>
<div class="nav-section">
<span class="nav-section-title">Customization</span>
<ul>
<li><a href="theming.html">Theming</a></li>
<li><a href="theming-format-strings.html">Format Strings</a></li>
<li><a href="logging.html">Logging & Search</a></li>
</ul>
</div>
<div class="nav-section">
<span class="nav-section-title">Usage</span>
<ul>
<li><a href="web-frontend.html">Web Frontend</a></li>
<li><a href="sessions.html">Sessions & Detach</a></li>
</ul>
</div>
<div class="nav-section">
<span class="nav-section-title">Project</span>
<ul>
<li><a href="architecture.html">Architecture</a></li>
<li><a href="faq.html">FAQ</a></li>
</ul>
</div>
</nav>
<div class="sidebar-footer">
Built with <a href="https://www.rust-lang.org">Rust</a>
·
<a href="https://github.com/outragedevs/repartee">GitHub</a>
</div>
</aside>
<div class="sidebar-overlay"></div>
<div class="content-wrapper">
<main class="content">
<h1>Scripting — Examples</h1>
<blockquote>
<p><strong>Note:</strong> Scripts run in a sandboxed Lua environment. The <code>os</code>, <code>io</code>, <code>loadfile</code>, <code>dofile</code>, and <code>package</code> globals are removed. Use <code>api.log()</code> for debug output and <code>api.ui.print()</code> for UI messages.</p>
</blockquote>
<p>Practical Lua script examples for repartee.</p>
<h2>Auto-greet on join</h2>
<p>Greet users when they join a specific channel:</p>
<pre><code class="language-lua">meta = {
name = "autogreet",
version = "1.0",
description = "Auto-greet users on join"
}
function setup(api)
local greet_channels = { ["#mychannel"] = true }
api.on("irc.join", function(event)
if greet_channels[event.channel] and event.nick ~= api.store.our_nick() then
api.irc.say(event.channel, "Welcome, " .. event.nick .. "!")
end
end)
end
</code></pre>
<h2>URL logger</h2>
<p>Log all URLs posted to channels:</p>
<pre><code class="language-lua">meta = {
name = "urllogger",
version = "1.0",
description = "Log URLs from messages"
}
function setup(api)
local urls = {}
api.on("irc.privmsg", function(event)
for url in event.message:gmatch("https?://[%w%.%-/%%?&=_#]+") do
table.insert(urls, {
nick = event.nick,
channel = event.target,
url = url
})
api.log("URL: " .. url .. " from " .. event.nick)
end
end)
api.command("urls", {
handler = function(args)
local count = tonumber(args[1]) or 10
local start = math.max(1, #urls - count + 1)
for i = start, #urls do
local u = urls[i]
api.ui.print(u.nick .. " > " .. u.url)
end
end,
description = "Show recent URLs",
usage = "/urls [count]"
})
end
</code></pre>
<h2>Highlight monitor</h2>
<p>Copy highlighted messages to a dedicated buffer:</p>
<pre><code class="language-lua">meta = {
name = "hilight",
version = "1.0",
description = "Monitor highlighted messages"
}
function setup(api)
api.on("irc.privmsg", function(event)
local my_nick = api.store.our_nick()
if my_nick and event.message:lower():find(my_nick:lower(), 1, true) then
local msg = "[" .. event.target .. "] <" .. event.nick .. "> " .. event.message
api.ui.print(msg)
end
end)
end
</code></pre>
<h2>Custom slap command</h2>
<p>The classic IRC <code>/slap</code> command:</p>
<pre><code class="language-lua">meta = {
name = "slap",
version = "1.0",
description = "Slap someone with a large trout"
}
function setup(api)
local items = {
"a large trout",
"a mass of wet noodles",
"a mass-produced plastic toy",
"a mass of jello",
"a mass of cotton candy",
}
api.command("slap", {
handler = function(args)
local target = args[1]
if not target then
api.ui.print("Usage: /slap <nick>")
return
end
local item = items[math.random(#items)]
local buf = api.store.active_buffer()
if buf then
api.irc.action(buf, "slaps " .. target .. " around a bit with " .. item)
end
end,
description = "Slap someone with a random object",
usage = "/slap <nick>"
})
end
</code></pre>
<h2>Spam filter</h2>
<p>Block messages matching patterns:</p>
<pre><code class="language-lua">meta = {
name = "spamfilter",
version = "1.0",
description = "Filter spam messages"
}
function setup(api)
local patterns = {
"buy cheap",
"free bitcoins",
"click here now",
}
-- High priority so we run before default handlers
api.on("irc.privmsg", function(event)
local lower = event.message:lower()
for _, pattern in ipairs(patterns) do
if lower:find(pattern, 1, true) then
api.log("Blocked spam from " .. event.nick .. ": " .. event.message)
return true -- suppress the event
end
end
end, api.PRIORITY_HIGH)
end
</code></pre>
<h2>Nick highlight with sound</h2>
<p>Print an alert when your nick is mentioned:</p>
<pre><code class="language-lua">meta = {
name = "nickbell",
version = "1.0",
description = "Print alert on nick mention"
}
function setup(api)
api.on("irc.privmsg", function(event)
local my_nick = api.store.our_nick()
if my_nick and event.message:lower():find(my_nick:lower(), 1, true) then
api.ui.print("** Mentioned in " .. event.target .. " by " .. event.nick)
end
end)
end
</code></pre>
<nav class="page-nav">
<a href="scripting-api.html" class="page-nav-link prev">
<span class="page-nav-label">← Previous</span>
<span class="page-nav-title">API Reference</span>
</a>
<a href="theming.html" class="page-nav-link next">
<span class="page-nav-label">Next →</span>
<span class="page-nav-title">Theming</span>
</a>
</nav>
<footer class="site-footer">
Built with <a href="https://www.rust-lang.org">Rust</a> ·
<a href="https://github.com/outragedevs/repartee">GitHub</a> ·
MIT License
</footer>
</main>
</div>
</div>
<script>
(function() {
const hamburger = document.querySelector('.hamburger');
const sidebar = document.querySelector('.sidebar');
const overlay = document.querySelector('.sidebar-overlay');
function toggleSidebar() {
hamburger.classList.toggle('active');
sidebar.classList.toggle('open');
overlay.classList.toggle('visible');
document.body.style.overflow = sidebar.classList.contains('open') ? 'hidden' : '';
}
function closeSidebar() {
hamburger.classList.remove('active');
sidebar.classList.remove('open');
overlay.classList.remove('visible');
document.body.style.overflow = '';
}
hamburger.addEventListener('click', toggleSidebar);
overlay.addEventListener('click', closeSidebar);
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && sidebar.classList.contains('open')) {
closeSidebar();
}
});
})();
</script>
</body>
</html>