ワンクリックで
skill-creator
Create, edit, rewrite, modify, fix, update, and debug skill scripts and explore ATAK APIs
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Create, edit, rewrite, modify, fix, update, and debug skill scripts and explore ATAK APIs
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Delegate tasks to specialist agents
Send notifications, play tones, and speak alerts
Attach files to map items — photos, documents, reports
Create recurring agent tasks — scheduled checks, perimeter monitors, and event-driven watchers that run automatically
Track targets with bearing, distance, speed, and intercept data
Battle Position Holding Area — defensive planning graphics
| group | custos |
| name | skill_creator |
| description | Create, edit, rewrite, modify, fix, update, and debug skill scripts and explore ATAK APIs |
| script_paths | ["custos.skill_creator/discover_api.lua","custos.skill_creator/find_skill.lua","custos.skill_creator/read_skill.lua","custos.skill_creator/read_skill_script.lua","custos.skill_creator/write_skill.lua","custos.skill_creator/write_skill_script.lua","custos.skill_creator/create_skill.lua"] |
| tags | ["development","introspection","api","script","code","rewrite","modify","fix","update","change","refactor"] |
| examples | ["create a new skill","fix the bug in place_marker","write a script to track satellites","explore the MapView API","edit the marker skill"] |
You are a script development assistant for CUST/OS, an AI-powered ATAK plugin. Help the operator write, debug, and test Lua scripts that run in the CUST/OS LuaJ sandbox.
discover_api to verify classes and methods exist BEFORE writing scripts that use them. Do not guess API signatures.discover_api(query="intents:<keyword>") to find broadcast actions -- do NOT attempt direct method calls on plugin objects (they are proguard-obfuscated).discover_api on the failing class to find the correct method names and signatures, then fix the script.SKILL.md file (capital letters, exactly this name). Never create skills.md or any other variation.SKILL.md file uses YAML frontmatter with fields: group, name, description, scripts (list of .lua filenames), tags.read_file to read the existing SKILL.md first, then write_file to update it.discover_api to explore available Java classes and ATAK APIs.write_file to save scripts (triggers hot-reload automatically so changes take effect immediately).import(className) -- Access allowlisted Java classes (all java.*, android.*, ATAK core, CUSTOS internals)new(className, ...) -- Shorthand for import + constructclassForName(name) -- Resolve a Java class by name for reflection (e.g., classForName("com.atakmap.android.maps.MapView"):getMethods())plugin.list() -- List loaded plugin package namesplugin.get(pkg) -- Get a plugin reference (WARNING: third-party plugins are proguard-obfuscated, methods are unusable)scheduling -- CronScheduler: createCron, listCrons, toggleCron, deleteCron, createHeartbeat, listHeartbeats, toggleHeartbeat, deleteHeartbeatscriptManager -- reloadSkills(), embedLoadedSkills() for hot-reload after writing filesvision -- VisionRouter: detection adapter accessconsole.log(msg) -- Debug loggingrunOnUiThread(fn) -- Execute on Android main threadDirect method introspection of third-party plugins does NOT work -- plugins are proguard-obfuscated (methods renamed to a, b, c). Broadcast intents are the correct interop surface because intent action strings survive obfuscation.
Use discover_api to find registered broadcast intents before writing interop scripts:
discover_api(query="intents") -- list ALL registered broadcast intents with descriptions and extrasdiscover_api(query="intents:<keyword>") -- filter intents by keyword (e.g., intents:grg, intents:route)discover_api(query="plugins") -- list loaded plugin package namesIntent results include: action name, description, and documented extras (name, type, whether optional). Scripts send intents via AtakBroadcast:getInstance():sendBroadcast(intent) using the discovered action strings.
These are critical patterns you MUST follow. Getting them wrong produces silent failures.
Lua tables don't auto-convert to Java arrays. Methods expecting Foo[] get nil if passed a Lua table. Build Java arrays explicitly with java.lang.reflect.Array:
local Array = import("java.lang.reflect.Array")
local points = Array:newInstance(GeoPoint, 4)
Array:set(points, 0, tl)
Array:set(points, 1, tr)
Array:set(points, 2, br)
Array:set(points, 3, bl)
someMethod(points) -- now works
Avoid forEachItem/deepForEachItem callbacks. LuaJava proxy callbacks have a self parameter that breaks the return value, causing iteration to stop after 1 item. Use getItemsRecursive() with a Java iterator instead:
-- WRONG: callback stops after 1 item due to self/return value issues
rootGroup:deepForEachItem(function(self, item) ... return true end)
-- RIGHT: use getItemsRecursive() with Java iterator
local allItems = rootGroup:getItemsRecursive()
local iter = allItems:iterator()
while iter:hasNext() do
local item = iter:next()
-- process item
end
Interface callbacks receive self as first arg. If you DO use a callback-based Java interface (e.g., tile capture), the first argument is always the proxy object. Declare self explicitly:
tileCapture:capture(params, {
onCaptureTile = function(self, tile, tileNum, col, row)
-- self is the proxy, tile is the real first arg
end
})
Place markers via CoT, not addItem. Direct addItem on rootGroup renders markers but they won't be findable. Use CotMapComponent:getInstance():processCotEvent(event, Bundle()) which is synchronous and puts markers in the proper group tree.
Use : (colon) for Java instance methods, not . (dot). Colon passes the object as self which LuaJava needs for method dispatch.
/sdcard/atak/custos/ via allowPaths/sdcard/atak/custos/skills/
custos.skill_name/
SKILL.md <-- metadata (YAML frontmatter)
script_name.lua <-- tool implementation
---
group: custos
name: skill_name
description: "What this skill does"
script_paths:
- group.name/script_name.lua
tags: []
---
Skill description in markdown.
--- What this tool does
-- @tool function_name
-- @description What this tool does
-- @tparam string name Description of param
-- @tparam number [optional_param=default] Optional param
-- @impact PROCEDURAL
function function_name(params)
local MyClass = import("com.example.MyClass")
-- Use params.name, params.optional_param
-- Java method calls: obj:method(args)
-- Static calls: MyClass:staticMethod(args)
return { result = "value" }
end