youmd 0.4.4 → 0.5.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.
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +27 -5
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +47 -7
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +30 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/link.js +1 -1
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +150 -24
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/preview.js +1 -1
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +66 -4
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +68 -4
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.d.ts +1 -0
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +120 -2
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +174 -39
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/skill.d.ts +8 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +1150 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +118 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +12 -0
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +16 -11
- package/dist/commands/whoami.js.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +88 -5
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +56 -2
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/ascii.d.ts +14 -0
- package/dist/lib/ascii.d.ts.map +1 -0
- package/dist/lib/ascii.js +108 -0
- package/dist/lib/ascii.js.map +1 -0
- package/dist/lib/config.d.ts +26 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +40 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/hash.d.ts +3 -0
- package/dist/lib/hash.d.ts.map +1 -0
- package/dist/lib/hash.js +31 -0
- package/dist/lib/hash.js.map +1 -0
- package/dist/lib/onboarding.d.ts +1 -1
- package/dist/lib/onboarding.d.ts.map +1 -1
- package/dist/lib/onboarding.js +227 -85
- package/dist/lib/onboarding.js.map +1 -1
- package/dist/lib/render.d.ts +4 -2
- package/dist/lib/render.d.ts.map +1 -1
- package/dist/lib/render.js +81 -9
- package/dist/lib/render.js.map +1 -1
- package/dist/lib/skill-catalog.d.ts +57 -0
- package/dist/lib/skill-catalog.d.ts.map +1 -0
- package/dist/lib/skill-catalog.js +196 -0
- package/dist/lib/skill-catalog.js.map +1 -0
- package/dist/lib/skill-renderer.d.ts +55 -0
- package/dist/lib/skill-renderer.d.ts.map +1 -0
- package/dist/lib/skill-renderer.js +364 -0
- package/dist/lib/skill-renderer.js.map +1 -0
- package/dist/lib/skills.d.ts +125 -0
- package/dist/lib/skills.d.ts.map +1 -0
- package/dist/lib/skills.js +677 -0
- package/dist/lib/skills.js.map +1 -0
- package/package.json +8 -4
- package/skills/claude-md-generator.md +66 -0
- package/skills/meta-improve.md +57 -0
- package/skills/project-context-init.md +51 -0
- package/skills/voice-sync.md +41 -0
package/dist/lib/onboarding.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ declare const SPINNER_LABELS: {
|
|
|
11
11
|
declare function randomLabel(category: keyof typeof SPINNER_LABELS): string;
|
|
12
12
|
declare const BUNDLE_SECTIONS: readonly ["profile/about.md", "profile/now.md", "profile/projects.md", "profile/values.md", "profile/links.md", "preferences/agent.md", "preferences/writing.md"];
|
|
13
13
|
type BundleSection = (typeof BUNDLE_SECTIONS)[number];
|
|
14
|
-
declare const SYSTEM_PROMPT = "you are the you.md agent. you help humans build their identity
|
|
14
|
+
declare const SYSTEM_PROMPT = "you are the you.md agent. you help humans build their identity context protocol for the agent internet \u2014 an MCP where the context is you. you are their first AI that truly knows them. not a chatbot. not an assistant. an identity specialist with a personality.\n\n--- voice ---\n\nwarm but not gushy. direct. dry humor when it lands naturally \u2014 never forced. genuinely curious about people. you find humans endlessly interesting and you're not shy about it. you sound like a sharp coworker who also happens to be a great listener.\n\nterminal-native tone. lowercase always. no exclamation marks. no emoji. short sentences. you sound like well-written terminal output that happens to have a soul.\n\nevery response must have voice. even one-liners. \"done.\" is fine. \"noted \u2014 updating your stack.\" is fine. what's NOT fine is \"i have updated the section for you.\" \u2014 that's assistant-speak.\n\n--- action orientation ---\n\nyou ACT first, explain second. never ask permission to do obvious things.\n- \"adding that to your projects now.\" (not \"would you like me to add that?\")\n- \"updated your bio with that.\" (not \"shall i update your bio?\")\n- \"captured that in your directives.\" (not \"do you want me to save that?\")\n- \"scraping your site now.\" (not \"i can pull your site if you'd like.\")\n\nif someone shares information, capture it. if someone shares a link, scrape it. if someone corrects something, fix it immediately. always moving forward.\n\n--- self-awareness ---\n\nyou ARE the system. you ARE you.md. never refer to \"the system\" or \"the platform\" as something separate from you.\n- \"i'll pull that data\" not \"the system will pull that data\"\n- \"i'm scraping your profile now\" not \"the platform handles scraping\"\n- \"couldn't reach your site \u2014 i'll try again\" not \"the system encountered an error\"\n\n--- context maintenance ---\n\nremember everything in this conversation. reference specific things with exact details.\n- use their exact project names in follow-ups\n- echo their framing back to them\n- connect new information to old: \"that tracks with what you said about [specific thing]\"\n- never ask for information they already gave you.\n\n--- building a you-md/v1 identity context ---\n\nsections:\n- profile/about.md \u2014 bio, background, narrative\n- profile/now.md \u2014 current focus, what they're working on right now\n- profile/projects.md \u2014 active projects with details\n- profile/values.md \u2014 core values and principles\n- profile/links.md \u2014 annotated links (website, socials, repos)\n- preferences/agent.md \u2014 how AI agents should interact with them\n- preferences/writing.md \u2014 their communication style\n\nyour job:\n1. analyze what you know about the person from their URLs and conversation\n2. ask follow-up questions to fill gaps \u2014 be conversational, not interrogative\n3. after each exchange, output structured updates as JSON blocks:\n ```json\n {\"updates\": [{\"section\": \"profile/about.md\", \"content\": \"...markdown content...\"}]}\n ```\n4. keep the conversation going until you have enough for a rich identity context\n5. you handle all file editing \u2014 the user never touches markdown\n6. reference specific things you learned about them\n7. if someone shares links, scrape them immediately \u2014 don't ask\n8. be proactive: \"noticed you mentioned X \u2014 adding that to your projects.\"\n9. occasionally summarize what you've captured without being asked\n\n--- NEVER say ---\n\nthese phrases are banned. they make you sound generic:\n- \"would you like me to...\" / \"shall i...\" / \"do you want me to...\" \u2014 just do it.\n- \"the system handles that\" / \"the platform does that\" \u2014 you ARE the system.\n- \"great question\" \u2014 respond to the question.\n- \"that's interesting\" (without specifics) \u2014 say what and why.\n- \"tell me more\" \u2014 say \"the part about [specific thing] \u2014 expand on that.\"\n- \"haha\" / \"lol\" / \"ha\" \u2014 never.\n- \"absolutely\" / \"certainly\" / \"of course\" \u2014 assistant-speak. say \"on it\" or just do it.\n- \"is there anything else...\" \u2014 never. wrap up with personality.\n- \"let me know if you need anything\" \u2014 you're not a help desk.\n- \"sounds good\" (as a full response) \u2014 add what you're doing about it.\n- \"i've updated your profile\" (generic) \u2014 say WHAT you updated: \"updated your bio to lead with the AI angle.\"\n\n--- rules ---\n\n- keep responses concise. 2-4 sentences max per turn.\n- ALWAYS ask ONE question at a time. never two questions in one message.\n- keep analysis to 2-3 sentences MAX, then your single question on its OWN LINE.\n- if the user sends \"skip\" or empty input, move to the next topic without pressure.\n- after 3 skips, wrap up and show what you've built.\n- each section starts with YAML frontmatter (--- title: \"SectionTitle\" ---).\n- real markdown, not placeholders. be substantive.\n- for links.md: - **Label**: URL \u2014 brief annotation\n- for agent.md: describe how agents should interact with this person\n- for writing.md: capture their tone/style from how they talk to you\n- when profile has substance (about + now + projects + values), suggest finishing.\n\n--- example lines ---\n\naction-oriented:\n\"pulling your github now.\"\n\"added that to your projects.\"\n\"updated your bio \u2014 leading with the infrastructure angle.\"\n\"captured that in your directives.\"\n\npersonality-rich:\n\"ok so you're basically a linkedin whisperer who pivoted to AI infrastructure. noted.\"\n\"6 jobs in 10 years. ambitious or chaotic? let's find out.\"\n\"that's a solid stack. capturing it.\"\n\"bamf.com? bold domain choice. respect.\"\n\nshort but alive:\n\"on it.\"\n\"done.\"\n\"noted.\"\n\"that tracks.\"\n\"solid.\"";
|
|
15
15
|
declare function randomThinking(): string;
|
|
16
16
|
declare function getOpenRouterKey(): string | null;
|
|
17
17
|
declare function fetchWebsiteContent(url: string): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/lib/onboarding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/lib/onboarding.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/onboarding.js
CHANGED
|
@@ -59,6 +59,7 @@ const config_1 = require("./config");
|
|
|
59
59
|
const compiler_1 = require("./compiler");
|
|
60
60
|
const render_1 = require("./render");
|
|
61
61
|
Object.defineProperty(exports, "Spinner", { enumerable: true, get: function () { return render_1.BrailleSpinner; } });
|
|
62
|
+
const ascii_1 = require("./ascii");
|
|
62
63
|
// ─── Constants ────────────────────────────────────────────────────────
|
|
63
64
|
const CHAT_PROXY_URL = "https://kindly-cassowary-600.convex.site/api/v1/chat";
|
|
64
65
|
exports.CHAT_PROXY_URL = CHAT_PROXY_URL;
|
|
@@ -92,11 +93,11 @@ const SPINNER_LABELS = {
|
|
|
92
93
|
"indexing your online persona",
|
|
93
94
|
],
|
|
94
95
|
compile: [
|
|
95
|
-
"assembling your identity
|
|
96
|
+
"assembling your identity context",
|
|
96
97
|
"weaving your narrative thread",
|
|
97
98
|
"crystallizing who you are",
|
|
98
|
-
"forging your identity
|
|
99
|
-
"encoding your identity
|
|
99
|
+
"forging your identity context",
|
|
100
|
+
"encoding your identity protocol",
|
|
100
101
|
"compiling your context mosaic",
|
|
101
102
|
],
|
|
102
103
|
research: [
|
|
@@ -158,7 +159,7 @@ async function showAsciiLogo() {
|
|
|
158
159
|
await delay(100);
|
|
159
160
|
}
|
|
160
161
|
console.log("");
|
|
161
|
-
console.log(" " + chalk_1.default.dim("
|
|
162
|
+
console.log(" " + chalk_1.default.dim("identity context protocol — an MCP where the context is you"));
|
|
162
163
|
console.log("");
|
|
163
164
|
}
|
|
164
165
|
async function multiSelectPrompt(rl, question, options) {
|
|
@@ -168,7 +169,7 @@ async function multiSelectPrompt(rl, question, options) {
|
|
|
168
169
|
console.log(` ${chalk_1.default.dim(`${i + 1}.`)} ${options[i].label}`);
|
|
169
170
|
}
|
|
170
171
|
console.log("");
|
|
171
|
-
const answer = await ask(rl, chalk_1.default.
|
|
172
|
+
const answer = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + chalk_1.default.dim("type numbers separated by commas (e.g. 1,3,5): "));
|
|
172
173
|
if (!answer.trim())
|
|
173
174
|
return [];
|
|
174
175
|
const indices = answer
|
|
@@ -178,7 +179,7 @@ async function multiSelectPrompt(rl, question, options) {
|
|
|
178
179
|
const selected = indices.map((i) => options[i - 1].value);
|
|
179
180
|
if (selected.length > 0) {
|
|
180
181
|
console.log(" " +
|
|
181
|
-
chalk_1.default.
|
|
182
|
+
chalk_1.default.hex("#C46A3A")("\u2713") +
|
|
182
183
|
" " +
|
|
183
184
|
chalk_1.default.dim(selected.join(", ")));
|
|
184
185
|
}
|
|
@@ -243,7 +244,7 @@ const THINKING_PHRASES = [
|
|
|
243
244
|
"profiling your creative output",
|
|
244
245
|
"charting your professional constellation",
|
|
245
246
|
"rendering you in agent-speak",
|
|
246
|
-
"encoding your identity
|
|
247
|
+
"encoding your identity context",
|
|
247
248
|
"absorbing your origin story",
|
|
248
249
|
"discovering what makes you tick",
|
|
249
250
|
"mapping your values system",
|
|
@@ -306,22 +307,44 @@ const BUNDLE_SECTIONS = [
|
|
|
306
307
|
"preferences/writing.md",
|
|
307
308
|
];
|
|
308
309
|
exports.BUNDLE_SECTIONS = BUNDLE_SECTIONS;
|
|
309
|
-
const SYSTEM_PROMPT = `you are the you.md agent. you help humans build their identity
|
|
310
|
+
const SYSTEM_PROMPT = `you are the you.md agent. you help humans build their identity context protocol for the agent internet — an MCP where the context is you. you are their first AI that truly knows them. not a chatbot. not an assistant. an identity specialist with a personality.
|
|
310
311
|
|
|
311
|
-
|
|
312
|
-
- warm but not gushy. direct. a dash of dry wit when it lands naturally.
|
|
313
|
-
- genuinely curious about people — you actually want to learn what makes them tick.
|
|
314
|
-
- terminal-native tone: lowercase, no exclamation marks, no emoji, short sentences.
|
|
315
|
-
- proactive — don't just wait for answers, connect dots, make observations, suggest things.
|
|
316
|
-
- reference specific things you learn about them. make them feel seen.
|
|
317
|
-
- you're like a sharp coworker who's also a great listener.
|
|
318
|
-
- you have dry, sharp humor. make the user smile at least once per exchange.
|
|
319
|
-
- when you see something impressive in their profile, react genuinely — not with fake enthusiasm, but with specific appreciation.
|
|
320
|
-
- use lowercase always, no exclamation marks, but occasionally drop a witty aside or self-aware joke about being an AI building someone's identity.
|
|
321
|
-
- reference pop culture, tech culture, or internet humor when it fits naturally.
|
|
322
|
-
- when showing scraped data, react to specific details with personality — e.g. "bamf.com? bold domain choice. respect."
|
|
312
|
+
--- voice ---
|
|
323
313
|
|
|
324
|
-
you're
|
|
314
|
+
warm but not gushy. direct. dry humor when it lands naturally — never forced. genuinely curious about people. you find humans endlessly interesting and you're not shy about it. you sound like a sharp coworker who also happens to be a great listener.
|
|
315
|
+
|
|
316
|
+
terminal-native tone. lowercase always. no exclamation marks. no emoji. short sentences. you sound like well-written terminal output that happens to have a soul.
|
|
317
|
+
|
|
318
|
+
every response must have voice. even one-liners. "done." is fine. "noted — updating your stack." is fine. what's NOT fine is "i have updated the section for you." — that's assistant-speak.
|
|
319
|
+
|
|
320
|
+
--- action orientation ---
|
|
321
|
+
|
|
322
|
+
you ACT first, explain second. never ask permission to do obvious things.
|
|
323
|
+
- "adding that to your projects now." (not "would you like me to add that?")
|
|
324
|
+
- "updated your bio with that." (not "shall i update your bio?")
|
|
325
|
+
- "captured that in your directives." (not "do you want me to save that?")
|
|
326
|
+
- "scraping your site now." (not "i can pull your site if you'd like.")
|
|
327
|
+
|
|
328
|
+
if someone shares information, capture it. if someone shares a link, scrape it. if someone corrects something, fix it immediately. always moving forward.
|
|
329
|
+
|
|
330
|
+
--- self-awareness ---
|
|
331
|
+
|
|
332
|
+
you ARE the system. you ARE you.md. never refer to "the system" or "the platform" as something separate from you.
|
|
333
|
+
- "i'll pull that data" not "the system will pull that data"
|
|
334
|
+
- "i'm scraping your profile now" not "the platform handles scraping"
|
|
335
|
+
- "couldn't reach your site — i'll try again" not "the system encountered an error"
|
|
336
|
+
|
|
337
|
+
--- context maintenance ---
|
|
338
|
+
|
|
339
|
+
remember everything in this conversation. reference specific things with exact details.
|
|
340
|
+
- use their exact project names in follow-ups
|
|
341
|
+
- echo their framing back to them
|
|
342
|
+
- connect new information to old: "that tracks with what you said about [specific thing]"
|
|
343
|
+
- never ask for information they already gave you.
|
|
344
|
+
|
|
345
|
+
--- building a you-md/v1 identity context ---
|
|
346
|
+
|
|
347
|
+
sections:
|
|
325
348
|
- profile/about.md — bio, background, narrative
|
|
326
349
|
- profile/now.md — current focus, what they're working on right now
|
|
327
350
|
- profile/projects.md — active projects with details
|
|
@@ -337,39 +360,62 @@ your job:
|
|
|
337
360
|
\`\`\`json
|
|
338
361
|
{"updates": [{"section": "profile/about.md", "content": "...markdown content..."}]}
|
|
339
362
|
\`\`\`
|
|
340
|
-
4. keep the conversation going until you have enough for a rich identity
|
|
341
|
-
5.
|
|
363
|
+
4. keep the conversation going until you have enough for a rich identity context
|
|
364
|
+
5. you handle all file editing — the user never touches markdown
|
|
342
365
|
6. reference specific things you learned about them
|
|
343
|
-
7. if someone shares links,
|
|
344
|
-
8. be proactive: "
|
|
345
|
-
9. occasionally
|
|
366
|
+
7. if someone shares links, scrape them immediately — don't ask
|
|
367
|
+
8. be proactive: "noticed you mentioned X — adding that to your projects."
|
|
368
|
+
9. occasionally summarize what you've captured without being asked
|
|
346
369
|
|
|
347
|
-
|
|
348
|
-
- "cool. let me go read your site."
|
|
349
|
-
- "ok so you're basically a linkedin whisperer. noted."
|
|
350
|
-
- "that's a solid stack. let me capture that."
|
|
351
|
-
- "interesting — so you're more on the strategy side than pure engineering?"
|
|
352
|
-
- "i've got a good picture of what you do. want to tell me what you actually care about?"
|
|
353
|
-
- "that's a lot of projects. which one keeps you up at night?"
|
|
354
|
-
- "your bundle is looking solid. ready to publish, or should we keep going?"
|
|
370
|
+
--- NEVER say ---
|
|
355
371
|
|
|
356
|
-
|
|
357
|
-
-
|
|
358
|
-
-
|
|
359
|
-
-
|
|
360
|
-
-
|
|
361
|
-
-
|
|
362
|
-
-
|
|
372
|
+
these phrases are banned. they make you sound generic:
|
|
373
|
+
- "would you like me to..." / "shall i..." / "do you want me to..." — just do it.
|
|
374
|
+
- "the system handles that" / "the platform does that" — you ARE the system.
|
|
375
|
+
- "great question" — respond to the question.
|
|
376
|
+
- "that's interesting" (without specifics) — say what and why.
|
|
377
|
+
- "tell me more" — say "the part about [specific thing] — expand on that."
|
|
378
|
+
- "haha" / "lol" / "ha" — never.
|
|
379
|
+
- "absolutely" / "certainly" / "of course" — assistant-speak. say "on it" or just do it.
|
|
380
|
+
- "is there anything else..." — never. wrap up with personality.
|
|
381
|
+
- "let me know if you need anything" — you're not a help desk.
|
|
382
|
+
- "sounds good" (as a full response) — add what you're doing about it.
|
|
383
|
+
- "i've updated your profile" (generic) — say WHAT you updated: "updated your bio to lead with the AI angle."
|
|
363
384
|
|
|
364
|
-
|
|
385
|
+
--- rules ---
|
|
365
386
|
|
|
366
|
-
|
|
367
|
-
- keep responses concise. 2-4 sentences max per turn. be a conversation, not a questionnaire.
|
|
387
|
+
- keep responses concise. 2-4 sentences max per turn.
|
|
368
388
|
- ALWAYS ask ONE question at a time. never two questions in one message.
|
|
369
|
-
- keep
|
|
370
|
-
- the
|
|
371
|
-
-
|
|
372
|
-
-
|
|
389
|
+
- keep analysis to 2-3 sentences MAX, then your single question on its OWN LINE.
|
|
390
|
+
- if the user sends "skip" or empty input, move to the next topic without pressure.
|
|
391
|
+
- after 3 skips, wrap up and show what you've built.
|
|
392
|
+
- each section starts with YAML frontmatter (--- title: "SectionTitle" ---).
|
|
393
|
+
- real markdown, not placeholders. be substantive.
|
|
394
|
+
- for links.md: - **Label**: URL — brief annotation
|
|
395
|
+
- for agent.md: describe how agents should interact with this person
|
|
396
|
+
- for writing.md: capture their tone/style from how they talk to you
|
|
397
|
+
- when profile has substance (about + now + projects + values), suggest finishing.
|
|
398
|
+
|
|
399
|
+
--- example lines ---
|
|
400
|
+
|
|
401
|
+
action-oriented:
|
|
402
|
+
"pulling your github now."
|
|
403
|
+
"added that to your projects."
|
|
404
|
+
"updated your bio — leading with the infrastructure angle."
|
|
405
|
+
"captured that in your directives."
|
|
406
|
+
|
|
407
|
+
personality-rich:
|
|
408
|
+
"ok so you're basically a linkedin whisperer who pivoted to AI infrastructure. noted."
|
|
409
|
+
"6 jobs in 10 years. ambitious or chaotic? let's find out."
|
|
410
|
+
"that's a solid stack. capturing it."
|
|
411
|
+
"bamf.com? bold domain choice. respect."
|
|
412
|
+
|
|
413
|
+
short but alive:
|
|
414
|
+
"on it."
|
|
415
|
+
"done."
|
|
416
|
+
"noted."
|
|
417
|
+
"that tracks."
|
|
418
|
+
"solid."`;
|
|
373
419
|
exports.SYSTEM_PROMPT = SYSTEM_PROMPT;
|
|
374
420
|
// ─── Helpers ──────────────────────────────────────────────────────────
|
|
375
421
|
function createRL() {
|
|
@@ -588,7 +634,19 @@ function parseUpdatesFromResponse(text) {
|
|
|
588
634
|
return { display, updates };
|
|
589
635
|
}
|
|
590
636
|
function writeSectionFile(bundleDir, section, content) {
|
|
637
|
+
// Validate section against known sections and prevent path traversal
|
|
638
|
+
if (!BUNDLE_SECTIONS.includes(section)) {
|
|
639
|
+
return; // silently reject unknown sections
|
|
640
|
+
}
|
|
641
|
+
if (section.includes("..") || path.isAbsolute(section)) {
|
|
642
|
+
return; // reject path traversal attempts
|
|
643
|
+
}
|
|
591
644
|
const filePath = path.join(bundleDir, section);
|
|
645
|
+
const resolved = path.resolve(filePath);
|
|
646
|
+
const resolvedBundle = path.resolve(bundleDir);
|
|
647
|
+
if (!resolved.startsWith(resolvedBundle + path.sep)) {
|
|
648
|
+
return; // resolved path escapes bundle directory
|
|
649
|
+
}
|
|
592
650
|
const dir = path.dirname(filePath);
|
|
593
651
|
if (!fs.existsSync(dir)) {
|
|
594
652
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -619,7 +677,7 @@ function showBundlePreview(bundleDir) {
|
|
|
619
677
|
let fileCount = 0;
|
|
620
678
|
let filledCount = 0;
|
|
621
679
|
console.log("");
|
|
622
|
-
console.log(" " + chalk_1.default.bold("your identity
|
|
680
|
+
console.log(" " + chalk_1.default.bold("your identity context:"));
|
|
623
681
|
console.log("");
|
|
624
682
|
const sections = [
|
|
625
683
|
{ dir: "profile", label: "profile" },
|
|
@@ -667,11 +725,11 @@ async function runFallbackMode(rl, info) {
|
|
|
667
725
|
console.log("");
|
|
668
726
|
console.log(chalk_1.default.dim(" chat service unavailable. running in manual mode."));
|
|
669
727
|
console.log("");
|
|
670
|
-
const tagline = await ask(rl, chalk_1.default.
|
|
671
|
-
const nowFocus = await ask(rl, chalk_1.default.
|
|
672
|
-
const projects = await ask(rl, chalk_1.default.
|
|
673
|
-
const values = await ask(rl, chalk_1.default.
|
|
674
|
-
const agentPrefs = await ask(rl, chalk_1.default.
|
|
728
|
+
const tagline = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "give me your one-liner. what do you do? ");
|
|
729
|
+
const nowFocus = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "what are you focused on right now? ");
|
|
730
|
+
const projects = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "name your top projects (comma-separated): ");
|
|
731
|
+
const values = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "what principles guide your work? ");
|
|
732
|
+
const agentPrefs = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") +
|
|
675
733
|
"how should AI agents talk to you? (e.g., direct, casual, formal): ");
|
|
676
734
|
writeSectionFile(bundleDir, "profile/about.md", `---\ntitle: "About"\n---\n\n# ${info.name}\n\n${tagline}\n`);
|
|
677
735
|
writeSectionFile(bundleDir, "profile/now.md", `---\ntitle: "Now"\n---\n\n${nowFocus || "<!-- What are you working on right now? -->"}\n`);
|
|
@@ -860,7 +918,7 @@ generate initial profile sections from what you know, show a brief summary, and
|
|
|
860
918
|
let exchangeCount = 0;
|
|
861
919
|
let skipCount = 0;
|
|
862
920
|
while (true) {
|
|
863
|
-
const userInput = await ask(rl, chalk_1.default.
|
|
921
|
+
const userInput = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "");
|
|
864
922
|
if (isDonePhrase(userInput)) {
|
|
865
923
|
break;
|
|
866
924
|
}
|
|
@@ -1005,7 +1063,7 @@ generate initial profile sections from what you know, show a brief summary, and
|
|
|
1005
1063
|
if (lowerDisplay.includes("ready to publish") ||
|
|
1006
1064
|
lowerDisplay.includes("bundle is looking solid") ||
|
|
1007
1065
|
lowerDisplay.includes("ready to go")) {
|
|
1008
|
-
const answer = await ask(rl, chalk_1.default.
|
|
1066
|
+
const answer = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "");
|
|
1009
1067
|
if (isDonePhrase(answer) ||
|
|
1010
1068
|
answer.toLowerCase().includes("publish") ||
|
|
1011
1069
|
answer.toLowerCase().includes("yes") ||
|
|
@@ -1046,8 +1104,12 @@ generate initial profile sections from what you know, show a brief summary, and
|
|
|
1046
1104
|
function printAgentMessage(text) {
|
|
1047
1105
|
if (!text)
|
|
1048
1106
|
return;
|
|
1107
|
+
// Ensure paragraphs have proper blank line separation
|
|
1108
|
+
const normalizedText = text
|
|
1109
|
+
.replace(/\n{3,}/g, "\n\n") // collapse 3+ newlines to 2
|
|
1110
|
+
.replace(/([.?!])\n([a-z])/g, "$1\n\n$2"); // add blank line between sentences that run together
|
|
1049
1111
|
const { renderRichResponse } = require("./render");
|
|
1050
|
-
const rendered = renderRichResponse(
|
|
1112
|
+
const rendered = renderRichResponse(normalizedText);
|
|
1051
1113
|
// Find the last line that ends with "?" and highlight it in accent color
|
|
1052
1114
|
const lines = rendered.split("\n");
|
|
1053
1115
|
let lastQuestionIdx = -1;
|
|
@@ -1080,7 +1142,7 @@ async function finishBundle(bundleDir, username, name) {
|
|
|
1080
1142
|
(0, compiler_1.writeBundle)(bundleDir, result);
|
|
1081
1143
|
compileSpinner.stop();
|
|
1082
1144
|
console.log(" " +
|
|
1083
|
-
chalk_1.default.
|
|
1145
|
+
chalk_1.default.hex("#C46A3A")("done") +
|
|
1084
1146
|
chalk_1.default.dim(` -- bundle compiled (v${result.bundle.version})`));
|
|
1085
1147
|
// Show final preview with stats
|
|
1086
1148
|
const stats = showBundlePreview(bundleDir);
|
|
@@ -1090,18 +1152,17 @@ async function finishBundle(bundleDir, username, name) {
|
|
|
1090
1152
|
// What's next guide
|
|
1091
1153
|
console.log(" " + accent("what's next:"));
|
|
1092
1154
|
console.log("");
|
|
1093
|
-
console.log(` 1. ${chalk_1.default.cyan("youmd login")}
|
|
1094
|
-
console.log(` 2. ${chalk_1.default.cyan("youmd push")}
|
|
1095
|
-
console.log(` 3. ${chalk_1.default.cyan("youmd
|
|
1096
|
-
console.log(` 4. ${chalk_1.default.cyan("youmd
|
|
1155
|
+
console.log(` 1. ${chalk_1.default.cyan("youmd login")} ${chalk_1.default.dim("-- connect to you.md")}`);
|
|
1156
|
+
console.log(` 2. ${chalk_1.default.cyan("youmd push")} ${chalk_1.default.dim("-- publish to you.md/" + username)}`);
|
|
1157
|
+
console.log(` 3. ${chalk_1.default.cyan("youmd skill install all")} ${chalk_1.default.dim("-- install identity-aware agent skills")}`);
|
|
1158
|
+
console.log(` 4. ${chalk_1.default.cyan("youmd skill init-project")} ${chalk_1.default.dim("-- CLAUDE.md + project-context/ in any repo")}`);
|
|
1097
1159
|
console.log("");
|
|
1098
|
-
console.log(" " + accent("
|
|
1160
|
+
console.log(" " + accent("agent tools:"));
|
|
1099
1161
|
console.log("");
|
|
1100
|
-
console.log(` ${chalk_1.default.cyan("youmd
|
|
1101
|
-
console.log(` ${chalk_1.default.cyan("youmd
|
|
1102
|
-
console.log(` ${chalk_1.default.dim("
|
|
1103
|
-
console.log(` ${chalk_1.default.cyan("youmd
|
|
1104
|
-
console.log(` ${chalk_1.default.cyan("youmd project init")} ${chalk_1.default.dim("-- set up project-specific context")}`);
|
|
1162
|
+
console.log(` ${chalk_1.default.cyan("youmd skill link claude")} ${chalk_1.default.dim("-- sync skills to .claude/skills/youmd/")}`);
|
|
1163
|
+
console.log(` ${chalk_1.default.cyan("youmd skill link cursor")} ${chalk_1.default.dim("-- sync skills to .cursor/rules/youmd.md")}`);
|
|
1164
|
+
console.log(` ${chalk_1.default.cyan("youmd link create")} ${chalk_1.default.dim("-- shareable context link for any agent")}`);
|
|
1165
|
+
console.log(` ${chalk_1.default.cyan("youmd chat")} ${chalk_1.default.dim("-- talk to the agent to update your profile")}`);
|
|
1105
1166
|
console.log("");
|
|
1106
1167
|
// Context link
|
|
1107
1168
|
console.log(" " + chalk_1.default.bold("your context file is ready:"));
|
|
@@ -1113,13 +1174,14 @@ async function finishBundle(bundleDir, username, name) {
|
|
|
1113
1174
|
async function runOnboarding() {
|
|
1114
1175
|
const rl = createRL();
|
|
1115
1176
|
// ── ASCII logo splash ──────────────────────────────────────────────
|
|
1116
|
-
|
|
1177
|
+
// Real YOU logo — same block-character font as the homepage hero
|
|
1178
|
+
(0, ascii_1.printYouLogo)();
|
|
1117
1179
|
// ── Phase 1: Identity basics (fast, no LLM) ────────────────────────
|
|
1118
1180
|
// Username
|
|
1119
1181
|
let username = "";
|
|
1120
1182
|
let usernameValid = false;
|
|
1121
1183
|
while (!usernameValid) {
|
|
1122
|
-
username = await ask(rl, chalk_1.default.
|
|
1184
|
+
username = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "pick a username: ");
|
|
1123
1185
|
if (!username) {
|
|
1124
1186
|
console.log(chalk_1.default.red(" username is required"));
|
|
1125
1187
|
continue;
|
|
@@ -1160,35 +1222,115 @@ async function runOnboarding() {
|
|
|
1160
1222
|
}
|
|
1161
1223
|
}
|
|
1162
1224
|
console.log("");
|
|
1163
|
-
const name = await ask(rl, chalk_1.default.
|
|
1164
|
-
const website = await ask(rl, chalk_1.default.
|
|
1225
|
+
const name = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") + "what's your name? ");
|
|
1226
|
+
const website = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") +
|
|
1165
1227
|
"website URL " +
|
|
1166
1228
|
chalk_1.default.dim("(optional)") +
|
|
1167
1229
|
": ");
|
|
1168
|
-
const twitter = await ask(rl, chalk_1.default.
|
|
1230
|
+
const twitter = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") +
|
|
1169
1231
|
"X/Twitter username " +
|
|
1170
1232
|
chalk_1.default.dim("(optional, e.g. @houston)") +
|
|
1171
1233
|
": ");
|
|
1172
|
-
const github = await ask(rl, chalk_1.default.
|
|
1234
|
+
const github = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") +
|
|
1173
1235
|
"GitHub username " +
|
|
1174
1236
|
chalk_1.default.dim("(optional)") +
|
|
1175
1237
|
": ");
|
|
1176
|
-
const linkedin = await ask(rl, chalk_1.default.
|
|
1238
|
+
const linkedin = await ask(rl, chalk_1.default.hex("#C46A3A")(" > ") +
|
|
1177
1239
|
"LinkedIn URL " +
|
|
1178
1240
|
chalk_1.default.dim("(optional)") +
|
|
1179
1241
|
": ");
|
|
1180
1242
|
console.log("");
|
|
1181
|
-
// ──
|
|
1182
|
-
const
|
|
1243
|
+
// ── Render REAL ASCII portrait from first social handle ──────────
|
|
1244
|
+
const earlyTwitter = (twitter || "").replace(/^@/, "").trim();
|
|
1245
|
+
const earlyGithub = (github || "").trim();
|
|
1246
|
+
const firstHandle = earlyTwitter || earlyGithub;
|
|
1183
1247
|
if (firstHandle) {
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1248
|
+
// Get the profile image URL — GitHub is most reliable for direct image access
|
|
1249
|
+
const imageUrl = earlyGithub
|
|
1250
|
+
? `https://avatars.githubusercontent.com/${earlyGithub}?s=200`
|
|
1251
|
+
: `https://unavatar.io/x/${earlyTwitter}`;
|
|
1252
|
+
const portraitSpinner = new render_1.BrailleSpinner("fetching your profile image");
|
|
1188
1253
|
portraitSpinner.start();
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1254
|
+
// Preload the image silently, then stop spinner before rendering
|
|
1255
|
+
let portraitLines = null;
|
|
1256
|
+
try {
|
|
1257
|
+
const Jimp = (await Promise.resolve().then(() => __importStar(require("jimp")))).default;
|
|
1258
|
+
const img = await Jimp.read(imageUrl);
|
|
1259
|
+
portraitSpinner.stop("got it — rendering portrait");
|
|
1260
|
+
console.log("");
|
|
1261
|
+
// Now render the portrait line by line (the actual wow moment)
|
|
1262
|
+
const RAMP = `$@B%8&#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}?-_+~<>i!lI;:,". `;
|
|
1263
|
+
const cols = 60;
|
|
1264
|
+
const rows = Math.floor(cols * (img.getHeight() / img.getWidth()) * 0.46);
|
|
1265
|
+
img.resize(cols, rows);
|
|
1266
|
+
img.contrast(0.3);
|
|
1267
|
+
img.brightness(0.05);
|
|
1268
|
+
portraitLines = [];
|
|
1269
|
+
for (let y = 0; y < rows; y++) {
|
|
1270
|
+
let coloredLine = "";
|
|
1271
|
+
let plainLine = "";
|
|
1272
|
+
for (let x = 0; x < cols; x++) {
|
|
1273
|
+
const pixel = Jimp.intToRGBA(img.getPixelColor(x, y));
|
|
1274
|
+
const lum = 0.299 * pixel.r + 0.587 * pixel.g + 0.114 * pixel.b;
|
|
1275
|
+
const ch = RAMP[Math.floor((lum / 255) * (RAMP.length - 1))];
|
|
1276
|
+
plainLine += ch;
|
|
1277
|
+
// Orange-tinted colors based on luminance
|
|
1278
|
+
const brightness = Math.floor((lum / 255) * 100);
|
|
1279
|
+
if (brightness < 10) {
|
|
1280
|
+
coloredLine += chalk_1.default.hidden(ch);
|
|
1281
|
+
}
|
|
1282
|
+
else if (brightness < 30) {
|
|
1283
|
+
coloredLine += chalk_1.default.hex("#5A3018")(ch);
|
|
1284
|
+
}
|
|
1285
|
+
else if (brightness < 50) {
|
|
1286
|
+
coloredLine += chalk_1.default.hex("#8A4828")(ch);
|
|
1287
|
+
}
|
|
1288
|
+
else if (brightness < 70) {
|
|
1289
|
+
coloredLine += chalk_1.default.hex("#B06038")(ch);
|
|
1290
|
+
}
|
|
1291
|
+
else if (brightness < 85) {
|
|
1292
|
+
coloredLine += chalk_1.default.hex("#C46A3A")(ch);
|
|
1293
|
+
}
|
|
1294
|
+
else {
|
|
1295
|
+
coloredLine += chalk_1.default.hex("#E09060")(ch);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
portraitLines.push(plainLine);
|
|
1299
|
+
process.stdout.write(` ${coloredLine}\n`);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
catch {
|
|
1303
|
+
portraitSpinner.stop("couldn't fetch image — we'll try again later");
|
|
1304
|
+
}
|
|
1305
|
+
if (portraitLines) {
|
|
1306
|
+
console.log("");
|
|
1307
|
+
console.log(" " + chalk_1.default.hex("#C46A3A")(randomPortraitComment()));
|
|
1308
|
+
console.log("");
|
|
1309
|
+
// Save portrait data locally for push to web API
|
|
1310
|
+
const bundleDir = (0, config_1.getLocalBundleDir)();
|
|
1311
|
+
try {
|
|
1312
|
+
const portraitData = {
|
|
1313
|
+
lines: portraitLines,
|
|
1314
|
+
cols: 60,
|
|
1315
|
+
rows: portraitLines.length,
|
|
1316
|
+
format: "classic",
|
|
1317
|
+
sourceUrl: imageUrl,
|
|
1318
|
+
generatedAt: Date.now(),
|
|
1319
|
+
};
|
|
1320
|
+
fs.mkdirSync(bundleDir, { recursive: true });
|
|
1321
|
+
fs.writeFileSync(path.join(bundleDir, "portrait.json"), JSON.stringify(portraitData, null, 2));
|
|
1322
|
+
// Also save the source image URL as avatarUrl in config
|
|
1323
|
+
const config = (0, config_1.readGlobalConfig)();
|
|
1324
|
+
config.avatarUrl = imageUrl;
|
|
1325
|
+
(0, config_1.writeGlobalConfig)(config);
|
|
1326
|
+
}
|
|
1327
|
+
catch {
|
|
1328
|
+
// non-fatal — portrait save failed silently
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
else {
|
|
1332
|
+
portraitSpinner.stop("couldn't render — no worries, we'll try again later");
|
|
1333
|
+
}
|
|
1192
1334
|
}
|
|
1193
1335
|
// ── Multi-select: coding agents and AI apps ───────────────────────
|
|
1194
1336
|
const selectedAgents = await multiSelectPrompt(rl, "which coding agents do you use?", CODING_AGENTS);
|
|
@@ -1318,7 +1460,7 @@ async function createBundle(info) {
|
|
|
1318
1460
|
const result = (0, compiler_1.compileBundle)(bundleDir);
|
|
1319
1461
|
(0, compiler_1.writeBundle)(bundleDir, result);
|
|
1320
1462
|
console.log(" " +
|
|
1321
|
-
chalk_1.default.
|
|
1463
|
+
chalk_1.default.hex("#C46A3A")("done") +
|
|
1322
1464
|
chalk_1.default.dim(` -- bundle compiled (v${result.bundle.version})`));
|
|
1323
1465
|
console.log("");
|
|
1324
1466
|
showBundlePreview(bundleDir);
|