Skip to content

Releases: tardigrde/gcpath

v0.11.0

28 Apr 15:42

Choose a tag to compare

v0.11.0 (2026-04-28)

Bug Fixes

  • Address PR review comments and CI failures (1d733c9)

  • Remove duplicate test_ls_rich_format (ruff F811 CI blocker)

  • Tighten test_format_json_output assertion to check exit_code and option parsing

  • Replace import-time assert in toon.py with GCPathError for deterministic check

  • Keep count header in empty toon_ls output for schema consistency

  • Make _write_json atomic via tmp-file + os.replace

  • Validate JSON root type is dict in _read_json

  • Centralize managed hook matching with _is_managed_hook helper

  • Handle 0.0 cache age as fresh data (is not None check)

  • Narrow broad Exception catch in _parse_resource_arg to GCP/GCPath errors

  • Replace /tmp paths in hook status mock data with user config paths

  • Update README to drop non-existent --json/--yaml shorthand docs

  • Add minimal contents:read permission to CI workflow

Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com

  • Address PR review comments and SonarCloud hotspots (070529c)

  • Restore docstring on _resolve_scope in cli.py

  • Narrow except Exception to specific GCP/gcpath exceptions in path command

  • Fix return type hint on _truncate_metadata (Any -> Dict[str, str])

  • Add docstring on serialize_resource

  • Replace /tmp paths in test_serializers.py to resolve SonarCloud S5443

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Narrow broad exception catch and remove conflicting CodeQL workflow (aae603b)

  • Replace bare except Exception in _resolve_target_path_prefix with
    specific (GCPathError, gcp_exceptions.GoogleAPICallError) as suggested
    in review

  • Remove custom CodeQL workflow files that conflict with the repository's
    default CodeQL setup, causing SARIF upload failures

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

  • Remove unused Path import in test_hooks (8226380)

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Resolve CodeQL false positives and improve test coverage (509df66)

  • Add custom CodeQL workflow with config that excludes test paths from
    URL sanitization checks (fixes 5 false-positive high severity alerts)

  • Add 23 targeted tests for hook commands, rich format outputs, fresh
    cache home view, and format validation (cli.py coverage 73% → 87%)

  • Add codecov.yml with appropriate thresholds (patch ≥80%, project ±2%)

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

  • Resolve SonarCloud issues across cli, hooks, and tests (5414569)

  • Extract _cache_status_rich and _stats_rich to reduce cognitive complexity (S3776)

  • Extract _validate_stats_resource helper for stats command

  • Remove unused params: ctx in _show_home, level in _prepare_hierarchy_command,
    target_resource_name in _ls_help_lines (S1172)

  • Replace duplicated "gcpath hook run" literal with _GCPATH_HOOK_COMMAND constant (S1192)

  • Extract _check_hook_entries to reduce get_hook_status complexity (S3776)

  • Fix unused variables in test_serializers.py (S1481)

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Suppress CodeQL false positives in test assertions (8720d2c)

The in operator on strings like "example.com" triggers CodeQL rule py/incomplete-url-substring-sanitization. These are test output assertions, not URL sanitization code — suppress with lgtm comments.

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

  • Test_ls_type_organization assertion for TOON output format (2872c99)

  • Use simple substring check instead of urlparse which fails on TOON comma-separated rows

  • Remove unused urlparse import to silence CodeQL false positive

Chores

  • deps: Bump requests in the uv group across 1 directory (29b2d81)

Bumps the uv group with 1 update in the / directory: requests.

Updates requests from 2.32.5 to 2.33.0


updated-dependencies:

  • dependency-name: requests dependency-version: 2.33.0

dependency-type: indirect

dependency-group: uv ...

Signed-off-by: dependabot[bot] support@github.com

Documentation

  • Add Agent Skill section to README (be96998)

Adds a dedicated section explaining the bundled agent skill and how to install it via bunx/npx, plus a one-liner callout in the "Why use gcpath" bullet list.

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

  • Add gcpath agent skill for AI agent consumption (30bd24f)

Adds a skills/gcpath/ directory following the Agent Skills spec (agentskills.io), enabling agents to install and use gcpath via:

bunx skills add github:tardigrde/gcpath --skill gcpath

Includes SKILL.md (when-to-use guidance, all commands with examples, common workflows, gotchas) and references/commands.md (compact flag reference per command).

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

  • Rewrite README to highlight agent-native design (32e4bd3)

Restructure the README to lead with gcpath's agent-native qualities: read-only safety, AXI-compliant TOON output, ambient context hooks, and Agent Skill integration. Add output format comparison table and dedicated Agent Integration section with hook setup instructions.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • skill: Enrich frontmatter and trim body per Agent Skills spec (531d4d5)

  • Add allowed-tools: Bash(gcpath:) Bash(uvx gcpath:)

  • Add compatibility, license, and metadata fields

  • Trim SKILL.md from 258 to 143 lines: collapse verbose commands
    section into common workflows + key flags table, move full flag
    reference to references/commands.md with explicit load trigger

  • Keep gotchas inline per best-practices guidance

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

Features

  • Add AXI-compliant output with TOON format, hooks, and content-first home (1e10e8d)

Refactor gcpath from Rich-table-first output to AXI-compliant TOON-first output following the AXI specification (https://axi.md/).

New capabilities: - TOON format as default output (token-efficient, structured for AI agents) - --format toon|json|yaml|rich flag replaces old --json/--yaml flags - --fields flag for controlling output columns (replaces --long) - --full flag to expand truncated labels/tags - Content-first home view: gcpath with no args shows live dashboard - Pre-computed aggregates: count: N of M total on list outputs - Contextual help[] sections with next-step suggestions - Structured errors to stdout in TOON format (no more Rich stderr markup) - Ambient context hooks: gcpath hook install for Claude Code and Codex - gcpath hook run outputs compact session-start dashboard - Definitive empty states: 0 resources found not empty output - All interactive prompts removed (no more typer.confirm)

New files: - src/gcpath/toon.py — TOON encoder wrapper + AXI helpers - src/gcpath/hooks.py — Claude Code / Codex session hook management - tests/test_hooks.py — Hook management tests

Design decisions: - tree keeps classic unicode tree output (not TOON) — agents use ls -R - diagram keeps raw Mermaid/D2 output with --diagram-format flag - toon-format library (git dep) handles TOON encoding

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Add new Claude Code hook format support and README badges (cbfa81f)

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com


Detailed Changes: v0.10.0...v0.11.0

v0.10.0

29 Mar 06:06

Choose a tag to compare

v0.10.0 (2026-03-29)

Bug Fixes

  • Address PR review comments and SonarCloud findings (c756062)

  • Remove unimplemented --show-labels/--show-tags from ancestors command

  • Deduplicate _matches_labels/_matches_tags into generic _matches_metadata

  • Deduplicate _format_labels/_format_tags into generic _format_metadata

  • Use scope_resource for tag lookups instead of always querying org root

  • Replace duplicated "organizations/" literal with _RESOURCE_PREFIX_ORGS constant

  • Sanitize user-controlled data from cache log message

  • Fix single-iteration loop in build_folder_ancestors (parsers.py)

  • Reduce cognitive complexity across cli.py, core.py, formatters.py,
    loaders.py, and parsers.py by extracting helper functions

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

Chores

https://claude.ai/code/session_01HugtU9fbaL97tbb7zaqNPL

  • deps: Bump pyasn1 in the uv group across 1 directory (8adfd85)

Bumps the uv group with 1 update in the / directory: pyasn1.

Updates pyasn1 from 0.6.2 to 0.6.3


updated-dependencies:

  • dependency-name: pyasn1 dependency-version: 0.6.3

dependency-type: indirect

dependency-group: uv ...

Signed-off-by: dependabot[bot] support@github.com

Features

  • Add GCP labels and tags support to CLI commands (d428c9a)

Add opt-in support for GCP resource labels (key-value pairs) and resource tags (Tag Manager bindings) across CLI commands. Labels are fetched via an additional SQL column in Asset API queries (cheap). Tags require a separate Asset API query against TagBinding resources (expensive). Both are only fetched when explicitly requested via CLI flags.

New CLI options on ls, tree, find, ancestors: - --show-labels: display labels in output - --show-tags: display tags in output - --label key=value: filter by label (repeatable, ANDed) - --tag key=value: filter by tag (repeatable, ANDed)

Changes across the stack: - core.py: labels/tags fields on Folder and Project dataclasses - parsers.py: extract_labels() and has_labels param on parse functions - loaders.py: include_labels in SQL builders, load_tags_asset/apply_tags - cache.py: bump CACHE_VERSION to 2, serialize/deserialize labels+tags - serializers.py: include labels/tags in JSON/YAML output when non-empty - formatters.py: show labels/tags in tree view labels

https://claude.ai/code/session_01HugtU9fbaL97tbb7zaqNPL


Detailed Changes: v0.9.0...v0.10.0

v0.9.0

19 Mar 05:22

Choose a tag to compare

v0.9.0 (2026-03-19)

Bug Fixes

  • Address PR review feedback — narrow exception handling and improve consistency (d358e26)

  • Narrow bare except Exception in _resolve_scope() to catch only
    PermissionDenied, NotFound, and GCPathError

  • Move import fnmatch from local scope to top-level imports (PEP 8)

  • Add detailed comment explaining base_segments depth calculation

  • Make PermissionDenied handling consistent in _fetch_chain_link():
    folders and projects now use graceful fallback like organizations

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Reduce cognitive complexity and extract constants for SonarCloud (819f5dd)

  • Extract _fetch_chain_link() from resolve_ancestry_chain() to reduce
    cognitive complexity from 25 to under 15

  • Extract _search_hierarchy() from find command to reduce complexity

  • Extract _get_node_parent_name(), _get_child_folders() in formatters
    to reduce build_tree_view() complexity from 18 to under 15

  • Extract _node_to_dict(), _get_child_folders() in serializers to
    reduce serialize_tree_node() complexity from 18 to under 15

  • Add _PREFIX_ORGS/_PREFIX_FOLDERS/_PREFIX_PROJECTS constants in core.py
    to replace duplicated string literals

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Resolve CI failures, CodeQL alerts, and eager client initialization (d054977)

  • Add missing resolve_ancestry mock to two tests that pass a positional
    resource to ls -l, which triggers _resolve_scope() → resolve_ancestry()
    and fails in CI without GCP credentials

  • Fix 4 CodeQL "Incomplete URL substring sanitization" alerts by replacing
    "example.com" in result.stdout substring checks with exact-match
    alternatives (split()/list comprehension)

  • Lazily initialize GCP API clients in resolve_ancestry() so only the
    client needed for the given resource prefix triggers credential lookup

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Resolve remaining SonarCloud issues — constants and complexity (6257f97)

  • Replace all bare "organizations/", "folders/", "projects/" string
    literals in core.py with _PREFIX_ORGS/_PREFIX_FOLDERS/_PREFIX_PROJECTS

  • Simplify _search_hierarchy() by extracting _get_resource_display_name()
    and _get_resource_path() helpers, using a flat candidate list with
    list comprehension instead of nested loops

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Use explicit equality checks to resolve CodeQL URL sanitization alerts (26f4896)

Replace "example.com" in result.stdout.split() with any(token == "example.com" for token in ...) to avoid CodeQL's incomplete-url-substring-sanitization rule, which still triggers on in with split lists.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

Documentation

  • Document find, ancestors, --type filter, -L depth limit, and structured output (ce92751)

Add README sections for features from PR #26 (--json/--yaml structured output) and PR #28 (find command, ancestors command, --type filter on ls/tree, -L depth limit on ls -R). Updates Quick Start and Features summary accordingly.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

Features

  • Add --type filter, find command, ancestors command, and -L depth limit (25e1ded)

Add four new features to gcpath CLI:

  • --type/-t filter on ls and tree commands (folder, project, organization)
  • find command for glob-style name search with optional type and scope filters
  • ancestors command to show full ancestry chain from resource to org root
  • --level/-L depth limit on ls -R for recursive listing

Refactors scope resolution into shared _resolve_scope() helper to reduce duplication between ls and find commands.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com


Detailed Changes: v0.8.0...v0.9.0

v0.8.0

17 Mar 05:37

Choose a tag to compare

v0.8.0 (2026-03-17)

Bug Fixes

  • Address PR review feedback — reduce duplication in serializers and CLI (40ae2c6)

  • Extract _get_dumper() helper to eliminate repeated dumper selection logic

  • Remove unused hierarchy and show_ids params from serialize_tree_node

  • Reuse serialize_resource() for project dicts instead of duplicating

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

  • Extract duplicated string literals to constants in conftest.py (ed34bc6)

Resolves SonarCloud S1192 issues for "organizations/123", "folders/1", and "folders/11" repeated in test hierarchy builder.

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

  • Resolve SonarCloud duplication and unused variable issues (aa47ef5)

  • Extract shared test hierarchy builder to conftest.py (eliminates
    ~40-line duplication between test_cli.py and test_serializers.py)

  • Fix all 6 unused variable warnings in test_serializers.py

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

Features

  • Add --json and --yaml structured output flags (949d8e3)

Add global --json and --yaml flags for machine-readable output across all commands (ls, tree, name, path). This makes gcpath composable with jq, yq, shell scripts, and CI pipelines.

  • New serializers.py module for dict-building and JSON/YAML dumping
  • Mutually exclusive flags with clear error message
  • Cache status message moved to stderr to avoid polluting structured output
  • pyyaml>=6.0 added as dependency

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com


Detailed Changes: v0.7.1...v0.8.0

v0.7.1

17 Mar 04:23

Choose a tag to compare

v0.7.1 (2026-03-17)

Bug Fixes

  • Extract duplicated "folders/" literal to constant in loaders (b292a3e)

SonarCloud S1192: the string "folders/" was duplicated 5 times. Extract to module-level _FOLDER_PREFIX constant.

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

  • Resolve SonarCloud code quality issues (054bdbe)

Addresses 19 of 31 SonarCloud findings:

S1192 (CRITICAL): Extract duplicated string literals into module-level constants - Added _RESOURCE_PREFIX_PROJECTS, _RESOURCE_PREFIX_FOLDERS, _RESOURCE_PREFIX_ORGS - Added _RESOURCE_PREFIXES tuple and _REFRESH_HELP constant - Replaced all occurrences in cli.py

S1871 (MAJOR): Merge duplicate branches - formatters.py: Merged Folder/Project branches in get_display_path and _get_node_label - parsers.py: Merged hasattr/get and isinstance/dict checks in extract_value

S3358 (MAJOR): Extract nested ternaries into if/else blocks - loaders.py: Refactored folder_parent and project parent_res determination logic

S3776 (CRITICAL): Reduce cognitive complexity with helper extraction - cli.py: Extracted _try_read_cache() from _load_hierarchy() - core.py: Extracted _find_orgless_project() from get_resource_name() - loaders.py: Extracted _build_single_ancestor_chain() from fix_folder_ancestors()

S7504 (MINOR): Remove unnecessary list() call - loaders.py: Changed list(node.folders.values()) to node.folders.values()

S2737 (MINOR): Remove bare except clause - core.py: Removed no-op try/except that just re-raised

S2772 (MINOR): Remove unneeded pass - tests/test_cli.py: Replaced pass with meaningful assertion

S1481 (MINOR): Fix unused variable - tests/test_formatters.py: Changed folders to _ for unused variable

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

Testing

  • Add coverage for extracted helper functions (ab315ee)

Add direct tests for:

  • _build_single_ancestor_chain (loaders.py)
  • _find_orgless_project (core.py)
  • _try_read_cache (cli.py)

Coverage improved from 87% to 88%

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

  • Add coverage for loader conditional branches and remove dead code (37b7f01)

Cover the refactored if/elif/else branches in load_folders_asset and load_projects_asset that handle fallback parent resolution. Remove unreachable elif/else in the last else-branch where ancestors is guaranteed non-empty.

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com


Detailed Changes: v0.7.0...v0.7.1

v0.7.0

09 Mar 07:32

Choose a tag to compare

v0.7.0 (2026-03-09)

Bug Fixes

  • Validate resource format and escape rich markup in stats command (7728b16)

  • Add explicit else branch for invalid resource formats (not
    organizations/ or folders/) with a clear "Invalid resource format"
    error message instead of silently loading the full hierarchy

  • Escape user-supplied scope label with rich.markup.escape to prevent
    markup injection via crafted resource name arguments

  • Add test_stats_invalid_scope_error test case

https://claude.ai/code/session_01JxDqkYXvoag1R6LWBV8Mtq

Chores

  • deps: Bump protobuf in the uv group across 1 directory (176815d)

Bumps the uv group with 1 update in the / directory: protobuf.

Updates protobuf from 6.33.2 to 6.33.5


updated-dependencies:

  • dependency-name: protobuf dependency-version: 6.33.5

dependency-type: indirect

dependency-group: uv ...

Signed-off-by: dependabot[bot] support@github.com

Features

  • Add stats subcommand for folder/project counts in a scope (9a28f93)

Adds a new stats CLI subcommand that reports the number of organizations, folders, and projects within a given scope (organization or folder). When no scope is provided, it reports totals across all accessible organizations. Projects are rejected as the starting scope since they are leaf nodes.

https://claude.ai/code/session_01JxDqkYXvoag1R6LWBV8Mtq


Detailed Changes: v0.6.1...v0.7.0

v0.6.1

07 Mar 22:43

Choose a tag to compare

v0.6.1 (2026-03-07)

Bug Fixes

  • deps: Bump pyasn1 to 0.6.2 and urllib3 to 2.6.3 (bd4c47c)

Fixes CVE-2026-23490 (pyasn1 OID decoder issue) and CVE-2026-21441 (urllib3 decompression-bomb bypass, High severity).

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

Documentation

  • Refocus README on CLI usage, add pipx install, remove roadmap (cb03af6)

Move Python API section to the end as a secondary use case. Add pipx as a recommended installation option alongside pip and uv. Remove the roadmap section.

https://claude.ai/code/session_01E5TmezTsqmhrkBS6HdVSL9


Detailed Changes: v0.6.0...v0.6.1

v0.6.0

07 Mar 22:14

Choose a tag to compare

v0.6.0 (2026-03-07)

Chores

  • deps: Bump protobuf in the uv group across 1 directory (a21b624)

Bumps the uv group with 1 update in the / directory: protobuf.

Updates protobuf from 6.33.2 to 6.33.5


updated-dependencies:

  • dependency-name: protobuf dependency-version: 6.33.5

dependency-type: indirect

dependency-group: uv ...

Signed-off-by: dependabot[bot] support@github.com

  • deps: Configure Dependabot to use pip for updates (322a771)

Features

  • Add Python API documentation and library usage examples (aa65f59)

  • Add comprehensive "Python API" section to README.md covering:

    • Basic usage with Hierarchy.load() (both RM and Asset API modes)
    • Path ↔ resource name conversion methods
    • Lightweight single-resource lookup via Hierarchy.resolve_ancestry()
    • Scoped loading for large or restricted hierarchies
    • Error handling with GCPathError, ResourceNotFoundError, PathParsingError
    • API reference table for all public symbols
  • Update pyproject.toml description to reflect library capability

  • Add "Topic :: Software Development :: Libraries :: Python Modules" classifier

https://claude.ai/code/session_01M3eDcpXVjivW3zbCXnvbmx


Detailed Changes: v0.5.1...v0.6.0

v0.5.1

17 Feb 06:53

Choose a tag to compare

v0.5.1 (2026-02-17)

Bug Fixes

  • Make cache scope-aware so entrypoint loads are cached (c288a51)

The cache was completely bypassed when an entrypoint was configured because _load_hierarchy() only read/wrote cache when scope_resource was None. Now the cache stores which scope it was built for and only serves hits when the scope matches, enabling instant subsequent commands with entrypoints.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com


Detailed Changes: v0.5.0...v0.5.1

v0.5.0

16 Feb 16:46

Choose a tag to compare

v0.5.0 (2026-02-16)

Features

  • Add folder entrypoint support for folder admins without org access (e15c6ca)

Allow users who only have access to a folder (not the parent organization) to use ls, tree, diagram, and name commands by configuring a folder as the default entrypoint. When org loading fails and the scope is a folder, a fallback path creates a synthetic OrganizationNode and queries the Asset API directly from the folder scope.

Adds config subcommands (set-entrypoint, show, clear-entrypoint) and a global --entrypoint/-e flag.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com


Detailed Changes: v0.4.1...v0.5.0