🚀 OpenTTY Applications (Native)
Lima edited this page 2025-10-14 19:06:40 -03:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

🧭 Quick overview

When OpenTTY imports a package file whose content begins with a [ Config ] header, it parses that file into key/value properties and executes these steps (in roughly this order):

  1. API checksapi.version, api.match, api.error. If a required API version or match rule fails, the package can trigger an error action.
  2. Runtime dependency checksapi.require. If the package expects features not available (for example lua, canvas, devicefs), import can fail.
  3. Includesinclude can list other packages (comma-separated). Each included entry is imported recursively.
  4. Process / service setupprocess.* keys can start background processes, bind ports, etc.
  5. Run package configurationconfig is executed as a command (so it can set up environment, create files, register aliases, etc.).
  6. UI / MIDlet modulesmod together with process.name may register a GUI screen or service.
  7. Commands & Filescommand / file entries let the package create shell aliases and write files into /home/.
  8. Shell registrationshell.name, shell.args, and optional shell.unknown build a shell-command table that the main shell will use to dispatch subcommands.

Use the sections below for each field, how to configure it, and small examples.


🗂️ Format & parsing basics

  • A package is a plain text file parsed as key/value pairs (simple key=value lines). importScript() uses parseProperties() to build a property map from the file. Keys are referred to as PKG entries in OpenTTY code.
  • Several keys accept comma-separated lists (for example include, command, file, and shell.args).
  • Values can be other package keys (the loader will later evaluate environment substitution via env() at runtime), so you can reference one field from another in your package text.

🧾 Main package fields

Below are the fields you listed plus other commonly-used keys. For each key: what it does, expected value, and a small example.

Package identity & description

  • name — friendly app name (displayed by about and UI).
  • version — app version.
  • description — short description displayed to the user.

Example

name=MyTool
version=1.0
description=A tiny helper app

(When about is run, OpenTTY prints name version and description if present.)


⚖️ API checks (ensure compatibility)

  • api.version — version string the package expects (compared to OpenTTYs $VERSION).

  • api.match — matching mode for api.version. Accepted modes (seen in the loader) include:

    • exact-prefix (default) — checks that OpenTTYs version starts with api.version.
    • minimum / maximum — numeric comparisons on version parts.
    • exact-full — exact equality.
  • api.error — command string to run if the API compatibility check fails (e.g., warn Package requires newer OpenTTY).

Behavior: If the version check fails, the loader runs the api.error command (or true if none) and returns an error status; the package import stops.

Example

api.version=0.6
api.match=minimum
api.error=warn This package requires OpenTTY 0.6+

🧩 Runtime requirements (api.require)

  • api.require — comma-separated list of runtime capabilities the package needs (examples used by OpenTTY: lua, canvas, devicefs).
  • If any required capability is missing, import fails (the package can detect missing features and abort).

Example

api.require=lua,devicefs

🔗 Include other packages (include)

  • include — comma-separated list of other package sources (strings that will be passed to getcontent() and imported). The loader imports each included file before continuing with the main package startup. This is useful for shared libraries or dependencies.

Example

include=/lib/shared.conf,/lib/graphics.pkg

⚙️ Process / service fields (process.*)

These control running a background process or binding a port for the package.

  • process.name — a logical name for the process to register in OpenTTYs process table (used for ps, backgrounding, and for mod screens). If present, the loader calls start(process.name, ...) to register a process.
  • process.exit — command to run when the process should exit (registered as the “exit” action for that process). Used by the start() call.
  • process.type — (not always required) type tag for the process (used by the package if it wants to categorize itself).
  • process.port — if provided, the loader will attempt to bind that port and spawn a bind controller for the package; useful if the package exposes a network service. If the port is already in use, import warns and fails with a specific error.
  • process.db — optional extra argument passed when binding a port (used by the package to include a DB or mode string when handling incoming commands).

Example

process.name=my-service
process.exit=stop my-service
process.port=1337
process.db=sqlite

Behavior note: if process.port is present, OpenTTY checks session availability and then starts a bind thread that listens on the port and forwards incoming text to the package.


🧰 config — run commands at import time

  • config — a command (or chain of commands) executed immediately when the package is imported. This is where packages perform setup tasks, register aliases, write runtime state, or create files. The loader will execute this and if it returns a non-zero status the import fails.

Example

config=echo Installing...; touch /home/app-file.txt

🖥️ mod — Looping commands

  • mod — Run the value of this field while the generated process of the Application is alive. Requires process.name field.

Example

mod=echo "Until process be killed or an error have been occurred."

🧭 command — register shell commands / aliases

  • command — comma-separated list of names to expose as shell commands (each name must also be a key in the package whose value is the command string that will run). The loader creates shell aliases from those command names and their corresponding package values. If a referenced command key is missing, an error log is recorded.

Example

command=hello,goodbye
hello=echo "Hello, world!"
goodbye=echo "Goodbye!"

Behavior: after import, typing hello in the OpenTTY shell will run the configured command.


file — create files in /home/ 🗃️

  • file — comma-separated filenames. For every name listed OpenTTY will look for a package key with that name and write the corresponding value into /home/<filename> in the record store. If the content key is missing, a log warning is generated.

Example

file=README,example.conf
README=Welcome to MyTool!
example.conf=option1=1

After import the user can cat /home/README (or get README) to view the file.


🐚 shell.* — build a shell subcommand table

Packages can register a custom shell entry (a table of subcommands) that the interactive shell uses.

  • shell.name — the name under which this shell table will be registered (for example git or mytool).
  • shell.args — comma-separated list of property names that map to arguments/subcommands. For each NAME in shell.args, the loader fetches the package property NAME and stores the value in a table. If shell.unknown exists its saved too and used as fallback. The table is added to the global shell map — the interactive shell will detect it and route mytool subcmd to the tables stored command.

Example

shell.name=mytool
shell.args=start,stop,status
start=/home/mytool/start.sh
stop=/home/mytool/stop.sh
status=/home/mytool/status.sh
shell.unknown=echo Unknown subcommand

Behavior: typing mytool start will run the command stored in the table for start; if the subcommand is not found and shell.unknown exists that fallback command is executed.


✂️ Full minimal Application template (copy/paste)

Use this as a starting point — put it at the top of your package text:

[ Config ]
name=MyApp
version=0.1
description=A short description

api.version=1.16
api.require=lua
api.match=minimum
api.error=warn This package requires OpenTTY 1.16+ and Lua Runtime

include=/lib/common.pkg

process.name=myapp
process.exit=true
process.port=1337
process.db=execute

config=echo Installing...; true

command=start,stop
start=echo "Starting..."
stop=echo "Stopping..."

file=README
README=This is MyApp.

shell.name=myapp
shell.args=start,stop,status
shell.unknown=echo Unknown subcommand

Notes

  • config supports any shell-style commands recognized by OpenTTY (the loader executes it via the shell engine).
  • include entries are imported before the rest of the package is finalized; use them for shared dependencies.

📝 Practical tips

  • Test API requirements first — if your package needs optional features (Lua, canvas, or file access) declare them in api.require so import fails with a clear message instead of silently misbehaving.
  • Use config to create runtime files (via the shell), or use file= to provisioning persistent /home/ files from properties. The loader writes the file entries into /home/ automatically.
  • Avoid port conflicts — if you set process.port, the loader checks sessions and will fail the import when the port is unavailable (it logs a warn and returns a port-in-use error).
  • Shell subcommandsshell.name + shell.args is the recommended way to expose grouped commands (like git push) to the user shell. Provide shell.unknown to give a friendly fallback.

🔍 What OpenTTY logs / does on failure

  • If api.version check fails: the loader runs api.error (if provided) and aborts import with an error return.
  • If a include import fails: the entire import stops and returns the includes status.
  • If process.port is already in use the loader warns and aborts the package start.