Skip to content

Shell Integration Patterns

Purpose: Show how to run shell commands safely inside Fractalic and merge results without uncontrolled growth.

Why it matters:

  • Automate: Capture build steps, scans, generators inline.
  • Reproduce: Everything is in markdown history (diffable).
  • Compress: Summarize noisy outputs early to control tokens.
  • Chain: Feed command output directly into later @llm steps.

Internal Table of Contents


Basics (@shell)

Run a command and capture its stdout + stderr (interleaved) as a new block.

markdown
@shell
prompt: "echo 'Hello'"

Multi-line script (use |):

markdown
@shell
prompt: |
  set -e
  echo "Building"
  python -m pytest -q

Result is inserted after the operation (default append).

Minimal & Multi-Line Forms

FormWhen
Single line (no pipe)Short one-liner, no special chars needing YAML escaping.
Multi-line (``)

Selecting Where Output Goes (mode, to)

Control how the output merges:

  • append (default) grows history.
  • prepend positions output before existing content.
  • replace overwrites a target block's body (after stabilization). Target another block:
markdown
@shell
prompt: "ls -1 src"
to: workspace-scan
mode: replace

(Requires a heading with {id=workspace-scan} already defined.)

Summarizing Outputs

Large logs inflate later prompts. Pattern:

markdown
@shell
prompt: |
  set -e
  pytest -q --maxfail=1

Then compress:

markdown
@llm
prompt: |
  Summarize the latest test output into <=12 bullet points (failures first). Keep only actionable info.
block: shell-response/*
to: test-summary
mode: replace

Give the shell result block an ID (edit its heading) if you plan reuse: # Test Run Output {id=shell-response}.

Chaining Shell → LLM

Direct transformation:

markdown
@shell
prompt: "git diff HEAD~1 --name-only"

@llm
prompt: "Group the changed paths by top-level folder and note probable change types."
block: shell-response

Multiple shell outputs combined:

markdown
@shell
prompt: "git rev-parse --abbrev-ref HEAD"

@shell
prompt: "git log -1 --pretty=%B"

@llm
prompt: "Create a concise release note draft."
block:
  - branch-name
  - last-commit-msg

Assign IDs to the generated shell output headings (after first run) so they can be referenced (branch-name, last-commit-msg).

Repeated Tasks & Refresh Patterns

Use replace when refreshing status snapshots:

markdown
@shell
prompt: "du -sh . | sort -h"
to: size-scan
mode: replace

Accumulate progressive evidence first, then prune:

markdown
@shell
prompt: "grep -R 'TODO' -n src"  # exploratory
@shell
prompt: "grep -R 'FIXME' -n src"
@llm
prompt: "Merge all TODO / FIXME lines into a prioritized action list (dedupe)."
block:
  - shell-todo
  - shell-fixme
mode: replace
to: code-remediation-plan

Cost & Noise Control

TechniqueWhy
Add IDs earlyMakes re-selection explicit; prevents wildcard overreach.
Summarize long logsShrinks context for later LLM steps.
Use replace on stable snapshotsPrevents endless growth.
External file storage (future pattern)Keep raw logs out of hot context (then import distilled form).
Limit breadth of scansNarrow glob patterns to required subtrees.

Common Pitfalls

PitfallImpactFix
Forgetting `` for multi-line scriptYAML parse issues / truncated command
Overusing append for recurring scansToken bloatSwitch to replace after first stable format.
No IDs on shell outputsHard to target laterEdit heading to add {id=...}.
Summarizing too lateHigh cost paid alreadySummarize immediately if large.
Blindly capturing huge directoriesIrrelevant noiseScope commands narrowly.

Quick Reference

NeedPattern
One-linerprompt: "echo 'Hi'"
Multi-lineprompt:
Snapshot refreshmode: replace + to: <id>
Transform shell → summary@llm with block: shell-output-id
Combine multiple runsblock: [ id-a, id-b ]
Prune noiseSummarize + replace

Cross References

Released under the MIT License.