Python & JavaScript Development: The Plugins That Made Me Stop Fighting My Stack

>2025-10-16|11 min read

Get the tools: python-development

Also check out: javascript-typescript

The ATM Software Incident

Last month I was building backend services for chainbytes.com - Bitcoin ATM software that needs to handle concurrent transactions, talk to payment processors, manage device state, and not lose anyone's money. No pressure.

I started with FastAPI because async seemed right for the job. Then I hit reality.

My first attempt at handling concurrent ATM sessions looked like this:

pythonasync def process_transaction(transaction_id: str): # Get the transaction transaction = await db.get(transaction_id) # Do some processing await asyncio.sleep(0.1) # Simulate work # Update the transaction transaction.status = "completed" await db.save(transaction) # Race condition. Whoops.

See the bug? No? Neither did I. For three days.

Two ATMs submitted transactions simultaneously. Both read the same state. Both updated it. One update vanished. The logs showed everything working perfectly. The customer's Bitcoin did not.

This is when I realized I needed help. Not just "ask Claude" help - I needed expertise loaded and ready to go. Enter the python-development plugin.

What Python-Development Actually Is

It's a collection of specialized agents and skills for Python development. Not generic "write me some Python" help, but deep expertise in specific domains:

Three Agents:

  • django-pro
    - Django 5.x, DRF, Celery, Django Channels
  • fastapi-pro
    - Async APIs, SQLAlchemy 2.0, Pydantic V2
  • python-pro
    - Modern Python 3.12+, the 2024/2025 ecosystem

Five Skills:

  • async-python-patterns
    - asyncio, concurrent programming, producer-consumer
  • uv-package-manager
    - The blazing-fast package manager from Astral
  • python-testing-patterns
    - pytest, fixtures, mocking, TDD
  • python-packaging
    - pyproject.toml, PyPI publishing, wheels
  • python-performance-optimization
    - Profiling, bottleneck identification

The agents are heavy-weight - they load comprehensive domain knowledge. The skills are targeted references you invoke when you need specific guidance.

The Race Condition Fix

After installing the plugin, I invoked the async-python-patterns skill:

/async-python-patterns

Then I described my concurrent transaction problem. What came back wasn't just a fix - it was an explanation of why my code was broken and three different patterns for handling it:

pythonimport asyncio from typing import Optional class TransactionManager: """Manages concurrent transaction access with locks.""" def __init__(self): self._locks: dict[str, asyncio.Lock] = {} self._lock_lock = asyncio.Lock() async def get_lock(self, transaction_id: str) -> asyncio.Lock: """Get or create a lock for a specific transaction.""" async with self._lock_lock: if transaction_id not in self._locks: self._locks[transaction_id] = asyncio.Lock() return self._locks[transaction_id] async def process_transaction(self, transaction_id: str): """Process transaction with proper locking.""" lock = await self.get_lock(transaction_id) async with lock: transaction = await db.get(transaction_id) # Now we're safe - no other coroutine can modify # this transaction while we hold the lock await self._do_processing(transaction) transaction.status = "completed" await db.save(transaction)

The skill didn't just give me code. It explained the lock hierarchy problem (acquiring locks on locks), showed me the producer-consumer pattern for high-throughput scenarios, and pointed out that for really critical operations I should be using database-level locking anyway.

Django or FastAPI? Both.

Here's a confession: the chainbytes backend ended up being a hybrid. FastAPI for the async endpoints that talk to ATM hardware. Django for the admin interface and background job processing with Celery.

The django-pro and fastapi-pro agents handled the context switching. When I was working on the FastAPI side:

@fastapi-pro Design an endpoint that handles ATM status polling from multiple machines simultaneously

What I got back used proper dependency injection, Pydantic models with validation, and showed me how to structure the response for efficient polling:

pythonfrom fastapi import FastAPI, Depends, HTTPException from pydantic import BaseModel, Field from typing import Optional from datetime import datetime class ATMStatus(BaseModel): machine_id: str online: bool = True last_heartbeat: datetime current_transaction: Optional[str] = None cash_level: int = Field(ge=0, le=100) model_config = {"from_attributes": True} class StatusUpdate(BaseModel): machine_id: str cash_level: int error_code: Optional[int] = None app = FastAPI() @app.post("/atm/status", response_model=ATMStatus) async def update_status( update: StatusUpdate, session: AsyncSession = Depends(get_session), ): """Update ATM status with proper async session handling.""" atm = await session.get(ATM, update.machine_id) if not atm: raise HTTPException(status_code=404, detail="ATM not found") atm.cash_level = update.cash_level atm.last_heartbeat = datetime.utcnow() if update.error_code: await handle_error(session, atm, update.error_code) await session.commit() await session.refresh(atm) return ATMStatus.model_validate(atm)

Then when I switched to the Django admin and Celery tasks:

@django-pro Create a Celery task that reconciles transaction records between the ATM logs and the payment processor

The django-pro agent understood the context switch. It showed me how to structure Celery tasks with proper retry logic, how to use Django's ORM efficiently in background jobs, and reminded me about database connection handling in long-running tasks.

The uv Revelation

I was still using pip. I know, I know.

The python-development plugin includes a skill for uv, the Rust-based package manager that's 10-100x faster than pip. After running

/uv-package-manager
, I migrated the project in about an hour:

bash# Old way (pip) python -m venv .venv source .venv/bin/activate pip install -r requirements.txt # ... wait ... # ... still waiting ... # 47 seconds later, environment ready # New way (uv) uv venv uv add fastapi uvicorn sqlalchemy pydantic # 2.3 seconds. Done.

But the speed isn't even the best part. The lockfile support means reproducible builds:

bash# Generate lockfile uv lock # Install exact versions everywhere uv sync --frozen # CI/CD is now deterministic

The skill also showed me how to structure pyproject.toml properly, separate dev dependencies, and set up uv in GitHub Actions. My CI went from 90 seconds to 15 seconds just from the dependency installation speedup.

Testing Async Code

This is where I really suffered before the plugin. Testing async Python is confusing. pytest-asyncio has its own decorators. Fixtures can be async. Mocking async functions requires different patterns.

The python-testing-patterns skill broke it all down:

pythonimport pytest from unittest.mock import AsyncMock, patch @pytest.fixture async def mock_payment_processor(): """Async fixture for payment processor.""" processor = AsyncMock() processor.charge.return_value = {"status": "success", "tx_id": "abc123"} return processor @pytest.mark.asyncio async def test_transaction_success(mock_payment_processor): """Test successful transaction flow.""" with patch("app.services.get_processor", return_value=mock_payment_processor): result = await process_purchase( amount=100, customer_id="cust_123" ) assert result.status == "completed" mock_payment_processor.charge.assert_called_once_with( amount=100, customer="cust_123" ) @pytest.mark.asyncio async def test_transaction_retry_on_timeout(): """Test that transactions retry on processor timeout.""" processor = AsyncMock() processor.charge.side_effect = [ asyncio.TimeoutError(), # First call fails {"status": "success"} # Second call succeeds ] with patch("app.services.get_processor", return_value=processor): result = await process_purchase(amount=50, customer_id="cust_456") assert result.status == "completed" assert processor.charge.call_count == 2

The pattern of

AsyncMock
with
side_effect
for simulating flaky services saved me. Payment processors time out. Networks fail. ATM hardware is weird. The tests now cover these cases.

The Compound Effect

What I didn't expect was how these tools would work together.

Start a FastAPI project with uv. Add Django for the admin. Use async patterns for concurrent operations. Test everything with pytest-asyncio. Package it all with pyproject.toml.

Each skill builds on the others. The python-pro agent understands the whole stack. When I ask it about something, it considers the tools I'm using, the patterns I've established, the structure of my project.

I'm not constantly context-switching between "how does asyncio work" and "what's the pytest syntax again" and "wait, how do I install this." The knowledge is loaded when I need it, specialized for my use case.

JavaScript and TypeScript: The Other Half of the Stack

Python handles the backend. But the chainbytes project also has a dashboard. A real-time monitoring interface. WebSocket connections. All the frontend stuff that Python developers pretend doesn't exist.

This is where the javascript-typescript plugin comes in.

The Agents:

  • nodejs-pro
    - Modern Node.js development, async patterns, npm ecosystem
  • typescript-pro
    - Type-safe JavaScript, advanced TypeScript patterns

The Skills:

  • TypeScript configuration and strict mode setup
  • Modern ES modules and build tooling
  • Node.js performance patterns
  • React and frontend framework integration

The nodejs-pro agent is like having a senior Node developer who actually reads the documentation. When I was setting up the WebSocket server for real-time ATM monitoring:

@nodejs-pro Set up a WebSocket server that broadcasts ATM status updates to connected dashboard clients

What I got back wasn't just working code - it was production-ready patterns:

typescriptimport { WebSocketServer, WebSocket } from 'ws'; import { createServer } from 'http'; interface ATMUpdate { machineId: string; status: 'online' | 'offline' | 'error'; lastTransaction?: string; timestamp: number; } class ATMBroadcaster { private wss: WebSocketServer; private clients: Set<WebSocket> = new Set(); constructor(server: ReturnType<typeof createServer>) { this.wss = new WebSocketServer({ server }); this.wss.on('connection', (ws) => { this.clients.add(ws); ws.on('close', () => { this.clients.delete(ws); }); ws.on('error', (err) => { console.error('WebSocket error:', err); this.clients.delete(ws); }); }); } broadcast(update: ATMUpdate): void { const message = JSON.stringify(update); for (const client of this.clients) { if (client.readyState === WebSocket.OPEN) { client.send(message); } } } }

The agent showed me proper connection cleanup, error handling, and the TypeScript interfaces that make the whole thing type-safe. No more

any
types leaking through the codebase.

TypeScript That Actually Works

Here's my confession about TypeScript: I used to treat it like JavaScript with extra syntax. Just add

: string
to things until the red squiggles go away.

The typescript-pro agent fixed that. When I asked about proper typing for the dashboard's state management:

@typescript-pro How do I type a reducer that handles multiple ATM status updates with discriminated unions?

What came back was a proper TypeScript education:

typescript// Discriminated union for ATM events type ATMEvent = | { type: 'STATUS_UPDATE'; machineId: string; status: ATMStatus } | { type: 'TRANSACTION_START'; machineId: string; txId: string } | { type: 'TRANSACTION_COMPLETE'; machineId: string; txId: string; amount: number } | { type: 'ERROR'; machineId: string; code: number; message: string }; interface DashboardState { machines: Map<string, ATMStatus>; activeTransactions: Map<string, Transaction>; errors: ATMError[]; } function dashboardReducer(state: DashboardState, event: ATMEvent): DashboardState { switch (event.type) { case 'STATUS_UPDATE': return { ...state, machines: new Map(state.machines).set(event.machineId, event.status) }; case 'TRANSACTION_START': return { ...state, activeTransactions: new Map(state.activeTransactions).set( event.txId, { id: event.txId, machineId: event.machineId, startTime: Date.now() } ) }; case 'TRANSACTION_COMPLETE': { const updated = new Map(state.activeTransactions); updated.delete(event.txId); return { ...state, activeTransactions: updated }; } case 'ERROR': return { ...state, errors: [...state.errors, { machineId: event.machineId, code: event.code, message: event.message, timestamp: Date.now() }] }; } }

The discriminated union pattern means TypeScript knows exactly which properties exist in each case. No more runtime checks. No more

event.amount
when the event doesn't have an amount. The compiler catches it before the code runs.

The Full Stack Reality

The chainbytes project now has:

  • FastAPI backend handling ATM transactions (python-development)
  • Django admin for operations team (python-development)
  • Node.js WebSocket server for real-time updates (javascript-typescript)
  • TypeScript React dashboard (javascript-typescript)
  • Proper types flowing through the entire stack

Both plugins talk to each other conceptually. The Python types and the TypeScript types mirror each other. The async patterns in Python match the async patterns in Node. The testing strategies are consistent.

bash# Python side @fastapi-pro /async-python-patterns /python-testing-patterns # JavaScript side @nodejs-pro @typescript-pro

When I'm working on the API endpoint and need to update the dashboard to consume it, I switch agents and the context follows. The nodejs-pro agent understands REST APIs. The typescript-pro agent knows how to type the response. It's the same mental model, different syntax.

Getting Started

Install the plugins from agents-skills-plugins.

For Python work:

bash# For a FastAPI project @fastapi-pro # For Django work @django-pro # For general Python excellence @python-pro

Then dive into specific skills when you need them:

bash/async-python-patterns # Concurrent programming /uv-package-manager # Modern dependency management /python-testing-patterns # Pytest and TDD /python-packaging # Publishing to PyPI /python-performance # Profiling and optimization

For JavaScript and TypeScript work:

bash# For Node.js development @nodejs-pro # For TypeScript patterns @typescript-pro

The agents are proactive - they'll catch issues and suggest improvements. The skills are reference material - invoke them when you need specific guidance.

The Honest Ending

Did the plugins make me a better developer? Probably not.

Did they make me a more productive developer? Absolutely.

The chainbytes ATM backend ships transactions without race conditions now. The dashboard updates in real-time. The TypeScript is actually typed. The test suite runs in CI. Dependencies install in seconds instead of minutes.

These plugins aren't magic. They're expertise, encoded and ready. The same knowledge you'd get from reading the docs, watching the tutorials, and making all the mistakes - but loaded into context when you need it, not sitting in browser tabs you'll definitely read later (you won't).

For more tools like this, check out the agents-skills-plugins repo.


"The best code is code that doesn't fight you. The second best is code that knows when it's fighting."

Ship Python. Ship TypeScript. Ship it fast. Don't lose anyone's Bitcoin.

>_Eric Engine

Ask me anything

Type your question below

>