Files
apple-container-nova/extension.json
T
thatguygriffandClaude Opus 5 0506f44db3 Build the Apple Container extension
Turns the empty scaffold into a working Nova extension for Apple Container
and container-compose, in the shape of the Docker Suite extension.

Sidebar (Scripts/Sidebar):
- System, Containers, Images, Volumes and Networks sections
- Containers grouped into compose projects via the com.docker.compose.project
  label container-compose stamps; project rows drive compose up/down/build
  against the matching workspace file
- Lifecycle, shell, logs, inspect, browse and copy commands per resource
- Apple Container publishes no event stream, so the sidebar polls while
  visible and only reloads a section when a fingerprint of its data changes,
  which keeps selection and expansion intact

Hostnames (Scripts/Hostnames.js):
- A container's hostname is <name>.<domain> and the domain lives in Apple
  Container's config.toml, which has no CLI setter, so the Hostname Domain
  preference reads and writes that file directly
- Changing it offers to register the domain with macOS and restart the
  services; the write preserves the file's other tables and its mode

Language support:
- Dockerfile and Compose syntaxes backed by tree-sitter grammars built by
  Tools/build-syntaxes.sh, pinned to revisions that generate ABI 14
- The Compose syntax is named dockercompose because that is the languageId
  docker-language-server recognises compose files by
- docker-language-server is downloaded on first use rather than bundled, at
  roughly 40 MB

Icons are generated by Tools/make-icons.py so they can be regenerated rather
than hand-maintained.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UnSBcR5Lywz5Fbj5FmVbfc
2026-08-18 22:45:14 -03:00

777 lines
32 KiB
JSON

{
"identifier": "unsupervised.AppleContainer",
"name": "Apple Container",
"organization": "Unsupervised",
"description": "Sidebar, commands and language support for Apple Container and container-compose.",
"version": "1.0",
"license": "MIT",
"repository": "https://git.unsupervised.ca/",
"main": "main.js",
"keywords": [
"apple container",
"container",
"containers",
"compose",
"container-compose",
"dockerfile",
"containerfile",
"image",
"images",
"volume",
"network",
"sidebar"
],
"categories": [
"commands",
"completions",
"issues",
"languages",
"sidebars"
],
"entitlements": {
"clipboard": true,
"filesystem": "readwrite",
"process": true
},
"activationEvents": [
"onLanguage:dockerfile",
"onLanguage:dockercompose",
"onLanguage:yaml",
"onWorkspaceContains:*compose*.y*ml",
"onWorkspaceContains:Dockerfile",
"onWorkspaceContains:Containerfile"
],
"commands": {
"extensions": [
{
"title": "Reload Sidebar",
"command": "apple_container.reload"
},
{
"separator": true
},
{
"title": "Start Container Services",
"command": "apple_container.system.start"
},
{
"title": "Stop Container Services",
"command": "apple_container.system.stop"
},
{
"title": "Show System Status",
"command": "apple_container.system.status"
},
{
"title": "Show System Logs",
"command": "apple_container.system.logs"
},
{
"separator": true
},
{
"title": "Register DNS Domain with macOS\u2026",
"command": "apple_container.dns.register"
},
{
"title": "Open System Configuration",
"command": "apple_container.dns.openConfig"
},
{
"separator": true
},
{
"title": "Compose Up",
"command": "apple_container.compose.up"
},
{
"title": "Compose Down",
"command": "apple_container.compose.down"
},
{
"title": "Compose Build",
"command": "apple_container.compose.build"
},
{
"separator": true
},
{
"title": "Build Image from Editor\u2026",
"command": "apple_container.image.buildEditor"
},
{
"title": "Pull Image\u2026",
"command": "apple_container.image.pullPrompt"
},
{
"title": "Run Image\u2026",
"command": "apple_container.image.runPrompt"
},
{
"separator": true
},
{
"title": "Restart Language Server",
"command": "apple_container.lsp.restart"
},
{
"title": "Extension Preferences",
"command": "apple_container.preferences"
}
]
},
"sidebars": [
{
"id": "apple_container",
"name": "Apple Container",
"smallImage": "sidebar-small.png",
"smallSelectedImage": "sidebar-small.png",
"largeImage": "sidebar-large.png",
"largeSelectedImage": "sidebar-large.png",
"sections": [
{
"id": "apple_container.system",
"name": "System",
"allowMultiple": false,
"placeholderText": "Apple Container was not found.\nInstall it from github.com/apple/container.",
"headerCommands": [
{
"title": "Refresh",
"image": "__builtin.refresh",
"tooltip": "Refresh Apple Container",
"command": "apple_container.reload"
},
{
"title": "Settings",
"image": "__builtin.action",
"tooltip": "Extension Preferences",
"command": "apple_container.preferences"
}
],
"contextCommands": [
{
"title": "Hostname Settings\u2026",
"command": "apple_container.preferences",
"when": "viewItem == 'system.dns.default'"
},
{
"title": "Register with macOS\u2026",
"command": "apple_container.dns.register",
"when": "viewItem == 'system.dns.default'"
},
{
"title": "Open System Configuration",
"command": "apple_container.dns.openConfig",
"when": "viewItem == 'system.dns.default'"
},
{
"title": "Unregister from macOS\u2026",
"command": "apple_container.dns.unregister",
"when": "viewItem == 'system.dns'"
},
{
"separator": true
},
{
"title": "Start Services",
"command": "apple_container.system.start",
"when": "viewItem == 'system.services.stopped'"
},
{
"title": "Stop Services",
"command": "apple_container.system.stop",
"when": "viewItem == 'system.services.running'"
},
{
"title": "Restart Services",
"command": "apple_container.system.restart",
"when": "viewItem == 'system.services.running'"
},
{
"separator": true
},
{
"title": "Start Builder",
"command": "apple_container.builder.start",
"when": "viewItem == 'system.builder.stopped'"
},
{
"title": "Stop Builder",
"command": "apple_container.builder.stop",
"when": "viewItem == 'system.builder.running'"
},
{
"title": "Delete Builder",
"command": "apple_container.builder.delete",
"when": "viewItem == 'system.builder.running' || viewItem == 'system.builder.stopped'"
},
{
"separator": true
},
{
"title": "Show Logs",
"command": "apple_container.system.logs",
"when": "viewItem == 'system.services.running' || viewItem == 'system.services.stopped'"
},
{
"title": "Show Disk Usage",
"command": "apple_container.system.df",
"when": "viewItem == 'system.disk'"
},
{
"separator": true
},
{
"title": "Copy",
"command": "apple_container.system.copy"
}
],
"placeholderImage": "sidebar-large.png"
},
{
"id": "apple_container.containers",
"name": "Containers",
"allowMultiple": true,
"placeholderText": "No containers.",
"headerCommands": [
{
"title": "Refresh",
"image": "__builtin.refresh",
"tooltip": "Refresh containers",
"command": "apple_container.containers.reload"
},
{
"title": "Prune",
"image": "__builtin.remove",
"tooltip": "Remove all stopped containers",
"command": "apple_container.containers.prune"
}
],
"contextCommands": [
{
"title": "Compose Up",
"command": "apple_container.compose.upProject",
"when": "viewItem == 'project.compose'"
},
{
"title": "Compose Down",
"command": "apple_container.compose.downProject",
"when": "viewItem == 'project.compose'"
},
{
"title": "Compose Build",
"command": "apple_container.compose.buildProject",
"when": "viewItem == 'project.compose'"
},
{
"title": "Open Compose File",
"command": "apple_container.compose.openFile",
"when": "viewItem == 'project.compose'"
},
{
"separator": true
},
{
"title": "Start All",
"command": "apple_container.containers.startGroup",
"when": "viewItem == 'project.compose' || viewItem == 'project'"
},
{
"title": "Stop All",
"command": "apple_container.containers.stopGroup",
"when": "viewItem == 'project.compose' || viewItem == 'project'"
},
{
"separator": true
},
{
"title": "Start",
"command": "apple_container.containers.start",
"when": "viewItem == 'container.stopped'"
},
{
"title": "Stop",
"command": "apple_container.containers.stop",
"when": "viewItem == 'container.running'"
},
{
"title": "Restart",
"command": "apple_container.containers.restart",
"when": "viewItem == 'container.running'"
},
{
"title": "Kill",
"command": "apple_container.containers.kill",
"when": "viewItem == 'container.running'"
},
{
"separator": true
},
{
"title": "Open Shell",
"command": "apple_container.containers.shell",
"when": "viewItem == 'container.running'"
},
{
"title": "Follow Logs",
"command": "apple_container.containers.follow",
"when": "viewItem == 'container.running'"
},
{
"title": "Show Logs",
"command": "apple_container.containers.logs",
"when": "viewItem == 'container.running' || viewItem == 'container.stopped'"
},
{
"title": "Show Boot Logs",
"command": "apple_container.containers.bootLogs",
"when": "viewItem == 'container.running' || viewItem == 'container.stopped'"
},
{
"separator": true
},
{
"title": "Open in Browser",
"command": "apple_container.containers.browse",
"when": "viewItem == 'container.running'"
},
{
"title": "Inspect",
"command": "apple_container.containers.inspect",
"when": "viewItem == 'container.running' || viewItem == 'container.stopped'"
},
{
"title": "Copy",
"command": "apple_container.containers.copy",
"when": "viewItem == 'container.running' || viewItem == 'container.stopped'"
},
{
"separator": true
},
{
"title": "Delete",
"command": "apple_container.containers.delete",
"when": "viewItem == 'container.running' || viewItem == 'container.stopped'"
}
],
"placeholderImage": "sidebar-large.png"
},
{
"id": "apple_container.images",
"name": "Images",
"allowMultiple": true,
"placeholderText": "No images.",
"headerCommands": [
{
"title": "Pull",
"image": "__builtin.add",
"tooltip": "Pull an image",
"command": "apple_container.image.pullPrompt"
},
{
"title": "Refresh",
"image": "__builtin.refresh",
"tooltip": "Refresh images",
"command": "apple_container.images.reload"
},
{
"title": "Prune",
"image": "__builtin.remove",
"tooltip": "Remove unreferenced images",
"command": "apple_container.images.prune"
}
],
"contextCommands": [
{
"title": "Run\u2026",
"command": "apple_container.images.run",
"when": "viewItem == 'image.tag'"
},
{
"title": "Pull",
"command": "apple_container.images.pull",
"when": "viewItem == 'image.tag'"
},
{
"title": "Push",
"command": "apple_container.images.push",
"when": "viewItem == 'image.tag'"
},
{
"title": "Tag\u2026",
"command": "apple_container.images.tag",
"when": "viewItem == 'image.tag'"
},
{
"separator": true
},
{
"title": "Inspect",
"command": "apple_container.images.inspect",
"when": "viewItem == 'image.tag'"
},
{
"title": "Copy",
"command": "apple_container.images.copy",
"when": "viewItem == 'image.tag' || viewItem == 'image.repo'"
},
{
"separator": true
},
{
"title": "Delete",
"command": "apple_container.images.delete",
"when": "viewItem == 'image.tag' || viewItem == 'image.repo'"
}
],
"placeholderImage": "sidebar-large.png"
},
{
"id": "apple_container.volumes",
"name": "Volumes",
"allowMultiple": true,
"placeholderText": "No volumes.",
"headerCommands": [
{
"title": "Create",
"image": "__builtin.add",
"tooltip": "Create a volume",
"command": "apple_container.volumes.create"
},
{
"title": "Refresh",
"image": "__builtin.refresh",
"tooltip": "Refresh volumes",
"command": "apple_container.volumes.reload"
},
{
"title": "Prune",
"image": "__builtin.remove",
"tooltip": "Remove unreferenced volumes",
"command": "apple_container.volumes.prune"
}
],
"contextCommands": [
{
"title": "Inspect",
"command": "apple_container.volumes.inspect",
"when": "viewItem == 'volume'"
},
{
"title": "Reveal in Finder",
"command": "apple_container.volumes.reveal",
"when": "viewItem == 'volume'"
},
{
"title": "Copy",
"command": "apple_container.volumes.copy",
"when": "viewItem == 'volume'"
},
{
"separator": true
},
{
"title": "Delete",
"command": "apple_container.volumes.delete",
"when": "viewItem == 'volume'"
}
],
"placeholderImage": "sidebar-large.png"
},
{
"id": "apple_container.networks",
"name": "Networks",
"allowMultiple": true,
"placeholderText": "No networks.",
"headerCommands": [
{
"title": "Create",
"image": "__builtin.add",
"tooltip": "Create a network",
"command": "apple_container.networks.create"
},
{
"title": "Refresh",
"image": "__builtin.refresh",
"tooltip": "Refresh networks",
"command": "apple_container.networks.reload"
},
{
"title": "Prune",
"image": "__builtin.remove",
"tooltip": "Remove unused networks",
"command": "apple_container.networks.prune"
}
],
"contextCommands": [
{
"title": "Inspect",
"command": "apple_container.networks.inspect",
"when": "viewItem == 'network'"
},
{
"title": "Copy",
"command": "apple_container.networks.copy",
"when": "viewItem == 'network'"
},
{
"separator": true
},
{
"title": "Delete",
"command": "apple_container.networks.delete",
"when": "viewItem == 'network'"
}
],
"placeholderImage": "sidebar-large.png"
}
]
}
],
"config": [
{
"key": "apple_container.cli",
"title": "Command Line Tools",
"type": "section",
"children": [
{
"key": "apple_container.cli.container",
"title": "container",
"description": "Path to the Apple Container CLI. Leave empty to resolve `container` from your PATH.",
"type": "path",
"placeholder": "/usr/local/bin/container"
},
{
"key": "apple_container.cli.compose",
"title": "container-compose",
"description": "Path to container-compose. Leave empty to resolve `container-compose` from your PATH.",
"type": "path",
"placeholder": "/opt/homebrew/bin/container-compose"
},
{
"key": "apple_container.cli.shell",
"title": "Container Shell",
"description": "Shell used by the \u201cOpen Shell\u201d command.",
"type": "string",
"default": "/bin/sh"
},
{
"key": "apple_container.cli.terminal",
"title": "Terminal",
"description": "Application used for interactive commands such as logs and shells.",
"type": "enum",
"values": [
"Terminal",
"iTerm2"
],
"default": "Terminal"
}
]
},
{
"key": "apple_container.sidebar",
"title": "Sidebar",
"type": "section",
"children": [
{
"key": "apple_container.sidebar.disabled",
"title": "Disable Sidebar",
"description": "Stop the sidebar from querying Apple Container entirely.",
"type": "boolean",
"default": false
},
{
"key": "apple_container.sidebar.refresh",
"title": "Refresh Interval",
"description": "Seconds between refreshes while the sidebar is visible. Apple Container has no event stream, so the sidebar polls. Set to 0 to refresh only on demand.",
"type": "number",
"default": 5,
"min": 0,
"max": 300
},
{
"key": "apple_container.sidebar.autostart",
"title": "Start Services Automatically",
"description": "Run `container system start` when the sidebar loads and the services are not running.",
"type": "boolean",
"default": false
}
]
},
{
"key": "apple_container.containers",
"title": "Containers",
"type": "section",
"children": [
{
"key": "apple_container.containers.group",
"title": "Group by Compose Project",
"description": "Group containers using the `com.docker.compose.project` label stamped by container-compose.",
"type": "boolean",
"default": true
},
{
"key": "apple_container.containers.label",
"title": "Label",
"type": "enum",
"values": [
"Name",
"Image",
"Service"
],
"default": "Name"
},
{
"key": "apple_container.containers.desc.image",
"title": "Describe with Image",
"type": "boolean",
"default": true
},
{
"key": "apple_container.containers.desc.ports",
"title": "Describe with Published Ports",
"type": "boolean",
"default": true
},
{
"key": "apple_container.containers.desc.address",
"title": "Describe with IP Address",
"type": "boolean",
"default": false
},
{
"key": "apple_container.containers.desc.state",
"title": "Describe with State",
"type": "boolean",
"default": false
},
{
"key": "apple_container.containers.icons",
"title": "Status Icons",
"type": "enum",
"values": [
"Traffic Lights",
"Toggles",
"Power"
],
"default": "Traffic Lights"
}
]
},
{
"key": "apple_container.dns",
"title": "Hostnames",
"type": "section",
"children": [
{
"key": "apple_container.dns.domain",
"title": "Hostname Domain",
"description": "Domain appended to container hostnames, so a container named mysql is reachable as mysql.<domain>. This is Apple Container's own `dns.domain` setting: changing it here rewrites config.toml, offers to register the domain with macOS, and offers to restart the services. Leave empty for unqualified hostnames.",
"type": "string",
"placeholder": "test"
}
]
},
{
"key": "apple_container.images",
"title": "Images",
"type": "section",
"children": [
{
"key": "apple_container.images.group",
"title": "Group by Repository",
"type": "boolean",
"default": true
},
{
"key": "apple_container.images.registry",
"title": "Show Registry Host",
"description": "Show `docker.io/library/nginx` rather than `nginx`.",
"type": "boolean",
"default": false
},
{
"key": "apple_container.images.infra",
"title": "Show Infrastructure Images",
"description": "Include Apple Container's own images, such as the builder and init images.",
"type": "boolean",
"default": false
}
]
},
{
"key": "apple_container.compose",
"title": "Compose",
"type": "section",
"children": [
{
"key": "apple_container.compose.detach",
"title": "Detach on Up",
"description": "Pass `--detach` to `container-compose up`.",
"type": "boolean",
"default": true
},
{
"key": "apple_container.compose.terminal",
"title": "Run Compose in Terminal",
"description": "Run compose commands in your terminal app so you can watch the output, rather than in the background.",
"type": "boolean",
"default": true
}
]
},
{
"key": "apple_container.lsp",
"title": "Language Server",
"type": "section",
"children": [
{
"key": "apple_container.lsp.mode",
"title": "Language Server",
"description": "Docker Language Server provides completion, hover, validation and linting for Dockerfiles and Compose files.",
"type": "enum",
"values": [
"Managed Binary",
"Custom Path",
"Disabled"
],
"default": "Managed Binary"
},
{
"key": "apple_container.lsp.path",
"title": "Custom Path",
"description": "Path to a docker-language-server binary. Used when Language Server is set to Custom Path.",
"type": "path",
"placeholder": "/opt/homebrew/bin/docker-language-server"
},
{
"key": "apple_container.lsp.version",
"title": "Managed Version",
"description": "Release of docker/docker-language-server to download and run.",
"type": "string",
"default": "v0.20.1"
}
]
}
],
"configWorkspace": [
{
"key": "apple_container.compose.file",
"title": "Compose File",
"description": "Compose file used by the Compose commands. Defaults to the first compose file found in the workspace.",
"type": "path",
"filetype": [
"yml",
"yaml"
]
},
{
"key": "apple_container.compose.profiles",
"title": "Compose Profiles",
"description": "Space separated profiles passed to container-compose as `--profile`.",
"type": "string",
"placeholder": "debug tools"
}
]
}