https://github.com/zenor0/mdship
pack and ship your markdown
https://github.com/zenor0/mdship
cli go markdown md mermaid pandoc productivity typst
Last synced: 11 days ago
JSON representation
pack and ship your markdown
- Host: GitHub
- URL: https://github.com/zenor0/mdship
- Owner: zenor0
- License: mit
- Created: 2026-02-23T09:59:47.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-09T01:36:10.000Z (3 months ago)
- Last Synced: 2026-05-04T19:03:34.954Z (about 1 month ago)
- Topics: cli, go, markdown, md, mermaid, pandoc, productivity, typst
- Language: Go
- Homepage:
- Size: 3.31 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README

Deliver your Markdown content anywhere in one command. mdship is a CLI tool and Go library for packaging Markdown context and converting to various formats via Pandoc and other tools.
## Key features
- **Resource Discovery and Packaging**: Automatically discover local and remote resources (images, PDFs, etc.) linked in your Markdown, download remote assets, and package them into a structured workspace for conversion.
- **BibTex Citation Trimming**: Automatically extract and trim BibTeX entries for only the citations used in your document, keeping your bibliography lean and relevant.
- **Built-in neat Typst/Word templates**: Use mdship's built-in Typst templates for quick and beautiful PDF generation, or create your own templates for custom styling.
- **Mermaid Rendering**: Optionally render Mermaid diagrams to images before conversion, ensuring your diagrams look great in the final output.
- **Conversion Pipeline**: Convert your Markdown to various formats (PDF, HTML, Typst, etc.) using a configurable pipeline that can include pre-processing steps (like Mermaid rendering) and post-processing steps (like Typst compilation).
## Architecture
Two stages keep the system extensible:
1) **pack**: discover resources/citations, download remote assets, trim BibTeX,
and build a minimal workspace.
2) **convert**: run a conversion pipeline against packed markdown with predictable paths.
## Workspace layout (pack output)
```
/
document.md
manifest.json
bibliography.bib (optional)
assets/ (local files copied here)
remote/ (downloaded files)
```
## Installation
Install the CLI with Go:
```bash
go install github.com/zenor0/mdship/cmd/mdship@latest
```
For reproducible installs, prefer a tagged version instead of `latest`:
```bash
go install github.com/zenor0/mdship/cmd/mdship@v0.1.0
```
Make sure your Go bin directory is on `PATH`:
```bash
export PATH="$(go env GOPATH)/bin:$PATH"
```
Then verify the installation and check which external tools are still needed:
```bash
mdship --version
mdship check
```
## Requirements
- Go 1.24+ (only required for `go install` or local development)
- Pandoc on PATH
- Mermaid CLI (`mmdc`) when Mermaid rendering is enabled (pack defaults to enabled)
- Typst when compiling to PDF/PNG or using typst compile
## Local checks before commit
To catch the same Go formatting, vet, lint, and test failures before pushing, run:
```bash
make pre-commit
```
For a fuller local pass that also checks `go mod tidy` drift and race tests, run:
```bash
make ci-local
```
Install the repo-pinned `golangci-lint` version used by CI with (it is stored under `.tools/bin`):
```bash
make lint-install
```
`golangci-lint` is pinned in `.golangci-version`, and GitHub Actions reads that same file, so you only need to update one place when bumping the linter version. `make pre-commit` will auto-install or refresh that pinned version locally when missing or stale.
If you want Git to run the fast checks automatically before each commit, enable the repo hook once:
```bash
git config core.hooksPath .githooks
```
## Usage
Check external dependencies:
```bash
mdship check
mdship check --format json
```
`check` reports `pandoc`, `mmdc`, and `typst` so you can validate pack + convert toolchains up front.
### Structured error output for integrations
On command failure, mdship still prints a human-readable error line to `stderr`.
When `stderr` is non-interactive (pipe/file), mdship also appends one machine-readable line:
```text
MDSHIP_ERROR_JSON: {"error":{"source":"cli","code":"...","kind":"...","message":"...","suggestions":[...],"details":{...}}}
```
You can force this behavior with `MDSHIP_ERROR_JSON=1` or disable it with `MDSHIP_ERROR_JSON=0`.
Common codes include `CLI_FLAG_INVALID`, `CLI_DEPENDENCY_MISSING`, `CLI_CONFIG_INVALID`,
`CLI_PROFILE_INVALID`, `CLI_FILE_MISSING`, and `CLI_RESOURCE_MISSING`.
Pack a Markdown file:
```bash
mdship pack ./notes/example.md --out-dir ./mdship-out
```
By default, `pack` only searches the input directory for relative resources (`--parent-depth=0`). Increase `--parent-depth` (or add `--resource-path`) when you intentionally want parent-directory lookup.
Clean previously generated workspace artifacts before writing fresh outputs:
```bash
mdship pack ./notes/example.md --out-dir ./mdship-out --clean
```
Add resource paths and bibliography files:
```bash
mdship pack ./notes/example.md \
--resource-path ./attachments \
--bibliography ./refs/library.bib
```
Override Pandoc markdown output settings during pack:
```bash
mdship pack ./notes/example.md --pandoc-arg=--wrap=preserve
```
Convert the packaged document:
```bash
mdship convert --input ./mdship-out/document.md --to typst
```
Select a built-in conversion profile (e.g., Typst template preset):
```bash
mdship convert --input ./mdship-out/document.md --profile typst/default
```
Use Typst with a profile (embedded by default):
```bash
mdship convert --input ./mdship-out/document.md --to typst \
--profile typst/default
```
Use a custom profile on disk:
```bash
mdship convert --input ./mdship-out/document.md --to typst \
--profile /path/to/your/profile.yaml
```
Built-in profiles live under `modules//profiles`. You can also point `--profile` at a local `profile.yaml` (or a profile directory).
Release binaries and `go install` builds include built-in profiles from embedded assets. You can verify them with `mdship profiles` after installation.
List built-in profiles plus additional profile directories:
```bash
mdship profiles
mdship profiles --profile-dir ./modules --profile-dir /path/to/custom/modules
mdship profiles --profile-dir ./modules --verbose
mdship profiles --profile-dir ./modules --format json
```
`profile.yaml` defines pandoc CLI args plus template metadata. `args` can be raw strings or structured YAML (unset fields are skipped):
```yaml
meta:
name: Typst Default
alias: [default]
tags: [typst]
author: mdship
description: Default typst template profile.
args:
to: typst
standalone: true
template: profiles/default/template.typst
lua-filter:
- common/filters/html-br-linebreak.lua
- profiles/default/filters/callout-blocks.lua
metadata:
example: true
```
Rules of thumb: keys map to Pandoc flags, `true` adds a flag, lists repeat flags, and `metadata`/`variable` accept maps.
Render Mermaid blocks before conversion:
```bash
mdship convert --input ./mdship-out/document.md --to pdf --mermaid
```
Configure a conversion chain explicitly:
```bash
mdship convert --input ./mdship-out/document.md --to pdf \
--pipeline mermaid,pandoc:typst,typst-compile
```
Keep intermediate Typst output when compiling to PDF/PNG:
```bash
mdship convert --input ./mdship-out/document.md --to pdf --pipeline typst,typst-compile --typst-compile-keep
```
Pass extra Pandoc arguments after `--`:
```bash
mdship convert --input ./mdship-out/document.md --to typst -- --template template.typst
```
Ship a markdown file (pack + convert in a temp workspace):
```bash
mdship ship ./notes/example.md --to typst
```
When `ship` runs in default `file` mode and `--out` is omitted, output files are written to the current working directory (for example `./example.typ`).
When `ship` writes outputs in `file` mode, existing conflicting files are protected by default (primary output + sidecars). In an interactive terminal, mdship prompts before overwrite; in non-interactive runs it fails safely.
Use `--force` to overwrite without prompting:
```bash
mdship ship ./notes/example.md --to typst --force
```
When using `ship`, `--resource-path/-r` is also applied to the pack stage so external assets can be collected into the packaged workspace:
```bash
mdship ship ./notes/example.md --to typst --resource-path ./attachments
```
Ship into a directory or zip archive:
```bash
mdship ship ./notes/example.md --to typst --ship-package dir --out ./dist
mdship ship ./notes/example.md --to pdf --ship-package zip --out ./dist/example.zip
```
`ship` now preserves packaged sidecar resources (`assets/`, `remote/`) for text-like outputs (for example Typst/Markdown/HTML) so relative links keep working after export. It also writes a ship report with warnings/missing resources for downstream tooling:
- file mode: `.ship-manifest.json`
- dir/zip mode: `ship-manifest.json`
`ship-manifest.json` and preflight reports now share the same JSON envelope (`version: 0.2.0`) so external callers can parse one schema for both dry-run checks and real shipments.
Run a preflight check (pack-only) before full ship, and fail on any warnings/missing resources:
```bash
mdship ship ./notes/example.md --preflight --strict --report-out ./dist/preflight-report.json
```
Use `pack --strict` to fail when unresolved resources or warnings are detected:
```bash
mdship pack ./notes/example.md --strict --report-out ./mdship-out/preflight-report.json
```
Override a specific markdown resource target without moving files into resource paths:
```bash
mdship ship ./notes/example.md --preflight --strict \
--resource-map "images/logo.png=/tmp/uploads/new-logo.png"
```
Use a config file (YAML or JSON) to provide defaults:
```bash
mdship --config ./mdship.yaml pack ./notes/example.md
```
The default config lives at `internal/config/default.yaml` (copy it as a starting point). CLI flags override config values when provided. For module layout conventions, see `docs/modules.md`.
For an implementation-based CLI input/output/error contract, see `docs/cli-contract.md`.
Profiles can be declared in config and selected via `convert.profile` or `--profile`:
```yaml
convert:
profiles:
typst/default:
path: typst/default
profile: typst/default
```
Print the default or effective config:
```bash
mdship config
mdship --config ./mdship.yaml config --effective
```
## Example
See `examples/example.md` for a minimal Markdown + asset + bibliography setup.
## Contact
For questions, feedback, or contributions, please open an issue or reach out on GitHub Discussions.
## License
mdship is licensed under the MIT License. See [LICENSE](LICENSE) for details.