@leejungkiin/awkit 1.5.1 → 1.5.3

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 (63) hide show
  1. package/bin/awk.js +152 -139
  2. package/package.json +1 -1
  3. package/skill-packs/ads-management/pack.json +8 -0
  4. package/skill-packs/mobile-android/pack.json +2 -6
  5. package/skill-packs/neural-memory/pack.json +2 -2
  6. package/skill-packs/reverse-engineering/pack.json +9 -0
  7. package/workflows/mobile/reverse-android-build.md +0 -222
  8. package/workflows/mobile/reverse-android-design.md +0 -139
  9. package/workflows/mobile/reverse-android-discover.md +0 -150
  10. package/workflows/mobile/reverse-android.md +0 -143
  11. package/workflows/mobile/reverse-ios-build.md +0 -240
  12. package/workflows/mobile/reverse-ios-design.md +0 -112
  13. package/workflows/mobile/reverse-ios-discover.md +0 -120
  14. package/workflows/mobile/reverse-ios.md +0 -152
  15. /package/{skills → skill-packs/ads-management/skills}/admob-roas/SKILL.md +0 -0
  16. /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-analyst.md +0 -0
  17. /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-audit.md +0 -0
  18. /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-creative.md +0 -0
  19. /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-full-optimization.md +0 -0
  20. /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-optimize.md +0 -0
  21. /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-plan.md +0 -0
  22. /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-targeting.md +0 -0
  23. /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-user-analysis.md +0 -0
  24. /package/{workflows/ads → skill-packs/ads-management/workflows}/adsExpert.md +0 -0
  25. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/SKILL.md +0 -0
  26. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/api-extraction-patterns.md +0 -0
  27. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/call-flow-analysis.md +0 -0
  28. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/fernflower-usage.md +0 -0
  29. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/jadx-usage.md +0 -0
  30. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/setup-guide.md +0 -0
  31. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/check-deps.sh +0 -0
  32. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/decompile.sh +0 -0
  33. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/find-api-calls.sh +0 -0
  34. /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/install-dep.sh +0 -0
  35. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/SKILL.md +0 -0
  36. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/examples/getting-started/tech-stack.md +0 -0
  37. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/examples/pipeline/data-ui-parity.md +0 -0
  38. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/examples/pipeline/scanner-and-bootstrap.md +0 -0
  39. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/library-patterns.md +0 -0
  40. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-0-discovery.md +0 -0
  41. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-1-architecture.md +0 -0
  42. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-2-blueprint-ui.md +0 -0
  43. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-2-blueprint.md +0 -0
  44. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-3-build.md +0 -0
  45. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-3-logic-build.md +0 -0
  46. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/smali-reading-guide.md +0 -0
  47. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/templates/app-map.md +0 -0
  48. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/templates/architecture.md +0 -0
  49. /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/templates/blueprint.md +0 -0
  50. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-build.md +0 -0
  51. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-design.md +0 -0
  52. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-discover.md +0 -0
  53. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-scan.md +0 -0
  54. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android.md +0 -0
  55. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-build.md +0 -0
  56. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-design.md +0 -0
  57. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-discover.md +0 -0
  58. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-scan.md +0 -0
  59. /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios.md +0 -0
  60. /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-config.md +0 -0
  61. /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-flow.md +0 -0
  62. /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-interstitial.md +0 -0
  63. /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-native.md +0 -0
package/bin/awk.js CHANGED
@@ -522,7 +522,7 @@ function cmdInstall(args = []) {
522
522
  } else if (args.length > 0 && !args[0].startsWith('-') && args[0] !== 'all' && args[0] !== '--update') {
523
523
  legacyArg = args[0];
524
524
  }
525
-
525
+
526
526
  if (legacyArg && PLATFORMS[legacyArg] && !selectedPlatforms.includes(legacyArg)) {
527
527
  selectedPlatforms.push(legacyArg);
528
528
  }
@@ -543,7 +543,7 @@ function cmdInstall(args = []) {
543
543
  log(` 5. All of the above`);
544
544
  log(`${C.gray}Press Enter to install only the active platform: ${PLATFORMS[defaultPlatform].name}.${C.reset}`);
545
545
  const choice = promptChoice('Choice', defaultChoice).trim().toLowerCase();
546
-
546
+
547
547
  if (choice === '5' || choice === 'all') {
548
548
  selectedPlatforms = Object.keys(PLATFORMS);
549
549
  } else {
@@ -587,73 +587,73 @@ function cmdInstall(args = []) {
587
587
  checkSymphony({ silent: platform !== selectedPlatforms[0] });
588
588
 
589
589
  // 1. Ensure target dirs exist
590
- info('Creating directories...');
591
- const dirKeys = Object.values(plat.dirs);
592
- for (const dir of dirKeys) {
593
- const fullPath = path.join(target, dir);
594
- if (!fs.existsSync(fullPath)) {
595
- fs.mkdirSync(fullPath, { recursive: true });
596
- }
597
- }
598
- ok('Directories ready');
599
-
600
- // 2. Sync rules (platform-specific)
601
- if (platform === 'antigravity') {
602
- info('Syncing GEMINI.md...');
603
- syncGeminiMd();
604
- } else if (platform === 'cline') {
605
- info('Generating Cline global rules...');
606
- generateClineRules(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
607
- } else if (platform === 'codex') {
608
- info('Generating Codex AGENTS.md...');
609
- generateCodexAgentsMd(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
610
- } else if (platform === 'claude') {
611
- info('Generating Claude Code CLAUDE.md...');
612
- const claudeTemplateSrc = path.join(AWK_ROOT, 'core', 'CLAUDE.md');
613
- const claudeRulesDest = path.join(target, plat.rulesFile);
614
- generateClaudeRules(claudeTemplateSrc, claudeRulesDest);
615
- }
616
-
617
- // 3. Backup and install workflows
618
- if (plat.dirs.workflows) {
619
- info('Installing workflows...');
620
- const wfSrc = path.join(AWK_ROOT, 'workflows');
621
- const wfDest = path.join(target, plat.dirs.workflows);
622
-
623
- // Backup existing workflows
624
- if (fs.existsSync(wfDest)) {
625
- const backupDir = getPlatformBackupRoot(platform);
626
- if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
627
-
628
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
629
- const zipFile = path.join(backupDir, `workflows_${timestamp}.bak.zip`);
630
- try {
631
- execSync(`zip -r "${zipFile}" .`, { cwd: wfDest, stdio: 'ignore' });
632
- dim(`Backup: ${zipFile}`);
633
- } catch (e) {
634
- warn(`Failed to create backup: ${e.message}`);
590
+ info('Creating directories...');
591
+ const dirKeys = Object.values(plat.dirs);
592
+ for (const dir of dirKeys) {
593
+ const fullPath = path.join(target, dir);
594
+ if (!fs.existsSync(fullPath)) {
595
+ fs.mkdirSync(fullPath, { recursive: true });
635
596
  }
636
597
  }
598
+ ok('Directories ready');
599
+
600
+ // 2. Sync rules (platform-specific)
601
+ if (platform === 'antigravity') {
602
+ info('Syncing GEMINI.md...');
603
+ syncGeminiMd();
604
+ } else if (platform === 'cline') {
605
+ info('Generating Cline global rules...');
606
+ generateClineRules(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
607
+ } else if (platform === 'codex') {
608
+ info('Generating Codex AGENTS.md...');
609
+ generateCodexAgentsMd(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
610
+ } else if (platform === 'claude') {
611
+ info('Generating Claude Code CLAUDE.md...');
612
+ const claudeTemplateSrc = path.join(AWK_ROOT, 'core', 'CLAUDE.md');
613
+ const claudeRulesDest = path.join(target, plat.rulesFile);
614
+ generateClaudeRules(claudeTemplateSrc, claudeRulesDest);
615
+ }
616
+
617
+ // 3. Backup and install workflows
618
+ if (plat.dirs.workflows) {
619
+ info('Installing workflows...');
620
+ const wfSrc = path.join(AWK_ROOT, 'workflows');
621
+ const wfDest = path.join(target, plat.dirs.workflows);
622
+
623
+ // Backup existing workflows
624
+ if (fs.existsSync(wfDest)) {
625
+ const backupDir = getPlatformBackupRoot(platform);
626
+ if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
627
+
628
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
629
+ const zipFile = path.join(backupDir, `workflows_${timestamp}.bak.zip`);
630
+ try {
631
+ execSync(`zip -r "${zipFile}" .`, { cwd: wfDest, stdio: 'ignore' });
632
+ dim(`Backup: ${zipFile}`);
633
+ } catch (e) {
634
+ warn(`Failed to create backup: ${e.message}`);
635
+ }
636
+ }
637
637
 
638
- if (platform === 'cline') {
639
- generateClineWorkflows(wfSrc, wfDest);
640
- } else if (platform !== 'codex') {
641
- const wfCount = flattenWorkflows(wfSrc, wfDest);
642
- ok(`${wfCount} workflows installed`);
638
+ if (platform === 'cline') {
639
+ generateClineWorkflows(wfSrc, wfDest);
640
+ } else if (platform !== 'codex') {
641
+ const wfCount = flattenWorkflows(wfSrc, wfDest);
642
+ ok(`${wfCount} workflows installed`);
643
+ }
643
644
  }
644
- }
645
645
 
646
- // 4. Copy AGENTS.md
647
- if (platform === 'antigravity' && plat.dirs.workflows) {
648
- const agentsSrc = path.join(AWK_ROOT, 'core', 'AGENTS.md');
649
- const agentsDest = path.join(target, plat.dirs.workflows, 'AGENTS.md');
650
- if (fs.existsSync(agentsSrc)) {
651
- fs.copyFileSync(agentsSrc, agentsDest);
652
- ok('AGENTS.md installed');
646
+ // 4. Copy AGENTS.md
647
+ if (platform === 'antigravity' && plat.dirs.workflows) {
648
+ const agentsSrc = path.join(AWK_ROOT, 'core', 'AGENTS.md');
649
+ const agentsDest = path.join(target, plat.dirs.workflows, 'AGENTS.md');
650
+ if (fs.existsSync(agentsSrc)) {
651
+ fs.copyFileSync(agentsSrc, agentsDest);
652
+ ok('AGENTS.md installed');
653
+ }
653
654
  }
654
- }
655
655
 
656
- // 5. Copy skills
656
+ // 5. Copy skills
657
657
  if (plat.dirs.skills) {
658
658
  info('Installing skills...');
659
659
  const skillsSrc = path.join(AWK_ROOT, 'skills');
@@ -673,36 +673,36 @@ function cmdInstall(args = []) {
673
673
  }
674
674
  }
675
675
 
676
- // 6. Copy orchestrator
677
- if (platform === 'antigravity') {
678
- const orchSrc = path.join(AWK_ROOT, 'core', 'orchestrator.md');
679
- const orchDestDir = path.join(target, plat.dirs.skills, 'orchestrator');
680
- if (!fs.existsSync(orchDestDir)) fs.mkdirSync(orchDestDir, { recursive: true });
681
- fs.copyFileSync(orchSrc, path.join(orchDestDir, 'SKILL.md'));
682
- ok('Orchestrator skill installed');
683
- }
676
+ // 6. Copy orchestrator
677
+ if (platform === 'antigravity') {
678
+ const orchSrc = path.join(AWK_ROOT, 'core', 'orchestrator.md');
679
+ const orchDestDir = path.join(target, plat.dirs.skills, 'orchestrator');
680
+ if (!fs.existsSync(orchDestDir)) fs.mkdirSync(orchDestDir, { recursive: true });
681
+ fs.copyFileSync(orchSrc, path.join(orchDestDir, 'SKILL.md'));
682
+ ok('Orchestrator skill installed');
683
+ }
684
684
 
685
- // 7. Copy schemas (always overwrite)
686
- if (plat.dirs.schemas) {
687
- info('Installing schemas...');
688
- const schemaSrc = path.join(AWK_ROOT, 'schemas');
689
- const schemaDest = path.join(target, plat.dirs.schemas);
690
- const schemaCount = copyDirRecursive(schemaSrc, schemaDest);
691
- ok(`${schemaCount} schemas installed`);
692
- }
685
+ // 7. Copy schemas (always overwrite)
686
+ if (plat.dirs.schemas) {
687
+ info('Installing schemas...');
688
+ const schemaSrc = path.join(AWK_ROOT, 'schemas');
689
+ const schemaDest = path.join(target, plat.dirs.schemas);
690
+ const schemaCount = copyDirRecursive(schemaSrc, schemaDest);
691
+ ok(`${schemaCount} schemas installed`);
692
+ }
693
693
 
694
- // 8. Copy templates (don't overwrite existing)
695
- if (plat.dirs.templates) {
696
- info('Installing templates...');
697
- const tmplSrc = path.join(AWK_ROOT, 'templates');
698
- const tmplDest = path.join(target, plat.dirs.templates);
699
- const tmplCount = copyDirRecursive(tmplSrc, tmplDest, { overwrite: false });
700
- ok(`${tmplCount} templates installed`);
701
- }
694
+ // 8. Copy templates (don't overwrite existing)
695
+ if (plat.dirs.templates) {
696
+ info('Installing templates...');
697
+ const tmplSrc = path.join(AWK_ROOT, 'templates');
698
+ const tmplDest = path.join(target, plat.dirs.templates);
699
+ const tmplCount = copyDirRecursive(tmplSrc, tmplDest, { overwrite: false });
700
+ ok(`${tmplCount} templates installed`);
701
+ }
702
702
 
703
- // 9. Save version
704
- fs.writeFileSync(plat.versionFile, AWK_VERSION);
705
- ok(`Version ${AWK_VERSION} saved`);
703
+ // 9. Save version
704
+ fs.writeFileSync(plat.versionFile, AWK_VERSION);
705
+ ok(`Version ${AWK_VERSION} saved`);
706
706
 
707
707
  // 10. Install default skill packs
708
708
  const defaultPacks = installDefaultPacks();
@@ -732,35 +732,35 @@ function cmdInstall(args = []) {
732
732
  ok(`Install state saved (${desiredSkills.size} active skills)`);
733
733
 
734
734
  // 11. Summary
735
- log('');
736
- log(`${C.gray}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}`);
737
- log(`${C.yellow}${C.bold}🎉 AWK v${AWK_VERSION} installed for ${plat.name}!${C.reset}`);
738
- log('');
739
- dim(`Platform: ${plat.name}`);
740
- if (plat.dirs.workflows) dim(`Workflows: ${path.join(target, plat.dirs.workflows)}`);
741
- if (plat.dirs.skills) dim(`Skills: ${path.join(target, plat.dirs.skills)}`);
742
- if (plat.dirs.schemas) dim(`Schemas: ${path.join(target, plat.dirs.schemas)}`);
743
- if (plat.dirs.templates) dim(`Templates: ${path.join(target, plat.dirs.templates)}`);
744
- if (plat.dirs.agents) dim(`Agents: ${path.join(target, plat.dirs.agents)}`);
735
+ log('');
736
+ log(`${C.gray}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}`);
737
+ log(`${C.yellow}${C.bold}🎉 AWK v${AWK_VERSION} installed for ${plat.name}!${C.reset}`);
738
+ log('');
739
+ dim(`Platform: ${plat.name}`);
740
+ if (plat.dirs.workflows) dim(`Workflows: ${path.join(target, plat.dirs.workflows)}`);
741
+ if (plat.dirs.skills) dim(`Skills: ${path.join(target, plat.dirs.skills)}`);
742
+ if (plat.dirs.schemas) dim(`Schemas: ${path.join(target, plat.dirs.schemas)}`);
743
+ if (plat.dirs.templates) dim(`Templates: ${path.join(target, plat.dirs.templates)}`);
744
+ if (plat.dirs.agents) dim(`Agents: ${path.join(target, plat.dirs.agents)}`);
745
745
 
746
- if (plat.rulesFile) {
747
- dim(`Global Rules: ${plat.rulesFile}`);
748
- }
749
- if (activePacks.length > 0) {
750
- dim(`Packs: ${activePacks.join(', ')}`);
751
- }
752
- if (platform === 'antigravity') {
753
- dim(`Symphony: task tracking ready`);
754
- }
755
- log('');
746
+ if (plat.rulesFile) {
747
+ dim(`Global Rules: ${plat.rulesFile}`);
748
+ }
749
+ if (activePacks.length > 0) {
750
+ dim(`Packs: ${activePacks.join(', ')}`);
751
+ }
752
+ if (platform === 'antigravity') {
753
+ dim(`Symphony: task tracking ready`);
754
+ }
755
+ log('');
756
756
 
757
- if (platform === 'antigravity') {
758
- log(`${C.cyan}👉 Run 'awkit init' in any project to initialize it.${C.reset}`);
759
- } else if (platform === 'codex') {
760
- log(`${C.cyan}👉 Type '$skill' in Codex to invoke skills.${C.reset}`);
761
- }
762
- log(`${C.cyan}👉 Run 'awkit doctor' to verify installation.${C.reset}`);
763
- log('');
757
+ if (platform === 'antigravity') {
758
+ log(`${C.cyan}👉 Run 'awkit init' in any project to initialize it.${C.reset}`);
759
+ } else if (platform === 'codex') {
760
+ log(`${C.cyan}👉 Type '$skill' in Codex to invoke skills.${C.reset}`);
761
+ }
762
+ log(`${C.cyan}👉 Run 'awkit doctor' to verify installation.${C.reset}`);
763
+ log('');
764
764
  } // End of platform loop
765
765
  }
766
766
 
@@ -987,7 +987,7 @@ function cmdBrowser(args) {
987
987
  }
988
988
 
989
989
  const recordingsDir = path.join(TARGETS.antigravity, 'browser_recordings');
990
-
990
+
991
991
  log('');
992
992
  log(`${C.cyan}${C.bold}🧹 AWK Browser Cleanup${C.reset}`);
993
993
  log('');
@@ -1016,7 +1016,7 @@ function cmdBrowser(args) {
1016
1016
  } else {
1017
1017
  log(`Cleaning browser recordings older than ${C.yellow}${keepDays} days${C.reset}...`);
1018
1018
  }
1019
-
1019
+
1020
1020
  const now = Date.now();
1021
1021
  const cutoff = now - (keepDays * 24 * 60 * 60 * 1000);
1022
1022
  let deletedCount = 0;
@@ -1772,7 +1772,7 @@ async function cmdAdmin() {
1772
1772
  stdio: 'ignore'
1773
1773
  });
1774
1774
  child.unref();
1775
-
1775
+
1776
1776
  info('Vui lòng đợi 3 giây để service khởi động...');
1777
1777
  await new Promise(r => setTimeout(r, 3000));
1778
1778
  }
@@ -1805,9 +1805,9 @@ async function cmdRestart() {
1805
1805
  // Probably no process running on port 3100
1806
1806
  dim('Không tìm thấy service đang chạy.');
1807
1807
  }
1808
-
1808
+
1809
1809
  await new Promise(r => setTimeout(r, 1000));
1810
-
1810
+
1811
1811
  // Auto-build production bundle so code changes take effect
1812
1812
  const symphonyDir = path.join(AWK_ROOT, '..', 'symphony');
1813
1813
  if (fs.existsSync(path.join(symphonyDir, 'package.json'))) {
@@ -1820,17 +1820,17 @@ async function cmdRestart() {
1820
1820
  dim(buildErr.message?.slice(0, 200));
1821
1821
  }
1822
1822
  }
1823
-
1823
+
1824
1824
  info('Đang khởi động lại service ngầm...');
1825
1825
  const child = spawn('symphony', ['start'], {
1826
1826
  detached: true,
1827
1827
  stdio: 'ignore'
1828
1828
  });
1829
1829
  child.unref();
1830
-
1830
+
1831
1831
  info('Vui lòng đợi 3 giây để service khởi động...');
1832
1832
  await new Promise(r => setTimeout(r, 3000));
1833
-
1833
+
1834
1834
  log(`${C.green}✅ Restart thành công!${C.reset}`);
1835
1835
  } catch (e) {
1836
1836
  err('Lỗi khi restart service: ' + e.message);
@@ -1958,8 +1958,8 @@ function cmdHelp() {
1958
1958
  log(` ${C.gray}awkit harvest # Pull live edits → repo${C.reset}`);
1959
1959
  log(` ${C.gray}awkit sync # harvest + install in one shot${C.reset}`);
1960
1960
  log('');
1961
- log(` ${C.cyan}# Enable NeuralMemory${C.reset}`);
1962
- log(` ${C.gray}awkit enable-pack neural-memory${C.reset}`);
1961
+ log(` ${C.cyan}# Enable Marketing Skills${C.reset}`);
1962
+ log(` ${C.gray}awkit enable-pack marketing${C.reset}`);
1963
1963
  log('');
1964
1964
  log(` ${C.cyan}# Repo${C.reset}`);
1965
1965
  log(` ${C.gray}https://github.com/babyskill/awk${C.reset}`);
@@ -2359,7 +2359,7 @@ async function cmdInit(forceFlag = false) {
2359
2359
  log('');
2360
2360
  warn('Trello API Key & Token are not set.');
2361
2361
  log(` 👉 To setup Trello integration, please get your credentials at: https://trello.com/app-key`);
2362
-
2362
+
2363
2363
  const readline = require('readline');
2364
2364
  const rl = readline.createInterface({
2365
2365
  input: process.stdin,
@@ -2388,14 +2388,14 @@ async function cmdInit(forceFlag = false) {
2388
2388
  if (!fs.existsSync(profilePath) && fs.existsSync(path.join(os.homedir(), '.bashrc'))) {
2389
2389
  profilePath = path.join(os.homedir(), '.bashrc');
2390
2390
  }
2391
-
2391
+
2392
2392
  const exportLines = `\n# Trello API Credentials for AWKit\nexport TRELLO_KEY="${apiKey}"\nexport TRELLO_TOKEN="${apiToken}"\n`;
2393
2393
  fs.appendFileSync(profilePath, exportLines);
2394
-
2394
+
2395
2395
  // Also inject into current process so immediate awkit trello calls work
2396
2396
  process.env.TRELLO_KEY = apiKey;
2397
2397
  process.env.TRELLO_TOKEN = apiToken;
2398
-
2398
+
2399
2399
  ok(`Credentials saved to ${path.basename(profilePath)} ✅`);
2400
2400
  log(` ${C.green}👉 Trello is ready! Credentials are active for this session and all future terminals.${C.reset}`);
2401
2401
  } else {
@@ -2470,7 +2470,7 @@ Additional project context can be found in:
2470
2470
  // ── 4.5. .gitignore ────────────────────────────────────────────────────────
2471
2471
  const gitignorePath = path.join(cwd, '.gitignore');
2472
2472
  const ignoreRules = ['log.txt', 'tmp/', '.gitnexus/', 'node_modules/'];
2473
-
2473
+
2474
2474
  if (fs.existsSync(gitignorePath)) {
2475
2475
  let content = fs.readFileSync(gitignorePath, 'utf8');
2476
2476
  let added = 0;
@@ -2549,6 +2549,19 @@ Additional project context can be found in:
2549
2549
  log(`${C.cyan}👉 Run 'symphony task list' to manage tasks.${C.reset}`);
2550
2550
  log(`${C.cyan}👉 Run 'npx gitnexus analyze' after major changes to refresh index.${C.reset}`);
2551
2551
  log('');
2552
+
2553
+ // ── 7. Open Documentation ───────────────────────────────────────────────────
2554
+ try {
2555
+ const platform = process.platform;
2556
+ let openCmd = 'xdg-open';
2557
+ if (platform === 'darwin') openCmd = 'open';
2558
+ else if (platform === 'win32') openCmd = 'start ""';
2559
+
2560
+ execSync(`${openCmd} "help.html"`, { cwd, stdio: 'ignore' });
2561
+ dim('Opened help.html in browser');
2562
+ } catch (e) {
2563
+ // Silently ignore if opening fails
2564
+ }
2552
2565
  }
2553
2566
 
2554
2567
  // ─── Telegram Bot API ─────────────────────────────────────────────────────────
@@ -3087,35 +3100,35 @@ function cmdTrello(args) {
3087
3100
  err("Credentials or config missing for REST API fallback.");
3088
3101
  break;
3089
3102
  }
3090
-
3103
+
3091
3104
  // 1. Get checklists
3092
3105
  const clRes = spawnSync('npx', ['--yes', 'trello-cli', 'card:checklists', '--board', cfgItem.board, '--list', cfgItem.list, '--card', cfgItem.card, '--format', 'json'], { env: { ...process.env, TRELLO_KEY: credItem.api_key, TRELLO_TOKEN: credItem.api_token }, encoding: 'utf-8' });
3093
-
3106
+
3094
3107
  if (clRes.status !== 0) {
3095
3108
  err(`Failed to get checklists: ${clRes.stderr || clRes.stdout}`);
3096
3109
  break;
3097
3110
  }
3098
-
3111
+
3099
3112
  try {
3100
3113
  // Sometime trello-cli outputs to stdout along with some other logs.
3101
3114
  // We extract the JSON array part.
3102
3115
  const outText = clRes.stdout;
3103
3116
  const jsonStr = outText.substring(outText.indexOf('['));
3104
3117
  const checklists = JSON.parse(jsonStr);
3105
-
3118
+
3106
3119
  if (!checklists || checklists.length === 0) {
3107
3120
  err("No checklists found on card. Create one first using 'awkit trello checklist <name>'.");
3108
3121
  break;
3109
3122
  }
3110
-
3123
+
3111
3124
  // Add to the LAST checklist (most recently appended usually)
3112
3125
  const targetChecklist = checklists[checklists.length - 1];
3113
3126
  const checklistId = targetChecklist.id;
3114
-
3127
+
3115
3128
  // 2. Add item via curl
3116
3129
  const url = `https://api.trello.com/1/checklists/${checklistId}/checkItems?name=${encodeURIComponent(text)}&key=${credItem.api_key}&token=${credItem.api_token}`;
3117
3130
  const addRes = spawnSync('curl', ['-s', '-X', 'POST', url], { encoding: 'utf-8' });
3118
-
3131
+
3119
3132
  const responseJson = JSON.parse(addRes.stdout);
3120
3133
  if (responseJson.id) {
3121
3134
  ok(`Item added successfully to checklist "${targetChecklist.name}".`);
@@ -3192,7 +3205,7 @@ function checkAutoUpdate() {
3192
3205
 
3193
3206
  function cmdServe(args) {
3194
3207
  const http = require('http');
3195
-
3208
+
3196
3209
  let port = 8080;
3197
3210
  let serveDir = process.cwd();
3198
3211
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leejungkiin/awkit",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
4
  "description": "Antigravity Workflow Kit. Unified AI agent orchestration system.",
5
5
  "main": "bin/awk.js",
6
6
  "bin": {
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "ads-management",
3
+ "auto_install": false,
4
+ "description": "App monetization strategies, ASO context, and AdMob ROAS/AARRR optimization",
5
+ "skills": [
6
+ "admob-roas"
7
+ ]
8
+ }
@@ -2,9 +2,5 @@
2
2
  "name": "mobile-android",
3
3
  "auto_install": false,
4
4
  "description": "Android development skills: Kotlin, Jetpack Compose, reverse engineering, AdMob ROAS, and APK analysis",
5
- "skills": [
6
- "smali-to-kotlin",
7
- "android-re-analyzer",
8
- "admob-roas"
9
- ]
10
- }
5
+ "skills": []
6
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neural-memory",
3
- "auto_install": false,
3
+ "auto_install": true,
4
4
  "description": "NeuralMemory-powered ambient brain sync with spreading activation recall",
5
5
  "skills": [
6
6
  "nm-memory-sync",
@@ -38,4 +38,4 @@
38
38
  "Claude Code": "Run: /plugin install neural-memory"
39
39
  }
40
40
  }
41
- }
41
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "reverse-engineering",
3
+ "auto_install": false,
4
+ "description": "Android & iOS remote engineering, decompilation, code porting, and smali modding capabilities",
5
+ "skills": [
6
+ "smali-to-kotlin",
7
+ "android-re-analyzer"
8
+ ]
9
+ }