# Lotusscript

> Use when writing LotusScript code, Domino agents, script libraries, or working with HCL Domino backend classes. Use when encountering NotesSession, NotesDatabase, NotesDocument, or any Notes* classes. Use when building web agents that return HTML or JSON from Domino.

- Skill: `gigbuilder/lotusscript` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add gigbuilder/lotusscript`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gigbuilder/lotusscript/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: gigbuilder (https://skillmd.com/u/gigbuilder)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/gigbuilder/lotusscript

---


# LotusScript for HCL Domino

LotusScript is the scripting language for HCL Domino (formerly IBM Lotus Notes/Domino). It resembles Visual Basic but has critical differences. Target platform: **Domino 14**, backend classes only (web-based applications).

## CRITICAL: LotusScript Is NOT Visual Basic

Claude frequently confuses LotusScript with VBA/VB6. These differences will cause broken code if ignored:

| Feature | LotusScript | Visual Basic |
|---------|-------------|--------------|
| Default parameter passing | **ByRef** (always assume ByRef) | ByVal |
| Associative arrays | **List** type (built-in) | No equivalent (use Dictionary) |
| Iterate collections | **ForAll** loop | No equivalent (use For Each) |
| String functions | `StrLeft`, `StrRight`, `StrLeftBack`, `StrRightBack` | No equivalent |
| Run formula language | `Evaluate("@Formula")` | No equivalent |
| Include files | `%Include "filename"` | No equivalent |
| Module scope | `Option Public` (makes module members public) | `Public` on each member |
| Require declarations | `Option Declare` | `Option Explicit` |
| Object cleanup | `Delete` statement | `Set x = Nothing` |
| Print in web agents | Writes to **HTTP response** | Writes to console/debug |
| Property syntax | `Property Get/Set/Let` with no parentheses on Get | Parentheses on Get |
| No `Set` for assignment | `Set` only for object references | `Set` for objects, `Let` for values |
| String variant | Use `$` suffix: `Left$()`, `Mid$()` | No `$` variants |
| Class events | `Sub New` / `Sub Delete` | `Class_Initialize` / `Class_Terminate` |
| Error object | `Err`, `Erl`, `Error$` (line number tracking) | `Err.Number`, `Err.Description` |
| Boolean values | `True = -1`, `False = 0` | Same, but watch for implicit conversion |

## Scope: Backend Classes Only

This project uses Domino as a **web application server**. All code runs in agents and script libraries triggered by HTTP requests. **Never use front-end (UI) classes:**

- **DO NOT USE:** `NotesUIWorkspace`, `NotesUIDocument`, `NotesUIView`, `NotesUIDatabase`
- **USE:** `NotesSession`, `NotesDatabase`, `NotesDocument`, `NotesView`, etc.

## Web Agent Essentials

```lotusscript
Sub Initialize
    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim doc As NotesDocument

    Set db = session.CurrentDatabase
    Set doc = session.DocumentContext  ' CGI variables and POST data

    ' Read query string
    Dim queryString As String
    queryString = doc.GetItemValue("Query_String_Decoded")(0)

    ' Output HTTP response
    Print "Content-Type: application/json"
    Print ""
    Print |{"status": "ok"}|
End Sub
```

**Key web agent rules:**
- `Print` writes to the HTTP response body — first print `Content-Type`, then a blank line, then body
- `session.DocumentContext` provides CGI variables as fields on a document
- Pipe `|` characters delimit strings that can contain quotes
- Web agents run as the authenticated user (or Anonymous for unauthenticated)

## Common Gotchas

1. **GetItemValue returns a Variant array** — always index with `(0)` for single values
2. **Save is not automatic** — always call `doc.Save True, False` after modifications
3. **Nothing checks** — always check `If Not (doc Is Nothing)` before using objects
4. **String comparison** — use `StrCompare` or `LCase$()` for case-insensitive comparison
5. **Arrays are 0-based by default** — use `Option Base 1` to change, or use `LBound`/`UBound`
6. **Lists vs Arrays** — Lists are associative (keyed by string), Arrays are indexed by integer
7. **Variant vs typed variables** — always use `Option Declare` and type your variables
8. **RichText fields** — cannot be read with `GetItemValue`, must use `GetFirstItem` and cast to `NotesRichTextItem`
9. **Date handling** — use `NotesDateTime` objects, not native date functions, for Domino date fields
10. **Chr(0) is CRLF** — in Domino, `Chr(0)` acts as `Chr(10)+Chr(13)` (newline), not a null byte as in standard ASCII. Long-standing Domino behavior since the 1990s.
11. **Large POST bodies are chunked** — Domino splits large `Request_Content` into numbered fields (`request_content_000`, `request_content_001`, etc.), each ~32-64K depending on platform
12. **NotesHTTPRequest.ResponseCode is a String** — returns the full status line (e.g., `"HTTP/1.1 200 OK"`), NOT an integer. Use `InStr(http.ResponseCode, "200") > 0` to check status — never `http.ResponseCode = 200`

## Reference Files

- **syntax-fundamentals.md** — Data types, control flow, error handling, strings, arrays, Lists
- **domino-object-model.md** — Backend class hierarchy and usage (NotesSession → NotesDocument)
- **domino-modern-features.md** — Domino 10-14: DQL, JSON classes, HTTPRequest, LS2J, MIME
- **web-agent-patterns.md** — Web agent patterns: CGI vars, JSON output, CRUD, error handling

