{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Camil Benameur - Blog",
  "home_page_url": "https://blog.camilbenameur.com/",
  "feed_url": "https://blog.camilbenameur.com/feed.json",
  "description": "Write-ups of software I have built, mostly in Go. By Camil Benameur, software engineer in Nice, France.",
  "language": "en",
  "authors": [
    {
      "name": "Camil Benameur",
      "url": "https://camilbenameur.com/"
    }
  ],
  "items": [
    {
      "id": "https://blog.camilbenameur.com/blog/offline-installer-retrospective/",
      "url": "https://blog.camilbenameur.com/blog/offline-installer-retrospective/",
      "title": "How an Offline Installer Works, and What I Over-Built Along the Way",
      "summary": "How an installer for air-gapped industrial PCs works, from SSH deployment and live progress to an offline .deb relay, and what I over-built and would change.",
      "content_text": "How an installer for air-gapped industrial PCs works, from SSH deployment and live progress to an offline .deb relay, and what I over-built and would change.",
      "date_published": "2026-10-14T00:00:00.000Z",
      "authors": [
        {
          "name": "Camil Benameur"
        }
      ],
      "tags": [
        "go",
        "architecture",
        "offline",
        "installation",
        "industrial",
        "retrospective",
        "ai-assisted-development"
      ],
      "language": "en"
    },
    {
      "id": "https://blog.camilbenameur.com/blog/from-backlog-to-offline-installer/",
      "url": "https://blog.camilbenameur.com/blog/from-backlog-to-offline-installer/",
      "title": "From Backlog to MVP: Building an Offline Industrial Installer in Go",
      "summary": "How I designed and built, as an intern, an installer for air-gapped industrial PCs: offline Docker installs from .deb packages, with 27.5.1 as the default version, and what I learned doing it.",
      "content_text": "Correction (2026-10-14): October 14, 2026: I corrected how I described the offline Docker install (which packages were pinned, how dependencies were resolved, what some steps did), reworded other steps and the supporting system to match how the installer actually worked, softened claims about the architecture and the outcome, and removed one setup detail and one statement about other people's availability. A later post looks at the project in more depth. September 29, 2026: I removed claims I could not back up: that a manual install took hours and dropped to minutes, that the installer scaled to fleets, that the result was reproducible and less error-prone, that it ran in production, and that there were strict deployment windows. I also removed statements about my teammates and about working mostly alone, described the starting point as a need rather than a client request, softened some general claims about industrial PCs, and added that I owned the project until March 2026.\n\nHow I designed and built, as an intern, an installer for air-gapped industrial PCs: offline Docker installs from .deb packages, with 27.5.1 as the default version, and what I learned doing it.",
      "date_published": "2026-02-05T00:00:00.000Z",
      "date_modified": "2026-10-14T00:00:00.000Z",
      "authors": [
        {
          "name": "Camil Benameur"
        }
      ],
      "tags": [
        "go",
        "architecture",
        "devops",
        "offline",
        "installation",
        "industrial"
      ],
      "language": "en"
    },
    {
      "id": "https://blog.camilbenameur.com/blog/on-streaming-optimization/",
      "url": "https://blog.camilbenameur.com/blog/on-streaming-optimization/",
      "title": "Streaming LLM JSON in Go: a Resumable Scanner and a Healer",
      "summary": "How go-llm-stream parses and repairs JSON streamed by LLMs: a resumable byte-level scanner, a healer for truncated output, and what its benchmarks do and do not show.",
      "content_text": "Correction (2026-09-29): When I published this post in January, I wrote that the streaming approach of encoding/json re-parses the whole buffer on every chunk and is O(n²), and that go-llm-stream fixes that. That was wrong. encoding/json.Decoder is O(n). The quadratic cost only appears when you accumulate chunks and re-parse the whole buffer yourself on every chunk. The comparison table I originally showed (about 500 parses for 1 MB) was never benchmarked. When I benchmarked the approaches head to head in June 2026, Decoder was also about 2 to 3 times faster per operation than the StreamReader of go-llm-stream on chunked input. The library is worth using for healing truncated output, reading fields as they complete, and saving and restoring scanner state, not for speed. I also retitled the post and fixed several other claims; the list is at the end of the post.\n\nHow go-llm-stream parses and repairs JSON streamed by LLMs: a resumable byte-level scanner, a healer for truncated output, and what its benchmarks do and do not show.",
      "date_published": "2026-01-27T00:00:00.000Z",
      "date_modified": "2026-09-29T00:00:00.000Z",
      "authors": [
        {
          "name": "Camil Benameur"
        }
      ],
      "tags": [
        "go",
        "llm",
        "streaming",
        "state-machines"
      ],
      "language": "en"
    }
  ]
}