O que portifact faz?
A Portifact publica artefatos estáticos com seu próprio URL, controle de acesso, expiração e restauração, e anotações opcionais de revisores autenticados. Os agentes a utilizam através da CLI portifact ou do servidor MCP remoto.
Verifique quais versões suportam
A Portifact está em desenvolvimento inicial e ganha comandos a cada versão. Antes de usar qualquer comando:
- Execute
portifact --versionpara confirmar que a CLI está instalada. - Execute
portifact --helppara ver os comandos que esta versão suporta. - Use apenas comandos e flags que
--helplista. Nunca adivinhe um comando. Se o usuário pedir algo que a versão instalada não pode fazer, diga isso e sugira a atualização.
Versões cujo --help lista login podem fazer login, logout e mostrar a conta conectada. Versões cujo --help também lista publish podem publicar arquivos e pastas e gerenciar artefatos e seu acesso, e versões cujo --help lista versions, rollback e pull podem listar versões, reverter e baixar, e versões cujo --help lista annotations podem gerenciar threads de comentários, conforme descrito abaixo. Versões onde portifact publish --help lista --source, --ref e --assets publicam arquivos ZIP, anexam fontes privadas e publicam assets Markdown; versões onde portifact pull --help lista --git constroem um histórico Git das fontes privadas; versões cujo --help lista usage mostram as cotas da conta; versões cujo --help lista logs mostram quem abriu um artefato; e versões cujo --help lista licenses imprimem as licenças do software de código aberto no binário (portifact licenses; também em https://portifact.com/third-party-notices). O servidor MCP em https://app.portifact.com/mcp pode listar, publicar e gerenciar documentos pequenos, listar, baixar e reverter versões, ler, escrever, moderar e exportar anotações, e reportar uso e logs de acesso; veja abaixo.
Instalar ou atualizar a CLI
A CLI é um único executável e não precisa de Node ou Bun. Pergunte antes de instalar software na máquina do usuário.
curl -fsSL https://portifact.com/install | bash
irm https://portifact.com/install.ps1 | iex
- No Alpine Linux, instale o runtime C++ primeiro:
apk add libstdc++ libgcc. - Execute o mesmo comando novamente para atualizar.
- Defina
PORTIFACT_VERSION=0.2.0para instalar uma versão específica. - Em ambientes não interativos ou isolados, defina
PORTIFACT_NO_MODIFY_PATH=1e chame~/.portifact/bin/portifactdiretamente em vez de editar perfis de shell. - O instalador verifica o download com os checksums de lançamento e para em caso de incompatibilidade. Não ignore uma verificação falha.
Fazer login
Verifique primeiro com portifact whoami --json. Código de saída 0 imprime {"server","userId","clientId","scopes"}; código de saída 3 significa que este dispositivo não está conectado ou a sessão expirou.
Para fazer login, execute portifact login (adicione --json para um resultado parseável). Ele usa o fluxo de dispositivo OAuth:
- A CLI imprime uma página (
https://app.portifact.com/device) e um código de 8 caracteres no stderr, e abre o navegador quando uma pessoa está no terminal. Passe--no-browserpara pular a abertura. - Mostre ao usuário a página e o código exatamente como impressos, e peça para ele fazer login lá, verificar se a página mostra o mesmo código e aprová-lo. Nunca aprove por ele e nunca peça para ele colar nada dessa página de volta para você. A página de login pede ao usuário para confirmar que tem 18 anos ou mais e aceitar os termos (
https://portifact.com/terms); essa escolha é dele, então nunca a aceite por ele. Se a página disser que não pode enviar um código de e-mail para o endereço dele (e-mail anterior foi devolvido ou denunciado como spam) ou que os códigos de e-mail estão pausados para o mês, diga ao usuário para fazer login com Google ou GitHub. - O comando aguarda até que o usuário aprove ou negue, ou o código expire (10 minutos), então execute-o onde o usuário possa ver seu stderr e deixe-o terminar.
As credenciais vão para o armazenamento de credenciais do sistema operacional. Quando não houver nenhum (por exemplo, um servidor Linux sem um Secret Service), elas vão para credentials.json no diretório de configuração do usuário (~/.config/portifact no Linux, ~/Library/Application Support/portifact no macOS, %APPDATA%\portifact no Windows) com permissões apenas para o usuário, e a CLI imprime um aviso. Nunca leia, imprima, copie ou faça upload desse arquivo ou dos tokens armazenados; a CLI os atualiza sozinha.
portifact logout revoga os tokens deste dispositivo no servidor e depois os remove. Ele revoga tokens, então confirme com o usuário primeiro. Se o servidor não puder ser alcançado, ele mantém as credenciais e sai com código 1; execute novamente mais tarde.
PORTIFACT_APP_ORIGIN aponta a CLI para outro servidor e existe para testes e staging. Não o defina a menos que o usuário peça.
Publicar
Apenas em versões cujo --help lista publish.
- Visualize primeiro:
portifact publish <caminho> --dry-run --jsonconstrói o manifesto sem fazer login ou enviar. Retorna{"dryRun","type","name","entrypoint","totalBytes","files":[{"path","size","sha256","contentType"}],"excluded":[{"path","reason"}]}, além de"sources":{"chosenBy","totalBytes","files","excluded","origin","lfsPointers"}com--source. Mostre ao usuário os arquivos, as fontes e o que foi deixado de fora, e pare se algo parecer privado. - Publique:
portifact publish <caminho> --json. O resultado é{"artifactId","versionId","versionNumber","url","expiresAt","uploadId","files","totalBytes","sourceFiles","sourceBytes","sourceOrigin","uploadedFiles","uploadedBytes"}. O progresso e o manifesto vão para o stderr.
- O tipo é inferido a partir do caminho: uma pasta, um arquivo
.zipou.htmlé umsite,.mdémarkdowne.txtétext. Passe--type site|markdown|textpara outros arquivos. Pastas e arquivos ZIP só podem ser sites. - Um único arquivo HTML é publicado como o
index.htmldo site. Uma pasta precisa de umindex.html, ou--entry <caminho>com a página para abrir primeiro. --namedefine o nome mostrado na lista de artefatos; o padrão é o nome do arquivo ou pasta.--artifact <id>publica uma nova versão de um artefato existente, mantendo seu nome, tipo e acesso, a menos que--namemude o nome. Se alguém publicou no meio tempo, falha comversion_conflict(saída 6); verifique o artefato e publique novamente.- Pastas sempre excluem
.git,node_modules, caches, arquivos do sistema e arquivos que podem conter segredos (.enve.env.*exceto exemplos,.dev.vars,.npmrc,.netrc, chaves SSH,*.pem,*.key,*.p12, estado do Terraform e similares). Nomear tal arquivo diretamente é recusado. O filtro é uma rede de segurança, não uma revisão: ainda verifique o manifesto. - Links simbólicos e arquivos especiais são recusados, nunca seguidos.
- Arquivos que a conta já armazena não são enviados novamente. Uploads interrompidos são repetidos, e se a publicação falhar após o upload ter começado, a CLI o cancela para que nada seja publicado pela metade.
- Versões cujo progresso mostra
Uploaded part <n> of <m> of <caminho>enviam arquivos com mais de 64 MiB em partes de 16 MiB, transmitidos do disco, para que um arquivo grande nunca precise caber na memória e uma parte falha seja enviada novamente por conta própria. Uma versão contém no máximo 250 MB de arquivos publicados, independentemente do tamanho da parte. - Um arquivo ZIP é expandido na máquina do usuário antes de qualquer upload ser feito. Quando todos os arquivos dentro dele estão em uma pasta, essa pasta se torna a raiz. Links, arquivos especiais, entradas criptografadas, caminhos que saem do arquivo, nomes conflitantes, entradas sobrepostas, arquivos que se expandem além do tamanho declarado ou mais de 200 vezes, mais de 10.000 entradas e qualquer coisa acima dos limites de tamanho são recusados (
invalid_input, saída 2, ouquota_exceeded, saída 7). As exclusões padrão e o filtro de segredos também se aplicam às suas entradas. --source <caminho>anexa fontes privadas à versão: apenas o proprietário pode vê-las e baixá-las (pull --source), elas contam para o armazenamento, mas não para o tamanho publicado, e os arquivos publicados e de fonte juntos têm no máximo 1.000. O caminho pode ser uma pasta, um único arquivo ou um arquivo ZIP. Em uma pasta dentro de um repositório git, o git escolhe os arquivos: o que ele versiona mais novos arquivos que não ignora, sem submódulos ou repositórios aninhados.--ref <commit>anexa exatamente a árvore desse commit (um branch, tag ou ID de commit; nunca inclui alterações não commitadas). A CLI então registra o commit, o branch, o remoto sem credenciais e se houve alterações não commitadas como osourceOriginda versão. Fora de um repositório, ou semgitinstalado, a pasta é percorrida com as exclusões padrão. Arquivos que podem conter segredos nunca são anexados, independentemente do que o git disser. Um aviso no stderr lista os ponteiros Git LFS, que são anexados como ponteiros, não como conteúdo; sugiragit lfs pullprimeiro.--assets <dir>publica uma pasta de imagens e outros arquivos com um documento Markdown, em seu caminho relativo ao documento, para que seus links relativos funcionem. A pasta deve estar dentro da pasta do documento, e as exclusões padrão se aplicam.- A Portifact renderiza um artefato
markdownoutextpor conta própria: seu URL abre uma página renderizada a partir do documento, onde HTML bruto em Markdown é mostrado como texto e nada é executado. O arquivo original é baixado de seu próprio caminho sob o URL do artefato (por exemplo<url>plan.md, ou<url>index.mdparapublish_document), com o mesmo acesso da página. Um documento tem no máximo 5 MB de texto UTF-8, e um artefatotexté um único arquivo.
Gerenciar artefatos
Apenas em versões cujo --help lista esses comandos. Todo comando aceita --json.
portifact list [--limit N] [--cursor C] [--search TEXTO] [--state active|archived|suspended|purging] [--type site|markdown|text] [--access public|authenticated|restricted] [--annotations off|open|locked]retorna{"items":[...],"nextCursor"}; passenextCursorcomo--cursor, com os mesmos filtros, para a próxima página. Cada item é o queportifact inforetorna mais"activity":{"versions","currentBytes","openThreads","lastAnnotationAt"}: as versões retidas (a atual incluída), os bytes da versão atual (arquivos publicados e fontes,nullsem uma versão), os tópicos abertos na versão atual e quando um tópico em qualquer versão mudou pela última vez (nullsem tópicos). O tráfego é contado por conta, não por artefato, portanto está apenas emportifact usage.--searchcorresponde a uma parte do nome (letras em qualquer maiúscula/minúscula) ou do ID, e cada filtro fornecido deve ser verdadeiro, então use-os para encontrar um artefato em vez de percorrer tudo.portifact info <id>retorna um item:{"id","name","type","state","accessMode","annotations","currentVersionId","url","expiresAt","archivedAt","purgeAt","createdAt","updatedAt"}, mais"suspension":{"reason"}enquanto o artefato estiver suspenso.portifact renew <id>,archive <id>erestore <id>retornam{"artifactId","state","expiresAt","purgeAt"}. Pergunte antes de arquivar.portifact delete <id>exclui permanentemente. Ele pede que a pessoa no terminal digite o ID do artefato; sem um terminal, requer--yese, caso contrário, falha com saída 2. Só passe--yesdepois que o usuário confirmar esse artefato exato.
Controlar acesso
Apenas em versões cujo --help lista access. Todo comando aceita --json e imprime {"artifactId","mode","readers","indexable","embeddable","policyGeneration"}.
portifact access <id>mostra a política atual. Use-o para relatar o modo de acesso após a publicação.portifact access set <id> restricted|authenticated|public:restrictedé o proprietário mais leitores listados,authenticatedé qualquer pessoa conectada à Portifact,publicé qualquer pessoa com o link. Contas nos primeiros 7 dias não podem tornar um artefato público (account_too_new_for_public, saída 7).portifact access add <id> <email>...eaccess remove <id> <email>...alteram a lista de leitores (no máximo 100 endereços por vez). Os leitores só importam enquanto o modo érestricted.
Versões, reversão e download
Apenas em versões cujo --help lista esses comandos. Todo comando aceita --json.
Um artefato mantém sua versão atual mais as versões que a substituíram durante os últimos sete dias. A reversão e o download funcionam apenas nessas versões retidas.
portifact versions <id>lista-as, da mais recente para a mais antiga.--jsonimprime{"artifactId","items":[{"id","number","current","entrypoint","publishedBytes","sourceBytes","publishedFiles","sourceFiles","rendererVersion","committedAt","expiresAt","sourceOrigin"}]};expiresAté quando uma versão anterior para de ser retida e énullpara a atual, esourceOriginé{"commit","branch","remote","dirty"}quando as fontes vieram do git, caso contrário,null. A origem é o que o editor declarou; a Portifact não pode verificá-la.portifact rollback <id> <versão-id>torna uma versão retida atual novamente. Ela é publicada como uma nova versão com os mesmos arquivos, reinicia os 30 dias e não altera o acesso: leitores removidos desde essa versão permanecem removidos. Pergunte ao usuário antes de reverter. Retorna{"artifactId","versionId","versionNumber","url","expiresAt","fromVersionId","fromVersionNumber"}. Se alguém publicou no meio tempo, falha comversion_conflict(saída 6); verifiqueversionsnovamente e pergunte ao usuário. Em versões cujoportifact rollback --helpdiz "version ID or number",<versão-id>também pode ser o número da versão (3ouv3), epull --versionaceita um também; um número que não é retido falha comnot_found(saída 5).portifact pull <id> --out <dir>baixa os arquivos publicados da versão atual em<dir>/published. Adicione--sourcepara as fontes privadas (em<dir>/source, apenas proprietário),--published --sourcepara ambos, e--version <versão-id>para uma versão anterior.<dir>não deve existir ainda; o pull nunca escreve fora dele, recusa caminhos dentro de uma pasta.git, verifica o SHA-256 de cada arquivo e remove a pasta se algo falhar (download_failed, saída 1). Retorna{"artifactId","versionId","versionNumber","out","files":[{"kind","path","size","sha256"}],"totalBytes"}. Se um artefato é compartilhado com alguém, o total de bytes inclui tudo; você pode baixar apenas os arquivos publicados ou apenas as fontes. O diretório de saída é criado com permissões seguras.
Anotações
Apenas em versões cujo --help lista annotations. Todo comando aceita --json.
Um artefato pode ter anotações em qualquer estado de acesso. O estado de anotações de um artefato é off, open ou locked, e portifact access set não o altera; veja portifact annotations.
portifact annotations on|off|lock <id>define o estado de anotações do artefato.offremove anotações existentes,openpermite novas,lockedmantém as existentes, mas impede novas; pergunte ao usuário antes de mudar paraoff.portifact annotations list <id>lista tópicos de anotação na versão atual, cada um com seuthreadIde contagem de comentários. Passe--all-versionspara listar tópicos no artefato, e--openapenas para tópicos abertos.portifact annotations export <id> [--format json|xlsx|md|csv] [--no-comments]exporta anotações do artefato. O formato padrão éjson; passe-no lugar de<id>para exportar da entrada padrão.portifact annotations threads <id> add <texto>cria um tópico de anotação na versão atual. Ele tenta incluir citações no contexto de seleção do usuário; anotações sem contexto são colocadas no início do documento.portifact annotations threads <id> reply <thread-id> <texto>eresolve|reopengerenciam um tópico.resolveusa padrão "Resolvido"; cubra outros padrões com "resolvido". Sempre anexe um comentário ao resolver; nunca resolva sem ele.
Uso e logs
Apenas em versões cujo --help lista usage ou logs.
portifact usage --jsonretorna a cota de armazenamento da conta (storageLimit,storageUsed), a cota de anotações (annotationLimit,annotationsUsed), a cota de tráfego (trafficLimit,trafficUsed), data de reinício do tráfego (trafficResetsAt) e se o artefato é público (publicAllowed).portifact logs <id> [--limit N] [--cursor C] [--geocode]retorna quem abriu este artefato (items: [{requestId, artifactId, ip, userAgent, method, path, status, bytes, durationMs, createdAt}]). O tráfego não anônimo é o único tráfego registrado e é mantido por 30 dias. Passe--geocodepara incluir cidade/país aproximados a partir do IP; a própria Portifact geocodifica e nunca compartilha IPs brutos. Os itens são por solicitação; várias visualizações da mesma pessoa na mesma página, com ou sem autenticação, aparecem separadamente. Um item com status402é uma solicitação de visualização de um documento que foi bloqueada porque uma das cotas foi excedida.
Licenças
Apenas em versões cujo --help lista licenses. portifact licenses imprime as licenças de código aberto do binário. O mesmo conteúdo está em https://portifact.com/third-party-notices. Esse arquivo também é empacotado com o binário e está disponível sem uma conta.
Configuração
PORTIFACT_APP_ORIGIN (string de URL) aponta a CLI para um servidor Portifact não padrão. Existe para testes e staging; não defina a menos que o usuário peça.
PORTIFACT_MCP_ALLOW_TOOLS (string de ferramentas separadas por vírgula) restringe quais ferramentas MCP este servidor pode expor. O valor padrão permite todas.
Servidor MCP
A Portifact também expõe um servidor MCP em https://app.portifact.com/mcp que agentes compatíveis com MCP podem usar para ler, escrever e moderar artefatos. A lista exata de ferramentas muda à medida que o servidor evolui; consulte seu ponto final de lista de ferramentas e nunca invente uma. As ferramentas disponíveis incluem:
- Listar artefatos – Busca artefatos por nome, tipo, estado, modo de acesso e estado de anotações.
- Obter informações do artefato – Detalhes de um artefato pelo seu ID.
- Publicar artefato (documento) – Publica um documento Markdown ou texto com metadados (nome, tipo, modo de acesso, lista de leitores). Usa texto simples (não caminhos de arquivo); documentos pequenos apenas (5 MB de texto).
- Listar versões – Versões retidas de um artefato.
- Baixar versão – O texto do documento atual ou de uma versão anterior.
- Reverter versão – Torna uma versão anterior a atual.
- Ler anotações – Tópicos de anotação de um artefato.
- Escrever anotação – Adiciona um novo tópico de anotação a um artefato.
- Responder a anotação – Adiciona um comentário a um tópico existente.
- Moderar anotações – Resolve ou reabre um tópico de anotação.
- Exportar anotações – Todas as anotações de um artefato em JSON, XLSX, Markdown ou CSV.
- Obter uso – Cotas e uso da conta.
- Obter logs de acesso – Quem abriu um artefato.
Para usar com o Claude Code, adicione ao seu ~/.claude.json5:
{
mcpServers: {
portifact: {
command: "npx",
args: ["-y", "@portifact/mcp-server"]
}
}
}
A ferramenta publish_document retorna detalhes do artefato publicado; a ferramenta list_artifacts retorna um cursor para paginação.