\n\n\n\n My Guide to Software Packages: Art, Not Just Code - AgntKit \n

My Guide to Software Packages: Art, Not Just Code

📖 10 min read1,820 wordsUpdated Apr 7, 2026

Hey everyone, Riley Fox here, back in your inbox (or browser, as the case may be) with another deep dive into the nitty-gritty of what makes our digital lives, well, livable. Today, I want to talk about something that often gets conflated, misunderstood, and sometimes, frankly, ignored until you’re neck-deep in a project that feels like it’s held together with duct tape and good intentions: the humble but mighty package. Specifically, I want to talk about the art of curating and maintaining your go-to personal package repository.

Now, I know what some of you are thinking: “Riley, a package is just a package. You install it, you use it, you move on.” And for a long time, that was my philosophy too. I’d grab whatever npm package or Python library seemed to do the trick, throw it into my project, and then promptly forget about it until the next dependency update broke everything. My personal ‘toolkit’ was less a finely tuned engine and more a collection of spare parts I’d found rattling around in the attic. This approach, while convenient in the short term, led to a lot of wasted time, security headaches, and a general feeling of digital clutter.

It was about two years ago, working on a particularly gnarly client project that involved integrating with three different legacy APIs and a new real-time data stream, that I hit my breaking point. I had about 40 different microservices, each with its own set of dependencies, many of them overlapping but at different versions. The dependency hell was so real, I started having nightmares about package.json files. That’s when I decided to get serious about my personal package strategy. I realized that a truly effective agent toolkit isn’t just about the cool new apps; it’s about the foundational elements you build with. And for me, a big part of that foundation is a well-considered, actively managed personal package repository.

Why a Personal Package Repository Isn’t Just for Big Teams

You might associate “package repository” with massive enterprise setups, internal NuGet feeds, or private npm registries for hundreds of developers. And yes, those are valid use cases. But I’m talking about something much simpler and more personal. Think of it as your own curated collection of utility functions, small libraries, and configurations that you find yourself using again and again across different projects, languages, and contexts.

For example, how many times have you written a function to sanitize user input? Or to parse a specific date format? Or to make a rate-limited API call? If you’re like me, it’s been dozens. Each time, you probably copy-pasted it, maybe tweaked it slightly, and then forgot about it. This is where a personal package repository shines. Instead of copy-pasting, you build these small, self-contained utilities into proper, versioned packages that you can then easily install and update in any project.

The benefits are huge:

  • Consistency: You’re using the exact same, tested code everywhere. No more subtle bugs creeping in from slightly different copy-pastes.
  • Maintainability: Find a bug in your date parsing function? Fix it once in your package, update the version, and then simply upgrade the package in all your projects.
  • Security: You can proactively review and audit your own packages, knowing exactly what’s in them.
  • Efficiency: Stop reinventing the wheel. Just install your package and get on with the actual problem-solving.
  • Learning: The process of packaging forces you to think about modularity, API design, and testing in a way that quick-and-dirty scripts don’t.

Setting Up Your Personal Package Ecosystem: A Practical Guide

Okay, so how do you actually do this without turning it into another full-time job? The key is to start small and iterate. Don’t try to package every single utility you’ve ever written on day one. Pick one or two things that you find yourself writing most frequently.

Step 1: Choose Your Platform(s)

This will largely depend on the languages you primarily work in. For me, it’s a mix of JavaScript/TypeScript and Python. So, my personal package strategy involves:

  • npm for JavaScript/TypeScript: This is my go-to for front-end utilities, Node.js helper functions, and build configurations.
  • PyPI (or local wheels) for Python: For data manipulation, API wrappers, and specific backend logic.

You don’t need a fancy private registry to start. For npm, you can simply publish scoped packages to the public npm registry (e.g., @myusername/my-utility). For Python, you can use pip install path/to/my/package for local development, or publish to PyPI for wider use (though I find local wheels sufficient for many personal tools). For more sensitive things, a private GitHub Packages registry is also an option, or even just keeping them as private repos you can install directly from Git.

Step 2: Start Small: Your First Personal Package

Let’s take a common example: a utility for formatting dates and times in a consistent way. I used to have a utils.js file that I’d copy-paste. Now, it’s a proper npm package.

Example: A Simple Date Formatter (TypeScript/npm)

First, create a new directory for your package and initialize it:


mkdir my-date-utils
cd my-date-utils
npm init -y
npm install --save-dev typescript @types/node
npx tsc --init

Now, let’s create our core utility in src/index.ts:


// src/index.ts

type DateFormatOptions = {
 includeTime?: boolean;
 locale?: string;
 shortMonth?: boolean;
};

/**
 * Formats a Date object into a consistent string representation.
 * @param date The Date object to format.
 * @param options Formatting options.
 * @returns A formatted date string.
 */
export function formatToStandardDate(
 date: Date,
 options: DateFormatOptions = {}
): string {
 const { includeTime = true, locale = 'en-US', shortMonth = false } = options;

 const monthOptions: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow' = shortMonth ? 'short' : 'long';

 let dateParts = new Intl.DateTimeFormat(locale, {
 year: 'numeric',
 month: monthOptions,
 day: '2-digit',
 }).formatToParts(date);

 let formattedDate = dateParts
 .filter(p => p.type !== 'literal')
 .map(p => p.value)
 .join('/'); // Example: "11/Apr/2026" or "11/April/2026"

 if (includeTime) {
 const timeParts = new Intl.DateTimeFormat(locale, {
 hour: '2-digit',
 minute: '2-digit',
 second: '2-digit',
 hour12: false, // Force 24-hour format for consistency
 }).formatToParts(date);

 const formattedTime = timeParts
 .filter(p => p.type !== 'literal')
 .map(p => p.value)
 .join(':'); // Example: "14:35:05"

 return `${formattedDate} ${formattedTime}`;
 }

 return formattedDate;
}

/**
 * Parses a common ISO-like date string into a Date object.
 * @param dateString The date string to parse.
 * @returns A Date object, or null if parsing fails.
 */
export function parseIsoLikeDate(dateString: string): Date | null {
 try {
 const date = new Date(dateString);
 if (isNaN(date.getTime())) {
 return null;
 }
 return date;
 } catch (error) {
 console.error("Failed to parse date string:", dateString, error);
 return null;
 }
}

Update your tsconfig.json to compile to dist:


{
 "compilerOptions": {
 "target": "es2016",
 "module": "commonjs",
 "outDir": "./dist",
 "esModuleInterop": true,
 "forceConsistentCasingInFileNames": true,
 "strict": true,
 "skipLibCheck": true,
 "declaration": true // Important for type definitions
 },
 "include": ["src/**/*.ts"],
 "exclude": ["node_modules"]
}

And your package.json:


{
 "name": "@rileyfox/my-date-utils", // Use your scope!
 "version": "1.0.0",
 "description": "My personal date formatting and parsing utilities.",
 "main": "dist/index.js",
 "types": "dist/index.d.ts", // Point to your type definitions
 "scripts": {
 "build": "tsc",
 "test": "echo \"Error: no test specified\" && exit 1"
 },
 "keywords": ["date", "time", "utility", "formatter"],
 "author": "Riley Fox ",
 "license": "MIT",
 "devDependencies": {
 "@types/node": "^20.12.7",
 "typescript": "^5.4.5"
 }
}

Run npm run build. Now you have a distributable package! You can publish this to npm (npm publish --access public if it’s scoped and you want it public) or use npm link for local testing.

Step 3: Establish a Naming Convention

This is crucial for keeping things organized. I use a simple pattern: @rileyfox/<purpose-or-domain>-<utility-name>. For example: @rileyfox/api-client-base, @rileyfox/form-validation-helpers, @rileyfox/config-loader.

Step 4: Versioning and Documentation

Treat these packages like real open-source projects. Use semantic versioning (Major.Minor.Patch). Write a clear README.md that explains what the package does, how to install it, and how to use it. Even if it’s just for you, good documentation saves future-you a lot of head-scratching.

Step 5: Integrate into Your Workflow

The beauty of this approach comes when you start a new project. Instead of writing that same utility again, you just run:


npm install @rileyfox/my-date-utils

Then, in your code:


import { formatToStandardDate, parseIsoLikeDate } from '@rileyfox/my-date-utils';

const now = new Date();
console.log(formatToStandardDate(now, { shortMonth: true })); // e.g., "07/Apr/2026 14:35:05"

const parsedDate = parseIsoLikeDate("2026-03-15T10:30:00Z");
if (parsedDate) {
 console.log(formatToStandardDate(parsedDate, { includeTime: false })); // e.g., "15/March/2026"
}

Beyond the Code: What Else to Package?

It’s not just about code. Think about any recurring configuration or boilerplate. For instance:

  • ESLint/Prettier configurations: I have a standard set of linting rules I like. Instead of copying .eslintrc.js into every project, I have @rileyfox/eslint-config-base that I can extend.
  • VS Code settings: Common workspace settings or recommended extensions can be packaged into a simple repo you clone.
  • Dockerfiles/docker-compose setups: For common development environments.
  • CI/CD pipeline templates: If you use GitHub Actions or GitLab CI frequently, common job definitions can be extracted.

The principle is the same: if you find yourself copying and pasting or rewriting something more than twice, consider turning it into a package or a template that can be easily pulled in.

My Journey: From Package Chaos to Calm

It took me a while to get into this rhythm. My initial attempts were clunky. I tried to make packages too big, or too small. I struggled with versioning. But over time, I refined the process. Now, when I start a new project, my setup time is drastically reduced. I spend less time fixing mundane bugs in utility code and more time on the actual business logic. And when a vulnerability is found in a dependency of one of my core utilities, I fix it once, update my package, and then roll out that update across all relevant projects with minimal fuss.

This approach has transformed my personal productivity. It’s given me a sense of control over my development environment that I didn’t have before. It’s an investment, absolutely, but one that pays dividends in terms of time saved, headaches avoided, and a general feeling of professionalism in my own work.

Actionable Takeaways for Your Own Package Journey

  1. Identify Your Repetitive Tasks: What code, configurations, or scripts do you copy-paste or rewrite most often? Start a list.
  2. Pick One or Two: Don’t overwhelm yourself. Choose the easiest or most impactful item from your list to package first.
  3. Choose Your Platform: Decide whether npm, PyPI, GitHub Packages, or even just private Git repos are the best fit for your chosen item.
  4. Start Simple, Iterate: Don’t aim for perfection on day one. Get a working package, use it, and refine it over time.
  5. Document Everything: Even if it’s just for you, a good README will save you time later.
  6. Embrace Semantic Versioning: It makes updates much less stressful.
  7. Think Beyond Code: Consider packaging configurations, templates, and boilerplate too.

Building your personal package repository isn’t just about being a “better developer”; it’s about being a more efficient, less frustrated, and ultimately more effective agent in your own digital world. Give it a shot. Your future self will thank you.

🕒 Published:

✍️
Written by Jake Chen

AI technology writer and researcher.

Learn more →
Browse Topics: comparisons | libraries | open-source | reviews | toolkits
Scroll to Top