diff --git a/bin/ansi2html b/bin/ansi2html
new file mode 100755
index 0000000..9140cfb
--- /dev/null
+++ b/bin/ansi2html
@@ -0,0 +1,8 @@
+#!/bin/sh
+for F; do
+ sed -e "s|$(printf '\33\\[0;34m')|<span style=\"color: blue;\">|g" \
+ -e "s|$(printf '\33\\[0;35m')|<span style=\"color: purple;\">|g" \
+ -e "s|$(printf '\33\\[0m')|</span>|g" \
+ -e 's|$|<br/>|' \
+ < "$F" > "$F.html"
+done
diff --git a/bin/shpkg_ci b/bin/shpkg_ci
new file mode 100755
index 0000000..2f250a6
--- /dev/null
+++ b/bin/shpkg_ci
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+logs2html () {
+ for F in ~/"www/log/${SHPKG_TARGET}/${SHPKG_REPO}".*.log; do
+ if ! [ -f "$F.html" ]; then
+ ansi2html "$F"
+ fi
+ done
+}
+
+if [ "x${CC}" = "x" ]; then
+ if which cc >/dev/null; then
+ CC=cc
+ elif which gcc >/dev/null; then
+ CC=gcc
+ elif which egcc >/dev/null; then
+ CC=egcc
+ else
+ err 1 "C compiler not found."
+ fi
+fi
+SHPKG_TARGET="$(LC_ALL=C.UTF-8 ${CC} -v 2>&1 | grep '^Target: ' | head -n 1 | cut -c 9-)"
+
+if ! [ -d ~/"www/log/${SHPKG_TARGET}" ]; then
+ mkdir -p ~/"www/log/${SHPKG_TARGET}"
+fi
+
+for SHPKG_REPO; do
+ export SHPKG_DIR=~/"shpkg_${SHPKG_REPO}"
+ if ! [ -d "${SHPKG_DIR}" ]; then
+ shpkg_bootstrap
+ fi
+ ( . ~/"shpkg_${SHPKG_REPO}/etc/shpkg/profile"
+ shpkg upgrade "${SHPKG_REPO}"
+ cp ~/"shpkg_${SHPKG_REPO}/var/log/shpkg/tags/${SHPKG_REPO}".*.log ~/"www/log/${SHPKG_TARGET}/"
+ logs2html
+ shpkg_bootstrap -f ~/"shpkg_${SHPKG_REPO}"; )
+ ( . ~/"shpkg_${SHPKG_REPO}/etc/shpkg/profile"
+ shpkg install "${SHPKG_REPO}"
+ cp ~/"shpkg_${SHPKG_REPO}/var/log/shpkg/tags/${SHPKG_REPO}".*.log ~/"www/log/${SHPKG_TARGET}"
+ logs2html; )
+done