This toolkit provides essential tools for developing in GreyScript, the scripting language used in Grey Hack. The extension offers syntax highlighting, code execution, bundling, minification, and more to streamline GreyScript development in VSCode.
Prefer a different editor? The GreyScript Language Server is also available and compatible with IDEs like Sublime Text, IntelliJ, nvim and more. Examples for setting up these editors are included in the repository.
Project Resources
- Changelog: View the latest changes and updates.
- greybel-js CLI: Command-line interface for Greybel.
- GreyScript Documentation: API documentation for GreyScript.
Projects Using Greybel
- gsse: GreyScript Script Extender is a modular library that aims to expand the current scripting framework of greyscript.
- minizod: A lightweight, Zod-inspired validation library for MiniScript.
- Minesweeper: A Minesweeper game created in GreyScript. (Demo project)
- JSON Parser: JSON parsing functionality. (Demo project)
- TEdit: Text editor built with GreyScript. (Demo project)
Do you have a project that uses Greybel? If so, feel free to create a pull request to showcase it here.
Grey Hack Tools
- Image Transformer: Tool for transforming images in Grey Hack.
- Website Image Generator: Tool for generating Grey Hack website images.
Community
- awesome-greyhack: List with several resources related to Grey Hack.
- Greybel Discord: Join the community on Discord for support and discussion.
This extension automatically detects .gs, .src, and .ms files and provides convenient commands to streamline your workflow.
Commands available (CTRL+SHIFT+P):
Greybel: Build file from context- Transpile/Build your GreyScript code. More infoGreybel: Run/Debug file from context- Run your GreyScript code. More infoGreybel: Share- Share your code with others easily. More infoGreybel: API- Open the API browser for quick reference. More infoGreybel: Snippets- Insert GreyScript snippets into your code. More infoGreybel: Preview output– View a preview of the ingame like output. More infoGreybel: Import file into the game– Upload files into the game. More info
You can also access these commands through the context menu for quick right-click access.
Tip: Make sure to configure settings to customize Greybel to your preferences.
There are two tutorial videos available that demonstrate the setup and configuration process:
Windows Setup Tutorial
The first video shows how to install the message-hook plugin on Windows. It also provides insights on configuring the extension to enable in-game import, auto-compile functionality, and changing the type analyzer strategy. Huge thanks to @redit0 for creating it!
Linux Setup Tutorial
The second video demonstrates how to install the message-hook plugin on Linux using Proton. Big thanks to @0x0 for the contribution!
- General
- Autocomplete: Activate/Deactivate
- Diagnostic: Activate/Deactivate
- Hoverdocs: Activate/Deactivate
- Formatter: Activate/Deactivate
- File Extensions: Define allowed file extension
- Root File: Define the root project file. If not set, the extension will rely on the given context to built or execute files
- Create in-game
- Active: Activate/Deactivate
- Auto Compile: Auto compile and delete source files
- Allow Import: Enable allowImport on auto compile
- Port: Select the port of the message-hook server
- Interpreter
- Default Args: Default call arguments
- Environment Variables: JSON used to define environment variables (ENVs)
- Environment Variables File: Define .env file from which environment variables should be loaded from
- Hide Unsupported Text Mesh Pro Rich Text Tags: Hides unsupported rich tags in the pseudo-terminal
- Seed: Seed used to generate the testing environment
- Silence Error Popups: Silences error popups due to execution failure
- Port: Select the port of the message-hook server
- Environment type: Interpreter environment type
- Program name: Defines program name in runtime
- Transpiler
- Build Type: Default, Uglify, Beautify
- Beautify
- Indentation: Tab or whitespace. What should be used for indentation?
- Indentation Spaces: In case whitespace is used this will determine the amount of whitespaces
- Keep Parentheses: Will always use parentheses
- Literals Optimizations: Activate/Deactivate
- Namespaces Optimizations: Activate/Deactivate
- Environment Variables: JSON used to define environment variables (ENVs)
- Environment Variables File: Define .env file from which environment variables should be loaded from
- Excluded Namespaces: List of namespaces that should not be optimized
- In-game Directory: Destination folder used in the game
- Installer
- Active: Activate/Deactivate
- Auto Compile: Adds boilerplate code to the installer for auto-deletion of the script after execution
- Allow Import: Enable allowImport when performing auto compile in installer
- Max Chars: Define the maximum number of characters at which the installer should split the code
- Obfuscation: Enables minification of namespaces using special characters
- Watch: Watch project files for changes and run build automatically
- Output Filename: Specify the name of the main output file.
- Type Analyzer
- Strategy: Specifies which files are used for type resolution. The "Dependency" strategy resolves types from all files imported into the current file. Alternatively, the "Workspace" strategy resolves types from all files within the workspace
- Exclude: Specifies files to ignore based on matching glob patterns
- Transform
- Build
- Upload
- Interpreter
- Message Hook
- API Browser
- Comment Docs
- Snippets
- Share
- Goto Error
- Preview output
- Providers
Transpiles your code into a specific format. Be sure to select your desired output in the settings. By default, the "Default" build type is selected.
There are three different modes: "Default", "Uglify", and "Beautify". The output will vary depending on the mode selected.
-
Default: No special behavior like optimization or formatting. This format is the best all-rounder if you're unsure.
-
Uglify: Minifies your code and optimizes literals and namespaces. You can disable these features if necessary, especially if namespaces must remain unchanged for your code to function properly. You can also exclude specific namespaces from optimization.
-
Beautify: Formats your code to improve readability. There is currently no customizability available in this mode, which might limit its use case.
Important: Unlike the build function, transforms will ignore any #include, #import, or import_code lines. Use the build functionality instead.
Greybel allows you to inject environment variables during transformation. These can be configured in the extension settings.
Building transforms and bundles your scripts in a way that makes them easy to import into Grey Hack. As mentioned in the transform section, building also provides three different output modes: "Default", "Uglify", and "Beautify". For more details, check out the output-modes section.
You can automatically create transpiled files in the game by enabling the "create-ingame" option. To use it, you must have message-hook installed.
Scripting in Grey Hack can be challenging, especially when you have files that import each other or are working on a larger project where you have to copy-paste each file manually into the game every time. Greybel aims to reduce this hassle, allowing you to spend more time coding and playing rather than copy-pasting files repeatedly.
Greybel enables you to split your code into different files, which helps maintain readability and also makes your code reusable.
It is recommended to use include and import for small or medium-sized projects.
For larger projects, import_code should be used instead, as the transpiler will bundle your files in a way that maximizes the use of import_code in the game, helping to avoid exceeding the maximum character limit of 160,000.
Cyclic dependencies will also be detected. If a cyclic dependency is found, an error will be thrown, indicating which file is causing it.
A step-by-step guide is available here.
Used to import exported namespaces from a file. Features:
- Supports relative imports
- Loads code only when required
- Does not pollute global scope
- Only imports once, no matter how many times it’s referenced
- Exports only what you want
- Code is appended to the root file, which may exceed the character limit in GreyHack. If that's an issue, use import_code instead
You can check out the example code for a better understanding of how to use this feature.
Used to import the content of a file. Features:
- Supports relative includes
- Easy to use
- Pollutes global scope
- Includes the content every time, which may lead to redundant code
- May exceed the character limit of GreyHack, so use import_code instead if this is a concern
You can review the example code for more details.
Used to import code from a file. Features:
- Keeps files separate in-game, helping to avoid the character limit
- Supports nested
import_code - Supports relative imports
Here’s some example code.
When the installer option is enabled, Greybel will create one or more installer files depending on the size of your project. These installer files will contain all the code files and logic to create the files in the game. Essentially, you just need to copy and paste the installer code into the game, then compile and execute it. Using the --auto-compile flag adds logic to automatically compile the project and remove all source files.
By setting up the in-game directory in the settings, you can define where you want the files to be imported in the game. By default, /root/ is used.
Additionally, nested import_code is supported. This is achieved by moving all imports into the entry file based on their usage throughout the project. It’s recommended to only use import_code at the head of the file, as the import locations of nested files cannot be guaranteed.
Any valid MiniScript or GreyScript syntax is supported. Additionally, some minor syntax sugar is added to these languages. If you use these features, keep in mind to transpile your code first. Using these is completely optional.
myList = [
false,
null
]
myMap = {
"test": {
"level2": {
"bar": true
}
}
}
a /= b
a *= b
a -= b
a += b
a = b << c
a = b >> c
a = b >>> c
a = b | c
a = b & c
/*
My block comment
*/
print("test")
print(#filename)
The filename expression will be replaced with the string literal containing the name of the file before transpiling. This can be useful for debugging.
print(#line)
The line expression will be replaced with the number literal containing the line of the expression before transpiling. This can be useful for debugging.
print(#envar MY_TEST_VAR)
The envar expression will be replaced with the value of the provided environment variable. Make sure you define an environment variable for the provided namespace. If no value is found, it will instead use null.
print(#inject "path/to/file")
The inject expression will be replaced with the content of whatever file exists at the provided path. If the file does not exist, it will be replaced with null. Content injected will automatically be escaped.
If you're not interested in the build functionality or need to upload many files into the game, you can use the "Import files into game" command. This will behave similarly to the create-in-game build feature, but without the building step.
This feature will also use the transpiler's "Ingame directory" setting as the in-game destination.
IMPORTANT: Please keep in mind that you first need to setup the message-hook agent.
Greybel comes with its own GreyScript interpreter, allowing you to test and debug your code outside of the game. This is partly due to the test environment that gets generated on the fly, attempting to emulate the game's API.
Dependencies are dynamically loaded into the execution without any limitations. Cyclic dependencies are also supported.
Greybel supports the injection of environment variables into the interpreter. These environment variables can be configured in the extension settings.
When using this environment, Greybel will automatically generate a local setup, including simulated computers, networks, filesystems and more, on the fly. By default, generation is based on a seed value called test. You can modify this seed using the appropriate option. Using the same seed consistently will ensure that the generated entities remain stable across sessions.
The local computer configuration is hardcoded, with admin credentials set to root:test. Additionally, your local machine will have crypto.so and metaxploit.so available by default.
Note that the mock environment runs locally and is independent from the actual game. As a result, some intrinsic game behaviors may not be fully supported. If you need highly accurate debugging, consider using the In-game Environment instead.
metax = include_lib("/lib/metaxploit.so") //returns metaxploit interface
print(metax) //prints metaxploit
myShell = get_shell("root", "test") //get local root shell
This environment uses the actual in-game setup. To use it, you must have message-hook installed and the game running in singleplayer mode.
The key advantage of the in-game environment is that it mirrors real gameplay behavior exactly, unlike the mock environment, which is an approximation.
TextMesh Pro Rich Text is partially supported.
Note: For the pseudo-terminal, Greybel will attempt to transform TextMesh Pro Rich-Text tags into ANSI codes. Due to the nature of TextMesh Pro Rich-Text tags, some formatting may be lost. If you're looking for a proper preview of your output in Grey Hack, please check out the Preview Output feature.
The debugger allows you to set breakpoints, run code in a breakpoint context, and jump to the next line of execution. It's helpful for debugging your code.
Note: Make sure to set the breakpoint on a non-empty line, or it will be skipped.
A REPL is also available while executing the script or having an active breakpoint.
The Message Hook enables Greybel to communicate with the game server via the game client, extending its functionality. Features such as in-game auto-create (used for building) and the in-game interpreter environment rely on this capability. Installing it is entirely optional and not required for basic use.
To use the Message Hook, you must first install BepInEx, followed by the appropriate plugin. Instructions are provided below for both BepInEx 5.x.x and 6.x.x versions.
If you prefer videos over written instructions, there are also tutorial videos created by @redit0 and @0x0 that walk you through the setup process.
Note: BepInEx 6.x.x is in a pre-release state and may be less stable than 5.x.x. If you experience frequent crashes, consider switching back to version 5.x.x.
- Download BepInEx 5.x.x: BepInEx v5.4.23.2
- Install by extracting BepInEx files into your Grey Hack game folder (location of the game executable). See the Installation Guide if needed.
- Add the Plugin: Download GreyHackMessageHook5.dll and move it to the plugins folder in BepInEx.
- Configure Launch Options (macOS/Linux Only):
- Go to Steam Library > Grey Hack > Properties > Launch Options.
- macOS:
"/path/to/Steam/steamapps/common/Grey Hack/run_bepinex.sh" %command% - Linux:
"/path/to/.steam/steam/steamapps/common/Grey Hack/run_bepinex.sh" || %command%
- macOS:
- Go to Steam Library > Grey Hack > Properties > Launch Options.
- Launch Grey Hack via Steam to load BepInEx 5 with the plugin.
- Download BepInEx 6.x.x: BepInEx version 6.0.0-pre.2 Unity.Mono
- Install by extracting BepInEx files into your Grey Hack game folder (location of the game executable). See the Installation Guide if needed.
- Add the Plugin: Download GreyHackMessageHook.dll and move it to the plugins folder in BepInEx.
- Configure Launch Options (macOS/Linux Only):
- Go to Steam Library > Grey Hack > Properties > Launch Options.
- macOS:
"/path/to/Steam/steamapps/common/Grey Hack/run_bepinex.sh" %command% - Linux:
"/path/to/.steam/steam/steamapps/common/Grey Hack/run_bepinex.sh" || %command%
- macOS:
- Go to Steam Library > Grey Hack > Properties > Launch Options.
- Launch Grey Hack via Steam to load BepInEx 6 with the plugin.
Since version 0.9.5694, Grey Hack runs natively on Apple Silicon Macs. When used with BepInEx, this can cause crashes, specifically the following error:
EntryPointNotFoundException: SteamInternal_SteamAPI_Init assembly:<unknown assembly> type:<unknown type> member:(null)
at (wrapper managed-to-native) Steamworks.SteamAPI+Native.SteamInternal_SteamAPI_Init(string,intptr)
at Steamworks.SteamAPI.Init (System.String pszInternalCheckInterfaceVersions, System.String& pOutErrMsg) [0x0000e] in <6edbf121be6b4184ba49a762e217ee3b>:0
at Steamworks.SteamClient.Init (System.UInt32 appid, System.Boolean asyncCallbacks) [0x000f4] in <6edbf121be6b4184ba49a762e217ee3b>:0
at ClientSteam.Start () [0x0001e] in <5900bf36cb6f404fa6809df9b65e2cde>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
ClientSteam:Start()You can fix this crash by deleting the libsteam_api.dylib file located in the game's root directory. This crash is caused by multiple versions of libsteam_api.dylib being present, leading to the wrong library loading first. Deleting the duplicate libsteam_api.dylib in the game root prevents this conflict, allowing the correct version to load. This fix does not appear to affect gameplay or functionality.
This feature creates a web view that renders actual TextMesh Pro Rich-Text tags within VSCode. Its main purpose is to emulate the actual output of the game, making it useful for drawing images or creating fancy prompts.
The API Browser for GreyScript brings the GreyScript API Documentation directly into Visual Studio Code.
You can add function signatures in your comments to improve the developer experience.
- Hover tooltips will display parameter and return type information.
- The type system can use these annotations to provide context-sensitive autocomplete suggestions.
Example:
// Hello world
// I am **bold**
// @description Alternative description
// @example test("title", 123)
// @param {string} test - Some text.
// @param {string|number} abc - Some text.
// @returns {crypto} - Some info about the return value
test = function(test, abc)
print(test)
end functionYou can also define your own types and describe their properties. These types can then be used as return values or extended in other places.
// @type Bar
// @property {string} virtualMoo
// @property {string} nested.virtualMoo
Bar = {}
Bar.moo = ""
// @description Example with parameters
// @param {string} test
// @param {string|number} abc
// @returns {Bar} - Some info about the return value
Bar.test = function(test, abc)
print("test")
return self
end function
// @type Foo
Foo = new Bar
// @returns {Foo}
Foo.New = function(message)
result = new Foo
return result
end function
myVar = Foo.New
// Hover/autocomplete results:
// myVar.test → shows signature of Bar.test
// myVar.virtualMoo → recognized as string
// myVar.nested.virtualMoo → recognized as stringSometimes you want to describe types that exist only in documentation and tooling, without needing a runtime implementation. These are called virtual types.
They can include properties, functions, and even inherit from other virtual types.
// @vtype myOtherType
// @property {map<string,string>} hallo
// @vtype myCustomType
// @extends myOtherType
// @function foo
// @params {string} bar
// @returns {string}
// @description This is a custom type with a function
// @example Example usage of myCustomType
// @property {number} myProperty
// @define {myCustomType}
bar = {}
// Hover/autocomplete results:
// bar.foo → shows signature of myCustomType.fooShares your code via editor.greyscript.org. The related link will be copied to your clipboard.
Provides a list of available GreyHack snippets, such as ls, mkdir, and more.
Jumps to the next existing syntax error.
This extension includes several IntelliSense providers to enhance your coding experience with GreyScript:
-
Autocompletion Provider
Offers context-aware suggestions based on your current position in the code. -
Signature Helper Provider
Displays function signatures with parameter types and return values as you type, helping you use functions correctly and efficiently without needing to reference documentation. -
Hover Tooltips Provider
Displays helpful information about functions and types when you hover over them. -
Diagnostics Provider
Identifies and highlights syntax errors in your code for easier debugging. -
Symbol Provider
Lists all symbols available in the active file for easy navigation.
-
Definition Provider
Locates and displays definitions within the active file and its dependencies.
-
Color Picker Provider
Shows a color picker when you use color or mark tags in your code.
Sloth icons created by Freepik - Flaticon
For questions, feature requests, or support, feel free to join the dedicated Greybel Discord.