Non-graphical PCB design software
Though EAGLE is a graphical editor, it can be controlled entirely via command line, which is the single input line above the drawing area. The commands can also be written to a script file, and though I haven't looked for it, it is for sure possible to start EAGLE from the operating system's command line and tell it to run the script and then do a CAM job to generate the Gerber files.

This is the layout of the well known simple astable multivibrator:



and this is a (cleaned-up) script which would draw it. (I've drawn it and exported it via the export-board.ulp from here):


GRID INCH 0.005

ADD 'C1' C025-024X044@rcl R0.000 (0.300 0.700);
ADD 'C2' C025-024X044@rcl R0.000 (0.600 0.700);
ADD 'GND' P1-13@testpad R0.000 (1.000 0.150);
ADD 'R1' 0204V@rcl R90.000 (0.100 0.750);
ADD 'R2' 0204V@rcl R90.000 (0.350 0.900);
ADD 'R3' 0204V@rcl R90.000 (0.550 0.900);
ADD 'R4' 0204V@rcl R90.000 (0.800 0.750);
ADD 'T1' TO92@transistor R270.000 (0.800 0.400);
ADD 'T2' TO92@transistor R270.000 (0.100 0.400);
ADD 'VCC' P1-13@testpad R0.000 (1.000 0.950);


LAYER 20
WIRE 0.000 (0.000 0.000) (1.187 0.000);
WIRE 0.000 (1.187 0.000) (1.187 1.100);
WIRE 0.000 (1.187 1.100) (0.000 1.100);
WIRE 0.000 (0.000 1.100) (0.000 0.000);

LAYER 1
SIGNAL 'N$1' R1 1 C1 1 T2 3;

WIRE 'N$1' 0.016 (0.100 0.450) (0.100 0.700);
WIRE 'N$1' 0.016 (0.100 0.700) (0.250 0.700);

SIGNAL 'N$2' C1 2 R2 1 T1 2;
WIRE 'N$2' 0.016 (0.350 0.850) (0.350 0.700);
LAYER 16
WIRE 'N$2' 0.016 (0.875 0.400) (0.450 0.400);
WIRE 'N$2' 0.016 (0.450 0.400) (0.350 0.500);
WIRE 'N$2' 0.016 (0.350 0.500) (0.350 0.700);
LAYER 1

SIGNAL 'N$3' R3 1 C2 1 T2 2;
WIRE 'N$3' 0.016 (0.550 0.850) (0.550 0.700);
WIRE 'N$3' 0.016 (0.175 0.400) (0.450 0.400);
WIRE 'N$3' 0.016 (0.450 0.400) (0.550 0.500);
WIRE 'N$3' 0.016 (0.550 0.500) (0.550 0.700);

SIGNAL 'N$4' C2 2 R4 1 T1 3;
WIRE 'N$4' 0.016 (0.650 0.700) (0.800 0.700);
WIRE 'N$4' 0.016 (0.800 0.700) (0.800 0.450);

SIGNAL 'N$5' R1 2 R2 2 R3 2 R4 2 VCC TP;
WIRE 'N$5' 0.016 (0.100 0.800) (0.100 0.850);
WIRE 'N$5' 0.016 (0.100 0.850) (0.200 0.950);
WIRE 'N$5' 0.016 (0.200 0.950) (0.350 0.950);
WIRE 'N$5' 0.016 (0.350 0.950) (0.550 0.950);
WIRE 'N$5' 0.016 (0.550 0.950) (0.800 0.950);
WIRE 'N$5' 0.016 (0.800 0.950) (1.000 0.950);
WIRE 'N$5' 0.016 (0.800 0.800) (0.800 0.950);

SIGNAL 'N$7' T2 1 T1 1 GND TP;
WIRE 'N$7' 0.016 (0.100 0.350) (0.100 0.250);
WIRE 'N$7' 0.016 (0.100 0.250) (0.200 0.150);
WIRE 'N$7' 0.016 (0.200 0.150) (0.800 0.150);
WIRE 'N$7' 0.016 (0.800 0.150) (1.000 0.150);
WIRE 'N$7' 0.016 (0.800 0.350) (0.800 0.150);



One could simplify this, but yet, that's something for someone with way too much time...