codeply-cli 0.2.0 → 0.3.1

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 (43) hide show
  1. package/THIRD_PARTY_NOTICES.md +63 -0
  2. package/bin/codeply.js +558 -370
  3. package/lib/agent.mjs +1627 -160
  4. package/lib/ai.js +1107 -387
  5. package/lib/apply-limit.js +33 -51
  6. package/lib/apply-patch.js +217 -0
  7. package/lib/arity-table.json +138 -0
  8. package/lib/arity.js +70 -0
  9. package/lib/auth.js +118 -112
  10. package/lib/commands.js +103 -0
  11. package/lib/config.js +392 -136
  12. package/lib/design-library/artifact-template.html +500 -0
  13. package/lib/design-library/assemble-artifact.mjs +21 -0
  14. package/lib/design-library/build.mjs +226 -0
  15. package/lib/design-library/cleanup.mjs +45 -0
  16. package/lib/design-library/index.json +22380 -0
  17. package/lib/design-library/make-table-data.mjs +39 -0
  18. package/lib/design-library/query.mjs +104 -0
  19. package/lib/diagnostics.js +192 -0
  20. package/lib/edit-engine.js +171 -14
  21. package/lib/github-agent.mjs +307 -0
  22. package/lib/history.js +75 -0
  23. package/lib/mcp.js +258 -0
  24. package/lib/native-tools.mjs +189 -0
  25. package/lib/oauth-connectors.js +478 -0
  26. package/lib/permissions.js +109 -0
  27. package/lib/plugins.js +353 -0
  28. package/lib/render-md.mjs +617 -617
  29. package/lib/server.mjs +457 -0
  30. package/lib/session-db.js +220 -0
  31. package/lib/share.js +168 -0
  32. package/lib/skills.js +80 -22
  33. package/lib/snapshot.js +146 -0
  34. package/lib/subagents.js +164 -0
  35. package/lib/terminal-hints.js +154 -0
  36. package/lib/textarea.mjs +258 -258
  37. package/lib/tools.mjs +1658 -79
  38. package/lib/tui.js +7 -7
  39. package/lib/tui.mjs +1086 -992
  40. package/lib/typecheck-worker.js +147 -0
  41. package/lib/web-tools.js +158 -0
  42. package/package.json +4 -3
  43. package/skills/premium-web-design/SKILL.md +154 -0
@@ -0,0 +1,500 @@
1
+ <title>App Screenshot Atlas</title>
2
+ <style>
3
+ :root {
4
+ --bg: #f7f8fa;
5
+ --surface: #ffffff;
6
+ --surface-alt: #eef1f5;
7
+ --border: #dde2e8;
8
+ --border-strong: #c7ced7;
9
+ --text: #14171b;
10
+ --text-muted: #5b6169;
11
+ --text-faint: #8a919b;
12
+ --accent: #3462ea;
13
+ --accent-soft: #e8edfd;
14
+ --accent-contrast: #ffffff;
15
+ --radius: 8px;
16
+ --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
17
+ --font-mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
18
+ }
19
+
20
+ @media (prefers-color-scheme: dark) {
21
+ :root:not([data-theme="light"]) {
22
+ --bg: #0b0d10;
23
+ --surface: #14171b;
24
+ --surface-alt: #1b1f24;
25
+ --border: #262b31;
26
+ --border-strong: #333a42;
27
+ --text: #e8eaed;
28
+ --text-muted: #9ba1aa;
29
+ --text-faint: #676e78;
30
+ --accent: #6f93ff;
31
+ --accent-soft: #1b2440;
32
+ --accent-contrast: #0b0d10;
33
+ }
34
+ }
35
+
36
+ :root[data-theme="dark"] {
37
+ --bg: #0b0d10;
38
+ --surface: #14171b;
39
+ --surface-alt: #1b1f24;
40
+ --border: #262b31;
41
+ --border-strong: #333a42;
42
+ --text: #e8eaed;
43
+ --text-muted: #9ba1aa;
44
+ --text-faint: #676e78;
45
+ --accent: #6f93ff;
46
+ --accent-soft: #1b2440;
47
+ --accent-contrast: #0b0d10;
48
+ }
49
+
50
+ * { box-sizing: border-box; }
51
+
52
+ html, body {
53
+ margin: 0;
54
+ padding: 0;
55
+ background: var(--bg);
56
+ color: var(--text);
57
+ }
58
+
59
+ body {
60
+ font-family: var(--font-ui);
61
+ font-size: 14px;
62
+ line-height: 1.5;
63
+ -webkit-font-smoothing: antialiased;
64
+ }
65
+
66
+ .wrap {
67
+ max-width: 1180px;
68
+ margin: 0 auto;
69
+ padding: 28px 20px 64px;
70
+ }
71
+
72
+ header.top {
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: 4px;
76
+ margin-bottom: 20px;
77
+ }
78
+
79
+ header.top h1 {
80
+ font-size: 22px;
81
+ font-weight: 800;
82
+ letter-spacing: -0.01em;
83
+ margin: 0;
84
+ text-wrap: balance;
85
+ }
86
+
87
+ header.top p {
88
+ margin: 0;
89
+ color: var(--text-muted);
90
+ font-size: 13px;
91
+ }
92
+
93
+ .totals {
94
+ font-variant-numeric: tabular-nums;
95
+ font-family: var(--font-mono);
96
+ color: var(--text-faint);
97
+ font-size: 12px;
98
+ }
99
+
100
+ .overview {
101
+ display: flex;
102
+ flex-direction: column;
103
+ gap: 6px;
104
+ background: var(--surface);
105
+ border: 1px solid var(--border);
106
+ border-radius: var(--radius);
107
+ padding: 14px 16px;
108
+ margin-bottom: 20px;
109
+ }
110
+
111
+ .overview-row {
112
+ display: grid;
113
+ grid-template-columns: 130px 1fr 70px;
114
+ align-items: center;
115
+ gap: 10px;
116
+ font-size: 12px;
117
+ }
118
+
119
+ .overview-row .cat-label {
120
+ color: var(--text-muted);
121
+ white-space: nowrap;
122
+ overflow: hidden;
123
+ text-overflow: ellipsis;
124
+ }
125
+
126
+ .overview-bar-track {
127
+ height: 6px;
128
+ border-radius: 3px;
129
+ background: var(--surface-alt);
130
+ overflow: hidden;
131
+ }
132
+
133
+ .overview-bar-fill {
134
+ height: 100%;
135
+ border-radius: 3px;
136
+ background: var(--cat-color, var(--accent));
137
+ }
138
+
139
+ .overview-row .cat-count {
140
+ font-family: var(--font-mono);
141
+ font-variant-numeric: tabular-nums;
142
+ color: var(--text-faint);
143
+ text-align: right;
144
+ }
145
+
146
+ .controls {
147
+ display: flex;
148
+ flex-wrap: wrap;
149
+ gap: 8px;
150
+ margin-bottom: 14px;
151
+ align-items: center;
152
+ }
153
+
154
+ .search {
155
+ flex: 1;
156
+ min-width: 200px;
157
+ background: var(--surface);
158
+ border: 1px solid var(--border);
159
+ border-radius: var(--radius);
160
+ padding: 9px 12px;
161
+ font-size: 13px;
162
+ color: var(--text);
163
+ font-family: var(--font-ui);
164
+ outline: none;
165
+ }
166
+
167
+ .search:focus {
168
+ border-color: var(--accent);
169
+ }
170
+
171
+ .search::placeholder {
172
+ color: var(--text-faint);
173
+ }
174
+
175
+ .chip {
176
+ border: 1px solid var(--border);
177
+ background: var(--surface);
178
+ color: var(--text-muted);
179
+ font-size: 12px;
180
+ font-weight: 600;
181
+ padding: 6px 11px;
182
+ border-radius: 999px;
183
+ cursor: pointer;
184
+ white-space: nowrap;
185
+ transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
186
+ }
187
+
188
+ .chip:hover {
189
+ border-color: var(--border-strong);
190
+ }
191
+
192
+ .chip.active {
193
+ background: var(--accent);
194
+ border-color: var(--accent);
195
+ color: var(--accent-contrast);
196
+ }
197
+
198
+ .chip-row {
199
+ display: flex;
200
+ flex-wrap: wrap;
201
+ gap: 6px;
202
+ margin-bottom: 16px;
203
+ }
204
+
205
+ .result-count {
206
+ color: var(--text-faint);
207
+ font-size: 12px;
208
+ font-family: var(--font-mono);
209
+ margin-bottom: 8px;
210
+ }
211
+
212
+ .table-scroll {
213
+ overflow-x: auto;
214
+ border: 1px solid var(--border);
215
+ border-radius: var(--radius);
216
+ background: var(--surface);
217
+ }
218
+
219
+ table {
220
+ width: 100%;
221
+ border-collapse: collapse;
222
+ min-width: 640px;
223
+ }
224
+
225
+ thead th {
226
+ position: sticky;
227
+ top: 0;
228
+ background: var(--surface-alt);
229
+ text-align: left;
230
+ font-size: 11px;
231
+ text-transform: uppercase;
232
+ letter-spacing: 0.04em;
233
+ color: var(--text-muted);
234
+ font-weight: 700;
235
+ padding: 10px 12px;
236
+ border-bottom: 1px solid var(--border);
237
+ cursor: pointer;
238
+ user-select: none;
239
+ white-space: nowrap;
240
+ }
241
+
242
+ thead th:hover {
243
+ color: var(--text);
244
+ }
245
+
246
+ thead th.sorted {
247
+ color: var(--accent);
248
+ }
249
+
250
+ tbody tr {
251
+ border-bottom: 1px solid var(--border);
252
+ }
253
+
254
+ tbody tr:last-child {
255
+ border-bottom: none;
256
+ }
257
+
258
+ tbody tr:hover {
259
+ background: var(--surface-alt);
260
+ }
261
+
262
+ td {
263
+ padding: 8px 12px;
264
+ vertical-align: middle;
265
+ }
266
+
267
+ .app-cell {
268
+ display: flex;
269
+ align-items: center;
270
+ gap: 10px;
271
+ min-width: 220px;
272
+ }
273
+
274
+ .app-icon {
275
+ width: 28px;
276
+ height: 28px;
277
+ border-radius: 7px;
278
+ flex-shrink: 0;
279
+ background: var(--surface-alt);
280
+ object-fit: cover;
281
+ }
282
+
283
+ .app-name {
284
+ font-weight: 600;
285
+ color: var(--text);
286
+ overflow: hidden;
287
+ text-overflow: ellipsis;
288
+ white-space: nowrap;
289
+ max-width: 320px;
290
+ }
291
+
292
+ .app-name a {
293
+ color: inherit;
294
+ text-decoration: none;
295
+ }
296
+
297
+ .app-name a:hover {
298
+ text-decoration: underline;
299
+ }
300
+
301
+ .cat-tag {
302
+ display: inline-block;
303
+ font-size: 11px;
304
+ font-weight: 700;
305
+ padding: 3px 8px;
306
+ border-radius: 999px;
307
+ background: var(--cat-color-soft, var(--accent-soft));
308
+ color: var(--cat-color, var(--accent));
309
+ white-space: nowrap;
310
+ }
311
+
312
+ .num {
313
+ font-family: var(--font-mono);
314
+ font-variant-numeric: tabular-nums;
315
+ color: var(--text-muted);
316
+ text-align: right;
317
+ }
318
+
319
+ .num.shots {
320
+ color: var(--text);
321
+ font-weight: 700;
322
+ }
323
+
324
+ .rating-stars {
325
+ color: var(--text-faint);
326
+ font-size: 11px;
327
+ }
328
+
329
+ footer.note {
330
+ margin-top: 20px;
331
+ color: var(--text-faint);
332
+ font-size: 11px;
333
+ line-height: 1.6;
334
+ }
335
+
336
+ @media (max-width: 640px) {
337
+ .overview-row { grid-template-columns: 90px 1fr 50px; }
338
+ .app-name { max-width: 160px; }
339
+ }
340
+ </style>
341
+
342
+ <div class="wrap">
343
+ <header class="top">
344
+ <h1>App Screenshot Atlas</h1>
345
+ <p>Private design reference library. Real screenshots sourced from Apple's public iTunes Search API, official App Store listings only. Not shown publicly.</p>
346
+ </header>
347
+
348
+ <div class="overview" id="overview"></div>
349
+
350
+ <div class="controls">
351
+ <input class="search" id="search" type="text" placeholder="Search app name…" autocomplete="off" />
352
+ </div>
353
+
354
+ <div class="chip-row" id="chips"></div>
355
+
356
+ <div class="result-count" id="resultCount"></div>
357
+
358
+ <div class="table-scroll">
359
+ <table>
360
+ <thead>
361
+ <tr>
362
+ <th data-sort="n">App</th>
363
+ <th data-sort="c">Category</th>
364
+ <th data-sort="r" style="text-align:right">Rating</th>
365
+ <th data-sort="s" class="sorted" style="text-align:right">Screenshots</th>
366
+ </tr>
367
+ </thead>
368
+ <tbody id="tbody"></tbody>
369
+ </table>
370
+ </div>
371
+
372
+ <footer class="note">
373
+ Generated __GENERATED_AT__ &middot; __TOTAL_APPS__ apps &middot; __TOTAL_SHOTS__ screenshots &middot; source: Apple iTunes Search API (public, unauthenticated)
374
+ </footer>
375
+ </div>
376
+
377
+ <script id="table-data" type="application/json">__DATA_JSON__</script>
378
+ <script>
379
+ (function () {
380
+ var raw = JSON.parse(document.getElementById('table-data').textContent);
381
+ var labels = raw.labels;
382
+ var rows = raw.rows;
383
+
384
+ var CAT_HUES = {
385
+ productivity: 217, finance: 152, shopping: 28, social: 330, travel: 190,
386
+ food_delivery: 12, health_fitness: 260, education: 45, entertainment: 350, real_estate: 172,
387
+ };
388
+
389
+ var catKeys = Object.keys(labels);
390
+ var style = document.createElement('style');
391
+ var css = '';
392
+ catKeys.forEach(function (k) {
393
+ var h = CAT_HUES[k] || 200;
394
+ css += '[data-cat="' + k + '"] { --cat-color: hsl(' + h + ' 65% 45%); --cat-color-soft: hsl(' + h + ' 70% 94%); }\n';
395
+ css += '@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) [data-cat="' + k + '"] { --cat-color: hsl(' + h + ' 75% 68%); --cat-color-soft: hsl(' + h + ' 40% 18%); } }\n';
396
+ css += ':root[data-theme="dark"] [data-cat="' + k + '"] { --cat-color: hsl(' + h + ' 75% 68%); --cat-color-soft: hsl(' + h + ' 40% 18%); }\n';
397
+ });
398
+ style.textContent = css;
399
+ document.head.appendChild(style);
400
+
401
+ // overview bars
402
+ var overviewEl = document.getElementById('overview');
403
+ var catCounts = {};
404
+ rows.forEach(function (r) { catCounts[r.c] = (catCounts[r.c] || 0) + r.s; });
405
+ var maxShots = Math.max.apply(null, Object.values(catCounts));
406
+ catKeys.forEach(function (k) {
407
+ var shots = catCounts[k] || 0;
408
+ var row = document.createElement('div');
409
+ row.className = 'overview-row';
410
+ row.setAttribute('data-cat', k);
411
+ row.innerHTML =
412
+ '<span class="cat-label">' + labels[k] + '</span>' +
413
+ '<span class="overview-bar-track"><span class="overview-bar-fill" style="width:' + (shots / maxShots * 100) + '%"></span></span>' +
414
+ '<span class="cat-count">' + shots + '</span>';
415
+ overviewEl.appendChild(row);
416
+ });
417
+
418
+ // chips
419
+ var chipsEl = document.getElementById('chips');
420
+ var activeCat = null;
421
+ function renderChips() {
422
+ chipsEl.innerHTML = '';
423
+ var allChip = document.createElement('button');
424
+ allChip.className = 'chip' + (activeCat === null ? ' active' : '');
425
+ allChip.textContent = 'All categories';
426
+ allChip.onclick = function () { activeCat = null; renderChips(); renderTable(); };
427
+ chipsEl.appendChild(allChip);
428
+ catKeys.forEach(function (k) {
429
+ var chip = document.createElement('button');
430
+ chip.className = 'chip' + (activeCat === k ? ' active' : '');
431
+ chip.textContent = labels[k];
432
+ chip.onclick = function () { activeCat = k; renderChips(); renderTable(); };
433
+ chipsEl.appendChild(chip);
434
+ });
435
+ }
436
+
437
+ var sortKey = 's';
438
+ var sortDir = -1;
439
+ var searchTerm = '';
440
+
441
+ document.querySelectorAll('th[data-sort]').forEach(function (th) {
442
+ th.addEventListener('click', function () {
443
+ var key = th.getAttribute('data-sort');
444
+ if (sortKey === key) sortDir *= -1;
445
+ else { sortKey = key; sortDir = key === 'n' || key === 'c' ? 1 : -1; }
446
+ document.querySelectorAll('th[data-sort]').forEach(function (t) { t.classList.remove('sorted'); });
447
+ th.classList.add('sorted');
448
+ renderTable();
449
+ });
450
+ });
451
+
452
+ document.getElementById('search').addEventListener('input', function (e) {
453
+ searchTerm = e.target.value.trim().toLowerCase();
454
+ renderTable();
455
+ });
456
+
457
+ function renderTable() {
458
+ var filtered = rows.filter(function (r) {
459
+ if (activeCat && r.c !== activeCat) return false;
460
+ if (searchTerm && r.n.toLowerCase().indexOf(searchTerm) === -1) return false;
461
+ return true;
462
+ });
463
+ filtered.sort(function (a, b) {
464
+ var av = a[sortKey], bv = b[sortKey];
465
+ if (typeof av === 'string') return av.localeCompare(bv) * sortDir;
466
+ return ((av || 0) - (bv || 0)) * sortDir;
467
+ });
468
+
469
+ document.getElementById('resultCount').textContent = filtered.length + ' apps shown';
470
+
471
+ var tbody = document.getElementById('tbody');
472
+ var frag = document.createDocumentFragment();
473
+ filtered.forEach(function (r) {
474
+ var tr = document.createElement('tr');
475
+ tr.setAttribute('data-cat', r.c);
476
+ var ratingText = r.r ? r.r.toFixed(1) : '-';
477
+ tr.innerHTML =
478
+ '<td><div class="app-cell">' +
479
+ '<img class="app-icon" src="' + r.i + '" alt="" loading="lazy" />' +
480
+ '<span class="app-name"><a href="' + r.u + '" target="_blank" rel="noopener">' + escapeHtml(r.n) + '</a></span>' +
481
+ '</div></td>' +
482
+ '<td><span class="cat-tag">' + labels[r.c] + '</span></td>' +
483
+ '<td class="num">' + ratingText + '</td>' +
484
+ '<td class="num shots">' + r.s + '</td>';
485
+ frag.appendChild(tr);
486
+ });
487
+ tbody.innerHTML = '';
488
+ tbody.appendChild(frag);
489
+ }
490
+
491
+ function escapeHtml(s) {
492
+ return String(s).replace(/[&<>"']/g, function (c) {
493
+ return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' }[c];
494
+ });
495
+ }
496
+
497
+ renderChips();
498
+ renderTable();
499
+ })();
500
+ </script>
@@ -0,0 +1,21 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ const template = readFileSync(path.join(__dirname, 'artifact-template.html'), 'utf8');
7
+ const data = JSON.parse(readFileSync(path.join(__dirname, 'table-data.json'), 'utf8'));
8
+
9
+ const totalApps = data.rows.length;
10
+ const totalShots = data.rows.reduce((s, r) => s + r.s, 0);
11
+ const generatedAt = new Date(data.generatedAt).toISOString().slice(0, 16).replace('T', ' ') + ' UTC';
12
+
13
+ const out = template
14
+ .replace('__DATA_JSON__', JSON.stringify(data).replace(/</g, '\\u003c'))
15
+ .replace('__GENERATED_AT__', generatedAt)
16
+ .replace('__TOTAL_APPS__', String(totalApps))
17
+ .replace('__TOTAL_SHOTS__', String(totalShots));
18
+
19
+ const outPath = process.argv[2];
20
+ writeFileSync(outPath, out);
21
+ console.log('wrote', outPath, '(' + (out.length / 1024).toFixed(0) + ' KB)');