Updated documentation, will have to change again later.

This commit is contained in:
Storm Dragon committed 2026-10-13 16:44:59 -04:00
1 parent 785569abdd
commit ba5876f57c
2 files changed
+352 -6

No files matched your search

+351 -5
View File
@@ -7,11 +7,21 @@ Repository material and Hello World are licensed under GPL-3.0-or-later; see
`repository.toml` identifies this source. `catalog.toml` explicitly lists its
Tentacles, each in a direct top-level folder with its own `tentacle.toml`.
The catalog lists verified native packages for Linux amd64 and arm64. Prepared
release artifacts live in `dist/`; they become downloadable only after publication.
The catalog lists native packages for Linux amd64 and arm64. Hello World 0.1.0 is
available from the [release page](https://git.stormux.org/storm/cthulhu-tentacles/releases/tag/hello-world-v0.1.0).
Local build artifacts live in the ignored `dist/` directory.
The discovery source URL is
`https://git.stormux.org/storm/cthulhu-tentacles`.
Tentacles are independent of the Git hosting service. Discovery reads TOML files
from an HTTPS Git repository; installation downloads the HTTPS URLs explicitly
listed in its catalog. Packages can live in pretty much any git provider,
on an HTTPS web server, or in object storage with stable public HTTPS
links. The reader does not call a hosting service's release API. Keeping packages
in separate downloads avoids putting binaries into Git history.
To write your own, follow the [creation and release tutorial](#create-and-release-your-own-tentacle).
## Build and check
Keep the matching experimental `cthulhu-go` checkout beside this directory.
@@ -86,6 +96,342 @@ changed content; bump the version before preparing a later release.
The package command creates local artifacts only. It does not create commits,
releases, tags, uploads or pushes. Prepared catalog changes are not evidence that
the corresponding release is already available. Live shortcut, speech, Braille,
lock/handoff and interruption checks remain necessary after publication and an
explicit reader restart. For source-only local testing, the development launch
procedure remains in [Hello World](hello-world/README.md#local-launch).
lock/handoff and interruption checks remain necessary after installation. An
explicit restart is needed when changing the reader itself. For source-only local
testing, the development launch procedure remains in
[Hello World](hello-world/README.md#local-launch).
## Create and release your own Tentacle
This tutorial creates a native Go Tentacle named **Greeting**, then makes it
installable from a repository. The SDK and package format are experimental;
use a matching Cthulhu-Go checkout. Currently the installer supports native Linux
executables, protocol 1.0, command registration and optional presentation access.
Python SDK development is separate from this native package workflow. Broader
APIs and automatic package updates are still pending.
### 1. Set up the source repository
You need Go 1.24 or newer, Git, Python 3.11 or newer for this repository's checks,
GNU tar and gzip. Keep your new repository beside `cthulhu-go`. From their parent
directory:
```sh
mkdir -p greeting-tentacles/greeting/src
cd greeting-tentacles
git init -b main
```
Create these files:
```text
greeting-tentacles/
repository.toml
catalog.toml
go.mod
.gitignore
greeting/
tentacle.toml
README.md
LICENSE
src/main.go
```
Use this `go.mod`:
```go
module example.org/greeting-tentacles
go 1.24.0
require git.stormux.org/storm/cthulhu-go v0.0.0
replace git.stormux.org/storm/cthulhu-go => ../cthulhu-go
```
The SDK import path names its source project; it does not constrain where you
host your own repository or downloads. Record the tested reader/SDK revision in
release notes, since this local replacement does not pin it. Add `/dist/` and
`/greeting/bin/` to `.gitignore`.
Give `greeting/README.md` a description, shortcut, requirements and test procedure.
Put the full license text in `greeting/LICENSE`; choose terms you have permission
to distribute. For an example derived from Hello World, preserve its notices and
GPL-3.0-or-later license. Include source corresponding to your executable.
Create `repository.toml`:
```toml
format-version = 1
id = "example.greeting-tentacles"
name = "Greeting Tentacles"
description = "A small example Tentacle repository."
```
Create the initial `catalog.toml`:
```toml
format-version = 1
[[tentacles]]
id = "greeting"
manifest = "greeting/tentacle.toml"
```
Manifests belong in direct top-level folders. Repository and Tentacle IDs start
with a lowercase letter and contain only lowercase letters, digits, dots and
hyphens, up to 128 characters. Keep IDs stable: the reader uses the source URL,
repository ID and Tentacle ID to identify an installation. A catalog can list
several Tentacles, each with its own manifest and releases. Entries without
releases can be discovered, but cannot yet be installed.
### 2. Describe the package and permissions
Create `greeting/tentacle.toml`, replacing the example source URL with your own
HTTPS Git URL before publication:
```toml
format-version = 1
id = "greeting"
name = "Greeting"
description = "Speak and braille a short greeting."
version = "0.1.0"
authors = ["Contributor"]
license = "GPL-3.0-or-later"
source = "https://example.org/projects/greeting-tentacles.git"
help = "README.md"
runtime = "native"
platforms = ["linux"]
entry-point = ["bin/greeting"]
apis = ["commands", "presentation"]
capabilities = ["presentation"]
[protocol]
major = 1
minor = 0
```
Paths refer to the archive's root, not the source repository's root. The entry
point is an executable followed by optional literal arguments, not a shell
command. Presentation access allows speech and Braille results through the
reader. A command-only package uses `apis = ["commands"]` and
`capabilities = []`, without requesting presentation in command registration.
Other package API or capability combinations are currently unsupported.
### 3. Implement a command
Create `greeting/src/main.go`:
```go
package main
import (
"context"
"encoding/json"
"os"
"git.stormux.org/storm/cthulhu-go/sdk/go/tentacle"
)
func say_greeting(ctx context.Context, _ json.RawMessage) (any, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
return tentacle.Presentation{
Speech: "Hello from Greeting!",
Braille: "Hello from Greeting!",
}, nil
}
func main() {
command := tentacle.Command{
ID: "greet", Title: "Greeting",
Description: "Speak and braille a greeting", Presentation: true,
Bindings: []tentacle.Binding{
{Layout: "desktop", Scope: "global", Key: "Cthulhu+Ctrl+Alt+F10"},
{Layout: "laptop", Scope: "global", Key: "Cthulhu+Ctrl+Alt+F10"},
},
Handle: say_greeting,
}
if tentacle.Serve(os.Stdin, os.Stdout, []tentacle.Command{command}) != nil {
os.Exit(1)
}
}
```
The SDK handles the JSON-RPC session and registration. Stdout belongs exclusively
to that protocol; send limited diagnostics to stderr. Respect the supplied
context when doing work, including network requests. The reader owns input,
speech, Braille, user settings and lifecycle safeguards. Use its public SDK
instead of reader internals or output backends. Core and user bindings take
precedence over suggested shortcuts; users can remap Tentacle commands.
Greeting uses ordinary interruptible presentation. Hello World demonstrates
`Uninterruptible: true`; use that deliberately, rather than for every message.
See its [output behavior](hello-world/README.md) for cancellation, the 30-second
protection bound and speech backend limitations.
### 4. Build and test before packaging
From `greeting-tentacles`:
```sh
gofmt -w greeting/src/main.go
mkdir -p greeting/bin
CGO_ENABLED=0 GOCACHE=/tmp/cthulhu-go-cache go build -buildvcs=false -mod=readonly -trimpath -o greeting/bin/greeting ./greeting/src
GOCACHE=/tmp/cthulhu-go-cache go test ./...
```
Invoke the compiled command through the development host. From `cthulhu-go`:
```sh
GOCACHE=/tmp/cthulhu-go-cache go run ./cmd/tentacle-host -presentation -command greet "$PWD/../greeting-tentacles/greeting/bin/greeting"
```
Expect JSON containing `speech` and `braille`, both `Hello from Greeting!`.
This runs the executable through the actual command host, but produces no speech
or Braille. The harness's default mode has no resource containment; use it only
with development code you trust. Protocol tests do not establish live behavior.
For a live test, follow [Hello World's development launch procedure](hello-world/README.md#local-launch),
substituting your absolute executable path and launch ID `greeting`, with
`Presentation: true` in the launch JSON. `--replace --tentacles` replaces the
current Go reader and selects the development list instead of the saved registry;
run it explicitly when ready. Rebuild the reader first if its implementation
changed. Production activation requires delegated cgroup resources and does not
silently fall back when delegation fails.
Test the shortcut, learn mode, remapping, ordinary reading and web navigation on
Xorg. Verify speech modes, interruption, screen lock, terminal handoff, disable
and connected Braille where affected. See [CONTRIBUTING.md](CONTRIBUTING.md) for
review and regression requirements; contributors remain responsible for reviewing
and testing AI-assisted changes.
### 5. Create architecture-specific archives
The `make build`, `make check` and `tools/package.py` commands in **this**
repository currently target Hello World specifically. They do not automatically
discover or package a new folder. Its checker also pins the current example
version. Adapt those tools and checks when extending this repository, or use
this standalone procedure for Greeting.
From `greeting-tentacles`, stage the root manifest, documentation and license:
```sh
mkdir -p dist/greeting-package/bin
cp greeting/tentacle.toml greeting/README.md greeting/LICENSE dist/greeting-package/
```
Run the following in Bash for version `0.1.0`. Change the version together with
the manifest on later releases. `set -euo pipefail` stops on build/archive failures.
```bash
set -euo pipefail
version=0.1.0
for architecture in amd64 arm64; do
CGO_ENABLED=0 GOOS=linux GOARCH="$architecture" GOCACHE=/tmp/cthulhu-go-cache \
go build -buildvcs=false -mod=readonly -trimpath -ldflags='-s -w' \
-o dist/greeting-package/bin/greeting ./greeting/src
tar --sort=name --mtime=@0 --owner=0 --group=0 --numeric-owner \
-C dist/greeting-package -cf - tentacle.toml README.md LICENSE bin \
| gzip -n > "dist/greeting-$version-linux-$architecture.tar.gz"
done
sha256sum "dist/greeting-$version-linux-amd64.tar.gz" \
"dist/greeting-$version-linux-arm64.tar.gz" \
| sed 's@ dist/@ @' > dist/SHA256SUMS
```
Each archive must have this layout, without an enclosing `greeting/` folder:
```text
tentacle.toml
README.md
LICENSE
bin/greeting
```
The executable must be a regular, executable Linux ELF file for the advertised
architecture. Static Go builds avoid undeclared shared-library dependencies.
The reader rejects unsafe paths, symbolic/hard links and special files. Current
limits are 32 MiB per compressed download, 64 MiB expanded file data and 1,024
archive entries. Installation runs no install scripts or source builds. Package
ID, name, version and capabilities must match the repository manifest.
Inspect each archive with `tar -tzf`; from `dist`, run `sha256sum -c SHA256SUMS`.
Run each extracted executable through the host on its matching architecture;
a cross-build alone is not an execution test. The staging executable above ends
with the last architecture built, so use the appropriate extracted archive for
your local test. Keep the exact archives for publication. Normalized tar/gzip
metadata supports repeatable packaging; compare hashes when rebuilding with the
same source and toolchain.
### 6. Publish downloads, then advertise them
Review the source diff and tests before committing. Push reviewed source to your
chosen Git host. For later versions, use a release branch while preparing assets
so the default branch's existing manifest and catalog remain consistent. Create
a release/tag such as `greeting-v0.1.0` targeting that source commit. If using a
separate download server, record that source revision alongside the files.
Upload both `.tar.gz` files and `SHA256SUMS`, and make the release public when the
assets are ready. Keep `dist/` and executables out of Git.
Use stable direct HTTPS download URLs. Release attachments are convenient but
optional; an ordinary HTTPS file server works too. URLs cannot embed credentials
or fragments, and redirects must remain HTTPS. The reader has no authenticated
private-download workflow; expiring signed URLs are unsuitable for a durable
catalog.
Download the published files again and check `sha256sum -c SHA256SUMS` against
those downloads. Check the archive manifest and executable. Only then append
these tables after Greeting's entry in `catalog.toml`:
```toml
[[tentacles.releases]]
platform = "linux"
architecture = "amd64"
url = "https://downloads.example.org/greeting/0.1.0/greeting-0.1.0-linux-amd64.tar.gz"
sha256 = "REPLACE_WITH_THE_AMD64_ARCHIVE_SHA256"
[[tentacles.releases]]
platform = "linux"
architecture = "arm64"
url = "https://downloads.example.org/greeting/0.1.0/greeting-0.1.0-linux-arm64.tar.gz"
sha256 = "REPLACE_WITH_THE_ARM64_ARCHIVE_SHA256"
```
Replace the URLs and placeholders with published URLs and their actual
64-character lowercase hexadecimal hashes. These tables belong to the preceding
`[[tentacles]]`; each platform/architecture pair may appear once. Keep the
manifest version equal to the version inside the packages. Include only
architectures you actually publish. For several Tentacles, preserve the existing
entries: this repository's generated `dist/catalog.toml` lists only Hello World
and must not overwrite a larger catalog.
Review and push the matching catalog and manifest together to the repository's
default branch, which discovery fetches. Never replace a release file with changed
content: increase the version, create new archives and URLs, then publish a new
catalog revision. Refresh updates available metadata, not installed packages.
To test a newer version with the current reader, remove that managed Tentacle
and install it again after refreshing the source.
### 7. Verify the published installation
Open global Preferences → Tentacles → Add repository in the matching reader and
enter your HTTPS Git URL, or refresh an existing source. Select Greeting and
press Space. Check source, version and presentation access in the first-use
dialog, then choose **Install and enable**. Confirm status becomes Active and
test Cthulhu+Ctrl+Alt+F10 and the live checks from step 4.
Also check **Install** without enabling, enable/disable, offline reader restart
and removal. Disabled packages retain their files; installed packages launch
offline. Removing a source retains installed packages; removing a managed
Tentacle stops it and deletes its package files. Keep ordinary reader commands,
keyboard navigation and speech/Braille preferences working.
For no compatible release, check architecture and refresh the source. For
download/checksum errors, verify the exact public URL and digest. For package
metadata errors, compare the archive manifest with the repository manifest. For
activation failures, check the reader log for protocol, executable or cgroup
errors. Resource limits constrain consumption; they do not sandbox access to
account files or network. Install publishers you trust and state any remaining
unverified live behavior in release notes.