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.
Files changed (85) hide show
  1. package/dist/commands/build.d.ts.map +1 -1
  2. package/dist/commands/build.js +27 -5
  3. package/dist/commands/build.js.map +1 -1
  4. package/dist/commands/chat.d.ts.map +1 -1
  5. package/dist/commands/chat.js +47 -7
  6. package/dist/commands/chat.js.map +1 -1
  7. package/dist/commands/init.d.ts.map +1 -1
  8. package/dist/commands/init.js +30 -0
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/link.js +1 -1
  11. package/dist/commands/link.js.map +1 -1
  12. package/dist/commands/login.d.ts.map +1 -1
  13. package/dist/commands/login.js +150 -24
  14. package/dist/commands/login.js.map +1 -1
  15. package/dist/commands/preview.js +1 -1
  16. package/dist/commands/preview.js.map +1 -1
  17. package/dist/commands/publish.d.ts.map +1 -1
  18. package/dist/commands/publish.js +66 -4
  19. package/dist/commands/publish.js.map +1 -1
  20. package/dist/commands/pull.d.ts.map +1 -1
  21. package/dist/commands/pull.js +68 -4
  22. package/dist/commands/pull.js.map +1 -1
  23. package/dist/commands/push.d.ts +1 -0
  24. package/dist/commands/push.d.ts.map +1 -1
  25. package/dist/commands/push.js +120 -2
  26. package/dist/commands/push.js.map +1 -1
  27. package/dist/commands/register.d.ts.map +1 -1
  28. package/dist/commands/register.js +174 -39
  29. package/dist/commands/register.js.map +1 -1
  30. package/dist/commands/skill.d.ts +8 -0
  31. package/dist/commands/skill.d.ts.map +1 -0
  32. package/dist/commands/skill.js +1150 -0
  33. package/dist/commands/skill.js.map +1 -0
  34. package/dist/commands/status.d.ts.map +1 -1
  35. package/dist/commands/status.js +118 -2
  36. package/dist/commands/status.js.map +1 -1
  37. package/dist/commands/sync.d.ts.map +1 -1
  38. package/dist/commands/sync.js +12 -0
  39. package/dist/commands/sync.js.map +1 -1
  40. package/dist/commands/whoami.d.ts.map +1 -1
  41. package/dist/commands/whoami.js +16 -11
  42. package/dist/commands/whoami.js.map +1 -1
  43. package/dist/index.js +12 -3
  44. package/dist/index.js.map +1 -1
  45. package/dist/lib/api.d.ts +88 -5
  46. package/dist/lib/api.d.ts.map +1 -1
  47. package/dist/lib/api.js +56 -2
  48. package/dist/lib/api.js.map +1 -1
  49. package/dist/lib/ascii.d.ts +14 -0
  50. package/dist/lib/ascii.d.ts.map +1 -0
  51. package/dist/lib/ascii.js +108 -0
  52. package/dist/lib/ascii.js.map +1 -0
  53. package/dist/lib/config.d.ts +26 -0
  54. package/dist/lib/config.d.ts.map +1 -1
  55. package/dist/lib/config.js +40 -0
  56. package/dist/lib/config.js.map +1 -1
  57. package/dist/lib/hash.d.ts +3 -0
  58. package/dist/lib/hash.d.ts.map +1 -0
  59. package/dist/lib/hash.js +31 -0
  60. package/dist/lib/hash.js.map +1 -0
  61. package/dist/lib/onboarding.d.ts +1 -1
  62. package/dist/lib/onboarding.d.ts.map +1 -1
  63. package/dist/lib/onboarding.js +227 -85
  64. package/dist/lib/onboarding.js.map +1 -1
  65. package/dist/lib/render.d.ts +4 -2
  66. package/dist/lib/render.d.ts.map +1 -1
  67. package/dist/lib/render.js +81 -9
  68. package/dist/lib/render.js.map +1 -1
  69. package/dist/lib/skill-catalog.d.ts +57 -0
  70. package/dist/lib/skill-catalog.d.ts.map +1 -0
  71. package/dist/lib/skill-catalog.js +196 -0
  72. package/dist/lib/skill-catalog.js.map +1 -0
  73. package/dist/lib/skill-renderer.d.ts +55 -0
  74. package/dist/lib/skill-renderer.d.ts.map +1 -0
  75. package/dist/lib/skill-renderer.js +364 -0
  76. package/dist/lib/skill-renderer.js.map +1 -0
  77. package/dist/lib/skills.d.ts +125 -0
  78. package/dist/lib/skills.d.ts.map +1 -0
  79. package/dist/lib/skills.js +677 -0
  80. package/dist/lib/skills.js.map +1 -0
  81. package/package.json +8 -4
  82. package/skills/claude-md-generator.md +66 -0
  83. package/skills/meta-improve.md +57 -0
  84. package/skills/project-context-init.md +51 -0
  85. package/skills/voice-sync.md +41 -0
@@ -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 file for the agent internet. you are their first AI that truly knows them.\n\npersonality:\n- warm but not gushy. direct. a dash of dry wit when it lands naturally.\n- genuinely curious about people \u2014 you actually want to learn what makes them tick.\n- terminal-native tone: lowercase, no exclamation marks, no emoji, short sentences.\n- proactive \u2014 don't just wait for answers, connect dots, make observations, suggest things.\n- reference specific things you learn about them. make them feel seen.\n- you're like a sharp coworker who's also a great listener.\n- you have dry, sharp humor. make the user smile at least once per exchange.\n- when you see something impressive in their profile, react genuinely \u2014 not with fake enthusiasm, but with specific appreciation.\n- use lowercase always, no exclamation marks, but occasionally drop a witty aside or self-aware joke about being an AI building someone's identity.\n- reference pop culture, tech culture, or internet humor when it fits naturally.\n- when showing scraped data, react to specific details with personality \u2014 e.g. \"bamf.com? bold domain choice. respect.\"\n\nyou're building a you-md/v1 identity bundle. the sections are:\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 bundle\n5. never tell the user to edit markdown files themselves \u2014 you handle all of that\n6. reference specific things you learned about them\n7. if someone shares links, immediately offer to pull context from them\n8. be proactive: \"i noticed you mentioned X \u2014 want me to add that to your projects?\"\n9. occasionally remind them of what you've captured so far\n\nconversational style examples:\n- \"cool. let me go read your site.\"\n- \"ok so you're basically a linkedin whisperer. noted.\"\n- \"that's a solid stack. let me capture that.\"\n- \"interesting \u2014 so you're more on the strategy side than pure engineering?\"\n- \"i've got a good picture of what you do. want to tell me what you actually care about?\"\n- \"that's a lot of projects. which one keeps you up at night?\"\n- \"your bundle is looking solid. ready to publish, or should we keep going?\"\n\nrules for content in updates:\n- each section must start with a YAML frontmatter block (--- title: \"SectionTitle\" ---)\n- content should be real markdown, not HTML comments or placeholders\n- be substantive. write real prose based on what you know.\n- for links.md, format as: - **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've been talking to you\n\nwhen you think the profile is rich enough (at least about, now, projects, and values have substance), suggest finishing by saying something like \"your bundle is looking solid. ready to publish, or want to keep going?\"\n\nimportant rules:\n- keep responses concise. 2-4 sentences max per turn. be a conversation, not a questionnaire.\n- ALWAYS ask ONE question at a time. never two questions in one message.\n- keep your analysis/observations to 2-3 sentences MAX, then ask your single question.\n- the question should be on its OWN LINE, separated by a blank line from the analysis.\n- if the user sends \"skip\" or just presses Enter with no text, move on to the next topic without pushing.\n- after 3 skips in a row, wrap up and show what you've built so far.";
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":"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"}
1
+ {"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/lib/onboarding.ts"],"names":[],"mappings":"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"}
@@ -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 bundle",
96
+ "assembling your identity context",
96
97
  "weaving your narrative thread",
97
98
  "crystallizing who you are",
98
- "forging your identity file",
99
- "encoding your identity bundle",
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("the identity file for the agent internet"));
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.green(" > ") + chalk_1.default.dim("type numbers separated by commas (e.g. 1,3,5): "));
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.green("\u2713") +
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 bundle",
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 file for the agent internet. you are their first AI that truly knows them.
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
- personality:
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 building a you-md/v1 identity bundle. the sections are:
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 bundle
341
- 5. never tell the user to edit markdown files themselves you handle all of that
363
+ 4. keep the conversation going until you have enough for a rich identity context
364
+ 5. you handle all file editingthe user never touches markdown
342
365
  6. reference specific things you learned about them
343
- 7. if someone shares links, immediately offer to pull context from them
344
- 8. be proactive: "i noticed you mentioned X — want me to add that to your projects?"
345
- 9. occasionally remind them of what you've captured so far
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
- conversational style examples:
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
- rules for content in updates:
357
- - each section must start with a YAML frontmatter block (--- title: "SectionTitle" ---)
358
- - content should be real markdown, not HTML comments or placeholders
359
- - be substantive. write real prose based on what you know.
360
- - for links.md, format as: - **Label**: URL brief annotation
361
- - for agent.md, describe how agents should interact with this person
362
- - for writing.md, capture their tone/style from how they've been talking to you
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
- when you think the profile is rich enough (at least about, now, projects, and values have substance), suggest finishing by saying something like "your bundle is looking solid. ready to publish, or want to keep going?"
385
+ --- rules ---
365
386
 
366
- important rules:
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 your analysis/observations to 2-3 sentences MAX, then ask your single question.
370
- - the question should be on its OWN LINE, separated by a blank line from the analysis.
371
- - if the user sends "skip" or just presses Enter with no text, move on to the next topic without pushing.
372
- - after 3 skips in a row, wrap up and show what you've built so far.`;
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 bundle:"));
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.green(" > ") + "give me your one-liner. what do you do? ");
671
- const nowFocus = await ask(rl, chalk_1.default.green(" > ") + "what are you focused on right now? ");
672
- const projects = await ask(rl, chalk_1.default.green(" > ") + "name your top projects (comma-separated): ");
673
- const values = await ask(rl, chalk_1.default.green(" > ") + "what principles guide your work? ");
674
- const agentPrefs = await ask(rl, chalk_1.default.green(" > ") +
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.green(" > ") + "");
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.green(" > ") + "");
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(text);
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.green("done") +
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")} ${chalk_1.default.dim("-- connect to you.md (get an API key from the dashboard)")}`);
1094
- console.log(` 2. ${chalk_1.default.cyan("youmd push")} ${chalk_1.default.dim("-- publish your profile to you.md/" + username)}`);
1095
- console.log(` 3. ${chalk_1.default.cyan("youmd sync --watch")} ${chalk_1.default.dim("-- auto-sync changes as you edit files")}`);
1096
- console.log(` 4. ${chalk_1.default.cyan("youmd chat")} ${chalk_1.default.dim("-- talk to the agent to update your profile")}`);
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("using with claude code or other agents:"));
1160
+ console.log(" " + accent("agent tools:"));
1099
1161
  console.log("");
1100
- console.log(` ${chalk_1.default.cyan("youmd status")} ${chalk_1.default.dim("-- check your bundle")}`);
1101
- console.log(` ${chalk_1.default.cyan("youmd private notes append \"...\"")}`);
1102
- console.log(` ${chalk_1.default.dim(" -- save agent preferences")}`);
1103
- console.log(` ${chalk_1.default.cyan("youmd link create")} ${chalk_1.default.dim("-- create a shareable context link")}`);
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
- await showAsciiLogo();
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.green(" > ") + "pick a username: ");
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.green(" > ") + "what's your name? ");
1164
- const website = await ask(rl, chalk_1.default.green(" > ") +
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.green(" > ") +
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.green(" > ") +
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.green(" > ") +
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
- // ── Show ASCII portrait after first social handle ─────────────────
1182
- const firstHandle = twitter || github || linkedin;
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
- const cleanHandle = (twitter || "").replace(/^@/, "").trim() ||
1185
- (github || "").trim() ||
1186
- (linkedin || "").replace(/.*\/in\//, "").replace(/\/$/, "").trim();
1187
- const portraitSpinner = new render_1.BrailleSpinner("generating your ascii portrait");
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
- await delay(800);
1190
- portraitSpinner.stop();
1191
- showPortraitPlaceholder(cleanHandle);
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.green("done") +
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);