Termlings apps are agent-native file-based CLI command surfaces. They extend agent capabilities, inject app-specific system context, and give agents CLI access to the matching termlings commands.
They also control which capability areas appear in agent system context, top-level CLI help, the TUI, slash commands, and agent-facing runtime access.
This is not markdown-tag parsing. The app model is structured and code-driven.
There are three layers:
- Built-in core apps in JSON-backed code manifests.
- Workspace overrides in
.termlings/workspace.json.apps. - Agent-specific app allowlists in
.termlings/agents/<slug>/SOUL.md.
The launcher resolves the final app set for the current agent before building the injected system context.
If .termlings/workspace.json has no apps key, every toggleable core app defaults to true.
Current core app keys:
messagingrequestsorg-chartbrieftaskworkflowscalendarbrowserskillsbranddesignsocialadsmemorycmscrmmediaanalyticsfinanceeval
These are built-in apps, not arbitrary markdown sections.
messaging is required. It cannot be disabled in workspace.json.
Global app availability still lives in .termlings/workspace.json:
{
"version": 1,
"projectName": "my-project",
"createdAt": 1772790000000,
"updatedAt": 1772790000000,
"settings": {
"avatarSize": "large"
},
"apps": {
"defaults": {
"crm": false,
"browser": true,
"ads": false
}
}
}Resolution order:
- Built-in defaults
apps.defaults- Agent SOUL frontmatter
apps:allowlist, if present
Example behavior:
- no
appsobject: all core apps enabled apps.defaults.crm = false: CRM disabled for everyoneapps.defaults.ads = false: Ads disabled for everyone
Per-agent app access now comes from SOUL.md.
If an agent has no apps: frontmatter field, it keeps access to all globally-enabled apps.
If apps: is present, that list becomes the agent allowlist.
Canonical example:
---
name: Growth
dna: 80bf40
apps:
- messaging
- brief
- task
- social
- ads
- analytics
- finance
---Important rules:
messagingis still forced on even if omitted- invalid app keys are ignored
- SOUL
apps:narrows access; it does not override a workspace default that disabled an app globally - no
apps:key means full access to all globally-enabled apps evalis operator-only and is always hidden from normal agent sessions
App-aware context injection works like this:
termlings spawnresolves the target agent and runtime.- The launcher reads identity from
.termlings/agents/<slug>/SOUL.md. - The launcher resolves workspace defaults, then applies the agent SOUL
apps:allowlist if present. - The launcher renders the system context from structured code sections.
- Disabled apps are omitted from the rendered prompt.
- The final prompt is injected into the runtime:
- Claude:
--append-system-prompt "<context>" - Codex: trailing injected prompt argument
- Claude:
.termlings/GOAL.mdis appended after the generated system context if present.
Current implementation points:
- core app manifests:
src/apps/core-apps.json - core app registry:
src/apps/registry.ts - app resolution:
src/engine/apps.ts - workspace app storage:
src/workspace/state.ts - system context rendering:
src/system-context.ts - runtime injection:
src/agents/launcher.ts
What Gets Hidden
When an app is disabled for an agent:
- the corresponding capability guidance is omitted from injected system context
- related command examples are omitted from quick reference sections
termlings --helpomits the disabled top-level commands when the current agent slug is available inTERMLINGS_AGENT_SLUG- direct CLI commands for that app are blocked at runtime
- TUI tabs contributed by that app are omitted
- slash commands contributed by that app are omitted
- app-specific activity feed entries can be omitted
termlings briefomits app-backed sections the current agent does not have access to
Current enforced example:
crmis hidden from context, help, and runtime access when disabledrequests,task, andcalendartabs disappear from the TUI when disabledbrowseractivity entries are hidden from the activity feed when the browser app is disabledmessagingalways stays enabled because it is a required app
This design avoids:
- parsing markdown for app sections
- custom
<tags>inside docs - prompt-only hiding without runtime enforcement
It keeps app availability:
- structured
- testable
- workspace-configurable
- agent-specific
This also leaves room for future per-app feature flags later without overloading the meaning of "app" now.