Back to blog
24 Oct 2024
5 min read

Building an AI Code Assistant in 2021

When your side project is just early enough to be too late

The Origin Story 🚀

Picture this: It’s 2021, the world is still debating whether pants are necessary for Zoom calls, and OpenAI casually drops Codex like it’s no big deal. Being among the chosen few with API access (flex intended), we did what any caffeine-fueled developers would do – we built something that nobody asked for but everyone secretly needed.

Armed with nothing but Figma’s free tier (RIP good old days) and dreams bigger than our production budget, we set out to create the sleekest developer tool landing page.

Our Humble Beginnings in Figma

The Tech Stack That Made It Happen 🛠️

We didn’t just pick a tech stack; we curated a gourmet student meal - Cheap and pretty

  • Frontend & Backend: NextJS with TypeScript (because we’re masochists who love type safety)
  • AI Integration: OpenAI Codex API (our magical code whisperer)
  • Analytics: Amplitude (because we’re data nerds)
    trackEvent('user_mind_blown', { intensity: 'maximum' });
    
  • Authentication: Firebase Auth (Google’s gift to MVP enthusiasts)
  • Database: Firestore (NoSQL and free, perfect!)
  • Deployment: Vercel (easy CI/CD, free hosting)

Features That Made Us Feel Like Wizards 🧙‍♂️

1. VSCode Extension

Yes, this was before copilot became mainstream. Came with chat, docstring, fix code and what not! Surprisingly has 7k downloads ( we have about 1500 signups ) ¯\(ツ)

2. CLI Tool

For the terminal warriors who think GUIs are for the weak:

$ krinql how to compile typescript code
# *poof* Documentation appears like magic 🎩

Each release came with a npm package, linux, windows and macOS binaries!

3. Automated Docstring Generation

Because life’s too short to write “Parameters: None, Returns: void”:

# Before Krinql
def calculate_risk_matrix():
    # TODO: Add docs later (narrator: they never did)
    pass

# After Krinql
def calculate_risk_matrix(
    exposure_level: float,
    risk_factors: List[str]
) -> RiskMatrix:
    """
    Calculates the risk matrix based on exposure levels and risk factors.
    
    Args:
        exposure_level (float): The measured exposure level in millisieverts
        risk_factors (List[str]): List of identified risk factors
        
    Returns:
        RiskMatrix: A 2D matrix representing risk levels
        
    Raises:
        ValueError: If exposure_level is negative
    """
    pass

4. Code Translation

Babel fish for programming languages:

# Python input
def quicksort(arr):
    if len(arr) <= 1: return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quicksort(left) + middle + quicksort(right)
// TypeScript output (auto-generated)
function quicksort<T>(arr: T[]): T[] {
    if (arr.length <= 1) return arr;
    const pivot = arr[Math.floor(arr.length / 2)];
    const left = arr.filter(x => x < pivot);
    const middle = arr.filter(x => x === pivot);
    const right = arr.filter(x => x > pivot);
    return [...quicksort(left), ...middle, ...quicksort(right)];
}

The Plot Twist: Success, But Not How We Planned 📈

We launched on Product Hunt expecting to break the internet… and got enough upvotes to fill a medium-sized coffee shop. But then something magical happened – developers actually started using it! We grew to 1,500+ users through word of mouth, probably because people got “free AI” back when it was still kept under the wraps for general public.

Our Product Hunt Adventure

The Grand Finale: Timing Is Everything 🎭

Just as we were fielding acquisition talks on LittleExits, OpenAI dropped ChatGPT like a mic drop. Suddenly, everyone from tech giants to bootcamp graduates were building AI coding assistants. Our lovingly crafted tool found itself in a world where billions of dollars were being thrown at similar problems.

Technical Learnings That Will Live Forever in Our Git History 🤓

  1. AI Integration Complexity:

    // What we thought AI integration would be:
    const aiResponse = await ai.generateCode(prompt);
    
    // What it actually was:
    try {
      const response = await retryWithExponentialBackoff(
        async () => {
          const result = await ai.generateCode(prompt);
          if (containsStackOverflowLinks(result)) {
            throw new Error('AI is just googling');
          }
          return validateAndSanitizeCode(result);
        }
      );
    } catch (error) {
      console.log('AI is taking a coffee break');
    }
    
  2. VSCode Extension Development:

    • Learned that Webviews are both a blessing and a curse
    • Mastered the art of console.log debugging (trust me, setting up a debugger for a vscode extension is painful)
    • Issue #1: VSCode Extension Not working - SSL Error ( Electron issue with LetsEncrypt Certs :) ) - We have a fun utility method called certConfigHack as a workaround
    • Easiest way to do auth is by registering a VSCode URI and passing a JWT as a param which is then decoded and validated by the extension after authflow is completed on the browser
  3. CLI Extension:

  • Authenticating your webapp with a CLI tool is simpler than it sounds, just involves running a http server to data from the browser after the auth flow by opening a url

Legacy Code: Our Digital Time Capsule 💾

While Krinql may have been steamrolled by the AI giants, we like to think we were just too early to the party. We built GitHub Copilot-like features when most developers were still skeptical about AI code completion. And hey, at least we can say we were doing AI-powered development before it was cool!

We’ve still left the website, extension and cli tool running ( albeit with limited API access since we ran out of free usage ages ago)

Epitaph 🪦

+------------------------+
|        KRINQL          |
|      2021 - 2023       |
|   "Copilot's cousin"   |
+------------------------+

Survived by 1,500+ users and countless unfinished feature branches

P.S. If you’re reading this in 2024+, remember us when AI assistants are writing entire applications while developers focus on the real challenge: naming variables.