Back to the catalogue

Text Utils

Word count, case conversion, regex matching — with actions and triggers

ProductivityUtilitiesNot reviewed by Astra moderators

Install in Astra

In Astra, open Plugins and search for:

text-utils

Don’t have Astra yet? Get Astra

Details

Updated
2026-10-17
License
MIT
Status
Grandfathered until 2026-12-15 06:00 UTC

Being listed means these bytes were published by the repository shown and passed the registry’s automated checks. It is not a sandbox, not a security review, and not an endorsement.

About

Text Utils

Word counts, case conversion, regex matching and a scheduled trigger.

What it does

Three tools the assistant can use mid-conversation:

  • word_count — words, characters and lines in a piece of text.
  • case_convert — upper, lower, title, snake or camel.
  • regex_match — run a regular expression over text and return every match with a count.

One "Transform Text" action for the command editor: uppercase, lowercase, title case, reverse, Base64 encode and Base64 decode, on text from an earlier step, with the result optionally stored in a variable.

One "Scheduled Time" trigger. Give it a time in HH:MM and any command subscribed to it runs when the machine's local clock reaches that minute. The check runs every 30 seconds and fires at most once per minute, so a command never runs twice for the same tick. It only runs while Astra is running — this is not a cron replacement, and a machine that is asleep at 09:00 misses 09:00.

What it needs

  • Python 3.10 or newer on the machine running Astra. Astra ships no Python runtime; the bundle declares runtimes = ["python"] so the daemon fails clearly if there is no interpreter instead of dying at startup.
  • The dependencies in requirements.txt (astra-plugin-sdk, grpcio, protobuf).

No network, no account.

Capabilities it asks for, and why

CapabilityWhat it allowsWhy this plugin asks
toolsAstra's assistant may call the plugin during a conversationThe three text tools
actionsThe plugin contributes steps to the command editor"Transform Text"
triggersThe plugin can start your commands"Scheduled Time"

The regex tool runs a pattern you supply against text you supply, in the plugin process. A pathological pattern can make that process spin — it will not take Astra down with it, but the plugin will stop answering until you restart it.

Configuration

SettingDefaultMeaning
Max text length10000every tool refuses text longer than this, so a pasted log file cannot stall the plugin

That label is not written in plugin.toml. The schema carries "$config.max_text_length.title" and the daemon looks it up in locales/ per request — see Languages below.

A value that is not a number is logged and ignored rather than fatal: a config hook has nowhere to report a failure, and refusing to start over one bad field would take the whole plugin down.

Languages

Ships English, Russian and Ukrainian, and is the worked example of locales/ from Python. Two things are translated, by two different mechanisms, and which one a string belongs to is decided by who renders it:

Rendered byWritten as
The settings form's field label and help textthe daemon, per request, from the locales/ copy it took at install"$config.max_text_length.title" in [config] schema
The health line — ok — 3 operations processedthis process, at the moment it produces the sentenceself.i18n.tn("health.ok", n, n=str(n))
The store cardthe registry, out of the bundlethe reserved listing.name / listing.description keys

The health line is the reason tn and not t: it carries a count, which the daemon cannot know, and Russian and Ukrainian need four forms of the counted noun where English needs two. astra-plugin locale add ru writes exactly the rows a language needs — health.ok.one/few/many/other for these two — and locales.lock.json records which English each translation was made against, so rewriting the English makes the translations report themselves stale instead of quietly describing a sentence that no longer exists.

The action label, its field labels and its dropdown options are deliberately literal English. Astra's current release resolves $keys inside [config] schema and nowhere else, so a key there would reach the command editor as the text $action.transform.label; src/plugin.py says so where the labels are written, and one test in the suite holds the line.

The other seven languages are not translated and do not need to be: lookup falls back per key to English, so a de user reads the English label and everything works.

astra-plugin locale ls                 # what is shipped, and what is not
astra-plugin locale render --lang uk   # the settings form, without a daemon
astra-plugin locale check              # the locale rules alone

Testing it — the reference suite

tests/test_text_utils.py is the worked example for testing a Python Astra plugin, and is worth reading before writing tests for your own:

pip install -e '.[dev]'      # astra-plugin-sdk[test] — pytest and the harness
pytest

It uses both levels of astra_plugin_sdk.testing:

  • Level 1, astra_harness, drives the plugin through its own gRPC servicer in-process. That is not the same as calling the method: it goes through tool registration, the JSON round-trip, the schema, and the error taxonomy — which is where plugins actually break. RecordingHost records everything the plugin asked Astra for, and fail_next makes the "Astra said no" branch reachable at all. Without it, the path a plugin takes when fire_trigger is denied for a missing [permissions] entry is untested by construction.
  • Level 2, astra_wire, runs the plugin's real run() against a mock daemon over loopback gRPC — registration, the protobuf descriptor, the capability interceptor, the x-session-token on every host call. One test, at the end, because it catches a class of bug level 1 structurally cannot see.

The last test in the file breaks the plugin on purpose — one tool loses its @tool decorator — and shows the suite catching it. A test suite nobody has watched fail is a test suite nobody should trust.

Build it yourself

cd examples/text-utils
pip install -r requirements.txt
astra-plugin build            # produces text-utils-<version>-noarch.astraplugin

The bundle is noarch: the plugin is pure Python, and the platform-specific part is the interpreter, which comes from the user's machine.

Files

  • src/plugin.py — the whole plugin. The @tool / @action / @trigger decorators register everything; there is no manual wiring to read.
  • tests/test_text_utils.py — the reference suite, above.
  • conftest.py — three lines, so src.plugin imports from tests/ the same way the daemon imports it.
  • locales/en.json, locales/ru.json, locales/uk.json — the translations: the two reserved listing.* keys the store card is drawn from, the config field's label and help text, and the health.ok plural family. Flat string → string, one file per language, beside plugin.toml — the daemon deserialises them into a string map and drops the whole file on a nested object. Written with astra-plugin locale add, never by hand.
  • locales.lock.json — at the root and not inside locales/, because everything in locales/ that ends in .json is a language. It records, per translated key, a digest of the English that translation was made against; astra-plugin locale sync derives it and astra-plugin locale check reads it back. See the localisation page.
  • icon.svg — the store icon, hand-drawn SVG.

MIT licensed.

Releases

“Reviewed” means only that an Astra moderator read that release and marked it: it is not a security review, not a code audit and not an endorsement. A release marked not reviewed passed the registry’s automated checks and no moderator has marked it; a moderator’s approval of a held release is not a review.

0.1.42026-10-17

Not reviewed by Astra moderatorsProtocol 1

Permissions

  • fire_trigger StandardThe author says: “Fires the on_time trigger at the time you set, so your commands can run on a schedule”
Files and provenance
TargetSizeSHA-256
noarchtext-utils-0.1.4-noarch.astraplugin13.4 kB9cbde97b380003af82b9e92486c9747f0fec809b1143676a5be75ae5303ed7ae

Provenance

Repository
mihailinl/AstraPlugins
Release repository
mihailinl/AstraPlugins
Tag
text-utils-v0.1.4
Commit
f7827b5dff8d6ad421adc25d9c06e83e3ea03330
Older releases (3)

0.1.32026-08-20

Protocol 1

Permissions

  • fire_trigger StandardThe author says: “Fires the on_time trigger at the time you set, so your commands can run on a schedule”
Files and provenance
TargetSizeSHA-256
noarchtext-utils-0.1.3-noarch.astraplugin8.3 kB33dfcc6240a21c11bdf3e19bef23997ee8c7a0d089f4732755b8fdaad59316ac

Provenance

Repository
mihailinl/AstraPlugins
Release repository
mihailinl/AstraPlugins
Tag
text-utils-v0.1.3
Commit
1116e1af689dd36cd2f9a5ec92f2e3a66972e27e

0.1.22026-08-19

Protocol 1

Permissions

  • fire_trigger StandardThe author says: “Fires the on_time trigger at the time you set, so your commands can run on a schedule”
Files and provenance
TargetSizeSHA-256
noarchtext-utils-0.1.2-noarch.astraplugin8.3 kB7ef9945812d3d20a6c2504ac861988c1a41a1d7703e91f34036917fe405b7acd

Provenance

Repository
mihailinl/AstraPlugins
Release repository
mihailinl/AstraPlugins
Tag
text-utils-v0.1.2
Commit
5b5d2605961b54271b74304f6988972edb83d598

0.1.12026-08-10

Protocol 1

No SHA-256 — this release cannot be installed.

Files and provenance
TargetSizeSHA-256
noarchtext-utils-0.1.1-noarch.astrapluginNo SHA-256 — this release cannot be installed.

Provenance

Repository
mihailinl/AstraPlugins
Release repository
mihailinl/AstraPlugins
Tag
text-utils-v0.1.1
For the publisherThis listing has to be bound to a repositoryBind by 2026-12-15 06:00 UTC · cutover 2026-10-16 06:00 UTCHow

Migration notice, round 2.

The binding deadline is 2026-12-15 06:00 UTC.

Binding needs a Minice account that owns Astra, a binding line committed to the repository, a new tag, and a moderator’s approval of the first binding.

A release that is not held and passes the automated checks is published at once, marked not reviewed by moderators.

From 2026-10-16 06:00 UTC, a held release waits until this listing is bound.

Binding happens in the plugins panel; there is nowhere else to do it. Repository bindings