CometV2 Docs
These docs cover everything you need to write CometV2 plugins: the scripting language, the built-in functions, and how plugins get access to files on your PC.
New here? Read Environment Setup and Plugins first, then come back to the other pages when you need them.
Download the client from your Panel Dashboard and sign in with your account.
What's in here
- Language: variables, functions, if statements and error handling.
- Plugin API: printing to the console and showing notifications.
- Libraries: tabs (Window Library), files (File System),
task,math,stringandtime. - Guidelines: keeping your account safe, and fixes for common problems.
Environment Setup
CometV2 runs on 64-bit Windows 11. Make sure these are installed before you launch it:
The Visual C++ link downloads the installer straight from Microsoft. If CometV2 still won't start after installing these, restart your PC and try again.
Plugins
A plugin is a script that adds your own tabs and tools to CometV2. Plugins are plain text files with the .cp (CometPlugin) extension.
- Turn on Experimental Mode. Plugins won't load without it.
- Save your script with the
.cpextension and load it from the Plugins page. - To see what your plugin prints, open Press F9 › Show Console.
File access
Plugins can't touch your files until you allow it in CometV2 › Plugins Settings. There are two switches:
- Local file access: lets plugins use their own workspace folder,
%localappdata%\CometV2\Plugins\workspace. Paths like""or"folder/"point inside it. - Public file access: lets plugins use full paths like
"C:/Games/MyGame/", but only inside the folders you add there (and their subfolders).
If a plugin tries to use a file it isn't allowed to, it gets a PermissionError. See Errors for how to handle that.
Naming your tab
Your plugin gets its own tab. To change its name, put this as the very first line of your file:
main.plugin.tab.name = "My Plugin"
A first plugin
This one names its tab, adds a "Tools" tab inside it, and lets you know it loaded:
main.plugin.tab.name = "My Plugin" addnw(type=create.tab, location="My Plugin", name="Tools", tier=1) notify("My Plugin", "Loaded") print("Started at " + time.date("%H:%M"))
To stop and unload a plugin from inside the script, use break. It's covered in Conditions & Flow.
The Basics
CometV2 scripts are read top to bottom, one command per line. If you've used Lua or Python before, most of this will look familiar.
Variables
Give a value a name with =. There's nothing to declare first.
name = "Builderman" lives = 3 print(name)
Text
Text goes in double quotes. Use + to join pieces of text together:
greeting = "Hello " + name print(greeting) -- Hello Builderman
Anything after -- on a line is a comment and is ignored.
None
None means "no value". Functions that don't return anything give back None, and None counts as false in an if. Check for it with == / ~=, or with is / is not:
result = None if result is None then print("nothing yet") end
Converting values
Reads a number out of text. Spaces around it are fine. Gives None if the text isn't a number.
tonumber(" 42 ") -- 42
Turns any value into text. Handy when you build a message out of numbers.
print("Lives: " + tostring(lives))
Doing math
Arithmetic goes through the math library, for example math.add(score, 1). The whole list is on the Math page.
global
Inside a function, name = ... creates a new variable that only exists in that function. If you want to change a variable from outside the function, mark it with global first. You can list several: global a, b.
score = 0 def win() global score score = math.add(score, 1) end win() print(score) -- 1
Functions
A function is a block of code you can run again by its name. Define it with def, close it with end, and call it like any built-in.
def greet(name, greeting="Hello") print(greeting, name) return name end who = greet("Bob")
Parameters
- A parameter can have a default value:
greeting="Hello". It's used when the caller leaves it out. - Any parameter that's left out and has no default is
None. - You can pass arguments by position or by name:
greet("Bob")andgreet(name="Bob")do the same thing.
return
return leaves the function right away and hands a value back to whoever called it. A bare return, or reaching the end without one, gives None.
def check(x) if x == 5 then return "five" end return None end
function
function is the original way to write the same thing and works exactly like def. Use whichever you prefer.
function greet(name) print("Hello " + name) end greet("Builderman")
Conditions & Flow
Use if to run code only when something is true. Add as many elseif branches as you need, an optional else at the end, and close the block with end.
x = 5 if x == 5 then print("five") elseif x > 5 then print("big") else print("small") end
elifandelse ifwork the same aselseif.thenafter the condition is optional, but it makes the code easier to read.- Only one
elseis allowed, and it has to come after everyelseif.
Comparing values
Numbers are compared as numbers; everything else is compared as text. "", false, nil and 0 all count as false.
break
break stops the whole script on the spot. It isn't an error: nothing after it runs, any function it's inside stops too, and the script's waiting tasks (from task.delay and task.defer) are cancelled.
In a plugin, break also unloads the plugin and its tabs disappear. That's true even if it runs later inside a task. In the Code Runner it just stops the script. break() works too.
if readfile("config.txt", "") == "" then print("no config, unloading") break end print("config found")
pass
pass does nothing. Put it where a command is needed but you have nothing to run yet, like an empty branch or a function you'll finish later. pass() works too.
def later() pass end
Errors
When something goes wrong, like a missing file or a folder you didn't allow, the script stops with an error. Wrap risky code in try to handle the error yourself instead.
try print(readfile("save.txt", "C:/Games/MyGame/")) except PermissionError as e print("no access: " + e) except FileNotFoundError print("no save yet") end
How it works
- The code under
tryruns normally. If it fails, the firstexceptthat names that error type runs instead. except PermissionError, FileNotFoundErrorcatches either one.- A plain
exceptwith no type catches anything. It has to be the last one. as eputs the error message intoe.expectis accepted as another spelling ofexcept.
finally
finally goes at the end of a try and always runs: after the try, after an except, when an error isn't caught (the error carries on after it), and on return or break.
try writefile("log.txt", "", "started") except PermissionError print("no file access") finally print("done") end
Error types
Raising your own error
Stops with your own error. The type is optional. A try can catch it like any other error.
error("no save file", "FileNotFoundError")
Output
Two ways to show something to the user: write to the console, or pop up a notification.
Writes text, a number or a variable to the CometV2 VM console. Open it from Press F9 › Show Console. You can pass more than one value.
Syntax
print(value)
Example
name = readfile("d.txt", "folder/") print(name) print("Hello", name)
See all Output functions.
notify
Shows a notification in the CometV2 app. You can pass the arguments by position or by name.
Syntax
notify(title, message)
Example
notify("Welcome", "Script finished") notify(title="Done", message="All good")
See all Output functions.
Window Library
Everything to do with tabs: add your own with addnw, remove them with removetab, and rename your plugin's main tab.
Renaming your plugin's tab
Your plugin gets its own tab. To change its name, put this as the very first line of your file:
main.plugin.tab.name = "My Plugin"
addnw
Adds a new tab to CometV2. All four arguments are passed by name.
Syntax
addnw(type, location, name, tier)
Example
addnw(type=create.tab, location="My Plugin", name="Tools", tier=1)
Arguments
What to create. create.tab makes a brand new tab in the chosen location.
Where the tab goes.
The title shown on the tab, e.g. name="Tools".
The tab's position in the list: tier=1 puts it at the top, tier=4 fourth. An invalid tier, like tier=9, raises a ValueError.
See all Window Library functions.
removetab
Removes a tab you made with addnw. Pass the same location and name you created it with.
removetab is still being worked on and was released early by mistake. We don't recommend using it for now.
Syntax
removetab(location, name)
Example
removetab(location="My Plugin", name="Tools")
See all Window Library functions.
File System
These functions let a plugin save and load its own files. By default they work inside the plugin workspace:
%localappdata%\CometV2\Plugins\workspace
For a path, use "" for the workspace itself or "folder/" for a folder inside it. Full paths like "C:/Games/MyGame/" only work inside folders you added under Public file access (see Plugins).
readfile and writefile take the file name first, then the path. Every other function here takes the path first, then the name.
Reading and writing
Checking what exists
Folders and deleting
Putting it together
Load a settings file if there is one, and create it with a default value if there isn't:
try if isfile("", "settings.txt") == "true" then print(readfile("settings.txt", "")) else writefile("settings.txt", "", "volume=50") end except PermissionError notify("My Plugin", "Turn on file access in Plugins Settings") end
File functions can raise PermissionError, FileNotFoundError, FileExistsError, IsADirectoryError and NotADirectoryError. except OSError catches all of them. More on the Errors page.
readfile
Returns the contents of a file.
Syntax
readfile(filename, path)
Example
text = readfile("d.txt", "folder/") print(text)
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
writefile
Writes text to a file, replacing what was in it. Use \n for a new line.
Syntax
writefile(filename, path, content)
Example
writefile("output.txt", "folder/", "content here")
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
appendfile
Adds text to the end of a file. Use \n to start a new line.
Syntax
appendfile(path, name, content)
Example
appendfile("folder/", "d.txt", "\nmore text")
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
isfile
Returns the text "true" if the file exists, or "false" if it doesn't.
Syntax
isfile(path, name)
Example
if isfile("folder/", "d.txt") == "true" then print("found it") end
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
isfolder
Returns "true" if the folder exists, or "false" if it doesn't.
Syntax
isfolder(path, name)
Example
print(isfolder("", "folder"))
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
makefolder
Creates a folder.
Syntax
makefolder(path, name)
Example
makefolder("", "myfolder")
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
delfile
Deletes a file.
Syntax
delfile(path, name)
Example
delfile("folder/", "d.txt")
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
delfolder
Deletes a folder.
Syntax
delfolder(path, name)
Example
delfolder("", "folder")
Paths start in the plugin workspace. Full paths like "C:/Games/" only work inside folders you allowed under Public file access. Remember that readfile and writefile take the file name first, and the other file functions take the path first.
See all File System functions.
Task
The task library lets you wait, and run code later, without freezing CometV2.
Starting too many tasks at once raises a RuntimeError. A break cancels all of the script's waiting tasks.
task.wait
Pauses the script for that many seconds while the app keeps responding, then returns how long it actually waited.
Syntax
task.wait(seconds)
Example
print("Starting...") task.wait(1.5) print("1.5 seconds later!")
Starting too many tasks at once raises a RuntimeError. A break cancels all of the script's waiting tasks.
See all Task functions.
task.delay
Runs something after a number of seconds, without pausing the rest of your script. Returns a task ID you can pass to task.cancel.
Syntax
task.delay(seconds, callback)
Example
task.delay(2, print("Runs after 2 seconds"))
Starting too many tasks at once raises a RuntimeError. A break cancels all of the script's waiting tasks.
See all Task functions.
task.spawn
Runs something straight away through the task scheduler.
Syntax
task.spawn(callback)
Example
task.spawn(print("Runs now"))
Starting too many tasks at once raises a RuntimeError. A break cancels all of the script's waiting tasks.
See all Task functions.
task.defer
Runs something right after the current script finishes.
Syntax
task.defer(callback)
Example
task.defer(print("Runs when the script is done"))
Starting too many tasks at once raises a RuntimeError. A break cancels all of the script's waiting tasks.
See all Task functions.
task.cancel
Cancels a task.delay or task.defer that hasn't run yet.
Syntax
task.cancel(taskId)
Example
t = task.delay(5, print("Never prints")) task.cancel(t)
Starting too many tasks at once raises a RuntimeError. A break cancels all of the script's waiting tasks.
See all Task functions.
Math
Everything to do with numbers. math.add, math.mul, math.min and math.max take as many numbers as you like.
math.add
Adds numbers together.
Syntax
math.add(a, b, ...)
Example
math.add(2, 3) -- 5
See all Math functions.
math.mul
Multiplies numbers.
Syntax
math.mul(a, b, ...)
Example
math.mul(2, 3, 4) -- 24
See all Math functions.
math.div
a divided by b. Dividing by 0 raises a ValueError.
Syntax
math.div(a, b)
Example
math.div(7, 2) -- 3.5
See all Math functions.
math.mod
The remainder after dividing a by b.
Syntax
math.mod(a, b)
Example
math.mod(7, 3) -- 1
See all Math functions.
math.pow
a to the power of b.
Syntax
math.pow(a, b)
Example
math.pow(2, 10) -- 1024
See all Math functions.
math.abs
The number without its minus sign.
Syntax
math.abs(x)
Example
math.abs(-4) -- 4
See all Math functions.
math.floor
Rounds down.
Syntax
math.floor(x)
Example
math.floor(2.7) -- 2
See all Math functions.
math.round
Rounds to a number of decimal places. Leave out digits to round to a whole number.
Syntax
math.round(x, digits)
Example
math.round(3.14159, 2) -- 3.14
See all Math functions.
math.min
The smallest number.
Syntax
math.min(a, b, ...)
Example
math.min(4, 2, 8) -- 2
See all Math functions.
math.max
The largest number.
Syntax
math.max(a, b, ...)
Example
math.max(4, 2, 8) -- 8
See all Math functions.
math.clamp
Keeps a number between min and max.
Syntax
math.clamp(x, min, max)
Example
math.clamp(15, 0, 10) -- 10
See all Math functions.
math.random
A random whole number from min to max. With no arguments, it gives 0 or 1.
Syntax
math.random(min, max)
Example
roll = math.random(1, 6)
See all Math functions.
String
Functions for working with text. Positions start at 1 for the first character.
string.len
How many characters the text has.
Syntax
string.len(text)
Example
string.len("hello") -- 5
See all String functions.
string.upper
The text in capitals.
Syntax
string.upper(text)
Example
string.upper("hi") -- HI
See all String functions.
string.lower
The text in lower case.
Syntax
string.lower(text)
Example
string.lower("Hi") -- hi
See all String functions.
string.trim
Removes spaces from both ends.
Syntax
string.trim(text)
Example
string.trim(" hi ") -- hi
See all String functions.
string.sub
The part of the text from start to finish. Negative numbers count from the end.
Syntax
string.sub(text, start, finish)
Example
string.sub("Comet", 2, 4) -- ome
See all String functions.
string.find
Where part starts in the text, or 0 if it isn't there.
Syntax
string.find(text, part)
Example
string.find("hello", "ll") -- 3
See all String functions.
string.contains
True if the text has part anywhere in it.
Syntax
string.contains(text, part)
Example
string.contains("hello", "ell") -- true
See all String functions.
string.startswith
True if the text starts with part.
Syntax
string.startswith(text, part)
Example
string.startswith("hello", "he") -- true
See all String functions.
string.endswith
True if the text ends with part.
Syntax
string.endswith(text, part)
Example
string.endswith("file.txt", ".txt") -- true
See all String functions.
string.replace
Replaces every old with new.
Syntax
string.replace(text, old, new)
Example
string.replace("a-b-c", "-", "+") -- a+b+c
See all String functions.
string.rep
The text repeated count times.
Syntax
string.rep(text, count)
Example
string.rep("ab", 3) -- ababab
See all String functions.
string.reverse
The text backwards.
Syntax
string.reverse(text)
Example
string.reverse("abc") -- cba
See all String functions.
string.count
How many times part appears.
Syntax
string.count(text, part)
Example
string.count("banana", "a") -- 3
See all String functions.
Time
Format codes
print(time.date("%Y-%m-%d %H:%M:%S"))
time.now
The number of seconds since 1970. Take it twice and subtract to time something.
Syntax
time.now()
Example
start = time.now() task.wait(2) print(math.sub(time.now(), start))
See all Time functions.
time.date
The local date and time as text. The format is optional.
Syntax
time.date(format)
Example
time.date("%H:%M") -- 14:05
See all Time functions.
Security Guidelines
Keep your account details to yourself. Never share your password, license key or loader file with anyone.
Sharing your license key or account breaks our Terms of Service and gets your hardware locked automatically.
Plugins and your files
- Only run plugins from people you trust. A plugin can read and change anything you give it access to.
- Leave file access off unless a plugin actually needs it.
- Under Public file access, only add the folders a plugin needs, not your whole drive.
Troubleshooting & FAQ
Make sure Experimental Mode is on and the file ends in .cp.
Output goes to the VM console. Open it from Press F9 › Show Console.
Turn on file access in CometV2 › Plugins Settings. For full paths like "C:/Games/", add that folder under Public file access.
Check the order: readfile(filename, path) takes the name first. Most other file functions take the path first.
The loader's file name is randomized each time you download it. Press Ctrl + J and choose "Keep anyway".
Join our Discord at discord.gg/k25qCWbhUF and open a ticket.