ΤΕΥΧΟΣ 019  ·  23 ΟΚΤΩΒΡΙΟΥ 2026 RSS
CodeCity
ΑΝΑΠΤΥΞΗ № 0019

ast-grep: το grep που καταλαβαίνει κώδικα, όχι κείμενο

Το ast-grep ψάχνει και ξαναγράφει κώδικα με βάση τη δομή του, όχι το κείμενο, ώστε το ίδιο μοτίβο να βρίσκει όλες τις κλήσεις που έχουν την ίδια μορφή και καμία από τις παγίδες που απλώς μοιάζουν με κώδικα. Στη δοκιμή μας, σε αρχείο με τη λέξη console.log μέσα σε σχόλιο, μέσα σε αλφαριθμητικό και μέσα σε κλειδί αντικειμένου, το απλό grep βρήκε 4 σημεία και το ast-grep βρήκε 1 — τη μόνη πραγματική κλήση.

ast-grep: το grep που καταλαβαίνει κώδικα, όχι κείμενο

Τι κάνει

Έχεις ένα project με χιλιάδες αρχεία. Θέλεις να βρεις κάθε σημείο όπου καλείται μία συνάρτηση, ή να αλλάξεις ένα παλιό μοτίβο σε καινούργιο σε όλο τον κώδικα. Παίρνεις το γνωστό εργαλείο αναζήτησης κειμένου, γράφεις τη λέξη, και παίρνεις πίσω τριών λογιών πράγματα: τις αληθινές κλήσεις, τις αναφορές μέσα σε σχόλια, και τις ίδιες λέξεις μέσα σε αλφαριθμητικά. Και τα τρία μοιάζουν με κώδικα. Μόνο τα πρώτα είναι.

Το ast-grep λύνει το πρόβλημα επειδή δεν διαβάζει το κείμενο γραμμή προς γραμμή. Διαβάζει το συντακτικό δέντρο — το AST, δηλαδή τον τρόπο που ο υπολογιστής αναπαριστά τον κώδικα, με κόμβους για κλήσεις, ορίσματα, τελεστές. Γράφεις το μοτίβο σαν να έγραφες κώδικα, και το εργαλείο ψάχνει κόμβους με την ίδια δομή, αδιαφορώντας για κενά, αλλαγές γραμμής ή στοίχιση.

Μεταβλητές που ξεκινούν με $, όπως το $A, στέκονται στη θέση οποιουδήποτε κομματιού κώδικα. Το μοτίβο $PROP && $PROP() βρίσκει κάθε έλεγχο μηδενικής τιμής πάνω σε κλήση μεθόδου. Η παράμετρος --rewrite αλλάζει το κομμάτι που βρέθηκε, και η υποεντολή scan εφαρμόζει κανόνες γραμμένους σε YAML, σαν linter με δικά σου κριτήρια.

Πίσω από αυτό είναι ένα τετράχρονο έργο γραμμένο σε Rust: github.com/ast-grep/ast-grep, άδεια MIT, 16.319 αστέρια, 482 forks, 54 ανοιχτά issues, πρώτη δημοσίευση την 1η Ιουλίου 2022. Η τελευταία έκδοση είναι η 0.51.0, δημοσιευμένη στις 15 Οκτωβρίου 2026 — 177 εκδόσεις συνολικά. Στο μητρώο npm, το πακέτο @ast-grep/cli κατέβηκε 7.576.712 φορές τον τελευταίο μήνα, από τις 19 Σεπτεμβρίου έως τις 18 Οκτωβρίου 2026. Το άλλο πακέτο, το @ast-grep/napi, που το χρησιμοποιούν άλλα εργαλεία για να μιλήσουν στο ίδιο δέντρο: 14.789.641 λήψεις στο ίδιο διάστημα.

Για ποιον είναι

Για όποιον έχει κώδικα και θέλει να τον αλλάξει μαζικά χωρίς να τον αλλάξει λάθος. Μία μετονομασία που πρέπει να γίνει σε πεντακόσια σημεία. Ένα παλιό μοτίβο κλήσης που αντικαθίσταται από καινούργιο. Έναν κανόνα που απαγορεύει τη χρήση μίας συνάρτησης και θέλεις να δεις πού παραβιάζεται.

Το μεγάλο κοινό του όμως είναι αλλού. Είναι οι πράκτορες κώδικα. Ένας βοηθός που δουλεύει σε αποθετήριο αναζητά συνεχώς πράγματα και συχνά ξαναγράφει αρχεία. Εκεί το ast-grep γίνεται τα μάτια του: του δίνεις μία εντολή, και παίρνει ακριβείς θέσεις αντί για θόρυβο. Δεν χρειάζεται να ξέρεις Rust, ούτε να στήσεις τίποτα βαρύ — ένα δυαδικό αρχείο είναι.

Δεν έχει νόημα όταν ψάχνεις κείμενο, όχι κώδικα. Σε ένα αρχείο καταγραφής, σε μία τεκμηρίωση, σε μία λίστα ονομάτων, το απλό grep είναι σωστό εργαλείο και ταχύτερο. Και δεν έχει νόημα για μία και μοναδική αλλαγή που την κάνεις με το χέρι σε δέκα δευτερόλεπτα.

Εγκατάσταση

Ο δρόμος του npm

Από οποιονδήποτε φάκελο, μία φορά:

npm i -g @ast-grep/cli@0.51.0

Στη δοκιμή μας πήρε 6,246 δευτερόλεπτα. Έλεγχος ότι μπήκε:

ast-grep --version

Η απάντηση ήταν ast-grep 0.51.0. Το πακέτο έχει μία μόνο εξάρτηση, τη detect-libc.

Ο δρόμος του zip για Windows

Κατεβάζεις το αρχείο για Windows από τη σελίδα εκδόσεων του αποθετηρίου. Είναι 16.249.102 bytes, δηλαδή 16,2 MB, και μέσα κρύβει ένα δυαδικό των 54.041.600 bytes (51,5 MB). Δεν έχει εγκαταστάτη, δεν πειράζει το PATH, δεν θέλει επανεκκίνηση. Το ξεπακετάρεις, μπαίνεις στον φάκελο και ρωτάς την έκδοση:

ast-grep --version

Η απάντηση ήταν πάλι ast-grep 0.51.0. Αυτός ο δρόμος είναι ο πιο καθαρός για δοκιμή: δεν εγκαθιστά τίποτα στο σύστημα και δεν αφήνει τίποτα πίσω όταν τον σβήσεις.

Και στις δύο περιπτώσεις ισχύει το ίδιο: δεν ζητάει κλειδί, δεν βγαίνει στο δίκτυο, δεν έχει τηλεμετρία.

Χρήση σε κάθε LLM

Πρώτα το σημαντικό, γιατί εδώ κρύβεται μία παρεξήγηση. Το ast-grep δεν είναι MCP server. Δεν το «δηλώνεις» σε έναν βοηθό όπως δηλώνεις έναν server εργαλείων. Στην έκδοση 0.51.0 οι υποεντολές του είναι run, scan, test, new, lsp, outline και completions — δεν υπάρχει υποεντολή mcp (CLI reference).

Άρα η χρήση του από πράκτορα γίνεται με δύο τρόπους. Ο πρώτος, και ο πιο συνηθισμένος, είναι το κέλυφος: ο πράκτορας δίνει την εντολή και παίρνει πίσω κείμενο ή JSON. Ο δεύτερος είναι ο language server, που τον χρησιμοποιεί η επέκταση του VS Code και δίνει διαγνώσεις μέσα στον επεξεργαστή καθώς γράφεις, μαζί με γρήγορες διορθώσεις.

Οι εντολές που ακολουθούν είναι εντολές κελύφους και τις τρέξαμε ως τέτοιες. Τι δεν τρέξαμε: δεν οδηγήσαμε τον πράκτορα του Codex CLI ούτε του Claude Code από την αρχή ως το τέλος, γιατί δεν έχουμε αυτά τα προγράμματα σε αυτό το μηχάνημα — τον Cursor τον έχουμε, αλλά πάλι δεν άνοιξα συνεδρία πράκτορα μέσα του. Δηλαδή: οι εντολές δουλεύουν, η συμπεριφορά του κάθε βοηθού απέναντί τους είναι δική μου εκτίμηση από τη ροή λειτουργίας.

Claude Code

Στο Claude Code ο δρόμος είναι το εργαλείο του κελύφους. Δίνεις στον πράκτορα άδεια να τρέξει την εντολή, και μετά τη ζητάει μόνος του μέσα στην κουβέντα. Αναζήτηση με δομή, με έξοδο που διαβάζει μηχανή:

ast-grep run -p 'console.log($A)' -l js --json

Μαζική διόρθωση από κανόνες, αφού πρώτα δεις τι θα αλλάξει:

ast-grep scan -U

Έλεγχος ότι ο κανόνας πιάνει αυτό που νομίζεις:

ast-grep test

Ένα σχόλιο εδώ, και το εξηγώ στην ενότητα των παγίδων: το scan διαβάζει κανόνες από ένα αρχείο ρύθμισης και έναν φάκελο με κανόνες, και το -U εφαρμόζει τις αλλαγές χωρίς ερώτηση. Δεν είναι εντολή για να την αφήσεις ελεύθερη σε έναν βοηθό πριν ελέγξεις τους κανόνες.

Codex CLI

Στο Codex CLI ο δρόμος είναι ίδιος στο σκεπτικό — κέλυφος — με τη διαφορά ότι το Codex έχει δικά του όρια ασφαλείας στο τι επιτρέπει να τρέξει. Οι εντολές είναι οι ίδιες:

ast-grep run -p '$A && $A()' --rewrite '$A?.()' -l ts

Αυτή δείχνει τη διαφορά που θα έκανε, χωρίς να την κάνει. Όταν είσαι σύμφωνος, προσθέτεις την εφαρμογή. Και για να πάρεις δομημένη λίστα αντί για κείμενο:

ast-grep run -k call_expression -l ts --json=stream

Το -k ψάχνει με βάση το είδος του κόμβου αντί για ολόκληρο μοτίβο, χρήσιμο όταν θες το αντίστροφο — όχι «αυτή η κλήση» αλλά «κάθε κλήση».

Cursor

Στον Cursor έχεις και τους δύο δρόμους μαζί. Ο πράκτορας έχει τερματικό και τρέχει τις ίδιες εντολές. Και επειδή ο Cursor είναι VS Code με άλλο ένδυμα, δέχεται την επέκταση του ast-grep, που μιλάει στον language server και σου δίνει υπογραμμίσεις και διορθώσεις μέσα στο αρχείο.

Από το τερματικό, μία γρήγορη χαρτογράφηση ενός φακέλου — τι έχει μέσα, χωρίς να το ανοίξεις:

ast-grep outline src/

Και αναζήτηση μέσα σε ένα project Python:

ast-grep run -p 'foo($A)' -l py --json

Για τον δρόμο της επέκτασης, η διαδρομή είναι: άνοιξε τον πίνακα επεκτάσεων, αναζήτησε ast-grep, εγκατέστησε, και μετά η επέκταση φορτώνει τον language server της ίδιας της γραμμής εντολών. Δεν το δοκιμάσαμε αυτό το κομμάτι — δεν άνοιξα επέκταση μέσα στον Cursor.

Πού κερδίζει, πού χάνει

Κερδίζει στο πρώτο, μεγάλο πρόβλημα: βρίσκει κώδικα και δεν πιάνει ό,τι μοιάζει με κώδικα. Τα νούμερα της δοκιμής το λένε. Και κερδίζει στην ταχύτητα, με φόντο τη γλώσσα που το φιλοξενεί, τη Rust: 94.025 αρχεία σε 17,119 δευτερόλεπτα.

Κερδίζει γιατί είναι ένα δυαδικό αρχείο χωρίς εξαρτήσεις και χωρίς δίκτυο. Κατεβάζεις, ξεπακετάρεις, τρέχεις. Δεν ζητά κλειδί, δεν στέλνει τίποτα έξω, δεν έχει τηλεμετρία.

Και κερδίζει γιατί δεν φέρνει τίποτα μαζί του στη συνεδρία ενός βοηθού. Δεν είναι MCP server, δεν φορτώνει σχήματα εργαλείων στο πλαίσιο. Μία εντολή, μία απάντηση.

Τώρα πού χάνει και τι προσέχεις. Πέντε πράγματα, με σειρά σοβαρότητας.

Πρώτο, το sg. Θα το δεις σε παλιά άρθρα, παλιά σχόλια, παλιά παραδείγματα. Είναι το παλιό όνομα του εργαλείου και έχει αποσυρθεί· επιπλέον σε Linux κρούει με την ενσωματωμένη εντολή setgroups. Η σωστή εντολή είναι ast-grep. Αν αντιγράψεις παράδειγμα με sg, μπορεί να μη βρεις καν το πρόγραμμα.

Δεύτερο, το -U γράφει παντού όπου κοιτάζει. Δεν κάνει ερώτηση και δεν σταματά. Σε δοκιμή μας, ένας αντιγραμμένος φάκελος μέσα στο project διπλασίασε τις αλλαγές: 10 αντί για 5. Το λάθος δεν είναι του εργαλείου, είναι της λίστας των αρχείων που του έδωσες. Πριν το -U: δες τους κανόνες, δες τα μοτίβα αγνόησης, τρέξε το σκέτο scan χωρίς -U και διάβασε τη διαφορά.

Τρίτο, το ast-grep test δεν περνάει με την πρώτη. Ο μηχανισμός δουλεύει με στιγμιότυπο σύγκρισης (baseline snapshot). Σε καινούργιο κανόνα, το πρώτο πέρασμα βγαίνει FAIL επειδή το στιγμιότυπο δεν υπάρχει ακόμη. Θέλει --update-all για να γραφτεί πρώτα, και μετά το τεστ είναι πραγματικό τεστ. Όποιος δει FAIL και νομίσει ότι ο κανόνας είναι λάθος, θα κυνηγήσει φαντάσματα.

Τέταρτο, η διακυβέρνηση κρέμεται από ένα πρόσωπο. Το έργο έχει 97 συνεργάτες, αλλά ο βασικός συντηρητής έχει 2.812 commits, την ώρα που ο επόμενος άνθρωπος έχει 12 (GitHub contributors API, σήμερα). Είναι ώριμο τετράχρονο έργο, με χορηγούς, χωρίς εταιρεία από πίσω. Δεν είναι σκάνδαλο, είναι ρίσκο που το ξέρεις: αν του συμβεί κάτι, το έργο δεν έχει δεύτερο τιμόνι.

Πέμπτο, οι χρήστες που δηλώνει. Η σελίδα τεκμηρίωσης λέει ότι το χρησιμοποιούν τα SWC, Shopify Hydrogen, CodeRabbit, Codemod, Dify και Modern.js. Το μεταφέρω ως ισχυρισμό του έργου, όχι ως γεγονός που ελέγξαμε — δεν πήγα σε κάθε ένα από αυτά τα αποθετήρια να το επιβεβαιώσω.

Και μία διαφορά από ό,τι έχουμε καλύψει ως τώρα. Το Context7 δίνει τεκμηρίωση, το Basic Memory κρατά σημειώσεις — και τα δύο απαντούν στο «τι σημαίνει αυτό». Το ast-grep απαντά στο «πού είναι αυτό μέσα στον κώδικα», και μάλιστα με τη μορφή που μια μηχανή μπορεί να διαβάσει. Είναι άλλο είδος εργαλείου, και μπαίνει ακριβώς στη στιγμή που ένας πράκτορας σηκώνει το χέρι του να αλλάξει κώδικα.

Δοκιμή

Ό,τι ακολουθεί το τρέξαμε σήμερα σε Windows 11, σε ένα Dell Inspiron 3576, χωρίς κάρτα γραφικών.

Η εγκατάσταση από τον npm πήρε 6,246 δευτερόλεπτα, και η έκδοση απάντησε ast-grep 0.51.0. Δίσκος: 16,2 MB κατέβασμα, 51,5 MB μετά την αποσυσκευασία.

Το πείραμα που μετράει, πρώτο. Έφτιαξα ένα αρχείο όπου η λέξη console.log υπάρχει σκόπιμα σε τρία λάθος σημεία: μέσα σε σχόλιο, μέσα σε αλφαριθμητικό, και ως κλειδί αντικειμένου — και σε ένα σωστό σημείο, ως πραγματική κλήση. Το απλό grep βρήκε 4 σημεία. Το ast-grep βρήκε 1: τη μόνη πραγματική κλήση.

Το ίδιο, σε δείγμα τεσσάρων αρχείων. Το απλό grep έδωσε 8 σημεία, το ast-grep 5. Δηλαδή 37,5% όσων θα «διόρθωνε» μία αντικατάσταση κειμένου θα ήταν ζημιά — τρεις από τις οκτώ αλλαγές θα χτυπούσαν σχόλια, αλφαριθμητικά ή κλειδιά.

Δεύτερο, μαζική διόρθωση με κανόνα:

ast-grep scan -U

Απάντηση: «Applied 5 changes» σε 0,070 δευτερόλεπτα. Πέντε στις πέντε σωστές.

Τρίτο, τεστ κανόνα:

ast-grep test

Το πρώτο πέρασμα βγήκε FAIL, επειδή δεν υπήρχε στιγμιότυπο σύγκρισης. Με --update-all γράφτηκε το στιγμιότυπο, και το δεύτερο πέρασμα βγήκε PASS: «1 passed; 0 failed» σε 0,078 δευτερόλεπτα.

Τέταρτο, κλίμακα. Σάρωσα 94.025 αρχεία κώδικα, σε JavaScript, TypeScript και Python, σε 17,119 δευτερόλεπτα. Όσο πίνεις μία γουλιά καφέ.

Και η παγίδα που μετράει, γιατί είναι η ακριβή. Έβαλα μέσα στο project έναν αντιγραμμένο φάκελο με τα ίδια αρχεία και ξανάτρεξα το scan -U. Οι αλλαγές διπλασιάστηκαν: 10 αντί για 5, γιατί το εργαλείο είδε τα ίδια αρχεία δύο φορές. Τίποτα δεν κατέστρεψε — τα αρχεία ήταν αντίγραφα — αλλά το μάθημα κόστισε ένα λεπτό και θα μπορούσε να κοστίσει ένα αποθετήριο.

Τι δεν τρέξαμε, και το λέω καθαρά: δεν τρέξαμε καμία συνεδρία πράκτορα μέσα σε Claude Code, Codex CLI ή Cursor. Δεν έχουμε τα δύο πρώτα στο μηχάνημα, και στον Cursor δεν άνοιξα συνεδρία. Οι εντολές που έδωσα παραπάνω τρέχουν στο κέλυφος, και αυτό είναι το κομμάτι που δοκιμάστηκε.

Τι κοστίζει

Χρήμα: μηδέν. Άδεια MIT, επαληθευμένη και στο αποθετήριο και στο npm. Δεν υπάρχει συνδρομή, δεν υπάρχει κλειδί, δεν υπάρχει χρέωση ανά χρήση.

Βάρος: 16,2 MB κατέβασμα, 51,5 MB στον δίσκο μετά την αποσυσκευασία. Το πακέτο του npm έχει μία εξάρτηση, τη detect-libc, που υπάρχει μόνο για να καταλάβει το εργαλείο σε ποιο σύστημα τρέχει.

Πλαίσιο και tokens: εδώ είναι το καλό νέο, και το λέω ως εκτίμηση από τη ροή λειτουργίας, όχι ως μέτρηση. Επειδή δεν είναι MCP server, δεν φορτώνει κανένα σχήμα εργαλείων στη συνεδρία του βοηθού. Δεν πληρώνεις τίποτα μέχρι να το καλέσεις, και όταν το καλέσεις πληρώνεις μόνο την έξοδο που διάλεξες: μία γραμμή κειμένου, ή λίγο JSON με τις θέσεις που ζήτησες. Δεν μετράω tokens εδώ γιατί δεν υπάρχει καταχώρηση στη λίστα εργαλείων να μετρηθεί.

Κρυφό κόστος: ο χρόνος της μάθησης. Το --rewrite και το scan θέλουν να μάθεις τη λογική των μοτίβων — πού μπαίνει το $, τι πιάνει το -k, τι σημαίνει «αυστηρότητα» στην αντιστοίχιση. Δεν είναι δύσκολο, αλλά δεν είναι και η πρώτη φορά. Και υπάρχει η ασφάλεια γύρω από το -U, που κοστίζει πειθαρχία: κοίτα τη διαφορά πριν την εφαρμόσεις.

Δημόσια νούμερα, με την πηγή τους. Στο npm, το @ast-grep/cli έχει 7.576.712 λήψεις τον μήνα από 19 Σεπτεμβρίου έως 18 Οκτωβρίου 2026, με 177 εκδόσεις συνολικά, η τελευταία στις 15 Οκτωβρίου 2026. Στο GitHub, 16.319 αστέρια, 482 forks, 54 ανοιχτά issues, αποθετήριο ανοιχτό από την 1η Ιουλίου 2022. Το ότι η βιβλιοθήκη napi έχει τις διπλάσιες και πάνω λήψεις από τη γραμμή εντολών λέει κάτι ενδιαφέρον: το μεγαλύτερο κοινό του ast-grep δεν το τρέχει, το καλεί μέσα από άλλα εργαλεία.

Ετυμηγορία

Το ast-grep κάνει μία δουλειά που όλοι νομίζουν ότι την κάνουν με το grep, και δεν την κάνουν. Στο πείραμά μας, το απλό grep έδωσε τέσσερα σημεία και το ast-grep ένα — τη μόνη πραγματική κλήση. Στα τέσσερα αρχεία, το 37,5% των αλλαγών που θα έκανε μία αντικατάσταση κειμένου θα ήταν ζημιά.

Είναι μικρό, γρήγορο και δωρεάν. 94.025 αρχεία σε 17,119 δευτερόλεπτα, 16,2 MB κατέβασμα, μηδέν ευρώ, μηδέν κλειδί, μηδέν τηλεμετρία. Για έναν πράκτορα κώδικα είναι σχεδόν ιδανικό εργαλείο: δεν του φορτώνει το πλαίσιο με σχήματα, του δίνει όμως ένα ζευγάρι μάτια που δεν ξεγελιούνται από σχόλια.

Οι αντιρρήσεις είναι συγκεκριμένες. Το sg έχει αποσυρθεί και η μπερδεμένη ονομασία θα σε ταλαιπωρήσει μία φορά. Το -U γράφει όπου του πεις, και σε δοκιμή μας το αντίγραφο φακέλου διπλασίασε τις αλλαγές. Το test θέλει πρώτα στιγμιότυπο. Και η διακυβέρνηση στηρίζεται σε έναν άνθρωπο, με 2.812 commits έναντι 12 του επόμενου.

Αν δουλεύεις κώδικα — μόνος ή με πράκτορα — εγκατέστησέ το σήμερα. Δεν έχει κόστος, δεν έχει ρίσκο εγκατάστασης, και απαντά σε μία ερώτηση που θα κάνεις αύριο. Πριν αφήσεις το -U ελεύθερο σε ζωντανό αποθετήριο, τρέξε το σκέτο μία φορά και διάβασε τι θα άλλαζε.

Score: 9.0/10.

Πηγές: αποθετήριο https://github.com/ast-grep/ast-grep · πακέτο γραμμής εντολών https://www.npmjs.com/package/@ast-grep/cli · βιβλιοθήκη napi https://www.npmjs.com/package/@ast-grep/napi · τεκμηρίωση https://ast-grep.github.io/ · αναφορά γραμμής εντολών https://ast-grep.github.io/reference/cli.html · γρήγορη εκκίνηση https://ast-grep.github.io/guide/quick-start.html · συντελεστές https://api.github.com/repos/ast-grep/ast-grep/contributors