Skip to content

Instantly share code, notes, and snippets.

@fmarier
Created December 7, 2025 23:59
Show Gist options
  • Select an option

  • Save fmarier/049184a4ee4b389b847fe571e31486aa to your computer and use it in GitHub Desktop.

Select an option

Save fmarier/049184a4ee4b389b847fe571e31486aa to your computer and use it in GitHub Desktop.
Ghost writing for feeding.cloud.geek.nz

AGENTS.md

This file provides guidance to AI agents when working with code in this repository.

Repository Overview

This is "Feeding the Cloud", François Marier's personal blog (feeding.cloud.geek.nz). The repository contains a static blog built using ikiwiki, a wiki compiler that generates static websites from markup files.

Architecture

  • Content Format: Blog posts are written in .mdwn (Markdown) files using ikiwiki's extended markdown syntax
  • Structure:
    • /posts/ - Individual blog posts and their associated directories
    • /templates/ - HTML templates (page.tmpl contains the main page template)
    • Root directory contains site-wide pages like index.mdwn, sidebar.mdwn
  • Blog Posts: Each post is a .mdwn file with ikiwiki meta directives at the top:
    [[!meta title="Post Title"]]
    [[!meta date="2009-07-29T23:52:00.000+12:00"]]
    [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)"]]
    
  • Template System: Uses ikiwiki's template system with TMPL_VAR variables and conditionals
  • Licensing: Content is licensed under Creative Commons Attribution-ShareAlike 4.0 International License

Key Files

  • templates/page.tmpl - Main HTML template for all pages
  • index.mdwn - Homepage that displays recent posts using [[!inline pages="page(./posts/*)"]]
  • sidebar.mdwn - Site navigation sidebar
  • local.css - Custom CSS styling
  • contribute.json - Project metadata (blog of François Marier)

ikiwiki Directives

Common ikiwiki directives used in this blog:

  • [[!meta]] - Page metadata (title, date, license, etc.)
  • [[!inline]] - Include/embed other pages or listings
  • [[!tag]] - Tag posts for categorization
  • [[!if]] and [[!else]] - Conditional content

Development Notes

  • This is a static site generator setup - no build scripts or package.json
  • Content is version controlled, but the actual site generation happens elsewhere
  • When editing posts, maintain the ikiwiki meta directive format at the top of each file
  • New blog posts should be added to the /posts/ directory with .mdwn extension
  • The site uses responsive design and includes various meta tags for social media and search engines

Writing workflow for new posts

  1. Intake and context
  • Read the user request or outline twice and underline concrete actions, commands, paths, and results.
  • Skim 1-2 recent posts with a similar topic to refresh the house voice before drafting anything.
  • Note any specific technical details (versions, error messages, outputs) that need to be preserved verbatim.
  1. Research and verification
  • Reproduce or reason through every command/configuration before mentioning it. If you cannot test something, explicitly say so instead of guessing.
  • Capture error messages or outputs from the outline verbatim and keep them in indented code blocks.
  1. Metadata setup
  • Derive the filename first (kebab-case, .mdwn, under posts/) to avoid renaming later.
  • Copy the [[!meta]] header exactly. Keep the timezone identical to the most recent post in the repo.
  • ALWAYS check timezone: Search for the newest post by date using grep -r "meta date" posts/*.mdwn | sort | tail -1 or similar. Do NOT assume the timezone. The example below may be outdated.
  • As of this writing, the newest post is posts/totp-in-2025.mdwn with timezone -07:00, but verify this before writing.
  1. Drafting
  • Choose the structure pattern (problem-solution, configuration, tip) that matches the outline and stick to it end-to-end.
  • Map each outline bullet or sentence to a paragraph or heading in the same order unless the user explicitly says otherwise. Combine short bullets into flowing sentences, but do not invent steps that were not provided.
  • Introduce each command or config change in prose, then follow immediately with an indented code block so readers know why it is there.
  1. Polish and handoff
  • Reread the draft for first-person voice, short declarative sentences, and the absence of filler words ("robust", "seamless", "simply", "just", "easily").
  • Verify each command/config was introduced in prose before its code block.
  • Double-check that code/config blocks use four-space indentation (no fenced blocks) and that there is exactly one blank line between paragraphs/headings.
  • Add internal/external links (use /posts/slug/ format for internal links), check the tags/ directory and set appropriate tags.
  • Walk through the Final Checklist section below before responding to the user.

Blog Post Style Guide

This section guides AI agents in writing blog posts that match François's established style. Read several recent posts before writing to internalize the voice.

Voice and Tone

  1. Direct and practical - Get to the point immediately. No preambles like "In this post, I will show you..." or "Have you ever wondered...?"

  2. First person, conversational - Write as "I" naturally. Example: "I recently upgraded my server to Debian trixie and ran into an interesting problem."

  3. Canadian English - Use Canadian spelling: "colour", "favourite", "behaviour", "centre", etc. Not US spelling.

  4. Assume technical competence - Readers are developers/sysadmins. Don't explain what SSH is or why you'd want to use the command line.

  5. Document for your future self - Many posts read like personal notes that happen to be public. The implicit audience is "me in 6 months when I forget how I did this."

  6. No marketing language - Never use words like "robust", "seamless", "leverage", "streamline", "comprehensive solution", or "best practices" as filler.

  7. No false enthusiasm - Avoid "Great!", "Awesome!", "Exciting!". If something is good, describe why factually.

Structure Patterns

Problem-Solution Posts (most common)

[Brief context - 1-2 sentences max]
[The problem encountered - often with error message]
[The solution, usually with code]
[Optional: explanation of why it works]
[Optional: related links or references]

Example opening: "After upgrading to Bookworm, I noticed that my backup script was failing with a cryptic error."

Or even terser: "I needed to rotate API keys on my server without downtime."

Configuration/Setup Posts

[What you're setting up and why - 1 sentence]
[Step-by-step instructions with code blocks]
[Any gotchas or things that tripped you up]
[Optional: references]

Short Tip Posts

Some posts are just 2-3 paragraphs (or even less) sharing a useful command or technique. This is fine and even encouraged when appropriate. Not everything needs to be comprehensive.

Very old posts (pre-2010) tend to be even terser than modern ones. This historical style is still acceptable - focus on information density over word count.

Writing Rules

  1. Start with context, not throat-clearing -

    • ❌ "Today I want to share something interesting I discovered while working on my server."
    • ✅ "I needed to rotate API keys on my server without downtime."
  2. One blank line between paragraphs - Standard markdown spacing.

  3. Use code blocks liberally - Show the actual commands/config and indent them with four spaces. Ikiwiki renders indented blocks correctly; fenced code blocks ( ) should not be used in posts. Examples in this file may use fenced blocks for clarity, but the published posts should not.

    sudo systemctl restart nginx

    When showing command output is helpful (e.g., for debugging), include it with a $ prompt:

    $ systemctl status systemd-timesyncd.service ● systemd-timesyncd.service - Network Time Synchronization Loaded: loaded Active: inactive (dead)

  4. Include file paths - When showing config files, indicate where they live (exact path): "I added the following to /etc/apt/apt.conf.d/50unattended-upgrades:"

    Not: "I edited the config file" or "In the config file"

  5. Show both the problem and solution - If relevant, include error messages you encountered. This helps others who google the same error. Format error messages as indented code blocks.

  6. Link to sources - Reference documentation, bug reports, Stack Overflow answers, or other blog posts that helped. Use inline markdown links.

  7. Keep sentences short - Prefer simple declarative sentences. Break up complex explanations.

  8. Use "Note:" sparingly - For genuine warnings or important asides. Format as a paragraph starting with "Note:" or use emphasis.

What NOT to Do

  • No introductions that restate the title - The title is right there.
  • No conclusions that summarize what you just said - The post is short enough to not need it.
  • No "hope this helps!" - It's implied.
  • No apologizing - Don't say "This is a quick post" or "I don't have time to explain fully."
  • No hedging without reason - Don't say "I think this might work" if you tested it and it works. Don't say "This should fix it" - just say "This fixes it."
  • No qualifiers as filler - Avoid "simply", "just", "easily" unless they add meaning. "Just run this command" → "Run this command".
  • No SEO padding - Don't repeat keywords unnaturally or add filler to increase length.
  • No bullet points for flowing prose - Use bullets for lists of items, not for regular paragraphs.
  • No emojis.

Technical Accuracy

  1. Test everything - Don't include commands or config you haven't verified.

  2. Version specificity - Mention OS/software versions when relevant: "On Debian bookworm (12)..." or "With Python 3.11..."

  3. Show your work - If debugging, show the diagnostic commands and their output.

  4. Admit limitations - If a solution is a workaround or has known issues, say so.

Formatting Conventions

Meta Header

Every post starts with:

[[!meta title="Descriptive Title Here"]]
[[!meta date="YYYY-MM-DDTHH:MM:SS.000+TZ:00"]]
[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)"]]
  • For the date, use the same timezone as the most recent blog post in the repository.
  • The date format is ISO 8601 with milliseconds (always .000) and timezone offset.
  • Leave exactly one blank line between the meta header and the first paragraph.

Titles

  • Sentence case, not Title Case: "Setting up unattended upgrades on Debian"
  • Be specific: "Debugging slow SSH connections on Debian bookworm" not "SSH tips"
  • Often describes the task or problem

Headings

  • Use ## for main sections within a post (H2)
  • Use ### for subsections (H3)
  • Use #### for sub-subsections (H4) when needed
  • Headings are sentence case, not Title Case
  • Keep them short and descriptive
  • Leave a blank line before and after each heading for readability.

Code Blocks

  • Use indented code blocks (4 spaces) rather than fenced blocks

  • For shell commands:

    • Use $ prompt when showing command output together (e.g., $ command followed by output)
    • Omit $ prompt for commands that stand alone without output
    • Be consistent within a single post
  • For config files, include enough context (not just the changed line). Show surrounding config or the complete relevant section.

  • Introduce each block with a sentence explaining why it is there and leave a blank line before and after the block.

  • Use diff format for configuration changes when showing before/after (indented with 4 spaces):

    --- a/etc/config
    +++ b/etc/config
    @@ -1,1 +1,1 @@
    -old_setting=false
    +old_setting=true
    

Links

  • Inline links: [link text](URL)
  • For Debian packages: link to https://packages.debian.org/ (include suite like bookworm when relevant)
  • For man pages: link to https://manpages.debian.org/
  • For upstream projects: link to official docs or GitHub
  • When referencing another post in this blog, use /posts/slug/ URLs (e.g., /posts/usual-server-setup/)
  • Use descriptive link text, not "click here" or bare URLs
  • It's fine to have multiple links in a sentence when relevant

Tags

  • Place tags at the very bottom of the file
  • Use one directive per tag: [[!tag debian]] [[!tag security]]
  • Tags can be on one line or multiple lines - use whichever reads better
  • IMPORTANT: Before selecting tags, list the tags/ directory to see all available tags
  • Use existing tags when possible. Common tags include:
    • debian, ubuntu (distro-specific)
    • sysadmin, security, backup
    • mozilla (for Firefox/Mozilla-related posts)
    • python, golang (language-specific - note there is no rust tag)
    • apache, nginx (web servers)
    • asterisk, ham, dmr (telephony/radio)
  • Only create new tags when existing ones truly don't fit
  • Retired tags (do not use): catalyst, nzoss

File Naming

  • Use kebab-case for filenames: my-new-post-title.mdwn
  • Derive the filename from the title, removing stop words if necessary
  • Always use the .mdwn extension
  • Place the file in the posts/ directory

Example Post Structures

Modern problem-solution post:

[[!meta title="Fixing locale warnings after upgrading to Debian trixie"]]
[[!meta date="2025-11-24T10:00:00.000-08:00"]]
[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)"]]

After upgrading one of my servers to Debian trixie, I started seeing locale
warnings whenever I ran apt:

    perl: warning: Setting locale failed.
    perl: warning: Please check that your locale settings...

The fix was to reconfigure locales and ensure my desired locale was generated:

    sudo dpkg-reconfigure locales

I selected `en_CA.UTF-8` from the list and set it as the default.

The warnings stopped after logging out and back in.

[[!tag debian]] [[!tag sysadmin]]

Older terse post (2008 style - still acceptable):

[[!meta title="Debugging concurrency problems: Forcing a process to run on a single CPU"]]
[[!meta date="2008-03-30T11:51:00.004+13:00"]]
[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)"]]

Multi-threading can cause hard-to-diagnose problems and they are especially visible on multi-core CPUs where threads actually run concurrently.

Here's a quick way to find out if the segfaults you are experiencing might be due to some concurrency/locking problem: force the application to run on a single CPU using schedtool.

    schedtool -a 0 -e applicationname

[[!tag debian]] [[!tag ubuntu]]

Working from a topic or outline

If asked to write a post from rough notes or an outline, treat the outline as the source of truth and avoid creative writing detours.

Before drafting

  • Ask clarifying questions when any step, command, or outcome is ambiguous.
  • Highlight unknowns in your own notes so you can either verify them or call them out explicitly in the post.

While drafting

  • Keep the outline's ordering unless the user explicitly asks for a different flow.
  • Convert every bullet/sentence into full prose or headings; no outline item should disappear.
  • Bring short fragments into sentences that explain why the action happened before showing the command or config in an indented block.
  • Carry over quoted text, paths, error messages, or command output verbatim (format as code blocks) so the user recognizes their own words.
  • Maintain the established first-person voice. If the user wrote parts of a paragraph already, integrate their phrasing unchanged unless it conflicts with style rules.
  • Keep it tight. A concise 200-word post that answers the question beats a padded 1,000-word essay.
  • Preserve exact version numbers, package names, and technical details from the outline.

Handling gaps

  • If the outline lacks a command, setting, or result you need, either ask for it or insert a short TODO note for the user instead of inventing details.
  • When you cannot run a command yourself, state that fact in the post and explain what still needs to be verified.

Example translation

Outline fragment:

- apt install foo
- edit /etc/foo.conf (set bar=1)
- restart service

Resulting prose:

I installed the Foo helper so I could test the API locally:

apt install foo

Then I set bar=1 inside /etc/foo.conf to enable the fast path:

bar=1

and restarted the service:

systemctl restart foo

Final checklist

Before replying to the user, confirm that:

  • The timezone was verified by checking the most recent post (do not assume -07:00).
  • The filename, [[!meta]] header, and date format match existing posts.
  • Every outline item appears in the post in the same order unless the user requested otherwise.
  • All commands/config snippets are indented with 4 spaces (not fenced blocks), introduced in prose, and paired with results or explanations where appropriate.
  • Command prompts ($) are used consistently - either showing output or omitted entirely.
  • Any unverified steps are explicitly called out (e.g., "I haven't tested this yet" or TODO notes).
  • Links point to official sources or internal /posts/slug/ URLs where appropriate.
  • The tags/ directory was checked and tags at the bottom reuse existing entries.
  • There is exactly one blank line between paragraphs/headings.
  • No concluding "hope this helps" paragraph or other unnecessary framing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment