惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
博客园 - 司徒正美
F
Fortinet All Blogs
D
Docker
aimingoo的专栏
aimingoo的专栏
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
U
Unit 42
The Register - Security
The Register - Security
Martin Fowler
Martin Fowler
IT之家
IT之家
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research
Security Archives - TechRepublic
Security Archives - TechRepublic
Project Zero
Project Zero
T
Tenable Blog
S
Security Affairs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google DeepMind News
Google DeepMind News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
W
WeLiveSecurity
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tailwind CSS Blog
TaoSecurity Blog
TaoSecurity Blog
T
The Blog of Author Tim Ferriss
L
Lohrmann on Cybersecurity
雷峰网
雷峰网
Forbes - Security
Forbes - Security
Recent Announcements
Recent Announcements
N
News | PayPal Newsroom
Schneier on Security
Schneier on Security
酷 壳 – CoolShell
酷 壳 – CoolShell
Hugging Face - Blog
Hugging Face - Blog
博客园 - 聂微东
P
Palo Alto Networks Blog
C
Cybersecurity and Infrastructure Security Agency CISA
S
Schneier on Security
Attack and Defense Labs
Attack and Defense Labs
Latest news
Latest news
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
Last Week in AI
Last Week in AI
Scott Helme
Scott Helme
A
Arctic Wolf
L
LINUX DO - 最新话题
A
About on SuperTechFans
K
Kaspersky official blog
博客园 - Franky

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
FMix: a package manager for Forth
Alexey Bolsh · 2026-05-19 · via DEV Community

In modern programming languages, we almost always expect the language to come with a convenient tool for working with projects.

Elixir has Mix. Rust has Cargo. Ruby has Bundler and RubyGems. Haskell has Cabal and Stack. JavaScript has npm, pnpm and Yarn. Go has modules.

We are used to being able to create a project with one command, describe dependencies in one file, fetch them from the network, run tests, and prepare a release. It feels like a basic part of the ecosystem, not a luxury.

But older programming languages often have a different story.

When many of them were created, this approach was not yet a standard expectation. Code was distributed differently, projects were structured differently, and ecosystems grew without the package managers and build tools we now take for granted.

And you can still feel it today.

Why I Started Thinking About This

For one of my projects I use Forth.

Forth is a very interesting language. It is minimalistic, direct, and unusual. There is something very attractive about it: you are close to computation, close to the stack, and close to the actual hardware of the computer, which I sometimes build myself.

But when I started writing something in Forth that looked more or less like a project, I quickly began missing the usual things:

  • creating a new project;
  • describing dependencies;
  • downloading dependencies;
  • running tests;
  • having a clear project structure;
  • connecting libraries from Git;
  • not having to keep everything manually in my head.

Yes, you can use git submodules, copy files by hand, or invent your own conventions. But for me, this is not a very convenient path. I wanted something closer to what I am used to in modern languages.

I found the f.4th library, which is connected to theforth.net. It is a useful tool, but it follows a different approach: library code and versions are stored on its own server.

I wanted to be able to pull dependencies directly from Git repositories. For example, specify a GitHub URL, a branch or a tag, and get the library into the project.

That is how the idea for fmix appeared.

What Is FMix

fmix is a small build tool and package tool for Forth, inspired by Elixir Mix.

Repository: github.com/VitaSound/fmix

It does not try to be a large framework. Its goal is simpler: to give a Forth project a minimal set of familiar tools.

Right now fmix can do this:

fmix new example
fmix packages.get
fmix test
fmix version

Enter fullscreen mode Exit fullscreen mode

In other words, you can create a new package, fetch dependencies, run tests, and check the tool version.

Creating a Project

A new project is created like this:

fmix new example
cd example

Enter fullscreen mode Exit fullscreen mode

After that, you get a basic project structure:

example/
  example.4th
  package.4th
  README.md
  tests/
  forth-packages/

Enter fullscreen mode Exit fullscreen mode

package.4th is the package description file. It contains the name, version, license, main file, and dependencies.

Example:

forth-package
    key-value name example
    key-value version 0.1.0
    key-value license COPL
    key-value description example
    key-value main example.4th

    key-list dependencies f git https://github.com/VitaSound/f tag 0.2.4
    key-list dependencies ttester git https://github.com/VitaSound/ttester tag 1.1.0
end-forth-package

Enter fullscreen mode Exit fullscreen mode

I like that the file itself is also written in a Forth-like style. It is not JSON, YAML, or TOML. It is a tiny declarative Forth format.

Dependencies from Git

The main reason I started making fmix was Git dependencies.

In package.4th, you can define a dependency like this:

key-list dependencies ftest git https://github.com/VitaSound/ftest.git branch main

Enter fullscreen mode Exit fullscreen mode

Or like this, if you need a specific version via a tag:

key-list dependencies ftest git https://github.com/VitaSound/ftest.git tag 0.1.0

Enter fullscreen mode Exit fullscreen mode

After that, you only need to run:

fmix packages.get

Enter fullscreen mode Exit fullscreen mode

Dependencies will be installed into the local project directory:

./forth-packages/

Enter fullscreen mode Exit fullscreen mode

This structure makes it possible to keep different versions of the same library side by side:

forth-packages/
  f/
    0.2.4/
  ttester/
    1.1.0/

Enter fullscreen mode Exit fullscreen mode

You can include a dependency with the usual require:

require ./forth-packages/f/0.2.4/f.4th

Enter fullscreen mode Exit fullscreen mode

Support for theforth.net

Although I wanted Git dependencies, I did not want to completely abandon the existing ecosystem.

So fmix can also work with packages from theforth.net through f.4th.

For example:

key-list dependencies f 0.2.4

Enter fullscreen mode Exit fullscreen mode

This means one project can use both Git dependencies and packages from theforth.net.

Tests

Another basic thing I was missing was running tests.

fmix has this command:

fmix test

Enter fullscreen mode Exit fullscreen mode

It runs tests from the tests/ directory.

You can also run a specific file:

fmix test tests/some_test.4th

Enter fullscreen mode Exit fullscreen mode

Tests use ttester. If ttester exists in the project dependencies, fmix loads it from ./forth-packages. If not, it uses the version from the installed FMIX_HOME.

For me, this matters: tests should run with one command. Even if the project is small.

What Was Fixed in Recent Versions

fmix has already gone through several generations of changes.

I wrote the first versions myself. But I am not a very strong Forth developer, so many things were difficult for me. I made one major refactoring with the help of Gemini. I finished the latest version with Cursor.

The latest releases fixed quite a few practical problems.

GitHub Actions CI was added: the workflow builds GForth 0.7.9 from source and runs:

gforth fmix.4th -e version
gforth fmix.4th -e test

Enter fullscreen mode Exit fullscreen mode

Later, a release pipeline was added: when a version tag is pushed, a GitHub Release is created automatically, and the release text is taken from .github/RELEASE_NOTES_X.Y.Z.md.

Path handling was also fixed. Previously, part of the logic depended on PWD. Now the project is detected from the directory where the command is started. This matters because FMIX_HOME points to the installed fmix, while commands should operate on the current project.

Several dependency installation problems were fixed:

  • git clone now checks its result;
  • failed shell commands make GForth exit with code 1;
  • parent directories are created before git clone;
  • git fetch and checkout are executed so that failures are not hidden;
  • Git commands use GIT_TERMINAL_PROMPT=0, so the command does not hang in a non-interactive environment.

Another important thing is input validation. fmix validates package names, versions, paths, Git URLs, and Git refs before calling cp, sed, or git. It is not a complex escaping system, but a simple whitelist. It rejects spaces, ;, $, backticks, pipes, and other shell metacharacters.

An Unexpected Terminal Problem

There was a separate story with the terminal. Before using the fmix command in the console, it had to be configured as an alias.

When running through a simple alias like this:

alias fmix='gforth "$FMIX_HOME/fmix.4th" -e'

Enter fullscreen mode Exit fullscreen mode

the terminal sometimes ended up in a bad state after commands finished. Strange symbols appeared in the prompt, for example:

0c0c
[?2004l

Enter fullscreen mode Exit fullscreen mode

This was especially visible in WSL.

In version 0.4.4, I switched to the bin/fmix launcher script. It restores the TTY after commands, resets bracketed paste mode, and briefly drains queued input from /dev/tty. To be honest, I would definitely not have solved all of that on my own. I patiently helped the neural network try hypothesis after hypothesis to fix the problem. Unlike the AI tools I had tried before, this time I only had to stop the AI once and create a new context because it seemed to get stuck in an endless correction loop.

But it worked, and now instead of an alias it is recommended to use:

export FMIX_HOME="$HOME/fmix"
export PATH="$FMIX_HOME/bin:$PATH"

Enter fullscreen mode Exit fullscreen mode

And then run it simply as:

fmix

Enter fullscreen mode Exit fullscreen mode

Installation

Right now installation looks like this:

git clone https://github.com/VitaSound/fmix.git ~/fmix

Enter fullscreen mode Exit fullscreen mode

Then add this to your shell config, for example .bashrc:

export FMIX_HOME="$HOME/fmix"
export PATH="$FMIX_HOME/bin:$PATH"

Enter fullscreen mode Exit fullscreen mode

After that, the command should work directly in the console:

fmix version

Enter fullscreen mode Exit fullscreen mode

Important: at the moment fmix expects Linux, Git, sed, cp, and GForth 0.7.9.

I do not recommend using earlier versions of GForth or the Snap version. Snap runs programs in a confined environment, so the current directory and paths may not match what the shell session expects. This breaks commands like new and packages.get.

It is better to use GForth from apt, a local build, or a tarball from the official GForth page.

Why This Matters

I think old languages really need tools like this to fit modern realities.

They do not have to be huge. They do not have to be perfect. But they should at least cover the basic scenarios. When a language has convenient tooling around projects, it becomes friendlier.

It is easier for a newcomer to try the language. It is easier for an experienced user to start a new project. Libraries are easier to reuse. Tests are easier to run.

This does not change the language itself, but it changes the experience of working with it. It allows an old tool to be used in new projects.

In the case of Forth, this is especially interesting. Forth is often seen as something old, strange, and niche. But maybe part of that “oldness” is not only in the language itself, but also in the absence of familiar modern tooling around it.

If we add convenient tools, the language can feel very different.

What Is Next

fmix is still small and experimental.

Right now it can create packages, fetch dependencies from Git and theforth.net, run tests, and publish releases through GitHub Actions.

In the future, I would like to improve compatibility, add documentation, and maybe add more commands around Forth package development.

But even now, it has become much more convenient for me to work on my Forth projects. But that is another story.

Links