Cable Clip
A snap-in cable clip that sticks under or beside a desk with double-sided tape, or screws on with optional M3 tabs. Each round channel has an opening narrower than the cable, so cables are pushed in from the side and held by the flex of the plastic, with a chamfered entry to guide them in. Choosing the cable diameter (3, 5 or 7 mm) updates the channel size, spacing and height together, and the grip tightness is a single ratio. The default 3-channel clip for 5 mm cables measures 25.8 x 12 x 9.7 mm. For the strongest snap, print it standing on its end face so the channels are vertical; it also prints flat on its base without supports. Adjustable parameters: cable diameter, number of channels, clip width, opening ratio and screw tabs.
# Cable Clip - stick or screw under/beside a desk
# Snap-fit: push cables sideways into round channels whose opening is narrower than the cable
@param choices:[3, 5, 7] desc:"Cable diameter (mm)"
cable_d = 5
@param 1..8 desc:"Number of channels"
channels = 3
@param 8..30 desc:"Clip width (along the cable, mm)"
width = 12
@param 0.55..0.9..0.05 desc:"Opening width / cable diameter (smaller = tighter)"
snap = 0.75
@param desc:"Add M3 screw tabs at both ends"
screw_tabs = false
clear = 0.3 # channel clearance per side (loose fit)
base_t = 2.5 # base thickness (double-sided tape side)
rim = 1.6 # minimum wall around the channels
bore = cable_d + clear * 2
pitch = bore + 2.5
end_wall = 2
span = channels * pitch + (end_wall * 2 - (pitch - bore))
h = base_t + bore + rim # leave rim material above the channels (the entry is cut through it)
cz = base_t + bore / 2 # height of the channel centers
gap = cable_d * snap # opening width (narrower than the cable)
flare = 1.2 # entry chamfer (per side)
# Draw the profile (x = across, y = height) on XY, extrude, then stand it up
xs = [(k - (channels - 1) / 2) * pitch for k in range(channels)]
prof0 = rect span h at:(0, h / 2)
bores = [circle (bore / 2) at:(x, cz) for x in xs]
slots = [polyline [(x - gap / 2, cz), (x + gap / 2, cz), (x + gap / 2, h - flare), (x + gap / 2 + flare, h + 0.5), (x - gap / 2 - flare, h + 0.5), (x - gap / 2, h - flare)] for x in xs]
prof = prof0 - bores - slots
clip = prof | extrude width | rotate 90 0 0 | translate 0 (width / 2) 0
# Screw tabs (M3 clearance hole 3.4 dia, no countersink)
tab_l = 9
tab = box tab_l width base_t | floor
tabs = union [tab | translate (span / 2 + tab_l / 2 - 0.5) 0 0, tab | translate (span / -2 - tab_l / 2 + 0.5) 0 0]
holes = union [cylinder 1.7 10 at:((span / 2 + tab_l / 2), 0, 0), cylinder 1.7 10 at:((span / -2 - tab_l / 2), 0, 0)]
with_tabs = (clip + tabs) - holes
if screw_tabs then with_tabs else clip