M4 nuts are nominally 3.2mm thick. I made the base and lid 2.4mm and sliced it with 0.4mm layers. That meant the top of the nut would be flush with a layer boundary at 5.6mm and I confirmed that the first covering layer was at 6.0mm in Skeinlayer. So I needed to pause the build before the start of the layer at Z=6.0 and insert the nuts.
I run my USB machines using Raspberry PIs and OctoPrint (so that all my machines are connected via Ethernet) and noticed a post by the author, Gina Häußge, that said OctoPrint interprets an M0 in the gcode as a pause command. The host stops sending gcode until you press the pause button to un-pause it again. I believe other hosts use
F12000.0 G1 X-9.082 Y3.907 Z6.0 F12000.0 G1 X-5.457 Y-3.937 Z6.0 F12000.0 G1 X-7.05 Y-3.803 Z6.0 F12000.0 G1 X-11.486 Y-4.991 Z6.0 F12000.0 G1 X-13.721 Y-10.229 Z6.0 F12000.0 G1 F1800.0 G1 E1.0 G1 F12000.0 M101 G1 X-12.65 Y-10.848 Z6.0 F1837.1615 E0.036
What we have is a sequence of non-extruding moves followed by an un-retract and the first extrusion. The moves are the result of the comb module and not really relevant if we are restarting after a pause, so I removed all but the last move and inserted my pause code:
M104 S100 G1 Z6.0 G1 X-100 Y-100 F9000 M0 G1 X10.0 Y98.0 F9000 G1 Z0.05 M109 S250 G92 E0 G1 E3 F50 G1 E-1 F1200 G1 X40.0 F4000 G1 Z6.0 F9000 G1 X-13.721 Y-10.229 Z6.0 F12000.0 G1 F1800.0 G1 E1.0 G1 F12000.0 M101 G1 X-12.65 Y-10.848 Z6.0 F1837.1615 E0.036
The cavity for the nut is made by subtracting a shape like this: 
Here is the OpenScad code. It needs various functions from the Mendel90 source tree.
//
// Smaller alternative to a wingnut
//
include <conf config.scad>
module hanging_hole(or, ir, ofn = 0) {
    union() {
        intersection() {
            if(ofn)
                cylinder(r = or, h = 3 * layer_height, center = true, $fn = ofn);
            else
                poly_cylinder(r = or, h = 3 * layer_height, center = true);
            rotate([0, 0, 90])
                cube([2 * or + 1, 2 * ir, 2 * layer_height], center = true);
        }
        rotate([0, 0, 90])
            cube([ir * 2, ir * 2, 4 * layer_height + 4 * eta], center = true);
        rotate([0, 0, 22.5])
            translate([0, 0, 2 * layer_height])
                cylinder(r = corrected_radius(ir, 8), h = 100, $fn = 8);
    }
}
base_thickness = 2.4;
lid_thickness = 2.4;
function nut_knob_height(nut) = base_thickness + nut_thickness(nut) + lid_thickness;
module nut_knob_stl(screw = M4_hex_screw, d = 14) {
    nut = screw_nut(screw);
    h = nut_knob_height(nut);
    flutes = 3;
    stl("nut_knob");
    rotate([0, 0, -45])
        difference() {
            cylinder(r = d / 2, h = h);                                                 // basic shape
            for(i = [0 : flutes - 1])                                                   // flutes for finger grip
                rotate([0, 0, i * 360 / flutes + 30])
                    translate([d * cos(90 / flutes), 0, base_thickness])
                        cylinder(r = d / 2, h = 100);
            union() {                                                                   // nut cavity
                difference() {
                    translate([0, 0, base_thickness + nut_thickness(nut)])
                        nut_trap(screw_clearance_radius(screw), nut_radius(nut), nut_thickness(nut));
                    translate([0, 0, base_thickness + nut_thickness(nut)])              // remove top of nut trap
                        cylinder(r = 20, h = 110);
                }
                translate([0, 0, base_thickness + nut_thickness(nut)])
                    hanging_hole(nut_radius(nut), screw_clearance_radius(screw), 6);    // replace with hanging hole
            }
        }
}
So this seems to be a general solution to printing holes in mid air without any support material. The only downside is that it is a bit weaker than using a membrane and drilling it out. In this case no strength above the nut was required. In general you can just make it two layers thicker.






