Reviving Abandoned Projects with AI Coding Assistants


The Starting Problem: Viable Project, Zero Momentum

The project idea had existed for a while: bridge YouTube Music into an OpenSubsonic server contract so clients like Feishin or Symfonium could use it without custom integrations.

The initial proof of concept had already shown the core architecture worked:

  • ytmusicapi for metadata lookup and search.
  • yt-dlp for extracting playable audio URLs.
  • A FastAPI service exposing OpenSubsonic endpoints.

So why was it unfinished? Not because the hard idea failed. It stalled on the usual long tail:

  • endpoint conformance details,
  • defensive response shaping,
  • caching and persistence,
  • cleanup behavior for interrupted streams,
  • boring-but-necessary integration polish.

That profile is exactly where coding assistants can help: a well-scoped domain with a concrete API spec, clear success criteria, and lots of repetitive glue work.

Step 1: Constrain the Model Before Writing Any Code

A major reason this effort worked quickly is that the environment was prepared before asking for large changes.

The setup was intentionally explicit:

  1. Create a Python project with known dependencies (fastapi, pydantic, ytmusicapi, yt-dlp).
  2. Provide the OpenSubsonic OpenAPI spec locally.
  3. Seed a short README describing architecture and data flow.
  4. Add a TODO surface to track incremental implementation.
  5. Generate tool instructions (CLAUDE.md) and add coding conventions.

Those conventions matter. The model was told to prefer:

  • type annotations,
  • modern Pydantic v2 patterns,
  • structured docstrings,
  • pytest-style tests with fixtures and direct assertions.

In other words: instead of asking the assistant to “build everything,” the author defined standards first, then delegated execution inside those guardrails.

Step 2: Build an MVP by Slicing Scope Aggressively

The first meaningful prompt was not “implement OpenSubsonic.” It was narrower: implement async FastAPI stubs for the newer JSON endpoints from the provided spec.

That single scope decision prevented immediate collapse into uncontrolled complexity.

Then came a practical validation loop:

  1. Generate a first implementation pass.
  2. Clear context.
  3. Ask for a second-pass verification against the spec.
  4. Fix mismatches before adding behavior.

This two-pass pattern is underrated. Even with a machine-readable spec, first-pass output can miss fields, naming, or edge semantics. Forcing a second verification pass catches a surprising amount of drift.

Step 3: Implement the Smallest End-to-End Vertical Slice

After stubs existed, the target changed from “more endpoints” to one user-visible workflow:

  • connect a Subsonic client,
  • search for a song,
  • stream audio back successfully.

That required only a subset of endpoints and behavior, including:

  • minimal user/license/directory responses that are structurally valid,
  • search3 wired to ytmusicapi,
  • stream wired to yt-dlp and run safely from async code,
  • getCoverArt support.

At this stage, the implementation looked good on paper but failed in client reality. The fix was straightforward and disciplined:

  • run the real client,
  • capture failing requests and logs,
  • feed failures back into the assistant,
  • add tests for each discovered mismatch.

An example from the process: some endpoint naming/format details (like suffix handling) were not obvious from high-level assumptions, so behavior had to be corrected based on real client interactions.

The result: audio played through Feishin after only a few focused iterations.

Step 4: Accept That MVP Success Is Not Product Success

Working audio is the milestone that feels complete, but it is usually only the beginning.

The write-up is particularly useful here because it does not stop at the demo. It describes the long-tail tasks required to make the service actually usable:

  • add metadata caching to reduce repeated upstream calls,
  • store library metadata in SQLite for browse features,
  • implement broader endpoint coverage beyond search/stream,
  • save streamed songs to disk to avoid repeated downloads,
  • clean up partial files when stream clients disconnect early.

None of these are flashy. All of them are operationally important.

This is where many side projects die: not in architecture, but in the accumulation of medium-importance, low-novelty tasks. AI assistance helps most when it is fed one concrete backlog item at a time and validated continuously.

Why This Worked Fast (Without Pretending It Was Magic)

The project moved in a short evening because several favorable conditions were present simultaneously:

  • A clear external contract (OpenAPI spec).
  • Existing prior knowledge from the author’s earlier POC.
  • Tight scope at each step.
  • Immediate runtime feedback from a real client.
  • Test generation after every discovered failure.

This is very different from “generate an app from a vague idea.”

The speed came from reducing ambiguity, not from removing engineering judgment.

The Two-Bucket Project Model

A key framing in the source post is splitting personal projects into two buckets:

  1. Stretch projects: chosen to force skill growth.
  2. Wish-fulfillment projects: things you want to exist in your life, even if they are not ideal learning vehicles.

The argument is not “use assistants for everything.”

The argument is: if a project has sat untouched for months (or years), AI-assisted execution can be a legitimate way to convert intent into a useful artifact. You still need bucket 1 work to keep sharpening fundamentals, but bucket 2 no longer has to stay permanently unfinished.

That distinction matters because many debates about AI coding tools collapse into all-or-nothing positions. This framing keeps the tradeoff grounded:

  • Use assistance to unlock completion where perfection is not the goal.
  • Preserve deliberate challenge where learning is the goal.

Practical Playbook You Can Reuse

If you want similar results on your own abandoned project, this workflow is a strong template:

  1. Write a one-page project brief: architecture, constraints, interfaces, and definition of done.
  2. Supply canonical specs/docs locally (OpenAPI, protocol docs, data schemas).
  3. Encode coding and testing conventions up front.
  4. Start with endpoint stubs or interface skeletons before feature behavior.
  5. Ship a vertical slice first, not broad coverage.
  6. Test with a real client early, not just unit tests.
  7. Convert every runtime bug into a regression test.
  8. Keep prompts narrow and sequential; avoid giant “do everything” asks.
  9. Re-summarize context after major changes so the assistant doesn’t drift.
  10. Treat long-tail chores as first-class backlog work.

The most important point: assistants help most when you run them like an implementation partner under tight product management, not as an autonomous replacement for engineering decisions.

Limits and Risks to Keep in View

The post is also explicit about a real concern: over-reliance can lead to deskilling. That risk does not disappear because a side project ships faster.

A practical way to manage this:

  • keep one active stretch project where you deliberately avoid heavy assistance,
  • require yourself to explain each generated subsystem in your own words,
  • own test design and production correctness criteria personally,
  • treat generated code as a draft until validated by execution and tests.

That keeps the completion benefit while reducing the “I can’t do this without the tool” failure mode.

Closing

The strongest takeaway is operational, not ideological:

If a project has a clear spec and repeatedly dies in implementation drudgery, AI coding assistance can be the leverage that gets it finished. But the success pattern is disciplined scoping, fast feedback, and persistent verification, not blind delegation.

That is how an abandoned idea becomes running software.

References