mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-09 22:38:10 -05:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a68e63bc49 | ||
|
|
cab51f06df | ||
|
|
20080fcb78 | ||
|
|
a46f189def | ||
|
|
3f8ca72010 | ||
|
|
f58f20bcd0 | ||
|
|
70f8c013f3 | ||
|
|
8f6e2a3d4a | ||
|
|
fad176a0a8 | ||
|
|
dd213eb965 | ||
|
|
d205dbcdac | ||
|
|
f8ff9129b5 | ||
|
|
f9d01b5ebb | ||
|
|
2c7f4753a2 | ||
|
|
9b261b9adf | ||
|
|
a23b6d518f |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -52,6 +52,6 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Update Release Description
|
||||
run: go run ./cmd/generate_changelog --release ${{ github.ref_name }}
|
||||
run: go run ./cmd/generate_changelog --release ${{ github.event.client_payload.tag || github.ref_name }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -11,6 +11,8 @@ on:
|
||||
- "cmd/generate_changelog/incoming/*.txt"
|
||||
- "scripts/pattern_descriptions/*.json"
|
||||
- "web/static/data/pattern_descriptions.json"
|
||||
- "**/*.md"
|
||||
- .vscode/**
|
||||
|
||||
permissions:
|
||||
contents: write # Ensure the workflow has write permissions
|
||||
|
||||
23
.vscode/settings.json
vendored
23
.vscode/settings.json
vendored
@@ -7,6 +7,7 @@
|
||||
"Anki",
|
||||
"anthropics",
|
||||
"Aoede",
|
||||
"aplicar",
|
||||
"atotto",
|
||||
"Autonoe",
|
||||
"badfile",
|
||||
@@ -39,6 +40,7 @@
|
||||
"Eisler",
|
||||
"elif",
|
||||
"Elister",
|
||||
"entrada",
|
||||
"envrc",
|
||||
"Erinome",
|
||||
"Errorf",
|
||||
@@ -89,6 +91,7 @@
|
||||
"Langdock",
|
||||
"Laomedeia",
|
||||
"ldflags",
|
||||
"legibilidad",
|
||||
"libexec",
|
||||
"libnotify",
|
||||
"listcontexts",
|
||||
@@ -109,6 +112,7 @@
|
||||
"modeline",
|
||||
"modelines",
|
||||
"mpga",
|
||||
"nicksnyder",
|
||||
"nometa",
|
||||
"numpy",
|
||||
"ollama",
|
||||
@@ -125,9 +129,11 @@
|
||||
"pipx",
|
||||
"PKCE",
|
||||
"pkgs",
|
||||
"porque",
|
||||
"presencepenalty",
|
||||
"printcontext",
|
||||
"printsession",
|
||||
"puede",
|
||||
"Pulcherrima",
|
||||
"pycache",
|
||||
"pyperclip",
|
||||
@@ -162,6 +168,8 @@
|
||||
"unconfigured",
|
||||
"unmarshalling",
|
||||
"updatepatterns",
|
||||
"useb",
|
||||
"USERPROFILE",
|
||||
"videoid",
|
||||
"webp",
|
||||
"WEBVTT",
|
||||
@@ -176,7 +184,16 @@
|
||||
"youtu",
|
||||
"YTDLP"
|
||||
],
|
||||
"cSpell.ignorePaths": ["go.mod", ".gitignore", "CHANGELOG.md"],
|
||||
"cSpell.ignorePaths": [
|
||||
"go.mod",
|
||||
".gitignore",
|
||||
"CHANGELOG.md",
|
||||
"scripts/installer/install.*",
|
||||
"web/static/data/pattern_descriptions.json",
|
||||
"scripts/pattern_descriptions/*.json",
|
||||
"data/patterns/pattern_explanations.md",
|
||||
"internal/i18n/locales/es.json"
|
||||
],
|
||||
"markdownlint.config": {
|
||||
"MD004": false,
|
||||
"MD011": false,
|
||||
@@ -190,10 +207,12 @@
|
||||
"code",
|
||||
"div",
|
||||
"em",
|
||||
"h",
|
||||
"h4",
|
||||
"img",
|
||||
"module",
|
||||
"p"
|
||||
"p",
|
||||
"sup"
|
||||
]
|
||||
},
|
||||
"MD041": false
|
||||
|
||||
65
CHANGELOG.md
65
CHANGELOG.md
@@ -1,5 +1,70 @@
|
||||
# Changelog
|
||||
|
||||
## v1.4.308 (2025-09-05)
|
||||
|
||||
### PR [#1755](https://github.com/danielmiessler/Fabric/pull/1755) by [ksylvan](https://github.com/ksylvan): Add i18n Support for Multi-Language Fabric Experience
|
||||
|
||||
- Add Spanish localization support with i18n
|
||||
- Create contexts and sessions tutorial documentation
|
||||
- Fix broken Warp sponsorship image URL
|
||||
- Remove solve_with_cot pattern from codebase
|
||||
- Update pattern descriptions and explanations
|
||||
### Direct commits
|
||||
|
||||
- Update Warp sponsor section with proper formatting
|
||||
|
||||
- Replace with correct div structure and styling
|
||||
- Use proper Warp image URL from brand assets
|
||||
|
||||
- Add 'Special thanks to:' text and platform availability
|
||||
- Maintains proper spacing and alignment
|
||||
- Fix unclosed div tag in README causing display issues
|
||||
|
||||
- Close the main div container properly after fabric screenshot
|
||||
- Fix HTML structure that was causing repetitive content display
|
||||
|
||||
- Ensure proper markdown rendering on GitHub
|
||||
🤖 Generated with [Claude Code](<https://claude.ai/code)>
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
- Update Warp sponsor section with new banner and branding
|
||||
|
||||
- Replace old banner with new warp-banner-light.png image
|
||||
- Update styling to use modern p tags with proper centering
|
||||
|
||||
- Maintain existing go.warp.dev/fabric redirect URL
|
||||
- Add descriptive alt text and emphasis text for accessibility
|
||||
🤖 Generated with [Claude Code](<https://claude.ai/code)>
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
|
||||
## v1.4.307 (2025-09-01)
|
||||
|
||||
### PR [#1745](https://github.com/danielmiessler/Fabric/pull/1745) by [ksylvan](https://github.com/ksylvan): Fabric Installation Improvements and Automated Release Updates
|
||||
|
||||
- Streamlined install process with one-line installer scripts and updated documentation
|
||||
- Added bash installer script for Unix systems
|
||||
- Added PowerShell installer script for Windows
|
||||
- Created installer documentation with usage examples
|
||||
- Simplified README installation with one-line installers
|
||||
|
||||
## v1.4.306 (2025-09-01)
|
||||
|
||||
### PR [#1742](https://github.com/danielmiessler/Fabric/pull/1742) by [ksylvan](https://github.com/ksylvan): Documentation and Pattern Updates
|
||||
|
||||
- Add winget installation method for Windows users
|
||||
- Include Docker Hub and GHCR image references with docker run examples
|
||||
- Remove deprecated PowerShell download link and unused show_fabric_options_markmap pattern
|
||||
- Update suggest_pattern with new AI patterns
|
||||
- Add personal development patterns for storytelling
|
||||
|
||||
## v1.4.305 (2025-08-31)
|
||||
|
||||
### PR [#1741](https://github.com/danielmiessler/Fabric/pull/1741) by [ksylvan](https://github.com/ksylvan): CI: Fix Release Description Update
|
||||
|
||||
- Fix: update release workflow to support manual dispatch with custom tag
|
||||
- Support custom tag from client payload in workflow
|
||||
- Fallback to github.ref_name when no custom tag provided
|
||||
- Enable manual release triggers with specified tag parameter
|
||||
|
||||
## v1.4.304 (2025-08-31)
|
||||
|
||||
### PR [#1740](https://github.com/danielmiessler/Fabric/pull/1740) by [ksylvan](https://github.com/ksylvan): Restore our custom Changelog Updates in GitHub Actions
|
||||
|
||||
101
README.md
101
README.md
@@ -1,7 +1,18 @@
|
||||
<div align="center">
|
||||
Fabric is graciously supported by…
|
||||
<a href="https://go.warp.dev/fabric" target="_blank">
|
||||
<sup>Special thanks to:</sup>
|
||||
<br>
|
||||
<img alt="Warp sponsorship" width="400" src="https://raw.githubusercontent.com/warpdotdev/brand-assets/refs/heads/main/Github/Sponsor/Warp-Github-LG-02.png">
|
||||
<br>
|
||||
<h>Warp, built for coding with multiple AI agents</b>
|
||||
<br>
|
||||
<sup>Available for macOS, Linux and Windows</sup>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
[](https://warp.dev/fabric)
|
||||
<br>
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img src="./docs/images/fabric-logo-gif.gif" alt="fabriclogo" width="400" height="400"/>
|
||||
|
||||
@@ -18,6 +29,10 @@ Fabric is graciously supported by…
|
||||
<h4><code>fabric</code> is an open-source framework for augmenting humans using AI.</h4>
|
||||
</div>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Updates](#updates) •
|
||||
[What and Why](#what-and-why) •
|
||||
[Philosophy](#philosophy) •
|
||||
@@ -118,16 +133,14 @@ Keep in mind that many of these were recorded when Fabric was Python-based, so r
|
||||
- [Breaking problems into components](#breaking-problems-into-components)
|
||||
- [Too many prompts](#too-many-prompts)
|
||||
- [Installation](#installation)
|
||||
- [Get Latest Release Binaries](#get-latest-release-binaries)
|
||||
- [Windows](#windows)
|
||||
- [macOS (arm64)](#macos-arm64)
|
||||
- [macOS (amd64)](#macos-amd64)
|
||||
- [Linux (amd64)](#linux-amd64)
|
||||
- [Linux (arm64)](#linux-arm64)
|
||||
- [One-Line Install (Recommended)](#one-line-install-recommended)
|
||||
- [Manual Binary Downloads](#manual-binary-downloads)
|
||||
- [Using package managers](#using-package-managers)
|
||||
- [macOS (Homebrew)](#macos-homebrew)
|
||||
- [Arch Linux (AUR)](#arch-linux-aur)
|
||||
- [Windows](#windows)
|
||||
- [From Source](#from-source)
|
||||
- [Docker](#docker)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [Setup](#setup)
|
||||
- [Per-Pattern Model Mapping](#per-pattern-model-mapping)
|
||||
@@ -204,40 +217,25 @@ Fabric has Patterns for all sorts of life and work activities, including:
|
||||
|
||||
## Installation
|
||||
|
||||
To install Fabric, you can use the latest release binaries or install it from the source.
|
||||
### One-Line Install (Recommended)
|
||||
|
||||
### Get Latest Release Binaries
|
||||
**Unix/Linux/macOS:**
|
||||
|
||||
#### Windows
|
||||
|
||||
`https://github.com/danielmiessler/fabric/releases/latest/download/fabric-windows-amd64.exe`
|
||||
|
||||
Or via PowerShell, just copy and paste and run the following snippet to install the binary into `{HOME}\.local\bin`. Please make sure that directory is included in your `PATH`.
|
||||
|
||||
```powershell
|
||||
$ErrorActionPreference = "Stop"
|
||||
$LATEST="https://github.com/danielmiessler/fabric/releases/latest/download/fabric-windows-amd64.exe"
|
||||
$DIR="${HOME}\.local\bin"
|
||||
New-Item -Path $DIR -ItemType Directory -Force
|
||||
Invoke-WebRequest -URI "${LATEST}" -outfile "${DIR}\fabric.exe"
|
||||
& "${DIR}\fabric.exe" /version
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | bash
|
||||
```
|
||||
|
||||
#### macOS (arm64)
|
||||
**Windows PowerShell:**
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-arm64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
```powershell
|
||||
iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
|
||||
```
|
||||
|
||||
#### macOS (amd64)
|
||||
> See [scripts/installer/README.md](./scripts/installer/README.md) for custom installation options and troubleshooting.
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-amd64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
### Manual Binary Downloads
|
||||
|
||||
#### Linux (amd64)
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-amd64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
|
||||
#### Linux (arm64)
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-arm64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
The latest release binary archives and their expected SHA256 hashes can be found at <https://github.com/danielmiessler/fabric/releases/latest>
|
||||
|
||||
### Using package managers
|
||||
|
||||
@@ -256,6 +254,12 @@ alias fabric='fabric-ai'
|
||||
|
||||
`yay -S fabric-ai`
|
||||
|
||||
#### Windows
|
||||
|
||||
Use the official Microsoft supported `Winget` tool:
|
||||
|
||||
`winget install danielmiessler.Fabric`
|
||||
|
||||
### From Source
|
||||
|
||||
To install Fabric, [make sure Go is installed](https://go.dev/doc/install), and then run the following command.
|
||||
@@ -265,6 +269,35 @@ To install Fabric, [make sure Go is installed](https://go.dev/doc/install), and
|
||||
go install github.com/danielmiessler/fabric/cmd/fabric@latest
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
Run Fabric using pre-built Docker images:
|
||||
|
||||
```bash
|
||||
# Use latest image from Docker Hub
|
||||
docker run --rm -it kayvan/fabric:latest --version
|
||||
|
||||
# Use specific version from GHCR
|
||||
docker run --rm -it ghcr.io/ksylvan/fabric:v1.4.305 --version
|
||||
|
||||
# Run setup (first time)
|
||||
mkdir -p $HOME/.fabric-config
|
||||
docker run --rm -it -v $HOME/.fabric-config:/root/.config/fabric kayvan/fabric:latest --setup
|
||||
|
||||
# Use Fabric with your patterns
|
||||
docker run --rm -it -v $HOME/.fabric-config:/root/.config/fabric kayvan/fabric:latest -p summarize
|
||||
|
||||
# Run the REST API server
|
||||
docker run --rm -it -p 8080:8080 -v $HOME/.fabric-config:/root/.config/fabric kayvan/fabric:latest --serve
|
||||
```
|
||||
|
||||
**Images available at:**
|
||||
|
||||
- Docker Hub: [kayvan/fabric](https://hub.docker.com/repository/docker/kayvan/fabric/general)
|
||||
- GHCR: [ksylvan/fabric](https://github.com/ksylvan/fabric/pkgs/container/fabric)
|
||||
|
||||
See [scripts/docker/README.md](./scripts/docker/README.md) for building custom images and advanced configuration.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
You may need to set some environment variables in your `~/.bashrc` on linux or `~/.zshrc` file on mac to be able to run the `fabric` command. Here is an example of what you can add:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v1.4.304"
|
||||
var version = "v1.4.308"
|
||||
|
||||
Binary file not shown.
@@ -178,48 +178,46 @@
|
||||
174. **refine_design_document**: Refines a design document based on a design review by analyzing, mapping concepts, and implementing changes using valid Markdown.
|
||||
175. **review_design**: Reviews and analyzes architecture design, focusing on clarity, component design, system integrations, security, performance, scalability, and data management.
|
||||
176. **sanitize_broken_html_to_markdown**: Converts messy HTML into clean, properly formatted Markdown, applying custom styling and ensuring compatibility with Vite.
|
||||
177. **show_fabric_options_markmap**: Visualizes the functionality of the Fabric framework by representing its components, commands, and features based on the provided input.
|
||||
178. **solve_with_cot**: Provides detailed, step-by-step responses with chain of thought reasoning, using structured thinking, reflection, and output sections.
|
||||
179. **suggest_pattern**: Suggests appropriate fabric patterns or commands based on user input, providing clear explanations and options for users.
|
||||
180. **summarize**: Summarizes content into a 20-word sentence, main points, and takeaways, formatted with numbered lists in Markdown.
|
||||
181. **summarize_board_meeting**: Creates formal meeting notes from board meeting transcripts for corporate governance documentation.
|
||||
182. **summarize_debate**: Summarizes debates, identifies primary disagreement, extracts arguments, and provides analysis of evidence and argument strength to predict outcomes.
|
||||
183. **summarize_git_changes**: Summarizes recent project updates from the last 7 days, focusing on key changes with enthusiasm.
|
||||
184. **summarize_git_diff**: Summarizes and organizes Git diff changes with clear, succinct commit messages and bullet points.
|
||||
185. **summarize_lecture**: Extracts relevant topics, definitions, and tools from lecture transcripts, providing structured summaries with timestamps and key takeaways.
|
||||
186. **summarize_legislation**: Summarizes complex political proposals and legislation by analyzing key points, proposed changes, and providing balanced, positive, and cynical characterizations.
|
||||
187. **summarize_meeting**: Analyzes meeting transcripts to extract a structured summary, including an overview, key points, tasks, decisions, challenges, timeline, references, and next steps.
|
||||
188. **summarize_micro**: Summarizes content into a 20-word sentence, 3 main points, and 3 takeaways, formatted in clear, concise Markdown.
|
||||
189. **summarize_newsletter**: Extracts the most meaningful, interesting, and useful content from a newsletter, summarizing key sections such as content, opinions, tools, companies, and follow-up items in clear, structured Markdown.
|
||||
190. **summarize_paper**: Summarizes an academic paper by detailing its title, authors, technical approach, distinctive features, experimental setup, results, advantages, limitations, and conclusion in a clear, structured format using human-readable Markdown.
|
||||
191. **summarize_prompt**: Summarizes AI chat prompts by describing the primary function, unique approach, and expected output in a concise paragraph. The summary is focused on the prompt's purpose without unnecessary details or formatting.
|
||||
192. **summarize_pull-requests**: Summarizes pull requests for a coding project by providing a summary and listing the top PRs with human-readable descriptions.
|
||||
193. **summarize_rpg_session**: Summarizes a role-playing game session by extracting key events, combat stats, character changes, quotes, and more.
|
||||
194. **t_analyze_challenge_handling**: Provides 8-16 word bullet points evaluating how well challenges are being addressed, calling out any lack of effort.
|
||||
195. **t_check_metrics**: Analyzes deep context from the TELOS file and input instruction, then provides a wisdom-based output while considering metrics and KPIs to assess recent improvements.
|
||||
196. **t_create_h3_career**: Summarizes context and produces wisdom-based output by deeply analyzing both the TELOS File and the input instruction, considering the relationship between the two.
|
||||
197. **t_create_opening_sentences**: Describes from TELOS file the person's identity, goals, and actions in 4 concise, 32-word bullet points, humbly.
|
||||
198. **t_describe_life_outlook**: Describes from TELOS file a person's life outlook in 5 concise, 16-word bullet points.
|
||||
199. **t_extract_intro_sentences**: Summarizes from TELOS file a person's identity, work, and current projects in 5 concise and grounded bullet points.
|
||||
200. **t_extract_panel_topics**: Creates 5 panel ideas with titles and descriptions based on deep context from a TELOS file and input.
|
||||
201. **t_find_blindspots**: Identify potential blindspots in thinking, frames, or models that may expose the individual to error or risk.
|
||||
202. **t_find_negative_thinking**: Analyze a TELOS file and input to identify negative thinking in documents or journals, followed by tough love encouragement.
|
||||
203. **t_find_neglected_goals**: Analyze a TELOS file and input instructions to identify goals or projects that have not been worked on recently.
|
||||
204. **t_give_encouragement**: Analyze a TELOS file and input instructions to evaluate progress, provide encouragement, and offer recommendations for continued effort.
|
||||
205. **t_red_team_thinking**: Analyze a TELOS file and input instructions to red-team thinking, models, and frames, then provide recommendations for improvement.
|
||||
206. **t_threat_model_plans**: Analyze a TELOS file and input instructions to create threat models for a life plan and recommend improvements.
|
||||
207. **t_visualize_mission_goals_projects**: Analyze a TELOS file and input instructions to create an ASCII art diagram illustrating the relationship of missions, goals, and projects.
|
||||
208. **t_year_in_review**: Analyze a TELOS file to create insights about a person or entity, then summarize accomplishments and visualizations in bullet points.
|
||||
209. **to_flashcards**: Create Anki flashcards from a given text, focusing on concise, optimized questions and answers without external context.
|
||||
210. **transcribe_minutes**: Extracts (from meeting transcription) meeting minutes, identifying actionables, insightful ideas, decisions, challenges, and next steps in a structured format.
|
||||
211. **translate**: Translates sentences or documentation into the specified language code while maintaining the original formatting and tone.
|
||||
212. **tweet**: Provides a step-by-step guide on crafting engaging tweets with emojis, covering Twitter basics, account creation, features, and audience targeting.
|
||||
213. **write_essay**: Writes essays in the style of a specified author, embodying their unique voice, vocabulary, and approach. Uses `author_name` variable.
|
||||
214. **write_essay_pg**: Writes concise, clear essays in the style of Paul Graham, focusing on simplicity, clarity, and illumination of the provided topic.
|
||||
215. **write_hackerone_report**: Generates concise, clear, and reproducible bug bounty reports, detailing vulnerability impact, steps to reproduce, and exploit details for triagers.
|
||||
216. **write_latex**: Generates syntactically correct LaTeX code for a new.tex document, ensuring proper formatting and compatibility with pdflatex.
|
||||
217. **write_micro_essay**: Writes concise, clear, and illuminating essays on the given topic in the style of Paul Graham.
|
||||
218. **write_nuclei_template_rule**: Generates Nuclei YAML templates for detecting vulnerabilities using HTTP requests, matchers, extractors, and dynamic data extraction.
|
||||
219. **write_pull-request**: Drafts detailed pull request descriptions, explaining changes, providing reasoning, and identifying potential bugs from the git diff command output.
|
||||
220. **write_semgrep_rule**: Creates accurate and working Semgrep rules based on input, following syntax guidelines and specific language considerations.
|
||||
221. **youtube_summary**: Create concise, timestamped Youtube video summaries that highlight key points.
|
||||
177. **suggest_pattern**: Suggests appropriate fabric patterns or commands based on user input, providing clear explanations and options for users.
|
||||
178. **summarize**: Summarizes content into a 20-word sentence, main points, and takeaways, formatted with numbered lists in Markdown.
|
||||
179. **summarize_board_meeting**: Creates formal meeting notes from board meeting transcripts for corporate governance documentation.
|
||||
180. **summarize_debate**: Summarizes debates, identifies primary disagreement, extracts arguments, and provides analysis of evidence and argument strength to predict outcomes.
|
||||
181. **summarize_git_changes**: Summarizes recent project updates from the last 7 days, focusing on key changes with enthusiasm.
|
||||
182. **summarize_git_diff**: Summarizes and organizes Git diff changes with clear, succinct commit messages and bullet points.
|
||||
183. **summarize_lecture**: Extracts relevant topics, definitions, and tools from lecture transcripts, providing structured summaries with timestamps and key takeaways.
|
||||
184. **summarize_legislation**: Summarizes complex political proposals and legislation by analyzing key points, proposed changes, and providing balanced, positive, and cynical characterizations.
|
||||
185. **summarize_meeting**: Analyzes meeting transcripts to extract a structured summary, including an overview, key points, tasks, decisions, challenges, timeline, references, and next steps.
|
||||
186. **summarize_micro**: Summarizes content into a 20-word sentence, 3 main points, and 3 takeaways, formatted in clear, concise Markdown.
|
||||
187. **summarize_newsletter**: Extracts the most meaningful, interesting, and useful content from a newsletter, summarizing key sections such as content, opinions, tools, companies, and follow-up items in clear, structured Markdown.
|
||||
188. **summarize_paper**: Summarizes an academic paper by detailing its title, authors, technical approach, distinctive features, experimental setup, results, advantages, limitations, and conclusion in a clear, structured format using human-readable Markdown.
|
||||
189. **summarize_prompt**: Summarizes AI chat prompts by describing the primary function, unique approach, and expected output in a concise paragraph. The summary is focused on the prompt's purpose without unnecessary details or formatting.
|
||||
190. **summarize_pull-requests**: Summarizes pull requests for a coding project by providing a summary and listing the top PRs with human-readable descriptions.
|
||||
191. **summarize_rpg_session**: Summarizes a role-playing game session by extracting key events, combat stats, character changes, quotes, and more.
|
||||
192. **t_analyze_challenge_handling**: Provides 8-16 word bullet points evaluating how well challenges are being addressed, calling out any lack of effort.
|
||||
193. **t_check_metrics**: Analyzes deep context from the TELOS file and input instruction, then provides a wisdom-based output while considering metrics and KPIs to assess recent improvements.
|
||||
194. **t_create_h3_career**: Summarizes context and produces wisdom-based output by deeply analyzing both the TELOS File and the input instruction, considering the relationship between the two.
|
||||
195. **t_create_opening_sentences**: Describes from TELOS file the person's identity, goals, and actions in 4 concise, 32-word bullet points, humbly.
|
||||
196. **t_describe_life_outlook**: Describes from TELOS file a person's life outlook in 5 concise, 16-word bullet points.
|
||||
197. **t_extract_intro_sentences**: Summarizes from TELOS file a person's identity, work, and current projects in 5 concise and grounded bullet points.
|
||||
198. **t_extract_panel_topics**: Creates 5 panel ideas with titles and descriptions based on deep context from a TELOS file and input.
|
||||
199. **t_find_blindspots**: Identify potential blindspots in thinking, frames, or models that may expose the individual to error or risk.
|
||||
200. **t_find_negative_thinking**: Analyze a TELOS file and input to identify negative thinking in documents or journals, followed by tough love encouragement.
|
||||
201. **t_find_neglected_goals**: Analyze a TELOS file and input instructions to identify goals or projects that have not been worked on recently.
|
||||
202. **t_give_encouragement**: Analyze a TELOS file and input instructions to evaluate progress, provide encouragement, and offer recommendations for continued effort.
|
||||
203. **t_red_team_thinking**: Analyze a TELOS file and input instructions to red-team thinking, models, and frames, then provide recommendations for improvement.
|
||||
204. **t_threat_model_plans**: Analyze a TELOS file and input instructions to create threat models for a life plan and recommend improvements.
|
||||
205. **t_visualize_mission_goals_projects**: Analyze a TELOS file and input instructions to create an ASCII art diagram illustrating the relationship of missions, goals, and projects.
|
||||
206. **t_year_in_review**: Analyze a TELOS file to create insights about a person or entity, then summarize accomplishments and visualizations in bullet points.
|
||||
207. **to_flashcards**: Create Anki flashcards from a given text, focusing on concise, optimized questions and answers without external context.
|
||||
208. **transcribe_minutes**: Extracts (from meeting transcription) meeting minutes, identifying actionables, insightful ideas, decisions, challenges, and next steps in a structured format.
|
||||
209. **translate**: Translates sentences or documentation into the specified language code while maintaining the original formatting and tone.
|
||||
210. **tweet**: Provides a step-by-step guide on crafting engaging tweets with emojis, covering Twitter basics, account creation, features, and audience targeting.
|
||||
211. **write_essay**: Writes essays in the style of a specified author, embodying their unique voice, vocabulary, and approach. Uses `author_name` variable.
|
||||
212. **write_essay_pg**: Writes concise, clear essays in the style of Paul Graham, focusing on simplicity, clarity, and illumination of the provided topic.
|
||||
213. **write_hackerone_report**: Generates concise, clear, and reproducible bug bounty reports, detailing vulnerability impact, steps to reproduce, and exploit details for triagers.
|
||||
214. **write_latex**: Generates syntactically correct LaTeX code for a new.tex document, ensuring proper formatting and compatibility with pdflatex.
|
||||
215. **write_micro_essay**: Writes concise, clear, and illuminating essays on the given topic in the style of Paul Graham.
|
||||
216. **write_nuclei_template_rule**: Generates Nuclei YAML templates for detecting vulnerabilities using HTTP requests, matchers, extractors, and dynamic data extraction.
|
||||
217. **write_pull-request**: Drafts detailed pull request descriptions, explaining changes, providing reasoning, and identifying potential bugs from the git diff command output.
|
||||
218. **write_semgrep_rule**: Creates accurate and working Semgrep rules based on input, following syntax guidelines and specific language considerations.
|
||||
219. **youtube_summary**: Create concise, timestamped Youtube video summaries that highlight key points.
|
||||
|
||||
@@ -1,481 +0,0 @@
|
||||
# IDENTITY AND GOALS
|
||||
|
||||
You are an advanced UI builder that shows a visual representation of functionality that's provided to you via the input.
|
||||
|
||||
# STEPS
|
||||
|
||||
- Think about the goal of the Fabric project, which is discussed below:
|
||||
|
||||
FABRIC PROJECT DESCRIPTION
|
||||
|
||||
fabriclogo
|
||||
fabric
|
||||
Static Badge
|
||||
GitHub top language GitHub last commit License: MIT
|
||||
|
||||
fabric is an open-source framework for augmenting humans using AI.
|
||||
|
||||
Introduction Video • What and Why • Philosophy • Quickstart • Structure • Examples • Custom Patterns • Helper Apps • Examples • Meta
|
||||
|
||||
Navigation
|
||||
|
||||
Introduction Videos
|
||||
What and Why
|
||||
Philosophy
|
||||
Breaking problems into components
|
||||
Too many prompts
|
||||
The Fabric approach to prompting
|
||||
Quickstart
|
||||
Setting up the fabric commands
|
||||
Using the fabric client
|
||||
Just use the Patterns
|
||||
Create your own Fabric Mill
|
||||
Structure
|
||||
Components
|
||||
CLI-native
|
||||
Directly calling Patterns
|
||||
Examples
|
||||
Custom Patterns
|
||||
Helper Apps
|
||||
Meta
|
||||
Primary contributors
|
||||
|
||||
Note
|
||||
|
||||
We are adding functionality to the project so often that you should update often as well. That means: git pull; pipx install . --force; fabric --update; source ~/.zshrc (or ~/.bashrc) in the main directory!
|
||||
March 13, 2024 — We just added pipx install support, which makes it way easier to install Fabric, support for Claude, local models via Ollama, and a number of new Patterns. Be sure to update and check fabric -h for the latest!
|
||||
|
||||
Introduction videos
|
||||
|
||||
Note
|
||||
|
||||
These videos use the ./setup.sh install method, which is now replaced with the easier pipx install . method. Other than that everything else is still the same.
|
||||
fabric_intro_video
|
||||
|
||||
Watch the video
|
||||
What and why
|
||||
|
||||
Since the start of 2023 and GenAI we've seen a massive number of AI applications for accomplishing tasks. It's powerful, but it's not easy to integrate this functionality into our lives.
|
||||
|
||||
In other words, AI doesn't have a capabilities problem—it has an integration problem.
|
||||
|
||||
Fabric was created to address this by enabling everyone to granularly apply AI to everyday challenges.
|
||||
|
||||
Philosophy
|
||||
|
||||
AI isn't a thing; it's a magnifier of a thing. And that thing is human creativity.
|
||||
We believe the purpose of technology is to help humans flourish, so when we talk about AI we start with the human problems we want to solve.
|
||||
|
||||
Breaking problems into components
|
||||
|
||||
Our approach is to break problems into individual pieces (see below) and then apply AI to them one at a time. See below for some examples.
|
||||
|
||||
augmented_challenges
|
||||
Too many prompts
|
||||
|
||||
Prompts are good for this, but the biggest challenge I faced in 2023——which still exists today—is the sheer number of AI prompts out there. We all have prompts that are useful, but it's hard to discover new ones, know if they are good or not, and manage different versions of the ones we like.
|
||||
|
||||
One of fabric's primary features is helping people collect and integrate prompts, which we call Patterns, into various parts of their lives.
|
||||
|
||||
Fabric has Patterns for all sorts of life and work activities, including:
|
||||
|
||||
Extracting the most interesting parts of YouTube videos and podcasts
|
||||
Writing an essay in your own voice with just an idea as an input
|
||||
Summarizing opaque academic papers
|
||||
Creating perfectly matched AI art prompts for a piece of writing
|
||||
Rating the quality of content to see if you want to read/watch the whole thing
|
||||
Getting summaries of long, boring content
|
||||
Explaining code to you
|
||||
Turning bad documentation into usable documentation
|
||||
Creating social media posts from any content input
|
||||
And a million more…
|
||||
Our approach to prompting
|
||||
|
||||
Fabric Patterns are different than most prompts you'll see.
|
||||
|
||||
First, we use Markdown to help ensure maximum readability and editability. This not only helps the creator make a good one, but also anyone who wants to deeply understand what it does. Importantly, this also includes the AI you're sending it to!
|
||||
Here's an example of a Fabric Pattern.
|
||||
|
||||
https://github.com/danielmiessler/fabric/blob/main/patterns/extract_wisdom/system.md
|
||||
pattern-example
|
||||
Next, we are extremely clear in our instructions, and we use the Markdown structure to emphasize what we want the AI to do, and in what order.
|
||||
|
||||
And finally, we tend to use the System section of the prompt almost exclusively. In over a year of being heads-down with this stuff, we've just seen more efficacy from doing that. If that changes, or we're shown data that says otherwise, we will adjust.
|
||||
|
||||
Quickstart
|
||||
|
||||
The most feature-rich way to use Fabric is to use the fabric client, which can be found under /client directory in this repository.
|
||||
|
||||
Setting up the fabric commands
|
||||
|
||||
Follow these steps to get all fabric related apps installed and configured.
|
||||
|
||||
Navigate to where you want the Fabric project to live on your system in a semi-permanent place on your computer.
|
||||
# Find a home for Fabric
|
||||
cd /where/you/keep/code
|
||||
Clone the project to your computer.
|
||||
# Clone Fabric to your computer
|
||||
git clone https://github.com/danielmiessler/fabric.git
|
||||
Enter Fabric's main directory
|
||||
# Enter the project folder (where you cloned it)
|
||||
cd fabric
|
||||
Install pipx:
|
||||
macOS:
|
||||
|
||||
brew install pipx
|
||||
Linux:
|
||||
|
||||
sudo apt install pipx
|
||||
Windows:
|
||||
|
||||
Use WSL and follow the Linux instructions.
|
||||
|
||||
Install fabric
|
||||
pipx install .
|
||||
Run setup:
|
||||
fabric --setup
|
||||
Restart your shell to reload everything.
|
||||
|
||||
Now you are up and running! You can test by running the help.
|
||||
|
||||
# Making sure the paths are set up correctly
|
||||
fabric --help
|
||||
Note
|
||||
|
||||
If you're using the server functions, fabric-api and fabric-webui need to be run in distinct terminal windows.
|
||||
Using the fabric client
|
||||
|
||||
Once you have it all set up, here's how to use it.
|
||||
|
||||
Check out the options fabric -h
|
||||
us the results in
|
||||
realtime. NOTE: You will not be able to pipe the
|
||||
output into another command.
|
||||
--list, -l List available patterns
|
||||
--clear Clears your persistent model choice so that you can
|
||||
once again use the --model flag
|
||||
--update, -u Update patterns. NOTE: This will revert the default
|
||||
model to gpt4-turbo. please run --changeDefaultModel
|
||||
to once again set default model
|
||||
--pattern PATTERN, -p PATTERN
|
||||
The pattern (prompt) to use
|
||||
--setup Set up your fabric instance
|
||||
--changeDefaultModel CHANGEDEFAULTMODEL
|
||||
Change the default model. For a list of available
|
||||
models, use the --listmodels flag.
|
||||
--model MODEL, -m MODEL
|
||||
Select the model to use. NOTE: Will not work if you
|
||||
have set a default model. please use --clear to clear
|
||||
persistence before using this flag
|
||||
--vendor VENDOR, -V VENDOR
|
||||
Specify vendor for the selected model (e.g., -V "LM Studio" -m openai/gpt-oss-20b)
|
||||
--listmodels List all available models
|
||||
--remoteOllamaServer REMOTEOLLAMASERVER
|
||||
The URL of the remote ollamaserver to use. ONLY USE
|
||||
THIS if you are using a local ollama server in an non-
|
||||
default location or port
|
||||
--context, -c Use Context file (context.md) to add context to your
|
||||
pattern
|
||||
age: fabric [-h] [--text TEXT] [--copy] [--agents {trip_planner,ApiKeys}]
|
||||
[--output [OUTPUT]] [--stream] [--list] [--clear] [--update]
|
||||
[--pattern PATTERN] [--setup]
|
||||
[--changeDefaultModel CHANGEDEFAULTMODEL] [--model MODEL]
|
||||
[--listmodels] [--remoteOllamaServer REMOTEOLLAMASERVER]
|
||||
[--context]
|
||||
|
||||
An open source framework for augmenting humans using AI.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--text TEXT, -t TEXT Text to extract summary from
|
||||
--copy, -C Copy the response to the clipboard
|
||||
--agents {trip_planner,ApiKeys}, -a {trip_planner,ApiKeys}
|
||||
Use an AI agent to help you with a task. Acceptable
|
||||
values are 'trip_planner' or 'ApiKeys'. This option
|
||||
cannot be used with any other flag.
|
||||
--output [OUTPUT], -o [OUTPUT]
|
||||
Save the response to a file
|
||||
--stream, -s Use this option if you want to see
|
||||
Example commands
|
||||
|
||||
The client, by default, runs Fabric patterns without needing a server (the Patterns were downloaded during setup). This means the client connects directly to OpenAI using the input given and the Fabric pattern used.
|
||||
|
||||
Run the summarize Pattern based on input from stdin. In this case, the body of an article.
|
||||
pbpaste | fabric --pattern summarize
|
||||
Run the analyze_claims Pattern with the --stream option to get immediate and streaming results.
|
||||
pbpaste | fabric --stream --pattern analyze_claims
|
||||
Run the extract_wisdom Pattern with the --stream option to get immediate and streaming results from any YouTube video (much like in the original introduction video).
|
||||
yt --transcript https://youtube.com/watch?v=uXs-zPc63kM | fabric --stream --pattern extract_wisdom
|
||||
new All of the patterns have been added as aliases to your bash (or zsh) config file
|
||||
pbpaste | analyze_claims --stream
|
||||
Note
|
||||
|
||||
More examples coming in the next few days, including a demo video!
|
||||
Just use the Patterns
|
||||
|
||||
fabric-patterns-screenshot
|
||||
If you're not looking to do anything fancy, and you just want a lot of great prompts, you can navigate to the /patterns directory and start exploring!
|
||||
|
||||
We hope that if you used nothing else from Fabric, the Patterns by themselves will make the project useful.
|
||||
|
||||
You can use any of the Patterns you see there in any AI application that you have, whether that's ChatGPT or some other app or website. Our plan and prediction is that people will soon be sharing many more than those we've published, and they will be way better than ours.
|
||||
|
||||
The wisdom of crowds for the win.
|
||||
|
||||
Create your own Fabric Mill
|
||||
|
||||
fabric_mill_architecture
|
||||
But we go beyond just providing Patterns. We provide code for you to build your very own Fabric server and personal AI infrastructure!
|
||||
|
||||
Structure
|
||||
|
||||
Fabric is themed off of, well… fabric—as in…woven materials. So, think blankets, quilts, patterns, etc. Here's the concept and structure:
|
||||
|
||||
Components
|
||||
|
||||
The Fabric ecosystem has three primary components, all named within this textile theme.
|
||||
|
||||
The Mill is the (optional) server that makes Patterns available.
|
||||
Patterns are the actual granular AI use cases (prompts).
|
||||
Stitches are chained together Patterns that create advanced functionality (see below).
|
||||
Looms are the client-side apps that call a specific Pattern hosted by a Mill.
|
||||
CLI-native
|
||||
|
||||
One of the coolest parts of the project is that it's command-line native!
|
||||
|
||||
Each Pattern you see in the /patterns directory can be used in any AI application you use, but you can also set up your own server using the /server code and then call APIs directly!
|
||||
|
||||
Once you're set up, you can do things like:
|
||||
|
||||
# Take any idea from `stdin` and send it to the `/write_essay` API!
|
||||
echo "An idea that coding is like speaking with rules." | write_essay
|
||||
Directly calling Patterns
|
||||
|
||||
One key feature of fabric and its Markdown-based format is the ability to _ directly reference_ (and edit) individual patterns directly—on their own—without surrounding code.
|
||||
|
||||
As an example, here's how to call the direct location of the extract_wisdom pattern.
|
||||
|
||||
https://github.com/danielmiessler/fabric/blob/main/patterns/extract_wisdom/system.md
|
||||
This means you can cleanly, and directly reference any pattern for use in a web-based AI app, your own code, or wherever!
|
||||
|
||||
Even better, you can also have your Mill functionality directly call system and user prompts from fabric, meaning you can have your personal AI ecosystem automatically kept up to date with the latest version of your favorite Patterns.
|
||||
|
||||
Here's what that looks like in code:
|
||||
|
||||
https://github.com/danielmiessler/fabric/blob/main/server/fabric_api_server.py
|
||||
# /extwis
|
||||
@app.route("/extwis", methods=["POST"])
|
||||
@auth_required # Require authentication
|
||||
def extwis():
|
||||
data = request.get_json()
|
||||
|
||||
# Warn if there's no input
|
||||
if "input" not in data:
|
||||
return jsonify({"error": "Missing input parameter"}), 400
|
||||
|
||||
# Get data from client
|
||||
input_data = data["input"]
|
||||
|
||||
# Set the system and user URLs
|
||||
system_url = "https://raw.githubusercontent.com/danielmiessler/fabric/main/patterns/extract_wisdom/system.md"
|
||||
user_url = "https://raw.githubusercontent.com/danielmiessler/fabric/main/patterns/extract_wisdom/user.md"
|
||||
|
||||
# Fetch the prompt content
|
||||
system_content = fetch_content_from_url(system_url)
|
||||
user_file_content = fetch_content_from_url(user_url)
|
||||
|
||||
# Build the API call
|
||||
system_message = {"role": "system", "content": system_content}
|
||||
user_message = {"role": "user", "content": user_file_content + "\n" + input_data}
|
||||
messages = [system_message, user_message]
|
||||
try:
|
||||
response = openai.chat.completions.create(
|
||||
model="gpt-4-1106-preview",
|
||||
messages=messages,
|
||||
temperature=0.0,
|
||||
top_p=1,
|
||||
frequency_penalty=0.1,
|
||||
presence_penalty=0.1,
|
||||
)
|
||||
assistant_message = response.choices[0].message.content
|
||||
return jsonify({"response": assistant_message})
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
Examples
|
||||
|
||||
Here's an abridged output example from the extract_wisdom pattern (limited to only 10 items per section).
|
||||
|
||||
# Paste in the transcript of a YouTube video of Riva Tez on David Perrel's podcast
|
||||
pbpaste | extract_wisdom
|
||||
## SUMMARY:
|
||||
|
||||
The content features a conversation between two individuals discussing various topics, including the decline of Western culture, the importance of beauty and subtlety in life, the impact of technology and AI, the resonance of Rilke's poetry, the value of deep reading and revisiting texts, the captivating nature of Ayn Rand's writing, the role of philosophy in understanding the world, and the influence of drugs on society. They also touch upon creativity, attention spans, and the importance of introspection.
|
||||
|
||||
## IDEAS:
|
||||
|
||||
1. Western culture is perceived to be declining due to a loss of values and an embrace of mediocrity.
|
||||
2. Mass media and technology have contributed to shorter attention spans and a need for constant stimulation.
|
||||
3. Rilke's poetry resonates due to its focus on beauty and ecstasy in everyday objects.
|
||||
4. Subtlety is often overlooked in modern society due to sensory overload.
|
||||
5. The role of technology in shaping music and performance art is significant.
|
||||
6. Reading habits have shifted from deep, repetitive reading to consuming large quantities of new material.
|
||||
7. Revisiting influential books as one ages can lead to new insights based on accumulated wisdom and experiences.
|
||||
8. Fiction can vividly illustrate philosophical concepts through characters and narratives.
|
||||
9. Many influential thinkers have backgrounds in philosophy, highlighting its importance in shaping reasoning skills.
|
||||
10. Philosophy is seen as a bridge between theology and science, asking questions that both fields seek to answer.
|
||||
|
||||
## QUOTES:
|
||||
|
||||
1. "You can't necessarily think yourself into the answers. You have to create space for the answers to come to you."
|
||||
2. "The West is dying and we are killing her."
|
||||
3. "The American Dream has been replaced by mass packaged mediocrity porn, encouraging us to revel like happy pigs in our own meekness."
|
||||
4. "There's just not that many people who have the courage to reach beyond consensus and go explore new ideas."
|
||||
5. "I'll start watching Netflix when I've read the whole of human history."
|
||||
6. "Rilke saw beauty in everything... He sees it's in one little thing, a representation of all things that are beautiful."
|
||||
7. "Vanilla is a very subtle flavor... it speaks to sort of the sensory overload of the modern age."
|
||||
8. "When you memorize chapters [of the Bible], it takes a few months, but you really understand how things are structured."
|
||||
9. "As you get older, if there's books that moved you when you were younger, it's worth going back and rereading them."
|
||||
10. "She [Ayn Rand] took complicated philosophy and embodied it in a way that anybody could resonate with."
|
||||
|
||||
## HABITS:
|
||||
|
||||
1. Avoiding mainstream media consumption for deeper engagement with historical texts and personal research.
|
||||
2. Regularly revisiting influential books from youth to gain new insights with age.
|
||||
3. Engaging in deep reading practices rather than skimming or speed-reading material.
|
||||
4. Memorizing entire chapters or passages from significant texts for better understanding.
|
||||
5. Disengaging from social media and fast-paced news cycles for more focused thought processes.
|
||||
6. Walking long distances as a form of meditation and reflection.
|
||||
7. Creating space for thoughts to solidify through introspection and stillness.
|
||||
8. Embracing emotions such as grief or anger fully rather than suppressing them.
|
||||
9. Seeking out varied experiences across different careers and lifestyles.
|
||||
10. Prioritizing curiosity-driven research without specific goals or constraints.
|
||||
|
||||
## FACTS:
|
||||
|
||||
1. The West is perceived as declining due to cultural shifts away from traditional values.
|
||||
2. Attention spans have shortened due to technological advancements and media consumption habits.
|
||||
3. Rilke's poetry emphasizes finding beauty in everyday objects through detailed observation.
|
||||
4. Modern society often overlooks subtlety due to sensory overload from various stimuli.
|
||||
5. Reading habits have evolved from deep engagement with texts to consuming large quantities quickly.
|
||||
6. Revisiting influential books can lead to new insights based on accumulated life experiences.
|
||||
7. Fiction can effectively illustrate philosophical concepts through character development and narrative arcs.
|
||||
8. Philosophy plays a significant role in shaping reasoning skills and understanding complex ideas.
|
||||
9. Creativity may be stifled by cultural nihilism and protectionist attitudes within society.
|
||||
10. Short-term thinking undermines efforts to create lasting works of beauty or significance.
|
||||
|
||||
## REFERENCES:
|
||||
|
||||
1. Rainer Maria Rilke's poetry
|
||||
2. Netflix
|
||||
3. Underworld concert
|
||||
4. Katy Perry's theatrical performances
|
||||
5. Taylor Swift's performances
|
||||
6. Bible study
|
||||
7. Atlas Shrugged by Ayn Rand
|
||||
8. Robert Pirsig's writings
|
||||
9. Bertrand Russell's definition of philosophy
|
||||
10. Nietzsche's walks
|
||||
Custom Patterns
|
||||
|
||||
You can also use Custom Patterns with Fabric, meaning Patterns you keep locally and don't upload to Fabric.
|
||||
|
||||
One possible place to store them is ~/.config/custom-fabric-patterns.
|
||||
|
||||
Then when you want to use them, simply copy them into ~/.config/fabric/patterns.
|
||||
|
||||
cp -a ~/.config/custom-fabric-patterns/* ~/.config/fabric/patterns/`
|
||||
Now you can run them with:
|
||||
|
||||
pbpaste | fabric -p your_custom_pattern
|
||||
Helper Apps
|
||||
|
||||
These are helper tools to work with Fabric. Examples include things like getting transcripts from media files, getting metadata about media, etc.
|
||||
|
||||
yt (YouTube)
|
||||
|
||||
yt is a command that uses the YouTube API to pull transcripts, pull user comments, get video duration, and other functions. It's primary function is to get a transcript from a video that can then be stitched (piped) into other Fabric Patterns.
|
||||
|
||||
usage: yt [-h] [--duration] [--transcript] [url]
|
||||
|
||||
vm (video meta) extracts metadata about a video, such as the transcript and the video's duration. By Daniel Miessler.
|
||||
|
||||
positional arguments:
|
||||
url YouTube video URL
|
||||
|
||||
options:
|
||||
-h, --help Show this help message and exit
|
||||
--duration Output only the duration
|
||||
--transcript Output only the transcript
|
||||
--comments Output only the user comments
|
||||
ts (Audio transcriptions)
|
||||
|
||||
'ts' is a command that uses the OpenApi Whisper API to transcribe audio files. Due to the context window, this tool uses pydub to split the files into 10 minute segments. for more information on pydub, please refer https://github.com/jiaaro/pydub
|
||||
|
||||
Installation
|
||||
|
||||
mac:
|
||||
brew install ffmpeg
|
||||
|
||||
linux:
|
||||
apt install ffmpeg
|
||||
|
||||
windows:
|
||||
download instructions https://www.ffmpeg.org/download.html
|
||||
ts -h
|
||||
usage: ts [-h] audio_file
|
||||
|
||||
Transcribe an audio file.
|
||||
|
||||
positional arguments:
|
||||
audio_file The path to the audio file to be transcribed.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
Save
|
||||
|
||||
save is a "tee-like" utility to pipeline saving of content, while keeping the output stream intact. Can optionally generate "frontmatter" for PKM utilities like Obsidian via the "FABRIC_FRONTMATTER" environment variable
|
||||
|
||||
If you'd like to default variables, set them in ~/.config/fabric/.env. FABRIC_OUTPUT_PATH needs to be set so save where to write. FABRIC_FRONTMATTER_TAGS is optional, but useful for tracking how tags have entered your PKM, if that's important to you.
|
||||
|
||||
usage
|
||||
|
||||
usage: save [-h] [-t, TAG] [-n] [-s] [stub]
|
||||
|
||||
save: a "tee-like" utility to pipeline saving of content, while keeping the output stream intact. Can optionally generate "frontmatter" for PKM utilities like Obsidian via the
|
||||
"FABRIC_FRONTMATTER" environment variable
|
||||
|
||||
positional arguments:
|
||||
stub stub to describe your content. Use quotes if you have spaces. Resulting format is YYYY-MM-DD-stub.md by default
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-t, TAG, --tag TAG add an additional frontmatter tag. Use this argument multiple timesfor multiple tags
|
||||
-n, --nofabric don't use the fabric tags, only use tags from --tag
|
||||
-s, --silent don't use STDOUT for output, only save to the file
|
||||
Example
|
||||
|
||||
echo test | save --tag extra-tag stub-for-name
|
||||
test
|
||||
|
||||
$ cat ~/obsidian/Fabric/2024-03-02-stub-for-name.md
|
||||
---
|
||||
generation_date: 2024-03-02 10:43
|
||||
tags: fabric-extraction stub-for-name extra-tag
|
||||
---
|
||||
test
|
||||
|
||||
END FABRIC PROJECT DESCRIPTION
|
||||
|
||||
- Take the Fabric patterns given to you as input and think about how to create a Markmap visualization of everything you can do with Fabric.
|
||||
|
||||
Examples: Analyzing videos, summarizing articles, writing essays, etc.
|
||||
|
||||
- The visual should be broken down by the type of actions that can be taken, such as summarization, analysis, etc., and the actual patterns should branch from there.
|
||||
|
||||
# OUTPUT
|
||||
|
||||
- Output comprehensive Markmap code for displaying this functionality map as described above.
|
||||
|
||||
- NOTE: This is Markmap, NOT Markdown.
|
||||
|
||||
- Output the Markmap code and nothing else.
|
||||
@@ -1,36 +0,0 @@
|
||||
# IDENTITY
|
||||
|
||||
You are an AI assistant designed to provide detailed, step-by-step responses. Your outputs should follow this structure:
|
||||
|
||||
# STEPS
|
||||
|
||||
1. Begin with a <thinking> section.
|
||||
|
||||
2. Inside the thinking section:
|
||||
|
||||
- a. Briefly analyze the question and outline your approach.
|
||||
|
||||
- b. Present a clear plan of steps to solve the problem.
|
||||
|
||||
- c. Use a "Chain of Thought" reasoning process if necessary, breaking down your thought process into numbered steps.
|
||||
|
||||
3. Include a <reflection> section for each idea where you:
|
||||
|
||||
- a. Review your reasoning.
|
||||
|
||||
- b. Check for potential errors or oversights.
|
||||
|
||||
- c. Confirm or adjust your conclusion if necessary.
|
||||
- Be sure to close all reflection sections.
|
||||
- Close the thinking section with </thinking>.
|
||||
- Provide your final answer in an <output> section.
|
||||
|
||||
Always use these tags in your responses. Be thorough in your explanations, showing each step of your reasoning process.
|
||||
Aim to be precise and logical in your approach, and don't hesitate to break down complex problems into simpler components.
|
||||
Your tone should be analytical and slightly formal, focusing on clear communication of your thought process.
|
||||
Remember: Both <thinking> and <reflection> MUST be tags and must be closed at their conclusion.
|
||||
Make sure all <tags> are on separate lines with no other text.
|
||||
|
||||
# INPUT
|
||||
|
||||
INPUT:
|
||||
@@ -71,7 +71,7 @@ Match the request to one or more of these primary categories:
|
||||
|
||||
## Common Request Types and Best Patterns
|
||||
|
||||
**AI**: ai, create_art_prompt, create_pattern, extract_mcp_servers, extract_wisdom_agents, generate_code_rules, improve_prompt, judge_output, rate_ai_response, rate_ai_result, raw_query, solve_with_cot, suggest_pattern, summarize_prompt
|
||||
**AI**: ai, create_ai_jobs_analysis, create_art_prompt, create_pattern, create_prediction_block, extract_mcp_servers, extract_wisdom_agents, generate_code_rules, improve_prompt, judge_output, rate_ai_response, rate_ai_result, raw_query, suggest_pattern, summarize_prompt
|
||||
|
||||
**ANALYSIS**: ai, analyze_answers, analyze_bill, analyze_bill_short, analyze_candidates, analyze_cfp_submission, analyze_claims, analyze_comments, analyze_debate, analyze_email_headers, analyze_incident, analyze_interviewer_techniques, analyze_logs, analyze_malware, analyze_military_strategy, analyze_mistakes, analyze_paper, analyze_paper_simple, analyze_patent, analyze_personality, analyze_presentation, analyze_product_feedback, analyze_proposition, analyze_prose, analyze_prose_json, analyze_prose_pinker, analyze_risk, analyze_sales_call, analyze_spiritual_text, analyze_tech_impact, analyze_terraform_plan, analyze_threat_report, analyze_threat_report_cmds, analyze_threat_report_trends, apply_ul_tags, check_agreement, compare_and_contrast, create_ai_jobs_analysis, create_idea_compass, create_investigation_visualization, create_prediction_block, create_recursive_outline, create_tags, dialog_with_socrates, extract_main_idea, extract_predictions, find_hidden_message, find_logical_fallacies, get_wow_per_minute, identify_dsrp_distinctions, identify_dsrp_perspectives, identify_dsrp_relationships, identify_dsrp_systems, identify_job_stories, label_and_rate, prepare_7s_strategy, provide_guidance, rate_content, rate_value, recommend_artists, recommend_talkpanel_topics, review_design, summarize_board_meeting, t_analyze_challenge_handling, t_check_dunning_kruger, t_check_metrics, t_describe_life_outlook, t_extract_intro_sentences, t_extract_panel_topics, t_find_blindspots, t_find_negative_thinking, t_red_team_thinking, t_threat_model_plans, t_year_in_review, write_hackerone_report
|
||||
|
||||
@@ -83,11 +83,11 @@ Match the request to one or more of these primary categories:
|
||||
|
||||
**CONVERSION**: clean_text, convert_to_markdown, create_graph_from_input, export_data_as_csv, extract_videoid, get_youtube_rss, humanize, md_callout, sanitize_broken_html_to_markdown, to_flashcards, transcribe_minutes, translate, tweet, write_latex
|
||||
|
||||
**CR THINKING**: capture_thinkers_work, create_idea_compass, create_markmap_visualization, dialog_with_socrates, extract_alpha, extract_controversial_ideas, extract_extraordinary_claims, extract_predictions, extract_primary_problem, extract_wisdom_nometa, find_hidden_message, find_logical_fallacies, solve_with_cot, summarize_debate, t_analyze_challenge_handling, t_check_dunning_kruger, t_find_blindspots, t_find_negative_thinking, t_find_neglected_goals, t_red_team_thinking
|
||||
**CR THINKING**: capture_thinkers_work, create_idea_compass, create_markmap_visualization, dialog_with_socrates, extract_alpha, extract_controversial_ideas, extract_extraordinary_claims, extract_predictions, extract_primary_problem, extract_wisdom_nometa, find_hidden_message, find_logical_fallacies, summarize_debate, t_analyze_challenge_handling, t_check_dunning_kruger, t_find_blindspots, t_find_negative_thinking, t_find_neglected_goals, t_red_team_thinking
|
||||
|
||||
**CREATIVITY**: create_mnemonic_phrases, write_essay
|
||||
|
||||
**DEVELOPMENT**: agility_story, analyze_prose_json, answer_interview_question, ask_secure_by_design_questions, ask_uncle_duke, coding_master, create_coding_feature, create_coding_project, create_command, create_design_document, create_git_diff_commit, create_mermaid_visualization, create_mermaid_visualization_for_github, create_pattern, create_sigma_rules, create_user_story, explain_code, explain_docs, export_data_as_csv, extract_algorithm_update_recommendations, extract_mcp_servers, extract_poc, generate_code_rules, get_youtube_rss, improve_prompt, official_pattern_template, recommend_pipeline_upgrades, refine_design_document, review_code, review_design, sanitize_broken_html_to_markdown, show_fabric_options_markmap, suggest_pattern, summarize_git_changes, summarize_git_diff, summarize_pull-requests, write_nuclei_template_rule, write_pull-request, write_semgrep_rule
|
||||
**DEVELOPMENT**: agility_story, analyze_logs, analyze_prose_json, answer_interview_question, ask_secure_by_design_questions, ask_uncle_duke, coding_master, create_coding_feature, create_coding_project, create_command, create_design_document, create_git_diff_commit, create_loe_document, create_mermaid_visualization, create_mermaid_visualization_for_github, create_pattern, create_prd, create_sigma_rules, create_user_story, explain_code, explain_docs, explain_project, export_data_as_csv, extract_algorithm_update_recommendations, extract_mcp_servers, extract_poc, extract_product_features, generate_code_rules, get_youtube_rss, identify_job_stories, improve_prompt, official_pattern_template, recommend_pipeline_upgrades, refine_design_document, review_code, review_design, sanitize_broken_html_to_markdown, suggest_pattern, summarize_git_changes, summarize_git_diff, summarize_pull-requests, write_nuclei_template_rule, write_pull-request, write_semgrep_rule
|
||||
|
||||
**DEVOPS**: analyze_terraform_plan
|
||||
|
||||
@@ -95,7 +95,7 @@ Match the request to one or more of these primary categories:
|
||||
|
||||
**GAMING**: create_npc, create_rpg_summary, summarize_rpg_session
|
||||
|
||||
**LEARNING**: analyze_answers, ask_uncle_duke, coding_master, create_diy, create_flash_cards, create_quiz, create_reading_plan, create_story_explanation, dialog_with_socrates, explain_code, explain_docs, explain_math, explain_project, explain_terms, extract_references, improve_academic_writing, provide_guidance, solve_with_cot, summarize_lecture, summarize_paper, to_flashcards, write_essay_pg
|
||||
**LEARNING**: analyze_answers, ask_uncle_duke, coding_master, create_diy, create_flash_cards, create_quiz, create_reading_plan, create_story_explanation, dialog_with_socrates, explain_code, explain_docs, explain_math, explain_project, explain_terms, extract_references, improve_academic_writing, provide_guidance, summarize_lecture, summarize_paper, to_flashcards, write_essay_pg
|
||||
|
||||
**OTHER**: extract_jokes
|
||||
|
||||
@@ -105,13 +105,13 @@ Match the request to one or more of these primary categories:
|
||||
|
||||
**SECURITY**: analyze_email_headers, analyze_incident, analyze_logs, analyze_malware, analyze_risk, analyze_terraform_plan, analyze_threat_report, analyze_threat_report_cmds, analyze_threat_report_trends, ask_secure_by_design_questions, create_command, create_cyber_summary, create_graph_from_input, create_investigation_visualization, create_network_threat_landscape, create_report_finding, create_security_update, create_sigma_rules, create_stride_threat_model, create_threat_scenarios, create_ttrc_graph, create_ttrc_narrative, extract_ctf_writeup, improve_report_finding, recommend_pipeline_upgrades, review_code, t_red_team_thinking, t_threat_model_plans, write_hackerone_report, write_nuclei_template_rule, write_semgrep_rule
|
||||
|
||||
**SELF**: create_better_frame, create_diy, create_reading_plan, dialog_with_socrates, extract_article_wisdom, extract_book_ideas, extract_book_recommendations, extract_insights, extract_insights_dm, extract_most_redeeming_thing, extract_recipe, extract_recommendations, extract_song_meaning, extract_wisdom, extract_wisdom_dm, extract_wisdom_short, find_female_life_partner, provide_guidance, t_check_dunning_kruger, t_create_h3_career, t_describe_life_outlook, t_find_neglected_goals, t_give_encouragement
|
||||
**SELF**: analyze_mistakes, analyze_personality, analyze_spiritual_text, create_better_frame, create_diy, create_reading_plan, create_story_about_person, dialog_with_socrates, extract_article_wisdom, extract_book_ideas, extract_book_recommendations, extract_insights, extract_insights_dm, extract_most_redeeming_thing, extract_recipe, extract_recommendations, extract_song_meaning, extract_wisdom, extract_wisdom_dm, extract_wisdom_short, find_female_life_partner, heal_person, provide_guidance, recommend_artists, t_check_dunning_kruger, t_create_h3_career, t_describe_life_outlook, t_find_neglected_goals, t_give_encouragement
|
||||
|
||||
**STRATEGY**: analyze_military_strategy, create_better_frame, prepare_7s_strategy, t_analyze_challenge_handling, t_find_blindspots, t_find_negative_thinking, t_find_neglected_goals, t_red_team_thinking, t_threat_model_plans, t_visualize_mission_goals_projects
|
||||
|
||||
**SUMMARIZE**: capture_thinkers_work, create_5_sentence_summary, create_micro_summary, create_newsletter_entry, create_show_intro, create_summary, extract_core_message, extract_latest_video, extract_main_idea, summarize, summarize_board_meeting, summarize_debate, summarize_git_changes, summarize_git_diff, summarize_lecture, summarize_legislation, summarize_meeting, summarize_micro, summarize_newsletter, summarize_paper, summarize_pull-requests, summarize_rpg_session, youtube_summary
|
||||
|
||||
**VISUALIZE**: create_excalidraw_visualization, create_graph_from_input, create_idea_compass, create_investigation_visualization, create_keynote, create_logo, create_markmap_visualization, create_mermaid_visualization, create_mermaid_visualization_for_github, create_video_chapters, create_visualization, enrich_blog_post, show_fabric_options_markmap, t_visualize_mission_goals_projects
|
||||
**VISUALIZE**: create_excalidraw_visualization, create_graph_from_input, create_idea_compass, create_investigation_visualization, create_keynote, create_logo, create_markmap_visualization, create_mermaid_visualization, create_mermaid_visualization_for_github, create_video_chapters, create_visualization, enrich_blog_post, t_visualize_mission_goals_projects
|
||||
|
||||
**WISDOM**: extract_alpha, extract_article_wisdom, extract_book_ideas, extract_insights, extract_most_redeeming_thing, extract_recommendations, extract_wisdom, extract_wisdom_dm, extract_wisdom_nometa, extract_wisdom_short
|
||||
|
||||
|
||||
@@ -78,10 +78,6 @@ Assess AI outputs against criteria, providing scores and feedback.
|
||||
|
||||
Process direct queries by interpreting intent.
|
||||
|
||||
### solve_with_cot
|
||||
|
||||
Solve problems using chain-of-thought reasoning.
|
||||
|
||||
### suggest_pattern
|
||||
|
||||
Recommend Fabric patterns based on user requirements.
|
||||
@@ -904,10 +900,6 @@ Create Mermaid diagrams to visualize workflows in documentation.
|
||||
|
||||
Transform concepts to ASCII art with explanations of relationships.
|
||||
|
||||
### show_fabric_options_markmap
|
||||
|
||||
Visualize Fabric capabilities using Markmap syntax.
|
||||
|
||||
### t_visualize_mission_goals_projects
|
||||
|
||||
Visualize missions and goals to clarify relationships.
|
||||
@@ -942,6 +934,10 @@ Identify neglected goals to surface opportunities.
|
||||
|
||||
## PERSONAL DEVELOPMENT PATTERNS
|
||||
|
||||
### create_story_about_person
|
||||
|
||||
Infer everyday challenges and realistic coping strategies from a psychological profile and craft an empathetic 500–700-word story consistent with the character.
|
||||
|
||||
### extract_recipe
|
||||
|
||||
Extract/format recipes into instructions with ingredients and steps.
|
||||
@@ -950,6 +946,10 @@ Extract/format recipes into instructions with ingredients and steps.
|
||||
|
||||
Clarify and summarize partner criteria in direct language.
|
||||
|
||||
### heal_person
|
||||
|
||||
Analyze a psychological profile, pinpoint issues and strengths, and deliver compassionate, structured strategies for spiritual, mental, and life improvement.
|
||||
|
||||
## CREATIVITY PATTERNS
|
||||
|
||||
### create_mnemonic_phrases
|
||||
|
||||
@@ -8,12 +8,13 @@ Thanks for contributing to Fabric! Here's what you need to know to get started q
|
||||
|
||||
- Go 1.24+ installed
|
||||
- Git configured with your details
|
||||
- GitHub CLI (`gh`)
|
||||
|
||||
### Getting Started
|
||||
|
||||
```bash
|
||||
# Clone and setup
|
||||
git clone https://github.com/danielmiessler/fabric.git
|
||||
# Clone your fork (upstream is set automatically)
|
||||
gh repo clone YOUR_GITHUB_USER/fabric
|
||||
cd fabric
|
||||
go build -o fabric ./cmd/fabric
|
||||
./fabric --setup
|
||||
@@ -52,12 +53,10 @@ docs: update installation instructions
|
||||
|
||||
### Changelog Generation (REQUIRED)
|
||||
|
||||
Before submitting your PR, generate a changelog entry:
|
||||
After opening your PR, generate a changelog entry:
|
||||
|
||||
```bash
|
||||
cd cmd/generate_changelog
|
||||
go build -o generate_changelog .
|
||||
./generate_changelog --incoming-pr YOUR_PR_NUMBER
|
||||
go run ./cmd/generate_changelog --ai-summarize --incoming-pr YOUR_PR_NUMBER
|
||||
```
|
||||
|
||||
**Requirements:**
|
||||
|
||||
107
docs/contexts-and-sessions-tutorial.md
Normal file
107
docs/contexts-and-sessions-tutorial.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Contexts and Sessions in Fabric
|
||||
|
||||
Fabric uses **contexts** and **sessions** to manage conversation state and reusable prompt data. This guide focuses on how to use them from the CLI and REST API.
|
||||
|
||||
## What is a Context?
|
||||
|
||||
A context is named text that Fabric injects at the beginning of a conversation. Contexts live on disk under `~/.config/fabric/contexts`; each file name is the context name, and its contents are included as a system message.
|
||||
|
||||
Command-line helpers:
|
||||
|
||||
- `--context <name>` select a context
|
||||
- `--listcontexts` list available contexts
|
||||
- `--printcontext <name>` show the contents
|
||||
- `--wipecontext <name>` delete it
|
||||
|
||||
## What is a Session?
|
||||
|
||||
A session tracks the message history of a conversation. When you specify a session name, Fabric loads any existing messages, appends new ones, and saves back to disk. Sessions are stored as JSON under `~/.config/fabric/sessions`.
|
||||
|
||||
Command-line helpers:
|
||||
|
||||
- `--session <name>` attach to a session
|
||||
- `--listsessions` list stored sessions
|
||||
- `--printsession <name>` print a session
|
||||
- `--wipesession <name>` delete it
|
||||
|
||||
## Everyday Use Cases
|
||||
|
||||
Contexts and sessions serve different everyday needs:
|
||||
|
||||
- **Context** – Reuse prompt text such as preferred style, domain knowledge, or instructions for the assistant.
|
||||
- **Session** – Maintain ongoing conversation history so Fabric remembers earlier exchanges.
|
||||
|
||||
Example workflow:
|
||||
|
||||
1. Create a context file manually in `~/.config/fabric/contexts/writer` with your writing guidelines.
|
||||
2. Start a session while chatting to build on previous answers (`fabric --session mychat`). Sessions are automatically created if they don't exist.
|
||||
|
||||
## How Contexts and Sessions Interact
|
||||
|
||||
When Fabric handles a chat request, it loads any named context, combines it with pattern text, and adds the result as a system message before sending the conversation history to the model. The assistant's reply is appended to the session so future calls continue from the same state.
|
||||
|
||||
## REST API Endpoints
|
||||
|
||||
The REST server exposes CRUD endpoints for managing contexts and sessions:
|
||||
|
||||
- `/contexts/:name` – get or save a context
|
||||
- `/contexts/names` – list available contexts
|
||||
- `/sessions/:name` – get or save a session
|
||||
- `/sessions/names` – list available sessions
|
||||
|
||||
## Summary
|
||||
|
||||
Contexts provide reusable system-level instructions, while sessions maintain conversation history. Together they allow Fabric to build rich, stateful interactions with language models.
|
||||
|
||||
## For Developers
|
||||
|
||||
### Loading Contexts from Disk
|
||||
|
||||
```go
|
||||
// internal/plugins/db/fsdb/contexts.go
|
||||
func (o *ContextsEntity) Get(name string) (*Context, error) {
|
||||
content, err := o.Load(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Context{Name: name, Content: string(content)}, nil
|
||||
}
|
||||
```
|
||||
|
||||
### Handling Sessions
|
||||
|
||||
```go
|
||||
// internal/plugins/db/fsdb/sessions.go
|
||||
type Session struct {
|
||||
Name string
|
||||
Messages []*chat.ChatCompletionMessage
|
||||
}
|
||||
|
||||
func (o *SessionsEntity) Get(name string) (*Session, error) {
|
||||
session := &Session{Name: name}
|
||||
if o.Exists(name) {
|
||||
err = o.LoadAsJson(name, &session.Messages)
|
||||
} else {
|
||||
fmt.Printf("Creating new session: %s\n", name)
|
||||
}
|
||||
return session, err
|
||||
}
|
||||
```
|
||||
|
||||
### Building a Session
|
||||
|
||||
```go
|
||||
// internal/core/chatter.go
|
||||
if request.ContextName != "" {
|
||||
ctx, err := o.db.Contexts.Get(request.ContextName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not find context %s: %v", request.ContextName, err)
|
||||
}
|
||||
contextContent = ctx.Content
|
||||
}
|
||||
|
||||
systemMessage := strings.TrimSpace(contextContent) + strings.TrimSpace(patternContent)
|
||||
if systemMessage != "" {
|
||||
session.Append(&chat.ChatCompletionMessage{Role: chat.ChatMessageRoleSystem, Content: systemMessage})
|
||||
}
|
||||
```
|
||||
182
docs/i18n.md
Normal file
182
docs/i18n.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# Internationalization (i18n) in Fabric
|
||||
|
||||
Fabric supports multiple languages through its internationalization system. The system automatically detects your preferred language from environment variables and provides localized messages.
|
||||
|
||||
## How Locale Detection Works
|
||||
|
||||
Fabric follows POSIX standards for locale detection with the following priority order:
|
||||
|
||||
1. **Explicit language flag**: `--language` or `-g` (highest priority)
|
||||
2. **LC_ALL**: Complete locale override environment variable
|
||||
3. **LC_MESSAGES**: Messages-specific locale environment variable
|
||||
4. **LANG**: General locale environment variable
|
||||
5. **Default fallback**: English (`en`) if none are set or valid
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Use explicit language flag
|
||||
fabric --language es --pattern summarize
|
||||
|
||||
# Use LC_ALL environment variable
|
||||
LC_ALL=fr_FR.UTF-8 fabric --pattern summarize
|
||||
|
||||
# Use LANG environment variable
|
||||
LANG=de_DE.UTF-8 fabric --pattern summarize
|
||||
|
||||
# Multiple environment variables (LC_ALL takes priority)
|
||||
LC_ALL=es_ES.UTF-8 LANG=fr_FR.UTF-8 fabric --pattern summarize
|
||||
# Uses Spanish (es_ES) because LC_ALL has higher priority
|
||||
```
|
||||
|
||||
## Supported Locale Formats
|
||||
|
||||
The system automatically normalizes various locale formats:
|
||||
|
||||
- `en_US.UTF-8` → `en-US`
|
||||
- `fr_FR@euro` → `fr-FR`
|
||||
- `zh_CN.GB2312` → `zh-CN`
|
||||
- `de_DE.UTF-8@traditional` → `de-DE`
|
||||
|
||||
Special cases:
|
||||
|
||||
- `C` or `POSIX` → treated as invalid, falls back to English
|
||||
|
||||
## Translation File Locations
|
||||
|
||||
Translations are loaded from multiple sources in this order:
|
||||
|
||||
1. **Embedded files** (highest priority): Compiled into the binary
|
||||
- Location: `internal/i18n/locales/*.json`
|
||||
- Always available, no download required
|
||||
|
||||
2. **User config directory**: Downloaded on demand
|
||||
- Location: `~/.config/fabric/locales/`
|
||||
- Downloaded from GitHub when needed
|
||||
|
||||
3. **GitHub repository**: Source for downloads
|
||||
- URL: `https://raw.githubusercontent.com/danielmiessler/Fabric/main/internal/i18n/locales/`
|
||||
|
||||
## Currently Supported Languages
|
||||
|
||||
- **English** (`en`): Default language, always available
|
||||
- **Spanish** (`es`): Available in embedded files
|
||||
|
||||
## Adding New Languages
|
||||
|
||||
To add support for a new language:
|
||||
|
||||
1. Create a new JSON file: `internal/i18n/locales/{lang}.json`
|
||||
2. Add translations in the format:
|
||||
|
||||
```json
|
||||
{
|
||||
"message_id": "localized message text"
|
||||
}
|
||||
```
|
||||
|
||||
3. Rebuild Fabric to embed the new translations
|
||||
|
||||
### Translation File Format
|
||||
|
||||
Translation files use JSON format with message IDs as keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"html_readability_error": "use original input, because can't apply html readability"
|
||||
}
|
||||
```
|
||||
|
||||
Spanish example:
|
||||
|
||||
```json
|
||||
{
|
||||
"html_readability_error": "usa la entrada original, porque no se puede aplicar la legibilidad de html"
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The i18n system is designed to be robust:
|
||||
|
||||
- **Download failures**: Non-fatal, falls back to embedded translations
|
||||
- **Invalid locales**: Skipped, next priority locale used
|
||||
- **Missing translations**: Falls back to English
|
||||
- **Missing files**: Uses embedded defaults
|
||||
|
||||
Error messages are logged to stderr but don't prevent operation.
|
||||
|
||||
## Environment Variable Examples
|
||||
|
||||
### Common Unix Locale Settings
|
||||
|
||||
```bash
|
||||
# Set system-wide locale
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
# Override all locale categories
|
||||
export LC_ALL=fr_FR.UTF-8
|
||||
|
||||
# Set only message locale (for this session)
|
||||
LC_MESSAGES=es_ES.UTF-8 fabric --pattern summarize
|
||||
|
||||
# Check current locale settings
|
||||
locale
|
||||
```
|
||||
|
||||
### Testing Locale Detection
|
||||
|
||||
You can test locale detection without changing your system settings:
|
||||
|
||||
```bash
|
||||
# Test with French
|
||||
LC_ALL=fr_FR.UTF-8 fabric --version
|
||||
|
||||
# Test with Spanish (if available)
|
||||
LC_ALL=es_ES.UTF-8 fabric --version
|
||||
|
||||
# Test with German (will download if available)
|
||||
LC_ALL=de_DE.UTF-8 fabric --version
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "i18n download failed" messages
|
||||
|
||||
This is normal when requesting a language not yet available. The system will fall back to English.
|
||||
|
||||
### Locale not detected
|
||||
|
||||
Check your environment variables:
|
||||
|
||||
```bash
|
||||
echo $LC_ALL
|
||||
echo $LC_MESSAGES
|
||||
echo $LANG
|
||||
```
|
||||
|
||||
Ensure they're in a valid format like `en_US.UTF-8` or `fr_FR`.
|
||||
|
||||
### Wrong language used
|
||||
|
||||
Remember the priority order:
|
||||
|
||||
1. `--language` flag overrides everything
|
||||
2. `LC_ALL` overrides `LC_MESSAGES` and `LANG`
|
||||
3. `LC_MESSAGES` overrides `LANG`
|
||||
|
||||
## Implementation Details
|
||||
|
||||
The locale detection system:
|
||||
|
||||
- Uses `golang.org/x/text/language` for parsing and validation
|
||||
- Follows BCP 47 language tag standards
|
||||
- Implements POSIX locale environment variable precedence
|
||||
- Provides comprehensive test coverage
|
||||
- Handles edge cases gracefully
|
||||
|
||||
For developers working on the codebase, see the implementation in:
|
||||
|
||||
- `internal/i18n/locale.go`: Locale detection logic
|
||||
- `internal/i18n/i18n.go`: Main i18n initialization
|
||||
- `internal/i18n/locale_test.go`: Test suite
|
||||
1
go.mod
1
go.mod
@@ -21,6 +21,7 @@ require (
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/mattn/go-sqlite3 v1.14.28
|
||||
github.com/nicksnyder/go-i18n/v2 v2.6.0
|
||||
github.com/ollama/ollama v0.11.7
|
||||
github.com/openai/openai-go v1.8.2
|
||||
github.com/otiai10/copy v1.14.1
|
||||
|
||||
4
go.sum
4
go.sum
@@ -8,6 +8,8 @@ cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeO
|
||||
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
@@ -180,6 +182,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE=
|
||||
github.com/ollama/ollama v0.11.7 h1:CuYjaJ/YEnvLDpJocJbbVdpdVFyGA/OP6lKFyzZD4dI=
|
||||
github.com/ollama/ollama v0.11.7/go.mod h1:9+1//yWPsDE2u+l1a5mpaKrYw4VdnSsRU3ioq5BvMms=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/core"
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
debuglog "github.com/danielmiessler/fabric/internal/log"
|
||||
"github.com/danielmiessler/fabric/internal/plugins/ai/openai"
|
||||
"github.com/danielmiessler/fabric/internal/tools/converter"
|
||||
@@ -19,6 +20,11 @@ func Cli(version string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// initialize internationalization using requested language
|
||||
if _, err = i18n.Init(currentFlags.Language); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.Setup {
|
||||
if err = ensureEnvFile(); err != nil {
|
||||
return
|
||||
@@ -86,7 +92,7 @@ func Cli(version string) (err error) {
|
||||
// Process HTML readability if needed
|
||||
if currentFlags.HtmlReadability {
|
||||
if msg, cleanErr := converter.HtmlReadability(currentFlags.Message); cleanErr != nil {
|
||||
fmt.Println("use original input, because can't apply html readability", cleanErr)
|
||||
fmt.Println(i18n.T("html_readability_error"), cleanErr)
|
||||
} else {
|
||||
currentFlags.Message = msg
|
||||
}
|
||||
|
||||
121
internal/i18n/i18n.go
Normal file
121
internal/i18n/i18n.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// embedded default locales
|
||||
//
|
||||
//go:embed locales/*.json
|
||||
var localeFS embed.FS
|
||||
|
||||
var (
|
||||
translator *i18n.Localizer
|
||||
initOnce sync.Once
|
||||
)
|
||||
|
||||
// Init initializes the i18n bundle and localizer. It loads the specified locale
|
||||
// and falls back to English if loading fails.
|
||||
// Translation files are searched in the user config directory and downloaded
|
||||
// from GitHub if missing.
|
||||
//
|
||||
// If locale is empty, it will attempt to detect the system locale from
|
||||
// environment variables (LC_ALL, LC_MESSAGES, LANG) following POSIX standards.
|
||||
func Init(locale string) (*i18n.Localizer, error) {
|
||||
// Use preferred locale detection if no explicit locale provided
|
||||
locale = getPreferredLocale(locale)
|
||||
if locale == "" {
|
||||
locale = "en"
|
||||
}
|
||||
|
||||
bundle := i18n.NewBundle(language.English)
|
||||
bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
|
||||
|
||||
// load embedded translations for the requested locale if available
|
||||
embedded := false
|
||||
if data, err := localeFS.ReadFile("locales/" + locale + ".json"); err == nil {
|
||||
_, _ = bundle.ParseMessageFileBytes(data, locale+".json")
|
||||
embedded = true
|
||||
} else if strings.Contains(locale, "-") {
|
||||
// Try base language if regional variant not found (e.g., es-ES -> es)
|
||||
baseLang := strings.Split(locale, "-")[0]
|
||||
if data, err := localeFS.ReadFile("locales/" + baseLang + ".json"); err == nil {
|
||||
_, _ = bundle.ParseMessageFileBytes(data, baseLang+".json")
|
||||
embedded = true
|
||||
}
|
||||
}
|
||||
if !embedded {
|
||||
if data, err := localeFS.ReadFile("locales/en.json"); err == nil {
|
||||
_, _ = bundle.ParseMessageFileBytes(data, "en.json")
|
||||
}
|
||||
}
|
||||
|
||||
// load locale from disk or download when not embedded
|
||||
path := filepath.Join(userLocaleDir(), locale+".json")
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) && !embedded {
|
||||
if err := downloadLocale(path, locale); err != nil {
|
||||
// if download fails, still continue with embedded translations
|
||||
fmt.Fprintln(os.Stderr, "i18n download failed:", err)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
if _, err := bundle.LoadMessageFile(path); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "i18n load failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
translator = i18n.NewLocalizer(bundle, locale)
|
||||
return translator, nil
|
||||
}
|
||||
|
||||
// T returns the localized string for the given message id.
|
||||
// If the translator is not initialized, it will automatically initialize
|
||||
// with system locale detection.
|
||||
func T(messageID string) string {
|
||||
initOnce.Do(func() {
|
||||
if translator == nil {
|
||||
Init("") // Empty string triggers system locale detection
|
||||
}
|
||||
})
|
||||
return translator.MustLocalize(&i18n.LocalizeConfig{MessageID: messageID})
|
||||
}
|
||||
|
||||
func userLocaleDir() string {
|
||||
dir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
dir = "."
|
||||
}
|
||||
path := filepath.Join(dir, "fabric", "locales")
|
||||
os.MkdirAll(path, 0o755)
|
||||
return path
|
||||
}
|
||||
|
||||
func downloadLocale(path, locale string) error {
|
||||
url := fmt.Sprintf("https://raw.githubusercontent.com/danielmiessler/Fabric/main/internal/i18n/locales/%s.json", locale)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("unexpected status: %s", resp.Status)
|
||||
}
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = io.Copy(f, resp.Body)
|
||||
return err
|
||||
}
|
||||
22
internal/i18n/i18n_test.go
Normal file
22
internal/i18n/i18n_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
gi18n "github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
)
|
||||
|
||||
func TestTranslation(t *testing.T) {
|
||||
loc, err := Init("es")
|
||||
if err != nil {
|
||||
t.Fatalf("init failed: %v", err)
|
||||
}
|
||||
msg, err := loc.Localize(&gi18n.LocalizeConfig{MessageID: "html_readability_error"})
|
||||
if err != nil {
|
||||
t.Fatalf("localize failed: %v", err)
|
||||
}
|
||||
expected := "usa la entrada original, porque no se puede aplicar la legibilidad de html"
|
||||
if msg != expected {
|
||||
t.Fatalf("unexpected translation: %s", msg)
|
||||
}
|
||||
}
|
||||
82
internal/i18n/locale.go
Normal file
82
internal/i18n/locale.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// detectSystemLocale detects the system locale using standard Unix environment variables.
|
||||
// Follows the POSIX priority order for locale environment variables:
|
||||
// 1. LC_ALL (highest priority - overrides all others)
|
||||
// 2. LC_MESSAGES (for messages specifically)
|
||||
// 3. LANG (general locale setting)
|
||||
// 4. Returns empty string if none are set or valid
|
||||
//
|
||||
// This implementation follows POSIX standards and Unix best practices for locale detection.
|
||||
func detectSystemLocale() string {
|
||||
// Check environment variables in priority order
|
||||
envVars := []string{"LC_ALL", "LC_MESSAGES", "LANG"}
|
||||
|
||||
for _, envVar := range envVars {
|
||||
if value := os.Getenv(envVar); value != "" {
|
||||
locale := normalizeLocale(value)
|
||||
if locale != "" && isValidLocale(locale) {
|
||||
return locale
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// normalizeLocale converts various locale formats to BCP 47 language tags.
|
||||
// Examples:
|
||||
// - "en_US.UTF-8" -> "en-US"
|
||||
// - "fr_FR@euro" -> "fr-FR"
|
||||
// - "zh_CN.GB2312" -> "zh-CN"
|
||||
// - "C" or "POSIX" -> "" (invalid, falls back to default)
|
||||
func normalizeLocale(locale string) string {
|
||||
// Handle special cases
|
||||
if locale == "C" || locale == "POSIX" || locale == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Remove encoding and modifiers
|
||||
// Examples: en_US.UTF-8@euro -> en_US
|
||||
locale = strings.Split(locale, ".")[0] // Remove encoding (.UTF-8)
|
||||
locale = strings.Split(locale, "@")[0] // Remove modifiers (@euro)
|
||||
|
||||
// Convert underscore to hyphen for BCP 47 compliance
|
||||
// en_US -> en-US
|
||||
locale = strings.ReplaceAll(locale, "_", "-")
|
||||
|
||||
return locale
|
||||
}
|
||||
|
||||
// isValidLocale checks if a locale string can be parsed as a valid language tag.
|
||||
func isValidLocale(locale string) bool {
|
||||
if locale == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Use golang.org/x/text/language to validate
|
||||
_, err := language.Parse(locale)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// getPreferredLocale returns the best locale to use based on user preferences.
|
||||
// Priority order:
|
||||
// 1. Explicit language flag (if provided)
|
||||
// 2. System environment variables (LC_ALL, LC_MESSAGES, LANG)
|
||||
// 3. Default fallback (empty string, which triggers "en" in Init)
|
||||
func getPreferredLocale(explicitLang string) string {
|
||||
// If explicitly set via flag, use that
|
||||
if explicitLang != "" {
|
||||
return explicitLang
|
||||
}
|
||||
|
||||
// Otherwise try to detect from system environment
|
||||
return detectSystemLocale()
|
||||
}
|
||||
288
internal/i18n/locale_test.go
Normal file
288
internal/i18n/locale_test.go
Normal file
@@ -0,0 +1,288 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDetectSystemLocale(t *testing.T) {
|
||||
// Save original environment
|
||||
originalLC_ALL := os.Getenv("LC_ALL")
|
||||
originalLC_MESSAGES := os.Getenv("LC_MESSAGES")
|
||||
originalLANG := os.Getenv("LANG")
|
||||
|
||||
// Clean up after test
|
||||
defer func() {
|
||||
os.Setenv("LC_ALL", originalLC_ALL)
|
||||
os.Setenv("LC_MESSAGES", originalLC_MESSAGES)
|
||||
os.Setenv("LANG", originalLANG)
|
||||
}()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
LC_ALL string
|
||||
LC_MESSAGES string
|
||||
LANG string
|
||||
expected string
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "LC_ALL takes highest priority",
|
||||
LC_ALL: "fr_FR.UTF-8",
|
||||
LC_MESSAGES: "de_DE.UTF-8",
|
||||
LANG: "es_ES.UTF-8",
|
||||
expected: "fr-FR",
|
||||
description: "LC_ALL should override all other variables",
|
||||
},
|
||||
{
|
||||
name: "LC_MESSAGES used when LC_ALL empty",
|
||||
LC_ALL: "",
|
||||
LC_MESSAGES: "ja_JP.UTF-8",
|
||||
LANG: "ko_KR.UTF-8",
|
||||
expected: "ja-JP",
|
||||
description: "LC_MESSAGES should be used when LC_ALL is not set",
|
||||
},
|
||||
{
|
||||
name: "LANG used when LC_ALL and LC_MESSAGES empty",
|
||||
LC_ALL: "",
|
||||
LC_MESSAGES: "",
|
||||
LANG: "zh_CN.GB2312",
|
||||
expected: "zh-CN",
|
||||
description: "LANG should be fallback when others are not set",
|
||||
},
|
||||
{
|
||||
name: "Empty when no valid locale set",
|
||||
LC_ALL: "",
|
||||
LC_MESSAGES: "",
|
||||
LANG: "",
|
||||
expected: "",
|
||||
description: "Should return empty when no environment variables set",
|
||||
},
|
||||
{
|
||||
name: "Handle C locale",
|
||||
LC_ALL: "C",
|
||||
LC_MESSAGES: "",
|
||||
LANG: "",
|
||||
expected: "",
|
||||
description: "C locale should be treated as invalid (fallback to default)",
|
||||
},
|
||||
{
|
||||
name: "Handle POSIX locale",
|
||||
LC_ALL: "",
|
||||
LC_MESSAGES: "POSIX",
|
||||
LANG: "",
|
||||
expected: "",
|
||||
description: "POSIX locale should be treated as invalid (fallback to default)",
|
||||
},
|
||||
{
|
||||
name: "Handle locale with modifiers",
|
||||
LC_ALL: "",
|
||||
LC_MESSAGES: "",
|
||||
LANG: "de_DE.UTF-8@euro",
|
||||
expected: "de-DE",
|
||||
description: "Should strip encoding and modifiers",
|
||||
},
|
||||
{
|
||||
name: "Skip invalid locale and use next priority",
|
||||
LC_ALL: "invalid_locale",
|
||||
LC_MESSAGES: "fr_CA.UTF-8",
|
||||
LANG: "en_US.UTF-8",
|
||||
expected: "fr-CA",
|
||||
description: "Should skip invalid high-priority locale and use next valid one",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Set test environment
|
||||
os.Setenv("LC_ALL", tt.LC_ALL)
|
||||
os.Setenv("LC_MESSAGES", tt.LC_MESSAGES)
|
||||
os.Setenv("LANG", tt.LANG)
|
||||
|
||||
result := detectSystemLocale()
|
||||
if result != tt.expected {
|
||||
t.Errorf("%s: expected %q, got %q", tt.description, tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeLocale(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
// Standard Unix locale formats
|
||||
{"en_US.UTF-8", "en-US"},
|
||||
{"fr_FR.ISO8859-1", "fr-FR"},
|
||||
{"de_DE@euro", "de-DE"},
|
||||
{"zh_CN.GB2312", "zh-CN"},
|
||||
{"ja_JP.eucJP@traditional", "ja-JP"},
|
||||
|
||||
// Already normalized
|
||||
{"en-US", "en-US"},
|
||||
{"fr-CA", "fr-CA"},
|
||||
|
||||
// Language only
|
||||
{"en", "en"},
|
||||
{"fr", "fr"},
|
||||
{"zh", "zh"},
|
||||
|
||||
// Special cases
|
||||
{"C", ""},
|
||||
{"POSIX", ""},
|
||||
{"", ""},
|
||||
|
||||
// Complex cases
|
||||
{"pt_BR.UTF-8@currency=BRL", "pt-BR"},
|
||||
{"sr_RS.UTF-8@latin", "sr-RS"},
|
||||
{"uz_UZ.UTF-8@cyrillic", "uz-UZ"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
result := normalizeLocale(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("normalizeLocale(%q): expected %q, got %q", tt.input, tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidLocale(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected bool
|
||||
}{
|
||||
// Valid locales
|
||||
{"en", true},
|
||||
{"en-US", true},
|
||||
{"fr-FR", true},
|
||||
{"zh-CN", true},
|
||||
{"ja-JP", true},
|
||||
{"pt-BR", true},
|
||||
{"es-MX", true},
|
||||
|
||||
// Invalid locales
|
||||
{"", false},
|
||||
{"invalid", false},
|
||||
{"123", false}, // Numbers
|
||||
|
||||
// Note: golang.org/x/text/language is quite lenient and accepts:
|
||||
// - "en-ZZ" (unknown country codes are allowed)
|
||||
// - "en_US" (underscores are normalized to hyphens)
|
||||
// These are actually valid according to the language package
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
result := isValidLocale(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("isValidLocale(%q): expected %v, got %v", tt.input, tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPreferredLocale(t *testing.T) {
|
||||
// Save original environment
|
||||
originalLC_ALL := os.Getenv("LC_ALL")
|
||||
originalLC_MESSAGES := os.Getenv("LC_MESSAGES")
|
||||
originalLANG := os.Getenv("LANG")
|
||||
|
||||
// Clean up after test
|
||||
defer func() {
|
||||
os.Setenv("LC_ALL", originalLC_ALL)
|
||||
os.Setenv("LC_MESSAGES", originalLC_MESSAGES)
|
||||
os.Setenv("LANG", originalLANG)
|
||||
}()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
explicitLang string
|
||||
LC_ALL string
|
||||
LC_MESSAGES string
|
||||
LANG string
|
||||
expected string
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "Explicit language takes precedence",
|
||||
explicitLang: "es-ES",
|
||||
LC_ALL: "fr_FR.UTF-8",
|
||||
LC_MESSAGES: "de_DE.UTF-8",
|
||||
LANG: "ja_JP.UTF-8",
|
||||
expected: "es-ES",
|
||||
description: "Explicit language should override environment variables",
|
||||
},
|
||||
{
|
||||
name: "Use environment when no explicit language",
|
||||
explicitLang: "",
|
||||
LC_ALL: "it_IT.UTF-8",
|
||||
LC_MESSAGES: "ru_RU.UTF-8",
|
||||
LANG: "pl_PL.UTF-8",
|
||||
expected: "it-IT",
|
||||
description: "Should detect from environment when no explicit language",
|
||||
},
|
||||
{
|
||||
name: "Empty when no explicit and no environment",
|
||||
explicitLang: "",
|
||||
LC_ALL: "",
|
||||
LC_MESSAGES: "",
|
||||
LANG: "",
|
||||
expected: "",
|
||||
description: "Should return empty when nothing is set",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Set test environment
|
||||
os.Setenv("LC_ALL", tt.LC_ALL)
|
||||
os.Setenv("LC_MESSAGES", tt.LC_MESSAGES)
|
||||
os.Setenv("LANG", tt.LANG)
|
||||
|
||||
result := getPreferredLocale(tt.explicitLang)
|
||||
if result != tt.expected {
|
||||
t.Errorf("%s: expected %q, got %q", tt.description, tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationWithInit(t *testing.T) {
|
||||
// Save original environment
|
||||
originalLC_ALL := os.Getenv("LC_ALL")
|
||||
originalLANG := os.Getenv("LANG")
|
||||
|
||||
// Clean up after test
|
||||
defer func() {
|
||||
os.Setenv("LC_ALL", originalLC_ALL)
|
||||
os.Setenv("LANG", originalLANG)
|
||||
translator = nil // Reset global state
|
||||
}()
|
||||
|
||||
// Test that Init uses environment variables when no explicit locale provided
|
||||
os.Setenv("LC_ALL", "es_ES.UTF-8")
|
||||
os.Setenv("LANG", "fr_FR.UTF-8")
|
||||
|
||||
localizer, err := Init("")
|
||||
if err != nil {
|
||||
t.Fatalf("Init failed: %v", err)
|
||||
}
|
||||
|
||||
if localizer == nil {
|
||||
t.Error("Expected non-nil localizer")
|
||||
}
|
||||
|
||||
// Reset translator to test T() function auto-initialization
|
||||
translator = nil
|
||||
os.Setenv("LC_ALL", "")
|
||||
os.Setenv("LANG", "es_ES.UTF-8")
|
||||
|
||||
// This should trigger auto-initialization with environment detection
|
||||
result := T("html_readability_error")
|
||||
if result == "" {
|
||||
t.Error("Expected non-empty translation result")
|
||||
}
|
||||
}
|
||||
3
internal/i18n/locales/en.json
Normal file
3
internal/i18n/locales/en.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"html_readability_error": "use original input, because can't apply html readability"
|
||||
}
|
||||
3
internal/i18n/locales/es.json
Normal file
3
internal/i18n/locales/es.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"html_readability_error": "usa la entrada original, porque no se puede aplicar la legibilidad de html"
|
||||
}
|
||||
@@ -223,6 +223,9 @@ schema = 3
|
||||
[mod."github.com/modern-go/reflect2"]
|
||||
version = "v1.0.2"
|
||||
hash = "sha256-+W9EIW7okXIXjWEgOaMh58eLvBZ7OshW2EhaIpNLSBU="
|
||||
[mod."github.com/nicksnyder/go-i18n/v2"]
|
||||
version = "v2.6.0"
|
||||
hash = "sha256-UrSECFbpCIg5avJ+f3LkJy/ncZFHa4q8sDqDIQ3YZJM="
|
||||
[mod."github.com/ollama/ollama"]
|
||||
version = "v0.11.7"
|
||||
hash = "sha256-3Wn1JWmil0aQQ2I/r398HbnUsi8ADoroqNyPziuxn/c="
|
||||
|
||||
@@ -1 +1 @@
|
||||
"1.4.304"
|
||||
"1.4.308"
|
||||
|
||||
114
scripts/installer/README.md
Normal file
114
scripts/installer/README.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Fabric One-Line Installer
|
||||
|
||||
This directory contains the official one-line installer scripts for Fabric.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Unix/Linux/macOS
|
||||
|
||||
Install Fabric with a single command:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | bash
|
||||
```
|
||||
|
||||
### Windows (PowerShell)
|
||||
|
||||
Install Fabric with a single PowerShell command:
|
||||
|
||||
```powershell
|
||||
iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
|
||||
```
|
||||
|
||||
## Custom Installation Directory
|
||||
|
||||
### Unix/Linux/macOS
|
||||
|
||||
By default, Fabric is installed to `~/.local/bin`. To install elsewhere:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | INSTALL_DIR=/usr/local/bin bash
|
||||
```
|
||||
|
||||
For system-wide installation (requires sudo):
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | sudo INSTALL_DIR=/usr/local/bin bash
|
||||
```
|
||||
|
||||
### Windows (PowerShell)
|
||||
|
||||
By default, Fabric is installed to `%USERPROFILE%\.local\bin`. To install elsewhere:
|
||||
|
||||
```powershell
|
||||
$env:INSTALL_DIR="C:\tools"; iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
|
||||
```
|
||||
|
||||
## Supported Systems
|
||||
|
||||
- **Operating Systems**: Darwin (macOS), Linux, Windows
|
||||
- **Architectures**: x86_64, arm64, i386 (Windows only)
|
||||
|
||||
## What It Does
|
||||
|
||||
1. **Detects** your OS and architecture automatically
|
||||
2. **Downloads** the latest Fabric release from GitHub
|
||||
3. **Extracts** only the `fabric` binary (not the full archive)
|
||||
4. **Installs** to your chosen directory (default: `~/.local/bin`)
|
||||
5. **Verifies** the installation works correctly
|
||||
6. **Provides** PATH setup instructions if needed
|
||||
|
||||
## Features
|
||||
|
||||
- ✅ **Cross-platform** - Unix/Linux/macOS (bash) and Windows (PowerShell)
|
||||
- ✅ **Zero dependencies** - No additional tools required
|
||||
- ✅ **Automatic detection** - OS and architecture
|
||||
- ✅ **Smart extraction** - Only the binary, not extra files
|
||||
- ✅ **Error handling** - Clear messages and graceful failures
|
||||
- ✅ **PATH guidance** - Helps you set up your environment
|
||||
- ✅ **Verification** - Tests the installation before completing
|
||||
|
||||
## Requirements
|
||||
|
||||
### Unix/Linux/macOS
|
||||
|
||||
- `curl` or `wget` for downloading
|
||||
- `tar` for extraction (standard on all Unix systems)
|
||||
- Write permissions to the installation directory
|
||||
|
||||
### Windows
|
||||
|
||||
- PowerShell (built into Windows)
|
||||
- Write permissions to the installation directory
|
||||
|
||||
## After Installation
|
||||
|
||||
1. **Configure Fabric**: Run `fabric --setup`
|
||||
2. **Add API keys**: Follow the setup prompts
|
||||
3. **Start using**: Try `fabric --help` or `fabric --listpatterns`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Permission denied?**
|
||||
|
||||
- Try with `sudo` for system directories
|
||||
- Or choose a directory you can write to: `INSTALL_DIR=~/bin`
|
||||
|
||||
**Binary not found after install?**
|
||||
|
||||
- Add the install directory to your PATH
|
||||
- The installer provides specific instructions for your shell
|
||||
|
||||
**Download fails?**
|
||||
|
||||
- Check your internet connection
|
||||
- Verify GitHub is accessible from your network
|
||||
|
||||
## Alternative Installation Methods
|
||||
|
||||
If the one-liner doesn't work for you, see the main [Installation Guide](../../README.md#installation) for:
|
||||
|
||||
- Binary downloads
|
||||
- Package managers (Homebrew, winget, AUR)
|
||||
- Docker images
|
||||
- Building from source
|
||||
253
scripts/installer/install.ps1
Normal file
253
scripts/installer/install.ps1
Normal file
@@ -0,0 +1,253 @@
|
||||
# Fabric Windows Installer Script
|
||||
# Usage: iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
|
||||
# Usage with custom directory: $env:INSTALL_DIR="C:\tools"; iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
|
||||
|
||||
param(
|
||||
[string]$InstallDir = $env:INSTALL_DIR
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Colors for output (Windows Console colors)
|
||||
$Colors = @{
|
||||
Red = "Red"
|
||||
Green = "Green"
|
||||
Yellow = "Yellow"
|
||||
Blue = "Cyan"
|
||||
White = "White"
|
||||
}
|
||||
|
||||
# Print functions
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
Write-Host "[INFO] $Message" -ForegroundColor $Colors.Blue
|
||||
}
|
||||
|
||||
function Write-Success {
|
||||
param([string]$Message)
|
||||
Write-Host "[SUCCESS] $Message" -ForegroundColor $Colors.Green
|
||||
}
|
||||
|
||||
function Write-Warning {
|
||||
param([string]$Message)
|
||||
Write-Host "[WARNING] $Message" -ForegroundColor $Colors.Yellow
|
||||
}
|
||||
|
||||
function Write-Error {
|
||||
param([string]$Message)
|
||||
Write-Host "[ERROR] $Message" -ForegroundColor $Colors.Red
|
||||
}
|
||||
|
||||
# Detect Windows architecture
|
||||
function Get-Architecture {
|
||||
$arch = $env:PROCESSOR_ARCHITECTURE
|
||||
$archAMD64 = $env:PROCESSOR_ARCHITEW6432
|
||||
|
||||
# Check for ARM64
|
||||
if ($arch -eq "ARM64") {
|
||||
return "arm64"
|
||||
}
|
||||
|
||||
# Check for x86_64/AMD64
|
||||
if ($arch -eq "AMD64" -or $archAMD64 -eq "AMD64") {
|
||||
return "x86_64"
|
||||
}
|
||||
|
||||
# Check for x86 (32-bit)
|
||||
if ($arch -eq "X86") {
|
||||
return "i386"
|
||||
}
|
||||
|
||||
Write-Error "Unsupported architecture: $arch"
|
||||
Write-Error "This installer supports x86_64, i386, and arm64"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Test if running with appropriate permissions for directory
|
||||
function Test-WritePermission {
|
||||
param([string]$Path)
|
||||
|
||||
try {
|
||||
if (!(Test-Path $Path)) {
|
||||
New-Item -Path $Path -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
$testFile = Join-Path $Path "fabric_write_test.tmp"
|
||||
"test" | Out-File -FilePath $testFile -Force
|
||||
Remove-Item $testFile -Force
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
# Download and install Fabric
|
||||
function Install-Fabric {
|
||||
param(
|
||||
[string]$Architecture,
|
||||
[string]$InstallDirectory
|
||||
)
|
||||
|
||||
# Construct download URL
|
||||
$filename = "fabric_Windows_$Architecture.zip"
|
||||
$downloadUrl = "https://github.com/danielmiessler/fabric/releases/latest/download/$filename"
|
||||
|
||||
Write-Info "Downloading Fabric for Windows $Architecture..."
|
||||
Write-Info "URL: $downloadUrl"
|
||||
|
||||
# Create temporary directory
|
||||
$tempDir = Join-Path $env:TEMP "fabric_install_$(Get-Random)"
|
||||
New-Item -Path $tempDir -ItemType Directory -Force | Out-Null
|
||||
$tempFile = Join-Path $tempDir "fabric.zip"
|
||||
|
||||
try {
|
||||
# Download the archive
|
||||
Write-Info "Downloading archive..."
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile $tempFile -UseBasicParsing
|
||||
|
||||
Write-Info "Extracting Fabric binary..."
|
||||
|
||||
# Extract the zip file
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
$zip = [System.IO.Compression.ZipFile]::OpenRead($tempFile)
|
||||
|
||||
# Find and extract only fabric.exe
|
||||
$fabricEntry = $zip.Entries | Where-Object { $_.Name -eq "fabric.exe" }
|
||||
if (!$fabricEntry) {
|
||||
Write-Error "fabric.exe not found in the downloaded archive"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create install directory if it doesn't exist
|
||||
if (!(Test-Path $InstallDirectory)) {
|
||||
Write-Info "Creating install directory: $InstallDirectory"
|
||||
New-Item -Path $InstallDirectory -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
# Extract fabric.exe to install directory
|
||||
$fabricPath = Join-Path $InstallDirectory "fabric.exe"
|
||||
Write-Info "Installing Fabric to $fabricPath..."
|
||||
|
||||
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($fabricEntry, $fabricPath, $true)
|
||||
$zip.Dispose()
|
||||
|
||||
Write-Success "Fabric installed successfully to $fabricPath"
|
||||
return $fabricPath
|
||||
}
|
||||
catch {
|
||||
Write-Error "Failed to download or extract Fabric: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
finally {
|
||||
# Clean up
|
||||
if (Test-Path $tempDir) {
|
||||
Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check if directory is in PATH
|
||||
function Test-InPath {
|
||||
param([string]$Directory)
|
||||
|
||||
$pathDirs = $env:PATH -split ';'
|
||||
return $pathDirs -contains $Directory
|
||||
}
|
||||
|
||||
# Provide PATH setup instructions
|
||||
function Show-PathInstructions {
|
||||
param([string]$InstallDir)
|
||||
|
||||
if (Test-InPath $InstallDir) {
|
||||
Write-Success "✅ $InstallDir is already in your PATH"
|
||||
}
|
||||
else {
|
||||
Write-Warning "⚠️ $InstallDir is not in your PATH"
|
||||
Write-Info "To use fabric from anywhere, you have a few options:"
|
||||
Write-Info ""
|
||||
Write-Info "Option 1 - Add to PATH for current user (recommended):"
|
||||
Write-Info " `$currentPath = [Environment]::GetEnvironmentVariable('PATH', 'User')"
|
||||
Write-Info " [Environment]::SetEnvironmentVariable('PATH', `"`$currentPath;$InstallDir`", 'User')"
|
||||
Write-Info ""
|
||||
Write-Info "Option 2 - Add to PATH for all users (requires admin):"
|
||||
Write-Info " `$currentPath = [Environment]::GetEnvironmentVariable('PATH', 'Machine')"
|
||||
Write-Info " [Environment]::SetEnvironmentVariable('PATH', `"`$currentPath;$InstallDir`", 'Machine')"
|
||||
Write-Info ""
|
||||
Write-Info "Option 3 - Add to current session only:"
|
||||
Write-Info " `$env:PATH += `";$InstallDir`""
|
||||
Write-Info ""
|
||||
Write-Info "After updating PATH, restart your terminal or run: refreshenv"
|
||||
}
|
||||
}
|
||||
|
||||
# Verify installation
|
||||
function Test-Installation {
|
||||
param([string]$FabricPath)
|
||||
|
||||
if (Test-Path $FabricPath) {
|
||||
Write-Info "Verifying installation..."
|
||||
try {
|
||||
$version = & $FabricPath --version 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Success "Fabric $version is working correctly!"
|
||||
}
|
||||
else {
|
||||
Write-Warning "Fabric binary exists but --version failed"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Fabric binary exists but could not run --version"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error "Fabric binary not found at $FabricPath"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Main installation function
|
||||
function Main {
|
||||
Write-Info "🚀 Starting Fabric installation..."
|
||||
|
||||
# Detect architecture
|
||||
$arch = Get-Architecture
|
||||
Write-Info "Detected architecture: $arch"
|
||||
|
||||
# Determine install directory
|
||||
if (!$InstallDir) {
|
||||
$InstallDir = Join-Path $env:USERPROFILE ".local\bin"
|
||||
}
|
||||
|
||||
Write-Info "Install directory: $InstallDir"
|
||||
|
||||
# Check permissions
|
||||
if (!(Test-WritePermission $InstallDir)) {
|
||||
Write-Error "Cannot write to $InstallDir"
|
||||
Write-Error "Try running as Administrator or choose a different directory"
|
||||
Write-Info "Example with custom directory: `$env:INSTALL_DIR=`"C:\tools`"; iwr -useb ... | iex"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Install Fabric
|
||||
$fabricPath = Install-Fabric -Architecture $arch -InstallDirectory $InstallDir
|
||||
|
||||
# Verify installation
|
||||
Test-Installation -FabricPath $fabricPath
|
||||
|
||||
# Check PATH and provide instructions
|
||||
Show-PathInstructions -InstallDir $InstallDir
|
||||
|
||||
Write-Info ""
|
||||
Write-Success "🎉 Installation complete!"
|
||||
Write-Info ""
|
||||
Write-Info "Next steps:"
|
||||
Write-Info " 1. Run 'fabric --setup' to configure Fabric"
|
||||
Write-Info " 2. Add your API keys and preferences"
|
||||
Write-Info " 3. Start using Fabric with 'fabric --help'"
|
||||
Write-Info ""
|
||||
Write-Info "Documentation: https://github.com/danielmiessler/fabric"
|
||||
}
|
||||
|
||||
# Run main function
|
||||
Main
|
||||
219
scripts/installer/install.sh
Executable file
219
scripts/installer/install.sh
Executable file
@@ -0,0 +1,219 @@
|
||||
#!/bin/bash
|
||||
# Fabric Installer Script
|
||||
# Usage: curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | bash
|
||||
# Usage with custom directory: curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | INSTALL_DIR=/usr/local/bin bash
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Print functions
|
||||
print_info() {
|
||||
printf "${BLUE}[INFO]${NC} %s\n" "$1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
printf "${GREEN}[SUCCESS]${NC} %s\n" "$1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
printf "${YELLOW}[WARNING]${NC} %s\n" "$1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
printf "${RED}[ERROR]${NC} %s\n" "$1" >&2
|
||||
}
|
||||
|
||||
# Detect OS
|
||||
detect_os() {
|
||||
case "$(uname -s)" in
|
||||
Darwin*)
|
||||
echo "Darwin"
|
||||
;;
|
||||
Linux*)
|
||||
echo "Linux"
|
||||
;;
|
||||
*)
|
||||
print_error "Unsupported operating system: $(uname -s)"
|
||||
print_error "This installer only supports Darwin (macOS) and Linux"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Detect architecture
|
||||
detect_arch() {
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64)
|
||||
echo "x86_64"
|
||||
;;
|
||||
arm64|aarch64)
|
||||
echo "arm64"
|
||||
;;
|
||||
*)
|
||||
print_error "Unsupported architecture: $(uname -m)"
|
||||
print_error "This installer only supports x86_64 and arm64"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check if command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Download and extract fabric
|
||||
install_fabric() {
|
||||
local os="$1"
|
||||
local arch="$2"
|
||||
local install_dir="$3"
|
||||
|
||||
# Construct download URL
|
||||
local filename="fabric_${os}_${arch}.tar.gz"
|
||||
local download_url="https://github.com/danielmiessler/fabric/releases/latest/download/${filename}"
|
||||
|
||||
print_info "Downloading Fabric for ${os} ${arch}..."
|
||||
print_info "URL: ${download_url}"
|
||||
|
||||
# Create temporary directory
|
||||
local temp_dir
|
||||
temp_dir=$(mktemp -d)
|
||||
local temp_file="${temp_dir}/fabric.tar.gz"
|
||||
|
||||
# Download the archive
|
||||
if command_exists curl; then
|
||||
if ! curl -fsSL "${download_url}" -o "${temp_file}"; then
|
||||
print_error "Failed to download Fabric"
|
||||
rm -rf "${temp_dir}"
|
||||
exit 1
|
||||
fi
|
||||
elif command_exists wget; then
|
||||
if ! wget -q "${download_url}" -O "${temp_file}"; then
|
||||
print_error "Failed to download Fabric"
|
||||
rm -rf "${temp_dir}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_error "Neither curl nor wget found. Please install one of them and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_info "Extracting Fabric binary..."
|
||||
|
||||
# Extract only the fabric binary from the archive
|
||||
if ! tar -xzf "${temp_file}" -C "${temp_dir}" fabric; then
|
||||
print_error "Failed to extract Fabric binary"
|
||||
rm -rf "${temp_dir}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create install directory if it doesn't exist
|
||||
if [ ! -d "${install_dir}" ]; then
|
||||
print_info "Creating install directory: ${install_dir}"
|
||||
if ! mkdir -p "${install_dir}"; then
|
||||
print_error "Failed to create install directory: ${install_dir}"
|
||||
print_error "You may need to run with sudo or choose a different directory"
|
||||
rm -rf "${temp_dir}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Move binary to install directory
|
||||
print_info "Installing Fabric to ${install_dir}/fabric..."
|
||||
if ! mv "${temp_dir}/fabric" "${install_dir}/fabric"; then
|
||||
print_error "Failed to install Fabric to ${install_dir}"
|
||||
print_error "You may need to run with sudo or choose a different directory"
|
||||
rm -rf "${temp_dir}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure it's executable
|
||||
chmod +x "${install_dir}/fabric"
|
||||
|
||||
# Clean up
|
||||
rm -rf "${temp_dir}"
|
||||
|
||||
print_success "Fabric installed successfully to ${install_dir}/fabric"
|
||||
}
|
||||
|
||||
# Check PATH and provide instructions
|
||||
check_path() {
|
||||
local install_dir="$1"
|
||||
|
||||
if echo "$PATH" | grep -q "${install_dir}"; then
|
||||
print_success "✅ ${install_dir} is already in your PATH"
|
||||
else
|
||||
print_warning "⚠️ ${install_dir} is not in your PATH"
|
||||
print_info "To use fabric from anywhere, add the following to your shell profile:"
|
||||
print_info " export PATH=\"\$PATH:${install_dir}\""
|
||||
print_info ""
|
||||
print_info "For bash, add it to ~/.bashrc or ~/.bash_profile"
|
||||
print_info "For zsh, add it to ~/.zshrc"
|
||||
print_info "For fish, run: fish_add_path ${install_dir}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Verify installation
|
||||
verify_installation() {
|
||||
local install_dir="$1"
|
||||
local fabric_path="${install_dir}/fabric"
|
||||
|
||||
if [ -x "${fabric_path}" ]; then
|
||||
print_info "Verifying installation..."
|
||||
local version
|
||||
if version=$("${fabric_path}" --version 2>/dev/null); then
|
||||
print_success "Fabric ${version} is working correctly!"
|
||||
else
|
||||
print_warning "Fabric binary exists but --version failed"
|
||||
fi
|
||||
else
|
||||
print_error "Fabric binary not found at ${fabric_path}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main installation function
|
||||
main() {
|
||||
print_info "🚀 Starting Fabric installation..."
|
||||
|
||||
# Detect system
|
||||
local os
|
||||
local arch
|
||||
os=$(detect_os)
|
||||
arch=$(detect_arch)
|
||||
|
||||
print_info "Detected system: ${os} ${arch}"
|
||||
|
||||
# Determine install directory
|
||||
local install_dir="${INSTALL_DIR:-${HOME}/.local/bin}"
|
||||
|
||||
print_info "Install directory: ${install_dir}"
|
||||
|
||||
# Install fabric
|
||||
install_fabric "${os}" "${arch}" "${install_dir}"
|
||||
|
||||
# Verify installation
|
||||
verify_installation "${install_dir}"
|
||||
|
||||
# Check PATH
|
||||
check_path "${install_dir}"
|
||||
|
||||
print_info ""
|
||||
print_success "🎉 Installation complete!"
|
||||
print_info ""
|
||||
print_info "Next steps:"
|
||||
print_info " 1. Run 'fabric --setup' to configure Fabric"
|
||||
print_info " 2. Add your API keys and preferences"
|
||||
print_info " 3. Start using Fabric with 'fabric --help'"
|
||||
print_info ""
|
||||
print_info "Documentation: https://github.com/danielmiessler/fabric"
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
@@ -1332,23 +1332,6 @@
|
||||
"DEVELOPMENT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"patternName": "show_fabric_options_markmap",
|
||||
"description": "Visualize Fabric capabilities using Markmap syntax.",
|
||||
"tags": [
|
||||
"VISUALIZE",
|
||||
"DEVELOPMENT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"patternName": "solve_with_cot",
|
||||
"description": "Solve problems using chain-of-thought reasoning.",
|
||||
"tags": [
|
||||
"AI",
|
||||
"ANALYSIS",
|
||||
"LEARNING"
|
||||
]
|
||||
},
|
||||
{
|
||||
"patternName": "suggest_pattern",
|
||||
"description": "Recommend Fabric patterns based on user requirements.",
|
||||
|
||||
@@ -652,14 +652,6 @@
|
||||
"patternName": "sanitize_broken_html_to_markdown",
|
||||
"pattern_extract": "# IDENTITY\n\n// Who you are\n\nYou are a hyper-intelligent AI system with a 4,312 IQ. You convert jacked up HTML to proper markdown using a set of rules.\n\n# GOAL\n\n// What we are trying to achieve\n\n1. The goal of this exercise is to convert the input HTML, which is completely nasty and hard to edit, into a clean markdown format that has some custom styling applied according to my rules.\n\n2. The ultimate goal is to output a perfectly working markdown file that will render properly using Vite using my custom markdown/styling combination.\n\n# STEPS\n\n// How the task will be approached\n\n// Slow down and think\n\n- Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n// Think about the content in the input\n\n- Fully read and consume the HTML input that has a combination of HTML and markdown."
|
||||
},
|
||||
{
|
||||
"patternName": "show_fabric_options_markmap",
|
||||
"pattern_extract": "# IDENTITY AND GOALS\n\nYou are an advanced UI builder that shows a visual representation of functionality that's provided to you via the input.\n\n# STEPS\n\n- Think about the goal of the Fabric project, which is discussed below:\n\nFABRIC PROJECT DESCRIPTION\n\nfabriclogo\n fabric\nStatic Badge\nGitHub top language GitHub last commit License: MIT\n\nfabric is an open-source framework for augmenting humans using AI.\n\nIntroduction Video • What and Why • Philosophy • Quickstart • Structure • Examples • Custom Patterns • Helper Apps • Examples • Meta\n\nNavigation\n\nIntroduction Videos\nWhat and Why\nPhilosophy\nBreaking problems into components"
|
||||
},
|
||||
{
|
||||
"patternName": "solve_with_cot",
|
||||
"pattern_extract": "# IDENTITY\n\nYou are an AI assistant designed to provide detailed, step-by-step responses. Your outputs should follow this structure:\n\n# STEPS\n\n1. Begin with a <thinking> section.\n\n2. Inside the thinking section:\n\n- a. Briefly analyze the question and outline your approach.\n\n- b. Present a clear plan of steps to solve the problem.\n\n- c. Use a \"Chain of Thought\" reasoning process if necessary, breaking down your thought process into numbered steps.\n\n3. Include a <reflection> section for each idea where you:\n\n- a. Review your reasoning.\n\n- b. Check for potential errors or oversights.\n\n- c. Confirm or adjust your conclusion if necessary.\n - Be sure to close all reflection sections.\n - Close the thinking section with </thinking>."
|
||||
},
|
||||
{
|
||||
"patternName": "suggest_pattern",
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\nYou are an AI assistant tasked with creating a new feature for a fabric command-line tool. Your primary responsibility is to develop a pattern that suggests appropriate fabric patterns or commands based on user input. You are knowledgeable about fabric commands and understand the need to expand the tool's functionality. Your role involves analyzing user requests, determining the most suitable fabric commands or patterns, and providing helpful suggestions to users.\n\nTake a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n# STEPS\n- Analyze the user's input to understand their specific needs and context\n- Determine the appropriate fabric pattern or command based on the user's request\n- Generate a response that suggests the relevant fabric command(s) or pattern(s)\n- Provide explanations or multiple options when applicable\n- If no specific command is found, suggest using `create_pattern`\n\n# OUTPUT INSTRUCTIONS\n- Only output Markdown\n- Provide suggestions for fabric commands or patterns based on the user's input\n- Include explanations or multiple options when appropriate\n- If suggesting `create_pattern`, include instructions for saving and using the new pattern\n- Format the output to be clear and easy to understand for users new to fabric\n- Ensure the response aligns with the goal of making fabric more accessible and user-friendly\n- Ensure you follow ALL these instructions when creating your output\n\n# INPUT\nINPUT:"
|
||||
|
||||
@@ -1332,23 +1332,6 @@
|
||||
"DEVELOPMENT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"patternName": "show_fabric_options_markmap",
|
||||
"description": "Visualize Fabric capabilities using Markmap syntax.",
|
||||
"tags": [
|
||||
"VISUALIZE",
|
||||
"DEVELOPMENT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"patternName": "solve_with_cot",
|
||||
"description": "Solve problems using chain-of-thought reasoning.",
|
||||
"tags": [
|
||||
"AI",
|
||||
"ANALYSIS",
|
||||
"LEARNING"
|
||||
]
|
||||
},
|
||||
{
|
||||
"patternName": "suggest_pattern",
|
||||
"description": "Recommend Fabric patterns based on user requirements.",
|
||||
|
||||
Reference in New Issue
Block a user