WIP: A simple cli for daily tangled use cases and AI integration. This is for my personal use right now, but happy if others get mileage from it! :)

Add lexicon code generation tooling

- Install @atproto/lex-cli for generating TypeScript types from lexicons
- Add npm scripts:
- codegen: Generate TS client API from lexicons
- update-lexicons: Update vendored lexicons from tangled.org

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

markbennett.ca bc2a27fd ebc5ed32

verified
+272 -2
+261
package-lock.json
··· 22 22 "tangled": "dist/index.js" 23 23 }, 24 24 "devDependencies": { 25 + "@atproto/lex-cli": "^0.9.8", 25 26 "@biomejs/biome": "^1.9.4", 26 27 "@types/node": "^22.10.2", 27 28 "tsx": "^4.21.0", ··· 73 74 "version": "3.25.76", 74 75 "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 75 76 "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 77 + "license": "MIT", 78 + "funding": { 79 + "url": "https://github.com/sponsors/colinhacks" 80 + } 81 + }, 82 + "node_modules/@atproto/lex-cli": { 83 + "version": "0.9.8", 84 + "resolved": "https://registry.npmjs.org/@atproto/lex-cli/-/lex-cli-0.9.8.tgz", 85 + "integrity": "sha512-0ebVyp12i3S8oE77+BxahbTmyrXcqeC9GTx2HGa/PA9KjnThapkGkgVQjIWw74DNQprzbg9EkiQsaKU2xFYhmA==", 86 + "dev": true, 87 + "license": "MIT", 88 + "dependencies": { 89 + "@atproto/lexicon": "^0.6.0", 90 + "@atproto/syntax": "^0.4.2", 91 + "chalk": "^4.1.2", 92 + "commander": "^9.4.0", 93 + "prettier": "^3.2.5", 94 + "ts-morph": "^24.0.0", 95 + "yesno": "^0.4.0", 96 + "zod": "^3.23.8" 97 + }, 98 + "bin": { 99 + "lex": "dist/index.js" 100 + }, 101 + "engines": { 102 + "node": ">=18.7.0" 103 + } 104 + }, 105 + "node_modules/@atproto/lex-cli/node_modules/commander": { 106 + "version": "9.5.0", 107 + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", 108 + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", 109 + "dev": true, 110 + "license": "MIT", 111 + "engines": { 112 + "node": "^12.20.0 || >=14" 113 + } 114 + }, 115 + "node_modules/@atproto/lex-cli/node_modules/zod": { 116 + "version": "3.25.76", 117 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 118 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 119 + "dev": true, 76 120 "license": "MIT", 77 121 "funding": { 78 122 "url": "https://github.com/sponsors/colinhacks" ··· 1698 1742 "win32" 1699 1743 ] 1700 1744 }, 1745 + "node_modules/@ts-morph/common": { 1746 + "version": "0.25.0", 1747 + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.25.0.tgz", 1748 + "integrity": "sha512-kMnZz+vGGHi4GoHnLmMhGNjm44kGtKUXGnOvrKmMwAuvNjM/PgKVGfUnL7IDvK7Jb2QQ82jq3Zmp04Gy+r3Dkg==", 1749 + "dev": true, 1750 + "license": "MIT", 1751 + "dependencies": { 1752 + "minimatch": "^9.0.4", 1753 + "path-browserify": "^1.0.1", 1754 + "tinyglobby": "^0.2.9" 1755 + } 1756 + }, 1701 1757 "node_modules/@types/estree": { 1702 1758 "version": "1.0.8", 1703 1759 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", ··· 1874 1930 "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==", 1875 1931 "license": "MIT" 1876 1932 }, 1933 + "node_modules/balanced-match": { 1934 + "version": "1.0.2", 1935 + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1936 + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1937 + "dev": true, 1938 + "license": "MIT" 1939 + }, 1940 + "node_modules/brace-expansion": { 1941 + "version": "2.0.2", 1942 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", 1943 + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", 1944 + "dev": true, 1945 + "license": "MIT", 1946 + "dependencies": { 1947 + "balanced-match": "^1.0.0" 1948 + } 1949 + }, 1877 1950 "node_modules/cac": { 1878 1951 "version": "6.7.14", 1879 1952 "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", ··· 1910 1983 "node": ">=18" 1911 1984 } 1912 1985 }, 1986 + "node_modules/chalk": { 1987 + "version": "4.1.2", 1988 + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1989 + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1990 + "dev": true, 1991 + "license": "MIT", 1992 + "dependencies": { 1993 + "ansi-styles": "^4.1.0", 1994 + "supports-color": "^7.1.0" 1995 + }, 1996 + "engines": { 1997 + "node": ">=10" 1998 + }, 1999 + "funding": { 2000 + "url": "https://github.com/chalk/chalk?sponsor=1" 2001 + } 2002 + }, 2003 + "node_modules/chalk/node_modules/ansi-styles": { 2004 + "version": "4.3.0", 2005 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2006 + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2007 + "dev": true, 2008 + "license": "MIT", 2009 + "dependencies": { 2010 + "color-convert": "^2.0.1" 2011 + }, 2012 + "engines": { 2013 + "node": ">=8" 2014 + }, 2015 + "funding": { 2016 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2017 + } 2018 + }, 1913 2019 "node_modules/chardet": { 1914 2020 "version": "2.1.1", 1915 2021 "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", ··· 1935 2041 "node": ">= 12" 1936 2042 } 1937 2043 }, 2044 + "node_modules/code-block-writer": { 2045 + "version": "13.0.3", 2046 + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", 2047 + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", 2048 + "dev": true, 2049 + "license": "MIT" 2050 + }, 2051 + "node_modules/color-convert": { 2052 + "version": "2.0.1", 2053 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2054 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2055 + "dev": true, 2056 + "license": "MIT", 2057 + "dependencies": { 2058 + "color-name": "~1.1.4" 2059 + }, 2060 + "engines": { 2061 + "node": ">=7.0.0" 2062 + } 2063 + }, 2064 + "node_modules/color-name": { 2065 + "version": "1.1.4", 2066 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2067 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2068 + "dev": true, 2069 + "license": "MIT" 2070 + }, 1938 2071 "node_modules/commander": { 1939 2072 "version": "12.1.0", 1940 2073 "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", ··· 2090 2223 "node": ">=12.0.0" 2091 2224 } 2092 2225 }, 2226 + "node_modules/fdir": { 2227 + "version": "6.5.0", 2228 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", 2229 + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", 2230 + "dev": true, 2231 + "license": "MIT", 2232 + "engines": { 2233 + "node": ">=12.0.0" 2234 + }, 2235 + "peerDependencies": { 2236 + "picomatch": "^3 || ^4" 2237 + }, 2238 + "peerDependenciesMeta": { 2239 + "picomatch": { 2240 + "optional": true 2241 + } 2242 + } 2243 + }, 2093 2244 "node_modules/fsevents": { 2094 2245 "version": "2.3.3", 2095 2246 "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", ··· 2128 2279 }, 2129 2280 "funding": { 2130 2281 "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 2282 + } 2283 + }, 2284 + "node_modules/has-flag": { 2285 + "version": "4.0.0", 2286 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 2287 + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 2288 + "dev": true, 2289 + "license": "MIT", 2290 + "engines": { 2291 + "node": ">=8" 2131 2292 } 2132 2293 }, 2133 2294 "node_modules/iconv-lite": { ··· 2221 2382 "@jridgewell/sourcemap-codec": "^1.5.5" 2222 2383 } 2223 2384 }, 2385 + "node_modules/minimatch": { 2386 + "version": "9.0.5", 2387 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", 2388 + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 2389 + "dev": true, 2390 + "license": "ISC", 2391 + "dependencies": { 2392 + "brace-expansion": "^2.0.1" 2393 + }, 2394 + "engines": { 2395 + "node": ">=16 || 14 >=14.17" 2396 + }, 2397 + "funding": { 2398 + "url": "https://github.com/sponsors/isaacs" 2399 + } 2400 + }, 2224 2401 "node_modules/ms": { 2225 2402 "version": "2.1.3", 2226 2403 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", ··· 2291 2468 "url": "https://github.com/sponsors/sindresorhus" 2292 2469 } 2293 2470 }, 2471 + "node_modules/path-browserify": { 2472 + "version": "1.0.1", 2473 + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", 2474 + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", 2475 + "dev": true, 2476 + "license": "MIT" 2477 + }, 2294 2478 "node_modules/pathe": { 2295 2479 "version": "1.1.2", 2296 2480 "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", ··· 2314 2498 "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 2315 2499 "license": "ISC" 2316 2500 }, 2501 + "node_modules/picomatch": { 2502 + "version": "4.0.3", 2503 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", 2504 + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", 2505 + "dev": true, 2506 + "license": "MIT", 2507 + "engines": { 2508 + "node": ">=12" 2509 + }, 2510 + "funding": { 2511 + "url": "https://github.com/sponsors/jonschlinkert" 2512 + } 2513 + }, 2317 2514 "node_modules/postcss": { 2318 2515 "version": "8.5.6", 2319 2516 "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", ··· 2341 2538 }, 2342 2539 "engines": { 2343 2540 "node": "^10 || ^12 || >=14" 2541 + } 2542 + }, 2543 + "node_modules/prettier": { 2544 + "version": "3.8.1", 2545 + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", 2546 + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", 2547 + "dev": true, 2548 + "license": "MIT", 2549 + "bin": { 2550 + "prettier": "bin/prettier.cjs" 2551 + }, 2552 + "engines": { 2553 + "node": ">=14" 2554 + }, 2555 + "funding": { 2556 + "url": "https://github.com/prettier/prettier?sponsor=1" 2344 2557 } 2345 2558 }, 2346 2559 "node_modules/resolve-from": { ··· 2503 2716 "url": "https://github.com/chalk/strip-ansi?sponsor=1" 2504 2717 } 2505 2718 }, 2719 + "node_modules/supports-color": { 2720 + "version": "7.2.0", 2721 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2722 + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2723 + "dev": true, 2724 + "license": "MIT", 2725 + "dependencies": { 2726 + "has-flag": "^4.0.0" 2727 + }, 2728 + "engines": { 2729 + "node": ">=8" 2730 + } 2731 + }, 2506 2732 "node_modules/tinybench": { 2507 2733 "version": "2.9.0", 2508 2734 "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", ··· 2517 2743 "dev": true, 2518 2744 "license": "MIT" 2519 2745 }, 2746 + "node_modules/tinyglobby": { 2747 + "version": "0.2.15", 2748 + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", 2749 + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", 2750 + "dev": true, 2751 + "license": "MIT", 2752 + "dependencies": { 2753 + "fdir": "^6.5.0", 2754 + "picomatch": "^4.0.3" 2755 + }, 2756 + "engines": { 2757 + "node": ">=12.0.0" 2758 + }, 2759 + "funding": { 2760 + "url": "https://github.com/sponsors/SuperchupuDev" 2761 + } 2762 + }, 2520 2763 "node_modules/tinypool": { 2521 2764 "version": "1.1.1", 2522 2765 "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", ··· 2554 2797 "license": "MIT", 2555 2798 "bin": { 2556 2799 "tlds": "bin.js" 2800 + } 2801 + }, 2802 + "node_modules/ts-morph": { 2803 + "version": "24.0.0", 2804 + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-24.0.0.tgz", 2805 + "integrity": "sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==", 2806 + "dev": true, 2807 + "license": "MIT", 2808 + "dependencies": { 2809 + "@ts-morph/common": "~0.25.0", 2810 + "code-block-writer": "^13.0.3" 2557 2811 } 2558 2812 }, 2559 2813 "node_modules/tslib": { ··· 3230 3484 "funding": { 3231 3485 "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 3232 3486 } 3487 + }, 3488 + "node_modules/yesno": { 3489 + "version": "0.4.0", 3490 + "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.4.0.tgz", 3491 + "integrity": "sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==", 3492 + "dev": true, 3493 + "license": "BSD" 3233 3494 }, 3234 3495 "node_modules/zod": { 3235 3496 "version": "4.3.6",
+11 -2
package.json
··· 17 17 "lint:fix": "biome check --write .", 18 18 "format": "biome format --write .", 19 19 "typecheck": "tsc --noEmit", 20 - "prepublishOnly": "npm run build" 20 + "prepublishOnly": "npm run build", 21 + "codegen": "npx lex gen-api --yes ./src/lexicon ./lexicons/sh/tangled/**/*.json", 22 + "update-lexicons": "./scripts/update-lexicons.sh" 21 23 }, 22 24 "engines": { 23 25 "node": ">=22.0.0" ··· 26 28 "type": "git", 27 29 "url": "git@tangled.org:markbennett.ca/tangled-cli" 28 30 }, 29 - "keywords": ["git", "tangled", "pds", "atproto", "cli"], 31 + "keywords": [ 32 + "git", 33 + "tangled", 34 + "pds", 35 + "atproto", 36 + "cli" 37 + ], 30 38 "author": "Mark Bennett", 31 39 "license": "MIT", 32 40 "dependencies": { ··· 40 48 "zod": "^4.3.6" 41 49 }, 42 50 "devDependencies": { 51 + "@atproto/lex-cli": "^0.9.8", 43 52 "@biomejs/biome": "^1.9.4", 44 53 "@types/node": "^22.10.2", 45 54 "tsx": "^4.21.0",