Building photoroom-cli with Claude Code: From API to NPM in 3 Days

Luiz TanureLuiz Tanure
5 min read

Building a CLI Tool with Claude Code: From API to NPM in 3 Days

I wanted to practice pair programming with Claude Code--but I needed a real project. Not a todo app. Not a playground. Something small, useful, and publishable.

Photoroom has a clean, AI-powered API for image editing--but no CLI. That was the gap. It’s a useful service, the docs are great, and the scope felt just right for a solo dev experiment.

photoroom-cli demo

Figuring out what to build

The real challenge wasn't coding--it was design.

After a rough first draft of the main commands, I started building a minimal TUI--separating it into clear use cases: background removal, AI-generated backgrounds, and API key setup.

Most of the endpoints are straightforward, but the image editing one has a lot of parameters. Some of them should just appear if another one has a specific value. Trying to reduce this complexity to a simple TUI interface was one of the biggest challenges, and it wasn't about coding only, but about how to organize the info and make it simple for the user.

Working with Claude Code

Claude helped me explore different ways to implement TUI interfaces quickly. When Claude generated disorganized code, first I let it go. After repetition, I started iterating to find useful and good abstractions and patterns.

This became the rhythm: let Claude explore, then I'd reorganize and extract reusable components.

Claude Code is Fast--Too Fast

Claude Code works fast. Too fast.

Lots of times, Claude was implementing full features, without thinking about reusing parts or patterns. On refactorings and code analysis, I was moving parts, reorganizing stuff, and forcing Claude to reuse in other parts.

This taught me something important: working with Claude, the coding skills need to be used differently. More guiding, reviewing, defining rules.

// Claude's first attempt - works but not reusable
async function removeBackground(imagePath: string) {
  const questions = [
    { type: "input", name: "output", message: "Output filename?" },
    { type: "list", name: "format", choices: ["png", "jpg"] },
  ];
  // ... implementation
}

// After refactoring - reusable question patterns
async function askQuestions<T>(config: QuestionConfig[]): Promise<T> {
  // Generic question handler that all features can use
}

I learned to establish patterns early and force consistency across modules. The AI is incredibly productive, but human oversight ensures the code remains maintainable.

Making it simple for users

I started as simple as possible: a menu for each endpoint, asking all the parameters. Later, I grouped them better, focused on the most important, used, required ones, and put the others as optional.

"Do you want to edit the background?" to avoid forcing the user to answer all params that they don't need most of the time.

After that, I added validation and complex TUI interfaces, like file selection.

The biggest challenge wasn't coding--it was information architecture.

Security and Polish with AI

Claude Code helped implement sophisticated features I might have skipped:

Encrypted API Key Management:

// AI helped design secure key storage
const encrypt = (text: string, key: Buffer): EncryptedData => {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipher("aes-256-gcm", key);
  // ... secure implementation
};

Error Handling: Claude generated comprehensive error scenarios I hadn't considered. The AI's systematic approach to edge cases made the tool more robust than I would have built alone.

CI/CD Pipeline: Setting up automated testing, releases, and even Claude Code Review integration in the CI pipeline. The AI helped configure modern tooling I was less familiar with.

What I learned

One quote I kept thinking about during this build:

“AI makes 80% of my coding skills almost useless,
but makes the other 20% 80× more important.”

So, it's not about typing code anymore, but saying what to create, defining a good architecture, evaluating the results, having more freedom to explore paths, go forward or rollback when necessary.

Coding with Claude isn’t about typing--it's about reviewing, refactoring, and maintaining structure. AI accelerates output, but you still have to think about what’s worth building, and how it fits together.

The Publishing Experience

Getting from working code to published NPM package involved:

  • TypeScript configuration for proper exports
  • Testing setup with Vitest
  • Documentation and examples
  • CI/CD for automated releases

Claude Code helped with the technical setup, but the decisions about what to include, how to organize it, and what the user experience should be--that was human judgment.

Building for others

I didn’t promote the project much, so feedback was limited. But it reminded me that building useful tools isn’t enough--you have to tell people. Shipping is just the first half. Sharing is the second.

Results

  • Published to NPM: https://www.npmjs.com/package/photoroom-cli
  • Open source: https://github.com/letanure/photoroom-cli
  • Real users: Solving actual problems for other developers
  • 3 days: From idea to published package

Key Takeaways

  1. AI coding requires different skills: More guiding, reviewing, defining rules
  2. Speed vs. quality balance: Let AI explore, then human reorganization
  3. Pattern enforcement: Establish consistency early and maintain it
  4. Focus on hard problems: Let AI handle implementation, you handle design
  5. Build for real users: Even practice projects should solve real problems

“AI makes 80% of my coding skills almost useless, but makes the other 20% 80× more important.”

That one line sums up this project better than anything else.

The future of development isn't human vs. AI--it's human with AI. The challenge is learning how to be a better conductor of the AI orchestra.

Tech Stack

Node.js, TypeScript, Yargs, Enquirer, Vitest, GitHub Actions, and of course, Claude Code as my pair programmer.

Sometimes the best “practice” is something small that real people can use. That’s what this was. A fast build, a solid CLI, and one more tool out in the wild.


Originally published at letanure.dev

0
Subscribe to my newsletter

Read articles from Luiz Tanure directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Luiz Tanure
Luiz Tanure