@torus-engineering/tas-kit 1.12.0 → 1.13.0

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/.tas/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TAS Kit
2
2
 
3
- **Torus Agentic SDLC Kit** — AI-assisted SDLC toolkit, designed following Spec-Driven Development philosophy and Context-Aware Architecture.
3
+ Turbo AI-first toolkit for modern agentic SDLC teams.
4
4
 
5
5
  ---
6
6
 
@@ -33,8 +33,8 @@ All code starts from spec. Story.md is "context digest" that has absorbed all in
33
33
  - When coding: MUST start new session (don't reuse old session that loaded PRD/SAD to avoid Window Context bloat)
34
34
 
35
35
  ### Role-Based & Template-Driven
36
- - 3 actual roles at Torus: PE (Product Engineer), SE (Software Engineer), DSE (DevOps Engineer)
37
- - Separate templates for PRD, SAD, ADR, Epic, Feature, Story per Torus standards
36
+ - 3 roles: PE (Product Engineer), SE (Software Engineer), DSE (DevOps Engineer)
37
+ - Separate templates for PRD, SAD, ADR, Epic, Feature, Story per team standards
38
38
  - Flow configurable via `tas.yaml` file
39
39
 
40
40
  ### Azure DevOps Compatible
@@ -4,7 +4,7 @@ Initialize TAS kit for the current project.
4
4
 
5
5
  ## Actions
6
6
  1. Need context from root/tas.yaml. If not exists, copy from .tas/tas-example.yaml to root and ask user to fill required information.
7
- 2. Create directory structure: .tas/templates/, docs/, docs/adr/, docs/epics/, docs/bugs/
7
+ 2. Create directory structure: .tas/templates/, docs/, docs/adr/, docs/epics/, docs/bugs/, docs/ref/
8
8
  3. Create root/project-status.yaml file with initial state (artifacts, epics, adrs all empty).
9
9
  4. Copy default templates to .tas/templates/ if not exist.
10
10
  5. If project type is brownfield and codebase_scan_on_init = true:
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TAS Kit
2
2
 
3
- **Torus Agentic SDLC Kit** — AI-assisted SDLC toolkit, designed following Spec-Driven Development philosophy and Context-Aware Architecture.
3
+ Turbo AI-first toolkit for modern agentic SDLC teams.
4
4
 
5
5
  ---
6
6
 
@@ -33,8 +33,8 @@ All code starts from spec. Story.md is "context digest" that has absorbed all in
33
33
  - When coding: MUST start new session (don't reuse old session that loaded PRD/SAD to avoid Window Context bloat)
34
34
 
35
35
  ### Role-Based & Template-Driven
36
- - 3 actual roles at Torus: PE (Product Engineer), SE (Software Engineer), DSE (DevOps Engineer)
37
- - Separate templates for PRD, SAD, ADR, Epic, Feature, Story per Torus standards
36
+ - 3 roles: PE (Product Engineer), SE (Software Engineer), DSE (DevOps Engineer)
37
+ - Separate templates for PRD, SAD, ADR, Epic, Feature, Story per team standards
38
38
  - Flow configurable via `tas.yaml` file
39
39
 
40
40
  ### Azure DevOps Compatible
package/bin/cli.js CHANGED
@@ -6,7 +6,7 @@ const command = args[0];
6
6
 
7
7
  function printHelp() {
8
8
  console.log(`
9
- tas-kit — Torus Agentic SDLC Kit installer
9
+ tas-kit — Turbo Agentic SDLC Kit installer
10
10
 
11
11
  Usage:
12
12
  npx @torus-engineering/tas-kit <command> [options]
@@ -55,9 +55,9 @@ export async function install({ tasDir, target }) {
55
55
  console.log(' [ok] .agents/rules/ (from .tas/rules/)');
56
56
  }
57
57
 
58
- // lean AGENTS.md
59
- await generateAgentsMd(agentsDir, target);
60
- console.log(' [ok] AGENTS.md');
58
+ // platform index (not root AGENTS.md — that's the template/system prompt)
59
+ await generateReadme(agentsDir);
60
+ console.log(' [ok] .agents/README.md');
61
61
  }
62
62
 
63
63
  async function commandToWorkflow(file, agentsDir) {
@@ -95,7 +95,7 @@ async function convertRules(rulesDir, outDir) {
95
95
  }
96
96
  }
97
97
 
98
- async function generateAgentsMd(agentsDir, target) {
98
+ async function generateReadme(agentsDir) {
99
99
  const workflowFiles = (await fs.readdir(agentsDir, { withFileTypes: true }))
100
100
  .filter(e => e.isFile() && e.name.endsWith('.md'))
101
101
  .map(e => `- \`/${e.name.replace('.md', '')}\``);
@@ -112,10 +112,8 @@ async function generateAgentsMd(agentsDir, target) {
112
112
  }
113
113
  }
114
114
 
115
- const agentsMd = [
116
- `# Project Instructions`,
117
- ``,
118
- `This project uses TAS Kit — Torus Agentic SDLC Kit.`,
115
+ const readme = [
116
+ `# TAS Kit — Antigravity`,
119
117
  ``,
120
118
  `## Workflows`,
121
119
  ``,
@@ -127,11 +125,7 @@ async function generateAgentsMd(agentsDir, target) {
127
125
  ``,
128
126
  ...skillLines,
129
127
  ``,
130
- `## Project Configuration`,
131
- ``,
132
- `See \`tas.yaml\` for project settings and project instructions file for detailed conventions.`,
133
- ``,
134
128
  ].join('\n');
135
129
 
136
- await fs.writeFile(path.join(target, 'AGENTS.md'), agentsMd);
130
+ await fs.writeFile(path.join(agentsDir, 'README.md'), readme);
137
131
  }
@@ -52,9 +52,9 @@ export async function install({ tasDir, target }) {
52
52
  console.log(' [ok] .codex/skills/ (rules)');
53
53
  }
54
54
 
55
- // lean AGENTS.md
56
- await generateAgentsMd(skillsOut, target);
57
- console.log(' [ok] AGENTS.md');
55
+ // platform index (not root AGENTS.md — that's the template/system prompt)
56
+ await generateReadme(skillsOut, codexDir);
57
+ console.log(' [ok] .codex/README.md');
58
58
  }
59
59
 
60
60
  async function commandToSkill(file, skillsOut) {
@@ -129,7 +129,7 @@ async function rulesToSkills(rulesDir, skillsOut) {
129
129
  }
130
130
  }
131
131
 
132
- async function generateAgentsMd(skillsOut, target) {
132
+ async function generateReadme(skillsOut, codexDir) {
133
133
  const skillDirs = await fs.readdir(skillsOut, { withFileTypes: true });
134
134
  const skillLines = [];
135
135
  for (const d of skillDirs.filter(e => e.isDirectory())) {
@@ -142,22 +142,16 @@ async function generateAgentsMd(skillsOut, target) {
142
142
  }
143
143
  }
144
144
 
145
- const agentsMd = [
146
- `# Project Instructions`,
147
- ``,
148
- `This project uses TAS Kit — Torus Agentic SDLC Kit.`,
145
+ const readme = [
146
+ `# TAS Kit — Codex`,
149
147
  ``,
150
148
  `## Available Skills`,
151
149
  ``,
152
- `Use \`/skills\` to list and invoke skills. Available skills:`,
150
+ `Use \`/skills\` to list and invoke skills:`,
153
151
  ``,
154
152
  ...skillLines,
155
153
  ``,
156
- `## Project Configuration`,
157
- ``,
158
- `See \`tas.yaml\` for project settings and \`CLAUDE.md\` for detailed instructions.`,
159
- ``,
160
154
  ].join('\n');
161
155
 
162
- await fs.writeFile(path.join(target, 'AGENTS.md'), agentsMd);
156
+ await fs.writeFile(path.join(codexDir, 'README.md'), readme);
163
157
  }
package/lib/install.js CHANGED
@@ -10,6 +10,25 @@ const TAS_SRC = path.join(PACKAGE_DIR, '.tas');
10
10
  const PLATFORMS_FILE = '.tas/platforms.json';
11
11
  const require = createRequire(import.meta.url);
12
12
 
13
+ // ─── Logo ────────────────────────────────────────────────────────────────────
14
+
15
+ function printLogo() {
16
+ const c = '\x1b[36m';
17
+ const d = '\x1b[90m';
18
+ const r = '\x1b[0m';
19
+ const art = [
20
+ ` ████████╗ █████╗ ███████╗ ██╗ ██╗ ██╗ ████████╗`,
21
+ ` ╚══██╔══╝ ██╔══██╗██╔════╝ ██║ ██╔╝ ██║ ╚══██╔══╝`,
22
+ ` ██║ ███████║███████╗ █████╔╝ ██║ ██║ `,
23
+ ` ██║ ██╔══██║╚════██║ ██╔═██╗ ██║ ██║ `,
24
+ ` ██║ ██║ ██║███████║ ██║ ██╗ ██║ ██║ `,
25
+ ` ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ `,
26
+ ].map(l => c + l + r).join('\n');
27
+ process.stdout.write('\n' + art + '\n' + d + ' Turbo Agentic SDLC Kit' + r + '\n\n');
28
+ }
29
+
30
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
31
+
13
32
  async function getDeletedFiles() {
14
33
  try {
15
34
  const manifest = require('./deleted-files.json');
@@ -57,30 +76,151 @@ async function copyDir(src, dest) {
57
76
  await fs.cp(src, dest, { recursive: true });
58
77
  }
59
78
 
79
+ const TAS_ROOT_EXCLUDE = new Set([
80
+ 'tas-example.yaml',
81
+ 'project-status-example.yaml',
82
+ 'platforms.json',
83
+ 'agents',
84
+ 'commands',
85
+ 'skills',
86
+ ]);
87
+
88
+ async function copyTasDir(src, dest) {
89
+ await fs.cp(src, dest, {
90
+ recursive: true,
91
+ filter: (srcPath) => !TAS_ROOT_EXCLUDE.has(path.relative(src, srcPath)),
92
+ });
93
+ }
94
+
95
+ async function chmodExecutables(target) {
96
+ const adoPy = path.join(target, '.tas', 'tools', 'tas-ado.py');
97
+ if (await exists(adoPy)) await fs.chmod(adoPy, 0o755);
98
+
99
+ const preCommit = path.join(target, '.tas', 'hooks', 'pre-commit');
100
+ if (await exists(preCommit)) await fs.chmod(preCommit, 0o755);
101
+
102
+ const hooksDir = path.join(target, '.tas', '_platform', 'hooks');
103
+ if (await exists(hooksDir)) {
104
+ const files = await fs.readdir(hooksDir);
105
+ for (const f of files) await fs.chmod(path.join(hooksDir, f), 0o755);
106
+ }
107
+ }
108
+
60
109
  // ─── Platform selection ───────────────────────────────────────────────────────
61
110
 
62
- async function choosePlatforms({ yes, forced }) {
63
- if (forced && forced.length > 0) return forced;
64
- if (yes) return ['claude-code'];
111
+ async function checkboxSelect(title, items, defaultIndexes = [0]) {
112
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
113
+ return fallbackTextSelect(title, items, defaultIndexes);
114
+ }
115
+
116
+ const selected = new Set(defaultIndexes);
117
+ let cursor = defaultIndexes[0] ?? 0;
118
+ let renderedLines = 0;
119
+
120
+ const clearRendered = () => {
121
+ if (renderedLines > 0) {
122
+ process.stdout.write(`\x1b[${renderedLines}A\x1b[0J`);
123
+ }
124
+ };
125
+
126
+ const render = () => {
127
+ clearRendered();
128
+ const lines = [];
129
+ lines.push(` ${title}`);
130
+ lines.push('');
131
+ for (let i = 0; i < items.length; i++) {
132
+ const mark = selected.has(i) ? '\x1b[32m◉\x1b[0m' : '○';
133
+ const arrow = cursor === i ? '\x1b[36m›\x1b[0m' : ' ';
134
+ const label = cursor === i ? `\x1b[36m${items[i].label}\x1b[0m` : items[i].label;
135
+ const note = items[i].note ? ` \x1b[90m${items[i].note}\x1b[0m` : '';
136
+ lines.push(` ${arrow} ${mark} ${label}${note}`);
137
+ }
138
+ lines.push('');
139
+ lines.push('\x1b[90m ↑↓ navigate space select enter confirm\x1b[0m');
140
+ renderedLines = lines.length;
141
+ process.stdout.write(lines.join('\n') + '\n');
142
+ };
143
+
144
+ return new Promise((resolve) => {
145
+ process.stdout.write('\x1b[?25l');
146
+ process.stdin.setRawMode(true);
147
+ process.stdin.resume();
148
+ process.stdin.setEncoding('utf8');
149
+
150
+ render();
151
+
152
+ const onKey = (key) => {
153
+ if (key === '\x03') {
154
+ finish(null);
155
+ process.exit(0);
156
+ } else if (key === '\x1b[A') {
157
+ cursor = (cursor - 1 + items.length) % items.length;
158
+ render();
159
+ } else if (key === '\x1b[B') {
160
+ cursor = (cursor + 1) % items.length;
161
+ render();
162
+ } else if (key === ' ') {
163
+ if (selected.has(cursor)) selected.delete(cursor);
164
+ else selected.add(cursor);
165
+ render();
166
+ } else if (key === '\r' || key === '\n') {
167
+ const ids = items.filter((_, i) => selected.has(i)).map(it => it.id);
168
+ finish(ids.length > 0 ? ids : [items[cursor].id]);
169
+ }
170
+ };
171
+
172
+ const finish = (result) => {
173
+ process.stdin.removeListener('data', onKey);
174
+ process.stdin.setRawMode(false);
175
+ process.stdin.pause();
176
+ process.stdout.write('\x1b[?25h');
177
+ clearRendered();
178
+ if (result) {
179
+ const labels = result.map(id => items.find(it => it.id === id)?.label || id).join(', ');
180
+ process.stdout.write(` Platforms: \x1b[36m${labels}\x1b[0m\n\n`);
181
+ resolve(result);
182
+ }
183
+ };
184
+
185
+ process.stdin.on('data', onKey);
186
+ });
187
+ }
65
188
 
66
- console.log('\n Agentic Coding Platform(s) to install:');
67
- PLATFORMS.forEach((p, i) => {
68
- const def = p.id === 'claude-code' ? ' (default)' : '';
69
- console.log(` [${i + 1}] ${p.label}${def}`);
189
+ async function fallbackTextSelect(title, items, defaultIndexes) {
190
+ console.log(`\n ${title}`);
191
+ items.forEach((item, i) => {
192
+ const def = defaultIndexes.includes(i) ? ' (default)' : '';
193
+ console.log(` [${i + 1}] ${item.label}${def}`);
70
194
  });
71
195
  console.log('');
72
196
  console.log(' Enter numbers comma-separated for multiple platforms.');
73
- const answer = await ask(' Choose [1/2/3/4] (default: 1): ', '1');
197
+ const nums = items.map((_, i) => i + 1).join('/');
198
+ const answer = await ask(` Choose [${nums}] (default: 1): `, '1');
74
199
 
75
200
  const selected = [];
76
201
  for (const part of answer.split(',')) {
77
202
  const idx = parseInt(part.trim(), 10) - 1;
78
- if (idx >= 0 && idx < PLATFORMS.length) {
79
- const id = PLATFORMS[idx].id;
203
+ if (idx >= 0 && idx < items.length) {
204
+ const id = items[idx].id;
80
205
  if (!selected.includes(id)) selected.push(id);
81
206
  }
82
207
  }
83
- return selected.length > 0 ? selected : ['claude-code'];
208
+ return selected.length > 0 ? selected : [items[defaultIndexes[0] ?? 0].id];
209
+ }
210
+
211
+ async function choosePlatforms({ yes, forced }) {
212
+ if (forced && forced.length > 0) return forced;
213
+ if (yes) return ['claude-code'];
214
+
215
+ return checkboxSelect(
216
+ 'Agentic Coding Platform(s) to install:',
217
+ PLATFORMS.map(p => ({
218
+ id: p.id,
219
+ label: p.label,
220
+ note: p.id === 'claude-code' ? '(default)' : '',
221
+ })),
222
+ [0],
223
+ );
84
224
  }
85
225
 
86
226
  async function savePlatforms(target, platforms) {
@@ -240,6 +380,7 @@ async function installSecurityHook({ target, mode }) {
240
380
  // ─── Update ──────────────────────────────────────────────────────────────────
241
381
 
242
382
  export async function update({ directory, yes, securityHook, platforms: forcedPlatforms }) {
383
+ printLogo();
243
384
  const target = path.resolve(directory);
244
385
 
245
386
  const tasExists = await exists(path.join(target, '.tas'));
@@ -249,7 +390,7 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
249
390
  process.exit(1);
250
391
  }
251
392
 
252
- console.log(`\nUpdating TAS Kit in: ${target}\n`);
393
+ console.log(`Updating TAS Kit in: ${target}\n`);
253
394
 
254
395
  const platforms = forcedPlatforms && forcedPlatforms.length > 0
255
396
  ? forcedPlatforms
@@ -270,7 +411,7 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
270
411
 
271
412
  const tasDest = path.join(target, '.tas');
272
413
  if (path.resolve(TAS_SRC) !== path.resolve(tasDest)) {
273
- await copyDir(TAS_SRC, tasDest);
414
+ await copyTasDir(TAS_SRC, tasDest);
274
415
  }
275
416
  console.log(' [ok] .tas/ (updated)');
276
417
 
@@ -282,7 +423,7 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
282
423
  }
283
424
  }
284
425
 
285
- await runPlatformAdapters(platforms, { tasDir: path.join(target, '.tas'), target });
426
+ await runPlatformAdapters(platforms, { tasDir: TAS_SRC, target });
286
427
 
287
428
  await savePlatforms(target, platforms);
288
429
 
@@ -294,7 +435,8 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
294
435
  await installSecurityHook({ target, mode: securityHook });
295
436
  }
296
437
 
297
- console.log(` [--] CLAUDE.md, tas.yaml, .env.example — not touched`);
438
+ const configFilename = platforms.includes('claude-code') ? 'CLAUDE.md' : 'AGENTS.md';
439
+ console.log(` [--] ${configFilename}, tas.yaml, project-status.yaml, .env.example — not touched`);
298
440
  console.log(`
299
441
  TAS Kit updated successfully!
300
442
 
@@ -306,11 +448,12 @@ and manually merge changes into your CLAUDE.md and tas.yaml if needed.
306
448
  // ─── Install ─────────────────────────────────────────────────────────────────
307
449
 
308
450
  export async function install({ directory, yes, securityHook, platforms: forcedPlatforms }) {
451
+ printLogo();
309
452
  const target = path.resolve(directory);
310
453
 
311
454
  await fs.mkdir(target, { recursive: true });
312
455
 
313
- console.log(`\nInstalling TAS Kit into: ${target}\n`);
456
+ console.log(`Installing TAS Kit into: ${target}\n`);
314
457
 
315
458
  const tasExists = await exists(path.join(target, '.tas'));
316
459
  if (tasExists && !yes) {
@@ -327,7 +470,7 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
327
470
  // Copy .tas/ (skip if installing into the package itself)
328
471
  const tasDest = path.join(target, '.tas');
329
472
  if (path.resolve(TAS_SRC) !== path.resolve(tasDest)) {
330
- await copyDir(TAS_SRC, tasDest);
473
+ await copyTasDir(TAS_SRC, tasDest);
331
474
  console.log(' [ok] .tas/');
332
475
  } else {
333
476
  console.log(' [--] .tas/ (source = destination, skipped)');
@@ -335,16 +478,18 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
335
478
 
336
479
  // Platform selection
337
480
  const platforms = await choosePlatforms({ yes, forced: forcedPlatforms });
338
- await runPlatformAdapters(platforms, { tasDir: path.join(target, '.tas'), target });
481
+ await runPlatformAdapters(platforms, { tasDir: TAS_SRC, target });
339
482
  await savePlatforms(target, platforms);
340
483
 
341
484
  // Project config files (first-time only)
342
- const claudeMdTarget = path.join(target, 'CLAUDE.md');
343
- if (!(await exists(claudeMdTarget))) {
344
- await fs.copyFile(path.join(PACKAGE_DIR, '.tas', 'templates', 'AGENTS.md'), claudeMdTarget);
345
- console.log(' [ok] CLAUDE.md (from .tas/templates/AGENTS.md)');
485
+ // Claude Code uses CLAUDE.md; all other platforms use AGENTS.md
486
+ const configFilename = platforms.includes('claude-code') ? 'CLAUDE.md' : 'AGENTS.md';
487
+ const configTarget = path.join(target, configFilename);
488
+ if (!(await exists(configTarget))) {
489
+ await fs.copyFile(path.join(PACKAGE_DIR, '.tas', 'templates', 'AGENTS.md'), configTarget);
490
+ console.log(` [ok] ${configFilename} (from .tas/templates/AGENTS.md)`);
346
491
  } else {
347
- console.log(' [--] CLAUDE.md already exists, skipped');
492
+ console.log(` [--] ${configFilename} already exists, skipped`);
348
493
  }
349
494
 
350
495
  const envExampleTarget = path.join(target, '.env.example');
@@ -363,6 +508,17 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
363
508
  console.log(' [--] tas.yaml already exists, skipped');
364
509
  }
365
510
 
511
+ const psYamlTarget = path.join(target, 'project-status.yaml');
512
+ if (!(await exists(psYamlTarget))) {
513
+ const psSrc = path.join(PACKAGE_DIR, '.tas', 'project-status-example.yaml');
514
+ if (await exists(psSrc)) {
515
+ await fs.copyFile(psSrc, psYamlTarget);
516
+ console.log(' [ok] project-status.yaml (from .tas/project-status-example.yaml)');
517
+ }
518
+ } else {
519
+ console.log(' [--] project-status.yaml already exists, skipped');
520
+ }
521
+
366
522
  if (process.platform !== 'win32') {
367
523
  await chmodExecutables(target);
368
524
  }
@@ -375,7 +531,7 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
375
531
  TAS Kit installed successfully! (Platforms: ${platformLabels})
376
532
 
377
533
  Next steps:
378
- 1. Edit CLAUDE.md — add your project's tech stack and conventions
534
+ 1. Edit ${configFilename.padEnd(10)} — add your project's tech stack and conventions
379
535
  2. Edit tas.yaml — set project name, team and ADO config
380
536
  3. Create .env — add AZURE_DEVOPS_PAT (see .env.example)
381
537
  4. Open your IDE — run /tas-init to initialize your project
@@ -385,19 +541,3 @@ Docs:
385
541
  .tas/hooks/README.md — pre-commit security hook details
386
542
  `);
387
543
  }
388
-
389
- // ─── Helpers ─────────────────────────────────────────────────────────────────
390
-
391
- async function chmodExecutables(target) {
392
- const adoPy = path.join(target, '.tas', 'tools', 'tas-ado.py');
393
- if (await exists(adoPy)) await fs.chmod(adoPy, 0o755);
394
-
395
- const preCommit = path.join(target, '.tas', 'hooks', 'pre-commit');
396
- if (await exists(preCommit)) await fs.chmod(preCommit, 0o755);
397
-
398
- const hooksDir = path.join(target, '.tas', '_platform', 'hooks');
399
- if (await exists(hooksDir)) {
400
- const files = await fs.readdir(hooksDir);
401
- for (const f of files) await fs.chmod(path.join(hooksDir, f), 0o755);
402
- }
403
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@torus-engineering/tas-kit",
3
- "version": "1.12.0",
4
- "description": "Torus Agentic SDLC Kit — Collection of commands, skills, rules, hooks, agents and workflows for modern AI-First SDLC",
3
+ "version": "1.13.0",
4
+ "description": "Turbo AI-first toolkit for modern agentic SDLC teams.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "tas-kit": "bin/cli.js"