gier: grep with code-block hierarchy awareness; chier is its companion for whole-file hierarchy queries.
Project description
gier — grep with code block hierarchy awareness
gier is grep with code block hierarchy awareness. chier is its small companion.
gier is a KISS command-line tool that tells you which code block a piece of
code lives in — the enclosing function, class, and control flow — instead of
just a bare line like plain grep. It grew out of watching coding agents (and
people) poke around with grep and wish they could see the surrounding block
hierarchy at a glance; the hope is simply that your friendly coding agent finds
it useful. chier is the companion you reach for when you want the whole-file
hierarchy or a direct "what encloses line N?" query.
Install
uv tool install gier
This installs both gier and chier onto your uv tool path, so you can run
them directly (no uv run needed):
gier "def " "src/**/*.py"
chier -c 47 file.py
If you prefer pip: pip install gier.
The block-path syntax
This is the little language both tools speak, so it is worth knowing by heart. A block is written as:
<level>/<decl>{<start_line>,<start_col>~<end_line>,<end_col>}
/divides the level from the declaration.<level>— 0-based nesting depth.0is the top level (outermost).<decl>— the declaration: the keyword, plus the name fordef/class/function definitions, with parameters and their brackets stripped. Examples:def abcd,class Foo,if,for,while,void foo,fn main,int main,(arrow),object:Foo,const o=.{…}wrap the coordinates.<start_line>,<start_col>— the first character of the declaration (1-based line and column).~separates start from end.<end_line>,<end_col>— the last character of the block's last line (for curly-brace languages, that is the closing}).
When several blocks are reported together, they are joined by a relative marker that describes the relationship to the previous block:
| marker | meaning |
|---|---|
> |
next block is a child (one level deeper) |
| ` | ` |
< |
next block is higher; the count of < is the number of levels ascended |
Example (Python)
0/def abcd{21,1~61,20}>1/if{46,5~48,16}|1/for{52,5~59,18}<0/if{63,1~69,13}
Read left to right: top-level def abcd (line 21) has an if child (line 46)
and a sibling for (line 52); then we ascend back to the top level for another
if (line 63). The whole description is exactly one line — one tidy record per
file, or per match — which is what makes it easy for an agent to parse.
gier — Grep code HIERarchy
gier [-iHh] [-M N] [-N N] PATTERN FILE [.. [FILE]]
For each FILE (expanded with Python's glob, so **/*.py works) every line
matching the compiled PATTERN yields a finding:
- inside a block → the enclosing block's hierarchy plus its source, exactly
like a
chier -cquery; - outside any block (docstring, import, top-level statement) → a classic
grep line
path:line:code.
Options:
-i/--ignore-case— case-insensitive (re.IGNORECASE;re.MULTILINEis always set).-H/--with-filename— always prefixpath:.-h/--no-filename— never prefix (overrides-Hand the auto rule).-N N/--min-block-length N(default5) and-M N/--max-block-length N(default20) — filter the code block;-Mdefaults to20so big blocks stay compact for agents.--help— show usage.
The file name is printed (as path:) when -H is given, or automatically when
the globs resolve to more than one file. Findings are separated by a -- line
(only between findings, never after the last). Exit status: 0 match, 1 none,
2 error.
chier — Code HIERarchy
chier PATH [PATH ...]
chier (-p|-c) LINE PATH
-p LINE/--path-query LINE— print the chain of nested blocks enclosingLINE(root first,>-separated).-c LINE/--code-query LINE— like-p, plus the block's source.-N N/--min-block-length N(default5) — blocks shorter thanNlines merge into their parent, so you get the enclosing scope, not a one-liner.-M N/--max-block-length N(default99999) — blocks longer thanNlines collapse to a singleLINE:CODEline.--exclude-fp-objects— by default a{after= : , [ returnis treated as a block (capturing closures that look like object literals); pass this to revert to the stricter heuristic.--help— show usage.
Library use
from gier import analyze
description = analyze(open("file.c").read(), path="file.c")
How it works
- Python — the
astmodule turns each compound statement into a block;else/finallyheaders are recovered by scanning the source. - Curly-brace languages — a tiny tokenizer (skipping strings, comments,
preprocessor lines) feeds a block matcher that pairs each declaration-
{with its closing}.
True to KISS, this is a deliberately simple heuristic: good recall on ordinary function / method / class / control-flow hierarchy, small readable code, and no pretense of being a full parser.
Tests
The suite in tests/ exercises both the library helpers and the CLI using
real-world files from test-repos/ (a cloned repo is skipped when absent):
uv run python -m unittest discover -s tests -t . -v
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gier-0.0.1.tar.gz.
File metadata
- Download URL: gier-0.0.1.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66103107d93501a4ac405bbbf422731caafab686b7fa9a276ed92e3ea5dedfa0
|
|
| MD5 |
2997ea632f1034b1d9f76b1cc76e81a8
|
|
| BLAKE2b-256 |
75890e32bdcfa45d28674c43423b9d307d85731850a767b2d408297fb14672bf
|
Provenance
The following attestation bundles were made for gier-0.0.1.tar.gz:
Publisher:
publish.yml on jejay/gier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gier-0.0.1.tar.gz -
Subject digest:
66103107d93501a4ac405bbbf422731caafab686b7fa9a276ed92e3ea5dedfa0 - Sigstore transparency entry: 2164617516
- Sigstore integration time:
-
Permalink:
jejay/gier@b9d49d28447773838c87418565865f8610a21960 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/jejay
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b9d49d28447773838c87418565865f8610a21960 -
Trigger Event:
release
-
Statement type:
File details
Details for the file gier-0.0.1-py3-none-any.whl.
File metadata
- Download URL: gier-0.0.1-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6faecc83bb31bb643f1ec96ded832af3bb0bbb2be77db50b230e25fd54beefcc
|
|
| MD5 |
0fd2f10703202c8c0d7198819b4e78db
|
|
| BLAKE2b-256 |
15e3f678e8c5045f0d06935bd4d6b8e628e403b1415f82d90ec2ad0a63d4c651
|
Provenance
The following attestation bundles were made for gier-0.0.1-py3-none-any.whl:
Publisher:
publish.yml on jejay/gier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gier-0.0.1-py3-none-any.whl -
Subject digest:
6faecc83bb31bb643f1ec96ded832af3bb0bbb2be77db50b230e25fd54beefcc - Sigstore transparency entry: 2164617523
- Sigstore integration time:
-
Permalink:
jejay/gier@b9d49d28447773838c87418565865f8610a21960 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/jejay
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b9d49d28447773838c87418565865f8610a21960 -
Trigger Event:
release
-
Statement type: