{"$schema":"https://ejfox.com/schema/page-twin@1.json","kind":"blog_post","url":"https://ejfox.com/blog/week-notes/2023-50","json_url":"https://ejfox.com/blog/week-notes/2023-50.json","generator":"ejfox.com/json-twin@1","data":{"cacheVersion":"2026-05-13-gear-cards","html":"<h2 class=\"\" id=\"key-projects--progress\">Key Projects &#x26; Progress</h2>\n<p class=\"\">Wrapped up big, exciting client project that I am really happy with. They had a lot of cool ideas and pushed for some really radical features that I ended up really proud of.</p>\n<h3 class=\"\" id=\"compiling-framework-docs-for-informed-ai-context\">Compiling framework docs for informed AI context</h3>\n<p class=\"\">There are two libraries that I use a lot that I often want the robot to think about first when helping me find solutions: <a href=\"https://vueuse.org\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://vueuse.org\">VueUse</a> and <a href=\"https://ui.nuxt.com/getting-started\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://ui.nuxt.com/getting-started\">Nuxt UI</a> - these frameworks are full of components and composables that make repeated patterns really easy, but often I find the robot doesn't know to use them, or how to call them properly, and they will always be changing and improving faster than an LLM corpus.</p>\n<p class=\"\">Step one to giving the robot the context is to clone the documentation, and combine all of the documentation markdown files into one markdown file that can be easily moved elsewhere.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"bash\" data-theme=\"\"><code data-language=\"bash\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#73D0FF\" class=\"\">cat</span><span style=\"color:#CCCAC2\" class=\"\"> $(</span><span style=\"color:#73D0FF\" class=\"\">find</span><span style=\"color:#D5FF80\" class=\"\"> .</span><span style=\"color:#95E6CB\" class=\"\"> -name</span><span style=\"color:#D5FF80\" class=\"\"> \"*.md\"</span><span style=\"color:#95E6CB\" class=\"\"> -type</span><span style=\"color:#D5FF80\" class=\"\"> f</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#F29E74\" class=\"\">></span><span style=\"color:#D5FF80\" class=\"\"> combined.md</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#73D0FF\" class=\"\">wc</span><span style=\"color:#95E6CB\" class=\"\"> -l</span><span style=\"color:#D5FF80\" class=\"\"> combined.md</span><span style=\"color:#B8CFE680;font-style:italic\" class=\"\"> # 6945 combined.md</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"cat $(find . -name &#x22;*.md&#x22; -type f) > combined.md\nwc -l combined.md # 6945 combined.md\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Maybe we also want to know how many tokens that is, we can use the <a href=\"https://github.com/oelmekki/tiktoken-cli\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://github.com/oelmekki/tiktoken-cli\">TikToken CLI<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" class=\"\"></path></svg></a></p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"bash\" data-theme=\"\"><code data-language=\"bash\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#73D0FF\" class=\"\">$</span><span style=\"color:#D5FF80\" class=\"\"> cat</span><span style=\"color:#D5FF80\" class=\"\"> ~/code/nuxt-ui/docs/content/combined.md</span><span style=\"color:#F29E74\" class=\"\"> |</span><span style=\"color:#73D0FF\" class=\"\"> ~/code/tiktoken-cli/./tiktoken-cli</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#B8CFE680;font-style:italic\" class=\"\"># 37163 tokens</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"$ cat ~/code/nuxt-ui/docs/content/combined.md | ~/code/tiktoken-cli/./tiktoken-cli\n# 37163 tokens\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<h3 class=\"\" id=\"evaluating-command-running-capabilities\">Evaluating command-running capabilities</h3>\n<p class=\"\">As I look into non-OpenAI LLMs to power parts of Coach Artie <a href=\"/blog/2023/how-i-built-coach-artie\" class=\"internal-link text-blue-600 dark:text-blue-400\">Blog/2023/how I Built Coach Artie</a> I think that I need to create some repeatable tests that help me evaluate how well alternatives do in a few areas.</p>\n<p class=\"\">One thing that I do now is allow the robot to call capabilities in the text of the response. If I detect a capability, I run it with the arguments supplied by the model, and add the response as a system message. Right now calling a capability looks like <code class=\"md-inline-code\">module:method(arg1, arg2)</code> - but the robot has sometimes struggled with that. I've also heard that due to the way that characters tokenize, it's easier to get the robot to improvise new method calls by using spaces, rather than special characters. I am also curious at how an XML style approach like <code class=\"md-inline-code\">&#x3C;Module method arg2=\"test\"> arg1 &#x3C;/Module></code> might compare to other syntaxes. I would also like to test different models abilities to \"chain\" capabilities, that is, call for other functionalities repeatedly until they get their answer.</p>\n<h3 class=\"\" id=\"exif-photo-printer\">EXIF Photo Printer</h3>\n<p class=\"\">I want to build a tool that will easily allow me to take a folder of images, and add a border and some metadata that I can then send to be printed as 4x5s at Walgreens. I like having the metadata on the physical photos, but it's annoying to do this, and I don't want to have to rely on third party tools like Lightroom for it.</p>\n<h3 class=\"\" id=\"experiments-with-tres-js\">Experiments with Tres JS</h3>\n<p class=\"\"><a href=\"https://tresjs.org/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://tresjs.org/\">TresJS</a> is a Vue/Nuxt wrapper for Three.js and makes it pretty easy to make reactive 3D scenes without spending a ton of time writing animation loops and importing a thousand things. Definitely want to play around with using it more.</p>\n<h2 class=\"\" id=\"creative-endeavors\">Creative Endeavors</h2>\n<p class=\"\">Bought some small wood panels to try to do gouache on - treated the surface with 2 coats of mod podge so that the wood pattern is still visible.</p>\n<h2 class=\"\" id=\"technical-accomplishments\">Technical Accomplishments</h2>\n<h3 class=\"\" id=\"npm-search-visualization\"><a href=\"https://github.com/room302studio/npm-search-viz\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://github.com/room302studio/npm-search-viz\">NPM Search Visualization<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" class=\"\"></path></svg></a></h3>\n<p class=\"\">I want an easier way to compare different npm packages that solve the same problem; I want to visualize various properties like the size, last commit, and other indicators and make a more intuitive interface for selecting a package over the default search.</p>","title":"Key Projects & Progress","metadata":{"tags":["weekly-notes","reflections","progress","code","javascript","vue","visualization"],"date":"2023-12-11T21:22:43.000Z","modified":"2025-08-28T19:08:24.000Z","dek":"In which the author concludes a successful client project, compiles documentation for informed AI context, evaluates command-running capabilities, plans an EXIF photo printer tool, experiments with Tres JS, and treats wood panels for gouache painting.","words":567,"images":0,"imageDetails":{"total":0,"cloudinary":0,"withDimensions":0},"links":5,"codeBlocks":2,"headers":{"h2":3},"toc":[{"text":"Key Projects & Progress","slug":"key-projects--progress","level":"h2","children":[{"text":"Compiling framework docs for informed AI context","slug":"compiling-framework-docs-for-informed-ai-context","level":"h3","children":[]},{"text":"Evaluating command-running capabilities","slug":"evaluating-command-running-capabilities","level":"h3","children":[]},{"text":"EXIF Photo Printer","slug":"exif-photo-printer","level":"h3","children":[]},{"text":"Experiments with Tres JS","slug":"experiments-with-tres-js","level":"h3","children":[]}]},{"text":"Creative Endeavors","slug":"creative-endeavors","level":"h2","children":[]},{"text":"Technical Accomplishments","slug":"technical-accomplishments","level":"h2","children":[{"text":"NPM Search Visualization","slug":"npm-search-visualization","level":"h3","children":[]}]}],"type":"post"}},"_links":{"self":"https://ejfox.com/blog/week-notes/2023-50.json","html":"https://ejfox.com/blog/week-notes/2023-50","index":"/blog.json"}}