Repository navigation
Releases: mpyw/tepra.tm2
Release list
v0.4.6
Claude Desktop
This release attaches tm2.mcpb, an MCP Bundle for Claude Desktop on macOS and Windows.
- Download
tm2.mcpb. - Open it. Claude Desktop asks you to install it.
Nothing else needs to be installed. The bundle has tm2 in it, and runs it as tm2 mcp.
Important
The bundle adds the tools to the chat of Claude Desktop only.
The Code tab of Claude Desktop runs Claude Code, and its sessions do not get them.
Add tm2 to Claude Code as the README says.
checksums.txt lists tm2.mcpb too.
The library, the CLI and the files they write are as in v0.4.5.
Changelog
v0.4.5
v0.4.4
MCP
Every tool of tm2 mcp now declares all four hints. Before, only inspect_label declared one, readOnlyHint. Some directories, such as OpenAI's, reject a tool that leaves out a hint.
| Tool | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
create_text_label, create_label_pages, create_pour_labels |
false | true | true | false |
edit_label |
false | true | false | false |
inspect_label |
true | false | true | false |
The tools themselves work as before.
Changelog
v0.4.3
Security
Important
This release is built with Go 1.27.3. Go 1.27.3 fixes CVE-2026-111943 in crypto/x509: certificate verification now rejects chains that contain eight eMudhra intermediate CAs whose private keys were compromised. Earlier releases were built with an older Go and accept those chains. Update to this release.
Changelog
v0.4.2
v0.4.1
This release names a label edited into another file after that file.
Changes
TEPRA LINK 2 lists a label by the fileName inside the file, not by the file's own name. In v0.4.0, a label edited into another file kept the name of the file it was read from. So the copy showed in the app under the old name.
| Edit | fileName in v0.4.0 |
fileName now |
|---|---|---|
edit_label with output, or tm2 edit -o |
The file read's | The new file's, as a label made there would get |
The same, with an operation on /fileName |
The patch's | The patch's |
| In place | Kept | Kept |
out.tm2andOUT.TM2both name the labelout.tm2, astm2 text -odoes. (#63)- To keep the old name, set it in the patch:
{"op": "replace", "path": "/fileName", "value": "old.tm2"}. (#63)
Changelog
v0.4.0
This release reads a .tm2 file whole, and changes it. A file saved by the app works too. It works from MCP, the command line and Go.
New
| Read every key | Change the file | |
|---|---|---|
| MCP | inspect_label with full: true. It also returns each picture as an image |
edit_label |
| Command | tm2 inspect --json file.tm2 |
tm2 edit [-o out.tm2] [-f] file.tm2 [patch.json] |
| Go | json.Marshal(f), as before |
(*File).Patch(ops...) |
- A change is a JSON Patch (RFC 6902) on the file, as
tm2 inspect --jsonprints it. (#62) - Either every operation applies, or nothing changes. (#62)
image_pathin an operation gives a picture from a PNG, JPEG or GIF file. (#62)- Without
-ooroutput, the file is changed in place. (#62)
This patch changes the third row of a pour file, and centres its text:
[
{"op": "replace", "path": "/tableData/2/0", "value": "4行目"},
{"op": "replace", "path": "/documents/0/drawers/0/TIAlignment", "value": 1}
]A patch keeps to what the app writes:
| Rule | Why |
|---|---|
| A key is not added or removed. A whole object put in place needs every key | The app writes every key. A key left out would be written as 0 |
A drawer added needs only its type (text, pour or image) and the keys to change |
It starts as the app makes one |
A copy gets a new identifier. Two or more pages get MultiplePage |
The app lists the pages only then |
| A box with new text no longer shows its placeholder | The app shows the placeholder instead of the text |
| Rows get 50 columns, and pictures are checked and made PNG | As the app writes them |
See Patches in the README for every rule, and what the numbers of the keys mean.
Important
A patch does not lay the label out again. Text made longer keeps its frame, and the app fits it there. Set frame too when the size must change.
Changes
tm2 inspectandinspect_labeldescribe more. Each drawer starts with its index, anddrawers:gives the path of the list, such as/documents/0/drawers. The settings that differ from a new drawer follow, such asalign centerorborder box 0.7. A script that reads the old lines must change. (#62)- New error:
ErrBadPatch. It is an operationPatchcannot apply, or a patch that makes no.tm2file. (#62)
Note
Files changed through edit_label were opened in TEPRA LINK 2, and showed as the patch meant. They were files of tm2, and files the app saved:
- Text with a border, given new text
- Pages, with a page copied
- Pour rows added, changed and removed
- A blank box of the app, given text
- A picture added
Tip
An edit in place writes over the file. Keep a copy of a file the app saved, or write to another file with -o.
Changelog
v0.3.0
This release renames the package, the command and the MCP server to tm2. The repository and the import path stay github.com/mpyw/tepra.tm2. What the files hold does not change.
Caution
Breaking Changes
- The Go package is
tm2, nottepra. Writetm2.NewText, nottepra.NewText. The import path does not change. (#61) - The command is
tm2, nottepra. It is built fromcmd/tm2, and the release archives aretm2_<version>_<os>_<arch>. (#61) - The MCP server is named
tm2. (#61) - Errors say
tm2:, nottepra:. Code that tests errors witherrors.Isdoes not change. (#61)
Notes
Important
.tm2 is the format of TEPRA LINK 2 only. TEPRA Creator (テプラ クリエイター), the app for Windows, does not open these files. The README now says so. (#61)
Upgrading
| You use | Do this |
|---|---|
| The Go API | Change tepra. to tm2.. The import path stays |
go install |
go install github.com/mpyw/tepra.tm2/cmd/tm2@latest, then remove the old tepra binary |
| mise | mise up. The command is now tm2 |
| A release binary | Put tm2 on your PATH, in place of tepra |
| Scripts | Change tepra text, tepra pages, tepra pour and tepra inspect to tm2 ... |
| The MCP server in Claude Code | claude mcp remove tepra, then claude mcp add tm2 -- tm2 mcp |
Changelog
v0.2.0
This release makes 12 mm the default tape, and fixes the defects that eight rounds of review found in v0.1.1. Files the app wrote read and write back as before, and keep keys this package does not know.
Caution
Breaking Changes
- The default tape is 12 mm, not 18 mm. It is the more common width. Pass
--tape 18, ortape_width_mm: 18over MCP, to keep 18 mm. The Go API takes aTapealways, so it does not change. (#60) - The CLI writes only a
.tm2file, in any case, with a name before it, as MCP does.-o out.txtand-o .tm2are refused. (#58) tepra helpis gone. Use-hor--help, which work on every command. (#41, #49)- More inputs are refused when a label is made, where they used to make a broken file or fail only when it was written. See Checks.
Checks
Each of these is refused by NewText, NewPages and NewPour, and by the CLI and MCP through them.
| Input | Error | PR |
|---|---|---|
| NaN or ±Inf for a font size, border width, padding, margin or length | ErrInvalidOptions |
#12 |
| Text, a value, a column title or a name that is not UTF-8 | ErrBadText (new) |
#12, #24 |
| Text, or a pour value, of blanks only | ErrNoText |
#12, #24 |
| A font size larger than fits the tape | ErrNoRoom, with the size that fits |
#57 |
| Padding that leaves no room, with a font size given too | ErrNoRoom |
#47 |
| A fixed length that shrinks the text to size 0 | ErrNoRoom |
#12 |
| A label of automatic length over 3000 mm | ErrOverLimit |
#12 |
| A picture over 8192 by 8192 pixels, by its header | ErrBadImage |
#24 |
A nil drawer, or one with no BaseDrawer |
ErrBadFile (new) |
#16, #24 |
Layout
- Inverted lines turned 180 read in order with the tape turned over: the first line is in the bottom box. (#56)
- In inverted pour, a value of fewer lines follows
--valign, in the first, middle or last boxes. (#56) - A length of 3000 mm is taken with any margin. Rounding refused it with some. (#32)
- A background is stretched to the printer's dots at most. A large one took 4.6 GB before. (#15)
- "No room" names its cause: the padding, too many lines, a line too long to run across the tape, or a font size too large. (#32, #42, #51, #57)
Files
- Keys this package does not know are kept through a read and a write. They are in a new
Unknownfield of the file, a document or a drawer. (#14) - A drawer of an unknown type is kept as
RawDrawer, whatever its keys hold. So is one that is not an object, or has no type. (#36, #43, #48, #51) ParseFilerefuses a file with no documents, or a document with no tape width, asErrBadFile. (#25, #36)- Errors of the JSON are
ErrBadFile. Errors of the file system and of a reader come back as they are, even inside a value. (#13, #25, #33)
CLI and MCP
- A label is encoded before its file is opened, so a file that cannot be encoded writes nothing and leaves an old one as it was. A replaced file is written in place: through a symlink, keeping its mode. (#10, #22)
- The CSV reader says when a file is not UTF-8, takes CR line ends and blanks around a quoted value, and keeps blanks inside one. (#12, #26, #29, #34, #41)
- Errors are short and printed once: one line each, grouped by message, at most 10 listed, and a usage error without the help. (#16, #23, #33, #35, #49)
- Smaller fixes: (#11, #26, #35)
- Help no longer says
(default: 0). -o X.TM2names the labelX.inspectreads a file with rows but no column titles.- Drawers count from 1 in errors.
- Help no longer says
Upgrading
| You use | Do this |
|---|---|
18 mm tape with the CLI or MCP, without --tape |
Add --tape 18, or tape_width_mm: 18 |
-o with another extension |
Name the file .tm2 |
tepra help |
Use tepra -h, or tepra <command> -h |
| The Go API | Nothing, unless you check for the errors above |
Changelog
- 18e28a2 Test the paths no test reached: pictures, icons, errors, CLI (#2)
- 7c44726 Write a label only once it is encoded, and replace it by rename (#10)
- 05376ef Describe a file with rows but no column titles (#11)
- d2e64b7 Check numbers and text when a label is made, not when it is written (#12)
- cb3a822 Wrap errors of reading and encoding files in ErrBadFile (#13)
- 06ff096 Keep keys the package does not know through a read and a write (#14)
- 50a9509 Stretch a background to the printer's dots at most (#15)
- a181658 Fix small defects: CLI message, page errors, icon buffer, nil drawers (#16)
- cd0c1da Replace a label in place, as other tools write (#22)
- 84ed202 Keep error messages short however long the list is (#23)
- 588df27 Check names, blank text, picture sizes and drawer bases (#24)
- 2402ff2 Reject a file with no documents, and pass reader errors through (#25)
- f1a48d3 Fix CLI help defaults, CSV spaces, MCP path message, drawer numbers (#26)
- a9aa904 Take 3000 mm with any margin, and say why there is no room (#32)
- 08baddc Keep reader errors, hidden sentinels and long values right in errors (#33)
- 06ec96b Keep blanks at line ends inside quoted CSV values (#34)
- b91b0fa Print a CLI usage error once, and name a label without .TM2 (#35)
- 280d990 Refuse documents with no tape width, and keep unknown drawers whatever their keys (#36)
- be049b9 Make the CLI and MCP agree on help, names and blanks (#41)
- c05b026 Blame the padding when it is what takes the room for text (#42)
- b7ef8c3 Keep an unknown drawer whatever its identifier holds (#43)
- 67ac1ad Check room for text with a font size too, and fix the error docs (#47)
- c7d67cd Keep a drawer that is not an object, or of no string type (#48)
- d0ffada Say an unknown command is unknown, and exit 1 (#49)
- 0caa29d Find the no-room cause by fitted size, and read base fields of drawers of no type (#51)
- 1671a9a Order inverted lines for 180 turns, and place short pour values by valign (#56)
- 5e7b581 Refuse a font size larger than fits the tape (#57)
- 21c737a Write a label only to a .tm2 file from the CLI, as MCP does (#58)
- fe5e9e9 List every cause of ErrNoRoom in its doc and the README (#59)
- c82729e Make 12 mm the default tape width (#60)
v0.1.1
This release reports every bad option and value at once, where v0.1.0 stopped at the first. The labels it writes are the same.
Errors
-
Every error comes back at once.
NewPourandNewPagescheck the values even when an option is bad. The CLI and MCP go on to them even when a name did not parse. (#1)$ printf '123\n123456789012\nx\n' | tepra pour --code jan13 --rotate 45 --margin 0 -o x.tm2 tepra: unknown name: rotation "45"; known: 0, 90, 180, 270 tepra: invalid options: margin 0 mm; the app takes 1 to 500 mm tepra: value 1: bad value for a code: "123" as jan13; it takes 12 digits; the app adds the check digit tepra: value 3: bad value for a code: "x" as jan13; it takes 12 digits; the app adds the check digit -
Values and pages count from 1, as the app's rows and pages do. (#1)
-
ParseRotationlists the rotations clockwise: 0, 90, 180, 270. (#1) -
The CLI prints each error on a line of its own, each with one
tepra:. (#1)
Other
- The social preview's text is centred beside the mascot. (#1)