td-ai-tools 1.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.
Files changed (41) hide show
  1. package/README.md +49 -0
  2. package/agents/README.md +10 -0
  3. package/agents/horizon-component-library/AGENTS.md +184 -0
  4. package/agents/horizon-component-library/README.md +10 -0
  5. package/agents/horizon-component-library/scripts/td-guard.sh +49 -0
  6. package/bin/cli.js +209 -0
  7. package/package.json +23 -0
  8. package/scripts/smoke-install.sh +56 -0
  9. package/skills/README.md +15 -0
  10. package/skills/cache-reset/SKILL.md +18 -0
  11. package/skills/cache-reset/agents/openai.yaml +4 -0
  12. package/skills/car-ticket-generator/SKILL.md +130 -0
  13. package/skills/car-ticket-generator/agents/openai.yaml +4 -0
  14. package/skills/everhour-basecamp-estimates/.env.example +2 -0
  15. package/skills/everhour-basecamp-estimates/SKILL.md +73 -0
  16. package/skills/everhour-basecamp-estimates/agents/openai.yaml +4 -0
  17. package/skills/everhour-basecamp-estimates/scripts/update_estimates.py +518 -0
  18. package/skills/everhour-basecamp-estimates/tests/test_update_estimates.py +93 -0
  19. package/skills/horizon-component-migration/SKILL.md +59 -0
  20. package/skills/horizon-component-migration/agents/openai.yaml +4 -0
  21. package/skills/pr-solver/SKILL.md +50 -0
  22. package/skills/pr-solver/agents/openai.yaml +4 -0
  23. package/skills/pr-solver/references/github-pr-reviewthreads-graphql.md +63 -0
  24. package/skills/pr-solver/scripts/list_unresolved_threads.py +307 -0
  25. package/skills/pull-request/SKILL.md +216 -0
  26. package/skills/pull-request/agents/openai.yaml +4 -0
  27. package/skills/record-changes/SKILL.md +75 -0
  28. package/skills/record-changes/agents/openai.yaml +4 -0
  29. package/skills/record-changes/scripts/branch_diff_context.py +190 -0
  30. package/skills/stylesheet-migration/SKILL.md +36 -0
  31. package/skills/stylesheet-migration/agents/openai.yaml +6 -0
  32. package/skills/stylesheet-migration/scripts/__pycache__/liquid_stylesheet_migrator.cpython-312.pyc +0 -0
  33. package/skills/stylesheet-migration/scripts/__pycache__/test_liquid_stylesheet_migrator.cpython-312.pyc +0 -0
  34. package/skills/stylesheet-migration/scripts/liquid_stylesheet_migrator.py +204 -0
  35. package/skills/stylesheet-migration/scripts/migrate_stylesheet_tags.py +172 -0
  36. package/skills/stylesheet-migration/scripts/test_liquid_stylesheet_migrator.py +254 -0
  37. package/skills/td-js-vanilla-rules/SKILL.md +70 -0
  38. package/skills/td-js-vanilla-rules/agents/openai.yaml +3 -0
  39. package/skills/td-review/SKILL.md +122 -0
  40. package/skills/td-review/agents/openai.yaml +4 -0
  41. package/skills/td-review/agents/td-theme-reviewer.md +221 -0
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # AgentToolkit
2
+
3
+ ## Project Overview
4
+ This repository is a lightweight foundation for organizing reusable agent packs, skills, workflows, and evaluation assets.
5
+
6
+ <!-- TODO: Add project mission, scope, and ownership details. -->
7
+
8
+ ## Repository Layout
9
+ - `AGENTS.md`: Repository-specific operating instructions.
10
+ - `agents/`: Reusable agent packs (`AGENTS.md` + helper assets per pack).
11
+ - `skills/`: Reusable skills (`SKILL.md`, optional scripts/references, model metadata).
12
+ - `workflows/`: Reusable multi-step orchestration workflows.
13
+ - `evals/`: Evaluation cases, datasets, and runners.
14
+
15
+ ## Basic Usage
16
+ 1. Add agent packs in `agents/` and index them in `agents/README.md`.
17
+ 2. Add capability specifications in `skills/` and index them in `skills/README.md`.
18
+ 3. Define orchestrations in `workflows/` and index them in `workflows/README.md`.
19
+ 4. Maintain evaluation assets in `evals/`.
20
+
21
+ ## CLI Usage
22
+ Run the packaged installer from inside a target project:
23
+
24
+ ```bash
25
+ npx td-ai-tools
26
+ ```
27
+
28
+ Useful commands:
29
+
30
+ ```bash
31
+ npx td-ai-tools list
32
+ npx td-ai-tools install
33
+ npx td-ai-tools install --all
34
+ npx td-ai-tools install pr-solver
35
+ npx td-ai-tools install pr-solver horizon-component-library
36
+ ```
37
+
38
+ The installer copies requested items into both agent layouts:
39
+
40
+ - Skills: `.claude/skills/<name>/` and `.agents/skills/<name>/`
41
+
42
+ This keeps the installed assets available to both Claude-style and `.agents`-style project conventions.
43
+
44
+ ## Local Verification
45
+ Run the local smoke test to package the repo and verify installation into a throwaway project:
46
+
47
+ ```bash
48
+ npm run smoke:install
49
+ ```
@@ -0,0 +1,10 @@
1
+ # agents
2
+
3
+ ## Available Agent Packs
4
+ - `horizon-component-library/`: Theory Digital Horizon component-library agent rules, with guard script.
5
+
6
+ ## Pack Structure Convention
7
+ - `<pack-name>/AGENTS.md`
8
+ - `<pack-name>/README.md`
9
+ - `<pack-name>/scripts/*` (optional)
10
+ - `<pack-name>/assets/*` (optional)
@@ -0,0 +1,184 @@
1
+ # .codex/AGENTS.md — Theory Digital
2
+
3
+ ## Scope
4
+ Default rules for Theory Digital component-library sections built with theme blocks.
5
+
6
+ ## Core Principles
7
+ - Prefer isolated TD implementations over vendor patching.
8
+ - Keep responsibilities separated:
9
+ - Liquid derives and normalizes state.
10
+ - Markup renders only the active structure.
11
+ - CSS handles layout and presentation.
12
+ - JavaScript handles behavior only.
13
+ - Build the simplest implementation that satisfies the requirement.
14
+ - Keep DOM, CSS, and JS minimal and maintainable.
15
+ - Every change must be logged in `docs/changes.md`.
16
+
17
+ ## File Conventions
18
+ - Custom code must live in `td-` or `_td-` prefixed files only.
19
+ - Vendor files are READ-ONLY unless wrapped in TD CHANGE delimiters and documented in `docs/hotspots.md`.
20
+ - Custom sections: `sections/td-*.liquid`
21
+ - Custom blocks: `blocks/td-*.liquid`
22
+ - Private blocks: `blocks/_td-*.liquid`
23
+ - Custom snippets: `snippets/td-*.liquid`
24
+ - Put generic, reusable styles in `assets/td-base.css`.
25
+ - Every file that directly renders or calls the Swiper custom element must also include the Swiper assets.
26
+ - Use vendor code only when it already solves the requirement as-is.
27
+ - Otherwise, build an isolated TD implementation instead of patching vendor internals.
28
+
29
+ ## Forbidden
30
+ - Never modify vendor section schemas.
31
+ - Never use `{% include %}`. Use `{% render %}` only.
32
+ - Never add inline scripts to `layout/` files.
33
+ - Never import unapproved third-party JavaScript.
34
+ - Never add non-`td`-prefixed custom CSS variables.
35
+ - Never add non-`data-td-*` custom data attributes.
36
+ - Never declare unnecessary Liquid variables for single-use values.
37
+ - Never overload one setting to drive incompatible behaviors.
38
+ - Never emit parallel desktop/mobile or alternate-mode structures unless needed.
39
+ - Never rely on CSS alone to hide unused structural markup when Liquid can resolve it.
40
+ - Never let invalid or legacy state leak into classes, attributes, or CSS variables.
41
+ - Do not add redundant fallback guards or defensive reassignment for schema-backed primitive settings.
42
+ - Avoid unnecessary conditionals, wrappers, and listeners.
43
+
44
+ ## Required Patterns
45
+
46
+ ### JavaScript
47
+ - Author JavaScript via `{% javascript %}` and Web Components.
48
+ - When creating or modifying JavaScript, load and follow the `$td-js-vanilla-rules` skill.
49
+ - If `$td-js-vanilla-rules` is unavailable, enforce the JavaScript baseline rules in this file.
50
+ - Always guard custom element registration:
51
+ - `if (!customElements.get(...))`
52
+ - Always clean up in `disconnectedCallback`:
53
+ - event listeners
54
+ - timers
55
+ - observers
56
+ - external subscriptions
57
+ - Keep JavaScript minimal, event-driven, and component-scoped.
58
+
59
+ ### CSS
60
+ - Author CSS via `{% stylesheet %}` and CSS variables.
61
+ - All custom properties must use the `--td-*` prefix.
62
+ - Use BEM naming for all classes.
63
+ - Use BEM modifier classes for discrete state:
64
+ - mode
65
+ - layout
66
+ - alignment
67
+ - position
68
+ - variant
69
+ - Use CSS variables for dynamic values:
70
+ - sizes
71
+ - spacing
72
+ - offsets
73
+ - dimensions
74
+ - Use inline CSS variables only when truly dynamic.
75
+ - Keep CSS ordered as:
76
+ - shared/base rules
77
+ - mobile-only rules
78
+ - desktop-only rules
79
+
80
+ ### Liquid
81
+ - Derive and normalize state at the top of the file before rendering.
82
+ - Trust schema-backed primitive settings to provide valid values.
83
+ - Normalize only values that are:
84
+ - derived
85
+ - cross-dependent
86
+ - legacy-sensitive
87
+ - conditionally invalid
88
+ - externally sourced
89
+ - For straightforward values, prefer inline Liquid over one-time-use variables.
90
+ - Only introduce variables when they improve reuse, clarity, or state normalization.
91
+ - Use clear breakpoint-specific names when behavior differs by breakpoint.
92
+ - Use `block.settings.<id>` directly when used once.
93
+ - Use `default` only when truly needed.
94
+ - Support deterministic fallbacks:
95
+ - explicit setting
96
+ - product/metafield
97
+ - placeholder
98
+ - Do not output unresolved or invalid state into markup, classes, attributes, or CSS variables.
99
+
100
+ ### Markup
101
+ - Render only the active structure.
102
+ - Keep DOM output minimal.
103
+ - Render only the wrappers required for the active mode.
104
+ - In component-library sections built with theme blocks, parent/child composition must use `{% content_for 'blocks' %}` for nested private blocks.
105
+ - Accessibility baseline:
106
+ - use real buttons/links for interaction
107
+ - keep `aria-expanded` and `aria-controls` synchronized in JS
108
+ - support Escape to close interactive UI
109
+ - respect `prefers-reduced-motion`
110
+
111
+ ## Section Architecture Rules
112
+ - Resolve layout decisions in Liquid whenever possible.
113
+ - If desktop and mobile behavior differ, use separate schema settings.
114
+ - Use `visible_if` to improve settings organization only when the setting type supports it and the dependency is valid under Shopify schema rules.
115
+ - Do not rely on `visible_if` for behavior enforcement, required logic, or unsupported setting relationships.
116
+ - Normalize invalid settings defensively in Liquid.
117
+ - Use BEM modifier classes for discrete state and CSS variables for dynamic values.
118
+
119
+ ## Schema Rules
120
+ - All hardcoded values must be settings or metafields unless they are true implementation constants.
121
+ - Schema labels, options, and headers should use translation keys (`t:*`) whenever possible.
122
+ - Reuse existing `td` translation keys first.
123
+ - New translation keys must be created under the `td` namespace when needed.
124
+ - Keep new keys simple and reusable.
125
+ - Add `info` text only when the setting is not self-explanatory.
126
+ - Use `visible_if` only where supported and only for editor organization, not as a substitute for Liquid validation.
127
+ - Model schema around actual user-facing behavior.
128
+
129
+ ## Global Schema Requirements
130
+ - All sections must include padding settings.
131
+ - All sections must include color scheme picker settings.
132
+ - All sections must include custom ID settings.
133
+ - All blocks must inherit the color scheme by default.
134
+ - All blocks must provide a custom scheme override option.
135
+
136
+ ## Rendering Rules
137
+ - Image URL width must be 2x the displayed maximum width.
138
+ - Example:
139
+ - displayed max width `80px`
140
+ - `image_url: width: 160`
141
+ - Render only the assets and markup required for the active implementation.
142
+
143
+ ## Performance Rules
144
+ - Keep JavaScript minimal and event-driven.
145
+ - Avoid unnecessary listeners, observers, timers, and DOM work.
146
+ - Prefer solving state once in Liquid instead of repeatedly in CSS or JS.
147
+
148
+ ## Editor Rules
149
+ - Add Shopify editor hooks when needed:
150
+ - `shopify:block:select`
151
+ - `shopify:block:deselect`
152
+ - Interactive UI must work in both storefront and theme editor contexts.
153
+
154
+ ## Hard Output Gate
155
+ - For any edits in `sections/td-*.liquid`, `blocks/td-*.liquid`, `blocks/_td-*.liquid`, or `snippets/td-*.liquid`, run `.claude/agents/horizon-component-library/scripts/td-guard.sh` before final output.
156
+ - If `td-guard` fails, fix the code and rerun the guard before responding.
157
+
158
+ ## Guard Retry Budget
159
+ - Auto-fix attempts after a failing required guard are capped at 2 retries per task.
160
+ - If the guard still fails after 2 retries, stop and ask the user for direction.
161
+ - Do not continue retrying without new user input.
162
+
163
+ ## Escalation Message Format
164
+ - When retry budget is exhausted, report:
165
+ - failing check name
166
+ - exact failing files and lines
167
+ - fixes attempted
168
+ - one recommended next action
169
+
170
+ ## Pre-Output Checklist
171
+ - Custom code is isolated in TD-prefixed files.
172
+ - Vendor internals were not patched unless allowed and documented.
173
+ - State is derived and normalized at the top of the file.
174
+ - Schema-backed primitive settings are not wrapped in redundant fallback guards.
175
+ - `.claude/agents/horizon-component-library/scripts/td-guard.sh` passes when TD Liquid files were changed.
176
+ - Desktop/mobile differences use explicit settings where needed.
177
+ - Invalid or legacy states are normalized defensively.
178
+ - Markup renders only the active structure.
179
+ - CSS uses BEM modifier classes for discrete state and variables for dynamic values.
180
+ - Inline CSS variables are used only when necessary.
181
+ - Accessibility requirements are satisfied.
182
+ - Required assets are rendered where needed.
183
+ - Schema follows translation and visibility rules.
184
+ - All changes are logged in `docs/changes.md`.
@@ -0,0 +1,10 @@
1
+ # Horizon Component Library Agent
2
+
3
+ This folder contains the reusable agent policy and helper script imported from `../HorizonComponentLibrary`.
4
+
5
+ ## Files
6
+ - `AGENTS.md`: Theory Digital agent rules for Horizon component-library section work.
7
+ - `scripts/td-guard.sh`: Guard script referenced by the agent rules.
8
+
9
+ ## Related Skill
10
+ - `skills/td-js-vanilla-rules/`: JavaScript standards skill referenced by this agent (`$td-js-vanilla-rules`).
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ cd "$ROOT_DIR"
6
+
7
+ if ! command -v rg >/dev/null 2>&1; then
8
+ echo "ERROR: ripgrep (rg) is required for td-guard checks."
9
+ exit 1
10
+ fi
11
+
12
+ changed_files=()
13
+ while IFS= read -r file; do
14
+ changed_files+=("$file")
15
+ done < <(
16
+ {
17
+ git diff --name-only --diff-filter=ACMRTUXB HEAD
18
+ git ls-files --others --exclude-standard
19
+ } | awk 'NF' | awk '!seen[$0]++'
20
+ )
21
+
22
+ td_targets=()
23
+ for file in "${changed_files[@]}"; do
24
+ case "$file" in
25
+ sections/td-*.liquid|blocks/td-*.liquid|blocks/_td-*.liquid|snippets/td-*.liquid)
26
+ if [[ -f "$file" ]]; then
27
+ td_targets+=("$file")
28
+ fi
29
+ ;;
30
+ esac
31
+ done
32
+
33
+ if [[ "${#td_targets[@]}" -eq 0 ]]; then
34
+ echo "td-guard: no changed TD liquid files to validate."
35
+ exit 0
36
+ fi
37
+
38
+ schema_default_pattern='(section|block)\.settings\.[A-Za-z0-9_]+\s*\|\s*default\s*:'
39
+
40
+ schema_default_hits="$(rg -n --pcre2 "$schema_default_pattern" "${td_targets[@]}" || true)"
41
+ if [[ -n "$schema_default_hits" ]]; then
42
+ echo "td-guard: FAIL - redundant schema fallback detected in changed TD files."
43
+ echo "Rule: do not use '| default:' with schema-backed section/block settings."
44
+ echo ""
45
+ echo "$schema_default_hits"
46
+ exit 1
47
+ fi
48
+
49
+ echo "td-guard: PASS"
package/bin/cli.js ADDED
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const readline = require('readline');
7
+
8
+ const TOOLKIT_ROOT = path.resolve(__dirname, '..');
9
+ const SKILLS_DIR = path.join(TOOLKIT_ROOT, 'skills');
10
+ const AGENTS_DIR = path.join(TOOLKIT_ROOT, 'agents');
11
+ const TARGET_ROOT = process.cwd();
12
+ const INSTALL_TARGETS = [
13
+ { label: 'claude', root: '.claude' },
14
+ { label: 'agents', root: '.agents' }
15
+ ];
16
+
17
+ function copyDir(src, dest) {
18
+ const srcStat = fs.statSync(src);
19
+ fs.mkdirSync(dest, { recursive: true, mode: srcStat.mode });
20
+ for (const entry of fs.readdirSync(src)) {
21
+ const srcPath = path.join(src, entry);
22
+ const destPath = path.join(dest, entry);
23
+ const entryStat = fs.statSync(srcPath);
24
+ if (entryStat.isDirectory()) {
25
+ copyDir(srcPath, destPath);
26
+ } else {
27
+ fs.copyFileSync(srcPath, destPath);
28
+ fs.chmodSync(destPath, entryStat.mode);
29
+ }
30
+ }
31
+ }
32
+
33
+ function getAvailable(dir) {
34
+ if (!fs.existsSync(dir)) return [];
35
+ return fs.readdirSync(dir).filter(d =>
36
+ fs.statSync(path.join(dir, d)).isDirectory()
37
+ );
38
+ }
39
+
40
+ function readFrontmatterField(mdPath, field) {
41
+ if (!fs.existsSync(mdPath)) return '';
42
+ const content = fs.readFileSync(mdPath, 'utf8');
43
+ const match = content.match(new RegExp(`^${field}:\\s*(.+)$`, 'm'));
44
+ return match ? match[1].trim() : '';
45
+ }
46
+
47
+ function installSkill(name) {
48
+ const src = path.join(SKILLS_DIR, name);
49
+ if (!fs.existsSync(src)) {
50
+ console.error(` [error] Skill "${name}" not found.`);
51
+ return false;
52
+ }
53
+ for (const target of INSTALL_TARGETS) {
54
+ const dest = path.join(TARGET_ROOT, target.root, 'skills', name);
55
+ copyDir(src, dest);
56
+ console.log(` [skill] ${name} -> ${target.root}/skills/${name}/`);
57
+ }
58
+ return true;
59
+ }
60
+
61
+ function installAgent(name) {
62
+ const src = path.join(AGENTS_DIR, name);
63
+ if (!fs.existsSync(src)) {
64
+ console.error(` [error] Agent pack "${name}" not found.`);
65
+ return false;
66
+ }
67
+ for (const target of INSTALL_TARGETS) {
68
+ const dest = path.join(TARGET_ROOT, target.root, 'agents', name);
69
+ copyDir(src, dest);
70
+ console.log(` [agent] ${name} -> ${target.root}/agents/${name}/`);
71
+ }
72
+ return true;
73
+ }
74
+
75
+ function printList() {
76
+ const skills = getAvailable(SKILLS_DIR);
77
+ const agents = getAvailable(AGENTS_DIR);
78
+
79
+ console.log('\nSkills:');
80
+ for (const name of skills) {
81
+ const desc = readFrontmatterField(path.join(SKILLS_DIR, name, 'SKILL.md'), 'description');
82
+ const truncated = desc.length > 72 ? desc.slice(0, 72) + '...' : desc;
83
+ console.log(` ${name}`);
84
+ if (truncated) console.log(` ${truncated}`);
85
+ }
86
+
87
+ console.log('\nAgent Packs:');
88
+ for (const name of agents) {
89
+ console.log(` ${name}`);
90
+ }
91
+ console.log('');
92
+ }
93
+
94
+ function buildMenu() {
95
+ const skills = getAvailable(SKILLS_DIR).map(name => ({ type: 'skill', name }));
96
+ const agents = getAvailable(AGENTS_DIR).map(name => ({ type: 'agent', name }));
97
+ return [...skills, ...agents];
98
+ }
99
+
100
+ function installItems(items) {
101
+ for (const item of items) {
102
+ if (item.type === 'skill') installSkill(item.name);
103
+ else installAgent(item.name);
104
+ }
105
+ }
106
+
107
+ async function interactiveInstall() {
108
+ const menu = buildMenu();
109
+ if (menu.length === 0) {
110
+ console.log('No skills or agent packs available.');
111
+ return;
112
+ }
113
+
114
+ console.log('\nAvailable (enter numbers separated by spaces, or "all"):\n');
115
+ menu.forEach((item, i) => {
116
+ const label = item.type === 'skill' ? 'skill' : 'agent';
117
+ console.log(` [${i + 1}] ${label}: ${item.name}`);
118
+ });
119
+ console.log('');
120
+
121
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
122
+ return new Promise(resolve => {
123
+ rl.question('Select items to install: ', answer => {
124
+ rl.close();
125
+ const trimmed = answer.trim().toLowerCase();
126
+ let selected;
127
+ if (trimmed === 'all') {
128
+ selected = menu;
129
+ } else {
130
+ const indices = trimmed.split(/\s+/).map(n => parseInt(n, 10) - 1);
131
+ selected = indices.filter(i => i >= 0 && i < menu.length).map(i => menu[i]);
132
+ }
133
+ console.log('');
134
+ installItems(selected);
135
+ resolve();
136
+ });
137
+ });
138
+ }
139
+
140
+ function resolveNames(names) {
141
+ const skills = getAvailable(SKILLS_DIR);
142
+ const agents = getAvailable(AGENTS_DIR);
143
+ const items = [];
144
+ for (const name of names) {
145
+ if (skills.includes(name)) {
146
+ items.push({ type: 'skill', name });
147
+ } else if (agents.includes(name)) {
148
+ items.push({ type: 'agent', name });
149
+ } else {
150
+ console.error(` [error] "${name}" not found as a skill or agent pack.`);
151
+ }
152
+ }
153
+ return items;
154
+ }
155
+
156
+ async function main() {
157
+ const args = process.argv.slice(2);
158
+
159
+ if (args.includes('--help') || args.includes('-h')) {
160
+ console.log(`
161
+ Usage:
162
+ npx td-ai-tools Interactive install
163
+ npx td-ai-tools list List available skills and agent packs
164
+ npx td-ai-tools install Interactive install
165
+ npx td-ai-tools install --all Install everything
166
+ npx td-ai-tools install <name...> Install specific skills or agent packs
167
+
168
+ Skills are installed to: .claude/skills/<name>/
169
+ .agents/skills/<name>/
170
+ Agent packs installed to: .claude/agents/<name>/
171
+ .agents/agents/<name>/
172
+ `);
173
+ return;
174
+ }
175
+
176
+ const cmd = args[0];
177
+ console.log('AgentToolkit');
178
+ console.log('------------');
179
+
180
+ if (!cmd || cmd === 'install' && args.length === 1) {
181
+ await interactiveInstall();
182
+ return;
183
+ }
184
+
185
+ if (cmd === 'list') {
186
+ printList();
187
+ return;
188
+ }
189
+
190
+ if (cmd === 'install') {
191
+ const rest = args.slice(1);
192
+ if (rest[0] === '--all') {
193
+ console.log('');
194
+ installItems(buildMenu());
195
+ } else {
196
+ console.log('');
197
+ installItems(resolveNames(rest));
198
+ }
199
+ return;
200
+ }
201
+
202
+ console.error(`Unknown command: "${cmd}". Run with --help for usage.`);
203
+ process.exit(1);
204
+ }
205
+
206
+ main().catch(err => {
207
+ console.error(err.message);
208
+ process.exit(1);
209
+ });
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "td-ai-tools",
3
+ "version": "1.0.2",
4
+ "description": "Install agent skills and packs into your project",
5
+ "scripts": {
6
+ "smoke:install": "./scripts/smoke-install.sh"
7
+ },
8
+ "bin": {
9
+ "td-ai-tools": "bin/cli.js",
10
+ "agent-toolkit": "bin/cli.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "scripts/",
15
+ "skills/",
16
+ "agents/"
17
+ ],
18
+ "engines": {
19
+ "node": ">=16"
20
+ },
21
+ "keywords": ["claude", "agents", "skills", "shopify", "theory-digital"],
22
+ "license": "MIT"
23
+ }
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ tmpdir="$(mktemp -d "${TMPDIR:-/tmp}/agent-toolkit-smoke.XXXXXX")"
6
+ cache_dir="$tmpdir/npm-cache"
7
+ project_dir="$tmpdir/project"
8
+
9
+ cleanup() {
10
+ rm -rf "$tmpdir"
11
+ }
12
+
13
+ trap cleanup EXIT
14
+
15
+ mkdir -p "$project_dir"
16
+
17
+ pushd "$tmpdir" >/dev/null
18
+ tarball="$(npm pack --quiet --cache "$cache_dir" "$repo_root")"
19
+ popd >/dev/null
20
+
21
+ tarball_path="$tmpdir/$tarball"
22
+
23
+ pushd "$project_dir" >/dev/null
24
+ npm exec --yes --cache "$cache_dir" --package "$tarball_path" td-ai-tools install pr-solver horizon-component-library
25
+ popd >/dev/null
26
+
27
+ required_paths=(
28
+ "$project_dir/.claude/skills/pr-solver/SKILL.md"
29
+ "$project_dir/.agents/skills/pr-solver/SKILL.md"
30
+ "$project_dir/.claude/agents/horizon-component-library/AGENTS.md"
31
+ "$project_dir/.agents/agents/horizon-component-library/AGENTS.md"
32
+ )
33
+
34
+ for required_path in "${required_paths[@]}"; do
35
+ if [[ ! -f "$required_path" ]]; then
36
+ echo "Missing expected installed file: $required_path" >&2
37
+ exit 1
38
+ fi
39
+ done
40
+
41
+ required_executables=(
42
+ "$project_dir/.claude/agents/horizon-component-library/scripts/td-guard.sh"
43
+ "$project_dir/.agents/agents/horizon-component-library/scripts/td-guard.sh"
44
+ )
45
+
46
+ for required_executable in "${required_executables[@]}"; do
47
+ if [[ ! -x "$required_executable" ]]; then
48
+ echo "Expected executable bit on: $required_executable" >&2
49
+ exit 1
50
+ fi
51
+ done
52
+
53
+ echo "Smoke install passed."
54
+ echo "Verified packaged install into:"
55
+ echo " $project_dir/.claude"
56
+ echo " $project_dir/.agents"
@@ -0,0 +1,15 @@
1
+ # skills
2
+
3
+ ## Available Skills
4
+ - `cache-reset`: Clear and warm Laravel and Statamic caches after content/template changes.
5
+ - `horizon-component-migration`: Bundle Horizon components and recursive dependencies into a migration package for another theme.
6
+ - `pr-solver`: Resolve unresolved GitHub PR review threads with GraphQL-driven workflow.
7
+ - `pull-request`: Generate structured pull request descriptions for Shopify theme work.
8
+ - `td-js-vanilla-rules`: Theory Digital vanilla JavaScript standards for Shopify themes.
9
+ - `td-review`: Multi-agent PR review that produces a findings report with TD compliance scoring.
10
+
11
+ ## Skill Structure Convention
12
+ - `<skill-name>/SKILL.md`
13
+ - `<skill-name>/agents/openai.yaml`
14
+ - `<skill-name>/scripts/*` (optional)
15
+ - `<skill-name>/references/*` (optional)
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: cache-reset
3
+ description: Clear and warm Laravel and Statamic caches after content or template changes.
4
+ alwaysApply: false
5
+ ---
6
+
7
+ Use this skill when the user asks to reset cache, clear stale Statamic output, or warm cache after deployments.
8
+
9
+ Run from project root in this order:
10
+
11
+ ```bash
12
+ php artisan cache:clear
13
+ php artisan config:cache
14
+ php artisan route:cache
15
+ php please stache:warm
16
+ ```
17
+
18
+ After running, report which commands succeeded and include any failing command output verbatim.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Cache Reset"
3
+ short_description: "Reset Laravel and Statamic caches"
4
+ default_prompt: "Reset Laravel and Statamic caches"