"; */ ?>

software


6
Jan 26

Mad Skills to Learn The Universe

Simple wins. Always. Because it is very composable, fun to work with, and organically evolves.

LLMs are great at language and text, but they don’t know how to do anything, so they rely on something running (e.g. a server) and listening to their output. If the output is formatted in a certain way, say:

sum(41, 1)

the server / listener can convert it to code, call a “sum” function and return 42:

In this particular case we would say that LLM has a “sumtool. And the LLM would have a prompt similar to this one where it would identify that two numbers need to be added from the user’s prompt, and would “call a tool” with “sum(41, 1)“.

But that was a few years ago, where we would beg LLMs to call a tool and return the response in JSON pretty please. And sometimes it would even work, and sometimes it would not.

Fast forward to now, we have Tools, MCP, Agents, LSP, + many more acronyms. Plus LLMs are much better at following our “please JSON” begging.

However, one capability, one discovery and innovation in this field stands out: Skills. The reason it stands out is because, compared to all the hype and acronyms, Skills are… simple.

Just a Directory

A Skill is effectively a directory. That’s it.

It doesn’t require a complex registration process or a heavy framework. It requires a folder, a markdown file, and maybe a script or two. It relies on a standard structure that the Agent (current fancy name for a “piece of code that calls LLM”) knows how to traverse.

This simplicity lowers the barrier to entry significantly. The best way to learn something is to do it, hence I needed a problem to solve.

The “Dad” Problem

My kids are navigating the ways of middle/high school: one is deep in ionic bonding in Chemistry, another one is grappling with graphing sine waves in Pre-Calculus.

I can explain these concepts to them with words, or I can scribble on a napkin (which I love doing), but some concepts just need to move. They need to be visualized. I could write a Python program or a D3.js visualization for every single problem, but that takes too long, even when done directly with “the big 4“.

I needed a way to say: “Show me a covalent bond in H₂O” and have the visualization write itself, test itself, run itself, and show me that interactive covalent bond moving step by step.

Great fit for a “Skill” I thought and built salvador that can do this:

> /visualize a covalent bond in H₂O


Salvador… Who?

Salvador is an Anthropic Skill (but I hear others are adopting skills as well) that lives in my terminal. Its job is to visualize physics, math, or any other Universe concepts on demand.

The beauty is in the organization and progressive disclosure. The Agent doesn’t load the entire “visualization knowledge base” into its context window at once, like it did with MCP. It discovers the skill via metadata and only loads the heavy instructions when I actually ask for a visualization.

Here is what it looks like on disk:

salvador/
├── SKILL.md                 <-- the brain
├── scripts/                 <-- the hands
│   ├── inspect.js
│   └── setup.sh
└── templates/               <-- the scaffolding
    └── visualization.html

The Brain (SKILL.md)

This is the core. It uses a markdown format with YAML frontmatter. But inside, it’s not code – it’s a codified intent. It defines the flow: analyze the ask, divide and conquer, plan the steps / structure, code the solution, verify the result, go back if needed, etc.

The Hands (scripts/)

An agent without tools is just a chatbot. For salvador to work, it needs to “see” what it created.

A small script, inspect.js, that lives inside, spins up a headless browser. When the Agent generates a visualization, it doesn’t “hope” it works. It runs inspect.js to capture console errors and take screenshots.

If the screen, or a sequence of screens, are not what they should be, whether the laws of Physics are off, or a text overlay is misplaced, the Agent catches it, understands the problem, and rewrites the code.

The Loop

This is where the “agent” part becomes real. It’s not the usual “text in, code out.”, it’s a loop:

Idea -> Code -> Inspect -> Fix (as many times as needed) -> Render

Now, when we work on grokking a Physics problem at the kitchen table, I have a lot more than a napkin drawing: me and Salvador are cooking:

$ claude
> /visualize the difference between gravity on Earth vs Mars using a bouncing ball

Salvador picks up the intent, writes the physics simulation, tests it, fixes the gravity constant if it got it wrong, and pops open a browser window:

Humans today create and “conduct” code with or without LLMs. But complementing it with a Skill unlocks learning The Universe quark by quark, lepton by lepton.

Composable. And very open for evolution, because it is.. Simple. and Simple Wins. Always.


23
Apr 15

Question Everything

Feeding Da Brain


In 90s you would say: “I am a programmer”. Some would reply with “o.. k”. More insightful would reply with a question “which programming language?”.

21st century.. socially accepted terminology has changed a bit, now you would say “I am a developer”. Some would ask “which programming language?”. More insightful would reply with a question “which out of these 42 languages do you use the most?”

The greatest thing about using several at the same time is that feeling of constant adjustment as I jump between the languages. It feels like my brain goes through exuberant synaptogenesis over and over again building those new formations.

   What's for dinner today honey?
   Asynchronous brain refactoring with a gentle touch of "mental polish"

With all these new synapses, I came to love the fact that something that seemed so holy and “crystal right” before, now gets questioned and can easily be dismissed. Was it wrong all along? No. Did it change? No. So what changed then? Well.. perception did.

Inmates of the “Gang of Four” Prison


Design patterns are these “ways” of doing things that cripple new programmers, and imprison many senior ones. Instead of having an ability to think freely, we have all these “software standard patterns” which mostly have to do with limitations of “technology at time”.

Take big guys, like C++ / Java / C#, while they have many great features and ideas, these languages have horrible story of “behavior and state”: you always have to guard something. Whether it is from multiple threads, or from other people misusing it. The languages themselves promote reuse vs. decoupling: i.e. “let’s inherit that behavior”, etc..

So how do we overcome these risks and limitations? Simple: let’s create dozens of “ways” that all developers will follow to fight this together. Oh, yea, and let’s make it industry standard, call them patterns, teach them in schools, and select people by how well they can “apply” these patterns to “any” problem at hand.

Not all developers bought into this cult of course. Here is Peter Norvig’s notes from 1996, where he “dismisses” 16 out of 23 patterns from Gang of Four, by just using functions, types, modules, etc.

Builder Pattern vs. Immutable Data Structures


Builder pattern makes sense unless.. several things. There is a great “Builders vs. Option Maps” short post that talks about builder patter limitations:

* Builders are too verbose
* Builders are not data structures
* Builders are mutable
* Builders can’t easily compose
* Builders are order dependent

Due to mutable data structures (in Java/C#/alike) Builders still make sense for things like Google protobufs with simple (i.e. primitive) types, but for most cases where immutable things need to be created it is best to use immutable data structures for the above reasons.

While jumping between the languages, I often need to create things in Clojure that are implemented in Java with Builders. This is not always easy, especially when Builders rely on external state or/and when Builders need to be passed around (i.e. to achieve a certain level of composition).

Let’s say I need to create a notification client that, by design (on the Java side of things), takes some initial state (i.e. an external system connection props), and then event handlers (callbacks) are registered on it one by one, before it gets built, i.e. builds a final, immutable notification client:

SomeClassBuilder builder = SomeClass.newBuilder()
                             .setState( state )
                             .setAnotherThing( thing );
 
builder.register( notificationHandlerOne );
builder.register( notificationHandlerTwo );
...
builder.register( notificationHandlerN );
 
builder.build();

In case you need to decouple “register events” logic from this monolithic piece above, you would pass that builder to the caller that would pass it down the chain. It is something that seems “normal” to do (at least to a “9 to 5” developer), since methods with side effects do not really raise any eyebrows in OO languages. In fact most of methods in those languages have side effects.

I quite often see people designing builders such as the one above (with lots of external state), and when I need to use them in Clojure, it becomes very apparent that the above is not well designed:

;; creates a "mutable" builder..
(defn- make-bldr [state thing]
  (-> (SomeClass/newBuilder)
      (.withState state)
      (.withAnotherThing thing)))
 
;; wraps "builder.register(foo)" into a composable function
(defn register-event-handler! [bldr handler]
    ;; in case handler is just a Clojure function wrap it with something ".register" will accept
    (.register bldr handler))
 
(defn notification-client [state thing]
  (let [bldr (make-bldr state thing)]
    ;; ... do things that would call "register-event-handler!" passing them the "bldr"
    (.build bldr)))

Things that immediately feel “off” are: returning a mutable builder from “make-bldr”, mutating that builder in “register-event-handler!”, and returning that mutated builder back.. Not something common in Clojure at all.

Again the goal is to “decouple logic to register events from notification client creation“, if both can happen at the same time, the above Builder would work.

In Clojure it would just be a map. All data structures in Clojure are immutable, so there would be no intermediate mutable holder/builder, it would always be an immutable map. When all handlers are registered, this map would be passed to a function that would create a notification client with these handlers and start it with “state” and “thing”.

Mocking Suspicions


Another synapse formation, that was created from using many languages at the same time, convinced me that if I have to use а mock to test something, that something needs a close look, and would potentially welcome refactoring.

The most common case for mocking is:

A method of a component "A" takes a component "B" that depends on a component "C".

So if I want to test A’s method, I can just mock B and not to worry about C.

The flaw here is:

"B" that depends on a component "C".

These things are extremely beneficial to question. I used to use Spring a lot, and when I did, I loved it. Learned from it, taught it to others, and had a great sense of accomplishment when high complexity could be broken down to simple pieces and re wired together with Spring.

Time went on, and in Erlang or Clojure, or even Groovy for that matter, I used Spring less and less. I still use it for all my Java work, but not as much. So if 10 years ago:

"B" that depends on a component "C".

was a way of life, now, every time I see it, I ask why?. Does “B” have to depend on “C”? Can “B” be stateless and take “C” whenever it needed it, rather that be injected with it and carry that state burden?

If before “B” was:

public class B {
 
  private final C c;
 
  public B ( C c ) {
    this.c = c;
  }
 
  public Profit doBusiness() {
    return new Profit( c.doYourBusiness() + 42 );
  }
}

Can it instead just be:

public final class B {
  public static Profit doBusiness( C c ) {
    return new Profit( c.doYourBusiness() + 42 );
  }
}

In most cases it can! It really can, the problem is not enough of us question that dependency, but we should.

This does not mean “B” no longer depends on “C”, it means something more: there is no “B” (“there is no spoon..”) as it just becomes a module, which does not need to be passed around as an instance. The only thing that is left from “B” is “doBusiness( C c )”. Do we need to mock “C” now? Can it, its instance disappear the way “B” did? Most likely, and even if it can’t for whatever reason (i.e. someone else’s code), I did question it, and so should you.


The more synapse formations I go through the better I learn to question pretty much everything. It is fun, and it pays back with beautiful revelations. I love my brain :)


6
Oct 10

Humans + Software = Zero

FACT:

Humans are stateful and mutable beings that have no problems processing many things concurrently and share state with others + they are usually “coupled”

GOAL:

And yet in software design we strive for being stateless, immutable and decoupled.


CONCLUSION I:

Humans should not design software

CONCLUSION II:

If humans were designed by software, that project sucked ( according to the GoF teachings )

CONCLUSION III:

Humans are not software, they are maybe… hardware

CONCLUSION IV:

Good software is going to lead to the race of Inhumans

CONCLUSION V:

Humans + Software = 0


15
Sep 08

Reset Lost Password in Sun Application Server

Sun Application Server Password ResetHappens to the best of us, less with system admins more with developers. But we are all human, and believe it or not we DO forget and loose passwords at least once every so often. Some time ago I wrote a tutorial on how to reset lost root password in mysql, and here is another similar tutorial on how to reset the lost domain password but this time for Sun Application Server.

Before going any further with this article, please first check “.asadminprefs” file:

cat /home/toly/.asadminprefs
 
AS_ADMIN_USER=admin
AS_ADMIN_PASSWORD=YourSecretPasswordInTextHere!

the admin password could be there

If it is not there, there are two ways to reset it:

  • Reinstall or recreate the affected domain.
  • Create a new dummy domain and copy its security key file over to the real domain to substitute the password.

Below is an explanation for the second approach (in case when “reinstall or recreate affected domain” is not an option):

Given:

 >   Sun App server is installed in                 "/opt/SUNWappserver"
 >   Domain to which the password is lost:   "domain1"

Step 1. Creating a new dummy domain

/opt/SUNWappserver/bin/asadmin create-domain --adminport 7070 --adminuser admin --instanceport 7071 dummy-domain
 
Please enter the admin password>password
Please enter the admin password again>password
Please enter the master password>password
Please enter the master password again>password
 
Domain dummy-domain created.

Step 2. Copy dummy-domain’s “admin-keyfile” to domain1’s “admin-keyfile”

cp /opt/SUNWappserver/domains/dummy-domain/config/admin-keyfile  /opt/SUNWappserver/domains/domain1/config/admin-keyfile

now the password for domain1 is “password” – DONE :)

Step 3. Deleting the dummy domain

/opt/SUNWappserver/bin/asadmin delete-domain dummy-domain
Domain dummy-domain deleted.

NOTES:

The above is true for Sun’s Application Server 8.x and later.

For Sun’s Application Server 9.x check out “change-admin-password


11
Sep 08

Install Sun Application Server on Ubuntu

Sun Microsystems

On the client site when working on Java (or should I say JEE) projects, the application servers are most of the time “rotate” between these four: JBoss, Websphere, Weblogic, and someties Geronimo. However there are some clients who have pretty tight contracts with Sun, and in these cases the Sun Application Server is used.

I think now days in development world in general, well except maybe .NET part of it, Ubuntu and/or Mac OS slowly become OSs of choice for developers. Sun app server however is not the most used app server out there, and since its installation could be a bit non-straightforward, here are four simple steps on how to install it on Ubuntu box:

Step 1. Download the “.bin” form sun:

“Sun Java System Application Server”

http://java.sun.com/j2ee/1.4/download.html (I needed 8.2, but there are more recent ones)

Step 2. Change permissions, to make it runnable:

chmod 744 sjsas_pe-8_2-linux.bin

Step 3. If you just run it:

./sjsas_pe-8_2-linux.bin

It is going to complaint that it is missing a standard c++ library:

./sjsas_pe-8_2-linux.bin: error while loading shared libraries: libstdc++-libc6.2-2.so.3: cannot open shared object file: No such file or directory

Having done some “apt-cache” searches ( apt-cache search libstdc++ ), found that Ubuntu has “libstdc++.so.6” in /usr/lib.
From /usr/lib run:

 sudo ln -s libstdc++.so.6 libstdc++-libc6.2-2.so.3

Step 4. Run it now, it will install Sun App Server successfully! * **

* Do not run installation as root – it will fail (for most sun app servers versions)

** If you use any form of Beryl (or some Compiz’es), disable it, or reload window manager as a “Gnome Manager”. This is due to the fact the the installer is written in Swing, and Swing does not get along too well with some display managers.