VIP-6: Effect's functions are globals
Status: accepted by Will, 2026-10-28.
Decision
effect function load(q) {
const r = try tryPromise((signal) => queryDb(q, { signal })) // Effect.tryPromise
const n = try sync(() => Date.now()) // Effect.sync
try retry(tryPromise(() => queryDb(q)), policy)
try sleep("1 second")
const d = try Effect.try(() => JSON.parse(s)) // `try` is a reserved word, so it stays Effect.try
}- Every export of Effect's
Effectmodule is a global variable in a.vibefile:retry,sleep,log,all,race,tryPromise,sync,callback,map, and so on. A local declaration or import shadows one, as with any global. - An option in
tsconfig.jsonturns the globals off (VIP-14: "like before this should be configurable in the tsconfig.json"). - A name that clashes is not a global, and is used as
Effect.xinstead. A name clashes if it is:- a reserved word:
try,catch,void,let; - a JavaScript global:
undefined; - a VibeLang keyword.
- a reserved word:
- If a later VIP adds a keyword with the same name as an Effect export, the global is removed. That may happen to
match,when,serviceandprovide. - No language feature wraps TypeScript into an Effect. You use Effect's own functions (
tryPromise,sync,callback,Effect.try), and their arrows capture locals as in Effect TS.
Corrected 2026-10-29: the example calls queryDb, a Promise-returning function imported from a .ts module, because VIP-33 forbids platform calls such as fetch anywhere in a .vibe file.
Prior art
Rust's prelude, Elixir's Kernel, Kotlin's top-level launch and delay, Python's builtins.
Will's words
"We should have a VIP regarding global variables where we make Effect.* global meaning we don't even need a language feature it can just be existing effect syntax for wrapping typescript"
"Ok these are global varaibles. There should be a config option to turn off globals. Anything that clashes must be accessed via Effect.* instead of globally if it clashes with either a javascript global or it clashes with a keyword we end up adding. If we add the keyword in future we will also remove it (like in case of provide and service)"
Footnote: old VibeLang
Old VibeLang is a reference only; nothing in it is part of the language unless a VIP adds it. For implementers, this VIP replaces:
- D151's hand-picked list of prefix-free functions, widened here to every
Effectexport. - D148's hatches (
sync,try,callbackas special prelude forms) and D229's no-capture rule.
VIP-14 decides which Effect modules are in scope without an import, with its configuration and precedence rules. Historical D146 supplies no independent authority.