Creating a Script
The fastest way to get started is by cloning the Script Template repository, which is pre-configured with sane defaults. Check the template's README for prerequisites before continuing.
Project structure
After cloning the template, the key files you will work with are:
your-script/
├── settings.gradle.kts # Project name
├── build.gradle.kts # Dependencies and ProGuard config
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/script/
│ │ │ ├── SampleScript.kt # Main script class
│ │ │ └── SampleConfiguration.kt # Configuration interface
│ │ └── resources/
│ │ └── manifest.json # Script metadata
│ └── test/
│ └── java/
│ └── TestSampleScript.kt # Unit tests
Note
The template places Kotlin sources under src/main/java/ (not src/main/kotlin/). This is intentional — both directories are valid Kotlin source roots, and the template uses java/ for compatibility with tooling that expects the convention.
The manifest
manifest.json is bundled inside the compiled JAR and tells Cereal how to load your script:
{
"package_name": "com.example.myscript",
"name": "My Script",
"version_code": 1,
"sdk_version": "1.9.0",
"script": "com.example.script.SampleScript"
}
| Field | Description |
|---|---|
package_name |
Unique identifier for your script. Cannot be changed after first upload. |
name |
Display name shown in Cereal. |
version_code |
Integer that must increase with every release. |
sdk_version |
Cereal SDK version your script was built against. When using the template, this is injected from the version catalog at build time. |
script |
Fully-qualified class name of your main script class. Must be preserved by ProGuard. |
See the Manifest reference for all available fields, including child_scripts and instructions.
The script class
Your main script class implements Script<T>, where T is your configuration interface:
class SampleScript : Script<SampleConfiguration> {
override suspend fun onStart(
configuration: SampleConfiguration,
provider: ComponentProvider
): Boolean {
// Return false to abort before the script runs
return true
}
override suspend fun execute(
configuration: SampleConfiguration,
provider: ComponentProvider,
statusUpdate: suspend (message: String) -> Unit
): ExecutionResult {
// Your automation logic
return ExecutionResult.Loop("Running...", 5000)
}
override suspend fun onFinish(
configuration: SampleConfiguration,
provider: ComponentProvider
) {
// Optional cleanup
}
}
The configuration interface
User-configurable settings are declared as an interface extending ScriptConfiguration. Each method represents one setting:
interface SampleConfiguration : ScriptConfiguration {
@ScriptConfigurationItem(
keyName = "targetUrl",
name = "Target URL",
description = "The URL your script will monitor",
position = 0
)
fun targetUrl(): String
}
Cereal renders these fields automatically in the script's settings panel. See Script Configuration for all supported types and options.
Next steps
- Script Configuration — define and validate user settings
- Advanced Configuration — dynamic visibility and script identifiers
- Components — Logger, Notifications, Preferences, and more
- Child Scripts — run parallel scripts from your main script
- Testing Your Script — unit tests and integration testing