text-compress 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,6 +14,7 @@ Brotli-compress text or entire folder trees into pasteable base64 or Z85 strings
14
14
  - **Password protection** — AES-256-GCM (`-p` / `--password`)
15
15
  - **v2 split parts** — self-describing parts; shuffled names, merged files, any sibling as entry
16
16
  - **CLI + library** — terminal or `import from "text-compress"`
17
+ - **Agent skills** — versioned [TanStack Intent](https://tanstack.com/intent/latest/docs/overview) skills ship with the package for AI coding agents
17
18
 
18
19
  ## Install
19
20
 
@@ -21,6 +22,9 @@ Brotli-compress text or entire folder trees into pasteable base64 or Z85 strings
21
22
  npm install -g text-compress
22
23
  ```
23
24
 
25
+ If you use an AI coding agent, run `npx @tanstack/intent@latest install` in your
26
+ project to load versioned skills shipped with this package.
27
+
24
28
  Or run without installing:
25
29
 
26
30
  ```bash
@@ -168,6 +172,16 @@ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) and [docs/LEARNING.md](docs/LEA
168
172
 
169
173
  ## Changelog
170
174
 
175
+ ### v2.0.2 — `text-compress` (2026-07-09)
176
+
177
+ - Ship [TanStack Intent](https://tanstack.com/intent/latest/docs/overview) agent skills (`core`, `cli`, `library`) inside the npm package
178
+ - Add `check-skills` CI workflow and `npm run validate:skills`
179
+
180
+ ### v2.0.1 — `text-compress` (2026-07-08)
181
+
182
+ - Republish as **`text-compress@2.0.1`** (npm name finalized after `txtc` rejection)
183
+ - Normalized `bin` path for npm publish
184
+
171
185
  ### v2.0.0 — `text-compress` (2026-07-08)
172
186
 
173
187
  - New npm package **`text-compress`** (v1 remains `@startdoing/tc@1.0.4`)
package/dist/cli.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "text-compress",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Brotli-compress text or folders to base64/base85 strings for easy sharing",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,19 +12,22 @@
12
12
  }
13
13
  },
14
14
  "bin": {
15
- "text-compress": "./dist/cli.js"
15
+ "text-compress": "dist/cli.js"
16
16
  },
17
17
  "files": [
18
- "dist"
18
+ "dist",
19
+ "skills",
20
+ "!skills/_artifacts"
19
21
  ],
20
22
  "scripts": {
21
23
  "build": "tsc",
22
- "check": "biome check --write . && tsc",
24
+ "check": "biome check --write . && tsc && npm run validate:skills",
23
25
  "dev": "tsx src/cli.ts",
24
26
  "test": "vitest run",
25
27
  "pretest": "npm run build",
26
28
  "test:watch": "vitest",
27
- "prepublishOnly": "npm run build"
29
+ "prepublishOnly": "npm run build",
30
+ "validate:skills": "intent validate"
28
31
  },
29
32
  "keywords": [
30
33
  "brotli",
@@ -33,7 +36,8 @@
33
36
  "base85",
34
37
  "z85",
35
38
  "text",
36
- "archive"
39
+ "archive",
40
+ "tanstack-intent"
37
41
  ],
38
42
  "repository": {
39
43
  "type": "git",
@@ -48,11 +52,12 @@
48
52
  "node": ">=18"
49
53
  },
50
54
  "devDependencies": {
51
- "@biomejs/biome": "^2.5.2",
52
- "@types/node": "^26.1.0",
53
- "tsx": "^4.19.4",
54
- "typescript": "7.0.1-rc",
55
- "vitest": "^4.1.9"
55
+ "@biomejs/biome": "^2.5.3",
56
+ "@tanstack/intent": "^0.3.5",
57
+ "@types/node": "^26.1.1",
58
+ "tsx": "^4.23.0",
59
+ "typescript": "^7.0.2",
60
+ "vitest": "^4.1.10"
56
61
  },
57
62
  "dependencies": {
58
63
  "ignore": "^7.0.5"
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: cli
3
+ description: >
4
+ text-compress CLI: auto-detect compress vs decompress from input path or -t
5
+ text, -e 64/85 encoding, -p password, -s split parts, -o output, --compress
6
+ and --decompress force flags. No compress/decompress subcommands in v2.
7
+ metadata:
8
+ type: sub-skill
9
+ library: text-compress
10
+ library_version: '2.0.2'
11
+ sources:
12
+ - startdo-ing/text-compress-cli:README.md
13
+ - startdo-ing/text-compress-cli:src/cli/main.ts
14
+ - startdo-ing/text-compress-cli:src/cli/args.ts
15
+ - startdo-ing/text-compress-cli:src/cli/detect.ts
16
+ ---
17
+
18
+ # text-compress — CLI
19
+
20
+ This skill builds on text-compress/core. Read it first for encoding, pipeline,
21
+ and v1→v2 migration context.
22
+
23
+ ## Setup
24
+
25
+ ```bash
26
+ npm install -g text-compress
27
+ # or without installing:
28
+ npx text-compress ./notes.md
29
+ ```
30
+
31
+ Local development:
32
+
33
+ ```bash
34
+ npm run dev -- ./notes.md
35
+ ```
36
+
37
+ ## Core Patterns
38
+
39
+ ### Auto-detect compress or decompress
40
+
41
+ Pass a path; the CLI picks the operation. Directories always compress. Files
42
+ and inline text are checked for a valid compressed payload.
43
+
44
+ ```bash
45
+ text-compress ./notes.md # compress file → notes.txt
46
+ text-compress ./notes.txt # decompress if valid payload
47
+ text-compress ./my-project # compress folder
48
+ text-compress -t "hello world" # compress inline text
49
+ ```
50
+
51
+ ### Password protection
52
+
53
+ ```bash
54
+ text-compress ./notes.md -p "my secret" -o locked.txt
55
+ text-compress ./locked.txt -p "my secret" -o notes.md
56
+ ```
57
+
58
+ ### Base85 encoding and split output
59
+
60
+ ```bash
61
+ text-compress ./notes.md -e 85
62
+ text-compress ./large-file.txt -s 4000
63
+ text-compress ./output.7.txt # decompress any split sibling
64
+ ```
65
+
66
+ ### Force mode when auto-detect is wrong
67
+
68
+ ```bash
69
+ text-compress --compress ./looks-compressed.txt
70
+ text-compress --decompress ./plain.md
71
+ ```
72
+
73
+ ## Default output paths (when `-o` omitted)
74
+
75
+ | Operation | Default output |
76
+ | --- | --- |
77
+ | Compress file/text | `<input>.txt` |
78
+ | Compress folder | `<folder-name>.txt` |
79
+ | Decompress text | `<input>.de.txt` |
80
+ | Decompress folder | `<input>.de/` |
81
+
82
+ ## Common Mistakes
83
+
84
+ ### [CRITICAL] Using v1 subcommands `compress` / `decompress`
85
+
86
+ Wrong:
87
+
88
+ ```bash
89
+ tc compress notes.md
90
+ tc decompress out.txt
91
+ ```
92
+
93
+ Correct:
94
+
95
+ ```bash
96
+ text-compress notes.md
97
+ text-compress out.txt
98
+ ```
99
+
100
+ v2 has no required subcommand. Legacy `compress`/`decompress` as the first
101
+ argument still work but are deprecated.
102
+
103
+ Source: README.md — Migration from @startdoing/tc v1
104
+
105
+ ### [HIGH] Omitting password on protected payload
106
+
107
+ Wrong:
108
+
109
+ ```bash
110
+ text-compress ./locked.txt
111
+ ```
112
+
113
+ Correct:
114
+
115
+ ```bash
116
+ text-compress ./locked.txt -p "my secret"
117
+ ```
118
+
119
+ Password-protected payloads error without `-p`. They are **not** silently
120
+ re-compressed.
121
+
122
+ Source: src/cli/main.ts, src/payload/tags.ts
123
+
124
+ ### [HIGH] Passing a directory to decompress
125
+
126
+ Wrong:
127
+
128
+ ```bash
129
+ text-compress ./restored-project/
130
+ ```
131
+
132
+ Correct:
133
+
134
+ ```bash
135
+ text-compress ./restored-project.txt
136
+ ```
137
+
138
+ Decompress expects a compressed file path, not an output directory.
139
+
140
+ Source: src/cli/args.ts
141
+
142
+ ### [MEDIUM] Mixing v1 and v2 split part files
143
+
144
+ Wrong:
145
+
146
+ ```bash
147
+ # Expecting v1 raw concatenation without TCP\x02 headers
148
+ text-compress ./v1-part.1.txt
149
+ ```
150
+
151
+ Correct:
152
+
153
+ ```bash
154
+ # v2 parts have TCP\x02 headers; pass any sibling
155
+ text-compress ./output.7.txt
156
+ ```
157
+
158
+ v2 split format is not compatible with v1.
159
+
160
+ Source: README.md — v2 split output
161
+
162
+ ### [MEDIUM] Multiple input sources
163
+
164
+ Wrong:
165
+
166
+ ```bash
167
+ text-compress ./a.md -t "hello"
168
+ ```
169
+
170
+ Correct:
171
+
172
+ ```bash
173
+ text-compress ./a.md
174
+ # or
175
+ text-compress -t "hello"
176
+ ```
177
+
178
+ Only one input source allowed per invocation.
179
+
180
+ Source: src/cli/args.ts
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: core
3
+ description: >
4
+ text-compress core concepts: Brotli-compress text or folders to pasteable
5
+ Base64 or Z85 strings. CLI auto-detect (compress vs decompress), library
6
+ API (compress, decompress, compressFolder, decompressToPath), encoding 64/85,
7
+ password protection, v2 split parts. Entry point for all text-compress skills.
8
+ metadata:
9
+ type: core
10
+ library: text-compress
11
+ library_version: '2.0.2'
12
+ sources:
13
+ - startdo-ing/text-compress-cli:README.md
14
+ - startdo-ing/text-compress-cli:docs/ARCHITECTURE.md
15
+ - startdo-ing/text-compress-cli:src/index.ts
16
+ ---
17
+
18
+ # text-compress — Core Concepts
19
+
20
+ `text-compress` turns UTF-8 text or entire folder trees into a single pasteable
21
+ string (Base64 or Z85), and back again. Use the CLI for terminal workflows or
22
+ import from `"text-compress"` in Node.js/TypeScript.
23
+
24
+ **Package:** npm package `text-compress` (v2). Legacy v1 is `@startdoing/tc@1.0.4`
25
+ — do not mix APIs or split formats between versions.
26
+
27
+ ## Pipeline
28
+
29
+ ```
30
+ Input → type tag → Brotli (max quality) → Base64 or Z85 → pasteable string
31
+ ```
32
+
33
+ Folder archives use a custom binary format before compression. Large outputs can
34
+ be split into numbered part files for chat paste limits.
35
+
36
+ ## Sub-Skills
37
+
38
+ | Need to... | Read |
39
+ | --- | --- |
40
+ | Run compress/decompress from the terminal | text-compress/cli/SKILL.md |
41
+ | Call compress/decompress from TypeScript | text-compress/library/SKILL.md |
42
+
43
+ ## Quick Decision Tree
44
+
45
+ - Terminal one-liner, auto-detect mode? → text-compress/cli
46
+ - Programmatic use in Node/TS? → text-compress/library
47
+ - Password-protected payload? → pass `-p` / `password` on both compress and decompress
48
+ - Large output for chat paste limits? → use `-s` split (CLI) or split helpers (library)
49
+ - Migrating from `@startdoing/tc` v1? → new package name, no subcommands, new split format
50
+
51
+ ## Encoding
52
+
53
+ | Value | Format | When |
54
+ | --- | --- | --- |
55
+ | `64` (default) | Base64 | Paste anywhere |
56
+ | `85` | Z85 (ZeroMQ RFC 32) | ~8% smaller; punctuation-safe in code blocks |
57
+
58
+ Use the same encoding for compress and decompress. When `-e` is omitted on
59
+ decompress, the CLI tries both.
60
+
61
+ ## Version
62
+
63
+ Targets `text-compress` v2.0.2.
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: library
3
+ description: >
4
+ text-compress library API: compress, decompress, compressFolder,
5
+ decompressToPath, decompressPayload, split helpers. Encoding 64|85, optional
6
+ password. TAG_TEXT vs TAG_FOLDER routing. Import from "text-compress".
7
+ metadata:
8
+ type: sub-skill
9
+ library: text-compress
10
+ library_version: '2.0.2'
11
+ sources:
12
+ - startdo-ing/text-compress-cli:README.md
13
+ - startdo-ing/text-compress-cli:src/index.ts
14
+ - startdo-ing/text-compress-cli:src/api/text.ts
15
+ - startdo-ing/text-compress-cli:src/api/folder.ts
16
+ ---
17
+
18
+ # text-compress — Library API
19
+
20
+ This skill builds on text-compress/core. Read it first for encoding and pipeline
21
+ context.
22
+
23
+ ## Setup
24
+
25
+ ```ts
26
+ import {
27
+ compress,
28
+ decompress,
29
+ compressFolder,
30
+ decompressToPath,
31
+ } from "text-compress";
32
+ ```
33
+
34
+ Requires Node.js >= 18. Package name is `"text-compress"` (not `@startdoing/tc`).
35
+
36
+ ## Core Patterns
37
+
38
+ ### Compress and decompress text
39
+
40
+ ```ts
41
+ const encoded = compress("hello world");
42
+ const restored = decompress(encoded);
43
+
44
+ // Z85 encoding (~8% smaller)
45
+ const z85 = compress("hello world", 85);
46
+ const fromZ85 = decompress(z85, 85);
47
+ ```
48
+
49
+ ### Password-protected text
50
+
51
+ ```ts
52
+ const locked = compress("hello world", 64, "my secret");
53
+ const unlocked = decompress(locked, 64, "my secret");
54
+ ```
55
+
56
+ ### Folder archives
57
+
58
+ ```ts
59
+ const { encoded, fileCount, dirCount, originalBytes } =
60
+ compressFolder("./my-project");
61
+
62
+ decompressToPath(encoded, "./restored-project");
63
+ ```
64
+
65
+ ### Low-level payload access
66
+
67
+ ```ts
68
+ import { decompressPayload, TAG_TEXT, TAG_FOLDER } from "text-compress";
69
+
70
+ const { tag, data } = decompressPayload(encoded, 64, password);
71
+ if (tag === TAG_TEXT) {
72
+ const text = data.toString("utf-8");
73
+ }
74
+ ```
75
+
76
+ ## API Reference
77
+
78
+ | Function | Description |
79
+ | --- | --- |
80
+ | `compress(text, encoding?, password?)` | UTF-8 text → encoded string (`64` or `85`) |
81
+ | `decompress(encoded, encoding?, password?)` | Encoded text payload → string |
82
+ | `compressFolder(dirPath, encoding?, password?)` | Folder → `{ encoded, fileCount, ... }` |
83
+ | `decompressToPath(encoded, destDir, encoding?, password?)` | Unpack folder archive |
84
+ | `decompressPayload(encoded, encoding?, password?)` | Low-level `{ tag, data }` |
85
+
86
+ ## Common Mistakes
87
+
88
+ ### [CRITICAL] Using v1 package import
89
+
90
+ Wrong:
91
+
92
+ ```ts
93
+ import { compress } from "@startdoing/tc";
94
+ ```
95
+
96
+ Correct:
97
+
98
+ ```ts
99
+ import { compress, decompress } from "text-compress";
100
+ ```
101
+
102
+ v1 remains frozen at 1.0.4; v2 is a separate npm package.
103
+
104
+ Source: README.md — Migration
105
+
106
+ ### [HIGH] Calling decompress on a folder payload
107
+
108
+ Wrong:
109
+
110
+ ```ts
111
+ const encoded = compressFolder("./project").encoded;
112
+ const text = decompress(encoded); // throws
113
+ ```
114
+
115
+ Correct:
116
+
117
+ ```ts
118
+ decompressToPath(encoded, "./restored");
119
+ ```
120
+
121
+ Text and folder payloads share encoding but differ by tag byte after Brotli
122
+ decompression. `decompress()` throws if the tag is `TAG_FOLDER`.
123
+
124
+ Source: src/api/text.ts
125
+
126
+ ### [HIGH] Calling decompressToPath on text payload
127
+
128
+ Wrong:
129
+
130
+ ```ts
131
+ const encoded = compress("hello");
132
+ decompressToPath(encoded, "./out"); // throws
133
+ ```
134
+
135
+ Correct:
136
+
137
+ ```ts
138
+ const text = decompress(encoded);
139
+ ```
140
+
141
+ Source: src/api/folder.ts
142
+
143
+ ### [MEDIUM] Mismatched encoding on round-trip
144
+
145
+ Wrong:
146
+
147
+ ```ts
148
+ const encoded = compress("hello", 85);
149
+ const text = decompress(encoded, 64); // fails or garbage
150
+ ```
151
+
152
+ Correct:
153
+
154
+ ```ts
155
+ const encoded = compress("hello", 85);
156
+ const text = decompress(encoded, 85);
157
+ ```
158
+
159
+ Source: src/encoding/index.ts
160
+
161
+ ### [MEDIUM] compressFolder loads entire tree into memory
162
+
163
+ Wrong:
164
+
165
+ ```ts
166
+ // For very large folders in production scripts
167
+ compressFolder("/huge-monorepo");
168
+ ```
169
+
170
+ Correct:
171
+
172
+ ```bash
173
+ # CLI uses streaming pipeline for folders (bounded memory)
174
+ text-compress ./huge-monorepo
175
+ ```
176
+
177
+ The library `compressFolder()` walks and serializes in memory. The CLI
178
+ streaming path is internal and not exported.
179
+
180
+ Source: docs/ARCHITECTURE.md — Two folder compression paths