Appearance
ts app
Show and change one app as it is placed in a workspace — its title, how users sign in to it, and the licensing and access rules that apply to it there.
Usage
text
ts apps <workspace>
ts app <id>
ts app <id> <property>
ts app new --file=<path>
ts app set <id> <property> <value>
ts app set <id> --file=<path>
ts app delete <id> [--force]Description
ts apps needs a workspace; there is no default. Give it the workspace ID (the short name in URLs, such as acme) or its GUID, the same way ts workspace accepts one. The listing shows the title, the repository the app comes from, its version, its engine, and the app's ID — the ID is what every ts app action takes.
An app placement carries far more configuration than a flag list can express: login mode, license type and count, IP access rules, server tag rules, launch modes, supported platforms, sort order, and the app's own configuration document. So ts app treats it as a JSON document. ts app <id> prints the document the server holds, verbatim, and ts app set <id> --file= sends one back. The two shapes match, which is what makes the read-edit-write loop safe: nothing is dropped because this version of ts did not know a field existed.
set is a merge, not a replace, and the server accepts a subset of the document: appTitle, loginMode, licenseType, licenseValue, ipAccessRules, and serverTagRules. The rest of the printed document — the config block, launchModes, supportedPlatforms, sortIndex, and the icon — is read-only through this command; change those in the Administration site. Leaving ipAccessRules or serverTagRules out of the document you send clears them, so edit the printed document rather than composing a fresh one.
For a single field there is a shorter path. ts app <id> <property> reads one field, and ts app set <id> <property> <value> writes one. The two write forms are complementary rather than alternatives: the accessor changes one field and leaves the rest of the document as it was, while --file replaces the whole document. Reach for the accessor for a one-field change — retitling an app, moving it to a different login mode — and for --file when you are editing structure or several fields at once. Because the accessor sends the whole document back, it cannot trip the clearing behavior above: ipAccessRules and serverTagRules travel along untouched.
Property names are kebab-case and map to the document's camelCase key, so app-title addresses appTitle. Values are typed from the field being replaced — licenseValue stays a number, a boolean stays boolean — so you never have to know a field's wire type. A field that is currently null is the exception: there is nothing to infer a type from, so the value goes in as a string.
A structured field has no accessor form. ipAccessRules and serverTagRules are arrays and config is an object, so all three are refused with a pointer at --file. An unknown property is refused too. Both refusals happen before anything is written, so a typo cannot half-apply. What the accessor cannot check is the server's editable subset: naming a read-only field such as sortIndex gets past the CLI, and the server then ignores that part of the document, so the command reports success and nothing changes.
The accessor is a read-modify-write: it fetches the document, changes the one field, and sends the whole document back. That is safe here because the document round-trips untyped, so a field this version of ts does not know about is preserved rather than dropped.
new does not consume a printed app. It attaches an existing app definition to a workspace and reads exactly two fields: workspaceId, which is the workspace's GUID, and appConfigId, the numeric id of the app definition. A printed app's workspaceId is the server's internal numeric id — its GUID prints as workspaceGuid — so feeding a printed document straight into new is rejected. Write the two-field document by hand.
delete is a soft delete: the app stops appearing in the workspace but the row is retained, and ts has no undo for it. It prompts first unless you pass --force, and where there is no terminal --force is required rather than assumed. Adding and removing an app are both recorded in the audit trail, so ts audit will show who did it.
Options
| Flag | Description | Default/Values | Notes |
|---|---|---|---|
--file | JSON document to send. | Path, or - to read stdin | Required by new. set needs it only for the whole-document form. |
--force, -f | Delete without confirming. | Required when there is no terminal. |
Examples
bash
# What is published in this workspace?
ts apps acme
# The whole document for one app
ts app 3f6a1c92-77b1-4a05-9a24-9b0c5f2e18d4
# Just one field
ts app 3f6a1c92-77b1-4a05-9a24-9b0c5f2e18d4 app-title
# Retitle it — one field, no file
ts app set 3f6a1c92-77b1-4a05-9a24-9b0c5f2e18d4 app-title "Acme CAD (2026)"
# The IP rules are an array, so those go through the document round trip
ts app 3f6a1c92-77b1-4a05-9a24-9b0c5f2e18d4 > app.json
$EDITOR app.json
ts app set 3f6a1c92-77b1-4a05-9a24-9b0c5f2e18d4 --file=app.json
# Attach an app definition to a workspace — hand-written, not a printed document
echo '{"workspaceId":"9b336df2-2599-490b-99bc-e17f2bf50f66","appConfigId":42}' \
| ts app new --file=-
# Full titles and IDs, nothing truncated
ts apps acme --csv
# Remove it from the workspace, unattended
ts app delete 3f6a1c92-77b1-4a05-9a24-9b0c5f2e18d4 --forceA path that does not exist is not reported as a missing file — --file=ap.json where you meant app.json prints the command's usage line instead. If set answers with usage text you were sure you satisfied, check the path first.
Output
print emits the server's JSON document unchanged, so it pipes into jq and back into set. Under --format=json the document is nested as entity inside the standard result envelope, so a script that already parses the envelope reads result.entity — which is not the shape set --file consumes, so keep the default text output for round trips.
A single-field read prints the bare value — Acme CAD, not "Acme CAD" — so it drops straight into a shell variable. Under --format=json that value comes back in the envelope under the document's own key, result.appTitle.
Exit Codes
0 on success. -2 when ts apps is run without a workspace. -6 when the workspace or the app ID does not exist, and when a single-field read names a property the document does not carry. -5 when the account is not a Server Administrator. -1 when the document is missing or unreadable, when the server rejects its contents, when you decline the delete prompt, and for the accessor's write-side refusals — an unknown property, or one holding an object or array.
Related Commands
- ts workspace — The workspace an app is placed in, and who can see it.
- ts channel — The channels that group apps within a workspace.
- ts link — Link shortcuts, which sit alongside apps in a workspace.
- ts repo — The repositories on the hub that apps are published from.
