@hidden-leaf/x-skill 1.0.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.
Files changed (53) hide show
  1. package/.env.example +50 -0
  2. package/CLAUDE.snippet.md +34 -0
  3. package/README.md +220 -0
  4. package/SKILL.md +265 -0
  5. package/dist/cache/store.d.ts +48 -0
  6. package/dist/cache/store.d.ts.map +1 -0
  7. package/dist/cache/store.js +381 -0
  8. package/dist/cache/store.js.map +1 -0
  9. package/dist/clients/types.d.ts +217 -0
  10. package/dist/clients/types.d.ts.map +1 -0
  11. package/dist/clients/types.js +77 -0
  12. package/dist/clients/types.js.map +1 -0
  13. package/dist/clients/x-client.d.ts +111 -0
  14. package/dist/clients/x-client.d.ts.map +1 -0
  15. package/dist/clients/x-client.js +421 -0
  16. package/dist/clients/x-client.js.map +1 -0
  17. package/dist/index.d.ts +20 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +52 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/skills/bookmarks/index.d.ts +79 -0
  22. package/dist/skills/bookmarks/index.d.ts.map +1 -0
  23. package/dist/skills/bookmarks/index.js +288 -0
  24. package/dist/skills/bookmarks/index.js.map +1 -0
  25. package/dist/skills/bookmarks/synthesize.d.ts +40 -0
  26. package/dist/skills/bookmarks/synthesize.d.ts.map +1 -0
  27. package/dist/skills/bookmarks/synthesize.js +164 -0
  28. package/dist/skills/bookmarks/synthesize.js.map +1 -0
  29. package/dist/skills/bookmarks/types.d.ts +71 -0
  30. package/dist/skills/bookmarks/types.d.ts.map +1 -0
  31. package/dist/skills/bookmarks/types.js +6 -0
  32. package/dist/skills/bookmarks/types.js.map +1 -0
  33. package/dist/utils/logger.d.ts +10 -0
  34. package/dist/utils/logger.d.ts.map +1 -0
  35. package/dist/utils/logger.js +43 -0
  36. package/dist/utils/logger.js.map +1 -0
  37. package/package.json +68 -0
  38. package/scripts/cache-report.ts +25 -0
  39. package/scripts/create-atlsk-ticket.ts +68 -0
  40. package/scripts/create-deep-dive-ticket.ts +66 -0
  41. package/scripts/create-jira-project.ts +31 -0
  42. package/scripts/create-launch-and-roadmap.ts +200 -0
  43. package/scripts/create-next-session.ts +71 -0
  44. package/scripts/create-roadmap.ts +150 -0
  45. package/scripts/debug-api.ts +45 -0
  46. package/scripts/debug-folder.ts +37 -0
  47. package/scripts/jira-close-v1-tickets.ts +83 -0
  48. package/scripts/jira-v1-close-and-post-v1.ts +272 -0
  49. package/scripts/oauth-flow.ts +216 -0
  50. package/scripts/postinstall.js +112 -0
  51. package/scripts/sync-test.ts +36 -0
  52. package/scripts/test-refresh-forced.ts +29 -0
  53. package/scripts/test-refresh.ts +25 -0
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Bookmark intelligence types
3
+ */
4
+ import type { Tweet, User, BookmarkFolder } from '../../clients/types.js';
5
+ /** A tweet with its author resolved from includes */
6
+ export interface EnrichedBookmark {
7
+ tweet: Tweet;
8
+ author: User | undefined;
9
+ /** Formatted display: "@username: text (likes, retweets)" */
10
+ formatted: string;
11
+ }
12
+ /** A folder with its tweets fetched and enriched */
13
+ export interface BookmarkFolderContents {
14
+ folder: BookmarkFolder;
15
+ bookmarks: EnrichedBookmark[];
16
+ fetchedAt: string;
17
+ }
18
+ export interface BriefOptions {
19
+ /** Folder name to scope the brief (if not provided, uses all bookmarks) */
20
+ folderName?: string;
21
+ /** Folder ID (resolved from folderName if not provided) */
22
+ folderId?: string;
23
+ /** Maximum tweets to include in the brief context (default: 50) */
24
+ maxTweets?: number;
25
+ /** Custom prompt to append to the brief generation */
26
+ customPrompt?: string;
27
+ /** HLN venture context — which venture(s) this research relates to */
28
+ hlnContext?: string[];
29
+ }
30
+ export interface ResearchBrief {
31
+ /** Folder or category this brief covers */
32
+ topic: string;
33
+ /** ISO timestamp of generation */
34
+ generatedAt: string;
35
+ /** Number of tweets analyzed */
36
+ tweetCount: number;
37
+ /** The synthesized markdown brief */
38
+ content: string;
39
+ /** Notable accounts referenced */
40
+ notableVoices: string[];
41
+ /** Key themes extracted */
42
+ themes: string[];
43
+ /** HLN relevance notes (which ventures/initiatives) */
44
+ hlnRelevance: string[];
45
+ }
46
+ export interface BookmarkListOutput {
47
+ folders: BookmarkFolder[];
48
+ totalFolders: number;
49
+ }
50
+ export interface BookmarkFetchOutput {
51
+ folder: string;
52
+ bookmarks: EnrichedBookmark[];
53
+ totalTweets: number;
54
+ uniqueAuthors: number;
55
+ }
56
+ export interface BookmarkBriefOutput {
57
+ brief: ResearchBrief;
58
+ /** Raw enriched bookmarks used as input */
59
+ sourceBookmarks: EnrichedBookmark[];
60
+ }
61
+ export interface SyncResult {
62
+ syncedAt: string;
63
+ totalFolders: number;
64
+ totalTweets: number;
65
+ folders: Array<{
66
+ name: string;
67
+ id: string;
68
+ tweetCount: number;
69
+ }>;
70
+ }
71
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/skills/bookmarks/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM1E,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,SAAS,CAAC;IACzB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oDAAoD;AACpD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uDAAuD;IACvD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAMD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,aAAa,CAAC;IACrB,2CAA2C;IAC3C,eAAe,EAAE,gBAAgB,EAAE,CAAC;CACrC;AAMD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Bookmark intelligence types
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/skills/bookmarks/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Structured logger for x-skill
3
+ */
4
+ export declare function createLogger(module: string): {
5
+ debug: (message: string, data?: Record<string, unknown>) => void;
6
+ info: (message: string, data?: Record<string, unknown>) => void;
7
+ warn: (message: string, data?: Record<string, unknown>) => void;
8
+ error: (message: string, data?: Record<string, unknown>) => void;
9
+ };
10
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwBH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM;qBAEtB,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBAGvC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBAGtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qBAGrC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;EAI1D"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * Structured logger for x-skill
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createLogger = createLogger;
7
+ const LEVELS = {
8
+ debug: 0,
9
+ info: 1,
10
+ warn: 2,
11
+ error: 3,
12
+ };
13
+ const currentLevel = process.env.LOG_LEVEL || 'info';
14
+ function shouldLog(level) {
15
+ return LEVELS[level] >= LEVELS[currentLevel];
16
+ }
17
+ function formatMessage(level, module, message, data) {
18
+ const timestamp = new Date().toISOString();
19
+ const prefix = `[${timestamp}] [${level.toUpperCase()}] [@hidden-leaf/x-skill:${module}]`;
20
+ const dataStr = data ? ` ${JSON.stringify(data)}` : '';
21
+ return `${prefix} ${message}${dataStr}`;
22
+ }
23
+ function createLogger(module) {
24
+ return {
25
+ debug: (message, data) => {
26
+ if (shouldLog('debug'))
27
+ console.debug(formatMessage('debug', module, message, data));
28
+ },
29
+ info: (message, data) => {
30
+ if (shouldLog('info'))
31
+ console.info(formatMessage('info', module, message, data));
32
+ },
33
+ warn: (message, data) => {
34
+ if (shouldLog('warn'))
35
+ console.warn(formatMessage('warn', module, message, data));
36
+ },
37
+ error: (message, data) => {
38
+ if (shouldLog('error'))
39
+ console.error(formatMessage('error', module, message, data));
40
+ },
41
+ };
42
+ }
43
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAwBH,oCAeC;AAnCD,MAAM,MAAM,GAA6B;IACvC,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,YAAY,GAAI,OAAO,CAAC,GAAG,CAAC,SAAsB,IAAI,MAAM,CAAC;AAEnE,SAAS,SAAS,CAAC,KAAe;IAChC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,aAAa,CAAC,KAAe,EAAE,MAAc,EAAE,OAAe,EAAE,IAA8B;IACrG,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,SAAS,MAAM,KAAK,CAAC,WAAW,EAAE,2BAA2B,MAAM,GAAG,CAAC;IAC1F,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,OAAO,GAAG,MAAM,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;AAC1C,CAAC;AAED,SAAgB,YAAY,CAAC,MAAc;IACzC,OAAO;QACL,KAAK,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE;YACzD,IAAI,SAAS,CAAC,OAAO,CAAC;gBAAE,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE;YACxD,IAAI,SAAS,CAAC,MAAM,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE;YACxD,IAAI,SAAS,CAAC,MAAM,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACpF,CAAC;QACD,KAAK,EAAE,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE;YACzD,IAAI,SAAS,CAAC,OAAO,CAAC;gBAAE,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACvF,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@hidden-leaf/x-skill",
3
+ "version": "1.0.0",
4
+ "description": "X (Twitter) bookmark intelligence skill for Claude Code — turn curated bookmarks into structured research briefs",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./SKILL.md": "./SKILL.md"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "scripts",
18
+ "SKILL.md",
19
+ "CLAUDE.snippet.md",
20
+ ".env.example"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "watch": "tsc --watch",
25
+ "lint": "eslint 'src/**/*.ts'",
26
+ "test": "jest --passWithNoTests",
27
+ "clean": "rm -rf dist",
28
+ "prepublishOnly": "npm run build",
29
+ "postinstall": "node scripts/postinstall.js"
30
+ },
31
+ "keywords": [
32
+ "x",
33
+ "twitter",
34
+ "bookmarks",
35
+ "claude-code",
36
+ "skill",
37
+ "research",
38
+ "intelligence"
39
+ ],
40
+ "author": "Hidden Leaf Networks",
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/Hidden-Leaf-Networks/x-skill.git"
45
+ },
46
+ "homepage": "https://github.com/Hidden-Leaf-Networks/x-skill#readme",
47
+ "dependencies": {
48
+ "@hidden-leaf/atlassian-skill": "^1.2.0",
49
+ "axios": "^1.6.0",
50
+ "axios-retry": "^4.0.0",
51
+ "better-sqlite3": "^12.8.0",
52
+ "dotenv": "^17.3.1"
53
+ },
54
+ "devDependencies": {
55
+ "@types/better-sqlite3": "^7.6.13",
56
+ "@types/jest": "^29.5.0",
57
+ "@types/node": "^20.10.0",
58
+ "@typescript-eslint/eslint-plugin": "^6.13.0",
59
+ "@typescript-eslint/parser": "^6.13.0",
60
+ "eslint": "^8.55.0",
61
+ "jest": "^29.7.0",
62
+ "ts-jest": "^29.1.0",
63
+ "typescript": "^5.3.0"
64
+ },
65
+ "engines": {
66
+ "node": ">=18.0.0"
67
+ }
68
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Report what's in the local cache vs what the folder IDs suggest.
3
+ */
4
+ import { createStoreFromEnv } from '../src/cache/store.js';
5
+
6
+ const store = createStoreFromEnv();
7
+ const folders = store.getFolders();
8
+ const stats = store.getStats();
9
+
10
+ console.log(`Cache: ${stats.tweets} tweets, ${stats.users} users, ${stats.folders} folders`);
11
+ console.log(`Last sync: ${stats.lastSync}\n`);
12
+
13
+ let totalLinked = 0;
14
+ for (const folder of folders) {
15
+ const tweets = store.getTweetsByFolder(folder.id);
16
+ const linked = tweets.length;
17
+ totalLinked += linked;
18
+ const hasTweet = tweets.filter(t => t.tweet.text && t.tweet.text.length > 0).length;
19
+ console.log(` ${folder.name.padEnd(25)} ${String(folder.tweet_count ?? '?').padStart(3)} folder IDs | ${String(linked).padStart(3)} linked w/ data | ${String(hasTweet).padStart(3)} have text`);
20
+ }
21
+
22
+ console.log(`\nTotal linked tweet-folder pairs: ${totalLinked}`);
23
+ console.log(`Unique tweets in DB: ${stats.tweets}`);
24
+
25
+ store.close();
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Create ATLSK ticket for dotenv auto-loading bug.
3
+ */
4
+ import * as dotenv from 'dotenv';
5
+ dotenv.config();
6
+ import { createJiraClientFromEnv, adf, text } from '@hidden-leaf/atlassian-skill';
7
+
8
+ async function main() {
9
+ const jira = createJiraClientFromEnv();
10
+
11
+ const issue = await jira.createIssue({
12
+ project: 'ATLSK',
13
+ issuetype: 'Bug',
14
+ summary: 'Auto-load .env from consuming project on import',
15
+ description: adf()
16
+ .heading(3, 'Problem')
17
+ .paragraph(
18
+ text().text(
19
+ 'When atlassian-skill is installed as a dependency in another project (e.g. x-skill), ' +
20
+ 'scripts that import from @hidden-leaf/atlassian-skill fail with "ATLASSIAN_CLOUD_ID and ' +
21
+ 'ATLASSIAN_SITE_URL are required" unless the consuming script manually calls dotenv.config() ' +
22
+ 'BEFORE the atlassian-skill import.'
23
+ )
24
+ )
25
+ .heading(3, 'Current behavior')
26
+ .paragraph(
27
+ text().text(
28
+ 'The factory functions (createJiraClientFromEnv, etc.) read process.env at call time, ' +
29
+ 'but the consuming project\'s .env is not loaded automatically. The atlassian-skill ' +
30
+ 'package calls dotenv.config() in its own modules, but that only finds .env relative ' +
31
+ 'to node_modules/@hidden-leaf/atlassian-skill/, not the consuming project root.'
32
+ )
33
+ )
34
+ .heading(3, 'Expected behavior')
35
+ .paragraph(
36
+ text().text(
37
+ 'Importing from @hidden-leaf/atlassian-skill should auto-resolve and load the .env ' +
38
+ 'from the consuming project\'s root directory (walking up from node_modules). The ' +
39
+ 'postinstall script already knows how to find the project root — the same logic should ' +
40
+ 'be used at runtime to locate and load .env.'
41
+ )
42
+ )
43
+ .heading(3, 'Suggested fix')
44
+ .paragraph(
45
+ text().text(
46
+ 'In src/index.ts or a new src/env.ts init module, detect if running inside node_modules ' +
47
+ 'and walk up to find the consuming project\'s .env. Call dotenv.config({ path: resolved }) ' +
48
+ 'before any factory functions read env vars. This is what x-skill had to work around by ' +
49
+ 'adding `import dotenv; dotenv.config()` before every atlassian-skill import.'
50
+ )
51
+ )
52
+ .heading(3, 'Reproduction')
53
+ .codeBlock(
54
+ 'typescript',
55
+ '// This FAILS:\nimport { createJiraClientFromEnv } from \'@hidden-leaf/atlassian-skill\';\nconst jira = createJiraClientFromEnv();\n// Error: ATLASSIAN_CLOUD_ID and ATLASSIAN_SITE_URL are required\n\n// This WORKS (but shouldn\'t be necessary):\nimport * as dotenv from \'dotenv\';\ndotenv.config();\nimport { createJiraClientFromEnv } from \'@hidden-leaf/atlassian-skill\';\nconst jira = createJiraClientFromEnv();'
56
+ )
57
+ .build(),
58
+ labels: ['bug', 'dx', 'dotenv'],
59
+ });
60
+
61
+ console.log(`Created: ${issue.key} — ${issue.self}`);
62
+ }
63
+
64
+ main().catch((err) => {
65
+ console.error('Failed:', err.message);
66
+ if (err.response?.data) console.error(JSON.stringify(err.response.data, null, 2));
67
+ process.exit(1);
68
+ });
@@ -0,0 +1,66 @@
1
+ import * as dotenv from 'dotenv';
2
+ dotenv.config();
3
+ import { createJiraClientFromEnv, adf, text } from '@hidden-leaf/atlassian-skill';
4
+
5
+ async function main() {
6
+ const jira = createJiraClientFromEnv();
7
+
8
+ const issue = await jira.createIssue({
9
+ project: 'XSKILL',
10
+ issuetype: 'Story',
11
+ summary: 'Deep dive: generate research briefs for all 20 bookmark categories',
12
+ description: adf()
13
+ .heading(3, 'Goal')
14
+ .paragraph(text().text(
15
+ 'Systematically generate research briefs for each of the 20 cached bookmark folders. ' +
16
+ 'Each brief feeds into a specific HLN initiative. This is the first real intelligence extraction pass.'
17
+ ))
18
+ .heading(3, 'Folder → HLN Initiative Mapping')
19
+ .paragraph(text().text(
20
+ 'Priority folders (direct HLN IP relevance):\n' +
21
+ '• CHIPS → HLOS, Scroll (hardware substrate for HLN OS + training infra)\n' +
22
+ '• Robotics → HLOS, Asimov (humanoid robotics, embodied AI)\n' +
23
+ '• LLMs → Scroll, ARIA, Konoha Engine (fine-tuning, orchestration)\n' +
24
+ '• Claude → ARIA v4, Applied AI Studio (Claude ecosystem, skill patterns)\n' +
25
+ '• Agentic Skills → x-skill, atlassian-skill (competitive landscape, format validation)\n' +
26
+ '• AI HARDWARE → HLOS, Scroll (compute, edge inference, custom silicon)\n' +
27
+ '• AI MEDICINE → Orvex, Applied AI Studio (client vertical)\n' +
28
+ '• AI MONEY → HLN strategy, Orvex (AI monetization, market signals)\n' +
29
+ '• Cybersecurity → EmLink, HLOS (security posture for HLN products)\n' +
30
+ '• Quantum Computing → long-horizon R&D signal\n' +
31
+ '• AI TTS → ARIA v4 voice reintegration\n' +
32
+ '• AI GAME DEV → MoPlay (game AI, procedural generation)\n' +
33
+ '• 3D AI GEN → MoPlay, Applied AI Studio (3D asset generation)\n' +
34
+ '• AI Live Action → Applied AI Studio (video/VFX AI)\n' +
35
+ '• Web design → HLNW, EmLink (frontend patterns)\n' +
36
+ '• App Design → EmLink, MoPlay (UX patterns)\n' +
37
+ '• Automotive → HLOS (vehicle OS, autonomy)\n' +
38
+ '• Textiles → iSWAG Resale (AI in fashion/textiles)\n' +
39
+ '• Generators and Motors → HLOS, SUCO (electromechanical, utility)\n' +
40
+ '• Home Design → SUCO (smart home, utility AI)'
41
+ ))
42
+ .heading(3, 'Process')
43
+ .paragraph(text().text(
44
+ '1. Run brief() for each folder with appropriate hlnContext\n' +
45
+ '2. Review each brief for actionable intelligence\n' +
46
+ '3. Create follow-up Jira tickets in relevant projects (HLN, HLOS, SCROLL, etc.) for any actions identified\n' +
47
+ '4. Flag cross-folder convergence points (e.g., CHIPS + Robotics + AI HARDWARE overlap)\n' +
48
+ '5. Archive briefs to Confluence as living research documents'
49
+ ))
50
+ .heading(3, 'Priority Order')
51
+ .paragraph(text().text(
52
+ 'Start with the goldmine folders: CHIPS, Robotics, AI HARDWARE, LLMs, Claude. ' +
53
+ 'These directly feed HLOS and Scroll — the two ventures waiting on capital/GPU that need the strongest research foundation when they activate.'
54
+ ))
55
+ .build(),
56
+ labels: ['intelligence', 'research', 'deep-dive', 'v1'],
57
+ });
58
+
59
+ console.log(`Created: ${issue.key} — ${issue.summary}`);
60
+ }
61
+
62
+ main().catch((err) => {
63
+ console.error('Failed:', err.message);
64
+ if (err.response?.data) console.error(JSON.stringify(err.response.data, null, 2));
65
+ process.exit(1);
66
+ });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Create the XSKILL Jira project for tracking x-skill development.
3
+ */
4
+ import * as dotenv from 'dotenv';
5
+ dotenv.config();
6
+ import { createJiraClientFromEnv } from '@hidden-leaf/atlassian-skill';
7
+
8
+ async function main() {
9
+ const jira = createJiraClientFromEnv();
10
+
11
+ // Get lead account ID
12
+ const me = await jira.getCurrentUser();
13
+
14
+ // Create the project
15
+ const project = await jira.createProject({
16
+ key: 'XSKILL',
17
+ name: 'X Skill',
18
+ projectTypeKey: 'software',
19
+ projectTemplateKey: 'com.pyxis.greenhopper.jira:gh-simplified-scrum-classic',
20
+ description: '@hidden-leaf/x-skill — X bookmark intelligence skill for Claude Code. Turns curated X bookmarks into structured research briefs for the HLN stack.',
21
+ leadAccountId: me.accountId,
22
+ });
23
+
24
+ console.log('Created Jira project:', JSON.stringify(project, null, 2));
25
+ }
26
+
27
+ main().catch((err) => {
28
+ console.error('Failed:', err.message);
29
+ if (err.response?.data) console.error(JSON.stringify(err.response.data, null, 2));
30
+ process.exit(1);
31
+ });
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Create XSKILL launch plan + v2/v3 roadmap tickets.
3
+ */
4
+ import * as dotenv from 'dotenv';
5
+ dotenv.config();
6
+ import { createJiraClientFromEnv, adf, text } from '@hidden-leaf/atlassian-skill';
7
+
8
+ interface TicketDef {
9
+ summary: string;
10
+ type: string;
11
+ description: string;
12
+ labels: string[];
13
+ }
14
+
15
+ const tickets: TicketDef[] = [
16
+ // ========== LAUNCH PLAN ==========
17
+ {
18
+ summary: 'Write launch thread for @hlntre X announcement',
19
+ type: 'Task',
20
+ description:
21
+ 'Write a launch thread for @hlntre announcing x-skill publicly. ' +
22
+ 'Hook: quote-reply the original @lexi_labs thread ("X content is consumable, it sinks once posted") ' +
23
+ 'with "I said I\'d build the open-source tooling. Here it is." ' +
24
+ 'Thread structure:\n' +
25
+ '1. Quote-reply @lexi_labs with the hook\n' +
26
+ '2. What x-skill does (bookmark folders → structured research briefs via Claude)\n' +
27
+ '3. Demo GIF or screenshot showing sync + brief output\n' +
28
+ '4. Install command: npm install @hidden-leaf/x-skill\n' +
29
+ '5. Link to GitHub repo\n' +
30
+ '6. Tag @AnthropicAI @claudecode — this is a Claude Code skill\n' +
31
+ '7. Call to action: "What folders would you build briefs from?"\n\n' +
32
+ 'Precedent: baoyu-youtube-transcript skill went viral with 1.9K likes, 521 RTs from a similar format post.',
33
+ labels: ['launch', 'marketing', 'v1'],
34
+ },
35
+ {
36
+ summary: 'Create demo GIF/video: sync → cache → brief pipeline',
37
+ type: 'Task',
38
+ description:
39
+ 'Record a terminal demo showing the full x-skill pipeline:\n' +
40
+ '1. npx tsx sync.ts — folders populate with tweet counts\n' +
41
+ '2. npx tsx fetch.ts --folder "Robotics" — shows enriched posts\n' +
42
+ '3. npx tsx brief.ts --folder "Robotics" — Claude generates research brief\n' +
43
+ 'Keep it under 30 seconds. Use asciinema or screen recording. ' +
44
+ 'This is the centerpiece of the launch thread and README.',
45
+ labels: ['launch', 'marketing', 'v1'],
46
+ },
47
+ {
48
+ summary: 'Submit x-skill to Claude Code community skill directories',
49
+ type: 'Task',
50
+ description:
51
+ 'After public launch, submit x-skill to:\n' +
52
+ '- Anthropic\'s Claude Code skill/extension listings (if any official directory exists)\n' +
53
+ '- The "Agentic Skills" community on X (where baoyu-youtube-transcript was featured)\n' +
54
+ '- awesome-claude-code or similar GitHub lists\n' +
55
+ '- npm package discovery (keywords already set)\n' +
56
+ 'The baoyu skill got featured on X\'s "Agentic Skills" trending page — aim for the same.',
57
+ labels: ['launch', 'marketing', 'v1'],
58
+ },
59
+ {
60
+ summary: 'Cross-post launch to LinkedIn and dev communities',
61
+ type: 'Task',
62
+ description:
63
+ 'Adapt the X launch thread for:\n' +
64
+ '- LinkedIn post (Tre\'s profile + HLN company page)\n' +
65
+ '- Reddit: r/ClaudeAI, r/artificial\n' +
66
+ '- Dev.to or Hashnode blog post: "I turned my X bookmarks into a research pipeline"\n' +
67
+ 'Position as: open-source, bootstrapped, built in a day with Claude Code.',
68
+ labels: ['launch', 'marketing', 'v1'],
69
+ },
70
+ {
71
+ summary: 'Add Applied AI Studio branding to x-skill as showcase project',
72
+ type: 'Task',
73
+ description:
74
+ 'x-skill is a showcase for what Applied AI Studio (post-MDAI) can build. ' +
75
+ 'Add "Built by Applied AI Studio" to README footer. ' +
76
+ 'Reference in studio portfolio/case studies. ' +
77
+ 'This demonstrates the studio\'s capability: shipped an open-source npm package from concept to cache-backed intelligence pipeline in one session.',
78
+ labels: ['launch', 'branding', 'v1'],
79
+ },
80
+
81
+ // ========== v2: SEARCH, THREADS, PROFILE ==========
82
+ {
83
+ summary: '[v2] Search skill — query X for topics and keywords',
84
+ type: 'Story',
85
+ description:
86
+ 'New sub-skill: src/skills/search/\n' +
87
+ 'Commands:\n' +
88
+ ' x search query "humanoid robotics" --limit 50\n' +
89
+ ' x search recent "Claude Code" --since 7d\n\n' +
90
+ 'Uses GET /2/tweets/search/recent (pay-per-use).\n' +
91
+ 'Cache results in SQLite like bookmarks.\n' +
92
+ 'Enables research beyond what the user has bookmarked — discover new signals.\n' +
93
+ 'Brief command should work on search results too, not just bookmarks.',
94
+ labels: ['v2', 'search', 'planned'],
95
+ },
96
+ {
97
+ summary: '[v2] Threads skill — fetch and parse full thread context',
98
+ type: 'Story',
99
+ description:
100
+ 'New sub-skill: src/skills/threads/\n' +
101
+ 'Commands:\n' +
102
+ ' x threads fetch <tweet_url_or_id>\n' +
103
+ ' x threads brief <tweet_url_or_id>\n\n' +
104
+ 'Uses conversation_id to reconstruct full threads.\n' +
105
+ 'Many bookmarked posts are part of longer threads — the single tweet loses context.\n' +
106
+ 'Thread-aware briefs will produce much higher quality intelligence.\n' +
107
+ 'Store thread relationships in cache (parent/child tweet links).',
108
+ labels: ['v2', 'threads', 'planned'],
109
+ },
110
+ {
111
+ summary: '[v2] Profile skill — account and list management',
112
+ type: 'Story',
113
+ description:
114
+ 'New sub-skill: src/skills/profile/\n' +
115
+ 'Commands:\n' +
116
+ ' x profile info @username\n' +
117
+ ' x profile followers --notable\n' +
118
+ ' x lists show\n' +
119
+ ' x lists members "AI Researchers"\n\n' +
120
+ 'Enables: "Who are the top voices in my Robotics bookmarks?" → profile lookup → follow recommendations.\n' +
121
+ 'List management ties into curation workflow.',
122
+ labels: ['v2', 'profile', 'planned'],
123
+ },
124
+ {
125
+ summary: '[v2] Cross-folder intelligence and trend analysis',
126
+ type: 'Story',
127
+ description:
128
+ 'New command:\n' +
129
+ ' x bookmarks trends\n' +
130
+ ' x bookmarks compare --folders "Robotics,AI HARDWARE,CHIPS"\n\n' +
131
+ 'Analyze signals across multiple folders. Detect convergence points ' +
132
+ '(e.g., "CHIPS + Robotics overlap on NVIDIA robotics chips").\n' +
133
+ 'Time-series analysis: what topics are accelerating in your bookmarks?\n' +
134
+ 'This is where the cached data really pays off — cross-folder queries at zero API cost.',
135
+ labels: ['v2', 'intelligence', 'planned'],
136
+ },
137
+
138
+ // ========== v3: PUBLISH ==========
139
+ {
140
+ summary: '[v3] Publish skill — post, schedule, and reply from CLI',
141
+ type: 'Story',
142
+ description:
143
+ 'New sub-skill: src/skills/publish/\n' +
144
+ 'Commands:\n' +
145
+ ' x publish post "text here"\n' +
146
+ ' x publish thread ["post 1", "post 2", "post 3"]\n' +
147
+ ' x publish schedule "text" --at "2026-04-01 09:00"\n' +
148
+ ' x publish reply <tweet_id> "response"\n\n' +
149
+ 'Requires OAuth 2.0 write scopes (tweet.write).\n' +
150
+ 'Enables full content lifecycle: research (bookmarks) → synthesize (brief) → publish (post).\n' +
151
+ 'Schedule feature needs a local cron or persistent process.\n' +
152
+ 'IMPORTANT: This changes the skill from read-only to read-write. Requires careful scope management and user confirmation before posting.',
153
+ labels: ['v3', 'publish', 'planned'],
154
+ },
155
+ {
156
+ summary: '[v3] Brief-to-thread pipeline — auto-generate X threads from research',
157
+ type: 'Story',
158
+ description:
159
+ 'Combine brief + publish:\n' +
160
+ ' x bookmarks brief --folder "Robotics" --output thread\n\n' +
161
+ 'Takes a research brief and formats it as a publishable X thread.\n' +
162
+ 'Claude rewrites the brief into thread-optimized format (hook, insights, CTA).\n' +
163
+ 'User reviews before posting (never auto-post without confirmation).\n' +
164
+ 'This closes the loop: consume X → synthesize → publish back to X.\n' +
165
+ 'Directly addresses the @lexi_labs insight — turn consumable content into durable assets.',
166
+ labels: ['v3', 'publish', 'brief', 'planned'],
167
+ },
168
+ ];
169
+
170
+ async function main() {
171
+ const jira = createJiraClientFromEnv();
172
+
173
+ console.log(`Creating ${tickets.length} tickets...\n`);
174
+
175
+ for (const ticket of tickets) {
176
+ const issue = await jira.createIssue({
177
+ project: 'XSKILL',
178
+ issuetype: ticket.type,
179
+ summary: ticket.summary,
180
+ description: adf()
181
+ .paragraph(text().text(ticket.description))
182
+ .build(),
183
+ labels: ticket.labels,
184
+ });
185
+
186
+ const phase = ticket.labels.includes('launch') ? 'LAUNCH'
187
+ : ticket.labels.includes('v2') ? 'v2'
188
+ : ticket.labels.includes('v3') ? 'v3'
189
+ : '???';
190
+ console.log(` ${issue.key} [${phase}] ${ticket.summary}`);
191
+ }
192
+
193
+ console.log('\nDone!');
194
+ }
195
+
196
+ main().catch((err) => {
197
+ console.error('Failed:', err.message);
198
+ if (err.response?.data) console.error(JSON.stringify(err.response.data, null, 2));
199
+ process.exit(1);
200
+ });