Skip to content

v0.16.12#67

Merged
runkids merged 20 commits intomainfrom
v0.16.12
Mar 5, 2026
Merged

v0.16.12#67
runkids merged 20 commits intomainfrom
v0.16.12

Conversation

@runkids
Copy link
Owner

@runkids runkids commented Mar 5, 2026

v0.16.12 adds structured JSON output to 8 more commands, bringing total --json coverage to all 12 major CLI commands. Every command now has a machine-readable output mode for agent consumption and CI/CD pipelines:

  1. 8 new --json commands — sync, install, update, uninstall, collect, target list, status, diff
  2. Non-interactive by design--json on mutating commands implies --force (skips prompts)
  3. Clean stdout — TUI, spinners, and progress suppressed; structured data to stdout only

No breaking changes. Drop-in upgrade from v0.16.11.

runkids added 6 commits March 5, 2026 17:08
Add structured JSON output support for agent and CI/CD consumption:

Phase 1 (mutating): sync, install, update, uninstall, collect
Phase 2 (read-only): target list, status, diff

Key design decisions:
- Per-command JSON schema (no universal envelope)
- Shared helper: writeJSON() with recursive nil slice→[] conversion
- --json implies --force for mutating commands (skip prompts)
- TUI/spinners suppressed; progress goes to stderr, JSON to stdout
- 10 integration tests covering valid JSON, dry-run, nil slices

Also includes post-review cleanup:
- ensureEmptySlices now recurses into nested structs/slices
- Unified mode resolution via getTargetMode() (removed 4 duplicates)
- sync --json now creates backups (behavioral parity with non-JSON)
- targetList no longer double-parses --json flag
- Replace hasFlag loop with slices.Contains (stdlib)
- Deduplicate checkRepoDirty → delegate to isRepoDirty
- Add nil-receiver guard to diffProgress.stop() for consistency
- Return explicit error for status --json in project mode
- Use consistent error message in sync --json source-not-found path
- Expand description from 160 to 708 chars with broader trigger keywords
  (targets, backup/restore, trash, hub, symlink/copy, include/exclude filters)
- Add Skill Hubs recipe section (hub add/list/remove/default/index)
- Add Scripting & CI/CD recipe section (12 --json commands)
- Add --json column to Quick Lookup table
- Fix backup row: correctly show ✗ for project mode (global-only)
- Split tui/ui rows: tui/upgrade are ✗, ui supports -p
- Add hub to command list
- Update AI Caller Rules: hardcoded secret detection, --no-tui commands,
  12 --json commands
- Add --json flag docs to reference files (install, update, uninstall,
  status, diff, sync, collect)

Eval results: 100% pass rate across 5 test cases (up from 80% in iteration 1).
Key fix: Quick Lookup backup ✗ resolved false project-mode claims.
Runbooks can now leverage structured JSON output for verification
instead of brittle text matching. Adds --json quick reference table
(12 commands), jq assertion patterns, and updated checklist/templates.
Structured JSON output for 8 commands (sync, install, update,
uninstall, collect, target list, status, diff), bringing total
--json coverage to all 12 major CLI commands.
@runkids runkids self-assigned this Mar 5, 2026
@runkids runkids added the enhancement New feature or request label Mar 5, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the command-line interface by integrating structured JSON output across a wider range of commands. The primary goal is to facilitate automation and integration with other tools, such as jq, by providing a consistent and machine-readable data format. This change streamlines scripting workflows and improves the reliability of assertions in automated tests, moving away from brittle text parsing. The implementation ensures that commands behave non-interactively when JSON output is requested, making them suitable for CI/CD environments.

Highlights

  • Expanded JSON Output: Structured JSON output has been added to 8 additional CLI commands: sync, install, update, uninstall, collect, target list, status, and diff. This brings the total number of commands supporting --json to 12, ensuring machine-readable output for agent consumption and CI/CD pipelines.
  • Non-Interactive --json Behavior: For mutating commands, the --json flag now implicitly includes --force, automatically skipping interactive prompts. This design ensures non-interactive operation suitable for automation.
  • Clean Standard Output: When --json is used, the Terminal User Interface (TUI), spinners, and progress indicators are suppressed. All structured data is directed exclusively to standard output, maintaining a clean and predictable interface for programmatic use.
  • Documentation Updates: The CHANGELOG.md, SKILL.md, and various command reference documents (install.md, status.md, sync.md, collect.md, diff.md, target.md, uninstall.md, update.md) have been updated to reflect the new --json capabilities and usage examples.
  • New JSON Output Utility: A new Go file (cmd/skillshare/json_output.go) was added to provide common utility functions for handling and writing JSON output, including ensuring nil slices are marshaled as empty arrays.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • CHANGELOG.md
    • Added new changelog entry for version 0.16.12 detailing the new structured JSON output feature.
  • website/src/pages/changelog.md
    • Added new changelog entry for version 0.16.12 detailing the new structured JSON output feature.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a --json flag to 8 CLI commands, providing structured, machine-readable output for automation and CI/CD pipelines. The implementation is extensive, touching many command files and adding new JSON helper functions and integration tests. My review focuses on improving code maintainability by reducing duplication in several command files where logic for JSON and non-JSON output is separated. I've also identified a high-severity issue where some commands still write non-JSON text to stdout in JSON mode, which is being masked by a workaround in the new tests. Additionally, I've suggested moving a shared utility function to a more appropriate location and improving error handling in the new JSON output helper. Overall, this is a great feature addition, and addressing these points will make the implementation more robust and maintainable.

Note: Security Review did not run due to the size of the PR.

runkids added 13 commits March 5, 2026 23:16
Address code review feedback from PR #67:

- Move all dry-run diagnostic messages (internal/sync) from stdout to
  stderr so they don't pollute JSON output
- Suppress UI output (spinners, headers, warnings) in uninstall --json
  mode by adding jsonOutput guards across all phases
- Return nil after writeJSONError to prevent dual output (JSON + plain
  text error) in install and sync commands
- Handle json.MarshalIndent error in writeJSONError with stderr fallback
- Merge duplicated discovery logic (JSON vs non-JSON branches) in sync,
  sync_project, diff, and collect using nullable spinner pattern
- Remove checkRepoDirty alias in status.go, call isRepoDirty directly
- Remove extractJSON test workaround — tests now assert stdout is valid
  JSON directly, enforcing the clean-stdout contract
writeJSONError now returns a jsonSilentError sentinel that main()
recognises — it exits with code 1 without printing plain-text output
to stdout. This fixes a regression where --json errors (config load
failure, missing source dir, discovery failure) returned exit 0.

All writeJSONError call sites changed from the broken pattern:
  writeJSONError(err); return nil   // exit 0, wrong
to:
  return writeJSONError(err)        // exit 1, correct

Also applied the same fix to update.go error paths which had the
older pattern of writeJSONError(err) followed by return err (which
would print both JSON and plain text).

Added regression tests for sync and install error paths verifying
both non-zero exit code and valid JSON error output on stdout.
Type assertion would break if the error gets wrapped via fmt.Errorf
with %w. errors.As handles wrapped errors correctly.
The --json addition accidentally removed the guard that rejects
unexpected positional arguments in project mode. Restore it so
`skillshare status --project foo` correctly returns an error
instead of silently ignoring the extra argument.
install --json: logo, spinners, and step output leaked to stdout,
corrupting machine-parseable JSON. Add suppressUIToStderr() around the
entire install flow, restoring stdout before writing JSON.

diff --project --json: spinner and progress display polluted stdout.
Skip spinner and progress creation in JSON mode, matching the existing
cmdDiffGlobal pattern.

uninstall --json: five error paths (discovery failure, no skills found,
glob detection, validation, preflight) returned plain-text errors instead
of JSON error envelopes. Wrap each with writeJSONError().

Add 8 integration tests (5 new failure cases + 3 confirming existing
behavior) with an assertPureJSON helper that validates stdout contains
only valid JSON with no leading/trailing noise.
… --json

suppressUIToStderr was redirecting UI to stderr, but in environments
where stdout and stderr share the same terminal (e.g. docker exec),
all the spinner/progress/header output was still visible alongside
the JSON. Replace with suppressUIToDevnull which opens os.DevNull
for both os.Stdout and ui.ProgressWriter, producing zero visible
noise in --json mode.

Also add status --json support for project mode, reusing the same
JSON schema as global mode (source, skill_count, tracked_repos,
targets, audit, version).
When no explicit analyzer filter was configured, status --json reported
an empty analyzers array. Now ResolvePolicy backfills the full list of
built-in analyzer IDs so the JSON output reflects what actually runs.

Add Registry.IDs() helper with deduplication (markdownLinkAnalyzer and
staticAnalyzer share the "static" ID).
updateTrackedRepo and updateRegularSkill now return (updateResult, error)
instead of just error, so callers (including project mode and JSON output)
can accurately report updated/skipped/securityFailed/pruned counts.

Adapt cmdUpdateProject, cmdUpdateProjectBatch, updateAllProjectSkills,
and list_project.go TUI action to the new signatures.
collect --json and sync --json returned the raw error after writing
JSON, causing main() to print a duplicate plain-text error. Wrap with
jsonSilentError so main() exits non-zero silently.

Also fix sync --json skipping backup output that would corrupt stdout.
- diff.go: align JSON struct field tags
- CHANGELOG: fix jq example (.errors → .details)
- analyzer_metadata: align map literal and test struct formatting
…semantics

- Extract writeJSONResult() to replace 5 identical write+silent-error trailers
- Replace local isRepoDirty() with existing git.IsDirty() (8 call sites)
- Use defer for suppressUIToDevnull restore instead of manual calls at each
  return site in install.go and update.go (prevents stdout leak on new paths)
- Fix ResolvePolicy always filling EnabledAnalyzers, which broke the
  nil-means-all contract for ForPolicy; add EffectiveAnalyzers() for display
- Simplify collectOutputJSON double map allocation
- Remove unnecessary string conversion in writeJSONError
Extract buildTrackedRepoJSON() that runs git.IsDirty concurrently via
goroutines + WaitGroup instead of sequential subprocess spawns per repo.
Also deduplicates the tracked-repo JSON loop between global and project
status paths, and optimizes skill counting to a single pass with a map.
JSON mode stdout was already pure JSON, but stderr still emitted
progress lines (e.g. "Discovering skills...", "Found N local skill(s)")
which broke `2>&1 | jq .` pipelines. Remove the else-branch stderr
writes so --json mode is fully silent except for stdout JSON output.
Keep sync dry-run diagnostics on stdout by default to avoid non-JSON behavior regressions. Introduce sync.DiagOutput so JSON mode can silence diagnostics via io.Discard at command entry and restore after execution. Update search JSON integration assertion to match fully silent progress behavior.
@runkids runkids merged commit 7223ac5 into main Mar 5, 2026
8 checks passed
runkids added a commit that referenced this pull request Mar 5, 2026
Address code review feedback from PR #67:

- Move all dry-run diagnostic messages (internal/sync) from stdout to
  stderr so they don't pollute JSON output
- Suppress UI output (spinners, headers, warnings) in uninstall --json
  mode by adding jsonOutput guards across all phases
- Return nil after writeJSONError to prevent dual output (JSON + plain
  text error) in install and sync commands
- Handle json.MarshalIndent error in writeJSONError with stderr fallback
- Merge duplicated discovery logic (JSON vs non-JSON branches) in sync,
  sync_project, diff, and collect using nullable spinner pattern
- Remove checkRepoDirty alias in status.go, call isRepoDirty directly
- Remove extractJSON test workaround — tests now assert stdout is valid
  JSON directly, enforcing the clean-stdout contract
@runkids runkids deleted the v0.16.12 branch March 5, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant