<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Timophei Lemeshchenko</title>
    <description>The latest articles on DEV Community by Timophei Lemeshchenko (@another1dd).</description>
    <link>https://dev.to/another1dd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4051093%2F0ec7c31b-9dd6-4f59-8a17-4550e000795c.jpg</url>
      <title>DEV Community: Timophei Lemeshchenko</title>
      <link>https://dev.to/another1dd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/another1dd"/>
    <language>en</language>
    <item>
      <title>Splitting a Swift monorepo shouldn't require git-subtree tricks (so I built a free registry)</title>
      <dc:creator>Timophei Lemeshchenko</dc:creator>
      <pubDate>Fri, 14 Aug 2026 13:08:52 +0000</pubDate>
      <link>https://dev.to/another1dd/splitting-a-swift-monorepo-shouldnt-require-git-subtree-tricks-so-i-built-a-free-registry-19i6</link>
      <guid>https://dev.to/another1dd/splitting-a-swift-monorepo-shouldnt-require-git-subtree-tricks-so-i-built-a-free-registry-19i6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I built &lt;a href="https://perchly.dev" rel="noopener noreferrer"&gt;Perchly&lt;/a&gt;, the tool this post ends up recommending. It started as a fix for my own problem, not a product — and this is the honest version of how it happened.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your team has more than one Swift package that always version together, you've probably hit this: either you split them into separate git repos and juggle a release per package on every single change, or you keep one repo and lean on git submodules / git-subtree hacks just to make each package independently resolvable by SwiftPM. Neither is great, and I kept seeing people run into it — including a &lt;a href="https://stackoverflow.com/questions/76071552" rel="noopener noreferrer"&gt;Stack Overflow question&lt;/a&gt; from someone trying to split a "newskit"/"the-sun" style theming package into independently versioned pieces without blowing up their repo structure.&lt;/p&gt;

&lt;p&gt;The root cause is that &lt;code&gt;swift package-registry publish&lt;/code&gt; (and Xcode's dependency resolution) publishes &lt;em&gt;whatever package lives at a given path&lt;/em&gt; — so each package you want to version independently needs its own &lt;code&gt;Package.swift&lt;/code&gt;, not a shared target inside one giant manifest. That part is actually fine once you know it. The part that's genuinely annoying is that Apple's own answer to "how do I host that privately for my team" is SE-0292, a real open protocol — but there was no simple, free way to actually run one if you're not Artifactory/JFrog-scale.&lt;/p&gt;

&lt;p&gt;So I built a private SPM registry that implements SE-0292 for real, not a wrapper around git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just use a private GitHub repo as a dependency
&lt;/h2&gt;

&lt;p&gt;That works fine for exactly one package. The moment you have several related packages that need independent versions in one repo, you're stuck choosing between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Splitting into N repos, so every cross-cutting change becomes N pull requests and N releases&lt;/li&gt;
&lt;li&gt;Keeping one repo and hacking around it with git-subtree splits or submodules, which nobody enjoys maintaining&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A real registry sidesteps this entirely. Each package resolves and versions independently regardless of how your source is actually organized on disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "real SE-0292" gets you
&lt;/h2&gt;

&lt;p&gt;Because Perchly speaks the actual &lt;a href="https://github.com/apple/swift-evolution/blob/main/proposals/0292-package-registry-service.md" rel="noopener noreferrer"&gt;SE-0292&lt;/a&gt; registry protocol instead of a proxy or a plugin, the standard SwiftPM CLI just works, unmodified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# once per machine/CI runner&lt;/span&gt;
swift package-registry &lt;span class="nb"&gt;set &lt;/span&gt;https://registry.perchly.dev

&lt;span class="c"&gt;# from inside a package directory&lt;/span&gt;
swift package-registry publish my-org.network-kit 1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on it elsewhere is just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"my-org.network-kit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No custom tooling, no forked SwiftPM, no post-install scripts. It even works through Xcode's own "Add Package" dependency resolution once you've run the &lt;code&gt;set&lt;/code&gt; command once — Xcode doesn't need to know Perchly exists.&lt;/p&gt;

&lt;p&gt;For the actual monorepo case, splitting into independently publishable packages just means giving each one its own &lt;code&gt;Package.swift&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-monorepo/
├── Sources/
│   ├── newskit/
│   │   ├── Package.swift          ← name: "newskit"
│   │   └── Sources/newskit/...
│   └── the-sun/
│       ├── Package.swift          ← name: "the-sun"
│       └── Sources/the-sun/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They still live in one git repo. Nothing about this requires separate repos, submodules, or subtree splits — you just publish each path with its own identifier and version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swift package-registry publish &lt;span class="nt"&gt;--package-path&lt;/span&gt; Sources/newskit my-org.newskit 1.0.0
swift package-registry publish &lt;span class="nt"&gt;--package-path&lt;/span&gt; Sources/the-sun my-org.the-sun 1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also open-sourced a small CLI, &lt;a href="https://github.com/Another1dd/perchly-cli" rel="noopener noreferrer"&gt;perchly-cli&lt;/a&gt;, that diffs the last publish against &lt;code&gt;HEAD&lt;/code&gt;, figures out which package directories actually changed, and bumps + publishes only those — so you're not doing that by hand every release once you have more than two or three packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other things it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub &lt;strong&gt;and&lt;/strong&gt; GitLab OAuth to sign in — no separate account/password to manage&lt;/li&gt;
&lt;li&gt;Versions are immutable once published (no silently overwriting &lt;code&gt;1.0.0&lt;/code&gt; out from under someone who's already pinned to it)&lt;/li&gt;
&lt;li&gt;Free plan: 3 members, 5 packages, 2GB storage, no credit card&lt;/li&gt;
&lt;li&gt;Paid tiers exist for bigger teams, but the whole point of the free tier is that a small team shouldn't need to talk to sales to stop fighting git-subtree&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it deliberately doesn't do (yet)
&lt;/h2&gt;

&lt;p&gt;No package signing yet (SwiftPM prints an "is not signed" warning but still resolves fine — that's an SwiftPM-level thing, not specific to Perchly). No self-hosted GitLab instance support, no per-package ACLs. It's intentionally a small, focused tool, not an attempt to out-feature Artifactory.&lt;/p&gt;

&lt;p&gt;If you want to poke at it: &lt;a href="https://perchly.dev" rel="noopener noreferrer"&gt;perchly.dev&lt;/a&gt;. Feedback, especially "this doesn't work for my setup because X," is genuinely useful to me right now.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>devops</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Comparing Dart &amp; Flutter package registries</title>
      <dc:creator>Timophei Lemeshchenko</dc:creator>
      <pubDate>Mon, 10 Aug 2026 13:18:37 +0000</pubDate>
      <link>https://dev.to/another1dd/comparing-dart-flutter-package-registries-o3j</link>
      <guid>https://dev.to/another1dd/comparing-dart-flutter-package-registries-o3j</guid>
      <description>&lt;p&gt;&lt;a href="https://dart.dev/tools/pub/custom-package-repositories" rel="noopener noreferrer"&gt;dart.dev's custom package repositories page&lt;/a&gt; lists six providers for hosting private Dart/Flutter packages and doesn't say a word about how they differ. Here's an honest breakdown, including whether you need one of these at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  At a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Free tier&lt;/th&gt;
&lt;th&gt;Cheapest paid plan&lt;/th&gt;
&lt;th&gt;Billing model&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloudsmith&lt;/td&gt;
&lt;td&gt;500MB data / 1GB delivery&lt;/td&gt;
&lt;td&gt;$149/mo (Pro)&lt;/td&gt;
&lt;td&gt;Usage-based (storage + delivery)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inedo ProGet&lt;/td&gt;
&lt;td&gt;Unlimited feeds &amp;amp; users (self-hosted)&lt;/td&gt;
&lt;td&gt;$2,395/yr (Basic)&lt;/td&gt;
&lt;td&gt;Flat, per-server license&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JFrog Artifactory&lt;/td&gt;
&lt;td&gt;Free trial only&lt;/td&gt;
&lt;td&gt;$150/mo (Pro)&lt;/td&gt;
&lt;td&gt;Usage-based (consumption) + tier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OnePub&lt;/td&gt;
&lt;td&gt;2 members / 25 packages&lt;/td&gt;
&lt;td&gt;$1-$15/member/mo&lt;/td&gt;
&lt;td&gt;Per-seat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLPub.dev&lt;/td&gt;
&lt;td&gt;1 package&lt;/td&gt;
&lt;td&gt;10 EUR/mo (Pro)&lt;/td&gt;
&lt;td&gt;Flat, per-org&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Publy&lt;/td&gt;
&lt;td&gt;1 member / 5 packages&lt;/td&gt;
&lt;td&gt;$19.99/mo (Starter)&lt;/td&gt;
&lt;td&gt;Flat, per-org&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;GLPub.dev prices in EUR, everyone else above in USD. Figures verified directly against each provider's own pricing page as of August 2026 — see the sections below for what each tier actually includes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is a registry even worth it over git dependencies?
&lt;/h2&gt;

&lt;p&gt;Dart 3.9 added &lt;code&gt;tag_pattern&lt;/code&gt; to git dependencies, which is a genuine fix, not a workaround. Tag your commits with real version numbers and the solver treats a git dep almost like a hosted one — a non-breaking bump no longer cascades through every consumer.&lt;/p&gt;

&lt;p&gt;What it doesn't fix: pub identifies a git dependency by its URL, so a teammate pulling over SSH and another pulling the same repo over HTTPS are two different packages to the solver. There's no publish-time validation, so a mismatched tag just sits there until a consumer fails to resolve. Tags are mutable by default, so force-moving one silently changes what a "version" means for everyone who already resolved it. And every dev machine and CI job needs git access to every package repo individually, instead of one scoped, revocable token.&lt;/p&gt;

&lt;p&gt;None of that is unsolvable — SSH-only conventions, protected tags, a shared CI service account — but it's all internal policy your team has to set up and keep alive. If you have a handful of git dependencies in their own repos, &lt;code&gt;tag_pattern&lt;/code&gt; probably closes the gap enough that a registry is overkill. Past a pile of interdependent packages across monorepos, it stops scaling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloudsmith
&lt;/h2&gt;

&lt;p&gt;Cloud-hosted, general-purpose artifact registry (not Dart-specific — it also handles npm, Maven, Docker, and a long list of other formats). It was the first third-party Dart repository, launched back in 2020. The free Core plan gives 500MB of artifact storage and 1GB of package delivery; Pro is $149/month for 5GB storage and 25GB delivery, plus $1.50/GB beyond that. Ultra and Enterprise are custom-priced. Comes with governance features (blocking versions, requiring metadata, quarantining packages) aimed at larger orgs already managing multiple package ecosystems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inedo ProGet
&lt;/h2&gt;

&lt;p&gt;Self-hosted (or their managed Cloud Edition from $4,895/yr), also general-purpose across many package/container formats. Pub support is recent — it landed in ProGet 2024.11 — and inherits a real limitation of the pub API itself: no search, and no README/license metadata without extra caching work. The Free edition supports unlimited feeds and users; paid self-hosted licenses run $2,395/yr (Basic) up to $11,995/yr (Enterprise Essentials) and from $29,995/yr (Enterprise Complete), licensed per server, not per user — every edition supports unlimited users. Self-hosting means you own uptime and patching unless you pay for the managed option.&lt;/p&gt;

&lt;h2&gt;
  
  
  JFrog Artifactory
&lt;/h2&gt;

&lt;p&gt;The enterprise option. Supports dozens of package formats beyond Dart through local, remote, and virtual repository types, self-hosted or cloud. The Pro tier is $150/month for 25GB of base consumption; Enterprise X starts at $950/month for 125GB plus SSO and artifact federation; Enterprise+ is custom-priced. No free tier for private packages beyond a trial. Makes sense if your org already standardized on Artifactory for other languages and just wants to add a pub feed to it — a lot of surface area to take on if Dart packages are the only thing you need it for.&lt;/p&gt;

&lt;h2&gt;
  
  
  OnePub
&lt;/h2&gt;

&lt;p&gt;Dart/Flutter-only, hosted, and the longest-running dedicated option in this list. Explicitly billed &lt;em&gt;"USD, per member, per month"&lt;/em&gt; on every tier: Free is 2 members / 25 packages, Pro is $1/member (5 members), Team is $10/member (20 members, their most popular), Enterprise is $15/member (unlimited members). A 20-person team on the Team plan is $200/month before storage or download overages — the cost scales with headcount (and typically a CI service account counts as a member too), not with actual usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  GLPub.dev
&lt;/h2&gt;

&lt;p&gt;Dart/Flutter-only, hosted, and signs in with GitLab, GitHub, or Google — not GitLab-exclusive despite the name, though it reuses whichever provider's project permissions natively. Flat per-org pricing, not per-seat: Free is 1 package with 10 versions/month, Pro is 10 EUR/month for up to 10 packages with unlimited versions, Business is 50 EUR/month for unlimited packages plus priority support. The smallest and newest-feeling option here, but the pricing model is closer to Publy's than to OnePub's.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publy
&lt;/h2&gt;

&lt;p&gt;Dart/Flutter-only and hosted, priced in flat tiers instead of per seat like OnePub: Free is 1 member / 5 packages / 250MB storage, Starter is $19.99/month flat for 10 members / 50 packages / 5GB (the same 10-member team costs $100/month on OnePub's per-seat Team plan), Team is $39.99/month flat for unlimited members and packages with storage capped at 25GB. Adding a teammate never changes the bill within a tier. Speaks the real pub hosted-repo protocol (the spec dart-lang publishes) directly, not a wrapper around git or a custom CLI, so &lt;code&gt;dart pub publish&lt;/code&gt; and &lt;code&gt;dart pub get&lt;/code&gt; work exactly like they do against pub.dev.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to actually pick one
&lt;/h2&gt;

&lt;p&gt;Already running Artifactory or ProGet for other package types at your org? Add a pub feed to what you have instead of standing up something new. Just a couple of small packages and comfortable with GitLab/GitHub-native permissions? GLPub.dev's free or 10 EUR tier probably covers it. Team size small and stable, with only a handful of internal packages? &lt;code&gt;tag_pattern&lt;/code&gt; on plain git dependencies might be all you need — skip a registry entirely. Want something Dart-specific and hosted without per-seat pricing creeping up as you hire, or need dozens of interdependent packages across monorepos to just work? That's the gap we built &lt;a href="https://publy.dev/pricing" rel="noopener noreferrer"&gt;Publy&lt;/a&gt; for.&lt;/p&gt;

&lt;p&gt;Pricing and feature details above were checked directly against each provider's own pricing page as of the date at the top of this post — registries change their plans, check each provider's own site before deciding.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does pub.dev support private packages?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No — pub.dev only hosts public packages. dart pub itself supports any hosted-repo-protocol-compliant server via publish_to and a custom hosted URL, which is exactly what the providers on this page (or self-hosting the spec yourself) give you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a free private Dart/Flutter package registry?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. Cloudsmith's Core plan, Inedo ProGet self-hosted, OnePub's Free tier, GLPub.dev's Free tier, and Publy's Free tier all have a $0 option — see the table above for what each actually includes before you rely on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the pub hosted-repo protocol?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's the REST API spec dart-lang publishes (the Hosted Pub Repository Specification, currently v2) that &lt;code&gt;dart pub publish&lt;/code&gt; and &lt;code&gt;dart pub get&lt;/code&gt; talk to — upload finalize with a Location header, a version-listing endpoint, archive downloads. Any server that implements it correctly works as a drop-in publish_to target; that's what distinguishes an actual registry from a wrapper around git or a custom CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need a registry if I only have one or two internal packages?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Probably not. Dart 3.9's &lt;code&gt;tag_pattern&lt;/code&gt; lets plain git dependencies resolve against real version tags, which covers small, stable setups fine — see the section above on what it does and doesn't fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens to already-downloaded packages if I switch providers or stop paying?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Depends on the provider — check before you commit. Publy, for example, keeps downloads unmetered for a full month after a missed payment, and packages your build already fetched keep whatever got cached; only new &lt;code&gt;dart pub get&lt;/code&gt; / &lt;code&gt;dart pub publish&lt;/code&gt; calls are affected after that grace period.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use more than one of these at once?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes — pub supports multiple hosted repositories at the same time, declared per-dependency in pubspec.yaml. Some teams do split package sources this way (self-hosted ProGet for one set of internal tools, a hosted registry for another), at the cost of juggling more than one set of credentials.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://publy.dev/blog/comparing-dart-flutter-package-registries" rel="noopener noreferrer"&gt;Publy blog&lt;/a&gt;, where it's kept up to date.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Sharing private Flutter packages shouldn't cost this much (so I built a free registry)</title>
      <dc:creator>Timophei Lemeshchenko</dc:creator>
      <pubDate>Tue, 28 Jul 2026 10:39:05 +0000</pubDate>
      <link>https://dev.to/another1dd/sharing-private-flutter-packages-shouldnt-cost-this-much-so-i-built-a-free-registry-4k3j</link>
      <guid>https://dev.to/another1dd/sharing-private-flutter-packages-shouldnt-cost-this-much-so-i-built-a-free-registry-4k3j</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I built &lt;a href="https://publy.dev" rel="noopener noreferrer"&gt;Publy&lt;/a&gt;, the tool this post ends up recommending. It started as a fix for my own problem, not a product — and this is the honest version of how it happened.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you've ever tried to share private Dart or Flutter code across more than one repo, you already know the two roads in front of you, and you already know both of them hurt.&lt;/p&gt;

&lt;p&gt;Road one: a &lt;strong&gt;paid private pub registry&lt;/strong&gt;. It works, &lt;code&gt;dart pub&lt;/code&gt; is happy, and the bill climbs every time your team or your package count grows.&lt;/p&gt;

&lt;p&gt;Road two: &lt;strong&gt;git dependencies&lt;/strong&gt;. It's free, and it quietly turns your &lt;code&gt;pubspec.yaml&lt;/code&gt; into a minefield.&lt;/p&gt;

&lt;p&gt;I spent a long time on both. Here's what actually went wrong, and what I did about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The git-dependency trap
&lt;/h2&gt;

&lt;p&gt;For a while my team went the free route — pull internal packages straight from git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app_core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git@github.com:our-org/app-core.git&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks fine on day one. It falls apart on week three.&lt;/p&gt;

&lt;p&gt;The moment you reference a package &lt;strong&gt;by branch or tag instead of a version&lt;/strong&gt;, you throw away everything &lt;code&gt;pub&lt;/code&gt;'s version solver does for you. There are no version constraints — &lt;code&gt;^1.4.0&lt;/code&gt; means nothing when you're pinned to &lt;code&gt;ref: main&lt;/code&gt;. Two apps depending on the same internal package at two different commits? The solver can't reconcile that, because as far as it's concerned they're the same unversioned thing.&lt;/p&gt;

&lt;p&gt;So you end up doing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependency_overrides&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app_core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git@github.com:our-org/app-core.git&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;a3f9c21&lt;/span&gt;   &lt;span class="c1"&gt;# the "known good" commit, do not touch, nobody remembers why&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dependency_overrides&lt;/code&gt; is meant to be a temporary, local escape hatch. When it becomes the &lt;em&gt;only&lt;/em&gt; way your dependency graph resolves, that's not a workaround anymore — that's your architecture, and it's a bad one. Every new package multiplied the pain. Across two internal SDK monorepos we had &lt;strong&gt;50+ packages&lt;/strong&gt; depending on each other, and the git approach turned every version bump into a manual archaeology dig through commit hashes.&lt;/p&gt;

&lt;p&gt;The whole point of semantic versioning and &lt;code&gt;pub&lt;/code&gt;'s solver is that you &lt;em&gt;don't&lt;/em&gt; do this. Git dependencies opt you out of the one thing that makes Dart's package management good.&lt;/p&gt;

&lt;h2&gt;
  
  
  The paid-registry trap
&lt;/h2&gt;

&lt;p&gt;So we did the sensible thing and moved to a hosted private registry. And it was genuinely better — real versions, &lt;code&gt;dart pub publish&lt;/code&gt;, the solver working again.&lt;/p&gt;

&lt;p&gt;Then the invoice showed up.&lt;/p&gt;

&lt;p&gt;I won't name numbers, but the pricing scaled per seat, and even with a &lt;strong&gt;small team of 3 developers plus CI/CD&lt;/strong&gt;, hosting our internal packages had become one of those line items you keep meaning to "look into." For a handful of private packages that just needed a place to live, the cost-to-value ratio stopped making sense. I was also paying out of pocket to host packages for my own side projects — and &lt;em&gt;that&lt;/em&gt; math was even harder to justify.&lt;/p&gt;

&lt;p&gt;I did not want a fancy product. I wanted the boring thing: a place to &lt;code&gt;dart pub publish&lt;/code&gt; internal packages, with real versions, that didn't charge me per human.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I built Publy
&lt;/h2&gt;

&lt;p&gt;I'm a Flutter dev, not a SaaS founder, and I built this because the alternatives annoyed me — so it's deliberately small. &lt;a href="https://publy.dev" rel="noopener noreferrer"&gt;Publy&lt;/a&gt; is a private Dart &amp;amp; Flutter package registry that implements the &lt;a href="https://github.com/dart-lang/pub/blob/master/doc/repository-spec-v2.md" rel="noopener noreferrer"&gt;standard pub hosted repository spec&lt;/a&gt;. That last part matters: there's no custom CLI, no plugin, no wrapper. &lt;code&gt;dart pub publish&lt;/code&gt; and &lt;code&gt;dart pub get&lt;/code&gt; work exactly like they do against pub.dev, because to &lt;code&gt;dart&lt;/code&gt; it &lt;em&gt;is&lt;/em&gt; just a hosted registry.&lt;/p&gt;

&lt;p&gt;Setup is three commands and one &lt;code&gt;pubspec&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Authenticate the CLI&lt;/strong&gt; (after signing in with GitHub and creating an org + token):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dart pub token add https://publy.dev/o/your-org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Tell a package where to publish&lt;/strong&gt; — in that package's &lt;code&gt;pubspec.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;publish_to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://publy.dev/o/your-org&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dart pub publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Consume it from another repo&lt;/strong&gt; like any hosted dependency — real version constraints, back at last:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app_core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;hosted&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://publy.dev/o/your-org&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^1.4.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;^1.4.0&lt;/code&gt; is the whole reason this exists. The solver is doing its job again. No &lt;code&gt;ref&lt;/code&gt;, no commit hash, no &lt;code&gt;dependency_overrides&lt;/code&gt; graveyard.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is and isn't
&lt;/h2&gt;

&lt;p&gt;Being honest about scope, since I hate posts that oversell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's free.&lt;/strong&gt; Not free-trial, not free-tier-with-an-asterisk — the plan you'd use for a small team costs nothing. I built it so I'd stop paying for this, so charging small teams would defeat the point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth is GitHub OAuth&lt;/strong&gt; for the web UI and &lt;strong&gt;bearer tokens&lt;/strong&gt; for the CLI / CI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versions are immutable&lt;/strong&gt; — republishing the same &lt;code&gt;name@version&lt;/code&gt; is a 409, never a silent overwrite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's young.&lt;/strong&gt; No per-package ACLs, no download analytics, no billing gymnastics. If you need enterprise compliance features today, this isn't that yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're a small-to-medium Flutter team quietly bleeding money on a private registry, or worse, drowning in git-dependency overrides — this is aimed squarely at you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You can be publishing in about five minutes: &lt;a href="https://publy.dev" rel="noopener noreferrer"&gt;publy.dev&lt;/a&gt;, and the &lt;a href="https://publy.dev/docs/getting-started" rel="noopener noreferrer"&gt;getting-started guide&lt;/a&gt; is the same three commands above with pictures.&lt;/p&gt;

&lt;p&gt;If you try it and something's broken or missing, tell me — genuinely. It exists because I hit a wall, and the fastest way to make it good is other people hitting different walls.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's your current setup for private Flutter packages — paid registry, git deps, or something cleverer? Curious what everyone else landed on.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>devops</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
