Skip to content

Data & Storage

Workspace-scoped document storage backed by LiteDB. Requires an open workspace.

MethodSignatureAsyncDescription
put(collection, key, data)NoStore a document
get(collection, key) → StoreDoc | nullNoRetrieve a document
list(collection, options?) → StoreDoc[]NoList documents in a collection
search(collection, query, options?) → StoreDoc[]NoText search within a collection
delete(collection, key) → booleanNoDelete a document
count(collection) → numberNoCount documents
clear(collection)NoDelete all documents in a collection
collections() → string[]NoList all collection names

StoreDoc:

{
key: string
data: any
createdAt: string // ISO 8601
updatedAt: string // ISO 8601
}

StoreListOptions:

{
limit?: number // default: 100
offset?: number // default: 0
sort?: string // "key", "createdAt", "updatedAt" (default)
order?: string // "asc" or "desc" (default)
}
async function main() {
// Store data
g.store.put("products", "item-1", {
name: "Widget",
price: 9.99,
inStock: true
});
// Retrieve it
const doc = g.store.get("products", "item-1");
if (doc) g.log("Found: " + doc.data.name);
// Search
const results = g.store.search("products", "Widget");
g.log("Matches: " + results.length);
}


Workspace-scoped persistent queue with priority levels and dead-letter support. Requires an open workspace.

MethodSignatureAsyncDescription
enqueue(name, data, options?)NoAdd an item to a queue
dequeue(name) → QueueItem | nullNoCheck out the next item
commit(checkoutId)NoMark a dequeued item as completed
abort(checkoutId, error?) → booleanNoReturn an item to the queue (or dead-letter if max retries)
peek(name) → QueueItem | nullNoView the next item without checking it out
count(name) → numberNoCount pending items
clear(name)NoDelete all items in a queue
list(name, options?) → QueueItem[]NoList pending items
queues() → string[]NoList all queue names
deadLetter(name, options?) → DeadLetterItem[]NoList dead-letter items
retry(name, deadLetterId)NoRe-enqueue a dead-letter item
waitForItem(name, options?) → Promise<QueueItem | null>YesBlock until an item is available

QueueEnqueueOptions:

{
priority?: number // 0=low, 1=normal (default), 2=high
maxRetries?: number // default: 3
}

QueueItem:

{
id: number
data: any
priority: number
attempts: number
maxRetries: number
enqueuedAt: string
lastAttemptAt?: string
lastError?: string
}
async function main() {
// Enqueue work items
g.queue.enqueue("urls", { url: "https://example.com/page1" });
g.queue.enqueue("urls", { url: "https://example.com/page2" }, { priority: 2 });
// Process items
const item = g.queue.dequeue("urls");
if (!item) return g.log("Queue empty");
await g.nav.navigateToUrl(item.data.url);
const html = await g.page.getDom();
// Mark complete
g.queue.commit(item.id);
}


Workspace-scoped Lucene.NET search index. Supports boolean operators, wildcards, fuzzy matching, and field-specific queries. Requires an open workspace.

MethodSignatureAsyncDescription
index(fields)NoIndex a document (must include _key and _collection)
query(queryString, options?) → SearchResult[]NoSearch the index with Lucene query syntax
delete(collection, key)NoRemove a document from the index
deleteByCollection(collection) → numberNoRemove all documents in a collection
count(collection?) → numberNoCount indexed documents
clear()NoClear the entire index

SearchResult:

{
key: string
collection: string
score: number // Lucene relevance score
fields: Record<string, string>
}
async function main() {
// Index documents
g.search.index({
_key: "article-1",
_collection: "articles",
title: "Getting Started with Guida",
body: "Guida is a scriptable browser..."
});
// Query with Lucene syntax
const results = g.search.query("scriptable browser", { collection: "articles" });
for (const r of results) {
g.log(r.fields.title + " (score: " + r.score + ")");
}
}


## g.s3.* — S3-Compatible Object Storage

Section titled “## g.s3.* — S3-Compatible Object Storage”

S3-compatible storage via MinIO SDK. Works with AWS S3, MinIO, and any S3-compatible service. The conn parameter is a secret name containing the connection string. Blocked for MCP-origin scripts.

MethodSignatureAsyncDescription
listBuckets(conn) → Promise<S3BucketInfo[]>YesList all accessible buckets
bucketExists(conn, bucket) → Promise<boolean>YesCheck if a bucket exists
listObjects(conn, bucket, options?) → Promise<S3ObjectInfo[]>YesList objects in a bucket
getObjectText(conn, bucket, key) → Promise<string>YesDownload object as UTF-8 text
getObject(conn, bucket, key, localPath) → PromiseYesDownload object to a local file
putObjectText(conn, bucket, key, content, contentType?) → PromiseYesUpload text as an object
putObject(conn, bucket, key, localPath, contentType?) → PromiseYesUpload a local file as an object
deleteObject(conn, bucket, key) → PromiseYesDelete an object
objectExists(conn, bucket, key) → Promise<boolean>YesCheck if an object exists
createBucket(conn, bucket, region?) → PromiseYesCreate a new bucket
copyObject(conn, srcBucket, srcKey, dstBucket, dstKey) → PromiseYesServer-side copy (no data through client)
getPresignedUrl(conn, bucket, key, options?) → Promise<string>YesGenerate a time-limited presigned URL

S3ListOptions:

{
prefix?: string // filter objects by key prefix
maxKeys?: number // max objects to return (default: 1000)
}

S3BucketInfo:

{
name: string
creationDate: string // ISO 8601
}

S3ObjectInfo:

{
key: string // object key (path)
size: number // size in bytes
lastModified: string // ISO 8601
etag: string // entity tag (hash)
}

S3PresignedUrlOptions:

{
method?: string // "GET" (download, default) or "PUT" (upload)
expiry?: number // URL expiry in seconds (default: 3600)
}
async function main() {
// List CSV files in a bucket
const files = await g.s3.listObjects("my-s3", "data-bucket", {
prefix: "exports/"
});
g.log("Found " + files.length + " objects");
// Upload scraped data
await g.s3.putObjectText(
"my-s3", "data-bucket", "exports/results.json",
JSON.stringify({ items: [1, 2, 3] }),
"application/json"
);
// Generate a shareable link
const url = await g.s3.getPresignedUrl("my-s3", "data-bucket", "exports/results.json", {
expiry: 86400 // 24 hours
});
g.log("Download link: " + url);
}


MongoDB operations via MongoDB.Driver. The conn parameter is a secret name containing the connection string. Uses automatic connection pooling. Blocked for MCP-origin scripts.

MethodSignatureAsyncDescription
find(conn, db, collection, filter?, options?) → Promise<object[]>YesFind documents matching a filter
findOne(conn, db, collection, filter?) → Promise<object | null>YesFind first matching document
insertOne(conn, db, collection, document) → Promise<MongoInsertResult>YesInsert a single document
insertMany(conn, db, collection, documents) → Promise<MongoInsertManyResult>YesInsert multiple documents
updateOne(conn, db, collection, filter, update) → Promise<MongoUpdateResult>YesUpdate first matching document
updateMany(conn, db, collection, filter, update) → Promise<MongoUpdateResult>YesUpdate all matching documents
deleteOne(conn, db, collection, filter) → Promise<MongoDeleteResult>YesDelete first matching document
deleteMany(conn, db, collection, filter) → Promise<MongoDeleteResult>YesDelete all matching documents
replaceOne(conn, db, collection, filter, replacement) → Promise<MongoUpdateResult>YesReplace first matching document
countDocuments(conn, db, collection, filter?) → Promise<number>YesCount matching documents
listDatabases(conn) → Promise<string[]>YesList all database names
listCollections(conn, db) → Promise<string[]>YesList collection names in a database
aggregate(conn, db, collection, pipeline) → Promise<object[]>YesRun an aggregation pipeline
createIndex(conn, db, collection, keys, options?) → Promise<string>YesCreate an index, returns index name
dropCollection(conn, db, collection) → PromiseYesDrop a collection
distinct(conn, db, collection, fieldName, filter?) → Promise<any[]>YesGet distinct values for a field
bulkWrite(conn, db, collection, operations) → Promise<MongoBulkWriteResult>YesExecute multiple write operations in a batch

MongoFindOptions:

{
sort?: object // e.g., { name: 1, age: -1 }
limit?: number
skip?: number
projection?: object // e.g., { name: 1, _id: 0 }
}

MongoInsertResult:

{
insertedId: string // the _id of the inserted document
}

MongoInsertManyResult:

{
insertedCount: number
insertedIds: string[]
}

MongoUpdateResult:

{
matchedCount: number
modifiedCount: number
}

MongoDeleteResult:

{
deletedCount: number
}

MongoIndexOptions:

{
unique?: boolean // enforce uniqueness
name?: string // custom index name
}

MongoBulkOperation:

{
type: string // "insertOne", "updateOne", "updateMany",
// "deleteOne", "deleteMany", "replaceOne"
filter?: object // for update/delete/replace
document?: object // for insertOne
update?: object // for updateOne/updateMany
replacement?: object // for replaceOne
}

MongoBulkWriteResult:

{
insertedCount: number
matchedCount: number
modifiedCount: number
deletedCount: number
}
async function main() {
const conn = "my-mongo"; // secret name with connection string
// Insert a document
const result = await g.mongodb.insertOne(conn, "scraping", "products", {
name: "Widget", price: 9.99, category: "tools"
});
g.log("Inserted: " + result.insertedId);
// Find with filter and sort
const docs = await g.mongodb.find(conn, "scraping", "products",
{ price: { $lt: 20 } },
{ sort: { price: 1 }, limit: 10 }
);
g.log("Found " + docs.length + " cheap products");
// Aggregation pipeline
const stats = await g.mongodb.aggregate(conn, "scraping", "products", [
{ $group: { _id: "$category", avgPrice: { $avg: "$price" }, count: { $sum: 1 } } },
{ $sort: { count: -1 } }
]);
for (const s of stats) {
g.log(s._id + ": " + s.count + " items, avg $" + s.avgPrice.toFixed(2));
}
}


PostgreSQL operations via Npgsql. Uses $1, $2, ... positional parameters — never interpolate values into SQL strings. The conn parameter is a secret name containing the connection string. Uses automatic connection pooling. Blocked for MCP-origin scripts.

MethodSignatureAsyncDescription
query(conn, sql, params?) → Promise<object[]>YesSELECT returning all rows
queryOne(conn, sql, params?) → Promise<object | null>YesSELECT returning first row
execute(conn, sql, params?) → Promise<PgExecuteResult>YesINSERT/UPDATE/DELETE
scalar(conn, sql, params?) → Promise<any>YesReturn first column of first row
transaction(conn, callback) → Promise<any>YesExecute callback in a transaction (JS only)
executeBatch(conn, statements) → Promise<PgBatchResult>YesMultiple statements in a single transaction
copyFrom(conn, table, rows, options?) → Promise<PgCopyResult>YesBulk insert via COPY protocol
copyTo(conn, query, options?) → Promise<string[][]>YesBulk export via COPY protocol
listDatabases(conn) → Promise<string[]>YesList non-template database names
listSchemas(conn, options?) → Promise<string[]>YesList schema names
listTables(conn, schema?) → Promise<PgTableInfo[]>YesList tables and views with row counts
describeTable(conn, table, schema?) → Promise<PgColumnInfo[]>YesColumn metadata (types, nullability, defaults, PKs)
listIndexes(conn, table, schema?) → Promise<PgIndexInfo[]>YesIndex metadata with definitions
listConstraints(conn, table, schema?) → Promise<PgConstraintInfo[]>YesConstraint metadata (PK, FK, UNIQUE, CHECK)

PgExecuteResult:

{
rowsAffected: number
}

PgTableInfo:

{
name: string
schema: string
type: string // "table" or "view"
estimatedRows: number // from pg_class.reltuples
}

PgColumnInfo:

{
name: string
type: string // e.g., "integer", "character varying", "timestamp with time zone"
nullable: boolean
defaultValue: string | null
isPrimaryKey: boolean
maxLength: number | null // for string types
}

PgIndexInfo:

{
name: string
columns: string[]
isUnique: boolean
isPrimary: boolean
definition: string // full CREATE INDEX statement
}

PgConstraintInfo:

{
name: string
type: string // "PRIMARY KEY", "FOREIGN KEY", "UNIQUE", "CHECK"
columns: string // comma-separated column names
definition: string // constraint definition
}

PgBatchStatement:

{
sql: string // SQL with $1, $2, ... positional parameters
params?: any[] // parameter values
}

PgBatchResult:

{
results: PgExecuteResult[] // per-statement rowsAffected counts
}

PgTransactionProxy — passed to the transaction callback:

{
query: (sql, params?) => Promise<object[]>
queryOne: (sql, params?) => Promise<object | null>
execute: (sql, params?) => Promise<PgExecuteResult>
scalar: (sql, params?) => Promise<any>
}

PgCopyFromOptions:

{
columns?: string[] // column names to map row values to (in order)
schema?: string // default: "public"
}

PgCopyToOptions:

{
schema?: string // default: "public" (only for table names, not SQL queries)
}

PgCopyResult:

{
rowsCopied: number
}

PgSchemaOptions:

{
includeSystem?: boolean // include pg_* and information_schema (default: false)
}
async function main() {
const conn = "my-postgres"; // secret name with connection string
try {
// Query with parameters
const rows = await g.postgres.query(conn,
"SELECT id, name, price FROM products WHERE price < $1 ORDER BY price",
[20.00]
);
g.log("Found " + rows.length + " products");
// Transaction with callback
const result = await g.postgres.transaction(conn, async (tx) => {
await tx.execute("INSERT INTO orders (product_id, qty) VALUES ($1, $2)", [42, 3]);
await tx.execute("UPDATE products SET stock = stock - $1 WHERE id = $2", [3, 42]);
return await tx.scalar("SELECT count(*) FROM orders");
});
g.log("Total orders: " + result);
// Bulk insert via COPY (much faster than row-by-row INSERT)
const copyResult = await g.postgres.copyFrom(conn, "products", [
["Widget A", 9.99, 100],
["Widget B", 14.99, 50],
["Widget C", 24.99, 25]
], { columns: ["name", "price", "stock"] });
g.log("Imported " + copyResult.rowsCopied + " rows");
} catch (e) {
g.log("Error: " + e.message);
}
}


Native support for querying and indexing data in external Elasticsearch clusters using Elastic.Clients.Elasticsearch. The conn parameter is a secret name containing the connection JSON object (url and optional apiKey or username/password). Blocked for MCP-origin scripts.

MethodSignatureAsyncDescription
ping(conn) → Promise<boolean>YesVerify connection to the cluster. Returns true if successful.
info(conn) → Promise<ElasticsearchInfoResult>YesRetrieve cluster metadata (name, version, tagline, etc.).
createIndex(conn, indexName, mappingJson?) → Promise<boolean>YesCreate an index with an optional JSON mapping string.
deleteIndex(conn, indexName) → Promise<boolean>YesDelete an existing index.
index(conn, indexName, id, document) → Promise<boolean>YesIndex a single JS object into the cluster.
get(conn, indexName, id) → Promise<any>YesRetrieve a single document by ID. Returns the parsed _source object.
bulk(conn, indexName, documents, chunkSize?) → Promise<ElasticsearchBulkResult>YesHigh-throughput ingestion. Automatically chunks large arrays to prevent payload limits.
search(conn, indexName, queryDsl) → Promise<any>YesExecute a raw JSON query DSL string or JS object and return deserialized hits.

ElasticsearchInfoResult:

{
name: string
clusterName: string
clusterUuid: string
version: string
tagline: string
}

ElasticsearchBulkResult:

{
total: number
successful: number
failed: number
}
async function main() {
const conn = "my-elastic"; // secret name
// Check connection
const isUp = await g.elasticsearch.ping(conn);
if (!isUp) return g.log("Connection failed");
// Bulk index documents
const docs = [{ id: 1, text: "A" }, { id: 2, text: "B" }];
const bulkRes = await g.elasticsearch.bulk(conn, "products", docs, 1000);
g.log(`Indexed ${bulkRes.successful} out of ${bulkRes.total}`);
// Query DSL search
const searchRes = await g.elasticsearch.search(conn, "products", {
query: { match_all: {} }
});
g.log(`Total hits: ${searchRes.hits.total.value}`);
}